### Eclipse Workspace Patch 1.0
#P oak-core
Index: src/test/java/org/apache/jackrabbit/oak/core/ImmutableTreeTest.java
===================================================================
--- src/test/java/org/apache/jackrabbit/oak/core/ImmutableTreeTest.java (revision 1500615)
+++ src/test/java/org/apache/jackrabbit/oak/core/ImmutableTreeTest.java (working copy)
@@ -18,11 +18,11 @@
*/
package org.apache.jackrabbit.oak.core;
+import static org.apache.jackrabbit.oak.OakAssert.assertSequence;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-
import org.apache.jackrabbit.oak.OakBaseTest;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.ContentSession;
@@ -32,6 +32,7 @@
import org.junit.Before;
import org.junit.Test;
+
public class ImmutableTreeTest extends OakBaseTest {
private Root root;
@@ -118,4 +119,34 @@
// success
}
}
+
+ @Test
+ public void orderBefore() throws Exception {
+ TreeImpl t = (TreeImpl) root.getTree("/x/y/z");
+
+ t.addChild("node1");
+ t.addChild("node2");
+ t.addChild("node3");
+
+
+ t.getChild("node1").orderBefore("node2");
+ t.getChild("node3").orderBefore(null);
+
+ root.commit();
+
+ ImmutableTree tree = new ImmutableTree(t.getNodeState());
+ assertSequence(tree.getChildren(), "node1", "node2", "node3");
+
+ t.getChild("node3").orderBefore("node2");
+ root.commit();
+
+ tree = new ImmutableTree(t.getNodeState());
+ assertSequence(tree.getChildren(), "node1", "node3", "node2");
+
+ t.getChild("node1").orderBefore(null);
+ root.commit();
+
+ tree = new ImmutableTree(t.getNodeState());
+ assertSequence(tree.getChildren(), "node3", "node2", "node1");
+ }
}
Index: src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java
===================================================================
--- src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java (revision 1497267)
+++ src/main/java/org/apache/jackrabbit/oak/core/ReadOnlyTree.java (working copy)
@@ -21,6 +21,8 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.transform;
import static org.apache.jackrabbit.oak.api.Type.STRING;
import java.util.Iterator;
@@ -33,10 +35,18 @@
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
public class ReadOnlyTree implements Tree {
+
+ /**
+ * Internal and hidden property that contains the child order
+ */
+ public static final String OAK_CHILD_ORDER = ":childOrder";
/**
* Parent of this tree, {@code null} for the root
@@ -159,38 +169,25 @@
* 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 getChildren() {
- return new Iterable() {
- @Override
- public Iterator iterator() {
- final Iterator extends ChildNodeEntry> iterator =
- state.getChildNodeEntries().iterator();
- return new Iterator() {
- @Override
- public boolean hasNext() {
- return iterator.hasNext();
- }
-
- @Override
- public Tree next() {
- ChildNodeEntry entry = iterator.next();
- return new ReadOnlyTree(
- ReadOnlyTree.this,
- entry.getName(), entry.getNodeState());
- }
-
+ Iterable childNames;
+ if (hasOrderableChildren()) {
+ childNames = getOrderedChildNames();
+ } else {
+ childNames = state.getChildNodeNames();
+ }
+ return transform(
+ filter(childNames, new Predicate() {
@Override
- public void remove() {
- throw new UnsupportedOperationException();
+ public boolean apply(@Nullable String name) {
+ return !isHidden(name);
}
- };
- }
- };
+ }),
+ getChildrenFunction());
}
@Override
@@ -251,4 +248,63 @@
return PathUtils.concat(parent.getIdentifier(), name);
}
}
+
+ /**
+ * @return {@code true} if this tree has orderable children;
+ * {@code false} otherwise.
+ */
+ private boolean hasOrderableChildren() {
+ return state.hasProperty(OAK_CHILD_ORDER);
+ }
+
+ /**
+ * Returns the ordered child names. This method must only be called when
+ * this tree {@link #hasOrderableChildren()}.
+ *
+ * @return the ordered child names.
+ */
+ private Iterable getOrderedChildNames() {
+ assert hasOrderableChildren();
+ return new Iterable() {
+ @Override
+ public Iterator iterator() {
+ return new Iterator() {
+ final PropertyState childOrder = state.getProperty(OAK_CHILD_ORDER);
+ int index = 0;
+
+ @Override
+ public boolean hasNext() {
+ return index < childOrder.count();
+ }
+
+ @Override
+ public String next() {
+ return childOrder.getValue(STRING, index++);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ };
+ }
+
+ private static boolean isHidden(String name) {
+ return NodeStateUtils.isHidden(name);
+ }
+
+ protected Function getChildrenFunction(){
+ return new ChildrenFunction();
+ }
+
+ //--------------------------------------------------------------------------
+
+ private class ChildrenFunction implements Function {
+ @Override
+ public Tree apply(String input) {
+ return new ReadOnlyTree(ReadOnlyTree.this, input,state.getChildNode(input));
+ }
+ }
}
Index: src/main/java/org/apache/jackrabbit/oak/core/ImmutableTree.java
===================================================================
--- src/main/java/org/apache/jackrabbit/oak/core/ImmutableTree.java (revision 1500636)
+++ src/main/java/org/apache/jackrabbit/oak/core/ImmutableTree.java (working copy)
@@ -18,19 +18,15 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static org.apache.jackrabbit.oak.api.Type.STRING;
-
-import java.util.Iterator;
-
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
-
+import com.google.common.base.Function;
import com.google.common.base.Objects;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.NodeState;
/**
@@ -176,37 +172,12 @@
* 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 getChildren() {
- return new Iterable() {
- @Override
- public Iterator iterator() {
- final Iterator extends ChildNodeEntry> iterator = state.getChildNodeEntries().iterator();
- return new Iterator() {
- @Override
- public boolean hasNext() {
- return iterator.hasNext();
- }
-
- @Override
- public Tree next() {
- ChildNodeEntry entry = iterator.next();
- return new ImmutableTree(
- ImmutableTree.this,
- entry.getName(), entry.getNodeState());
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
- }
- };
+ return super.getChildren();
}
//-------------------------------------------------------------< Object >---
@@ -263,6 +234,11 @@
return PathUtils.concat(getParent().getIdentifier(), getName());
}
}
+
+ @Override
+ protected Function getChildrenFunction(){
+ return new ChildrenFunction();
+ }
//--------------------------------------------------------------------------
public interface ParentProvider {
@@ -298,4 +274,13 @@
return parent;
}
}
+
+ private class ChildrenFunction implements Function {
+
+ @Override
+ public Tree apply(String input) {
+ return new ImmutableTree(ImmutableTree.this, input,state.getChildNode(input));
+ }
+
+ }
}