You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2009/05/27 18:18:08 UTC

svn commit: r779227 - in /jackrabbit/trunk: jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operati...

Author: angela
Date: Wed May 27 16:18:08 2009
New Revision: 779227

URL: http://svn.apache.org/viewvc?rev=779227&view=rev
Log:
JCR-2003: JCR2SPI / SPI: Add support for JCR 2.0

- initial implementation for Node.setPrimaryType
   needs more careful testing in case of 
   > changing node definition
   > batch utilities present in spi-commons

Added:
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetPrimaryType.java
Modified:
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntryImpl.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/OperationVisitor.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/StateUtility.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SerializableBatch.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/ChangeLogImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/ConsolidatingChangeLog.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/Operations.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/BatchLogger.java
    jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Batch.java
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java
    jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java Wed May 27 16:18:08 2009
@@ -66,6 +66,7 @@
 import org.apache.jackrabbit.jcr2spi.operation.ReorderNodes;
 import org.apache.jackrabbit.jcr2spi.operation.SetMixin;
 import org.apache.jackrabbit.jcr2spi.operation.Update;
+import org.apache.jackrabbit.jcr2spi.operation.SetPrimaryType;
 import org.apache.jackrabbit.jcr2spi.state.ItemState;
 import org.apache.jackrabbit.jcr2spi.state.ItemStateValidator;
 import org.apache.jackrabbit.jcr2spi.state.NodeState;
@@ -93,15 +94,11 @@
 
     private static Logger log = LoggerFactory.getLogger(NodeImpl.class);
 
