jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mreut...@apache.org
Subject svn commit: r1396646 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/api/ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ oak-core/src/main/java/org/...
Date Wed, 10 Oct 2012 15:32:34 GMT
Author: mreutegg
Date: Wed Oct 10 15:32:34 2012
New Revision: 1396646

URL: http://svn.apache.org/viewvc?rev=1396646&view=rev
Log:
OAK-169: Support orderable nodes
- move orderable nodes implementation from oak-jcr to oak-core

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/OrderedChildrenEditor.java
  (with props)
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/TreeTest.java  
(with props)
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/PropertyState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeValidator.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionValidator.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeDelegate.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OrderableNodesTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/PropertyState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/PropertyState.java?rev=1396646&r1=1396645&r2=1396646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/PropertyState.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/PropertyState.java
Wed Oct 10 15:32:34 2012
@@ -34,18 +34,6 @@ import javax.annotation.Nonnull;
 public interface PropertyState {
 
     /**
-     * If a JCR node is orderable the OAK API will expose an "{@code oak:childOrder}"
-     * property state indicating the order of child nodes.
-     *
-     * NOTE: this is an temporary solution (OAK-232) until we reach consensus (see also OAK-182)
-     *
-     * // TODO: Use a proper namespace for this property?
-     * // TODO: Expose this a API method on the Tree interface (see http://markmail.org/message/kzt7csiz2bd5n3ww)
?
-     * // TODO: Define if/how this internal property is exposed on the JCR API
-     */
-    String OAK_CHILD_ORDER = "childOrder";
-
-    /**
      * @return the name of this property state
      */
     @Nonnull

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java?rev=1396646&r1=1396645&r2=1396646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java Wed
Oct 10 15:32:34 2012
@@ -28,6 +28,13 @@ import javax.annotation.Nonnull;
  * which point an outdated snapshot will start throwing
  * {@code IllegalStateException}s to indicate that the snapshot is no
  * longer available.
+ * <p/>
+ * The children of a <code>Tree</code> are generally unordered. That is, the
+ * sequence of the children returned by {@link #getChildren()} may change over
+ * time as this Tree is modified either directly or through some other session.
+ * Calling {@link #orderBefore(String)} will persist the current order and
+ * maintain the order as new children are added or removed. In this case a new
+ * child will be inserted after the last child as seen by {@link #getChildren()}.
  * <p>
  * A tree instance belongs to the client and its state is only modified
  * in response to method calls made by the client. The various accessors
@@ -217,6 +224,21 @@ public interface Tree {
     Tree addChild(String name);
 
     /**
+     * Orders this <code>Tree</code> before the sibling tree with the given
+     * <code>name</code>. Calling this method for the first time on this
+     * <code>Tree</code> or any of its siblings will persist the current order
+     * of siblings and maintain it from this point on.
+     *
+     * @param name the name of the sibling node where this tree is ordered
+     *             before. This tree will become the last sibling if
+     *             <code>name</code> is <code>null</code>.
+     * @return <code>false</code> if there is no sibling with the given
+     *         <code>name</code> and no reordering was performed;
+     *         <code>true</code> otherwise.
+     */
+    boolean orderBefore(String name);
+
+    /**
      * Set a property state
      * @param property  The property state to set
      */

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java?rev=1396646&r1=1396645&r2=1396646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java
Wed Oct 10 15:32:34 2012
@@ -164,6 +164,7 @@ public class ContentRepositoryImpl imple
     //--------------------------------------------------------------------------
     private static NodeStore createNodeStore(MicroKernel microKernel, CommitHook commitHook)
{
         KernelNodeStore nodeStore = new KernelNodeStore(microKernel);
+        commitHook = new CompositeHook(commitHook, new OrderedChildrenEditor());
         nodeStore.setHook(commitHook);
         return nodeStore;
     }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/OrderedChildrenEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/OrderedChildrenEditor.java?rev=1396646&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/OrderedChildrenEditor.java
(added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/OrderedChildrenEditor.java
Wed Oct 10 15:32:34 2012
@@ -0,0 +1,123 @@
+/*
+ * 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.oak.core;
+
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
+import org.apache.jackrabbit.oak.spi.commit.CommitHook;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+
+import com.google.common.collect.Sets;
+
+import static org.apache.jackrabbit.oak.core.TreeImpl.OAK_CHILD_ORDER;
+
+/**
+ * Maintains the {@link TreeImpl#OAK_CHILD_ORDER} property for nodes that have
+ * orderable children. The class TreeImpl maintains the property as well for
+ * transient operations. This class makes sure the child order property is kept
+ * up-to-date when operations are performed on the {@link Root}. This includes
+ * {@link Root#copy(String, String)} and {@link Root#move(String, String)}.
+ */
+public class OrderedChildrenEditor implements CommitHook {
+
+    @Nonnull
+    @Override
+    public NodeState processCommit(NodeState before, NodeState after)
+            throws CommitFailedException {
+        NodeBuilder builder = after.builder();
+
+        after.compareAgainstBaseState(before,
+                new OrderedChildrenDiff(builder));
+
+        return builder.getNodeState();
+    }
+
+    private static class OrderedChildrenDiff extends DefaultNodeStateDiff {
+
+        private final NodeBuilder builder;
+
+        OrderedChildrenDiff(NodeBuilder builder) {
+            this.builder = builder;
+        }
+
+        @Override
+        public void childNodeAdded(String name, NodeState after) {
+            if (!NodeStateUtils.isHidden(name)) {
+                updateChildOrder();
+                NodeBuilder childBuilder = builder.child(name);
+                OrderedChildrenDiff diff = new OrderedChildrenDiff(childBuilder);
+                for (ChildNodeEntry entry : after.getChildNodeEntries()) {
+                    diff.childNodeAdded(entry.getName(), entry.getNodeState());
+                }
+            }
+        }
+
+        @Override
+        public void childNodeDeleted(String name, NodeState before) {
+            updateChildOrder();
+        }
+
+        @Override
+        public void childNodeChanged(String name,
+                                     NodeState before,
+                                     NodeState after) {
+            if (!NodeStateUtils.isHidden(name)) {
+                NodeBuilder childBuilder = builder.child(name);
+                OrderedChildrenDiff diff = new OrderedChildrenDiff(childBuilder);
+                after.compareAgainstBaseState(before, diff);
+            }
+        }
+
+        private void updateChildOrder() {
+            PropertyState childOrder = builder.getProperty(OAK_CHILD_ORDER);
+            if (childOrder != null) {
+                Set<String> children = Sets.newLinkedHashSet();
+                for (int i = 0; i < childOrder.count(); i++) {
+                    String name = childOrder.getValue(Type.STRING, i);
+                    // ignore hidden
+                    if (NodeStateUtils.isHidden(name)) {
+                        continue;
+                    }
+                    if (builder.hasChildNode(name)) {
+                        children.add(name);
+                    }
+                }
+                // make sure we have all
+                for (String name : builder.getChildNodeNames()) {
+                    // ignore hidden
+                    if (NodeStateUtils.isHidden(name)) {
+                        continue;
+                    }
+                    // will only add it if not yet present in set
+                    children.add(name);
+                }
+                builder.setProperty(PropertyStates.stringProperty(OAK_CHILD_ORDER, children));
+            }
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/OrderedChildrenEditor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/OrderedChildrenEditor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java?rev=1396646&r1=1396645&r2=1396646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java
Wed Oct 10 15:32:34 2012
@@ -146,6 +146,13 @@ public class ReadOnlyTree implements Tre
         return state.getChildNodeCount();
     }
 
+    /**
+     * This implementation does not respect ordered child nodes, but always
+     * returns them in some implementation specific order.
+     *
+     * TODO: respect orderable children (needed?)
+     * @return the children.
+     */
     @Override
     public Iterable<Tree> getChildren() {
         return new Iterable<Tree>() {
@@ -185,6 +192,11 @@ public class ReadOnlyTree implements Tre
     }
 
     @Override
+    public boolean orderBefore(String name) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void setProperty(PropertyState property) {
         throw new UnsupportedOperationException();
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java?rev=1396646&r1=1396645&r2=1396646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
Wed Oct 10 15:32:34 2012
@@ -18,24 +18,31 @@
  */
 package org.apache.jackrabbit.oak.core;
 
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.Map;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.collect.Iterables;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.TreeLocation;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.core.RootImpl.PurgeListener;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+import org.apache.jackrabbit.oak.util.NodeUtil;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.Iterables;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -43,6 +50,9 @@ import static org.apache.jackrabbit.oak.
 
 public class TreeImpl implements Tree, PurgeListener {
 
+    /** Internal and hidden property that contains the child order */
+    static final String OAK_CHILD_ORDER = ":childOrder";
+
     /** Underlying {@code Root} of this {@code Tree} instance */
     private final RootImpl root;
 
@@ -147,8 +157,7 @@ public class TreeImpl implements Tree, P
 
     @Override
     public long getPropertyCount() {
-        // TODO: make sure cnt respects access control
-        return getNodeBuilder().getPropertyCount();
+        return Iterables.size(getProperties());
     }
 
     @Override
@@ -207,8 +216,14 @@ public class TreeImpl implements Tree, P
 
     @Override
     public Iterable<Tree> getChildren() {
+        Iterable<String> childNames;
+        if (hasOrderableChildren()) {
+            childNames = getOrderedChildNames();
+        } else {
+            childNames = getNodeBuilder().getChildNodeNames();
+        }
         return Iterables.filter(Iterables.transform(
-                getNodeBuilder().getChildNodeNames(),
+                childNames,
                 new Function<String, Tree>() {
                     @Override
                     public Tree apply(String input) {
@@ -232,6 +247,13 @@ public class TreeImpl implements Tree, P
     public Tree addChild(String name) {
         if (!hasChild(name)) {
             getNodeBuilder().child(name);
+            if (hasOrderableChildren()) {
+                getNodeBuilder().setProperty(PropertyStates.stringProperty(
+                        OAK_CHILD_ORDER,
+                        Iterables.concat(
+                                getOrderedChildNames(),
+                                Collections.singleton(name))));
+            }
             root.purge();
         }
 
@@ -251,6 +273,16 @@ public class TreeImpl implements Tree, P
             builder.removeNode(name);
             parent.children.remove(name);
             removed = true;
+            if (parent.hasOrderableChildren()) {
+                builder.setProperty(PropertyStates.stringProperty(
+                        OAK_CHILD_ORDER,
+                        Iterables.filter(parent.getOrderedChildNames(), new Predicate<String>()
{
+                            @Override
+                            public boolean apply(@Nullable String input) {
+                                return !name.equals(input);
+                            }
+                        })));
+            }
             root.purge();
             return true;
         } else {
@@ -259,6 +291,52 @@ public class TreeImpl implements Tree, P
     }
 
     @Override
+    public boolean orderBefore(final String name) {
+        if (isRoot()) {
+            // root does not have siblings
+            return false;
+        }
+        if (name != null && !parent.hasChild(name)) {
+            // so such sibling or not accessible
+            return false;
+        }
+        // perform the reorder
+        parent.ensureChildOrderProperty();
+        // all siblings but not this one
+        Iterable<String> filtered = Iterables.filter(
+                parent.getOrderedChildNames(),
+                new Predicate<String>() {
+                    @Override
+                    public boolean apply(@Nullable String input) {
+                        return !TreeImpl.this.getName().equals(input);
+                    }
+                });
+        // create head and tail
+        Iterable<String> head;
+        Iterable<String> tail;
+        if (name == null) {
+            head = filtered;
+            tail = Collections.emptyList();
+        } else {
+            int idx = Iterables.indexOf(filtered, new Predicate<String>() {
+                @Override
+                public boolean apply(@Nullable String input) {
+                    return name.equals(input);
+                }
+            });
+            head = Iterables.limit(filtered, idx);
+            tail = Iterables.skip(filtered, idx);
+        }
+        // concatenate head, this name and tail
+        parent.getNodeBuilder().setProperty(PropertyStates.stringProperty(
+                OAK_CHILD_ORDER,
+                Iterables.concat(head, Collections.singleton(getName()), tail))
+        );
+        root.purge();
+        return true;
+    }
+
+    @Override
     public void setProperty(PropertyState property) {
         NodeBuilder builder = getNodeBuilder();
         builder.setProperty(property);
@@ -450,12 +528,72 @@ public class TreeImpl implements Tree, P
     }
 
     private boolean canReadProperty(String name) {
+        if (NodeStateUtils.isHidden(name)) {
+            return false;
+        }
         String path = PathUtils.concat(getPath(), name);
 
         // FIXME: special handling for access control item and version content
         return root.getPermissions().canRead(path, true);
     }
 
+    /**
+     * @return <code>true</code> if this tree has orderable children;
+     *         <code>false</code> otherwise.
+     */
+    private boolean hasOrderableChildren() {
+        return internalGetProperty(OAK_CHILD_ORDER) != null;
+    }
+
+    /**
+     * Returns the ordered child names. This method must only be called when
+     * this tree {@link #hasOrderableChildren()}.
+     *
+     * @return the ordered child names.
+     */
+    private Iterable<String> getOrderedChildNames() {
+        assert hasOrderableChildren();
+        return new Iterable<String>() {
+            @Override
+            public Iterator<String> iterator() {
+                return new Iterator<String>() {
+                    PropertyState childOrder = internalGetProperty(OAK_CHILD_ORDER);
+                    int index = 0;
+
+                    @Override
+                    public boolean hasNext() {
+                        return index < childOrder.count();
+                    }
+
+                    @Override
+                    public String next() {
+                        return childOrder.getValue(Type.STRING, index++);
+                    }
+
+                    @Override
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                };
+            }
+        };
+    }
+
+    /**
+     * Ensures that the {@link #OAK_CHILD_ORDER} exists. This method will create
+     * the property if it doesn't exist and initialize the value with the names
+     * of the children as returned by {@link NodeBuilder#getChildNodeNames()}.
+     */
+    private void ensureChildOrderProperty() {
+        PropertyState childOrder = getNodeBuilder().getProperty(OAK_CHILD_ORDER);
+        if (childOrder == null) {
+            getNodeBuilder().setProperty(
+                    PropertyStates.stringProperty(
+                            OAK_CHILD_ORDER,
+                            getNodeBuilder().getChildNodeNames()));
+        }
+    }
+
     private static boolean isSame(NodeState state1, NodeState state2) {
         final boolean[] isDirty = {false};
         state2.compareAgainstBaseState(state1, new NodeStateDiff() {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeValidator.java?rev=1396646&r1=1396645&r2=1396646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeValidator.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeValidator.java
Wed Oct 10 15:32:34 2012
@@ -85,9 +85,6 @@ class TypeValidator implements Validator
 
     @Override
     public void propertyAdded(PropertyState after) throws CommitFailedException {
-        if (isInternal(after)) {
-            return;
-        }
         try {
             checkType(after);
             getParentType().checkSetProperty(after);
@@ -104,9 +101,6 @@ class TypeValidator implements Validator
 
     @Override
     public void propertyChanged(PropertyState before, PropertyState after) throws CommitFailedException
{
-        if (isInternal(after)) {
-            return;
-        }
         try {
             checkType(after);
             getParentType().checkSetProperty(after);
@@ -123,9 +117,6 @@ class TypeValidator implements Validator
 
     @Override
     public void propertyDeleted(PropertyState before) throws CommitFailedException {
-        if (isInternal(before)) {
-            return;
-        }
         try {
             getParentType().checkRemoveProperty(before);
         }
@@ -189,10 +180,6 @@ class TypeValidator implements Validator
 
     //------------------------------------------------------------< private >---
 
-    private static boolean isInternal(PropertyState state) {
-        return state.getName().equals(PropertyState.OAK_CHILD_ORDER);
-    }
-
     private void checkType(PropertyState after) throws RepositoryException {
         boolean primaryType = JCR_PRIMARYTYPE.equals(after.getName());
         boolean mixinType = JCR_MIXINTYPES.equals(after.getName());

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionValidator.java?rev=1396646&r1=1396645&r2=1396646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionValidator.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/PermissionValidator.java
Wed Oct 10 15:32:34 2012
@@ -104,8 +104,6 @@ class PermissionValidator implements Val
         if (JcrConstants.JCR_PRIMARYTYPE.equals(name) || JcrConstants.JCR_MIXINTYPES.equals(name))
{
             // TODO: distinguish between autocreated and user-supplied modification (?)
             permission = Permissions.NODE_TYPE_MANAGEMENT;
-        } else if (PropertyState.OAK_CHILD_ORDER.equals(property.getName())) {
-            permission = Permissions.MODIFY_CHILD_NODE_COLLECTION;
         } else if (isLockProperty(name)) {
             permission = Permissions.LOCK_MANAGEMENT;
         } else if (isNamespaceDefinition(parentPath)) {

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/TreeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/TreeTest.java?rev=1396646&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/TreeTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/TreeTest.java Wed
Oct 10 15:32:34 2012
@@ -0,0 +1,88 @@
+/*
+ * 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.oak;
+
+import java.util.Iterator;
+
+import org.apache.jackrabbit.oak.api.ContentRepository;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.core.TreeImpl;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Contains tests related to {@link Tree}
+ */
+public class TreeTest extends AbstractOakTest {
+
+    @Override
+    protected ContentRepository createRepository() {
+        return createEmptyRepository();
+    }
+    @Test
+    public void orderBefore() throws Exception {
+        ContentSession s = createAdminSession();
+        try {
+            Root r = s.getLatestRoot();
+            Tree t = r.getTree("/");
+            t.addChild("node1");
+            t.addChild("node2");
+            t.addChild("node3");
+            r.commit();
+            t = r.getTree("/");
+            t.getChild("node1").orderBefore("node2");
+            t.getChild("node3").orderBefore(null);
+            checkSequence(t.getChildren().iterator(), "node1", "node2", "node3");
+            r.commit();
+            // check again after commit
+            t = r.getTree("/");
+            checkSequence(t.getChildren().iterator(), "node1", "node2", "node3");
+
+            t.getChild("node3").orderBefore("node2");
+            checkSequence(t.getChildren().iterator(), "node1", "node3", "node2");
+            r.commit();
+            t = r.getTree("/");
+            checkSequence(t.getChildren().iterator(), "node1", "node3", "node2");
+
+            t.getChild("node1").orderBefore(null);
+            checkSequence(t.getChildren().iterator(), "node3", "node2", "node1");
+            r.commit();
+            t = r.getTree("/");
+            checkSequence(t.getChildren().iterator(), "node3", "node2", "node1");
+
+            // :childOrder property invisible?
+            assertEquals("must not have any properties", 0, t.getPropertyCount());
+        } finally {
+            s.close();
+        }
+    }
+
+    private void checkSequence(Iterator<Tree> trees, String... names) {
+        for (String name : names) {
+            assertTrue(trees.hasNext());
+            assertEquals("wrong sequence", name, trees.next().getName());
+        }
+        assertFalse("no more nodes expected", trees.hasNext());
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/TreeTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/TreeTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeDelegate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeDelegate.java?rev=1396646&r1=1396645&r2=1396646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeDelegate.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeDelegate.java
Wed Oct 10 15:32:34 2012
@@ -16,14 +16,9 @@
  */
 package org.apache.jackrabbit.oak.jcr;
 
-import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
@@ -31,17 +26,15 @@ import javax.jcr.InvalidItemStateExcepti
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.ValueFormatException;
 
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterators;
 import org.apache.jackrabbit.oak.api.CoreValue;
-import org.apache.jackrabbit.oak.api.CoreValueFactory;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.TreeLocation;
 import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
 
-import static org.apache.jackrabbit.oak.api.Type.STRINGS;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterators;
 
 /**
  * {@code NodeDelegate} serve as internal representations of {@code Node}s.
@@ -141,9 +134,8 @@ public class NodeDelegate extends ItemDe
 
     /**
      * Returns an iterator for traversing all the children of this node.
-     * If the node is orderable (there is an {@link PropertyState#OAK_CHILD_ORDER}
-     * property) then the iterator will return child nodes in the specified
-     * order. Otherwise the ordering of the iterator is undefined.
+     * If the node is orderable then the iterator will return child nodes in the
+     * specified order. Otherwise the ordering of the iterator is undefined.
      *
      * @return child nodes of the node
      */
@@ -164,43 +156,7 @@ public class NodeDelegate extends ItemDe
                 return Collections.<NodeDelegate>emptySet().iterator();
             }
         } else {
-            PropertyState order = tree.getProperty(PropertyState.OAK_CHILD_ORDER);
-            if (order == null || !order.isArray()) {
-                // No specified ordering
-                return nodeDelegateIterator(tree.getChildren().iterator());
-            } else {
-                // Collect child nodes in the specified order
-                final Map<String, NodeDelegate> ordered =
-                        new LinkedHashMap<String, NodeDelegate>();
-
-                for (String name : order.getValue(STRINGS)) {
-                    Tree child = tree.getChild(name);
-                    if (child != null && !name.startsWith(":")) {
-                        ordered.put(name, new NodeDelegate(sessionDelegate, child));
-                    }
-                }
-
-                if (ordered.size() == count) {
-                    // We have all the child nodes
-                    return ordered.values().iterator();
-                } else {
-                    // The specified ordering didn't cover all the children,
-                    // so return a combined iterator that first iterates
-                    // through the ordered subset and then all the remaining
-                    // children in an undefined order
-                    Iterator<Tree> remaining = Iterators.filter(
-                            tree.getChildren().iterator(),
-                            new Predicate<Tree>() {
-                                @Override
-                                public boolean apply(Tree tree) {
-                                    return !ordered.containsKey(tree.getName());
-                                }
-                            });
-                    return Iterators.concat(
-                            ordered.values().iterator(),
-                            nodeDelegateIterator(remaining));
-                }
-            }
+            return nodeDelegateIterator(tree.getChildren().iterator());
         }
     }
 
@@ -212,34 +168,7 @@ public class NodeDelegate extends ItemDe
         } else if (target != null && tree.getChild(target) == null) {
             throw new ItemNotFoundException("Not a child: " + target);
         } else {
-            List<CoreValue> order = new ArrayList<CoreValue>();
-            Set<String> added = new HashSet<String>();
-            CoreValueFactory factory =
-                    sessionDelegate.getContentSession().getCoreValueFactory();
-
-            PropertyState property = tree.getProperty(PropertyState.OAK_CHILD_ORDER);
-            if (property != null) {
-                for (String name : property.getValue(STRINGS)) {
-                    if (!name.equals(source) && !added.contains(property)
-                            && !name.startsWith(":")) {
-                        if (name.equals(target)) {
-                            order.add(factory.createValue(source));
-                            added.add(source);
-                        }
-                        order.add(factory.createValue(name));
-                        added.add(name);
-                    }
-                }
-            }
-
-            if (!added.contains(source)) {
-                order.add(factory.createValue(source));
-            }
-            if (target != null && !added.contains(target)) {
-                order.add(factory.createValue(source));
-            }
-
-            tree.setProperty(PropertyStates.createProperty(PropertyState.OAK_CHILD_ORDER,
order));
+            tree.getChild(source).orderBefore(target);
         }
     }
 

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OrderableNodesTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OrderableNodesTest.java?rev=1396646&r1=1396645&r2=1396646&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OrderableNodesTest.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OrderableNodesTest.java
Wed Oct 10 15:32:34 2012
@@ -40,6 +40,7 @@ public class OrderableNodesTest extends 
         NodeIterator iterator;
 
         root.orderBefore("a", "b");
+        root.orderBefore("c", null);
         iterator = root.getNodes();
         assertEquals("a", iterator.nextNode().getName());
         assertEquals("b", iterator.nextNode().getName());



Mime
View raw message