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;
}