You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by st...@apache.org on 2004/09/06 19:10:43 UTC

cvs commit: jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core ItemManager.java NodeImpl.java PropertyImpl.java RepositoryImpl.java ItemImpl.java Test.java SessionImpl.java WorkspaceImpl.java

stefan      2004/09/06 10:10:43

  Modified:    proposals/jcrri/src/org/apache/slide/jcr/core
                        ItemManager.java NodeImpl.java PropertyImpl.java
                        RepositoryImpl.java ItemImpl.java Test.java
                        SessionImpl.java WorkspaceImpl.java
  Log:
  jcrri: implementing REFRERENCES type & minor fixes
  
  Revision  Changes    Path
  1.17      +28 -48    jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemManager.java
  
  Index: ItemManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemManager.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- ItemManager.java	2 Sep 2004 11:02:31 -0000	1.16
  +++ ItemManager.java	6 Sep 2004 17:10:43 -0000	1.17
  @@ -17,9 +17,7 @@
   
   import org.apache.commons.collections.ReferenceMap;
   import org.apache.log4j.Logger;
  -import org.apache.slide.jcr.core.nodetype.NodeDefId;
   import org.apache.slide.jcr.core.nodetype.NodeTypeRegistry;
  -import org.apache.slide.jcr.core.nodetype.PropDefId;
   import org.apache.slide.jcr.core.state.*;
   import org.apache.slide.jcr.core.version.FrozenNode;
   import org.apache.slide.jcr.core.version.VersionHistoryImpl;
  @@ -32,7 +30,10 @@
   import javax.jcr.nodetype.NodeDef;
   import javax.jcr.nodetype.PropertyDef;
   import java.io.PrintStream;
  -import java.util.*;
  +import java.util.ArrayList;
  +import java.util.Collections;
  +import java.util.Iterator;
  +import java.util.Map;
   
   /**
    * There's one <code>ItemManager</code> instance per <code>Workspace</code>
  @@ -161,6 +162,23 @@
       }
   
       /**
  +     * @param id
  +     * @return
  +     */
  +    boolean itemExists(ItemId id) {
  +	try {
  +	    getItem(id);
  +	    return true;
  +	} catch (ItemNotFoundException infe) {
  +	    return false;
  +	} catch (AccessDeniedException ade) {
  +	    return true;
  +	} catch (RepositoryException re) {
  +	    return false;
  +	}
  +    }
  +
  +    /**
        * @return
        * @throws RepositoryException
        */
  @@ -370,33 +388,9 @@
       }
   
       NodeImpl createNodeInstance(NodeState state) throws RepositoryException {
  -	// get definition of the specified node
  -
  -	// 1. get parent node
  -	NodeId parentId = new NodeId(state.getParentUUID());
  -	NodeImpl parent = (NodeImpl) getItem(parentId);
  -	// 2. get definition for the specified child node
  -	NodeDef def = null;
  -	NodeDefId defId = state.getDefinitionId();
  -	if (defId != null) {
  -	    def = session.getNodeTypeManager().getNodeDef(defId);
  -	}
  -	if (def == null) {
  -	    // fallback: find matching definition in parent node's node type and mixin types
  -	    // find the node's name in parent's child list
  -	    NodeState parentState = (NodeState) parent.getItemState();
  -	    List entries = parentState.getChildNodeEntries(state.getUUID());
  -	    if (entries.isEmpty()) {
  -		String msg = parentState.getUUID() + " has no child entry for " + state.getUUID();
  -		log.error(msg);
  -		throw new RepositoryException(msg);
  -	    }
  -	    NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) entries.get(0);
  -	    // find matching definiton
  -	    def = parent.getApplicableChildNodeDef(entry.getName(), state.getNodeTypeName());
  -	}
  -
  -	// 3. create instance
  +	// 1. get definition of the specified node
  +	NodeDef def = session.getNodeTypeManager().getNodeDef(state.getDefinitionId());
  +	// 2. create instance
   	return createNodeInstance(state, def);
       }
   
  @@ -412,23 +406,9 @@
   
       PropertyImpl createPropertyInstance(PropertyState state)
   	    throws RepositoryException {
  -	// get definition of the specified property
  -
  -	// 1. get parent node
  -	NodeId parentId = new NodeId(state.getParentUUID());
  -	NodeImpl parent = (NodeImpl) getItem(parentId);
  -	// 2. get matching definition for the specified property
  -	PropertyDef def = null;
  -	PropDefId defId = state.getDefinitionId();
  -	if (defId != null) {
  -	    def = session.getNodeTypeManager().getPropDef(defId);
  -	}
  -	if (def == null) {
  -	    // fallback: find matching definition in parent node's node type and mixin types
  -	    def = parent.getApplicablePropertyDef(state.getName(), state.getType());
  -	}
  -
  -	// 3. create instance
  +	// 1. get definition for the specified property
  +	PropertyDef def = session.getNodeTypeManager().getPropDef(state.getDefinitionId());
  +	// 2. create instance
   	return createPropertyInstance(state, def);
       }
   
  
  
  
  1.37      +13 -3     jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/NodeImpl.java
  
  Index: NodeImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/NodeImpl.java,v
  retrieving revision 1.36
  retrieving revision 1.37
  diff -u -r1.36 -r1.37
  --- NodeImpl.java	2 Sep 2004 11:02:31 -0000	1.36
  +++ NodeImpl.java	6 Sep 2004 17:10:43 -0000	1.37
  @@ -1869,8 +1869,18 @@
        * @see Node#getReferences()
        */
       public PropertyIterator getReferences() throws RepositoryException {
  -	// @todo implement REFERENCE type support
  -	throw new RepositoryException("not yet implemented");
  +	WorkspaceImpl wsp = (WorkspaceImpl) session.getWorkspace();
  +	ReferenceManager refMgr = wsp.getReferenceManager();
  +	synchronized(refMgr) {
  +	    NodeReferences refs = refMgr.get((NodeId) id);
  +	    Iterator iter = refs.getReferences().iterator();
  +	    ArrayList list = new ArrayList();
  +	    while (iter.hasNext()) {
  +		PropertyId propId = (PropertyId) iter.next();
  +		list.add(itemMgr.getItem(propId));
  +	    }
  +	    return new IteratorHelper(list);
  +	}
       }
   
       /**
  
  
  
  1.28      +8 -14     jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/PropertyImpl.java
  
  Index: PropertyImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/PropertyImpl.java,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- PropertyImpl.java	2 Sep 2004 11:02:31 -0000	1.27
  +++ PropertyImpl.java	6 Sep 2004 17:10:43 -0000	1.28
  @@ -93,20 +93,20 @@
   	}
   
   	try {
  -	    PropertyState thisState = (PropertyState) state;
  -	    PersistentPropertyState persistentState = (PersistentPropertyState) thisState.getOverlayedState();
  +	    PropertyState transientState = (PropertyState) state;
  +	    PersistentPropertyState persistentState = (PersistentPropertyState) transientState.getOverlayedState();
   	    if (persistentState == null) {
   		// this property is 'new'
  -		persistentState = itemStateMgr.createPersistentPropertyState(thisState.getParentUUID(), thisState.getName());
  +		persistentState = itemStateMgr.createPersistentPropertyState(transientState.getParentUUID(), transientState.getName());
   	    }
   	    // copy state from transient state
  -	    persistentState.setDefinitionId(thisState.getDefinitionId());
  -	    persistentState.setType(thisState.getType());
  -	    persistentState.setValues(thisState.getValues());
  +	    persistentState.setDefinitionId(transientState.getDefinitionId());
  +	    persistentState.setType(transientState.getType());
  +	    persistentState.setValues(transientState.getValues());
   	    // make state persistent
   	    persistentState.store();
   	    // remove listener from transient state
  -	    thisState.removeListener(this);
  +	    transientState.removeListener(this);
   	    // add listener to persistent state
   	    persistentState.addListener(this);
   	    // swap transient state with persistent state
  @@ -158,10 +158,6 @@
   		InternalValue old = oldValues[i];
   		if (old != null) {
   		    switch (old.getType()) {
  -			case PropertyType.REFERENCE:
  -			    // REFERENCE value
  -			    // @todo remove reference from target
  -			    break;
   			case PropertyType.BINARY:
   			    // BINARY value
   			    BLOBFileValue blob = (BLOBFileValue) old.internalValue();
  @@ -727,8 +723,6 @@
   	if (definition.isProtected()) {
   	    throw new ConstraintViolationException("cannot set the value of a protected property " + safeGetJCRPath());
   	}
  -
  -	// @todo implement correct semantics (i.e. referential integrity) for REFERENCE values
   
   	// check type according to definition of this property
   	int reqType = definition.getRequiredType();
  
  
  
  1.25      +24 -1     jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryImpl.java
  
  Index: RepositoryImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/RepositoryImpl.java,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- RepositoryImpl.java	1 Sep 2004 15:42:26 -0000	1.24
  +++ RepositoryImpl.java	6 Sep 2004 17:10:43 -0000	1.25
  @@ -22,6 +22,7 @@
   import org.apache.slide.jcr.core.state.ItemStateException;
   import org.apache.slide.jcr.core.state.PersistenceManager;
   import org.apache.slide.jcr.core.state.PersistentItemStateManager;
  +import org.apache.slide.jcr.core.state.ReferenceManager;
   import org.apache.slide.jcr.core.version.VersionManager;
   import org.apache.slide.jcr.fs.BasedFileSystem;
   import org.apache.slide.jcr.fs.FileSystem;
  @@ -91,6 +92,11 @@
       // the same named workspace, i.e. the same physical storage)
       private final HashMap wspStateMgrs = new HashMap();
   
  +    // map of workspace names and workspace reference managers
  +    // (might be shared among multiple workspace instances representing
  +    // the same named workspace, i.e. the same physical storage)
  +    private final HashMap wspRefMgrs = new HashMap();
  +
       // map of workspace names and observation managers
       private final HashMap wspObsMgrFactory = new HashMap();
   
  @@ -336,6 +342,23 @@
   	    wspStateMgrs.put(workspaceName, stateMgr);
   	}
   	return stateMgr;
  +    }
  +
  +    synchronized ReferenceManager getWorkspaceReferenceManager(String workspaceName)
  +	    throws NoSuchWorkspaceException, RepositoryException {
  +	WorkspaceDef wd = (WorkspaceDef) wspDefs.get(workspaceName);
  +	if (wd == null) {
  +	    throw new NoSuchWorkspaceException(workspaceName);
  +	}
  +	ReferenceManager refMgr
  +		= (ReferenceManager) wspRefMgrs.get(workspaceName);
  +	if (refMgr == null) {
  +	    // create reference mgr that uses the perstistence mgr configured
  +	    // in the workspace definition
  +	    refMgr = new ReferenceManager(createPersistenceManager(wd));
  +	    wspRefMgrs.put(workspaceName, refMgr);
  +	}
  +	return refMgr;
       }
   
       synchronized ObservationManagerFactory getObservationManagerFactory(String workspaceName)
  
  
  
  1.23      +179 -31   jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemImpl.java
  
  Index: ItemImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/ItemImpl.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- ItemImpl.java	30 Aug 2004 16:15:15 -0000	1.22
  +++ ItemImpl.java	6 Sep 2004 17:10:43 -0000	1.23
  @@ -35,10 +35,7 @@
   import javax.jcr.nodetype.NodeType;
   import javax.jcr.nodetype.PropertyDef;
   import javax.jcr.version.VersionHistory;
  -import java.util.ArrayList;
  -import java.util.Collections;
  -import java.util.Iterator;
  -import java.util.Map;
  +import java.util.*;
   
   /**
    * <code>ItemImpl</code> implements the <code>Item</code> interface.
  @@ -370,7 +367,7 @@
   			// the transient node's node type does not satisfy the
   			// 'required primary types' constraint
   			String msg = node.safeGetJCRPath() + " must be of node type " + ntReq.getName();
  -			log.error(msg);
  +			log.warn(msg);
   			throw new ConstraintViolationException(msg);
   		    }
   		}
  @@ -410,7 +407,7 @@
   		    PropertyDefImpl pd = (PropertyDefImpl) propDefs[i];
   		    if (!nodeState.hasPropertyEntry(pd.getQName())) {
   			String msg = node.safeGetJCRPath() + ": mandatory property " + pd.getName() + " does not exist";
  -			log.error(msg);
  +			log.warn(msg);
   			throw new ConstraintViolationException(msg);
   		    }
   		}
  @@ -420,7 +417,7 @@
   		    NodeDefImpl nd = (NodeDefImpl) nodeDefs[i];
   		    if (!nodeState.hasChildNodeEntry(nd.getQName())) {
   			String msg = node.safeGetJCRPath() + ": mandatory child node " + nd.getName() + " does not exist";
  -			log.error(msg);
  +			log.warn(msg);
   			throw new ConstraintViolationException(msg);
   		    }
   		}
  @@ -453,7 +450,7 @@
   			} catch (RepositoryException e) {
   			    // repack exception for providing verboser error message
   			    String msg = prop.safeGetJCRPath() + ": " + e.getMessage();
  -			    log.error(msg);
  +			    log.warn(msg);
   			    throw new ConstraintViolationException(msg);
   			}
   		    }
  @@ -464,6 +461,145 @@
   	    }
   	}
       }
  +    
  +    private void checkReferences(Iterator iterDirty, Iterator iterRemoved,
  +				 ReferenceManager refMgr)
  +	    throws ConstraintViolationException, RepositoryException {
  +	// map of target (node) id's and modified NodeReferences objects
  +	HashMap dirtyNodeRefs = new HashMap();
  +
  +	// walk through dirty items and process REFERENCE properties:
  +	// 1. verify that target node exists
  +	// 2. update and collect the affected NodeReferences objects of the
  +	//    target nodes in the dirtyNodeRefs map
  +	while (iterDirty.hasNext()) {
  +	    ItemState transientState = (ItemState) iterDirty.next();
  +	    if (!transientState.isNode()) {
  +		PropertyState propState = (PropertyState) transientState;
  +		if (propState.getType() == PropertyType.REFERENCE) {
  +		    if (propState.getStatus() == ItemState.STATUS_EXISTING_MODIFIED) {
  +			// this is a modified REFERENCE property:
  +			// remove the 'reference' stored in the old value
  +			PropertyState oldPropState = (PropertyState) propState.getOverlayedState();
  +			InternalValue[] vals = oldPropState.getValues();
  +			for (int i = 0; vals != null && i < vals.length; i++) {
  +			    String uuid = vals[i].toString();
  +			    NodeId targetId = new NodeId(uuid);
  +			    NodeReferences refs;
  +			    if (dirtyNodeRefs.containsKey(targetId)) {
  +				refs = (NodeReferences) dirtyNodeRefs.get(targetId);
  +			    } else {
  +				refs = refMgr.get(targetId);
  +				dirtyNodeRefs.put(targetId, refs);
  +			    }
  +			    // remove reference from target node
  +			    refs.removeReference((PropertyId) propState.getId());
  +			}
  +		    }
  +		    // add the reference stored in the new value
  +		    InternalValue[] vals = propState.getValues();
  +		    for (int i = 0; vals != null && i < vals.length; i++) {
  +			String uuid = vals[i].toString();
  +			NodeId targetId = new NodeId(uuid);
  +			// verify that target exists
  +			if (!itemMgr.itemExists(targetId)) {
  +			    String msg = itemMgr.safeGetJCRPath(propState.getId()) + ": target node of REFERENCE property does not exist";
  +			    log.warn(msg);
  +			    throw new ConstraintViolationException(msg);
  +			}
  +			// target is a new (unsaved) node; make sure that it is
  +			// within the scope of the current save operation
  +			// (by veryfying that it is a descendant of 'this' item)
  +			NodeImpl target = (NodeImpl) itemMgr.getItem(targetId);
  +			if (target.isNew()) {
  +			    try {
  +				if (!target.getPrimaryPath().isDescendantOf(getPrimaryPath())) {
  +				    String msg = itemMgr.safeGetJCRPath(propState.getId()) + ": target node of REFERENCE property is a new node and must therefore either be saved first or be within the scope of the current save operation.";
  +				    log.warn(msg);
  +				    throw new ConstraintViolationException(msg);
  +				}
  +			    } catch (MalformedPathException mpe) {
  +				// should never get here...
  +				String msg = itemMgr.safeGetJCRPath(propState.getId()) + ": failed to verify existence of target node";
  +				log.error(msg, mpe);
  +				throw new RepositoryException(msg, mpe);
  +			    }
  +			}
  +			NodeReferences refs;
  +			if (dirtyNodeRefs.containsKey(targetId)) {
  +			    refs = (NodeReferences) dirtyNodeRefs.get(targetId);
  +			} else {
  +			    refs = refMgr.get(targetId);
  +			    dirtyNodeRefs.put(targetId, refs);
  +			}
  +			// add reference to target node
  +			refs.addReference((PropertyId) propState.getId());
  +		    }
  +		}
  +	    }
  +	}
  +
  +	// walk through 'removed' items:
  +	// 1. build list of removed nodes
  +	// 2. process REFERENCE properties (update and collect the affected
  +	//    NodeReferences objects of the target nodes)
  +	ArrayList removedNodes = new ArrayList();
  +	while (iterRemoved.hasNext()) {
  +	    ItemState transientState = (ItemState) iterRemoved.next();
  +	    if (transientState.isNode()) {
  +		// removed node: collect for later processing
  +		removedNodes.add(transientState);
  +	    } else {
  +		PropertyState propState = (PropertyState) transientState;
  +		if (propState.getType() == PropertyType.REFERENCE) {
  +		    // this is a removed REFERENCE property:
  +		    // remove the 'reference' stored in the value
  +		    InternalValue[] vals = propState.getValues();
  +		    for (int i = 0; i < vals.length; i++) {
  +			String uuid = vals[i].toString();
  +			NodeId targetId = new NodeId(uuid);
  +			NodeReferences refs;
  +			if (dirtyNodeRefs.containsKey(targetId)) {
  +			    refs = (NodeReferences) dirtyNodeRefs.get(targetId);
  +			} else {
  +			    refs = refMgr.get(targetId);
  +			    dirtyNodeRefs.put(targetId, refs);
  +			}
  +			// remove reference to target node
  +			refs.removeReference((PropertyId) propState.getId());
  +		    }
  +		}
  +	    }
  +	}
  +
  +	// now that all NodeReferences objects have been updated,
  +	// walk through 'removed' nodes and verify that no node that is still
  +	// being referenced, is removed
  +	Iterator iter = removedNodes.iterator();
  +	while (iter.hasNext()) {
  +	    NodeState nodeState = (NodeState) iter.next();
  +	    // check if node is referenced
  +	    NodeId targetId = (NodeId) nodeState.getId();
  +	    NodeReferences refs;
  +	    if (dirtyNodeRefs.containsKey(targetId)) {
  +		refs = (NodeReferences) dirtyNodeRefs.get(targetId);
  +	    } else {
  +		refs = refMgr.get(targetId);
  +	    }
  +	    if (refs.hasReferences()) {
  +		String msg = nodeState.getId() + ": the node cannot be removed because it is being referenced.";
  +		log.warn(msg);
  +		throw new ConstraintViolationException(msg);
  +	    }
  +	}
  +
  +	// persist dirty NodeReferences objects
  +	iter = dirtyNodeRefs.values().iterator();
  +	while (iter.hasNext()) {
  +	    NodeReferences refs = (NodeReferences) iter.next();
  +	    refMgr.save(refs);
  +	}
  +    }
   
       private void removeTransientItems(Iterator iter) throws RepositoryException {
   	// walk through list of transient items marked 'removed'
  @@ -536,6 +672,7 @@
        * Same as <code>{@link Item#getName()}</code> except that
        * this method returns a <code>QName</code> instead of a
        * <code>String</code>.
  +     *
        * @return the name of this item as <code>QName</code>
        * @throws RepositoryException if an error occurs.
        */
  @@ -824,27 +961,39 @@
   	// (this will also validate child removals)
   	validateTransientItems(dirty.iterator());
   
  -	if (isNode()) {
  +	// we need to make sure that we are not interrupted while
  +	// verifying/persisting node references
  +	WorkspaceImpl wsp = (WorkspaceImpl) session.getWorkspace();
  +	ReferenceManager refMgr = wsp.getReferenceManager();
  +	synchronized (refMgr) {
  +
   	    // build list of transient descendents in the attic
   	    // (i.e. those marked as 'removed')
   	    ArrayList removed = new ArrayList();
  -	    iter = itemStateMgr.getDescendantTransientItemStatesInAttic(id);
  -	    while (iter.hasNext()) {
  -		transientState = (ItemState) iter.next();
  -		// check if stale
  -		if (transientState.getStatus() == ItemState.STATUS_STALE_MODIFIED) {
  -		    String msg = transientState.getId() + ": the item cannot be removed because it has been modified externally.";
  -		    log.error(msg);
  -		    throw new InvalidItemStateException(msg);
  -		}
  -		if (transientState.getStatus() == ItemState.STATUS_STALE_DESTROYED) {
  -		    String msg = transientState.getId() + ": the item cannot be removed because it has already been deleted externally.";
  -		    log.error(msg);
  -		    throw new InvalidItemStateException(msg);
  +	    if (isNode()) {
  +		iter = itemStateMgr.getDescendantTransientItemStatesInAttic(id);
  +		while (iter.hasNext()) {
  +		    transientState = (ItemState) iter.next();
  +		    // check if stale
  +		    if (transientState.getStatus() == ItemState.STATUS_STALE_MODIFIED) {
  +			String msg = transientState.getId() + ": the item cannot be removed because it has been modified externally.";
  +			log.error(msg);
  +			throw new InvalidItemStateException(msg);
  +		    }
  +		    if (transientState.getStatus() == ItemState.STATUS_STALE_DESTROYED) {
  +			String msg = transientState.getId() + ": the item cannot be removed because it has already been deleted externally.";
  +			log.error(msg);
  +			throw new InvalidItemStateException(msg);
  +		    }
  +		    removed.add(transientState);
   		}
  -		removed.add(transientState);
   	    }
   
  +	    // referential integrity checks:
  +	    // make sure that a referenced node cannot be removed and
  +	    // that all references are updated and persisted
  +	    checkReferences(dirty.iterator(), removed.iterator(), refMgr);
  +
   	    // definitively remove transient items marked as 'removed'
   	    removeTransientItems(removed.iterator());
   
  @@ -857,13 +1006,13 @@
   		// permanently invalidate the wrapping Item instance
   		itemStateMgr.disposeTransientItemStateInAttic(transientState);
   	    }
  -	}
   
  -	// initialize version histories for new nodes
  -	initVersionHistories(dirty.iterator());
  +	    // initialize version histories for new nodes
  +	    initVersionHistories(dirty.iterator());
   
  -	// persist 'new' or 'modified' transient states
  -	persistTransientItems(dirty.iterator());
  +	    // persist 'new' or 'modified' transient states
  +	    persistTransientItems(dirty.iterator());
  +	} // synchronized(refMgr)
   
   	// now it is safe to dispose the transient states
   	iter = dirty.iterator();
  @@ -874,8 +1023,7 @@
   	}
   
   	// all changes are persisted, now dispatch events
  -	WorkspaceImpl wsp = (WorkspaceImpl) session.getWorkspace();
  -	wsp.getRepository().getObservationManagerFactory(wsp.getName()).dispatchEvents(events);
  +	rep.getObservationManagerFactory(wsp.getName()).dispatchEvents(events);
       }
   
       /**
  
  
  
  1.18      +18 -0     jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/Test.java
  
  Index: Test.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/Test.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- Test.java	27 Aug 2004 09:56:51 -0000	1.17
  +++ Test.java	6 Sep 2004 17:10:43 -0000	1.18
  @@ -160,11 +160,29 @@
   	}
   
   	Node misc = root.addNode("misc", "nt:unstructured");
  +	misc.addMixin("mix:referenceable");
   	Property link = misc.setProperty("link", PathValue.valueOf("../blu[2]"));
   	root.save();
   	Node linkTarget = link.getParent().getNode(link.getString());
   	System.out.println(link.getPath() + " refers to " + linkTarget.getPath());
   
  +	root.setProperty("ref", misc);
  +	root.save();
  +	PropertyIterator pi = misc.getReferences();
  +	while (pi.hasNext()) {
  +	    Property prop = pi.nextProperty();
  +	    Node target = prop.getNode();
  +	    System.out.println(prop.getPath() + " is a reference to " + target.getPath());
  +	}
  +/*
  +	misc.remove(".");
  +	try {
  +	    root.save();
  +	} catch (ConstraintViolationException cve) {
  +	    root.remove("ref");
  +	    root.save();
  +	}
  +*/
   	String date1 = "2003-07-28T06:18:57.848+01:00";
   	root.setProperty("date", new DateValue(new StringValue(date1).getDate()));
   	Property p = root.getProperty("date");
  
  
  
  1.2       +5 -3      jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/SessionImpl.java
  
  Index: SessionImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/SessionImpl.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SessionImpl.java	27 Aug 2004 09:28:47 -0000	1.1
  +++ SessionImpl.java	6 Sep 2004 17:10:43 -0000	1.2
  @@ -128,7 +128,8 @@
   	nsMappings = new TransientNamespaceMappings(rep.getNamespaceRegistry());
   
   	ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), getNamespaceResolver());
  -	wsp = new WorkspaceImpl(wspName, rep.getWorkspaceStateManager(wspName), rep, this);
  +	wsp = new WorkspaceImpl(wspName, rep.getWorkspaceStateManager(wspName),
  +		rep.getWorkspaceReferenceManager(wspName), rep, this);
   	itemStateMgr = new SessionItemStateManager(rep.getRootNodeUUID(), wsp.getPersistentStateManager(), getNamespaceResolver());
   	hierMgr = itemStateMgr.getHierarchyMgr();
   	itemMgr = new ItemManager(itemStateMgr, hierMgr, this, ntMgr.getRootNodeDefinition(), rep.getRootNodeUUID());
  @@ -151,7 +152,8 @@
   	nsMappings = new TransientNamespaceMappings(rep.getNamespaceRegistry());
   
   	ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), getNamespaceResolver());
  -	wsp = new WorkspaceImpl(wspName, rep.getWorkspaceStateManager(wspName), rep, this);
  +	wsp = new WorkspaceImpl(wspName, rep.getWorkspaceStateManager(wspName),
  +		rep.getWorkspaceReferenceManager(wspName), rep, this);
   	itemStateMgr = new SessionItemStateManager(rep.getRootNodeUUID(), wsp.getPersistentStateManager(), getNamespaceResolver());
   	hierMgr = itemStateMgr.getHierarchyMgr();
   	itemMgr = new ItemManager(itemStateMgr, hierMgr, this, ntMgr.getRootNodeDefinition(), rep.getRootNodeUUID());
  
  
  
  1.17      +49 -89    jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/WorkspaceImpl.java
  
  Index: WorkspaceImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/WorkspaceImpl.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- WorkspaceImpl.java	27 Aug 2004 09:28:47 -0000	1.16
  +++ WorkspaceImpl.java	6 Sep 2004 17:10:43 -0000	1.17
  @@ -46,7 +46,7 @@
   
   /**
    * A <code>WorkspaceImpl</code> ...
  - * 
  + *
    * @author Stefan Guggisberg
    * @version $Revision$, $Date$
    */
  @@ -71,6 +71,12 @@
       protected final PersistentItemStateManager persistentStateMgr;
   
       /**
  +     * The reference mgr associated with the workspace represented by <i>this</i>
  +     * <code>Workspace</code> instance.
  +     */
  +    protected final ReferenceManager refMgr;
  +
  +    /**
        * The hierarchy mgr that reflects persistent state only
        * (i.e. that is isolated from transient changes made through
        * the session).
  @@ -89,16 +95,18 @@
   
       /**
        * Package private constructor.
  -     * 
  -     * @param wspName            
  -     * @param persistentStateMgr 
  -     * @param rep                
  +     *
  +     * @param wspName
  +     * @param persistentStateMgr
  +     * @param rep
        * @param session
        */
  -    WorkspaceImpl(String wspName, PersistentItemStateManager persistentStateMgr, RepositoryImpl rep, SessionImpl session) {
  +    WorkspaceImpl(String wspName, PersistentItemStateManager persistentStateMgr,
  +		  ReferenceManager refMgr, RepositoryImpl rep, SessionImpl session) {
   	this.wspName = wspName;
   	this.rep = rep;
   	this.persistentStateMgr = persistentStateMgr;
  +	this.refMgr = refMgr;
   	hierMgr = new HierarchyManagerImpl(rep.getRootNodeUUID(), persistentStateMgr, session.getNamespaceResolver());
   	this.session = session;
       }
  @@ -111,12 +119,16 @@
   	return persistentStateMgr;
       }
   
  +    ReferenceManager getReferenceManager() {
  +	return refMgr;
  +    }
  +
       /**
        * Dumps the state of this <code>Workspace</code> instance
        * (used for diagnostic purposes).
  -     * 
  -     * @param ps 
  -     * @throws RepositoryException 
  +     *
  +     * @param ps
  +     * @throws RepositoryException
        */
       void dump(PrintStream ps) throws RepositoryException {
   	ps.println("Workspace: " + wspName + " (" + this + ")");
  @@ -190,12 +202,12 @@
       }
   
       /**
  -     * @param nodePath 
  -     * @param hierMgr  
  -     * @param stateMgr 
  -     * @return 
  -     * @throws PathNotFoundException 
  -     * @throws RepositoryException   
  +     * @param nodePath
  +     * @param hierMgr
  +     * @param stateMgr
  +     * @return
  +     * @throws PathNotFoundException
  +     * @throws RepositoryException
        */
       protected static PersistentNodeState getNodeState(Path nodePath,
   						      HierarchyManagerImpl hierMgr,
  @@ -270,9 +282,9 @@
   	    throw new RepositoryException(msg, infe);
   	}
   
  -	// 2. check note type constraints
  +	// 2. check node type constraints
   
  -	ChildNodeDef parentDef = getDefinition(parentPath, ntReg, hierMgr, stateMgr);
  +	ChildNodeDef parentDef = ntReg.getNodeDef(parentState.getDefinitionId());
   	if (parentDef.isProtected()) {
   	    throw new ConstraintViolationException(hierMgr.safeGetJCRPath(parentPath) + ": cannot add child node to protected parent node");
   	}
  @@ -300,7 +312,7 @@
   		log.error(msg, ise);
   		throw new RepositoryException(msg, ise);
   	    }
  -	    ChildNodeDef conflictingTargetDef = getDefinition(conflictingState, nodeName.getName(), parentState, ntReg);
  +	    ChildNodeDef conflictingTargetDef = ntReg.getNodeDef(conflictingState.getDefinitionId());
   	    // check same-name sibling setting of both target and existing node
   	    if (!conflictingTargetDef.allowSameNameSibs() ||
   		    !newNodeDef.allowSameNameSibs()) {
  @@ -348,13 +360,13 @@
   	    throw new RepositoryException(msg, infe);
   	}
   
  -	// 2. check note type constraints
  +	// 2. check node type constraints
   
  -	ChildNodeDef parentDef = getDefinition(parentPath, ntReg, hierMgr, stateMgr);
  +	ChildNodeDef parentDef = ntReg.getNodeDef(parentState.getDefinitionId());
   	if (parentDef.isProtected()) {
   	    throw new ConstraintViolationException(hierMgr.safeGetJCRPath(parentPath) + ": cannot remove child node of protected parent node");
   	}
  -	ChildNodeDef targetDef = getDefinition(nodePath, ntReg, hierMgr, stateMgr);
  +	ChildNodeDef targetDef = ntReg.getNodeDef(targetState.getDefinitionId());
   	if (targetDef.isMandatory()) {
   	    throw new ConstraintViolationException(hierMgr.safeGetJCRPath(nodePath) + ": cannot remove mandatory node");
   	}
  @@ -391,72 +403,15 @@
       }
   
       /**
  -     * Helper method that returns the definition of the specified node.
  -     *
  -     * @param nodePath
  -     * @param ntReg
  -     * @param hierMgr
  -     * @param stateMgr
  -     * @return
  -     * @throws PathNotFoundException
  -     * @throws RepositoryException   if no applicable child node definition
  -     *                               could be found or if another error occured
  -     */
  -    protected static ChildNodeDef getDefinition(Path nodePath,
  -						NodeTypeRegistry ntReg,
  -						HierarchyManagerImpl hierMgr,
  -						PersistentItemStateManager stateMgr)
  -	    throws PathNotFoundException, RepositoryException {
  -	if (nodePath.denotesRoot()) {
  -	    // shortcut
  -	    return ntReg.getRootNodeDef();
  -	}
  -	NodeState state = getNodeState(nodePath, hierMgr, stateMgr);
  -	NodeDefId defId = state.getDefinitionId();
  -	if (defId != null) {
  -	    return ntReg.getNodeDef(defId);
  -	} else {
  -	    // fallback: find matching definition in parent node's node type
  -	    NodeState parentState = getNodeState(nodePath.getAncestor(1), hierMgr, stateMgr);
  -	    return findApplicableDefinition(nodePath.getNameElement().getName(),
  -		    state.getNodeTypeName(), parentState, ntReg);
  -	}
  -    }
  -
  -    /**
  -     * Helper method that returns the definition of the specified node.
  +     * Helper method that finds the applicable definition for the
  +     * a child node with the given name and node type in the parent node's
  +     * node type and mixin types.
        *
  -     * @param state
        * @param name
  +     * @param nodeTypeName
        * @param parentState
        * @param ntReg
        * @return a <code>ChildNodeDef</code>
  -     * @throws RepositoryException if no applicable child node definition
  -     *                             could be found
  -     */
  -    protected static ChildNodeDef getDefinition(NodeState state, QName name,
  -						NodeState parentState,
  -						NodeTypeRegistry ntReg)
  -	    throws RepositoryException {
  -	NodeDefId defId = state.getDefinitionId();
  -	if (defId != null) {
  -	    return ntReg.getNodeDef(defId);
  -	} else {
  -	    // fallback: find matching definition in parent node's node type
  -	    return findApplicableDefinition(name, state.getNodeTypeName(), parentState, ntReg);
  -	}
  -    }
  -
  -    /**
  -     * Helper method that finds the applicable definition for the
  -     * a child node with the given name and node type in the parent node's
  -     * node type and mixin types.
  -     * 
  -     * @param name         
  -     * @param nodeTypeName 
  -     * @param parentState  
  -     * @param ntReg        
  -     * @return a <code>ChildNodeDef</code>
        * @throws ConstraintViolationException if no applicable child node definition
        *                                      could be found
        * @throws RepositoryException          if another error occurs
  @@ -723,13 +678,18 @@
       /**
        * @see Workspace#clone(String, String, String)
        */
  -    public void clone(String srcAbsPath, String destAbsPath, String destWorkspace) throws NoSuchWorkspaceException, ConstraintViolationException, AccessDeniedException, PathNotFoundException, ItemExistsException, RepositoryException {
  -	PersistentItemStateManager destStateMgr = rep.getWorkspaceStateManager(destWorkspace);
  -	// FIXME need to setup a hierarchy manager for destination workspace
  -	HierarchyManagerImpl destHierMgr = new HierarchyManagerImpl(rep.getRootNodeUUID(), destStateMgr, session.getNamespaceResolver());
  +    public void clone(String srcWorkspace, String srcAbsPath, String destAbsPath)
  +	    throws NoSuchWorkspaceException, ConstraintViolationException,
  +	    AccessDeniedException, PathNotFoundException,
  +	    ItemExistsException, RepositoryException {
  +	// clone (i.e. pull) subtree at srcAbsPath from srcWorkspace
  +	// to 'this' workspace at destAbsPath
  +	PersistentItemStateManager srcStateMgr = rep.getWorkspaceStateManager(srcWorkspace);
  +	// FIXME need to setup a hierarchy manager for source workspace
  +	HierarchyManagerImpl srcHierMgr = new HierarchyManagerImpl(rep.getRootNodeUUID(), srcStateMgr, session.getNamespaceResolver());
   	// do cross-workspace copy
  -	internalCopy(srcAbsPath, persistentStateMgr, hierMgr,
  -		destAbsPath, destStateMgr, destHierMgr,
  +	internalCopy(srcAbsPath, srcStateMgr, srcHierMgr,
  +		destAbsPath, persistentStateMgr, hierMgr,
   		session.getAccessManager(), session.getNamespaceResolver(),
   		rep.getNodeTypeRegistry(), true);
       }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org