-    private Name primaryTypeName;
-
     protected NodeImpl(SessionImpl session, NodeState state, ItemLifeCycleListener[] listeners) {
         super(session, state, listeners);
         Name nodeTypeName = state.getNodeTypeName();
         // make sure the nodetype name is valid
-        if (session.getNodeTypeManager().hasNodeType(nodeTypeName)) {
-            primaryTypeName = nodeTypeName;
-        } else {
+        if (!session.getNodeTypeManager().hasNodeType(nodeTypeName)) {
             // should not occur. Since nodetypes are defined by the 'server'
             // its not possible to determine a fallback nodetype that is
             // always available.
@@ -673,15 +670,36 @@
      */
     public NodeType getPrimaryNodeType() throws RepositoryException {
         checkStatus();
-        return session.getNodeTypeManager().getNodeType(primaryTypeName);
+        return session.getNodeTypeManager().getNodeType(getPrimaryNodeTypeName());
     }
 
     /**
      * @see javax.jcr.Node#setPrimaryType(String)
      */
     public void setPrimaryType(String nodeTypeName) throws RepositoryException {
-        // TODO: implementation missing
-        throw new UnsupportedRepositoryOperationException("JCR-1104");
+        checkStatus();
+
+        if (getNodeState().isRoot()) {
+            String msg = "The primary type of the root node may not be changed.";
+            log.debug(msg);
+            throw new RepositoryException(msg);
+        }
+
+        Name ntName = getQName(nodeTypeName);
+        if (ntName.equals(getPrimaryNodeTypeName())) {
+            log.debug("Changing the primary type has no effect: '" + nodeTypeName + "' already is the primary node type.");
+            return;
+        }
+
+        NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
+        NodeType nt = ntMgr.getNodeType(ntName);
+        if (nt.isMixin() || nt.isAbstract()) {
+            throw new ConstraintViolationException("Cannot change the primary type: '" + nodeTypeName + "' is a mixin type or abstract.");
+        }
+        
+        // perform the operation
+        Operation op = SetPrimaryType.create(getNodeState(), ntName);
+        session.getSessionItemStateManager().execute(op);
     }
 
     /**
@@ -703,7 +721,7 @@
     public boolean isNodeType(String nodeTypeName) throws RepositoryException {
         checkStatus();
         // try shortcut first (avoids parsing of name)
-        if (session.getNameResolver().getJCRName(primaryTypeName).equals(nodeTypeName)) {
+        if (session.getNameResolver().getJCRName(getPrimaryNodeTypeName()).equals(nodeTypeName)) {
             return true;
         }
         // parse to Name and check against effective nodetype
@@ -823,7 +841,7 @@
     private EffectiveNodeType getRemainingENT(List remainingMixins)
             throws ConstraintViolationException, NoSuchNodeTypeException {
         Name[] allRemaining = (Name[]) remainingMixins.toArray(new Name[remainingMixins.size() + 1]);
-        allRemaining[remainingMixins.size()] = primaryTypeName;
+        allRemaining[remainingMixins.size()] = getPrimaryNodeTypeName();
         return session.getEffectiveNodeTypeProvider().getEffectiveNodeType(allRemaining);
     }
 
@@ -1294,7 +1312,7 @@
      */
     boolean isNodeType(Name qName) throws RepositoryException {
         // first do trivial checks without using type hierarchy
-        if (qName.equals(primaryTypeName)) {
+        if (qName.equals(getPrimaryNodeTypeName())) {
             return true;
         }
         // check if contained in mixin types
@@ -1597,7 +1615,7 @@
             log.error(mixin.getName() + ": not a mixin node type");
             return false;
         }
-        NodeTypeImpl primaryType = ntMgr.getNodeType(primaryTypeName);
+        NodeTypeImpl primaryType = ntMgr.getNodeType(getPrimaryNodeTypeName());
         if (primaryType.isNodeType(mixinName)) {
             log.debug(mixin.getName() + ": already contained in primary node type");
             return false;
@@ -1610,7 +1628,7 @@
 
         // check if the base type supports adding this mixin
         if (!entExisting.supportsMixin(mixinName)) {
-            log.debug(mixin.getName() + ": not supported on node type " + primaryTypeName);
+            log.debug(mixin.getName() + ": not supported on node type " + getPrimaryNodeTypeName());
             return false;
         }
 
@@ -1796,4 +1814,11 @@
             throws ConstraintViolationException, RepositoryException {
         return session.getItemDefinitionProvider().getQPropertyDefinition(getNodeState().getAllNodeTypeNames(), propertyName, type, multiValued);
     }
+
+    /**
+     * @return the primary node type name.
+     */
+    private Name getPrimaryNodeTypeName() {
+        return getNodeState().getNodeTypeName();
+    }
 }

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java Wed May 27 16:18:08 2009
@@ -60,6 +60,7 @@
 import org.apache.jackrabbit.jcr2spi.operation.CreateActivity;
 import org.apache.jackrabbit.jcr2spi.operation.CreateConfiguration;
 import org.apache.jackrabbit.jcr2spi.operation.RemoveActivity;
+import org.apache.jackrabbit.jcr2spi.operation.SetPrimaryType;
 import org.apache.jackrabbit.jcr2spi.security.AccessManager;
 import org.apache.jackrabbit.jcr2spi.observation.InternalEventListener;
 import org.apache.jackrabbit.jcr2spi.config.CacheBehaviour;
@@ -889,6 +890,14 @@
 
         /**
          * @inheritDoc
+         * @see OperationVisitor#visit(SetPrimaryType)
+         */
+        public void visit(SetPrimaryType operation) throws RepositoryException {
+            batch.setPrimaryType(operation.getNodeId(), operation.getPrimaryTypeName());
+        }
+
+        /**
+         * @inheritDoc
          * @see OperationVisitor#visit(SetPropertyValue)
          */
         public void visit(SetPropertyValue operation) throws RepositoryException {

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntryImpl.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntryImpl.java Wed May 27 16:18:08 2009
@@ -41,6 +41,7 @@
 import org.apache.jackrabbit.jcr2spi.operation.Remove;
 import org.apache.jackrabbit.jcr2spi.operation.ReorderNodes;
 import org.apache.jackrabbit.jcr2spi.operation.SetMixin;
+import org.apache.jackrabbit.jcr2spi.operation.SetPrimaryType;
 import org.apache.jackrabbit.jcr2spi.state.ItemState;
 import org.apache.jackrabbit.jcr2spi.state.NodeState;
 import org.apache.jackrabbit.jcr2spi.state.PropertyState;
@@ -278,6 +279,8 @@
             complete((AddProperty) operation);
         } else if (operation instanceof SetMixin) {
             complete((SetMixin) operation);
+        } else if (operation instanceof SetPrimaryType) {
+            complete((SetPrimaryType) operation);
         } else if (operation instanceof Remove) {
             complete((Remove) operation);
         } else if (operation instanceof ReorderNodes) {
@@ -1489,7 +1492,7 @@
                 break;
             case Operation.STATUS_UNDO:
                 if (!rmEntry.denotesNode()) {
-                    Name propName = ((PropertyEntry) rmEntry).getName();
+                    Name propName = rmEntry.getName();
                     if (propertiesInAttic.containsKey(propName)) {
                         properties.add((PropertyEntry) propertiesInAttic.remove(propName));
                     } // else: propEntry has never been moved to the attic (see 'addPropertyEntry')
@@ -1524,6 +1527,30 @@
         } // else: no such prop-Entry (should not occur)
     }
 
+    private void complete(SetPrimaryType operation) throws RepositoryException {
+        if (operation.getNodeState().getHierarchyEntry() != this) {
+            throw new IllegalArgumentException();
+        }
+        PropertyEntry pe = getPropertyEntry(NameConstants.JCR_PRIMARYTYPE);
+        if (pe != null) {
+            PropertyState pState = pe.getPropertyState();
+            switch (operation.getStatus()) {
+                case Operation.STATUS_PERSISTED:
+                    // NOTE: invalidation of this node entry is performed by
+                    // ChangeLog.persisted...
+                    // TODO: check if correct
+                    if (pState.getStatus() == Status.NEW || pState.getStatus() == Status.EXISTING_MODIFIED) {
+                        pState.setStatus(Status.EXISTING);
+                    }
+                    break;
+                case Operation.STATUS_UNDO:
+                    pe.revert();
+                    break;
+                default: // ignore
+            }
+        } // else: no such prop-Entry (should not occur)
+    }
+
     private void complete(ReorderNodes operation) throws RepositoryException {
         HierarchyEntry he = operation.getInsertNode().getHierarchyEntry();
         if (he != this) {

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/OperationVisitor.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/OperationVisitor.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/OperationVisitor.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/OperationVisitor.java Wed May 27 16:18:08 2009
@@ -42,6 +42,11 @@
 
     public void visit(SetMixin operation) throws RepositoryException;
 
+    /**
+     * @since JCR 2.0
+     */
+    public void visit(SetPrimaryType operation) throws RepositoryException;
+
     public void visit(SetPropertyValue operation) throws RepositoryException;
 
     public void visit(ReorderNodes operation) throws RepositoryException;
@@ -58,6 +63,9 @@
 
     public void visit(Checkin operation) throws UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException;
 
+    /**
+     * @since JCR 2.0
+     */
     public void visit(Checkpoint operation) throws RepositoryException;
 
     public void visit(Restore operation) throws VersionException, PathNotFoundException, ItemExistsException, UnsupportedRepositoryOperationException, LockException, InvalidItemStateException, RepositoryException;
@@ -80,9 +88,18 @@
 
     public void visit(WorkspaceImport operation) throws RepositoryException;
 
+    /**
+     * @since JCR 2.0
+     */
     public void visit(CreateActivity operation) throws RepositoryException;
 
+    /**
+     * @since JCR 2.0
+     */
     public void visit(RemoveActivity operation) throws RepositoryException;
 
+    /**
+     * @since JCR 2.0
+     */
     public void visit(CreateConfiguration operation) throws RepositoryException;
 }
\ No newline at end of file

Added: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetPrimaryType.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetPrimaryType.java?rev=779227&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetPrimaryType.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetPrimaryType.java Wed May 27 16:18:08 2009
@@ -0,0 +1,102 @@
+/*
+ * 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.jcr2spi.operation;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.jcr2spi.state.NodeState;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.version.VersionException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+
+/**
+ * <code>SetPrimaryNodeType</code>...
+ */
+public class SetPrimaryType extends AbstractOperation {
+
+    private final NodeId nodeId;
+    private final NodeState nodeState;
+    private final Name primaryTypeName;
+
+    private SetPrimaryType(NodeState nodeState, Name primaryTypeName) throws RepositoryException {
+        this.nodeState = nodeState;
+        this.nodeId = nodeState.getNodeId();
+        this.primaryTypeName = primaryTypeName;
+
+        // remember node state as affected state
+        addAffectedItemState(nodeState);
+    }
+
+    //----------------------------------------------------------< Operation >---
+    /**
+     *
+     * @param visitor
+     * @see Operation#accept(OperationVisitor)
+     */
+    public void accept(OperationVisitor visitor) throws AccessDeniedException, NoSuchNodeTypeException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+        assert status == STATUS_PENDING;
+        visitor.visit(this);
+    }
+
+    /**
+     * @see Operation#persisted()
+     */
+    public void persisted() throws RepositoryException {
+        assert status == STATUS_PENDING;
+        status = STATUS_PERSISTED;
+        nodeState.getHierarchyEntry().complete(this);
+    }
+
+    /**
+     * @see Operation#undo()
+     */
+    public void undo() throws RepositoryException {
+        assert status == STATUS_PENDING;
+        status = STATUS_UNDO;
+        nodeState.getHierarchyEntry().complete(this);
+    }
+
+    //----------------------------------------< Access Operation Parameters >---
+    public NodeState getNodeState() {
+        return nodeState;
+    }
+
+    public NodeId getNodeId() {
+        return nodeId;
+    }
+
+    public Name getPrimaryTypeName() {
+        return primaryTypeName;
+    }
+
+    //------------------------------------------------------------< Factory >---
+
+    public static Operation create(NodeState nodeState, Name primaryTypeName)
+            throws RepositoryException {
+        if (nodeState == null || primaryTypeName == null) {
+            throw new IllegalArgumentException();
+        }
+        SetPrimaryType op = new SetPrimaryType(nodeState, primaryTypeName);
+        return op;
+    }
+}
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/ChangeLog.java Wed May 27 16:18:08 2009
@@ -18,6 +18,7 @@
 
 import org.apache.jackrabbit.jcr2spi.operation.Operation;
 import org.apache.jackrabbit.jcr2spi.operation.SetMixin;
+import org.apache.jackrabbit.jcr2spi.operation.SetPrimaryType;
 import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEntry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -79,12 +80,16 @@
      * states to EXISTING.
      */
     public void persisted() throws RepositoryException {
-        List changedMixins = new ArrayList();
+        List<NodeState> changedMixins = new ArrayList<NodeState>();
+        List<NodeState> changedPrimaryTypes = new ArrayList<NodeState>();
+
         Operation[] ops = (Operation[]) operations.toArray(new Operation[operations.size()]);
         for (int i = 0; i < ops.length; i++) {
             ops[i].persisted();
             if (ops[i] instanceof SetMixin) {
                 changedMixins.add(((SetMixin) ops[i]).getNodeState());
+            } else if (ops[i] instanceof SetPrimaryType) {
+                changedPrimaryTypes.add(((SetPrimaryType) ops[i]).getNodeState());
             }
         }
         // process all remaining states that were not covered by the
@@ -96,10 +101,16 @@
             switch (state.getStatus()) {
                 case Status.EXISTING_MODIFIED:
                     state.setStatus(Status.EXISTING);
-                    if (state.isNode() && changedMixins.contains(state)) {
-                        // mixin changed for a node -> force reloading upon next
-                        // access in order to be aware of modified uniqueID.
-                        he.invalidate(false);
+                    if (state.isNode()) {
+                        if (changedPrimaryTypes.contains(state)) {
+                            // primary type changed for a node -> force reloading upon next
+                            // access in order to be aware of modified definition etc...
+                            he.invalidate(true);
+                        } else if (changedMixins.contains(state)) {
+                            // mixin changed for a node -> force reloading upon next
+                            // access in order to be aware of modified uniqueID.
+                            he.invalidate(false);
+                        }
                     }
                     break;
                 case Status.EXISTING_REMOVED:

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/NodeState.java Wed May 27 16:18:08 2009
@@ -47,7 +47,7 @@
     /**
      * the name of this node's primary type
      */
-    private final Name nodeTypeName;
+    private Name nodeTypeName;
 
     /**
      * Definition of this node state
@@ -132,6 +132,11 @@
             synchronized (another) {
                 NodeState nState = (NodeState) another;
 
+                if (!nodeTypeName.equals(nState.nodeTypeName)) {
+                    nodeTypeName = nState.nodeTypeName;
+                    modified = true;
+                }
+
                 if (nState.definition != null && !nState.definition.equals(definition)) {
                     definition = nState.definition;
                     modified = true;

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java Wed May 27 16:18:08 2009
@@ -20,6 +20,7 @@
 import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
 import org.apache.jackrabbit.jcr2spi.hierarchy.PropertyEntry;
 import org.apache.jackrabbit.jcr2spi.nodetype.EffectiveNodeType;
+import org.apache.jackrabbit.jcr2spi.nodetype.EffectiveNodeTypeProvider;
 import org.apache.jackrabbit.jcr2spi.nodetype.ItemDefinitionProvider;
 import org.apache.jackrabbit.jcr2spi.operation.AddNode;
 import org.apache.jackrabbit.jcr2spi.operation.AddProperty;
@@ -29,6 +30,7 @@
 import org.apache.jackrabbit.jcr2spi.operation.Remove;
 import org.apache.jackrabbit.jcr2spi.operation.ReorderNodes;
 import org.apache.jackrabbit.jcr2spi.operation.SetMixin;
+import org.apache.jackrabbit.jcr2spi.operation.SetPrimaryType;
 import org.apache.jackrabbit.jcr2spi.operation.SetPropertyValue;
 import org.apache.jackrabbit.jcr2spi.operation.TransientOperationVisitor;
 import org.apache.jackrabbit.jcr2spi.util.ReferenceChangeTracker;
@@ -56,6 +58,7 @@
 import javax.jcr.version.VersionException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 
@@ -364,6 +367,37 @@
     }
 
     /**
+     * @see OperationVisitor#visit(SetPrimaryType)
+     */
+    public void visit(SetPrimaryType operation) throws ConstraintViolationException, RepositoryException {
+        // NOTE: nodestate is only modified upon save of the changes!
+        Name primaryName = operation.getPrimaryTypeName();
+        NodeState nState = operation.getNodeState();
+        NodeEntry nEntry = nState.getNodeEntry();
+
+        // detect obvious node type conflicts
+
+        EffectiveNodeTypeProvider entProvider = mgrProvider.getEffectiveNodeTypeProvider();
+
+        // try to build new effective node type (will throw in case of conflicts)
+        Name[] mixins = nState.getMixinTypeNames();
+        List<Name> all = new ArrayList<Name>(Arrays.asList(mixins));
+        all.add(primaryName);
+        EffectiveNodeType entAll = entProvider.getEffectiveNodeType(all.toArray(new Name[all.size()]));
+
+        // modify the value of the jcr:primaryType property entry without
+        // changing the node state itself
+        PropertyEntry pEntry = nEntry.getPropertyEntry(NameConstants.JCR_PRIMARYTYPE);
+        PropertyState pState = pEntry.getPropertyState();
+        int options = ItemStateValidator.CHECK_VERSIONING | ItemStateValidator.CHECK_LOCK;
+        setPropertyStateValue(pState, getQValues(new Name[] {primaryName}, qValueFactory), PropertyType.NAME, options);
+
+        // mark the affected node state modified and remember the operation
+        nState.markModified();
+        transientStateMgr.addOperation(operation);
+    }
+
+    /**
      * @inheritDoc
      * @see OperationVisitor#visit(SetPropertyValue)
      */
@@ -436,7 +470,7 @@
             // try default primary type from definition
             nodeTypeName = definition.getDefaultPrimaryType();
             if (nodeTypeName == null) {
-                String msg = "an applicable node type could not be determined for " + nodeName;
+                String msg = "No applicable node type could be determined for " + nodeName;
                 log.debug(msg);
                 throw new ConstraintViolationException(msg);
             }

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/StateUtility.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/StateUtility.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/StateUtility.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/StateUtility.java Wed May 27 16:18:08 2009
@@ -58,6 +58,13 @@
         }
     }
 
+    public static Name getPrimaryTypeName(PropertyState ps) throws RepositoryException {
+        if (!NameConstants.JCR_PRIMARYTYPE.equals(ps.getName())) {
+            throw new IllegalArgumentException();
+        }
+        QValue[] values = ps.getValues();
+        return values[0].getName();
+    }
 
     public static boolean isUuidOrMixin(Name propName) {
         return NameConstants.JCR_UUID.equals(propName) || NameConstants.JCR_MIXINTYPES.equals(propName);

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SerializableBatch.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SerializableBatch.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SerializableBatch.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SerializableBatch.java Wed May 27 16:18:08 2009
@@ -122,6 +122,10 @@
         recording.add(new SetMixins(nodeId, mixinNodeTypeIds));
     }
 
+    public void setPrimaryType(NodeId nodeId, Name primaryNodeTypeName) throws RepositoryException {
+        recording.add(new SetPrimaryType(nodeId, primaryNodeTypeName));
+    }
+
     public void move(NodeId srcNodeId,
                      NodeId destParentNodeId,
                      Name destName) {
@@ -265,18 +269,37 @@
 
         private final NodeId nodeId;
 
-        private final Name[] mixinNodeTypeIds;
+        private final Name[] mixinNodeTypeNames;
+
+        SetMixins(NodeId nodeId, Name[] mixinNodeTypeNames) {
+            this.nodeId = nodeId;
+            this.mixinNodeTypeNames = mixinNodeTypeNames;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void replay(Batch batch) throws RepositoryException {
+            batch.setMixins(nodeId, mixinNodeTypeNames);
+        }
+    }
+
+    private static class SetPrimaryType implements Operation {
+
+        private final NodeId nodeId;
+
+        private final Name primaryNodeTypeName;
 
-        SetMixins(NodeId nodeId, Name[] mixinNodeTypeIds) {
+        SetPrimaryType(NodeId nodeId, Name primaryNodeTypeName) {
             this.nodeId = nodeId;
-            this.mixinNodeTypeIds = mixinNodeTypeIds;
+            this.primaryNodeTypeName = primaryNodeTypeName;
         }
 
         /**
          * {@inheritDoc}
          */
         public void replay(Batch batch) throws RepositoryException {
-            batch.setMixins(nodeId, mixinNodeTypeIds);
+            batch.setPrimaryType(nodeId, primaryNodeTypeName);
         }
     }
 

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/ChangeLogImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/ChangeLogImpl.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/ChangeLogImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/ChangeLogImpl.java Wed May 27 16:18:08 2009
@@ -76,6 +76,10 @@
         addOperation(Operations.setMixins(nodeId, mixinNodeTypeNames));
     }
 
+    public void setPrimaryType(NodeId nodeId, Name primaryNodeTypeName) throws RepositoryException {
+        addOperation(Operations.setPrimaryType(nodeId, primaryNodeTypeName));
+    }
+
     public void setValue(PropertyId propertyId, QValue value) throws RepositoryException {
         addOperation(Operations.setValue(propertyId, value));
     }

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/ConsolidatingChangeLog.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/ConsolidatingChangeLog.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/ConsolidatingChangeLog.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/ConsolidatingChangeLog.java Wed May 27 16:18:08 2009
@@ -103,9 +103,7 @@
         addOperation(CancelableOperations.remove(itemId));
     }
 
-    public void reorderNodes(NodeId parentId, NodeId srcNodeId, NodeId beforeNodeId)
-            throws RepositoryException {
-
+    public void reorderNodes(NodeId parentId, NodeId srcNodeId, NodeId beforeNodeId) throws RepositoryException {
         addOperation(CancelableOperations.reorderNodes(parentId, srcNodeId, beforeNodeId));
     }
 
@@ -113,6 +111,10 @@
         addOperation(CancelableOperations.setMixins(nodeId, mixinNodeTypeNames));
     }
 
+    public void setPrimaryType(NodeId nodeId, Name primaryNodeTypeName) throws RepositoryException {
+        addOperation(CancelableOperations.setPrimaryType(nodeId, primaryNodeTypeName));
+    }
+
     public void setValue(PropertyId propertyId, QValue value) throws RepositoryException {
         addOperation(CancelableOperations.setValue(propertyId, value));
     }
@@ -325,8 +327,7 @@
             return new AddNode(parentId, nodeName, nodetypeName, uuid);
         }
 
-        // -----------------------------------------------------< AddProperty >---
-
+        // ---------------------------------------------------< AddProperty >---
         /**
          * <code>AddProperty</code> operations might cancel with
          * {@link ConsolidatingChangeLog.CancelableOperations.Remove Remove} and
@@ -421,8 +422,7 @@
             return new AddProperty(parentId, propertyName, values);
         }
 
-        // -----------------------------------------------------< Move >---
-
+        // ----------------------------------------------------------< Move >---
         /**
          * An <code>Move</code> operation never cancels another operation and is never
          * cancelled by any other operation.
@@ -454,8 +454,7 @@
             return new Move(srcNodeId, destParentNodeId, destName);
         }
 
-        // -----------------------------------------------------< Remove >---
-
+        // --------------------------------------------------------< Remove >---
         /**
          * An <code>Remove</code> operation never cancels another operation and is never
          * cancelled by any other operation.
@@ -485,8 +484,7 @@
             return new Remove(itemId);
         }
 
-        // -----------------------------------------------------< Reorder Nodes >---
-
+        // -------------------------------------------------< Reorder Nodes >---
         /**
          * A <code>ReorderNodes</code> operation might cancel with
          * {@link ConsolidatingChangeLog.CancelableOperations.Remove Remove} and
@@ -549,7 +547,6 @@
         }
 
         // -----------------------------------------------------< SetMixins >---
-
         /**
          * A <code>SetMixins</code> operation might cancel with
          * {@link ConsolidatingChangeLog.CancelableOperations.Remove Remove} and
@@ -601,7 +598,7 @@
         }
 
         /**
-         * Factory method for creating a {@link SetMixins SetMixins} operation.
+         * Factory method for creating a {@link SetMixins} operation.
          *
          * @see Batch#setMixins(NodeId, Name[])
          * @param nodeId
@@ -612,8 +609,65 @@
             return new SetMixins(nodeId, mixinNodeTypeNames);
         }
 
-        // -----------------------------------------------------< SetValue >---
+        // -----------------------------------------------------< SetMixins >---
+        /**
+         * A <code>SetPrimaryType</code> operation might cancel with
+         * {@link ConsolidatingChangeLog.CancelableOperations.Remove Remove} and
+         * {@link ConsolidatingChangeLog.CancelableOperations.SetPrimaryType SetPrimaryType} operations.
+         */
+        public static class SetPrimaryType extends Operations.SetPrimaryType implements CancelableOperation {
+
+            public SetPrimaryType(NodeId nodeId, Name primaryTypeName) {
+                super(nodeId, primaryTypeName);
+            }
+
+            /**
+             * @return
+             * <ul>
+             * <li>{@link ConsolidatingChangeLog.CancelableOperation#CANCEL_THIS CANCEL_THIS} if
+             *   <code>other</code> is an instance of
+             *   {@link ConsolidatingChangeLog.CancelableOperations.Remove Remove} and has an node higher up
+             *   the hierarchy or this node as target. Or if <code>other</code> is an instance of
+             *   {@link ConsolidatingChangeLog.CancelableOperations.SetMixins SetMixins} which has this node
+             *   as target and has the same <code>mixinNodeTypeNames</code>.</li>
+             * <li>{@link ConsolidatingChangeLog.CancelableOperation#CANCEL_NONE CANCEL_NONE} otherwise.</li>
+             * </ul>
+             */
+            public int cancel(CancelableOperation other) throws RepositoryException {
+                if (other instanceof Remove) {
+                    Path thisPath = ConsolidatingChangeLog.getPath(nodeId);
+                    Path otherPath = ConsolidatingChangeLog.getPath(((Remove) other).itemId);
+                    return thisPath.isDescendantOf(otherPath) || thisPath.equals(otherPath)
+                        ? CANCEL_THIS
+                        : CANCEL_NONE;
+                }
+                if (other instanceof SetPrimaryType) {
+                    SetPrimaryType setPrimaryType = (SetPrimaryType) other;
+                    if (primaryTypeName.equals(setPrimaryType.primaryTypeName)) {
+                        Path thisPath = ConsolidatingChangeLog.getPath(nodeId);
+                        Path otherPath = ConsolidatingChangeLog.getPath(setPrimaryType.nodeId);
+                        if (thisPath.equals(otherPath)) {
+                            return CANCEL_THIS;
+                        }
+                    }
+                }
+                return CANCEL_NONE;
+            }
+        }
+
+        /**
+         * Factory method for creating a {@link SetPrimaryType} operation.
+         *
+         * @see Batch#setPrimaryType(NodeId, Name)
+         * @param nodeId
+         * @param primaryTypeName
+         * @return
+         */
+        public static CancelableOperation setPrimaryType(NodeId nodeId, Name primaryTypeName) {
+            return new SetPrimaryType(nodeId, primaryTypeName);
+        }
 
+        // ------------------------------------------------------< SetValue >---
         /**
          * A <code>SetValue</code> operation might cancel with
          * {@link ConsolidatingChangeLog.CancelableOperations.Remove Remove} and

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/Operations.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/Operations.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/Operations.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/Operations.java Wed May 27 16:18:08 2009
@@ -38,8 +38,7 @@
         super();
     }
 
-    // -----------------------------------------------------< Empty >---
-
+    // -------------------------------------------------------------< Empty >---
     /**
      * Representative of the empty {@link Operation} which does nothing when
      * applied to a {@link Batch}.
@@ -81,8 +80,7 @@
         return Empty.INSTANCE;
     }
 
-    // -----------------------------------------------------< AddNode >---
-
+    // -----------------------------------------------------------< AddNode >---
     /**
      * Representative of an add-node {@link Operation} which calls
      * {@link Batch#addNode(NodeId, Name, Name, String)} when applied to a {@link Batch}.
@@ -167,8 +165,7 @@
         return new AddNode(parentId, nodeName, nodetypeName, uuid);
     }
 
-    // -----------------------------------------------------< AddProperty >---
-
+    // -------------------------------------------------------< AddProperty >---
     /**
      * Representative of an add-property {@link Operation} which calls
      * {@link Batch#addProperty(NodeId, Name, QValue)} or {@link Batch#addProperty(NodeId, Name, QValue[])}
@@ -283,8 +280,7 @@
         return new AddProperty(parentId, propertyName, values);
     }
 
-    // -----------------------------------------------------< Move >---
-
+    // --------------------------------------------------------------< Move >---
     /**
      * Representative of a move {@link Operation} which calls
      * {@link Batch#move(NodeId, NodeId, Name)} when applied to a {@link Batch}.
@@ -361,8 +357,7 @@
         return new Move(srcNodeId, destParentNodeId, destName);
     }
 
-    // -----------------------------------------------------< Remove >---
-
+    // ------------------------------------------------------------< Remove >---
     /**
      * Representative of a remove {@link Operation} which calls {@link Batch#remove(ItemId)} when
      * applied to a {@link Batch}.
@@ -425,8 +420,7 @@
         return new Remove(itemId);
     }
 
-    // -----------------------------------------------------< ReorderNodes >---
-
+    // ------------------------------------------------------< ReorderNodes >---
     /**
      * Representative of a reorder-nodes {@link Operation} which calls
      * {@link Batch#reorderNodes(NodeId, NodeId, NodeId)} when applied to a {@link Batch}.
@@ -503,8 +497,7 @@
         return new ReorderNodes(parentId, srcNodeId, beforeNodeId);
     }
 
-    // -----------------------------------------------------< SetMixins >---
-
+    // ---------------------------------------------------------< SetMixins >---
     /**
      * Representative of a set-mixin {@link Operation} which calls
      * {@link Batch#setMixins(NodeId, Name[])} when applied to a {@link Batch}.
@@ -574,8 +567,77 @@
         return new SetMixins(nodeId, mixinNodeTypeNames);
     }
 
-    // -----------------------------------------------------< SetValue >---
+    // ----------------------------------------------------< SetPrimaryType >---
+    /**
+     * Representative of a set-mixin {@link Operation} which calls
+     * {@link Batch#setMixins(NodeId, Name[])} when applied to a {@link Batch}.
+     */
+    public static class SetPrimaryType implements Operation {
+        protected final NodeId nodeId;
+        protected final Name primaryTypeName;
+
+        /**
+         * Create a new set-mixin {@link Operation} for the given arguments.
+         *
+         * @see Batch#setMixins(NodeId, Name[])
+         * @param nodeId
+         * @param primaryTypeName
+         */
+        public SetPrimaryType(NodeId nodeId, Name primaryTypeName) {
+            super();
+            this.nodeId = nodeId;
+            this.primaryTypeName = primaryTypeName;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void apply(Batch batch) throws RepositoryException {
+            batch.setPrimaryType(nodeId, primaryTypeName);
+        }
+
+        public String toString() {
+            return "SetPrimaryType[" + nodeId + ", " + primaryTypeName + "]";
+        }
+
+        public boolean equals(Object other) {
+            if (null == other) {
+                return false;
+            }
+            if (this == other) {
+                return true;
+            }
+            if (other instanceof SetPrimaryType) {
+                return equals((SetPrimaryType) other);
+            }
+            return false;
+        }
+
+        public boolean equals(SetPrimaryType other) {
+            return Operations.equals(nodeId, other.nodeId)
+                && primaryTypeName.equals(other.primaryTypeName);
+        }
+
+        public int hashCode() {
+            return 41 * (
+                    41 + Operations.hashCode(nodeId))
+                    + Operations.hashCode(primaryTypeName);
+        }
+    }
+
+    /**
+     * Factory method for creating a set-primaryType {@link Operation} for the given arguments.
+     *
+     * @see Batch#setPrimaryType(NodeId, Name)
+     * @param nodeId
+     * @param primaryTypeName
+     * @return
+     */
+    public static Operation setPrimaryType(NodeId nodeId, Name primaryTypeName) {
+        return new SetPrimaryType(nodeId, primaryTypeName);
+    }
 
+    // ----------------------------------------------------------< SetValue >---
     /**
      * Representative of a set-value {@link Operation} which calls
      * {@link Batch#setValue(PropertyId, QValue)} or {@link Batch#setValue(PropertyId, QValue[])}
@@ -681,7 +743,7 @@
         return new SetValue(propertyId, values);
     }
 
-    // -----------------------------------------------------< private >---
+    // -----------------------------------------------------------< private >---
 
     protected static boolean equals(Object o1, Object o2) {
         return o1 == null

Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/BatchLogger.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/BatchLogger.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/BatchLogger.java (original)
+++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/BatchLogger.java Wed May 27 16:18:08 2009
@@ -123,6 +123,14 @@
             }}, "setMixins(NodeId, Name[])", new Object[]{nodeId, mixinNodeTypeNames});
     }
 
+    public void setPrimaryType(final NodeId nodeId, final Name primaryNodeTypeName) throws RepositoryException {
+        execute(new Callable() {
+            public Object call() throws RepositoryException {
+                batch.setPrimaryType(nodeId, primaryNodeTypeName);
+                return null;
+            }}, "setPrimaryType(NodeId, Name)", new Object[]{nodeId, primaryNodeTypeName});
+    }
+
     public void move(final NodeId srcNodeId, final NodeId destParentNodeId, final Name destName)
             throws RepositoryException {
 

Modified: jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Batch.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Batch.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Batch.java (original)
+++ jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Batch.java Wed May 27 16:18:08 2009
@@ -253,6 +253,16 @@
     public void setMixins(NodeId nodeId, Name[] mixinNodeTypeNames) throws RepositoryException;
 
     /**
+     * Change the primary type of the node identified by the given <code>nodeId</code>.
+     *
+     * @param nodeId NodeId identifying the node to be modified.
+     * @param primaryNodeTypeName
+     * @throws RepositoryException
+     * @see javax.jcr.Node#setPrimaryType(String)
+     */
+    public void setPrimaryType(NodeId nodeId, Name primaryNodeTypeName) throws RepositoryException;
+
+    /**
      * Move the node identified by the given <code>srcNodeId</code> to the
      * new parent identified by <code>destParentNodeId</code> and change its
      * name to <code>destName</code>.

Modified: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java Wed May 27 16:18:08 2009
@@ -2431,6 +2431,21 @@
             }
         }
 
+        public void setPrimaryType(NodeId nodeId, Name primaryNodeTypeName) throws RepositoryException {
+            checkConsumed();
+            try {
+                DavPropertySet setProperties = new DavPropertySet();
+                setProperties.add(new NodeTypeProperty(ItemResourceConstants.JCR_PRIMARYNODETYPE, new String[] {resolver.getJCRName(primaryNodeTypeName)}, false));
+
+                String uri = getItemUri(nodeId, sessionInfo);
+                PropPatchMethod method = new PropPatchMethod(uri, setProperties, new DavPropertyNameSet());
+
+                methods.add(method);
+            } catch (IOException e) {
+                throw new RepositoryException(e);
+            }
+        }
+
         /**
          * @see Batch#move(NodeId, NodeId, Name)
          */

Modified: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java Wed May 27 16:18:08 2009
@@ -43,6 +43,7 @@
 import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
 import org.apache.jackrabbit.spi.commons.name.PathBuilder;
 import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi2dav.ExceptionConverter;
 import org.apache.jackrabbit.util.Text;
 import org.apache.jackrabbit.webdav.DavException;
@@ -587,7 +588,18 @@
             for (int i = 0; i < mixinNodeTypeNames.length; i++) {
                 vs[i] = getQValueFactory(sessionInfo).create(mixinNodeTypeNames[i]);
             }
-            addProperty(nodeId, resolver.getQName(JcrConstants.JCR_MIXINTYPES), vs);
+            addProperty(nodeId, NameConstants.JCR_MIXINTYPES, vs);
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void setPrimaryType(NodeId nodeId, Name primaryNodeTypeName) throws RepositoryException {
+            assertMethod();
+
+            NamePathResolver resolver = getNamePathResolver(sessionInfo);
+            QValue qv = getQValueFactory(sessionInfo).create(primaryNodeTypeName);
+            setValue(getIdFactory().createPropertyId(nodeId, NameConstants.JCR_PRIMARYTYPE), qv);
         }
 
         /**

Modified: jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java?rev=779227&r1=779226&r2=779227&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java Wed May 27 16:18:08 2009
@@ -1438,6 +1438,16 @@
             });
         }
 
+        public void setPrimaryType(final NodeId nodeId, final Name primaryNodeTypeName) throws RepositoryException {
+            executeGuarded(new Callable() {
+                public Object run() throws RepositoryException {
+                    Node n = getNode(nodeId, sInfo);
+                    n.setPrimaryType(getJcrName(primaryNodeTypeName));
+                    return null;
+                }
+            });
+        }
+
         public void move(final NodeId srcNodeId,
                          final NodeId destParentNodeId,
                          final Name destName) throws RepositoryException {