Author: mduerig
Date: Thu Apr 26 16:18:40 2012
New Revision: 1330923
URL: http://svn.apache.org/viewvc?rev=1330923&view=rev
Log:
OAK-18: Define Oak API
- implement rebase
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/RepositoryTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java?rev=1330923&r1=1330922&r2=1330923&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
Thu Apr 26 16:18:40 2012
@@ -18,6 +18,8 @@
*/
package org.apache.jackrabbit.oak.core;
+import org.apache.jackrabbit.mk.api.MicroKernelException;
+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.Root;
@@ -26,9 +28,13 @@ import org.apache.jackrabbit.oak.core.Tr
import org.apache.jackrabbit.oak.kernel.NodeState;
import org.apache.jackrabbit.oak.kernel.NodeStateBuilder;
import org.apache.jackrabbit.oak.kernel.NodeStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
import java.util.List;
+import static java.util.Collections.singletonList;
import static org.apache.jackrabbit.mk.util.PathUtils.elements;
import static org.apache.jackrabbit.mk.util.PathUtils.getName;
import static org.apache.jackrabbit.mk.util.PathUtils.getParentPath;
@@ -39,6 +45,7 @@ import static org.apache.jackrabbit.mk.u
* to the {@link NodeStateBuilder} for the relevant sub-tree.
*/
public class RootImpl implements Root {
+ static final Logger log = LoggerFactory.getLogger(RootImpl.class);
/** The underlying store to which this root belongs */
private final NodeStore store;
@@ -104,16 +111,13 @@ public class RootImpl implements Root {
@Override
public void rebase() {
- // TODO implement rebase base =
store.getRoot().getChildNode(workspaceName);
+ rebase(true);
}
@Override
public void commit() throws CommitFailedException {
store.apply(nodeStateBuilder);
- treeListener = new TreeListener();
- base = store.getRoot().getChildNode(workspaceName);
- nodeStateBuilder = store.getBuilder(base);
- root = new TreeImpl(store, nodeStateBuilder, treeListener);
+ rebase(false);
}
@Override
@@ -140,47 +144,187 @@ public class RootImpl implements Root {
return state;
}
- // TODO accumulate change log for refresh/rebase
- private class TreeListener implements Listener {
- private boolean isDirty;
+ private void rebase(boolean applyChanges) {
+ TreeListener changes = treeListener;
+
+ treeListener = new TreeListener();
+ base = store.getRoot().getChildNode(workspaceName);
+ nodeStateBuilder = store.getBuilder(base);
+ root = new TreeImpl(store, nodeStateBuilder, treeListener);
+
+ if (applyChanges) {
+ apply(changes);
+ }
+ }
+
+ private void apply(TreeListener changes) {
+ for (Operation operation : changes.getChanges()) {
+ try {
+ switch (operation.type) {
+ case ADD_NODE: {
+ String parentPath =
PathUtils.getParentPath(operation.targetPath);
+ String name = PathUtils.getName(operation.targetPath);
+ getChild(parentPath).addChild(name);
+ break;
+ }
+ case REMOVE_NODE: {
+ String parentPath =
PathUtils.getParentPath(operation.targetPath);
+ String name = PathUtils.getName(operation.targetPath);
+ getChild(parentPath).removeChild(name);
+ break;
+ }
+ case SET_PROPERTY: {
+ String parentPath =
PathUtils.getParentPath(operation.targetPath);
+ String name = PathUtils.getName(operation.targetPath);
+ if (operation.isMultiple) {
+ getChild(parentPath).setProperty(name,
operation.values.get(0));
+ }
+ else {
+ getChild(parentPath).setProperty(name,
operation.values);
+ }
+ break;
+ }
+ case REMOVE_PROPERTY: {
+ String parentPath =
PathUtils.getParentPath(operation.targetPath);
+ String name = PathUtils.getName(operation.targetPath);
+ getChild(parentPath).removeProperty(name);
+ break;
+ }
+ case MOVE: {
+ move(operation.sourcePath, operation.targetPath);
+ break;
+ }
+ case COPY: {
+ copy(operation.sourcePath, operation.targetPath);
+ break;
+ }
+ }
+ }
+ catch (MicroKernelException e) {
+ log.warn("Skipping failed operation on refresh:" + operation);
+ }
+ }
+ }
+
+
+ private static class TreeListener implements Listener {
+ private final List<Operation> operations = new ArrayList<Operation>();
@Override
- public void addChild(TreeImpl tree, String name) {
- isDirty = true;
+ public void addChild(TreeImpl parent, String name) {
+ String targetPath = PathUtils.concat(parent.getPath(), name);
+ operations.add(Operation.addNode(targetPath));
}
@Override
- public void removeChild(TreeImpl tree, String name) {
- isDirty = true;
+ public void removeChild(TreeImpl parent, String name) {
+ String targetPath = PathUtils.concat(parent.getPath(), name);
+ operations.add(Operation.removeNode(targetPath));
}
@Override
- public void setProperty(TreeImpl tree, String name, CoreValue value) {
- isDirty = true;
+ public void setProperty(TreeImpl parent, String name, CoreValue value)
{
+ String targetPath = PathUtils.concat(parent.getPath(), name);
+ operations.add(Operation.setProperty(targetPath, value));
}
@Override
- public void setProperty(TreeImpl tree, String name, List<CoreValue>
values) {
- isDirty = true;
+ public void setProperty(TreeImpl parent, String name, List<CoreValue>
values) {
+ String targetPath = PathUtils.concat(parent.getPath(), name);
+ operations.add(Operation.setProperty(targetPath, values));
}
@Override
- public void removeProperty(TreeImpl tree, String name) {
- isDirty = true;
+ public void removeProperty(TreeImpl parent, String name) {
+ String targetPath = PathUtils.concat(parent.getPath(), name);
+ operations.add(Operation.removeProperty(targetPath));
}
@Override
- public void move(TreeImpl tree, String name, TreeImpl moved) {
- isDirty = true;
+ public void move(TreeImpl sourceParent, String sourceName, TreeImpl
moved) {
+ String sourcePath = PathUtils.concat(sourceParent.getPath(),
sourceName);
+ operations.add(Operation.move(sourcePath, moved.getPath()));
}
@Override
- public void copy(TreeImpl tree, String name, TreeImpl copied) {
- isDirty = true;
+ public void copy(TreeImpl sourceParent, String sourceName, TreeImpl
copied) {
+ String sourcePath = PathUtils.concat(sourceParent.getPath(),
sourceName);
+ operations.add(Operation.copy(sourcePath, copied.getPath()));
+ }
+
+ boolean hasChanges() {
+ return !operations.isEmpty();
}
- public boolean hasChanges() {
- return isDirty;
+ List<Operation> getChanges() {
+ return operations;
+ }
+ }
+
+ private static class Operation {
+ final Type type;
+ final String targetPath;
+ final String sourcePath;
+ final List<CoreValue> values;
+ final boolean isMultiple;
+
+ enum Type {ADD_NODE, REMOVE_NODE, SET_PROPERTY, REMOVE_PROPERTY, MOVE,
COPY}
+
+ private Operation(Type type, String targetPath, String sourcePath,
+ List<CoreValue> values, boolean isMultiple) {
+
+ this.type = type;
+ this.targetPath = targetPath;
+ this.sourcePath = sourcePath;
+ this.values = values;
+ this.isMultiple = isMultiple;
+ }
+
+ static Operation addNode(String targetPath) {
+ return new Operation(Type.ADD_NODE, targetPath, null, null, false);
+ }
+
+ static Operation removeNode(String targetPath) {
+ return new Operation(Type.REMOVE_NODE, targetPath, null, null,
false);
+ }
+
+ static Operation setProperty(String targetPath, CoreValue value) {
+ return new Operation(Type.SET_PROPERTY, targetPath, null,
singletonList(value), false);
+ }
+
+ static Operation setProperty(String targetPath, List<CoreValue>
values) {
+ return new Operation(Type.SET_PROPERTY, targetPath, null, values,
true);
+ }
+
+ static Operation removeProperty(String targetPath) {
+ return new Operation(Type.REMOVE_PROPERTY, targetPath, null, null,
false);
+ }
+
+ static Operation move(String sourcePath, String targetPath) {
+ return new Operation(Type.MOVE, targetPath, sourcePath, null,
false);
+ }
+
+ static Operation copy(String sourcePath, String targetPath) {
+ return new Operation(Type.COPY, targetPath, sourcePath, null,
false);
+ }
+
+ @Override
+ public String toString() {
+ switch (type) {
+ case ADD_NODE:
+ return '+' + targetPath + ":{}";
+ case REMOVE_NODE:
+ return '-' + targetPath;
+ case SET_PROPERTY:
+ return '^' + targetPath + ':' + (isMultiple ? values :
values.get(0));
+ case REMOVE_PROPERTY:
+ return '^' + targetPath + ":null";
+ case MOVE:
+ return '>' + sourcePath + ':' + targetPath;
+ case COPY:
+ return '*' + sourcePath + ':' + targetPath;
+ }
+ throw new IllegalStateException("We should never get here");
}
}
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=1330923&r1=1330922&r2=1330923&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
Thu Apr 26 16:18:40 2012
@@ -91,56 +91,56 @@ public class TreeImpl implements Tree {
/**
* The child of the given {@code name} has been added to {@code tree}.
- * @param tree parent to which a child was added
+ * @param parent parent to which a child was added
* @param name name of the added child
*/
- void addChild(TreeImpl tree, String name);
+ void addChild(TreeImpl parent, 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 parent parent from which a child was removed
* @param name name of the removed child
*/
- void removeChild(TreeImpl tree, String name);
+ void removeChild(TreeImpl parent, 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 parent parent on which the property was set.
* @param name name of the property
* @param value value of the property
*/
- void setProperty(TreeImpl tree, String name, CoreValue value);
+ void setProperty(TreeImpl parent, 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 parent parent on which the property was set.
* @param name name of the property
* @param values values of the property
*/
- void setProperty(TreeImpl tree, String name, List<CoreValue> values);
+ void setProperty(TreeImpl parent, 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 parent parent on which the property was removed.
* @param name name of the property
*/
- void removeProperty(TreeImpl tree, String name);
+ void removeProperty(TreeImpl parent, 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 sourceParent parent from which the child was moved
+ * @param sourceName name of the moved child
* @param moved moved child
*/
- void move(TreeImpl tree, String name, TreeImpl moved);
+ void move(TreeImpl sourceParent, String sourceName, TreeImpl 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 sourceParent parent from which the child way copied
+ * @param sourceName name of the copied child
* @param copied copied child
*/
- void copy(TreeImpl tree, String name, TreeImpl copied);
+ void copy(TreeImpl sourceParent, String sourceName, TreeImpl copied);
}
@Override
@@ -332,7 +332,7 @@ public class TreeImpl implements Tree {
builder.addNode(name);
TreeImpl added = getChild(name);
if (added != null) {
- listener.addChild(added, name);
+ listener.addChild(this, name);
}
return added;
}
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java?rev=1330923&r1=1330922&r2=1330923&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionImpl.java
Thu Apr 26 16:18:40 2012
@@ -181,8 +181,10 @@ public class SessionImpl extends Abstrac
@Override
public void refresh(boolean keepChanges) throws RepositoryException {
ensureIsAlive();
- root.rebase();
- if (!keepChanges) {
+ if (keepChanges) {
+ root.rebase();
+ }
+ else {
root = contentSession.getCurrentRoot();
}
}
Modified:
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/RepositoryTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/RepositoryTest.java?rev=1330923&r1=1330922&r2=1330923&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/RepositoryTest.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/RepositoryTest.java
Thu Apr 26 16:18:40 2012
@@ -1103,25 +1103,49 @@ public class RepositoryTest extends Abst
@Test
public void sessionRefreshFalse() throws RepositoryException {
- Session session = getRepository().login();
+ Session session1 = getRepository().login();
+ Session session2 = getRepository().login();
try {
- Node foo = session.getNode("/foo");
+ Node foo = session1.getNode("/foo");
foo.addNode("added");
- NodeIterator it = foo.getNodes();
- assertTrue(it.hasNext());
- session.refresh(false);
- it = foo.getNodes();
- assertFalse(it.hasNext());
+ session2.getNode("/foo").addNode("bar");
+ session2.save();
+
+ session1.refresh(false);
+ assertFalse(foo.hasNode("added"));
+ assertTrue(foo.hasNode("bar"));
}
finally {
- session.logout();
+ session1.logout();
+ session2.logout();
+ }
+ }
+
+ @Test
+ public void sessionRefreshTrue() throws RepositoryException {
+ Session session1 = getRepository().login();
+ Session session2 = getRepository().login();
+ try {
+ Node foo = session1.getNode("/foo");
+ foo.addNode("added");
+
+ session2.getNode("/foo").addNode("bar");
+ session2.save();
+
+ session1.refresh(true);
+ assertTrue(foo.hasNode("added"));
+ assertTrue(foo.hasNode("bar"));
+ }
+ finally {
+ session1.logout();
+ session2.logout();
}
}
@Test(expected = RepositoryException.class)
- @Ignore("WIP") // TODO needs implementation of Tree.refresh
- public void refreshConflict() throws RepositoryException {
+ @Ignore("WIP") // TODO clarify
+ public void saveRefreshConflict() throws RepositoryException {
Session session1 = getRepository().login();
Session session2 = getRepository().login();
try {
@@ -1139,7 +1163,7 @@ public class RepositoryTest extends Abst
}
@Test(expected = RepositoryException.class)
- @Ignore("WIP") // TODO needs implementation of Tree.refresh
+ @Ignore("WIP") // TODO clarify
public void refreshConflict2() throws RepositoryException {
getSession().getRootNode().addNode("node");
getSession().save();