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/04 16:09:29 UTC

svn commit: r1309397 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel: KernelNodeStateEditor.java TransientNodeState.java

Author: mduerig
Date: Wed Apr  4 14:09:29 2012
New Revision: 1309397

URL: http://svn.apache.org/viewvc?rev=1309397&view=rev
Log:
OAK-9: Internal tree builder
Javadoc, minor cleanup, fix in copy constructor

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateEditor.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/TransientNodeState.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateEditor.java?rev=1309397&r1=1309396&r2=1309397&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateEditor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateEditor.java Wed Apr  4 14:09:29 2012
@@ -58,7 +58,7 @@ public class KernelNodeStateEditor imple
      */
     KernelNodeStateEditor(NodeState base) {
         this.base = base;
-        transientState = new TransientNodeState(base, this, null, "");
+        transientState = new TransientNodeState(base, this);
         jsop = new StringBuilder();
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/TransientNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/TransientNodeState.java?rev=1309397&r1=1309396&r2=1309397&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/TransientNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/TransientNodeState.java Wed Apr  4 14:09:29 2012
@@ -17,34 +17,78 @@ import java.util.Set;
 
 import static org.apache.jackrabbit.oak.kernel.TransientNodeState.Iterators.*;
 
+/**
+ * A transient node state represents a node being edited. All edit operations are
+ * done through an associated {@link org.apache.jackrabbit.mk.model.NodeStateEditor}.
+ * <p>
+ * A transient node state contains the current state of a node and is
+ * in contrast to {@link org.apache.jackrabbit.mk.model.NodeState} instances
+ * mutable and not thread safe.
+ * <p>
+ * The various accessors on this class mirror these of {@code NodeState}. However,
+ * since instances of this class are mutable return values may change between
+ * invocations.
+ */
 public class TransientNodeState {
+    /** Editor acting upon this instance */
     private final KernelNodeStateEditor editor;
+
+    /**
+     * Underlying persistent state or {@code null} if this instance represents an
+     * added node state
+     */
     private final NodeState persistentState;
 
-    private final Map<NodeState, TransientNodeState> existingChildNodes =
-            new HashMap<NodeState, TransientNodeState>();
+    /** Resolved persistent child states */
+    private final Map<String, TransientNodeState> existingChildNodes =
+            new HashMap<String, TransientNodeState>();
+
+    /** Transiently added node states */
     private final Map<String, TransientNodeState> addedNodes =
             new HashMap<String, TransientNodeState>();
+
+    /** Transiently removed node stated */
     private final Set<String> removedNodes = new HashSet<String>();
+
+    /** Transiently added property states */
     private final Map<String, PropertyState> addedProperties = new HashMap<String, PropertyState>();
+
+    /** Transiently removed property states */
     private final Set<String> removedProperties = new HashSet<String>();
 
+    /** Name of this state */
     private String name;
-    private TransientNodeState parent;
 
-    TransientNodeState(NodeState persistentState, KernelNodeStateEditor editor,
-            TransientNodeState parent, String name) {
+    /** Parent of this state */
+    private TransientNodeState parent;
 
+    /**
+     * Create a new instance representing the root of a sub-tree.
+     * @param persistentState  underlying persistent state
+     * @param editor  editor acting upon the transient node state
+     */
+    TransientNodeState(NodeState persistentState, KernelNodeStateEditor editor) {
         this.editor = editor;
         this.persistentState = persistentState;
-        this.parent = parent;
-        this.name = name;
+        this.parent = null;
+        this.name = "";
     }
 
+    /**
+     * Create a new instance representing a added node state
+     * @param parentEditor  editor of the parent state
+     * @param name  name of the state
+     */
     private TransientNodeState(KernelNodeStateEditor parentEditor, String name) {
         this(parentEditor, name, null);
     }
-    
+
+    /**
+     * Create a new instance with an underlying persistent state
+     * @param parentEditor  editor of the parent state
+     * @param name  name of the state
+     * @param persistedState  underlying persistent state
+     */
     private TransientNodeState(KernelNodeStateEditor parentEditor, String name,
             NodeState persistedState) {
 
@@ -54,6 +98,13 @@ public class TransientNodeState {
         this.name = name;
     }
 
+    /**
+     * Copy constructor: create a deep copy of the passed {@code state} with
+     * the given {@code name} and {@code parent}.
+     * @param state  state to copy
+     * @param parent  parent of the copied state
+     * @param name  name of the copied state
+     */
     private TransientNodeState(TransientNodeState state, TransientNodeState parent,
             String name) {
 
@@ -62,6 +113,14 @@ public class TransientNodeState {
         this.parent = parent;
         this.name = name;
 
+        // recursively copy all existing node states
+        for (Entry<String, TransientNodeState> existing : existingChildNodes.entrySet()) {
+            String existingName = existing.getKey();
+            this.existingChildNodes.put(existingName,
+                    new TransientNodeState(existing.getValue(), this, existingName));
+        }
+        
+        // recursively copy all added node states
         for (Entry<String, TransientNodeState> added : addedNodes.entrySet()) {
             String addedName = added.getKey();
             this.addedNodes.put(addedName,
@@ -73,21 +132,39 @@ public class TransientNodeState {
         this.removedProperties.addAll(state.removedProperties);
     }
 
+    /**
+     * Get a property state
+     * @param name name of the property state
+     * @return  the property state with the given {@code name} or {@code null}
+     *          if no such property state exists.
+     */
     public PropertyState getProperty(String name) {
         PropertyState state = addedProperties.get(name);
         if (state != null) {
+            // Added or removed and re-added property
             return state;
         }
 
+        // Existing property unless removed
         return removedProperties.contains(name) || persistentState == null
             ? null
             : persistentState.getProperty(name);
     }
-    
+
+    /**
+     * Determine if a property state exists
+     * @param name  name of the property state
+     * @return  {@code true} if and only if a property with the given {@code name}
+     *          exists.
+     */
     public boolean hasProperty(String name) {
         return getProperty(name) != null;
     }
-    
+
+    /**
+     * Determine the number of properties.
+     * @return  number of properties
+     */
     public long getPropertyCount() {
         long persistentCount = persistentState == null
             ? 0
@@ -96,21 +173,39 @@ public class TransientNodeState {
         return persistentCount + addedProperties.size() - removedProperties.size();
     }
 
+    /**
+     * Get a child node state
+     * @param name  name of the child node state
+     * @return  the child node state with the given {@code name} or {@code null}
+     *          if no such child node state exists.
+     */
     public TransientNodeState getChildNode(String name) {
         TransientNodeState state = addedNodes.get(name);
         if (state != null) {
+            // Added or removed and re-added child node
             return state;
         }
 
+        // Existing child node unless removed
         return removedNodes.contains(name)
             ? null
             : getExistingChildNode(name);
     }
 
+    /**
+     * Determine if a child node state exists
+     * @param name  name of the child node state
+     * @return  {@code true} if and only if a child node with the given {@code name}
+     *          exists.
+     */
     public boolean hasNode(String name) {
         return getChildNode(name) != null;
     }
-    
+
+    /**
+     * Determine the number of child nodes.
+     * @return  number of child nodes.
+     */
     public long getChildNodeCount() {
         long persistentCount = persistentState == null
                 ? 0
@@ -119,25 +214,39 @@ public class TransientNodeState {
         return persistentCount + addedNodes.size() - removedNodes.size();
     }
 
+    /**
+     * All property states. The returned {@code Iterable} has snapshot semantics. That
+     * is, it reflect the state of this transient node state instance at the time of the
+     * call. Later changes to this instance are no visible to iterators obtained from
+     * the returned iterable.
+     * @return  An {@code Iterable} for all property states
+     */
     public Iterable<PropertyState> getProperties() {
+        // Persisted property states
         final Iterable<? extends PropertyState> persisted = persistentState == null
                 ? null
                 : persistentState.getProperties();
 
+        // Copy of removed property states
         final Set<String> removed = new HashSet<String>();
         removed.addAll(removedProperties);
 
+        // Copy of added and re-added property stated
         final Set<PropertyState> added = new HashSet<PropertyState>();
         added.addAll(addedProperties.values());
 
-        // persisted - removed + added
+        // Filter removed property states from persisted property states
+        // and add added property states
         return new Iterable<PropertyState>() {
             @Override
             public Iterator<PropertyState> iterator() {
-                Iterator<? extends PropertyState> properties = persisted == null
-                    ? Iterators.<PropertyState>empty()
-                    : persisted.iterator();
+                // persisted states
+                Iterator<? extends PropertyState> properties =
+                    persisted == null
+                        ? Iterators.<PropertyState>empty()
+                        : persisted.iterator();
 
+                // persisted states - removed states
                 Iterator<PropertyState> persistedMinusRemoved =
                     filter(properties, new Predicate<PropertyState>() {
                         @Override
@@ -146,30 +255,45 @@ public class TransientNodeState {
                         }
                 });
 
+                // persisted states - removed states + added states
                 return add(persistedMinusRemoved, added.iterator());
             }
         };
     }
 
+    /**
+     * All child node states. The returned {@code Iterable} has snapshot semantics. That
+     * is, it reflect the state of this transient node state instance at the time of the
+     * call. Later changes to this instance are no visible to iterators obtained from
+     * the returned iterable.
+     * @return  An {@code Iterable} for all child node states
+     */
     public Iterable<TransientNodeState> getChildNodes(long offset, int count) {
+        // Persisted child node states
         final Iterable<? extends ChildNodeEntry> persisted = persistentState == null
             ? null
             : persistentState.getChildNodeEntries(offset, count);
 
+        // Copy od removed child node states
         final Set<String> removed = new HashSet<String>();
         removed.addAll(removedNodes);
 
+        // Copy od added and re-added child node states
         final Set<TransientNodeState> added = new HashSet<TransientNodeState>();
         added.addAll(addedNodes.values());
 
-        // persisted - removed + added
+        // Filter removed child node entries from persisted child node entries,
+        // map remaining child node entries to child node states and add added
+        // child node states
         return new Iterable<TransientNodeState>() {
             @Override
             public Iterator<TransientNodeState> iterator() {
+                // persisted entries
                 Iterator<? extends ChildNodeEntry> nodes = persisted == null
                     ? Iterators.<ChildNodeEntry>empty()
                     : persisted.iterator();
 
+                // persisted entries - removed entries
                 Iterator<ChildNodeEntry> persistedMinusRemovedEntries =
                     filter(nodes, new Predicate<ChildNodeEntry>() {
                         @Override
@@ -178,6 +302,7 @@ public class TransientNodeState {
                         }
                 });
 
+                // persisted states - removed states
                 Iterator<TransientNodeState> persistedMinusRemoved =
                     map(persistedMinusRemovedEntries,
                         new Function1<ChildNodeEntry, TransientNodeState>() {
@@ -187,6 +312,7 @@ public class TransientNodeState {
                             }
                 });
 
+                // persisted states - removed states + added states
                 return add(persistedMinusRemoved, added.iterator());
             }
         };
@@ -194,10 +320,16 @@ public class TransientNodeState {
 
     //------------------------------------------------------------< internal >---
 
+    /**
+     * @return  editor acting upon this instance
+     */
     KernelNodeStateEditor getEditor() {
         return editor;
     }
 
+    /**
+     * @return  relative path of this transient node state
+     */
     String getPath() {
         if (parent == null) {
             return name;
@@ -210,28 +342,60 @@ public class TransientNodeState {
         }
     }
 
+    /**
+     * Add a new child node state with the given {@code name}.
+     * The behaviour of this method is not defined if a node state with that
+     * {@code name} already exists.
+     * @param name  name of the child node state
+     */
     void addNode(String name) {
         addedNodes.put(name, new TransientNodeState(editor, name));
     }
 
+    /**
+     * Remove the child node state with the given {@code name}.
+     * Does nothing if there is no node state with the given {@code name}.
+     * @param name  name of the child node state
+     */
     void removeNode(String name) {
         addedNodes.remove(name);
         if (hasExistingNode(name)) {
+            // Mark as removed if removing existing
             removedNodes.add(name);
         }
     }
 
+    /**
+     * Set a property state.
+     * @param state  a property state
+     */
     void setProperty(PropertyState state) {
         addedProperties.put(state.getName(), state);
     }
 
+    /**
+     * Remove the property state with the given {@code name}.
+     * Does nothing if there is no property state with the given {@code name}.
+     * @param name  a property state
+     */
     void removeProperty(String name) {
         addedProperties.remove(name);
         if (hasExistingProperty(name)) {
+            // Mark as removed if removing existing
             removedProperties.add(name);
         }
     }
 
+    /**
+     * Move the child node state with the given {@code name} to the new parent at
+     * The behaviour of this method is undefined if either this node state has
+     * no child node state with the given {@code name} or {@code destParent} already
+     * has a child node state of {@code destName}.
+     *
+     * @param name  name of the child node state to move
+     * @param destParent  parent of the moved node state
+     * @param destName  name of the moved node state
+     */
     void move(String name, TransientNodeState destParent, String destName) {
         TransientNodeState state = getChildNode(name);
         removeNode(name);
@@ -241,29 +405,64 @@ public class TransientNodeState {
         destParent.addedNodes.put(destName, state);
     }
 
+    /**
+     * Copy the child node state with the given {@code name} to the new parent at
+     * The behaviour of this method is undefined if {@code destParent} already
+     * has a child node state of {@code destName}.
+     *
+     * @param name  name of the child node state to move
+     * @param destParent  parent of the moved node state
+     * @param destName  name of the moved node state
+     */
     void copy(String name, TransientNodeState destParent, String destName) {
         destParent.addedNodes.put(destName,
                 new TransientNodeState(getChildNode(name), destParent, destName));
     }
 
+    /**
+     * Get a transient node state for a child node state which has
+     * an existing underlying persistent node date.
+     *
+     * @param name  name of the child node state
+     * @return  transient node state or {@code null} if this transient
+     *          node state does not have an underlying persistent state
+     *          or the underlying persistent state does not have a child
+     *          node state with the given {@code name}.
+     */
     private TransientNodeState getExistingChildNode(String name) {
         if (persistentState == null) {
             return null;
         }
 
-        NodeState state = persistentState.getChildNode(name);
-        TransientNodeState transientState = existingChildNodes.get(state);
+        TransientNodeState transientState = existingChildNodes.get(name);
         if (transientState == null) {
+            NodeState state = persistentState.getChildNode(name);
             transientState = new TransientNodeState(editor, name, state);
-            existingChildNodes.put(state, transientState);
+            existingChildNodes.put(name, transientState);
         }
         return transientState;
     }
-    
+
+    /**
+     * Determine whether there is an underling persistent state which has
+     * a child node state with the given {@code name}.
+     * @param name  name of the child node state.
+     * @return  {@code true} if and only if this transient node state has an
+     *          underlying persistent state which has a child node state with
+     *          the given {@code name}.
+     */
     private boolean hasExistingNode(String name) {
         return persistentState != null && persistentState.getChildNode(name) != null;
     }
 
+    /**
+     * Determine whether there is an underling persistent state which has
+     * a property state with the given {@code name}.
+     * @param name  name of the property state.
+     * @return  {@code true} if and only if this transient node state has an
+     *          underlying persistent state which has a property state with
+     *          the given {@code name}.
+     */
     private boolean hasExistingProperty(String name) {
         return persistentState != null && persistentState.getProperty(name) != null;
     }