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>[EMAIL PROTECTED] 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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to