jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tri...@apache.org
Subject svn commit: r795452 [3/3] - in /jackrabbit/sandbox/tripod-JCR-2209: ./ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/
Date Sun, 19 Jul 2009 00:09:41 GMT
Added: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImplRestore.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImplRestore.java?rev=795452&view=auto
==============================================================================
--- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImplRestore.java (added)
+++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImplRestore.java Sun Jul 19 00:09:40 2009
@@ -0,0 +1,552 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.version;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.ItemExistsException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.version.OnParentVersionAction;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionException;
+import javax.jcr.version.VersionManager;
+
+import org.apache.jackrabbit.core.BatchedItemOperations;
+import org.apache.jackrabbit.core.HierarchyManager;
+import org.apache.jackrabbit.core.ItemValidator;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.id.NodeId;
+import org.apache.jackrabbit.core.nodetype.PropDef;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.state.ChildNodeEntry;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.PropertyState;
+import org.apache.jackrabbit.core.state.UpdatableItemStateManager;
+import org.apache.jackrabbit.core.value.InternalValue;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The JCR Version Manager impementation is split in several classes in order to
+ * group related methods together.
+ * </p>
+ * this class provides methods for the restore operations.
+ */
+abstract public class JcrVersionManagerImplRestore extends JcrVersionManagerImplBase {
+
+    /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(JcrVersionManagerImplRestore.class);
+
+    /**
+     * Creates a new version manager for the given session
+     * @param session workspace sesion
+     * @param stateMgr the underlying state manager
+     * @param hierMgr local hierarchy manager
+     */
+    protected JcrVersionManagerImplRestore(SessionImpl session,
+                                        UpdatableItemStateManager stateMgr,
+                                        HierarchyManager hierMgr) {
+        super(session, stateMgr, hierMgr);
+    }
+
+        /**
+     * @param state the state to restore
+     * @param version the version to restore
+     * @param removeExisting remove existing flag
+     * @throws RepositoryException if an error occurs
+     *
+     * @see javax.jcr.version.VersionManager#restore(String, Version, boolean)
+     */
+    protected void restore(NodeStateEx state, Version version, boolean removeExisting)
+            throws RepositoryException {
+        checkVersionable(state);
+        InternalVersion v = getVersion(version);
+        // check if 'own' version
+        if (!v.getVersionHistory().equals(getVersionHistory(state))) {
+            throw new VersionException("Unable to restore version. Not same version history.");
+        }
+        WriteOperation ops = startWriteOperation();
+        try {
+            internalRestore(state, v, new DateVersionSelector(version.getCreated()), removeExisting);
+            ops.save();
+        } catch (ItemStateException e) {
+            throw new RepositoryException(e);
+        } finally {
+            ops.close();
+        }
+    }
+
+    /**
+     * @param state the state to restore
+     * @param versionName the name of the version to restore
+     * @param removeExisting remove existing flag
+     * @throws RepositoryException if an error occurs
+     *
+     * @see VersionManager#restore(String, String, boolean)
+     */
+    protected void restore(NodeStateEx state, Name versionName, boolean removeExisting)
+            throws RepositoryException {
+        checkVersionable(state);
+        InternalVersion v = getVersionHistory(state).getVersion(versionName);
+        DateVersionSelector gvs = new DateVersionSelector(v.getCreated());
+        WriteOperation ops = startWriteOperation();
+        try {
+            internalRestore(state, v, gvs, removeExisting);
+            ops.save();
+        } catch (ItemStateException e) {
+            throw new RepositoryException(e);
+        } finally {
+            ops.close();
+        }
+    }
+
+    /**
+     * @param state the state to restore
+     * @param versionLabel the name of the version to restore
+     * @param removeExisting remove existing flag
+     * @throws RepositoryException if an error occurs
+     *
+     * @see VersionManager#restoreByLabel(String, String, boolean)
+     */
+    protected void restoreByLabel(NodeStateEx state, Name versionLabel, boolean removeExisting)
+            throws RepositoryException {
+        checkVersionable(state);
+        InternalVersion v = getVersionHistory(state).getVersionByLabel(versionLabel);
+        if (v == null) {
+            throw new VersionException("No version for label " + versionLabel + " found.");
+        }
+        WriteOperation ops = startWriteOperation();
+        try {
+            internalRestore(state, v, new LabelVersionSelector(versionLabel), removeExisting);
+            ops.save();
+        } catch (ItemStateException e) {
+            throw new RepositoryException(e);
+        } finally {
+            ops.close();
+        }
+    }
+
+    /**
+     * Restores the <code>version</code> below the <code>parent</code> node
+     * using the indicated <code>name</code>
+     *
+     * @param parent parent node
+     * @param name desired name
+     * @param version version to restore
+     * @param removeExisting remove exiting flag
+     * @throws RepositoryException if an error occurs
+     */
+    protected void restore(NodeStateEx parent, Name name, Version version, boolean removeExisting)
+            throws RepositoryException {
+        // check if versionable node exists
+        InternalFrozenNode fn = ((VersionImpl) version).getInternalFrozenNode();
+        if (stateMgr.hasItemState(fn.getFrozenId())) {
+            if (removeExisting) {
+                NodeStateEx existing = parent.getNode(fn.getFrozenId());
+                checkVersionable(existing);
+                InternalVersion v = getVersion(version);
+
+                // move versionable node below this one using the given "name"
+                WriteOperation ops = startWriteOperation();
+                try {
+                    NodeStateEx exParent = existing.getParent();
+                    NodeStateEx state = parent.moveFrom(existing, name, false);
+                    exParent.store();
+                    parent.store();
+                    // and restore it
+                    internalRestore(state, v, new DateVersionSelector(v.getCreated()), removeExisting);
+                    ops.save();
+                } catch (ItemStateException e) {
+                    throw new RepositoryException(e);
+                } finally {
+                    ops.close();
+                }
+            } else {
+                throw new ItemExistsException("Unable to restore version. Versionable node already exists.");
+            }
+        } else {
+            // create new node below parent
+            NodeStateEx state = parent.addNode(name, fn.getFrozenPrimaryType(), fn.getFrozenId());
+            state.setMixins(fn.getFrozenMixinTypes());
+            restore(state, version, removeExisting);
+        }
+    }
+
+    /**
+     * @param versions Versions to restore
+     * @param removeExisting remove existing flag
+     * @throws RepositoryException if an error occurs
+     *
+     * @see VersionManager#restore(Version[], boolean)
+     * @see VersionManager#restore(Version, boolean)
+     */
+    protected void restore(final Map<NodeId, InternalVersion> versions,
+                           boolean removeExisting)
+            throws RepositoryException {
+
+        // create a version selector to the set of versions
+        VersionSelector vsel = new VersionSelector() {
+            public InternalVersion select(InternalVersionHistory versionHistory) throws RepositoryException {
+                // try to select version as specified
+                InternalVersion v = versions.get(versionHistory.getId());
+                if (v == null) {
+                    // select latest one
+                    v = DateVersionSelector.selectByDate(versionHistory, null);
+                }
+                return v;
+            }
+        };
+
+        WriteOperation ops = startWriteOperation();
+        try {
+            // now restore all versions that have a node in the workspace
+            int numRestored = 0;
+            while (versions.size() > 0) {
+                Set<InternalVersion> restored = null;
+                for (InternalVersion v : versions.values()) {
+                    NodeStateEx state = getNodeStateEx(v.getFrozenNode().getFrozenId());
+                    if (state != null) {
+                        // todo: check should operate on workspace states, too
+                        int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_HOLD;
+                        checkModify(state, options, Permission.NONE);
+                        restored = internalRestore(state, v, vsel, removeExisting);
+                        // remove restored versions from set
+                        for (InternalVersion r : restored) {
+                            versions.remove(r.getVersionHistory().getId());
+                        }
+                        numRestored += restored.size();
+                        break;
+                    }
+                }
+                if (restored == null) {
+                    if (numRestored == 0) {
+                        throw new VersionException("Unable to restore. At least one version needs"
+                                + " existing versionable node in workspace.");
+                    } else {
+                        throw new VersionException("Unable to restore. All versions with non"
+                                + " existing versionable nodes need parent.");
+                    }
+                }
+            }
+            ops.save();
+        } catch (ItemStateException e) {
+            log.error("Error while reverting changes applied during restore.", e);
+            throw new RepositoryException(e);
+        } finally {
+            ops.close();
+        }
+    }
+    
+    /**
+     * Internal method to restore a version.
+     *
+     * @param state the state to restore
+     * @param version version to restore
+     * @param vsel the version selector that will select the correct version for
+     * OPV=Version child nodes.
+     * @param removeExisting remove existing flag
+     * @return set of restored versions
+     * @throws RepositoryException if an error occurs
+     * @throws ItemStateException if an error occurs
+     */
+    protected Set<InternalVersion> internalRestore(NodeStateEx state,
+                                             InternalVersion version,
+                                             VersionSelector vsel,
+                                             boolean removeExisting)
+            throws RepositoryException, ItemStateException {
+
+        // fail if root version
+        if (version.isRootVersion()) {
+            throw new VersionException("Restore of root version not allowed.");
+        }
+
+        boolean isFull = checkVersionable(state);
+
+        // check permission
+        Path path = hierMgr.getPath(state.getNodeId());
+        session.getAccessManager().checkPermission(path, Permission.VERSION_MNGMT);
+
+        // 1. The child node and properties of N will be changed, removed or
+        //    added to, depending on their corresponding copies in V and their
+        //    own OnParentVersion attributes (see 7.2.8, below, for details).
+        Set<InternalVersion> restored = new HashSet<InternalVersion>();
+        restoreFrozenState(state, version.getFrozenNode(), vsel, restored, removeExisting);
+        restored.add(version);
+
+        if (isFull) {
+            // 2. N's jcr:baseVersion property will be changed to point to V.
+            state.setPropertyValue(
+                    NameConstants.JCR_BASEVERSION, InternalValue.create(version.getId()));
+
+            // 4. N's jcr:predecessor property is set to null
+            state.setPropertyValues(NameConstants.JCR_PREDECESSORS, PropertyType.REFERENCE, InternalValue.EMPTY_ARRAY);
+
+            // also clear mergeFailed
+            state.removeProperty(NameConstants.JCR_MERGEFAILED);
+
+        } else {
+            // with simple versioning, the node is checked in automatically,
+            // thus not allowing any branches
+            vMgr.checkin(session, state);
+        }
+        // 3. N's jcr:isCheckedOut property is set to false.
+        state.setPropertyValue(NameConstants.JCR_ISCHECKEDOUT, InternalValue.create(false));
+        state.store();
+        return restored;
+    }
+
+    /**
+     * Restores the properties and child nodes from the frozen state.
+     *
+     * @param state state to restore
+     * @param freeze the frozen node
+     * @param vsel version selector
+     * @param restored set of restored versions
+     * @param removeExisting remove existing flag
+     * @throws RepositoryException if an error occurs
+     * @throws ItemStateException if an error occurs
+     */
+    protected void restoreFrozenState(NodeStateEx state, InternalFrozenNode freeze, VersionSelector vsel,
+                                   Set<InternalVersion> restored, boolean removeExisting)
+            throws RepositoryException, ItemStateException {
+
+        // check uuid
+        if (state.getEffectiveNodeType().includesNodeType(NameConstants.MIX_REFERENCEABLE)) {
+            if (!state.getNodeId().equals(freeze.getFrozenId())) {
+                throw new ItemExistsException("Unable to restore version of " + safeGetJCRPath(state) + ". UUID changed.");
+            }
+        }
+
+        // check primary type
+        if (!freeze.getFrozenPrimaryType().equals(state.getState().getNodeTypeName())) {
+            // todo: implement
+            throw new UnsupportedRepositoryOperationException("Unable to restore version of " + safeGetJCRPath(state) + ". PrimaryType change not supported yet.");
+        }
+
+        // adjust mixins
+        state.setMixins(freeze.getFrozenMixinTypes());
+
+        // copy frozen properties
+        PropertyState[] props = freeze.getFrozenProperties();
+        HashSet<Name> propNames = new HashSet<Name>();
+        for (PropertyState prop : props) {
+            // skip properties that should not to be reverted back
+            if (prop.getName().equals(NameConstants.JCR_ACTIVITY)) {
+                continue;
+            }
+            propNames.add(prop.getName());
+            state.copyFrom(prop);
+        }
+        // remove properties that do not exist in the frozen representation
+        for (PropertyState prop: state.getProperties()) {
+            // ignore some props that are not well guarded by the OPV
+            Name propName = prop.getName();
+            if (propName.equals(NameConstants.JCR_VERSIONHISTORY)) {
+                // ignore
+            } else if (propName.equals(NameConstants.JCR_PREDECESSORS)) {
+                // ignore
+            } else if (!propNames.contains(propName)) {
+                int opv = state.getDefinition(prop).getOnParentVersion();
+                if (opv == OnParentVersionAction.COPY || opv == OnParentVersionAction.VERSION) {
+                    state.removeProperty(propName);
+                }
+            }
+        }
+
+        // add 'auto-create' properties that do not exist yet
+        for (PropDef def: state.getEffectiveNodeType().getAutoCreatePropDefs()) {
+            if (!state.hasProperty(def.getName())) {
+                // compute system generated values if necessary
+                // todo: use NodeTypeInstanceHandler
+                InternalValue[] values =
+                        BatchedItemOperations.computeSystemGeneratedPropertyValues(state.getState(), def);
+                if (values == null) {
+                    values = def.getDefaultValues();
+                }
+                if (values != null) {
+                    state.setPropertyValues(def.getName(), def.getRequiredType(), values, def.isMultiple());
+                }
+            }
+        }
+
+        // first delete some of the child nodes. this is a bit tricky, in case
+        // the child node index changed. mark an sweep
+        LinkedList<ChildNodeEntry> toDelete = new LinkedList<ChildNodeEntry>();
+        for (ChildNodeEntry entry: state.getState().getChildNodeEntries()) {
+            NodeStateEx child = state.getNode(entry.getName(), entry.getIndex());
+            int opv = child.getDefinition().getOnParentVersion();
+            if (opv == OnParentVersionAction.COPY) {
+                // only remove OPV=Copy nodes
+                toDelete.addFirst(entry);
+            } else if (opv == OnParentVersionAction.VERSION) {
+                // only remove, if node to be restored does not contain child,
+                // or if restored child is not versionable
+                NodeId vhId = child.hasProperty(NameConstants.JCR_VERSIONHISTORY)
+                        ? child.getPropertyValue(NameConstants.JCR_VERSIONHISTORY).getNodeId()
+                        : null;
+                if (vhId == null || !freeze.hasFrozenHistory(vhId)) {
+                    toDelete.addFirst(entry);
+                }
+            }
+        }
+        for (ChildNodeEntry entry: toDelete) {
+            state.removeNode(entry.getName(), entry.getIndex());
+        }
+        // need to sync with state manager
+        state.store();
+
+        // restore the frozen nodes
+        InternalFreeze[] frozenNodes = freeze.getFrozenChildNodes();
+        for (InternalFreeze child : frozenNodes) {
+            NodeStateEx restoredChild = null;
+            if (child instanceof InternalFrozenNode) {
+                InternalFrozenNode f = (InternalFrozenNode) child;
+                // check for existing
+                if (f.getFrozenId() != null) {
+                    if (stateMgr.hasItemState(f.getFrozenId())) {
+                        NodeStateEx existing = state.getNode(f.getFrozenId());
+                        if (removeExisting) {
+                            NodeStateEx parent = existing.getParent();
+                            parent.removeNode(existing);
+                            parent.store();
+                        } else if (existing.getState().isShareable()) {
+                            // if existing node is shareable, then clone it
+                            restoredChild = state.moveFrom(existing, existing.getName(), true);
+                        } else {
+                            // since we delete the OPV=Copy children beforehand, all
+                            // found nodes must be outside of this tree
+                            throw new ItemExistsException(
+                                    "Unable to restore node, item already"
+                                            + " exists outside of restored tree: "
+                                            + existing);
+                        }
+
+                    }
+                }
+                if (restoredChild == null) {
+                    restoredChild = state.addNode(f.getName(), f.getFrozenPrimaryType(), f.getFrozenId());
+                    restoredChild.setMixins(f.getFrozenMixinTypes());
+                    restoreFrozenState(restoredChild, f, vsel, restored, removeExisting);
+                }
+
+            } else if (child instanceof InternalFrozenVersionHistory) {
+                InternalFrozenVersionHistory fh = (InternalFrozenVersionHistory) child;
+                InternalVersionHistory vh = vMgr.getVersionHistory(fh.getVersionHistoryId());
+                Name oldVersion = null;
+
+                // check if representing versionable already exists somewhere
+                NodeId nodeId = vh.getVersionableId();
+                if (stateMgr.hasItemState(nodeId)) {
+                    NodeStateEx existing = state.getNode(nodeId);
+                    if (existing.getParentId() == state.getNodeId()) {
+                        // remove
+                        state.removeNode(existing);
+                    } else if (removeExisting) {
+                        NodeStateEx parent = existing.getNode(existing.getNodeId());
+                        state.moveFrom(existing, fh.getName(), false);
+                        parent.store();
+
+                        // get old version name
+                        oldVersion = getBaseVersion(existing).getName();
+                    } else {
+                        // since we delete the OPV=Copy children beforehand, all
+                        // found nodes must be outside of this tree
+                        throw new ItemExistsException(
+                                "Unable to restore node, item already exists"
+                                        + " outside of restored tree: " + existing);
+                    }
+                }
+                // get desired version from version selector
+                InternalVersion v = vsel.select(vh);
+
+                // check existing version of item exists
+                if (!stateMgr.hasItemState(nodeId)) {
+                    if (v == null) {
+                        // if version selector was unable to select version,
+                        // choose the initial one
+                        InternalVersion[] vs = vh.getRootVersion().getSuccessors();
+                        if (vs.length == 0) {
+                            String msg = "Unable to select appropariate version for "
+                                    + child.getName() + " using " + vsel;
+                            log.error(msg);
+                            throw new VersionException(msg);
+                        }
+                        v = vs[0];
+                    }
+                    InternalFrozenNode f = v.getFrozenNode();
+                    restoredChild = state.addNode(fh.getName(), f.getFrozenPrimaryType(), f.getFrozenId());
+                    restoredChild.setMixins(f.getFrozenMixinTypes());
+                } else {
+                    restoredChild = state.getNode(nodeId);
+                    if (v == null || oldVersion == null || v.getName().equals(oldVersion)) {
+                        v = null;
+                    }
+                }
+                if (v != null) {
+                    try {
+                        internalRestore(restoredChild, v, vsel, removeExisting);
+                    } catch (RepositoryException e) {
+                        log.error("Error while restoring node: " + e);
+                        log.error("  child path: " + restoredChild);
+                        log.error("  selected version: " + v.getName());
+                        StringBuffer avail = new StringBuffer();
+                        for (Name name: vh.getVersionNames()) {
+                            avail.append(name);
+                            avail.append(", ");
+                        }
+                        log.error("  available versions: " + avail);
+                        log.error("  versionselector: " + vsel);
+                        throw e;
+                    }
+                    // add this version to set
+                    restored.add(v);
+                }
+            }
+            // ensure proper ordering (issue JCR-469)
+            if (restoredChild != null && state.getEffectiveNodeType().hasOrderableChildNodes()) {
+                // order at end
+                ArrayList<ChildNodeEntry> list = new ArrayList<ChildNodeEntry>(state.getState().getChildNodeEntries());
+                ChildNodeEntry toReorder = null;
+                boolean isLast = true;
+                for (ChildNodeEntry e: list) {
+                    if (e.getId().equals(restoredChild.getNodeId())) {
+                        toReorder = e;
+                    } else if (toReorder != null) {
+                        isLast = false;
+                    }
+                }
+                if (toReorder != null && !isLast) {
+                    list.remove(toReorder);
+                    list.add(toReorder);
+                    state.getState().setChildNodeEntries(list);
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

Propchange: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImplRestore.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImplRestore.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Modified: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/LabelVersionSelector.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/LabelVersionSelector.java?rev=795452&r1=795451&r2=795452&view=diff
==============================================================================
--- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/LabelVersionSelector.java (original)
+++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/LabelVersionSelector.java Sun Jul 19 00:09:40 2009
@@ -17,9 +17,8 @@
 package org.apache.jackrabbit.core.version;
 
 import javax.jcr.RepositoryException;
-import javax.jcr.version.Version;
-import javax.jcr.version.VersionException;
-import javax.jcr.version.VersionHistory;
+
+import org.apache.jackrabbit.spi.Name;
 
 /**
  * This Class implements a version selector that selects a version by label.
@@ -38,15 +37,15 @@
     /**
      * a versionlabel hint
      */
-    private String label = null;
+    private Name label = null;
 
     /**
      * Creates a <code>LabelVersionSelector</code> that will try to select a
      * version with the given label.
      *
-     * @param label
+     * @param label label hint
      */
-    public LabelVersionSelector(String label) {
+    public LabelVersionSelector(Name label) {
         this.label = label;
     }
 
@@ -55,28 +54,26 @@
      *
      * @return the label hint.
      */
-    public String getLabel() {
+    public Name getLabel() {
         return label;
     }
 
     /**
      * Sets the label hint
      *
-     * @param label
+     * @param label label hint
      */
-    public void setLabel(String label) {
+    public void setLabel(Name label) {
         this.label = label;
     }
 
     /**
+     * {@inheritDoc}
+     *
      * Selects a version from the given version history using the previously
      * assigned hint in the following order: name, label, date, latest.
-     *
-     * @param versionHistory
-     * @return
-     * @throws RepositoryException
      */
-    public Version select(VersionHistory versionHistory)
+    public InternalVersion select(InternalVersionHistory versionHistory)
             throws RepositoryException {
         return selectByLabel(versionHistory, label);
     }
@@ -84,18 +81,14 @@
     /**
      * Selects a version by label
      *
-     * @param history
-     * @param label
+     * @param history history to select from
+     * @param label desired label
      * @return the version with the given label or <code>null</code>
-     * @throws RepositoryException
+     * @throws RepositoryException if an error occurs
      */
-    public static Version selectByLabel(VersionHistory history, String label)
+    public static InternalVersion selectByLabel(InternalVersionHistory history, Name label)
             throws RepositoryException {
-        try {
-            return history.getVersionByLabel(label);
-        } catch (VersionException e) {
-            return null;
-        }
+        return history.getVersionByLabel(label);
     }
 
     /**

Modified: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java?rev=795452&r1=795451&r2=795452&view=diff
==============================================================================
--- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java (original)
+++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java Sun Jul 19 00:09:40 2009
@@ -16,32 +16,34 @@
  */
 package org.apache.jackrabbit.core.version;
 
+import java.util.List;
+import java.util.Set;
+
+import javax.jcr.ItemExistsException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+
+import org.apache.jackrabbit.core.PropertyImpl;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.id.PropertyId;
-import org.apache.jackrabbit.core.PropertyImpl;
 import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
 import org.apache.jackrabbit.core.nodetype.NodeDef;
 import org.apache.jackrabbit.core.nodetype.NodeTypeConflictException;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.nodetype.PropDef;
+import org.apache.jackrabbit.core.state.ChildNodeEntry;
 import org.apache.jackrabbit.core.state.ItemState;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
 import org.apache.jackrabbit.core.state.UpdatableItemStateManager;
-import org.apache.jackrabbit.core.state.ChildNodeEntry;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 
-import java.util.List;
-import java.util.Set;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.PropertyType;
-import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
-
 /**
  * This Class provides some basic node operations directly on the node state.
  */
@@ -70,8 +72,10 @@
     /**
      * Creates a new persistent node
      *
-     * @param stateMgr
-     * @param nodeState
+     * @param stateMgr state manager
+     * @param ntReg node type registry
+     * @param nodeState underlying node state
+     * @param name name (can be null)
      */
     public NodeStateEx(UpdatableItemStateManager stateMgr,
                        NodeTypeRegistry ntReg,
@@ -82,6 +86,26 @@
         this.name = name;
     }
 
+    /**
+     * Creates a new persistent node
+     *
+     * @param stateMgr state manager
+     * @param ntReg node type registry
+     * @param nodeId node id
+     * @throws RepositoryException if the node state can't be loaded
+     */
+    public NodeStateEx(UpdatableItemStateManager stateMgr,
+                       NodeTypeRegistry ntReg,
+                       NodeId nodeId) throws RepositoryException {
+        try {
+            this.ntReg = ntReg;
+            this.stateMgr = stateMgr;
+            this.nodeState = (NodeState) stateMgr.getItemState(nodeId);
+        } catch (ItemStateException e) {
+            throw new RepositoryException(e);
+        }
+    }
+
 
     /**
      * returns the name of this node
@@ -95,7 +119,7 @@
                 NodeState parent = (NodeState) stateMgr.getItemState(parentId);
                 name = parent.getChildNodeEntry(nodeState.getNodeId()).getName();
             } catch (ItemStateException e) {
-                // should never occurr
+                // should never occur
                 throw new IllegalStateException(e.toString());
             }
         }
@@ -121,6 +145,19 @@
     }
 
     /**
+     * Returns the parent node of this node
+     *
+     * @return the parent node of this node or <code>null</code> if root node
+     * @throws RepositoryException if an error occurs
+     */
+    public NodeStateEx getParent() throws RepositoryException {
+        if (nodeState.getParentId() == null) {
+            return null;
+        }
+        return getNode(nodeState.getParentId());
+    }
+
+    /**
      * Returns the underlaying node state.
      * @return the underlaying node state.
      */
@@ -132,6 +169,7 @@
      * Returns the properties of this node
      *
      * @return the properties of this node
+     * @throws ItemStateException if an error occurs
      */
     public PropertyState[] getProperties() throws ItemStateException {
         Set<Name> set = nodeState.getPropertyNames();
@@ -147,7 +185,7 @@
     /**
      * Checks if the given property exists
      *
-     * @param name
+     * @param name name of the property
      * @return <code>true</code> if the given property exists.
      */
     public boolean hasProperty(Name name) {
@@ -158,7 +196,7 @@
     /**
      * Returns the values of the given property of <code>null</code>
      *
-     * @param name
+     * @param name name of the property
      * @return the values of the given property.
      */
     public InternalValue[] getPropertyValues(Name name) {
@@ -174,7 +212,7 @@
     /**
      * Returns the value of the given property or <code>null</code>
      *
-     * @param name
+     * @param name name of the property
      * @return the value of the given property.
      */
     public InternalValue getPropertyValue(Name name) {
@@ -190,9 +228,9 @@
     /**
      * Sets the property value
      *
-     * @param name
-     * @param value
-     * @throws RepositoryException
+     * @param name name of the property
+     * @param value value to set
+     * @throws RepositoryException if an error occurs
      */
     public void setPropertyValue(Name name, InternalValue value)
             throws RepositoryException {
@@ -202,10 +240,10 @@
     /**
      * Sets the property values
      *
-     * @param name
-     * @param type
-     * @param values
-     * @throws RepositoryException
+     * @param name name of the property
+     * @param type property type
+     * @param values values to set
+     * @throws RepositoryException if an error occurs
      */
     public void setPropertyValues(Name name, int type, InternalValue[] values)
             throws RepositoryException {
@@ -215,56 +253,43 @@
     /**
      * Sets the property values
      *
-     * @param name
-     * @param type
-     * @param values
-     * @throws RepositoryException
-     */
-    public void setPropertyValues(Name name, int type, InternalValue[] values, boolean multiple)
-            throws RepositoryException {
-
-        PropertyState prop = getOrCreatePropertyState(name, type, multiple);
-        prop.setValues(values);
-    }
-
-
-    /**
-     * Retrieves or creates a new property state as child property of this node
-     *
-     * @param name
-     * @param type
-     * @param multiValued
-     * @return the property state
-     * @throws RepositoryException
+     * @param name name of the property
+     * @param type type of the values
+     * @param values values to set
+     * @param multiple <code>true</code>for MV properties
+     * @return the modified property state
+     * @throws RepositoryException if an error occurs
      */
-    private PropertyState getOrCreatePropertyState(Name name, int type, boolean multiValued)
+    public PropertyState setPropertyValues(Name name, int type, InternalValue[] values, boolean multiple)
             throws RepositoryException {
-
         PropertyId propId = new PropertyId(nodeState.getNodeId(), name);
         if (stateMgr.hasItemState(propId)) {
             try {
                 PropertyState propState = (PropertyState) stateMgr.getItemState(propId);
-                // someone calling this method will always alter the property state, so set status to modified
                 if (propState.getStatus() == ItemState.STATUS_EXISTING) {
                     propState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
                 }
-                // although this is not quite correct, we mark node as modified aswell
+                // although this is not quite correct, we mark node as modified as well
                 if (nodeState.getStatus() == ItemState.STATUS_EXISTING) {
                     nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
                 }
+                propState.setType(type);
+                propState.setValues(values);
                 return propState;
             } catch (ItemStateException e) {
                 throw new RepositoryException("Unable to create property: " + e.toString());
             }
         } else {
+
+            PropDef pd = getEffectiveNodeType().getApplicablePropertyDef(name, type, multiple);
+
             PropertyState propState = stateMgr.createNew(name, nodeState.getNodeId());
             propState.setType(type);
-            propState.setMultiValued(multiValued);
-
-            PropDef pd = getEffectiveNodeType().getApplicablePropertyDef(name, type, multiValued);
+            propState.setMultiValued(multiple);
             propState.setDefinitionId(pd.getId());
+            propState.setValues(values);
 
-            // need to store nodestate
+            // need to store node state
             nodeState.addPropertyName(name);
             if (nodeState.getStatus() == ItemState.STATUS_EXISTING) {
                 nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
@@ -278,7 +303,7 @@
      * of this node's primary and mixin node types.
      *
      * @return the effective node type
-     * @throws RepositoryException
+     * @throws RepositoryException if an error occurs
      */
     public EffectiveNodeType getEffectiveNodeType() throws RepositoryException {
         try {
@@ -293,7 +318,7 @@
     /**
      * checks if the given child node exists.
      *
-     * @param name
+     * @param name name of the node
      * @return <code>true</code> if the given child exists.
      */
     public boolean hasNode(Name name) {
@@ -303,30 +328,53 @@
     /**
      * removes the (first) child node with the given name.
      *
-     * @param name
+     * @param name name of hte node
      * @return <code>true</code> if the child was removed
-     * @throws RepositoryException
+     * @throws RepositoryException if an error occurs
      */
     public boolean removeNode(Name name) throws RepositoryException {
         return removeNode(name, 1);
     }
 
     /**
+     * removes the given child node
+     *
+     * @param node child node to remove
+     * @return <code>true</code> if the child was removed
+     * @throws RepositoryException if an error occurs
+     */
+    public boolean removeNode(NodeStateEx node) throws RepositoryException {
+        // locate child node entry
+        return removeNode(nodeState.getChildNodeEntry(node.getNodeId()));
+    }
+
+
+    /**
      * removes the child node with the given name and 1-based index
      *
-     * @param name
-     * @param index
+     * @param name name of the child node
+     * @param index index of the child node
      * @return <code>true</code> if the child was removed.
-     * @throws RepositoryException
+     * @throws RepositoryException if an error occurs
      */
     public boolean removeNode(Name name, int index) throws RepositoryException {
+        return removeNode(nodeState.getChildNodeEntry(name, index));
+    }
+
+    /**
+     * removes the child node with the given child node entry
+     *
+     * @param entry entry to remove
+     * @return <code>true</code> if the child was removed.
+     * @throws RepositoryException if an error occurs
+     */
+    public boolean removeNode(ChildNodeEntry entry) throws RepositoryException {
         try {
-            ChildNodeEntry entry = nodeState.getChildNodeEntry(name, index);
             if (entry == null) {
                 return false;
             } else {
                 removeNode(entry.getId());
-                nodeState.removeChildNodeEntry(name, index);
+                nodeState.removeChildNodeEntry(entry.getId());
                 nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
                 return true;
             }
@@ -338,8 +386,8 @@
     /**
      * removes recursively the node with the given id
      *
-     * @param id
-     * @throws ItemStateException
+     * @param id node id
+     * @throws ItemStateException if an error occurs
      */
     private void removeNode(NodeId id) throws ItemStateException {
         NodeState state = (NodeState) stateMgr.getItemState(id);
@@ -365,9 +413,9 @@
     /**
      * removes the property with the given name
      *
-     * @param name
+     * @param name name of the property
      * @return <code>true</code> if the property was removed.
-     * @throws RepositoryException
+     * @throws RepositoryException if an error occurs
      */
     public boolean removeProperty(Name name) throws RepositoryException {
         try {
@@ -390,10 +438,10 @@
      * retrieves the child node with the given name and 1-base index or
      * <code>null</code> if the node does not exist.
      *
-     * @param name
-     * @param index
+     * @param name name of hte child node
+     * @param index index of thechild node
      * @return the node state.
-     * @throws RepositoryException
+     * @throws RepositoryException if an error occurs
      */
     public NodeStateEx getNode(Name name, int index) throws RepositoryException {
         ChildNodeEntry entry = nodeState.getChildNodeEntry(name, index);
@@ -409,14 +457,57 @@
     }
 
     /**
+     * Returns the node with the given id.
+     * @param id node id
+     * @return the new node state
+     * @throws RepositoryException if an error occurs
+     */
+    public NodeStateEx getNode(NodeId id) throws RepositoryException {
+        try {
+            NodeState state = (NodeState) stateMgr.getItemState(id);
+            return new NodeStateEx(stateMgr, ntReg, state, name);
+        } catch (ItemStateException e) {
+            throw new RepositoryException("Unable to getNode: " + e.toString());
+        }
+    }
+
+    /**
+     * Checks if the given node state exists
+     * @param id node id
+     * @return <code>true</code> if the node state exists
+     */
+    public boolean hasNode(NodeId id) {
+        return stateMgr.hasItemState(id);
+    }
+
+    /**
      * Adds a new child node with the given name
      *
-     * @param nodeName
-     * @param nodeTypeName
+     * @param nodeName name of the new node
+     * @param nodeTypeName node type name
+     * @param id id of the new node
      * @return the node state
-     * @throws NoSuchNodeTypeException
-     * @throws ConstraintViolationException
-     * @throws RepositoryException
+     * @throws NoSuchNodeTypeException if the node type does not exist
+     * @throws ConstraintViolationException if there is a constraint violation
+     * @throws RepositoryException if an error occurs
+     */
+    public NodeStateEx addNode(Name nodeName, Name nodeTypeName, NodeId id)
+            throws NoSuchNodeTypeException, ConstraintViolationException, RepositoryException {
+        return addNode(nodeName, nodeTypeName, id,
+                ntReg.getEffectiveNodeType(nodeTypeName).includesNodeType(NameConstants.MIX_REFERENCEABLE));
+    }
+
+    /**
+     * Adds a new child node with the given name
+     *
+     * @param nodeName name of the new node
+     * @param nodeTypeName node type name
+     * @param id id of the new node
+     * @param referenceable if <code>true</code>, a UUID property is created
+     * @return the node state
+     * @throws NoSuchNodeTypeException if the node type does not exist
+     * @throws ConstraintViolationException if there is a constraint violation
+     * @throws RepositoryException if an error occurs
      */
     public NodeStateEx addNode(Name nodeName, Name nodeTypeName,
                                NodeId id, boolean referenceable)
@@ -445,9 +536,11 @@
     /**
      * creates a new child node
      *
-     * @param name
-     * @param id
+     * @param name name
+     * @param nodeTypeName node type name
+     * @param id id
      * @return the newly created node.
+     * @throws RepositoryException if an error occurs
      */
     private NodeStateEx createChildNode(Name name, Name nodeTypeName, NodeId id)
             throws RepositoryException {
@@ -475,10 +568,119 @@
     }
 
     /**
+     * Moves the source node to this node using the given name.
+     * @param src shareable source node
+     * @param name name of new node
+     * @param createShare if <code>true</code> a share is created instead.
+     * @return child node
+     * @throws RepositoryException if an error occurs
+     */
+    public NodeStateEx moveFrom(NodeStateEx src, Name name, boolean createShare)
+            throws RepositoryException {
+        if (name == null) {
+            name = src.getName();
+        }
+        // (4) check for name collisions
+        NodeDef def;
+        try {
+            def = getEffectiveNodeType().getApplicableChildNodeDef(name, nodeState.getNodeTypeName(), ntReg);
+        } catch (RepositoryException re) {
+            String msg = "no definition found in parent node's node type for new node";
+            throw new ConstraintViolationException(msg, re);
+        }
+        ChildNodeEntry cne = nodeState.getChildNodeEntry(name, 1);
+        if (cne != null) {
+            // there's already a child node entry with that name;
+            // check same-name sibling setting of new node
+            if (!def.allowsSameNameSiblings()) {
+                throw new ItemExistsException(getNodeId() + "/" + name);
+            }
+            NodeState existingChild;
+            try {
+                // check same-name sibling setting of existing node
+                existingChild = (NodeState) stateMgr.getItemState(cne.getId());
+            } catch (ItemStateException e) {
+                throw new RepositoryException(e);
+            }
+            if (!ntReg.getNodeDef(existingChild.getDefinitionId()).allowsSameNameSiblings()) {
+                throw new ItemExistsException(existingChild.toString());
+            }
+        } else {
+            // check if 'add' is allowed
+            if (getDefinition().isProtected()) {
+                String msg = "not allowed to modify a protected node";
+                throw new ConstraintViolationException(msg);
+            }
+        }
+
+        if (createShare) {
+            // (5) do clone operation
+            NodeId parentId = getNodeId();
+            src.addShareParent(parentId);
+            // attach to this parent
+            nodeState.addChildNodeEntry(name, src.getNodeId());
+            if (nodeState.getStatus() == ItemState.STATUS_EXISTING) {
+                nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+            }
+            return new NodeStateEx(stateMgr, ntReg, src.getState(), name);
+        } else {
+            // detach from parent
+            NodeStateEx parent = getNode(src.getParentId());
+            parent.nodeState.removeChildNodeEntry(src.getNodeId());
+            if (parent.nodeState.getStatus() == ItemState.STATUS_EXISTING) {
+                parent.nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+            }
+            // attach to this parent
+            nodeState.addChildNodeEntry(name, src.getNodeId());
+            if (nodeState.getStatus() == ItemState.STATUS_EXISTING) {
+                nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+            }
+            NodeState srcState = src.getState();
+            srcState.setParentId(getNodeId());
+            srcState.setDefinitionId(def.getId());
+            
+            if (srcState.getStatus() == ItemState.STATUS_EXISTING) {
+                srcState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+            }
+            return new NodeStateEx(stateMgr, ntReg, srcState, name);
+        }
+    }
+
+    /**
+     * Adds a share parent id
+     * @param parentId the parent id
+     * @throws RepositoryException if an error occurs
+     */
+    private void addShareParent(NodeId parentId) throws RepositoryException {
+        // verify that we're shareable
+        if (!nodeState.isShareable()) {
+            String msg = this + " is not shareable.";
+            throw new RepositoryException(msg);
+        }
+
+        // detect share cycle (TODO)
+        // NodeId srcId = getNodeId();
+        //HierarchyManager hierMgr = session.getHierarchyManager();
+        //if (parentId.equals(srcId) || hierMgr.isAncestor(srcId, parentId)) {
+        //    String msg = "This would create a share cycle.";
+        //    log.debug(msg);
+        //    throw new RepositoryException(msg);
+        //}
+
+        if (!nodeState.containsShare(parentId)) {
+            if (nodeState.addShare(parentId)) {
+                return;
+            }
+        }
+        String msg = "Adding a shareable node twice to the same parent is not supported.";
+        throw new UnsupportedRepositoryOperationException(msg);
+    }
+
+    /**
      * returns all child nodes
      *
      * @return the child nodes.
-     * @throws RepositoryException
+     * @throws RepositoryException if an error occurs
      */
     public NodeStateEx[] getChildNodes() throws RepositoryException {
         try {
@@ -498,7 +700,7 @@
     /**
      * stores the persistent state recursively
      *
-     * @throws RepositoryException
+     * @throws RepositoryException if an error occurs
      */
     public void store() throws RepositoryException {
         try {
@@ -511,8 +713,8 @@
     /**
      * stores the given persistent state recursively
      *
-     * @param state
-     * @throws ItemStateException
+     * @param state node state to store
+     * @throws ItemStateException if an error occurs
      */
     private void store(NodeState state)
             throws ItemStateException {
@@ -539,12 +741,12 @@
     /**
      * reloads the persistent state recursively
      *
-     * @throws RepositoryException
+     * @throws RepositoryException if an error occurs
      */
     public void reload() throws RepositoryException {
         try {
             reload(nodeState);
-            // refetch nodestate if discarded
+            // refetch node state if discarded
             nodeState = (NodeState) stateMgr.getItemState(nodeState.getNodeId());
         } catch (ItemStateException e) {
             throw new RepositoryException(e);
@@ -554,8 +756,8 @@
     /**
      * reloads the given persistent state recursively
      *
-     * @param state
-     * @throws ItemStateException
+     * @param state node state
+     * @throws ItemStateException if an error occurs
      */
     private void reload(NodeState state) throws ItemStateException {
         if (state.getStatus() != ItemState.STATUS_EXISTING) {
@@ -580,8 +782,8 @@
     /**
      * copies a property
      *
-     * @param prop
-     * @throws RepositoryException
+     * @param prop source property
+     * @throws RepositoryException if an error occurs
      */
     public void copyFrom(PropertyImpl prop) throws RepositoryException {
         if (prop.getDefinition().isMultiple()) {
@@ -596,4 +798,36 @@
         }
     }
 
+    /**
+     * copies a property
+     *
+     * @param prop source property
+     * @throws RepositoryException if an error occurs
+     */
+    public void copyFrom(PropertyState prop) throws RepositoryException {
+        InternalValue[] values = prop.getValues();
+        InternalValue[] copiedValues = new InternalValue[values.length];
+        for (int i = 0; i < values.length; i++) {
+            copiedValues[i] = values[i].createCopy();
+        }
+        setPropertyValues(prop.getName(), prop.getType(), copiedValues, prop.isMultiValued());
+    }
+
+    /**
+     * Returns the NodeDef for this state
+     * @return the node def
+     */
+    public NodeDef getDefinition() {
+        return ntReg.getNodeDef(nodeState.getDefinitionId());
+    }
+
+    /**
+     * Returns the property definition for the property state
+     * @param prop the property state
+     * @return the prop def
+     */
+    public PropDef getDefinition(PropertyState prop) {
+        return ntReg.getPropDef(prop.getDefinitionId());
+    }
+
 }

Modified: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManager.java?rev=795452&r1=795451&r2=795452&view=diff
==============================================================================
--- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManager.java (original)
+++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManager.java Sun Jul 19 00:09:40 2009
@@ -62,20 +62,22 @@
      * invokes the checkin() on the persistent version manager and remaps the
      * newly created version objects.
      *
+     * @param session session that invokes the checkin
      * @param node node to checkin
      * @return the newly created version
      * @throws RepositoryException if an error occurs
      */
-    Version checkin(NodeImpl node) throws RepositoryException;
+    InternalVersion checkin(Session session, NodeStateEx node) throws RepositoryException;
 
     /**
      * invokes the checkout() on the persistent version manager.
      *
-     * @param node node to checkout
-     * @return the base version
+     * @param state node to checkout
+     * @param activityId node id if the current activity
+     * @return the base version id
      * @throws RepositoryException if an error occurs
      */
-    Version checkout(NodeImpl node) throws RepositoryException;
+    NodeId canCheckout(NodeStateEx state, NodeId activityId) throws RepositoryException;
 
     /**
      * Removes the specified version from the given version history.

Modified: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java?rev=795452&r1=795451&r2=795452&view=diff
==============================================================================
--- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java (original)
+++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java Sun Jul 19 00:09:40 2009
@@ -23,20 +23,19 @@
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.jcr.version.ActivityViolationException;
 import javax.jcr.version.Version;
 import javax.jcr.version.VersionException;
 import javax.jcr.version.VersionHistory;
-import javax.jcr.version.ActivityViolationException;
 
 import org.apache.commons.collections.map.ReferenceMap;
-import org.apache.jackrabbit.core.id.ItemId;
-import org.apache.jackrabbit.core.id.NodeId;
-import org.apache.jackrabbit.core.NodeImpl;
-import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.cluster.UpdateEventChannel;
 import org.apache.jackrabbit.core.cluster.UpdateEventListener;
 import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.id.ItemId;
+import org.apache.jackrabbit.core.id.NodeId;
+import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.observation.DelegatingObservationDispatcher;
 import org.apache.jackrabbit.core.observation.EventState;
@@ -51,10 +50,10 @@
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.ItemStateListener;
 import org.apache.jackrabbit.core.state.LocalItemStateManager;
+import org.apache.jackrabbit.core.state.NodeReferences;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
 import org.apache.jackrabbit.core.state.SharedItemStateManager;
-import org.apache.jackrabbit.core.state.NodeReferences;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
 import org.apache.jackrabbit.spi.Name;
@@ -357,10 +356,9 @@
      * checks if the checkout is valid in respect to a possible activity set on
      * the session
      */
-    public Version checkout(NodeImpl node) throws RepositoryException {
-        NodeId baseId = NodeId.valueOf(node.getProperty(NameConstants.JCR_BASEVERSION).getString());
-        NodeImpl activity = (NodeImpl) node.getSession().getWorkspace().getVersionManager().getActivity();
-        if (activity != null) {
+    public NodeId canCheckout(NodeStateEx state, NodeId activityId) throws RepositoryException {
+        NodeId baseId = state.getPropertyValue(NameConstants.JCR_BASEVERSION).getNodeId();
+        if (activityId != null) {
             // If there exists another workspace with node N' where N' also has version
             // history H, N' is checked out and the jcr:activity property of N'
             // references A, then the checkout fails with an
@@ -369,10 +367,9 @@
 
             // we're currently leverage the fact, that only references to "real"
             // workspaces are recorded.
-            NodeId nodeId = activity.getNodeId();
-            if (stateMgr.hasNodeReferences(nodeId)) {
+            if (stateMgr.hasNodeReferences(activityId)) {
                 try {
-                    NodeReferences refs = stateMgr.getNodeReferences(nodeId);
+                    NodeReferences refs = stateMgr.getNodeReferences(activityId);
                     if (refs.hasReferences()) {
                         throw new ActivityViolationException("Unable to checkout. " +
                                 "Activity is already used for the same node in " +
@@ -383,12 +380,11 @@
                 }
             }
 
-            // TODO:
             // If there is a version in H that is not an eventual predecessor of N but
             // whose jcr:activity references A, then the checkout fails with an
             // ActivityViolationException
-            InternalActivityImpl a = (InternalActivityImpl) getItem(nodeId);
-            NodeId historyId = NodeId.valueOf(node.getProperty(NameConstants.JCR_VERSIONHISTORY).getString());
+            InternalActivityImpl a = (InternalActivityImpl) getItem(activityId);
+            NodeId historyId = state.getPropertyValue(NameConstants.JCR_VERSIONHISTORY).getNodeId();
             InternalVersionHistory history = (InternalVersionHistory) getItem(historyId);
             InternalVersion version = a.getLatestVersion(history);
             if (version != null) {
@@ -402,8 +398,7 @@
                 }
             }
         }
-        return (VersionImpl)
-                ((SessionImpl) node.getSession()).getNodeById(baseId);
+        return baseId;
     }
 
     /**
@@ -412,16 +407,17 @@
      * This method must not be synchronized since it could cause deadlocks with
      * item-reading listeners in the observation thread.
      */
-    public Version checkin(final NodeImpl node) throws RepositoryException {
-        InternalVersion version = (InternalVersion)
-                escFactory.doSourced((SessionImpl) node.getSession(), new SourcedTarget() {
+    public InternalVersion checkin(final Session session, final NodeStateEx node)
+            throws RepositoryException {
+        return (InternalVersion)
+                escFactory.doSourced((SessionImpl) session, new SourcedTarget() {
             public Object run() throws RepositoryException {
                 InternalVersionHistory vh;
-                if (node.isNodeType(NameConstants.MIX_VERSIONABLE)) {
+                if (node.getEffectiveNodeType().includesNodeType(NameConstants.MIX_VERSIONABLE)) {
                     // in full versioning, the history id can be retrieved via
                     // the property
-                    String histUUID = node.getProperty(NameConstants.JCR_VERSIONHISTORY).getString();
-                    vh = getVersionHistory(NodeId.valueOf(histUUID));
+                    NodeId histId = node.getPropertyValue(NameConstants.JCR_VERSIONHISTORY).getNodeId();
+                    vh = getVersionHistory(histId);
                     return internalCheckin((InternalVersionHistoryImpl) vh, node, false);
                 } else {
                     // in simple versioning the history id needs to be calculated
@@ -430,9 +426,6 @@
                 }
             }
         });
-
-        return (VersionImpl)
-                ((SessionImpl) node.getSession()).getNodeById(version.getId());
     }
 
     /**

Modified: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionSelector.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionSelector.java?rev=795452&r1=795451&r2=795452&view=diff
==============================================================================
--- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionSelector.java (original)
+++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionSelector.java Sun Jul 19 00:09:40 2009
@@ -17,8 +17,6 @@
 package org.apache.jackrabbit.core.version;
 
 import javax.jcr.RepositoryException;
-import javax.jcr.version.Version;
-import javax.jcr.version.VersionHistory;
 
 /**
  * This Interface defines the version selector that needs to provide a version,
@@ -42,10 +40,7 @@
  *
  * @see DateVersionSelector
  * @see LabelVersionSelector
- * @see org.apache.jackrabbit.core.NodeImpl#restore(String, boolean)
- * @see org.apache.jackrabbit.core.NodeImpl#restore(Version, boolean)
- * @see org.apache.jackrabbit.core.NodeImpl#restore(Version, String, boolean)
- * @see org.apache.jackrabbit.core.NodeImpl#restoreByLabel(String, boolean)
+ * @see javax.jcr.version.VersionManager#restore
  *
  */
 public interface VersionSelector {
@@ -59,6 +54,6 @@
      * @return A version or <code>null</code>.
      * @throws RepositoryException if an error occurs.
      */
-    Version select(VersionHistory versionHistory) throws RepositoryException;
+    InternalVersion select(InternalVersionHistory versionHistory) throws RepositoryException;
 
 }

Modified: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java?rev=795452&r1=795451&r2=795452&view=diff
==============================================================================
--- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java (original)
+++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java Sun Jul 19 00:09:40 2009
@@ -208,31 +208,32 @@
     /**
      * {@inheritDoc}
      */
-    public Version checkout(NodeImpl node) throws RepositoryException {
-        return vMgr.checkout(node);
+    public NodeId canCheckout(NodeStateEx state, NodeId activityId) throws RepositoryException {
+        return vMgr.canCheckout(state, activityId);
     }
 
     /**
      * {@inheritDoc}
      */
-    public Version checkin(NodeImpl node) throws RepositoryException {
+    public InternalVersion checkin(Session session, NodeStateEx node) throws RepositoryException {
         if (isInXA()) {
             InternalVersionHistory vh;
             InternalVersion version;
-            if (node.isNodeType(NameConstants.MIX_VERSIONABLE)) {
+            if (node.getEffectiveNodeType().includesNodeType(NameConstants.MIX_VERSIONABLE)) {
                 // in full versioning, the history id can be retrieved via
                 // the property
-                String histUUID = node.getProperty(NameConstants.JCR_VERSIONHISTORY).getString();
-                vh = getVersionHistory(NodeId.valueOf(histUUID));
+                NodeId histId = node.getPropertyValue(NameConstants.JCR_VERSIONHISTORY).getNodeId();
+                vh = getVersionHistory(histId);
                 version = internalCheckin((InternalVersionHistoryImpl) vh, node, false);
             } else {
                 // in simple versioning the history id needs to be calculated
                 vh = getVersionHistoryOfNode(node.getNodeId());
                 version = internalCheckin((InternalVersionHistoryImpl) vh, node, true);
             }
-            return (Version) ((SessionImpl) node.getSession()).getNodeById(version.getId());
+            return version;
+        } else {
+            return vMgr.checkin(session, node);
         }
-        return vMgr.checkin(node);
     }
 
     /**
@@ -449,7 +450,7 @@
      * Before modifying version history given, make a local copy of it.
      */
     protected InternalVersion internalCheckin(InternalVersionHistoryImpl history,
-                                      NodeImpl node, boolean simple)
+                                      NodeStateEx node, boolean simple)
             throws RepositoryException {
 
         if (history.getVersionManager() != this) {

Modified: jackrabbit/sandbox/tripod-JCR-2209/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/pom.xml?rev=795452&r1=795451&r2=795452&view=diff
==============================================================================
--- jackrabbit/sandbox/tripod-JCR-2209/pom.xml (original)
+++ jackrabbit/sandbox/tripod-JCR-2209/pom.xml Sun Jul 19 00:09:40 2009
@@ -55,7 +55,7 @@
     <module>jackrabbit-spi2jcr</module>
     <module>jackrabbit-spi2dav</module>
     <module>jackrabbit-jcr-client</module>
-    <module>jackrabbit-standalone</module>
+    <!-- <module>jackrabbit-standalone</module> -->
   </modules>
 
   <scm>



Mime
View raw message