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 ju...@apache.org on 2012/10/01 11:29:42 UTC

svn commit: r1392246 - in /jackrabbit/oak/trunk: doc/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/

Author: jukka
Date: Mon Oct  1 09:29:42 2012
New Revision: 1392246

URL: http://svn.apache.org/viewvc?rev=1392246&view=rev
Log:
OAK-344: Move NodeStore.getBuilder(NodeState) to NodeState.getBuilder()

Further NodeBuilder simplification: Make the mutator methods return the builder instance so that method calls can be chained.
Also improve and reflow the related documentation in nodestate.md.

Modified:
    jackrabbit/oak/trunk/doc/nodestate.md
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java

Modified: jackrabbit/oak/trunk/doc/nodestate.md
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/doc/nodestate.md?rev=1392246&r1=1392245&r2=1392246&view=diff
==============================================================================
--- jackrabbit/oak/trunk/doc/nodestate.md (original)
+++ jackrabbit/oak/trunk/doc/nodestate.md Mon Oct  1 09:29:42 2012
@@ -71,35 +71,85 @@ more details about this interface and al
 
 ## Building new node states
 
-Since node states are immutable, a separate builder interface, `NodeBuilder`, is
-used to construct new, modified node states. Calling the `getBuilder` method on
-a node state returns such a builder.
-
-A node builder can be thought of as a _mutable_ version of a node state. The `NodeBuilder`
-interface consists of the following sets of methods:
-
-  * Methods for accessing and modifying properties
-  * Methods for accessing and modifying child nodes
-  * The `getNodeState` method for getting a frozen snapshot of the modified node
-
-Property modifications are pretty simple, as you the only things you can do are
-either set the value of a property or remove a property with the `setProperty` and
-`removeProperty` methods. 
-
+Since node states are immutable, a separate builder interface,
+`NodeBuilder`, is used to construct new, modified node states. Calling
+the `getBuilder` method on a node state returns such a builder for
+modifying that node and the subtree below it.
+
+A node builder can be thought of as a _mutable_ version of a node state.
+In addition to property and child node access methods like the ones that
+are already present in the `NodeState` interface, the `NodeBuilder`
+interface contains the following key methods:
+
+  * The `setProperty` and `removeProperty` methods for modifying properties
+  * The `removeNode` method for removing a subtree
+  * The `setNode` method for adding or replacing a subtree
+  * The `getChildBuilder` method for creating or modifying a subtree with
+    a connected child builder
+  * The `getNodeState` method for getting a frozen snapshot of the modified
+    content tree
+
+The concept of _connected builders_ is designed to make it easy to manage
+complex content changes. Since individual node states are always immutable,
+modifying a particular node at a path like `/foo/bar` using the `setNode`
+method would require the following overly verbose code:
+
+    NodeState root = …;
+    NodeState foo = root.getChildNode("foo")
+    NodeState bar = foo.getChildNode("bar");
+    NodeBuilder barBuilder = bar.getBuilder();
+    barBuilder.setProperty("test", …);
+    NodeBuilder fooBuilder = foo.getBuilder();
+    fooBuilder.setNode("bar", barBuilder.getNodeState());
+    NodeBuilder rootBuilder = root.getBuilder();
+    rootBuilder.setNode("foo", fooBuilder.getNodeState());
+    root = rootBuilder.getNodeState();
+
+The complexity here is caused by the need to explicitly construct and
+re-connect each modified node state along the path from the root to the
+modified content in `/foo/bar`. This is because each `NodeBuilder` instance
+created by the `getBuilder` method is independent and can only be used to
+affect other builders in the manner shown above. In contrast the
+`getChildBuilder` method returns a builder instance that is "connected" to
+the parent builder in a way that any changes recorded in the child builder
+will automatically show up also in the node states created by the parent
+builder. With connected builders the above code can be simplified to:
+
+    NodeState root = …;
+    NodeBuilder rootBuilder = root.getBuilder();
+    rootBuilder
+        .getChildBuilder("foo")
+        .getChildBuilder("bar")
+        .setProperty("test", …);
+    root = rootBuilder.getNodeState();
+
+Typically the only case where the `setNode` method is preferable over
+`getChildBuilder` is when moving or copying subtrees from one location
+to another. For example, the following code copies the `/orig` subtree
+to `/copy`:
+
+    NodeState root = …;
+    NodeBuilder rootBuilder = root.getBuilder();
+    rootBuilder.setNode("copy", root.getChildNode("orig"));
+    root = rootBuilder.getNodeState();
+
+The node states constructed by a builder often retain an internal reference
+to the base state used by the builder. This allows common node state
+comparisons to perform really well as described in the next section.
 
 ## Comparing node states
 
