You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by md...@apache.org on 2012/04/26 12:03:32 UTC
svn commit: r1330741 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/api/
oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/
oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/
oak-jcr/src/main/java/org/apache/ja...
Author: mduerig
Date: Thu Apr 26 10:03:31 2012
New Revision: 1330741
URL: http://svn.apache.org/viewvc?rev=1330741&view=rev
Log:
OAK-18: Define Oak API
- alternative implementation which implements a fully persisted transient space (WIP)
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelTree2.java
Modified:
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/kernel/KernelNodeStateBuilder.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelRoot.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelRootFuzzIT.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelRootTest.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeDelegate.java
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=1330741&r1=1330740&r2=1330741&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 Thu Apr 26 10:03:31 2012
@@ -120,7 +120,7 @@ public interface Tree {
* the returned iterable.
* @return An {@code Iterable} for all property states
*/
- Iterable<PropertyState> getProperties();
+ Iterable<? extends PropertyState> getProperties();
/**
* Get a child of this {@code ContentTree} instance
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateBuilder.java?rev=1330741&r1=1330740&r2=1330741&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateBuilder.java Thu Apr 26 10:03:31 2012
@@ -42,8 +42,7 @@ public class KernelNodeStateBuilder impl
public static NodeStateBuilder create(MicroKernel kernel, CoreValueFactory valueFactory,
String path, String revision) {
- String[] r = new String[1];
- r[0] = revision;
+ String[] r = {revision};
return new KernelNodeStateBuilder(kernel, valueFactory, path, r);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelRoot.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelRoot.java?rev=1330741&r1=1330740&r2=1330741&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelRoot.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelRoot.java Thu Apr 26 10:03:31 2012
@@ -18,13 +18,11 @@
*/
package org.apache.jackrabbit.oak.kernel;
-import org.apache.jackrabbit.mk.util.PathUtils;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.CoreValue;
-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.kernel.KernelTree.Listener;
+import org.apache.jackrabbit.oak.kernel.KernelTree2.Listener;
import java.util.List;
@@ -48,7 +46,7 @@ public class KernelRoot implements Root
private NodeState base;
/** Root state of this tree */
- private KernelTree root;
+ private KernelTree2 root;
/** Listener for changes on the content tree */
private TreeListener treeListener = new TreeListener();
@@ -59,18 +57,18 @@ public class KernelRoot implements Root
this.store = store;
this.workspaceName = workspaceName;
this.base = store.getRoot().getChildNode(workspaceName);
- this.root = new KernelTree(base, treeListener);
nodeStateBuilder = store.getBuilder(base);
+ this.root = new KernelTree2(store, nodeStateBuilder, treeListener);
}
@Override
public boolean move(String sourcePath, String destPath) {
- KernelTree source = getTransientState(sourcePath);
+ KernelTree2 source = getTransientState(sourcePath);
if (source == null) {
return false;
}
- KernelTree destParent = getTransientState(getParentPath(destPath));
+ KernelTree2 destParent = getTransientState(getParentPath(destPath));
String destName = getName(destPath);
return destParent != null && source.move(destParent, destName);
@@ -78,12 +76,12 @@ public class KernelRoot implements Root
@Override
public boolean copy(String sourcePath, String destPath) {
- KernelTree sourceNode = getTransientState(sourcePath);
+ KernelTree2 sourceNode = getTransientState(sourcePath);
if (sourceNode == null) {
return false;
}
- KernelTree destParent = getTransientState(getParentPath(destPath));
+ KernelTree2 destParent = getTransientState(getParentPath(destPath));
String destName = getName(destPath);
return destParent != null && sourceNode.copy(destParent, destName);
@@ -105,7 +103,7 @@ public class KernelRoot implements Root
base = store.getRoot().getChildNode(workspaceName);
nodeStateBuilder = store.getBuilder(base);
treeListener = new TreeListener();
- root = new KernelTree(base, treeListener);
+ root = new KernelTree2(store, nodeStateBuilder, treeListener);
}
@Override
@@ -122,8 +120,8 @@ public class KernelRoot implements Root
* @return a {@link KernelTree} instance for the item
* at {@code path} or {@code null} if no such item exits.
*/
- private KernelTree getTransientState(String path) {
- KernelTree state = root;
+ private KernelTree2 getTransientState(String path) {
+ KernelTree2 state = root;
for (String name : elements(path)) {
state = state.getChild(name);
if (state == null) {
@@ -133,59 +131,42 @@ public class KernelRoot implements Root
return state;
}
+ // TODO accumulate change log for refresh/rebase
private class TreeListener implements Listener {
private boolean isDirty;
-
+
@Override
- public void addChild(KernelTree tree, String name) {
- NodeStateBuilder target = getBuilder(tree);
- target.addNode(name);
+ public void addChild(KernelTree2 tree, String name) {
isDirty = true;
}
@Override
- public void removeChild(KernelTree tree, String name) {
- NodeStateBuilder target = getBuilder(tree);
- target.removeNode(name);
+ public void removeChild(KernelTree2 tree, String name) {
isDirty = true;
}
@Override
- public void setProperty(KernelTree tree, String name, CoreValue value) {
- NodeStateBuilder target = getBuilder(tree);
- PropertyState propertyState = new KernelPropertyState(name, value);
- target.setProperty(propertyState);
+ public void setProperty(KernelTree2 tree, String name, CoreValue value) {
isDirty = true;
}
@Override
- public void setProperty(KernelTree tree, String name, List<CoreValue> values) {
- NodeStateBuilder target = getBuilder(tree);
- PropertyState propertyState = new KernelPropertyState(name, values);
- target.setProperty(propertyState);
+ public void setProperty(KernelTree2 tree, String name, List<CoreValue> values) {
isDirty = true;
}
@Override
- public void removeProperty(KernelTree tree, String name) {
- NodeStateBuilder target = getBuilder(tree);
- target.removeProperty(name);
+ public void removeProperty(KernelTree2 tree, String name) {
isDirty = true;
}
@Override
- public void move(KernelTree tree, String name, KernelTree moved) {
- NodeStateBuilder source = getBuilder(tree).getChildBuilder(name);
- NodeStateBuilder destParent = getBuilder(moved.getParent());
- source.moveTo(destParent, moved.getName());
+ public void move(KernelTree2 tree, String name, KernelTree2 moved) {
isDirty = true;
}
@Override
- public void copy(KernelTree tree, String name, KernelTree copied) {
- NodeStateBuilder source = getBuilder(tree).getChildBuilder(name);
- NodeStateBuilder destParent = getBuilder(copied.getParent());
- source.copyTo(destParent, copied.getName());
+ public void copy(KernelTree2 tree, String name, KernelTree2 copied) {
isDirty = true;
}
@@ -194,13 +175,4 @@ public class KernelRoot implements Root
}
}
- private NodeStateBuilder getBuilder(Tree tree) {
- String path = tree.getPath();
- NodeStateBuilder builder = nodeStateBuilder;
- for (String name : PathUtils.elements(path)) {
- builder = builder.getChildBuilder(name);
- }
-
- return builder;
- }
}
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelTree2.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelTree2.java?rev=1330741&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelTree2.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelTree2.java Thu Apr 26 10:03:31 2012
@@ -0,0 +1,422 @@
+/*
+ * 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.kernel;
+
+import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.util.Function1;
+import org.apache.jackrabbit.oak.util.Iterators;
+import org.apache.jackrabbit.oak.util.PagedIterator;
+
+import java.util.Iterator;
+import java.util.List;
+
+import static org.apache.jackrabbit.oak.util.Iterators.flatten;
+
+public class KernelTree2 implements Tree {
+
+ private final NodeStore store;
+
+ /**
+ * Underlying persistent state or {@code null} if this instance represents an
+ * added content tree
+ */
+ private final NodeState baseState;
+
+ private final NodeStateBuilder builder;
+
+ /** Listener for changes on this content tree */
+ private final Listener listener;
+
+ /** Name of this content tree */
+ private String name;
+
+ /** Parent of this content tree */
+ private KernelTree2 parent;
+
+ private KernelTree2(NodeStore store, NodeState baseState, NodeStateBuilder builder,
+ KernelTree2 parent, String name, Listener listener) {
+
+ this.store = store;
+ this.builder = builder;
+ this.baseState = baseState;
+ this.listener = listener;
+ this.name = name;
+ this.parent = parent;
+ }
+
+ KernelTree2(NodeStore store, NodeStateBuilder nodeStateBuilder, Listener listener) {
+ this(store, nodeStateBuilder.getNodeState(), nodeStateBuilder, null, "", listener);
+ }
+
+ /**
+ * Listener for changes on {@code ContentTree}s
+ */
+ interface Listener {
+
+ /**
+ * The child of the given {@code name} has been added to {@code tree}.
+ * @param tree parent to which a child was added
+ * @param name name of the added child
+ */
+ void addChild(KernelTree2 tree, String name);
+
+ /**
+ * The child of the given {@code name} has been removed from {@code tree}
+ * @param tree parent from which a child was removed
+ * @param name name of the removed child
+ */
+ void removeChild(KernelTree2 tree, String name);
+
+ /**
+ * The property of the given {@code name} and {@code value} has been set.
+ * @param tree parent on which the property was set.
+ * @param name name of the property
+ * @param value value of the property
+ */
+ void setProperty(KernelTree2 tree, String name, CoreValue value);
+
+ /**
+ * The property of the given {@code name} and {@code values} has been set.
+ * @param tree parent on which the property was set.
+ * @param name name of the property
+ * @param values values of the property
+ */
+ void setProperty(KernelTree2 tree, String name, List<CoreValue> values);
+
+ /**
+ * The property of the given {@code name} has been removed.
+ * @param tree parent on which the property was removed.
+ * @param name name of the property
+ */
+ void removeProperty(KernelTree2 tree, String name);
+
+ /**
+ * The child with the given {@code name} has been moved.
+ * @param tree parent from which the child was moved
+ * @param name name of the moved child
+ * @param moved moved child
+ */
+ void move(KernelTree2 tree, String name, KernelTree2 moved);
+
+ /**
+ * The child with the given {@code name} been copied.
+ * @param tree parent from which the child way copied
+ * @param name name of the copied child
+ * @param copied copied child
+ */
+ void copy(KernelTree2 tree, String name, KernelTree2 copied);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getPath() {
+ if (parent == null) {
+ return name;
+ }
+ else {
+ String path = parent.getPath();
+ return path.isEmpty()
+ ? name
+ : path + '/' + name;
+ }
+ }
+
+ @Override
+ public Tree getParent() {
+ return parent;
+ }
+
+ @Override
+ public PropertyState getProperty(String name) {
+ return getNodeState().getProperty(name);
+ }
+
+ @Override
+ public Status getPropertyStatus(String name) {
+ if (baseState == null) {
+ if (hasProperty(name)) {
+ return Status.NEW;
+ }
+ else {
+ return null;
+ }
+ }
+ else {
+ if (hasProperty(name)) {
+ if (baseState.getProperty(name) == null) {
+ return Status.NEW;
+ }
+ else {
+ PropertyState base = baseState.getProperty(name);
+ PropertyState head = getProperty(name);
+ if (base.equals(head)) {
+ return Status.EXISTING;
+ }
+ else {
+ return Status.MODIFIED;
+ }
+ }
+ }
+ else {
+ if (baseState.getProperty(name) == null) {
+ return null;
+ }
+ else {
+ return Status.REMOVED;
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean hasProperty(String name) {
+ return getNodeState().getProperty(name) != null;
+ }
+
+ @Override
+ public long getPropertyCount() {
+ return getNodeState().getPropertyCount();
+ }
+
+ @Override
+ public Iterable<? extends PropertyState> getProperties() {
+ return getNodeState().getProperties();
+ }
+
+ @Override
+ public KernelTree2 getChild(String name) {
+ NodeStateBuilder childBuilder = builder.getChildBuilder(name);
+ NodeState childBaseState = baseState == null
+ ? null
+ : baseState.getChildNode(name);
+
+ return childBuilder == null
+ ? null
+ : new KernelTree2(store, childBaseState, childBuilder, this, name, listener);
+ }
+
+ @Override
+ public Status getChildStatus(String name) {
+ if (baseState == null) {
+ if (hasChild(name)) {
+ return Status.NEW;
+ }
+ else {
+ return null;
+ }
+ }
+ else {
+ if (hasChild(name)) {
+ if (baseState.getChildNode(name) == null) {
+ return Status.NEW;
+ }
+ else {
+ if (equals(baseState, getNodeState())) {
+ return Status.EXISTING;
+ }
+ else {
+ return Status.MODIFIED;
+ }
+ }
+ }
+ else {
+ if (baseState.getChildNode(name) == null) {
+ return null;
+ }
+ else {
+ return Status.REMOVED;
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean hasChild(String name) {
+ return getNodeState().getChildNode(name) != null;
+ }
+
+ @Override
+ public long getChildrenCount() {
+ return getNodeState().getChildNodeCount();
+ }
+
+ @Override
+ public Iterable<Tree> getChildren() {
+ return new Iterable<Tree>() {
+ @Override
+ public Iterator<Tree> iterator() {
+
+ Iterator<? extends ChildNodeEntry> childEntries = flatten(
+ new PagedIterator<ChildNodeEntry>(1024) {
+ @Override
+ protected Iterator<? extends ChildNodeEntry> getPage(long pos, int size) {
+ return getNodeState().getChildNodeEntries(pos, size).iterator();
+ }
+ });
+
+ return Iterators.map(childEntries, new Function1<ChildNodeEntry, Tree>() {
+ @Override
+ public Tree apply(ChildNodeEntry entry) {
+ NodeStateBuilder childBuilder = builder.getChildBuilder(entry.getName());
+ return new KernelTree2(store, childBuilder.getNodeState(), childBuilder, KernelTree2.this, entry.getName(), listener);
+ }
+ });
+ }
+ };
+ }
+
+ @Override
+ public Tree addChild(String name) {
+ NodeStateBuilder childBuilder = builder.addNode(name);
+ KernelTree2 added = new KernelTree2(store, null, childBuilder, this, name, listener);
+ if (added != null) {
+ listener.addChild(this, name);
+ }
+ return added;
+ }
+
+ @Override
+ public boolean removeChild(String name) {
+ boolean result = builder.removeNode(name);
+ if (result) {
+ listener.removeChild(this, name);
+ }
+ return result;
+ }
+
+ @Override
+ public void setProperty(String name, CoreValue value) {
+ PropertyState propertyState = new KernelPropertyState(name, value);
+ builder.setProperty(propertyState);
+ if (listener != null) {
+ listener.setProperty(this, name, value);
+ }
+ }
+
+ @Override
+ public void setProperty(String name, List<CoreValue> values) {
+ PropertyState propertyState = new KernelPropertyState(name, values);
+ builder.setProperty(propertyState);
+ if (listener != null) {
+ listener.setProperty(this, name, values);
+ }
+ }
+
+ @Override
+ public void removeProperty(String name) {
+ builder.removeProperty(name);
+ if (listener != null) {
+ listener.removeProperty(this, name);
+ }
+ }
+
+ /**
+ * Move this tree to the parent at {@code destParent} with the new name
+ * {@code destName}.
+ *
+ * @param destParent new parent for this tree
+ * @param destName new name for this tree
+ * @return {@code true} if successful, {@code false otherwise}. I.e.
+ * when {@code destName} already exists at {@code destParent}
+ */
+ public boolean move(KernelTree2 destParent, String destName) {
+ boolean result = builder.moveTo(destParent.builder, destName);
+ if (result) {
+ KernelTree2 oldParent = parent;
+ String oldName = name;
+
+ name = destName;
+ parent = destParent;
+
+ if (listener != null) {
+ listener.move(oldParent, oldName, this);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Copy this tree to the parent at {@code destParent} with the name {@code destName}.
+ *
+ * @param destParent parent for the copied tree
+ * @param destName name for the copied tree
+ * @return {@code true} if successful, {@code false otherwise}. I.e.
+ * when {@code destName} already exists at {@code destParent}
+ */
+ public boolean copy(KernelTree2 destParent, String destName) {
+ boolean result = builder.copyTo(destParent.builder, destName);
+ if (result) {
+ if (listener != null) {
+ // FIXME call listener listener.copy(parent, name, copy);
+ }
+ return true;
+ }
+ return result;
+ }
+
+ //------------------------------------------------------------< private >---
+
+ private NodeState getNodeState() {
+ return builder.getNodeState();
+ }
+
+ private boolean equals(NodeState state1, NodeState state2) {
+ final boolean[] isDirty = {false};
+ store.compare(state1, state2, new NodeStateDiff() {
+ @Override
+ public void propertyAdded(PropertyState after) {
+ isDirty[0] = true;
+ }
+
+ @Override
+ public void propertyChanged(PropertyState before, PropertyState after) {
+ isDirty[0] = true;
+ }
+
+ @Override
+ public void propertyDeleted(PropertyState before) {
+ isDirty[0] = true;
+ }
+
+ @Override
+ public void childNodeAdded(String name, NodeState after) {
+ isDirty[0] = true;
+ }
+
+ @Override
+ public void childNodeChanged(String name, NodeState before, NodeState after) {
+ isDirty[0] = true; // FIXME cut transitivity here
+ }
+
+ @Override
+ public void childNodeDeleted(String name, NodeState before) {
+ isDirty[0] = true;
+ }
+ });
+
+ return !isDirty[0];
+ }
+
+}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelRootFuzzIT.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelRootFuzzIT.java?rev=1330741&r1=1330740&r2=1330741&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelRootFuzzIT.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelRootFuzzIT.java Thu Apr 26 10:03:31 2012
@@ -75,13 +75,13 @@ public class KernelRootFuzzIT {
public void setup() {
counter = 0;
- MicroKernel mk1 = new MicroKernelImpl("./target/mk1");
+ MicroKernel mk1 = new MicroKernelImpl("./target/mk1/" + random.nextInt());
vf = new CoreValueFactoryImpl(mk1);
store1 = new KernelNodeStore(mk1, vf);
mk1.commit("", "+\"/test\":{} +\"/test/root\":{}", mk1.getHeadRevision(), "");
root1 = new KernelRoot(store1, "test");
- MicroKernel mk2 = new MicroKernelImpl("./target/mk2");
+ MicroKernel mk2 = new MicroKernelImpl("./target/mk2/" + random.nextInt());
store2 = new KernelNodeStore(mk2, vf);
mk2.commit("", "+\"/test\":{} +\"/test/root\":{}", mk2.getHeadRevision(), "");
root2 = new KernelRoot(store2, "test");
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelRootTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelRootTest.java?rev=1330741&r1=1330740&r2=1330741&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelRootTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelRootTest.java Thu Apr 26 10:03:31 2012
@@ -22,6 +22,7 @@ import org.apache.jackrabbit.oak.api.Com
import org.apache.jackrabbit.oak.api.CoreValue;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Tree.Status;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@@ -114,7 +115,7 @@ public class KernelRootTest extends Abst
expectedProperties.put("b", valueFactory.createValue(2));
expectedProperties.put("c", valueFactory.createValue(3));
- Iterable<PropertyState> properties = tree.getProperties();
+ Iterable<? extends PropertyState> properties = tree.getProperties();
for (PropertyState property : properties) {
CoreValue value = expectedProperties.remove(property.getName());
assertNotNull(value);
@@ -334,6 +335,78 @@ public class KernelRootTest extends Abst
}
@Test
+ public void addAndRemoveProperty() throws CommitFailedException {
+ KernelRoot root = new KernelRoot(store, "test");
+ Tree tree = root.getTree("/");
+
+ tree.setProperty("P0", valueFactory.createValue("V1"));
+ root.commit();
+ tree = root.getTree("/");
+ assertTrue(tree.hasProperty("P0"));
+
+ tree.removeProperty("P0");
+ root.commit();
+ tree = root.getTree("/");
+ assertFalse(tree.hasProperty("P0"));
+ }
+
+ @Test
+ public void nodeStatus() throws CommitFailedException {
+ KernelRoot root = new KernelRoot(store, "test");
+ Tree tree = root.getTree("/");
+
+ tree.addChild("new");
+ assertEquals(Status.NEW, tree.getChildStatus("new"));
+ root.commit();
+
+ tree = root.getTree("/");
+ assertEquals(Status.EXISTING, tree.getChildStatus("new"));
+ Tree added = tree.getChild("new");
+ added.addChild("another");
+ assertEquals(Status.MODIFIED, tree.getChildStatus("new"));
+ root.commit();
+
+ tree = root.getTree("/");
+ assertEquals(Status.EXISTING, tree.getChildStatus("new"));
+ tree.getChild("new").removeChild("another");
+ assertEquals(Status.MODIFIED, tree.getChildStatus("new"));
+ assertEquals(Status.REMOVED, tree.getChild("new").getChildStatus("another"));
+ root.commit();
+
+ tree = root.getTree("/");
+ assertEquals(Status.EXISTING, tree.getChildStatus("new"));
+ assertNull(tree.getChild("new").getChild("another"));
+ assertNull(tree.getChild("new").getChildStatus("another"));
+ }
+
+ @Test
+ public void propertyStatus() throws CommitFailedException {
+ KernelRoot root = new KernelRoot(store, "test");
+ Tree tree = root.getTree("/");
+ CoreValue value1 = valueFactory.createValue("V1");
+ CoreValue value2 = valueFactory.createValue("V2");
+
+ tree.setProperty("new", value1);
+ assertEquals(Status.NEW, tree.getPropertyStatus("new"));
+ root.commit();
+
+ tree = root.getTree("/");
+ assertEquals(Status.EXISTING, tree.getPropertyStatus("new"));
+ tree.setProperty("new", value2);
+ assertEquals(Status.MODIFIED, tree.getPropertyStatus("new"));
+ root.commit();
+
+ tree = root.getTree("/");
+ assertEquals(Status.EXISTING, tree.getPropertyStatus("new"));
+ tree.removeProperty("new");
+ assertEquals(Status.REMOVED, tree.getPropertyStatus("new"));
+ root.commit();
+
+ tree = root.getTree("/");
+ assertNull(tree.getPropertyStatus("new"));
+ }
+
+ @Test
@Ignore("WIP") // FIXME: causes OOME since the branch/merge feature from OAK-45 is used
public void largeChildList() throws CommitFailedException {
KernelRoot root = new KernelRoot(store, "test");
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=1330741&r1=1330740&r2=1330741&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 Thu Apr 26 10:03:31 2012
@@ -16,14 +16,6 @@
*/
package org.apache.jackrabbit.oak.jcr;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.RepositoryException;
-
import org.apache.jackrabbit.oak.api.CoreValue;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
@@ -33,6 +25,12 @@ import org.apache.jackrabbit.oak.namepat
import org.apache.jackrabbit.oak.util.Function1;
import org.apache.jackrabbit.oak.util.Iterators;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import java.util.Iterator;
+import java.util.List;
+
public class NodeDelegate {
private final SessionContext<SessionImpl> sessionContext;
@@ -178,7 +176,7 @@ public class NodeDelegate {
}
private Iterator<PropertyDelegate> propertyDelegateIterator(
- Iterator<PropertyState> properties) {
+ Iterator<? extends PropertyState> properties) {
return Iterators.map(properties,
new Function1<PropertyState, PropertyDelegate>() {
@Override