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 2013/05/29 15:18:45 UTC
svn commit: r1487474 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java
test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilderTest.java
Author: mduerig
Date: Wed May 29 13:18:45 2013
New Revision: 1487474
URL: http://svn.apache.org/r1487474
Log:
OAK-781: Clarify / fix effects of MISSING_NODE as base state of NodeBuilder
Explicitly track connectedness through new Head.head()
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilderTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java?rev=1487474&r1=1487473&r2=1487474&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java Wed May 29 13:18:45 2013
@@ -103,7 +103,8 @@ public class MemoryNodeBuilder implement
private NodeState base;
/**
- * Head of this builder
+ * Head of this builder. Always use {@link #head()} for accessing to
+ * ensure the connected state is correctly updated.
*/
private Head head;
@@ -137,6 +138,14 @@ public class MemoryNodeBuilder implement
}
/**
+ * Update the head of this builder to reflect the actual connected state.
+ * @return head of this builder
+ */
+ private Head head() {
+ return head.update();
+ }
+
+ /**
* @return {@code true} iff this is the root builder
*/
private boolean isRoot() {
@@ -181,7 +190,7 @@ public class MemoryNodeBuilder implement
@Override
public NodeState getNodeState() {
- return head.getImmutableNodeState();
+ return head().getImmutableNodeState();
}
@Override
@@ -191,7 +200,7 @@ public class MemoryNodeBuilder implement
@Override
public boolean exists() {
- return head.getCurrentNodeState().exists();
+ return head().getCurrentNodeState().exists();
}
@Override
@@ -201,30 +210,29 @@ public class MemoryNodeBuilder implement
@Override
public boolean isModified() {
- NodeState state = head.getCurrentNodeState();
- return state instanceof MutableNodeState && ((MutableNodeState) state).isModified(base());
+ return head().isModified();
}
@Override
public void reset(NodeState newBase) {
base = checkNotNull(newBase);
baseRevision++;
- head.reset();
+ head().reset();
}
@Override
public long getChildNodeCount() {
- return head.getCurrentNodeState().getChildNodeCount();
+ return head().getCurrentNodeState().getChildNodeCount();
}
@Override
public Iterable<String> getChildNodeNames() {
- return head.getCurrentNodeState().getChildNodeNames();
+ return head().getCurrentNodeState().getChildNodeNames();
}
@Override
public boolean hasChildNode(String name) {
- return head.getCurrentNodeState().hasChildNode(checkNotNull(name));
+ return head().getCurrentNodeState().hasChildNode(checkNotNull(name));
}
@Override
@@ -249,7 +257,7 @@ public class MemoryNodeBuilder implement
@Override
public NodeBuilder setChildNode(String name, NodeState state) {
checkState(exists(), "This builder does not exist: " + name);
- head.getMutableNodeState().setChildNode(checkNotNull(name), checkNotNull(state));
+ head().getMutableNodeState().setChildNode(checkNotNull(name), checkNotNull(state));
MemoryNodeBuilder builder = createChildBuilder(name);
updated();
return builder;
@@ -258,8 +266,8 @@ public class MemoryNodeBuilder implement
@Override
public boolean remove() {
if (exists()) {
- head.getMutableNodeState();
- parent.head.getMutableNodeState().removeChildNode(name);
+ head().getMutableNodeState(); // Make sure the removed node is connected
+ parent.head().getMutableNodeState().removeChildNode(name);
return true;
} else {
return false;
@@ -268,22 +276,22 @@ public class MemoryNodeBuilder implement
@Override
public long getPropertyCount() {
- return head.getCurrentNodeState().getPropertyCount();
+ return head().getCurrentNodeState().getPropertyCount();
}
@Override
public Iterable<? extends PropertyState> getProperties() {
- return head.getCurrentNodeState().getProperties();
+ return head().getCurrentNodeState().getProperties();
}
@Override
public boolean hasProperty(String name) {
- return head.getCurrentNodeState().hasProperty(checkNotNull(name));
+ return head().getCurrentNodeState().hasProperty(checkNotNull(name));
}
@Override
public PropertyState getProperty(String name) {
- return head.getCurrentNodeState().getProperty(checkNotNull(name));
+ return head().getCurrentNodeState().getProperty(checkNotNull(name));
}
@Override
@@ -317,7 +325,7 @@ public class MemoryNodeBuilder implement
@Override
public NodeBuilder setProperty(PropertyState property) {
checkState(exists(), "This builder does not exist: " + name);
- head.getMutableNodeState().setProperty(checkNotNull(property));
+ head().getMutableNodeState().setProperty(checkNotNull(property));
updated();
return this;
}
@@ -337,7 +345,7 @@ public class MemoryNodeBuilder implement
@Override
public NodeBuilder removeProperty(String name) {
checkState(exists(), "This builder does not exist: " + name);
- if (head.getMutableNodeState().removeProperty(checkNotNull(name))) {
+ if (head().getMutableNodeState().removeProperty(checkNotNull(name))) {
updated();
}
return this;
@@ -350,6 +358,10 @@ public class MemoryNodeBuilder implement
return parent == null ? "/" : getPath(new StringBuilder()).toString();
}
+ private RootHead rootHead() {
+ return (RootHead) rootBuilder.head;
+ }
+
private StringBuilder getPath(StringBuilder parentPath) {
return parent == null ? parentPath : parent.getPath(parentPath).append('/').append(name);
}
@@ -362,16 +374,18 @@ public class MemoryNodeBuilder implement
//------------------------------------------------------------< Head >---
/**
- * The subclasses of this abstract base class represent the different
- * states builders can have: <em>unconnected</em>, <em>connected</em>,
- * and <em>root</em>. {@code MemoryNodeBuilder} implements most of its
- * functionality by forwarding to the methods of {@code Head} instances
- * where the actual type of {@code Head} determines the behaviour associated
- * with the current state.
+ * Subclasses of this base class represent the different states associated
+ * builders can have: <em>unconnected</em>, <em>connected</em>, and <em>root</em>.
+ * Its methods provide access to the node state being built by this builder.
*/
private abstract static class Head {
- protected long revision;
- protected NodeState state;
+
+ /**
+ * Update the {@link MemoryNodeBuilder#head} of this builder by apply any pending
+ * state transition.
+ * @return the new head of the associated builder.
+ */
+ public abstract Head update();
/**
* Returns the current node state associated with this head. This state
@@ -394,37 +408,62 @@ public class MemoryNodeBuilder implement
* Returns the current nodes state associated with this head.
* @return current head state.
*/
- public NodeState getImmutableNodeState() {
- NodeState state = getCurrentNodeState();
- return state instanceof MutableNodeState
- ? ((MutableNodeState) state).snapshot()
- : state;
- }
+ public abstract NodeState getImmutableNodeState();
+
+ /**
+ * Check whether the associated builder represents a modified node, which has
+ * either modified properties or removed or added child nodes.
+ * @return {@code true} for a modified node
+ */
+ public abstract boolean isModified();
public void reset() {
throw new IllegalStateException("Cannot reset a non-root builder");
}
}
- private class ConnectedHead extends Head {
+ private class UnconnectedHead extends Head {
+ private long revision;
+ private NodeState state;
+
@Override
- public MutableNodeState getCurrentNodeState() {
- if (revision != rootBuilder.baseRevision) {
- // the root builder's base state has been reset: re-get
- // state from parent.
- MutableNodeState parentState = (MutableNodeState) parent.head.getCurrentNodeState();
- state = parentState.getMutableChildNode(name);
- revision = rootBuilder.baseRevision;
+ public Head update() {
+ if (revision != rootHead().revision) {
+ // root revision changed: recursively re-get state from parent
+ NodeState parentState = parent.head().getCurrentNodeState();
+ NodeState newState = parentState.getChildNode(name);
+ if (newState instanceof MutableNodeState) {
+ return head = new ConnectedHead((MutableNodeState) newState);
+ } else {
+ state = newState;
+ }
+ revision = rootHead().revision;
}
- return (MutableNodeState) state;
+ return this;
+ }
+
+ @Override
+ public NodeState getCurrentNodeState() {
+ return state;
}
@Override
public MutableNodeState getMutableNodeState() {
- // incrementing the root revision triggers unconnected
- // child state to re-get their state on next access
- rootBuilder.head.revision++;
- return getCurrentNodeState();
+ // switch to connected state recursively up to the parent
+ MutableNodeState parentState = parent.head().getMutableNodeState();
+ head = new ConnectedHead(parentState.getMutableChildNode(name));
+ return head.getMutableNodeState();
+ }
+
+ @Override
+ public NodeState getImmutableNodeState() {
+ assert !(state instanceof MutableNodeState);
+ return state;
+ }
+
+ @Override
+ public boolean isModified() {
+ return false;
}
@Override
@@ -433,23 +472,47 @@ public class MemoryNodeBuilder implement
}
}
- private class UnconnectedHead extends Head {
+ private class ConnectedHead extends Head {
+ protected long revision;
+ protected MutableNodeState state;
+
+ public ConnectedHead(MutableNodeState state) {
+ this.state = state;
+ }
+
@Override
- public NodeState getCurrentNodeState() {
- if (revision != rootBuilder.head.revision) {
- // root revision changed: recursively re-get state from parent
- NodeState parentState = parent.head.getCurrentNodeState();
- state = parentState.getChildNode(name);
- revision = rootBuilder.head.revision;
+ public Head update() {
+ if (revision != rootBuilder.baseRevision) {
+ // the root builder's base state has been reset: re-get
+ // state from parent.
+ MutableNodeState parentState = (MutableNodeState) parent.head().getCurrentNodeState();
+ state = parentState.getMutableChildNode(name);
+ revision = rootBuilder.baseRevision;
}
+ return this;
+ }
+
+ @Override
+ public NodeState getCurrentNodeState() {
return state;
}
@Override
public MutableNodeState getMutableNodeState() {
- // switch to connected state recursively up to the parent
- parent.head.getMutableNodeState();
- return (head = new ConnectedHead()).getMutableNodeState();
+ // incrementing the root revision triggers unconnected
+ // child state to re-get their state on next access
+ rootHead().revision++;
+ return state;
+ }
+
+ @Override
+ public NodeState getImmutableNodeState() {
+ return state.snapshot();
+ }
+
+ @Override
+ public boolean isModified() {
+ return state.isModified(base());
}
@Override
@@ -458,20 +521,16 @@ public class MemoryNodeBuilder implement
}
}
- private class RootHead extends Head {
+ private class RootHead extends ConnectedHead {
public RootHead() {
+ super(new MutableNodeState(base));
// ensure updating of child builders on first access
- reset();
+ revision = 1;
}
@Override
- public MutableNodeState getCurrentNodeState() {
- return (MutableNodeState) state;
- }
-
- @Override
- public MutableNodeState getMutableNodeState() {
- return (MutableNodeState) state;
+ public Head update() {
+ return this;
}
@Override
@@ -479,11 +538,6 @@ public class MemoryNodeBuilder implement
state = new MutableNodeState(base);
revision++;
}
-
- @Override
- public String toString() {
- return toStringHelper(this).add("path", getPath()).toString();
- }
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilderTest.java?rev=1487474&r1=1487473&r2=1487474&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilderTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilderTest.java Wed May 29 13:18:45 2013
@@ -47,7 +47,7 @@ public class MemoryNodeBuilderTest {
builder.child("x").child("q");
builder.child("y");
builder.child("z");
- base = ModifiedNodeState.squeeze(builder.getNodeState());
+ base = builder.getNodeState();
}
@Test