-As a node evolves through a sequence of states, it's often important to be
-able to tell what has changed between two states of the node. As mentioned
-above, this functionality is available through the `compareAgainstBaseState`
-method. The method takes two arguments:
-
-  * A _base state_ for the comparison. The comparison will report all changes
-    necessary for moving from the given base state to the node state on which
-    the comparison method is invoked.
+As a node evolves through a sequence of states, it's often important to
+be able to tell what has changed between two states of the node. This
+functionality is available through the `compareAgainstBaseState` method.
+The method takes two arguments:
+
+  * A _base state_ for the comparison. The comparison will report all
+    changes necessary for moving from the given base state to the node
+    state on which the comparison method is invoked.
   * A `NodeStateDiff` instance to which all detected changes are reported.
-    The diff interface contains callback methods for reporting added, modified
-    or removed properties or child nodes.
+    The diff interface contains callback methods for reporting added,
+    modified or removed properties or child nodes.
 
 The comparison method can actually be used to compare any two nodes, but the
 implementations of the method are typically heavily optimized for the case

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=1392246&r1=1392245&r2=1392246&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 Mon Oct  1 09:29:42 2012
@@ -23,6 +23,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.Nonnull;
+
 import org.apache.jackrabbit.oak.api.CoreValue;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
@@ -231,8 +233,8 @@ public class MemoryNodeBuilder implement
         return read().getChildNodeNames();
     }
 
-    @Override
-    public void setNode(String name, NodeState state) {
+    @Override @Nonnull
+    public NodeBuilder setNode(String name, NodeState state) {
         MutableNodeState mstate = write();
 
         MutableNodeState cstate = mstate.nodes.get(name);
@@ -244,10 +246,11 @@ public class MemoryNodeBuilder implement
         }
 
         updated();
+        return this;
     }
 
-    @Override
-    public void removeNode(String name) {
+    @Override @Nonnull
+    public NodeBuilder removeNode(String name) {
         MutableNodeState mstate = write();
 
         if (mstate.base.getChildNode(name) != null) {
@@ -257,6 +260,7 @@ public class MemoryNodeBuilder implement
         }
 
         updated();
+        return this;
     }
 
     @Override
@@ -275,17 +279,18 @@ public class MemoryNodeBuilder implement
         return read().getProperty(name);
     }
 
-    @Override
-    public void setProperty(String name, CoreValue value) {
+    @Override @Nonnull
+    public NodeBuilder setProperty(String name, CoreValue value) {
         MutableNodeState mstate = write();
 
         mstate.props.put(name, new SinglePropertyState(name, value));
 
         updated();
+        return this;
     }
 
-    @Override
-    public void setProperty(String name, List<CoreValue> values) {
+    @Override @Nonnull
+    public NodeBuilder setProperty(String name, List<CoreValue> values) {
         MutableNodeState mstate = write();
 
         if (values.isEmpty()) {
@@ -295,10 +300,11 @@ public class MemoryNodeBuilder implement
         }
 
         updated();
+        return this;
     }
 
-    @Override
-    public void removeProperty(String name) {
+    @Override @Nonnull
+    public NodeBuilder removeProperty(String name) {
         MutableNodeState mstate = write();
 
         if (mstate.base.getProperty(name) != null) {
@@ -308,6 +314,7 @@ public class MemoryNodeBuilder implement
         }
 
         updated();
+        return this;
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java?rev=1392246&r1=1392245&r2=1392246&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java Mon Oct  1 09:29:42 2012
@@ -61,19 +61,24 @@ public interface NodeBuilder {
     Iterable<String> getChildNodeNames();
 
     /**
-     * Add a sub-tree
+     * Adds or replaces a sub-ree.
      *
-     * @param name  name child node containing the sub-tree
-     * @param nodeState  sub-tree
+     * @param name name of the child node containing the new subtree
+     * @param nodeState subtree
+     * @return this builder
      */
-    void setNode(String name, @Nonnull NodeState nodeState);
+    @Nonnull
+    NodeBuilder setNode(String name, @Nonnull NodeState nodeState);
 
     /**
      * Remove a child node. This method has no effect if a
      * property of the given {@code name} does not exist.
+     *
      * @param name  name of the child node
+     * @return this builder
      */
-    void removeNode(String name);
+    @Nonnull
+    NodeBuilder removeNode(String name);
 
     /**
      * Returns the current number of properties.
@@ -103,23 +108,30 @@ public interface NodeBuilder {
      *
      * @param name property name
      * @param value
+     * @return this builder
      */
-    void setProperty(String name, @Nonnull CoreValue value);
+    @Nonnull
+    NodeBuilder setProperty(String name, @Nonnull CoreValue value);
 
     /**
      * Set a property.
      *
      * @param name property name
      * @param values
+     * @return this builder
      */
-    void setProperty(String name, @Nonnull List<CoreValue> values);
+    @Nonnull
+    NodeBuilder setProperty(String name, @Nonnull List<CoreValue> values);
 
     /**
      * Remove the named property. This method has no effect if a
      * property of the given {@code name} does not exist.
+     *
      * @param name  name of the property
+     * @return this builder
      */
-    void removeProperty(String name);
+    @Nonnull
+    NodeBuilder removeProperty(String name);
 
     /**
      * Returns a builder for constructing changes to the named child node.

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java?rev=1392246&r1=1392245&r2=1392246&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java Mon Oct  1 09:29:42 2012
@@ -18,6 +18,8 @@ package org.apache.jackrabbit.oak.spi.st
 
 import java.util.List;
 
+import javax.annotation.Nonnull;
+
 import org.apache.jackrabbit.oak.api.CoreValue;
 import org.apache.jackrabbit.oak.api.PropertyState;
 
@@ -57,13 +59,13 @@ public class ReadOnlyBuilder implements 
         return state.getChildNodeNames();
     }
 
-    @Override
-    public void setNode(String name, NodeState nodeState) {
+    @Override @Nonnull
+    public NodeBuilder setNode(String name, NodeState nodeState) {
         throw unsupported();
     }
 
-    @Override
-    public void removeNode(String name) {
+    @Override @Nonnull
+    public NodeBuilder removeNode(String name) {
         throw unsupported();
     }
 
@@ -82,18 +84,18 @@ public class ReadOnlyBuilder implements 
         return state.getProperty(name);
     }
 
-    @Override
-    public void setProperty(String name, CoreValue value) {
+    @Override @Nonnull
+    public NodeBuilder setProperty(String name, CoreValue value) {
         throw unsupported();
     }
 
-    @Override
-    public void setProperty(String name, List<CoreValue> values) {
+    @Override @Nonnull
+    public NodeBuilder setProperty(String name, List<CoreValue> values) {
         throw unsupported();
     }
 
-    @Override
-    public void removeProperty(String name) {
+    @Override @Nonnull
+    public NodeBuilder removeProperty(String name) {
         throw unsupported();
     }