jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mdue...@apache.org
Subject svn commit: r1225281 - in /jackrabbit/sandbox/jackrabbit-microkernel/src: main/java/org/apache/jackrabbit/ main/java/org/apache/jackrabbit/state/ main/java/org/apache/jackrabbit/utils/ test/java/org/apache/jackrabbit/state/
Date Wed, 28 Dec 2011 18:54:56 GMT
Author: mduerig
Date: Wed Dec 28 18:54:55 2011
New Revision: 1225281

URL: http://svn.apache.org/viewvc?rev=1225281&view=rev
Log:
Microkernel based prototype of JCR implementation (WIP)
- re-implement ItemImpl, NodeImpl, PropertyImpl based on a NodeState class

Added:
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeState.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ItemNameMatcher.java   (contents, props changed)
      - copied, changed from r1224982, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ChildItemCollector.java
Removed:
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ChildItemCollector.java
Modified:
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/ItemImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/NodeImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/Path.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/PropertyImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/ChangeTree.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/TransientSpace.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/Predicates.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/state/TransientSpaceTest.java

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/ItemImpl.java?rev=1225281&r1=1225280&r2=1225281&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/ItemImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/ItemImpl.java Wed Dec 28 18:54:55 2011
@@ -20,63 +20,18 @@
 package org.apache.jackrabbit;
 
 import org.apache.jackrabbit.SessionImpl.Context;
-import org.apache.jackrabbit.state.ChangeTree.NodeDelta;
 
 import javax.jcr.Item;
-import javax.jcr.ItemNotFoundException;
 import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.UnsupportedRepositoryOperationException;
 
 abstract class ItemImpl implements Item {
     protected final Context sessionContext;
-    protected final Path path;
 
-    protected String revision;
-
-    protected ItemImpl(Context sessionContext, Path path) {
+    protected ItemImpl(Context sessionContext) {
         this.sessionContext = sessionContext;
-        this.path = path;
-        revision = sessionContext.getRevision();
-    }
-
-    @Override
-    public String getPath() throws RepositoryException {
-        return path.getJcrPath();
-    }
-
-    @Override
-    public String getName() throws RepositoryException {
-        return path.getName();
-    }
-
-    @Override
-    public Item getAncestor(int depth) throws RepositoryException {
-        Path parent = path.getAncestor(depth);
-        if (parent == null) {
-            throw new ItemNotFoundException("No ancestor of this depth");
-        }
-        
-        return NodeImpl.create(sessionContext, parent);
-    }
-
-    @Override
-    public Node getParent() throws RepositoryException {
-        Path parent = path.getParent();
-        if (parent == null) {
-            throw new ItemNotFoundException("Root has no parent");
-        }
-
-        else {
-            return NodeImpl.create(sessionContext, parent);
-        }
-    }
-
-    @Override
-    public int getDepth() throws RepositoryException {
-        return path.getDepth();
     }
 
     @Override
@@ -85,28 +40,6 @@ abstract class ItemImpl implements Item 
     }
 
     @Override
-    public boolean isNew() {
-        try {
-            return getNodeDelta().isTransient();
-        }
-        catch (PathNotFoundException e) {
-            // should never happen
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
-    public boolean isModified() {
-        try {
-            return getNodeDelta().hasChanges();
-        }
-        catch (PathNotFoundException e) {
-            // should never happen
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
     public boolean isSame(Item otherItem) throws RepositoryException {
         // Shortcut
         if (this == otherItem) {
@@ -149,14 +82,4 @@ abstract class ItemImpl implements Item 
         throw new UnsupportedRepositoryOperationException("Use Session#refresh");
     }
 
-    //------------------------------------------< internal >---
-
-    protected final boolean isStale() {
-        return !sessionContext.getRevision().equals(revision);
-    }
-
-    protected final NodeDelta getNodeDelta() throws PathNotFoundException {
-        return sessionContext.getTransientSpace().getNode(path);
-    }
-
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/NodeImpl.java?rev=1225281&r1=1225280&r2=1225281&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/NodeImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/NodeImpl.java Wed Dec 28 18:54:55 2011
@@ -20,26 +20,21 @@
 package org.apache.jackrabbit;
 
 import org.apache.jackrabbit.SessionImpl.Context;
-import org.apache.jackrabbit.json.FullJsonParser;
 import org.apache.jackrabbit.json.JsonValue;
-import org.apache.jackrabbit.json.JsonValue.JsonObject;
-import org.apache.jackrabbit.json.JsonValue.Type;
-import org.apache.jackrabbit.json.UnescapingJsonTokenizer;
-import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.json.JsonValue.JsonAtom;
 import org.apache.jackrabbit.spi.commons.iterator.Iterators;
+import org.apache.jackrabbit.spi.commons.iterator.Predicate;
 import org.apache.jackrabbit.spi.commons.iterator.Transformer;
-import org.apache.jackrabbit.state.ChangeTree.NodeDelta;
-import org.apache.jackrabbit.state.TransientSpace;
-import org.apache.jackrabbit.utils.Arrays;
-import org.apache.jackrabbit.utils.ChildItemCollector;
+import org.apache.jackrabbit.state.NodeState;
+import org.apache.jackrabbit.utils.ItemNameMatcher;
 import org.apache.jackrabbit.utils.NodeIteratorAdapter;
 import org.apache.jackrabbit.utils.PropertyIteratorAdapter;
 import org.apache.jackrabbit.utils.ValueConverter;
 
 import javax.jcr.Binary;
-import javax.jcr.InvalidItemStateException;
 import javax.jcr.Item;
 import javax.jcr.ItemExistsException;
+import javax.jcr.ItemNotFoundException;
 import javax.jcr.ItemVisitor;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
@@ -63,27 +58,76 @@ import java.util.Iterator;
 import java.util.Map.Entry;
 
 public class NodeImpl extends ItemImpl implements Node {
-    private JsonObject node;
+    private final NodeState nodeState;
 
     static boolean exist(Context sessionContext, Path path) {
-        return sessionContext.getTransientSpace().nodeExists(path);
+        return NodeState.hasNodeState(sessionContext.getTransientSpace(), path);
     }
 
-    static Node create(Context sessionContext, Path path) throws RepositoryException {
-        JsonObject node = getNode(sessionContext, path);
-        return new NodeImpl(sessionContext, path, node);
+    static Node create(Context sessionContext, Path path) throws PathNotFoundException {
+        NodeState nodeState = getNodeState(sessionContext, path);
+        return new NodeImpl(sessionContext, nodeState);
     }
 
-    static Node create(Context sessionContext, Path path, JsonObject node) {
-        return new NodeImpl(sessionContext, path, node);
+    static Node create(Context sessionContext, NodeState nodeState) {
+        return new NodeImpl(sessionContext, nodeState);
     }
 
-    private NodeImpl(Context sessionContext, Path path, JsonObject node) {
-        super(sessionContext, path);
-        this.node = node;
+    private NodeImpl(Context sessionContext, NodeState nodeState) {
+        super(sessionContext);
+        this.nodeState = nodeState;
     }
 
-    //------------------------------------------< Node >---
+    //------------------------------------------< Item/Node >---
+
+    @Override
+    public String getPath() throws RepositoryException {
+        return path().toJcrPath();
+    }
+
+    @Override
+    public String getName() throws RepositoryException {
+        return path().getName();
+    }
+
+    @Override
+    public Item getAncestor(int depth) throws RepositoryException {
+        Path parent = path().getAncestor(depth);
+        if (parent == null) {
+            throw new ItemNotFoundException(path().toJcrPath() + "has no ancestor of depth " + depth);
+        }
+
+        return create(sessionContext, parent);
+    }
+
+    @Override
+    public Node getParent() throws RepositoryException {
+        if (nodeState.isRoot()) {
+            throw new ItemNotFoundException("Root has no parent");
+        }
+
+        return create(sessionContext, path().getParent());
+    }
+
+    @Override
+    public int getDepth() throws RepositoryException {
+        return path().getDepth();
+    }
+
+    @Override
+    public boolean isNode() {
+        return true;
+    }
+
+    @Override
+    public boolean isNew() {
+        return nodeState.isNew();
+    }
+
+    @Override
+    public boolean isModified() {
+        return nodeState.isModified();
+    }
 
     @Override
     public Node addNode(String relPath) throws RepositoryException {
@@ -91,10 +135,10 @@ public class NodeImpl extends ItemImpl i
             throw new ItemExistsException(relPath);
         }
 
-        TransientSpace transientSpace = sessionContext.getTransientSpace();
-        Path newPath = path.concat(relPath);
-        transientSpace.getNode(newPath.getParent()).addNode(newPath.getName());
-        return getNode(relPath);
+        Path newPath = path().concat(relPath);
+        NodeState parentState = getNodeState(sessionContext, newPath.getParent());
+        NodeState childState = parentState.addNode(newPath.getName());
+        return create(sessionContext, childState);
     }
 
     @Override
@@ -103,57 +147,45 @@ public class NodeImpl extends ItemImpl i
             throw new ItemExistsException(relPath);
         }
 
-        TransientSpace transientSpace = sessionContext.getTransientSpace();
-        Path newPath = path.concat(relPath);
-        transientSpace.getNode(newPath.getParent()).addNode(newPath.getName());
-        setPrimaryType(primaryNodeTypeName);
-        return getNode(relPath);
+        Node childNode = addNode(relPath);
+        childNode.setPrimaryType(primaryNodeTypeName);
+        return childNode;
     }
 
     @Override
     public void remove() throws RepositoryException {
-        TransientSpace transientSpace = sessionContext.getTransientSpace();
-        transientSpace.getNode(path.getParent()).removeNode(path.getName());
+        nodeState.remove();
     }
 
     @Override
     public Property setProperty(String name, Value value, int type) throws RepositoryException {
-        TransientSpace transientSpace = sessionContext.getTransientSpace();
-        transientSpace.getNode(path).setValue(name, ValueConverter.toJsonValue(value));
+        nodeState.setProperty(name, ValueConverter.toJsonValue(value));
         return getProperty(name);
     }
 
     @Override
     public Property setProperty(String name, Value[] values, int type) throws RepositoryException {
-        TransientSpace transientSpace = sessionContext.getTransientSpace();
-        transientSpace.getNode(path).setValue(name, ValueConverter.toJsonValue(values));
+        nodeState.setProperty(name, ValueConverter.toJsonValue(values));
         return getProperty(name);
     }
 
     @Override
-    public void addMixin(String mixinName) throws RepositoryException {
-        TransientSpace transientSpace = sessionContext.getTransientSpace();
-        ValueFactory valueFactory = sessionContext.getValueFactory();
-        Value value = valueFactory.createValue(mixinName);
-        Value[] values = getProperty("jcr:mixinTypes").getValues();
-        transientSpace.getNode(path).setValue("jcr:mixinTypes", ValueConverter.toJsonValue(Arrays.add(values, value)));
+    public void setPrimaryType(String nodeTypeName) throws RepositoryException {
+        nodeState.setProperty("jcr:primaryType", JsonAtom.string(nodeTypeName));
     }
 
     @Override
-    public void removeMixin(String mixinName) throws RepositoryException {
-        TransientSpace transientSpace = sessionContext.getTransientSpace();
-        ValueFactory valueFactory = sessionContext.getValueFactory();
-        Value value = valueFactory.createValue(mixinName);
-        Value[] values = getProperty("jcr:mixinTypes").getValues();
-        transientSpace.getNode(path).setValue("jcr:mixinTypes", ValueConverter.toJsonValue(Arrays.remove(values, value)));
+    public void addMixin(String mixinName) throws RepositoryException {
+        JsonValue mixins = nodeState.getPropertyValue("jcr:mixinTypes");
+        mixins.asArray().add(JsonAtom.string(mixinName));
+        nodeState.setProperty("jcr:mixinTypes", mixins);
     }
 
     @Override
-    public void setPrimaryType(String nodeTypeName) throws RepositoryException {
-        TransientSpace transientSpace = sessionContext.getTransientSpace();
-        ValueFactory valueFactory = sessionContext.getValueFactory();
-        Value value = valueFactory.createValue(nodeTypeName);
-        transientSpace.getNode(path).setValue("jcr:primaryType", ValueConverter.toJsonValue(value));
+    public void removeMixin(String mixinName) throws RepositoryException {
+        JsonValue mixins = nodeState.getPropertyValue("jcr:mixinTypes");
+        mixins.asArray().remove(JsonAtom.string(mixinName));
+        nodeState.setProperty("jcr:mixinTypes", mixins);
     }
 
     
@@ -258,149 +290,95 @@ public class NodeImpl extends ItemImpl i
 
     @Override
     public boolean hasNode(String relPath) throws RepositoryException {
-        return sessionContext.getSession().nodeExists(path.concat(relPath));
+        return exist(sessionContext, path().concat(relPath));
     }
 
     @Override
     public Node getNode(String relPath) throws RepositoryException {
-        return create(sessionContext, path.concat(relPath));
+        return create(sessionContext, path().concat(relPath));
     }
 
     @Override
     public boolean hasNodes() throws RepositoryException {
-        return getNodes().hasNext();
+        return nodeState.hasChildNodeStates();
     }
 
     @Override
     public NodeIterator getNodes() throws RepositoryException {
-        Iterator<Entry<String, JsonValue>> persistedItems = getPersistedItems(this);
-        Iterator<Entry<String, JsonValue>> addedNodes = getAddedNodes(getNodeDelta());
-        Iterator<Entry<String, JsonValue>> childItems = Iterators.iteratorChain(persistedItems, addedNodes);
-
-        return new NodeIteratorAdapter(new ChildItemCollector<Node>(childItems) {
-            @Override
-            protected boolean include(String name, JsonValue value) {
-                return value.type() == Type.OBJECT;
-            }
-
-            @Override
-            protected Node createItem(String name, JsonValue value) {
-                return NodeImpl.create(sessionContext, path.concat(name), value.asObject());
-            }
-        }.iterator());
+        Iterator<NodeState> childNodeStates = nodeState.getChildNodeStates();
+        return new NodeIteratorAdapter(nodeIterator(childNodeStates));
     }
 
     @Override
     public NodeIterator getNodes(final String namePattern) throws RepositoryException {
-        Iterator<Entry<String, JsonValue>> persistedItems = getPersistedItems(this);
-        Iterator<Entry<String, JsonValue>> addedNodes = getAddedNodes(getNodeDelta());
-        Iterator<Entry<String, JsonValue>> childItems = Iterators.iteratorChain(persistedItems, addedNodes);
-
-        return new NodeIteratorAdapter(new ChildItemCollector<Node>(childItems) {
+        Iterator<NodeState> childNodeStates = nodeState.getChildNodeStates(new Predicate<NodeState>() {
             @Override
-            protected boolean include(String name, JsonValue value) {
-                return value.type() == Type.OBJECT && ChildItemCollector.matches(name, namePattern);
+            public boolean evaluate(NodeState nodeState) {
+                return ItemNameMatcher.matches(nodeState.getName(), namePattern);
             }
+        });
 
-            @Override
-            protected Node createItem(String name, JsonValue value) {
-                return NodeImpl.create(sessionContext, path.concat(name), value.asObject());
-            }
-        }.iterator());
+        return new NodeIteratorAdapter(nodeIterator(childNodeStates));
     }
 
     @Override
     public NodeIterator getNodes(final String[] nameGlobs) throws RepositoryException {
-        Iterator<Entry<String, JsonValue>> persistedItems = getPersistedItems(this);
-        Iterator<Entry<String, JsonValue>> addedNodes = getAddedNodes(getNodeDelta());
-        Iterator<Entry<String, JsonValue>> childItems = Iterators.iteratorChain(persistedItems, addedNodes);
-
-        return new NodeIteratorAdapter(new ChildItemCollector<Node>(childItems) {
+        Iterator<NodeState> childNodeStates = nodeState.getChildNodeStates(new Predicate<NodeState>() {
             @Override
-            protected boolean include(String name, JsonValue value) {
-                return value.type() == Type.OBJECT && ChildItemCollector.matches(name, nameGlobs);
+            public boolean evaluate(NodeState nodeState) {
+                return ItemNameMatcher.matches(nodeState.getName(), nameGlobs);
             }
+        });
 
-            @Override
-            protected Node createItem(String name, JsonValue value) {
-                return NodeImpl.create(sessionContext, path.concat(name), value.asObject());
-            }
-        }.iterator());
+        return new NodeIteratorAdapter(nodeIterator(childNodeStates));
     }
 
     @Override
     public boolean hasProperty(String relPath) throws RepositoryException {
-        return sessionContext.getSession().propertyExists(path.concat(relPath));
+        return PropertyImpl.exist(sessionContext, path().concat(relPath));
     }
 
     @Override
     public Property getProperty(String relPath) throws RepositoryException {
-        return PropertyImpl.create(sessionContext, path.concat(relPath));
+        return PropertyImpl.create(sessionContext, path().concat(relPath));
     }
 
     @Override
     public boolean hasProperties() throws RepositoryException {
-        return getProperties().hasNext();
+        return nodeState.hasProperties();
     }
 
     @Override
     public PropertyIterator getProperties() throws RepositoryException {
-        Iterator<Entry<String, JsonValue>> persistedItems = getPersistedItems(this);
-        Iterator<Entry<String, JsonValue>> addedProperties = getProperties(getNodeDelta());
-        Iterator<Entry<String, JsonValue>> childItems = Iterators.iteratorChain(persistedItems, addedProperties);
-
-        return new PropertyIteratorAdapter(new ChildItemCollector<Property>(childItems){
-            @Override
-            protected boolean include(String name, JsonValue value) {
-                return !name.startsWith(":") && value.type() != Type.OBJECT;
-            }
-
-            @Override
-            protected Property createItem(String name, JsonValue value) {
-                return PropertyImpl.create(sessionContext, path.concat(name), value);
-            }
-        }.iterator());
+        Iterator<Entry<String,JsonValue>> properties = nodeState.getProperties();
+        return new PropertyIteratorAdapter(propertyIterator(properties));
     }
 
     @Override
     public PropertyIterator getProperties(final String namePattern) throws RepositoryException {
-        Iterator<Entry<String, JsonValue>> persistedItems = getPersistedItems(this);
-        Iterator<Entry<String, JsonValue>> addedProperties = getProperties(getNodeDelta());
-        Iterator<Entry<String, JsonValue>> childItems = Iterators.iteratorChain(persistedItems, addedProperties);
-
-        return new PropertyIteratorAdapter(new ChildItemCollector<Property>(childItems){
-            @Override
-            protected boolean include(String name, JsonValue value) {
-                return !name.startsWith(":") && value.type() != Type.OBJECT
-                    && ChildItemCollector.matches(name, namePattern);
-            }
+        Iterator<Entry<String, JsonValue>> properties = nodeState.getProperties(
+            new Predicate<Entry<String, JsonValue>>() {
+                @Override
+                public boolean evaluate(Entry<String, JsonValue> entry) {
+                    return ItemNameMatcher.matches(entry.getKey(), namePattern);
+                }
+        });
 
-            @Override
-            protected Property createItem(String name, JsonValue value) {
-                return PropertyImpl.create(sessionContext, path.concat(name), value);
-            }
-        }.iterator());
+        return new PropertyIteratorAdapter(propertyIterator(properties));
     }
 
     @Override
     public PropertyIterator getProperties(final String[] nameGlobs) throws RepositoryException {
-        Iterator<Entry<String, JsonValue>> persistedItems = getPersistedItems(this);
-        Iterator<Entry<String, JsonValue>> addedProperties = getProperties(getNodeDelta());
-        Iterator<Entry<String, JsonValue>> childItems = Iterators.iteratorChain(persistedItems, addedProperties);
-
-        return new PropertyIteratorAdapter(new ChildItemCollector<Property>(childItems){
-            @Override
-            protected boolean include(String name, JsonValue value) {
-                return !name.startsWith(":") && value.type() != Type.OBJECT
-                    && ChildItemCollector.matches(name, nameGlobs);
-            }
+        Iterator<Entry<String, JsonValue>> propertyNames = nodeState.getProperties(
+                new Predicate<Entry<String, JsonValue>>() {
+                    @Override
+                    public boolean evaluate(Entry<String, JsonValue> entry) {
+                        return ItemNameMatcher.matches(entry.getKey(), nameGlobs);
+                    }
+                });
 
-            @Override
-            protected Property createItem(String name, JsonValue value) {
-                return PropertyImpl.create(sessionContext, path.concat(name), value);
-            }
-        }.iterator());
-    }
+        return new PropertyIteratorAdapter(propertyIterator(propertyNames));
+}
 
     @Override
     public Item getPrimaryItem() throws RepositoryException {
@@ -416,7 +394,7 @@ public class NodeImpl extends ItemImpl i
 
     @Override
     public String getIdentifier() throws RepositoryException {
-        return path.getMkPath();
+        return path().toMkPath();
         // todo implement getIdentifier
     }
 
@@ -601,79 +579,35 @@ public class NodeImpl extends ItemImpl i
     }
 
     @Override
-    public boolean isNode() {
-        return true;
-    }
-
-    @Override
     public void accept(ItemVisitor visitor) throws RepositoryException {
         visitor.visit(this);
     }
 
     //------------------------------------------< private >---
 
-    private JsonObject getNode() throws InvalidItemStateException {
-        if (isStale() || node.isEmpty() ) {
-            try {
-                node = getNode(sessionContext, path);
-                revision = sessionContext.getRevision();
-            }
-            catch (PathNotFoundException e) {
-                throw new InvalidItemStateException(path.getJcrPath(), e);
-            }
-        }
-        return node;
+    private static NodeState getNodeState(Context sessionContext, Path path) throws PathNotFoundException {
+        return NodeState.getNodeState(sessionContext, path);
     }
 
-    private static JsonObject getNode(Context sessionContext, Path path) throws PathNotFoundException {
-        NodeDelta delta = sessionContext.getTransientSpace().getNode(path);
-
-        Path persistedPath = delta.getPersistentPath();
-        if (persistedPath == null) {
-            return JsonObject.EMPTY;
-        }
-
-        MicroKernel microkernel = sessionContext.getMicrokernel();
-        String revision = sessionContext.getRevision();
-        String nodeJson = microkernel.getNodes(persistedPath.getMkPath(), revision, 0, 0, -1);
-        return FullJsonParser.parseObject(new UnescapingJsonTokenizer(nodeJson));
+    private Path path() {
+        return nodeState.getPath();
     }
 
-    private static Iterator<Entry<String, JsonValue>> getPersistedItems(NodeImpl node)
-            throws InvalidItemStateException {
-
-        return node.getNode().value().entrySet().iterator();
-    }
-
-    private static Iterator<Entry<String, JsonValue>> getAddedNodes(NodeDelta delta) {
-        return Iterators.transformIterator(delta.getNodes(),
-                new Transformer<Entry<String, NodeDelta>, Entry<String, JsonValue>>() {
-
-                    @Override
-                    public Entry<String, JsonValue> transform(final Entry<String, NodeDelta> entry) {
-                        return new Entry<String, JsonValue>() {
-                            @Override
-                            public String getKey() {
-                                return entry.getKey();
-                            }
-
-                            @Override
-                            public JsonValue getValue() {
-                                return JsonObject.EMPTY;
-                            }
-
-                            @Override
-                            public JsonValue setValue(JsonValue value) {
-                                assert false;
-                                return null;
-                            }
-                        };
-                    }
-                });
+    private Iterator<Node> nodeIterator(Iterator<NodeState> childNodeStates) {
+        return Iterators.transformIterator(childNodeStates, new Transformer<NodeState, Node>() {
+            @Override
+            public Node transform(NodeState nodeState) {
+                return NodeImpl.create(sessionContext, nodeState);
+            }
+        });
     }
 
-    private static Iterator<Entry<String, JsonValue>> getProperties(NodeDelta delta) {
-        return delta.getProperties();
+    private Iterator<Property> propertyIterator(Iterator<Entry<String, JsonValue>> properties) {
+        return Iterators.transformIterator(properties, new Transformer<Entry<String, JsonValue>, Property>() {
+            @Override
+            public Property transform(Entry<String, JsonValue> entry) {
+                return PropertyImpl.create(sessionContext, nodeState, entry.getKey(), entry.getValue());
+            }
+        });
     }
-
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/Path.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/Path.java?rev=1225281&r1=1225280&r2=1225281&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/Path.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/Path.java Wed Dec 28 18:54:55 2011
@@ -54,11 +54,11 @@ public final class Path {
         return workspace;
     }
 
-    public String getJcrPath() {
+    public String toJcrPath() {
         return jcrPath;
     }
 
-    public String getMkPath() {
+    public String toMkPath() {
         return buildMkPath(workspace, jcrPath);
     }
 

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/PropertyImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/PropertyImpl.java?rev=1225281&r1=1225280&r2=1225281&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/PropertyImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/PropertyImpl.java Wed Dec 28 18:54:55 2011
@@ -20,18 +20,14 @@
 package org.apache.jackrabbit;
 
 import org.apache.jackrabbit.SessionImpl.Context;
-import org.apache.jackrabbit.json.FullJsonParser;
 import org.apache.jackrabbit.json.JsonValue;
-import org.apache.jackrabbit.json.JsonValue.JsonObject;
 import org.apache.jackrabbit.json.JsonValue.Type;
-import org.apache.jackrabbit.json.UnescapingJsonTokenizer;
-import org.apache.jackrabbit.mk.api.MicroKernel;
-import org.apache.jackrabbit.state.ChangeTree.NodeDelta;
-import org.apache.jackrabbit.state.TransientSpace;
+import org.apache.jackrabbit.state.NodeState;
 import org.apache.jackrabbit.utils.ValueConverter;
 
 import javax.jcr.Binary;
-import javax.jcr.InvalidItemStateException;
+import javax.jcr.Item;
+import javax.jcr.ItemNotFoundException;
 import javax.jcr.ItemVisitor;
 import javax.jcr.Node;
 import javax.jcr.PathNotFoundException;
@@ -48,47 +44,117 @@ import java.math.BigDecimal;
 import java.util.Calendar;
 
 public class PropertyImpl extends ItemImpl implements Property {
-    private JsonValue value;
+    private final NodeState parentState;
+    private final String name;
+    private final JsonValue value;
 
     public static boolean exist(Context sessionContext, Path path) {
         try {
-            return getProperty(sessionContext, path) != null;
+            NodeState parentState = NodeState.getNodeState(sessionContext, path.getParent());
+            
+            return parentState.hasProperty(path.getName());
         }
         catch (PathNotFoundException e) {
+            // fixme don't use exception handling for flow control.
             return false;
         }
     }
 
-    static Property create(Context sessionContext, Path path) throws RepositoryException {
-        JsonValue value = getProperty(sessionContext, path);
-        return new PropertyImpl(sessionContext, path, value);
+    static Property create(Context sessionContext, Path path) throws PathNotFoundException,
+            ItemNotFoundException {
+
+        NodeState parentState = NodeState.getNodeState(sessionContext, path.getParent());
+
+        String name = path.getName();
+        JsonValue value = parentState.getPropertyValue(name);
+        return new PropertyImpl(sessionContext, parentState, name, value);
     }
 
-    static Property create(Context sessionContext, Path path, JsonValue value) {
-        return new PropertyImpl(sessionContext, path, value);
+    static Property create(Context sessionContext, NodeState parentState, String name, JsonValue value) {
+        return new PropertyImpl(sessionContext, parentState, name, value);
     }
 
-    private PropertyImpl(Context sessionContext, Path path, JsonValue value) {
-        super(sessionContext, path);
+    private PropertyImpl(Context sessionContext, NodeState parentState, String name, JsonValue value) {
+        super(sessionContext);
+        this.parentState = parentState;
+        this.name = name;
         this.value = value;
     }
 
+    //------------------------------------------< Item/Property >---
+
+    @Override
+    public String getPath() throws RepositoryException {
+        return parentState.getPath().concat(name).toJcrPath();
+    }
+
+    @Override
+    public String getName() throws RepositoryException {
+        return name;
+    }
+
+    @Override
+    public Item getAncestor(int depth) throws RepositoryException {
+        if (depth == getDepth() - 1) {
+            return getParent();
+        }
+        else {
+            return getParent().getAncestor(depth);
+        }
+    }
+
+    @Override
+    public Node getParent() throws RepositoryException {
+        return NodeImpl.create(sessionContext, parentState);
+    }
+
+    @Override
+    public int getDepth() throws RepositoryException {
+        return parentState.getPath().getDepth() + 1;
+    }
+
+    @Override
+    public boolean isNode() {
+        return false;
+    }
+
+    @Override
+    public boolean isNew() {
+        return parentState.isPropertyNew(name);
+    }
+
+    @Override
+    public boolean isModified() {
+        return parentState.isPropertyModified(name);
+    }
+
+    @Override
+    public void accept(ItemVisitor visitor) throws RepositoryException {
+        visitor.visit(this);
+    }
+
     @Override
     public void remove() throws RepositoryException {
-        setValue((Value) null);
+        parentState.removeProperty(name);
     }
 
     @Override
     public void setValue(Value value) throws RepositoryException {
-        TransientSpace transientSpace = sessionContext.getTransientSpace();
-        transientSpace.getNode(path.getParent()).setValue(path.getName(),
-                value == null ? null : ValueConverter.toJsonValue(value));
+        if (value == null) {
+            remove();
+        }
+        else {
+            parentState.setProperty(name, ValueConverter.toJsonValue(value));
+        }
     }
 
     @Override
     public void setValue(Value[] values) throws RepositoryException {
-        TransientSpace transientSpace = sessionContext.getTransientSpace();
-        transientSpace.getNode(path.getParent()).setValue(path.getName(), ValueConverter.toJsonValue(values));
+        int type = values.length == 0
+            ? PropertyType.STRING
+            : values[0].getType();
+
+        parentState.setProperty(name, ValueConverter.toJsonValue(values));
     }
 
     @Override
@@ -114,14 +180,24 @@ public class PropertyImpl extends ItemIm
 
     @Override
     public void setValue(InputStream value) throws RepositoryException {
-        ValueFactory valueFactory = sessionContext.getValueFactory();
-        setValue(valueFactory.createValue(value));
+        if (value == null) {
+            remove();
+        }
+        else {
+            ValueFactory valueFactory = sessionContext.getValueFactory();
+            setValue(valueFactory.createValue(value));
+        }
     }
 
     @Override
     public void setValue(Binary value) throws RepositoryException {
-        ValueFactory valueFactory = sessionContext.getValueFactory();
-        setValue(valueFactory.createValue(value));
+        if (value == null) {
+            remove();
+        }
+        else {
+            ValueFactory valueFactory = sessionContext.getValueFactory();
+            setValue(valueFactory.createValue(value));
+        }
     }
 
     @Override
@@ -138,14 +214,24 @@ public class PropertyImpl extends ItemIm
 
     @Override
     public void setValue(BigDecimal value) throws RepositoryException {
-        ValueFactory valueFactory = sessionContext.getValueFactory();
-        setValue(valueFactory.createValue(value));
+        if (value == null) {
+            remove();
+        }
+        else {
+            ValueFactory valueFactory = sessionContext.getValueFactory();
+            setValue(valueFactory.createValue(value));
+        }
     }
 
     @Override
     public void setValue(Calendar value) throws RepositoryException {
-        ValueFactory valueFactory = sessionContext.getValueFactory();
-        setValue(valueFactory.createValue(value));
+        if (value == null) {
+            remove();
+        }
+        else {
+            ValueFactory valueFactory = sessionContext.getValueFactory();
+            setValue(valueFactory.createValue(value));
+        }
     }
 
     @Override
@@ -156,30 +242,33 @@ public class PropertyImpl extends ItemIm
 
     @Override
     public void setValue(Node value) throws RepositoryException {
-        ValueFactory valueFactory = sessionContext.getValueFactory();
-        setValue(valueFactory.createValue(value));
+        if (value == null) {
+            remove();
+        }
+        else {
+            ValueFactory valueFactory = sessionContext.getValueFactory();
+            setValue(valueFactory.createValue(value));
+        }
     }
 
     @Override
     public Value getValue() throws RepositoryException {
-        JsonValue jsonValue = resolve();
-        if (jsonValue.type().compound()) {
-            throw new ValueFormatException(jsonValue.toJson());
+        if (value.type().compound()) {
+            throw new ValueFormatException(value.toJson());
         }
 
         ValueFactory valueFactory = sessionContext.getValueFactory();
-        return ValueConverter.toValue(valueFactory, jsonValue.asAtom());
+        return ValueConverter.toValue(valueFactory, value.asAtom());
     }
 
     @Override
     public Value[] getValues() throws RepositoryException {
-        JsonValue jsonValue = resolve();
-        if (jsonValue.type() != Type.ARRAY) {
-            throw new ValueFormatException(jsonValue.toJson());
+        if (value.type() != Type.ARRAY) {
+            throw new ValueFormatException(value.toJson());
         }
 
         ValueFactory valueFactory = sessionContext.getValueFactory();
-        return ValueConverter.toValue(valueFactory, jsonValue.asArray());
+        return ValueConverter.toValue(valueFactory, value.asArray());
     }
 
     @Override
@@ -286,58 +375,7 @@ public class PropertyImpl extends ItemIm
 
     @Override
     public boolean isMultiple() throws RepositoryException {
-        return resolve().type() == JsonValue.Type.ARRAY;
-    }
-
-    @Override
-    public boolean isNode() {
-        return false; 
-    }
-
-    @Override
-    public void accept(ItemVisitor visitor) throws RepositoryException {
-        visitor.visit(this);
-    }
-
-    //------------------------------------------< private >---
-
-    private JsonValue resolve() throws InvalidItemStateException {
-        if (isStale()) {
-            try {
-                value = getProperty(sessionContext, path);
-                revision = sessionContext.getRevision();
-            }
-            catch (PathNotFoundException e) {
-                throw new InvalidItemStateException(path.getJcrPath(), e);
-            }
-        }
-        return value;
-    }
-
-    private static JsonValue getProperty(Context sessionContext, Path path) throws PathNotFoundException {
-        NodeDelta delta = sessionContext.getTransientSpace().getNode(path.getParent());
-
-        String name = path.getName();
-        if (delta.hasProperty(name)) {
-            return delta.getProperty(name);
-        }
-
-        Path persistedPath = delta.getPersistentPath();
-        if (persistedPath == null) {
-            return null;
-        }
-
-        MicroKernel microkernel = sessionContext.getMicrokernel();
-        String revision = sessionContext.getRevision();
-        String nodeJson = microkernel.getNodes(persistedPath.getMkPath(), revision, 0, 0, -1);
-        JsonObject node = FullJsonParser.parseObject(new UnescapingJsonTokenizer(nodeJson));
-        JsonValue jsonValue = node.value().get(name);
-        if (jsonValue == null) {
-            throw new PathNotFoundException(path.getJcrPath());
-        }
-        else {
-            return jsonValue;
-        }
+        return value.type() == JsonValue.Type.ARRAY;
     }
 
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionImpl.java?rev=1225281&r1=1225280&r2=1225281&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionImpl.java Wed Dec 28 18:54:55 2011
@@ -56,7 +56,7 @@ public class SessionImpl implements Sess
     private String revision;
     private boolean live = true;
 
-    interface Context extends SessionContext<SessionImpl>{}
+    public interface Context extends SessionContext<SessionImpl>{}
 
     private final Context sessionContext = new Context() {
         @Override
@@ -208,7 +208,8 @@ public class SessionImpl implements Sess
 
     @Override
     public boolean nodeExists(String absPath) throws RepositoryException {
-        return nodeExists(Path.create(workspaceName, absPath));
+        Path path = Path.create(workspaceName, absPath);
+        return path.isRoot() || NodeImpl.exist(sessionContext, path);
     }
 
     @Override
@@ -222,7 +223,8 @@ public class SessionImpl implements Sess
 
     @Override
     public boolean propertyExists(String absPath) throws RepositoryException {
-        return propertyExists(Path.create(workspaceName, absPath));
+        Path path = Path.create(workspaceName, absPath);
+        return !path.isRoot() && PropertyImpl.exist(sessionContext, path);
     }
 
     @Override
@@ -415,16 +417,6 @@ public class SessionImpl implements Sess
         throw new UnsupportedRepositoryOperationException("getRetentionManager");
     }
 
-    //------------------------------------------< internal >---
-
-    boolean nodeExists(Path absPath) throws RepositoryException {
-        return absPath.isRoot() || NodeImpl.exist(sessionContext, absPath);
-    }
-
-    boolean propertyExists(Path absPath) throws RepositoryException {
-        return !absPath.isRoot() && PropertyImpl.exist(sessionContext, absPath);
-    }
-
     //------------------------------------------< private >---
 
     private void checkLive() throws RepositoryException {

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/ChangeTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/ChangeTree.java?rev=1225281&r1=1225280&r2=1225281&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/ChangeTree.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/ChangeTree.java Wed Dec 28 18:54:55 2011
@@ -95,7 +95,7 @@ public class ChangeTree {
     public NodeDelta getNode(Path path) throws PathNotFoundException {
         NodeDelta delta = getNodeOrNull(path);
         if (delta == null) {
-            throw new PathNotFoundException(path.getJcrPath());
+            throw new PathNotFoundException(path.toJcrPath());
         }
 
         return delta;
@@ -272,6 +272,13 @@ public class ChangeTree {
         }
 
         /**
+         * @return transient name of this node
+         */
+        public String getName() {
+            return name;
+        }
+
+        /**
          * @return persistent path to this node or {@code null} if this node is neither
          * an {@link org.apache.jackrabbit.state.ChangeTree.Existing existing} node nor a
          * {@link org.apache.jackrabbit.state.ChangeTree.Moved moved} node and this does
@@ -282,6 +289,16 @@ public class ChangeTree {
         }
 
         /**
+         * @return persistent name to this node or {@code null} if this node is neither
+         * an {@link org.apache.jackrabbit.state.ChangeTree.Existing existing} node nor a
+         * {@link org.apache.jackrabbit.state.ChangeTree.Moved moved} node and this does
+         * not have a persistent name.
+         */
+        public String getPersistedName() {
+            return null;
+        }
+
+        /**
          * @return {@code true} iff this is node has been transiently removed. This is
          * either the result of a remove or a move operation.
          */
@@ -330,11 +347,13 @@ public class ChangeTree {
          */
         public abstract NodeDelta getNode(String name);
 
-        public Iterator<Entry<String, NodeDelta>> getNodes() {
-            return Iterators.filterIterator(childNodes.entrySet().iterator(), new Predicate<Entry<String, NodeDelta>>() {
+        /**
+         * @return  Iterator of all added nodes and all nodes moved here.
+         */
+        public Iterator<NodeDelta> getNodes() {
+            return Iterators.filterIterator(childNodes().iterator(), new Predicate<NodeDelta>() {
                 @Override
-                public boolean evaluate(Entry<String, NodeDelta> entry) {
-                    NodeDelta delta = entry.getValue();
+                public boolean evaluate(NodeDelta delta) {
                     return delta.isTransient() && !delta.isRemoved();
                 }
             });
@@ -416,12 +435,12 @@ public class ChangeTree {
             }
 
             if (nodeExists(destination)) {
-                throw new ItemExistsException(destination.getJcrPath());
+                throw new ItemExistsException(destination.toJcrPath());
             }
 
             Path destParentPath = destination.getParent();
             if (!nodeExists(destParentPath)) {
-                throw new PathNotFoundException(destParentPath.getJcrPath());
+                throw new PathNotFoundException(destParentPath.toJcrPath());
             }
 
             if (source.isTransient()) {
@@ -511,6 +530,11 @@ public class ChangeTree {
         }
 
         @Override
+        public String getPersistedName() {
+            return getName();
+        }
+
+        @Override
         public boolean isRemoved() {
             return false;
         }
@@ -631,6 +655,11 @@ public class ChangeTree {
         }
 
         @Override
+        public String getPersistedName() {
+            return source.getPersistedName();
+        }
+
+        @Override
         public boolean isRemoved() {
             return false;
         }

Added: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeState.java?rev=1225281&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeState.java (added)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeState.java Wed Dec 28 18:54:55 2011
@@ -0,0 +1,214 @@
+package org.apache.jackrabbit.state;
+
+import org.apache.jackrabbit.Path;
+import org.apache.jackrabbit.SessionImpl.Context;
+import org.apache.jackrabbit.json.FullJsonParser;
+import org.apache.jackrabbit.json.JsonValue;
+import org.apache.jackrabbit.json.JsonValue.JsonObject;
+import org.apache.jackrabbit.json.JsonValue.Type;
+import org.apache.jackrabbit.json.UnescapingJsonTokenizer;
+import org.apache.jackrabbit.spi.commons.iterator.Iterators;
+import org.apache.jackrabbit.spi.commons.iterator.Predicate;
+import org.apache.jackrabbit.spi.commons.iterator.Transformer;
+import org.apache.jackrabbit.state.ChangeTree.NodeDelta;
+
+import javax.jcr.ItemExistsException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.PathNotFoundException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class NodeState {
+    private final Context sessionContext;
+    private final NodeDelta nodeDelta;
+
+    private String revision;
+    private JsonObject jsonObject;
+
+    private NodeState(Context sessionContext, NodeDelta nodeDelta) {
+        this.sessionContext = sessionContext;
+        this.nodeDelta = nodeDelta;
+    }
+
+    public boolean isRoot() {
+        return getPath().isRoot();
+    }
+
+    public Path getPath() {
+        return nodeDelta.getPath();
+    }
+
+    public String getName() {
+        return getPath().getName();
+    }
+
+    public boolean isNew() {
+        return nodeDelta.isTransient() && !nodeDelta.isRemoved();
+    }
+
+    public boolean isModified() {
+        return nodeDelta.isTransient();
+    }
+
+    public NodeState addNode(String name) throws ItemExistsException {
+        NodeDelta child = nodeDelta.addNode(name);
+        return new NodeState(sessionContext, child);
+    }
+
+    public void remove() throws ItemNotFoundException {
+        nodeDelta.remove();
+    }
+
+    public void setProperty(String name, JsonValue value) {
+        nodeDelta.setValue(name, value);
+    }
+
+    public boolean hasChildNodeStates() {
+        return getChildNodeStates().hasNext();
+    }
+
+    public Iterator<NodeState> getChildNodeStates() {
+        Iterator<NodeState> persisted = Iterators.filterIterator(getPersistedChildNodeStates(),
+            new Predicate<NodeState>() {
+                @Override
+                public boolean evaluate(NodeState nodeState) {
+                    return !nodeDelta.hasChild(nodeState.getName())
+                            || !nodeDelta.getNode(nodeState.getName()).isRemoved();
+                }
+        });
+
+        Iterator<NodeState> added = Iterators.transformIterator(nodeDelta.getNodes(),
+            new Transformer<NodeDelta, NodeState>() {
+                @Override
+                public NodeState transform(NodeDelta delta) {
+                    return new NodeState(sessionContext, nodeDelta);
+                }
+        });
+
+        return Iterators.iteratorChain(added, persisted);
+    }
+
+    public Iterator<NodeState> getChildNodeStates(Predicate<NodeState> condition) {
+        return Iterators.filterIterator(getChildNodeStates(), condition);
+    }
+
+    public boolean hasProperties() {
+        return getProperties().hasNext();
+    }
+
+    public Iterator<Entry<String, JsonValue>> getProperties() {
+        return Iterators.iteratorChain(getPersistedProperties(), nodeDelta.getProperties());
+    }
+
+    public Iterator<Entry<String, JsonValue>> getProperties(Predicate<Entry<String, JsonValue>> condition) {
+        return Iterators.filterIterator(getProperties(), condition);
+    }
+
+    public JsonValue getPropertyValue(String name) throws ItemNotFoundException {
+        JsonValue value = getPropertyValueOrNull(name);
+        if (value == null) {
+            throw new ItemNotFoundException(name);
+        }
+
+        return value;
+    }
+
+    public boolean hasProperty(String name) {
+        return getPropertyValueOrNull(name) != null;
+    }
+
+    public boolean isPropertyNew(String name) {
+        return nodeDelta.getProperty(name) != null && getPersistedPropertyValue(name) == null;
+    }
+
+    public boolean isPropertyModified(String name) {
+        return nodeDelta.getProperty(name) != null;
+    }
+
+    public void removeProperty(String name) {
+        nodeDelta.setValue(name, null);
+    }
+
+    public static NodeState getNodeState(Context sessionContext, Path path)
+            throws PathNotFoundException {
+
+        NodeDelta delta = sessionContext.getTransientSpace().getNode(path);
+        return new NodeState(sessionContext, delta);
+    }
+
+    public static boolean hasNodeState(TransientSpace transientSpace, Path path) {
+        return transientSpace.nodeExists(path);
+    }
+
+    //------------------------------------------< private >---
+
+    private static final Predicate<Entry<String, JsonValue>> IS_NODE = new Predicate<Entry<String, JsonValue>>() {
+        @Override
+        public boolean evaluate(Entry<String, JsonValue> entry) {
+            return isNode(entry.getValue());
+        }
+    };
+
+    private static boolean isNode(JsonValue value) {
+        return value.type() == Type.OBJECT;
+    }
+
+    private Iterator<NodeState> getPersistedChildNodeStates() {
+        Map<String, JsonValue> childEntries = getJsonObject().value();
+        Iterator<Entry<String, JsonValue>> nodeEntries =
+                Iterators.filterIterator(childEntries.entrySet().iterator(), IS_NODE);
+
+        return Iterators.transformIterator(nodeEntries, new Transformer<Entry<String, JsonValue>, NodeState>() {
+            @Override
+            public NodeState transform(Entry<String, JsonValue> entry) {
+                return new NodeState(sessionContext, nodeDelta.getNode(entry.getKey()));
+            }
+        });
+    }
+
+    private Iterator<Entry<String, JsonValue>> getPersistedProperties() {
+        Map<String, JsonValue> childEntries = getJsonObject().value();
+
+        return Iterators.filterIterator(childEntries.entrySet().iterator(),
+            new Predicate<Entry<String, JsonValue>>() {
+                @Override
+                public boolean evaluate(Entry<String, JsonValue> entry) {
+                    return !entry.getKey().startsWith(":") && !isNode(entry.getValue());
+                }
+        });
+    }
+
+    private JsonValue getPropertyValueOrNull(String name) {
+        if (nodeDelta.hasProperty(name)) {
+            JsonValue value = nodeDelta.getProperty(name);
+            if (value != null) {
+                return value;
+            }
+        }
+
+        return getPersistedPropertyValue(name);
+    }    
+
+    private JsonValue getPersistedPropertyValue(String name) {
+        JsonValue value = getJsonObject().get(name);
+        if (value == null) {
+            return null;
+        }
+        else {
+            return isNode(value) ? null : value;
+        }
+    }
+
+    private synchronized JsonObject getJsonObject() {
+        String baseRevision = sessionContext.getRevision();
+        if (jsonObject == null || !revision.equals(baseRevision)) {
+            revision =  baseRevision;
+            String json = sessionContext.getMicrokernel().getNodes(nodeDelta.getPersistentPath().toMkPath(), revision);
+            jsonObject = FullJsonParser.parseObject(new UnescapingJsonTokenizer(json));
+        }
+
+        return jsonObject;
+    }
+
+}

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/TransientSpace.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/TransientSpace.java?rev=1225281&r1=1225280&r2=1225281&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/TransientSpace.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/TransientSpace.java Wed Dec 28 18:54:55 2011
@@ -36,7 +36,7 @@ public class TransientSpace {
         changeTree = new ChangeTree(Path.create(workspace), new Predicate<Path>() {
             @Override
             public boolean evaluate(Path path) {
-                return microkernel.nodeExists(path.getMkPath(), getRevision());
+                return microkernel.nodeExists(path.toMkPath(), getRevision());
             }
         });
     }
@@ -74,30 +74,30 @@ public class TransientSpace {
                 @Override
                 public void addNode(Path path) {
                     jsop.append("+\"")
-                            .append(path.getMkPath())
+                            .append(path.toMkPath())
                             .append("\":{}");
                 }
 
                 @Override
                 public void removeNode(Path path) {
                     jsop.append("-\"")
-                            .append(path.getMkPath())
+                            .append(path.toMkPath())
                             .append('"');
                 }
 
                 @Override
                 public void moveNode(Path sourcePath, Path destinationPath) {
                     jsop.append(">\"")
-                            .append(sourcePath.getMkPath())
+                            .append(sourcePath.toMkPath())
                             .append("\":\"")
-                            .append(destinationPath.getMkPath())
+                            .append(destinationPath.toMkPath())
                             .append('"');
                 }
 
                 @Override
                 public void setProperty(Path path, JsonValue value) {
                     jsop.append("^\"")
-                            .append(path.getMkPath())
+                            .append(path.toMkPath())
                             .append("\":")
                             .append(value.toJson());
                 }
@@ -105,7 +105,7 @@ public class TransientSpace {
                 @Override
                 public void removeProperty(Path path) {
                     jsop.append("^\"")
-                            .append(path.getMkPath())
+                            .append(path.toMkPath())
                             .append("\":null");
                 }
             });

Copied: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ItemNameMatcher.java (from r1224982, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ChildItemCollector.java)
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ItemNameMatcher.java?p2=jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ItemNameMatcher.java&p1=jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ChildItemCollector.java&r1=1224982&r2=1225281&rev=1225281&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ChildItemCollector.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ItemNameMatcher.java Wed Dec 28 18:54:55 2011
@@ -19,51 +19,13 @@
 
 package org.apache.jackrabbit.utils;
 
-import org.apache.jackrabbit.json.JsonValue;
-import org.apache.jackrabbit.spi.commons.iterator.Iterators;
-import org.apache.jackrabbit.spi.commons.iterator.Predicate;
-import org.apache.jackrabbit.spi.commons.iterator.Transformer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.jcr.Item;
-import java.util.Iterator;
-import java.util.Map.Entry;
 import java.util.StringTokenizer;
 
-public abstract class ChildItemCollector<T extends Item> implements Iterable<T> {
-    static final Logger log = LoggerFactory.getLogger(ChildItemCollector.class);
+public final class ItemNameMatcher {
+    private static final char WILDCARD_CHAR = '*';
+    private static final String OR = "|";
 
-    static final char WILDCARD_CHAR = '*';
-    static final String OR = "|";
-
-    private final Iterator<Entry<String, JsonValue>> items;
-
-    protected ChildItemCollector(Iterator<Entry<String, JsonValue>> items) {
-        this.items = items;
-    }
-
-    @Override
-    public Iterator<T> iterator() {
-        return Iterators.transformIterator(
-            Iterators.filterIterator(items,
-                    new Predicate<Entry<String, JsonValue>>() {
-                        @Override
-                        public boolean evaluate(Entry<String, JsonValue> entry) {
-                            return include(entry.getKey(), entry.getValue());
-                        }
-                    }),
-
-            new Transformer<Entry<String, JsonValue>, T>() {
-                @Override
-                public T transform(Entry<String, JsonValue> entry) {
-                    return createItem(entry.getKey(), entry.getValue());
-                }
-            });
-    }
-
-    protected abstract boolean include(String name, JsonValue value);
-    protected abstract T createItem(String name, JsonValue value);
+    private ItemNameMatcher() { }
 
     /**
      * Matches the name pattern against the specified name.
@@ -136,6 +98,8 @@ public abstract class ChildItemCollector
         return false;
     }
 
+    //------------------------------------------< private >---
+
     /**
      * Internal helper used to recursively match the pattern
      *

Propchange: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ItemNameMatcher.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/ItemNameMatcher.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/Predicates.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/Predicates.java?rev=1225281&r1=1225280&r2=1225281&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/Predicates.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/utils/Predicates.java Wed Dec 28 18:54:55 2011
@@ -3,6 +3,8 @@ package org.apache.jackrabbit.utils;
 import org.apache.jackrabbit.spi.commons.iterator.Predicate;
 
 public final class Predicates {
+    public static final Predicate<?> TRUE = constant(true);
+    public static final Predicate<?> FALSE = constant(false);
 
     private Predicates() { }
 
@@ -15,4 +17,14 @@ public final class Predicates {
 
         return false;
     }
+    
+    public static <T> Predicate<T> constant(final boolean value) {
+        return new Predicate<T>() {
+            @Override
+            public boolean evaluate(T any) {
+                return value;
+            }
+        };
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/state/TransientSpaceTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/state/TransientSpaceTest.java?rev=1225281&r1=1225280&r2=1225281&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/state/TransientSpaceTest.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/state/TransientSpaceTest.java Wed Dec 28 18:54:55 2011
@@ -770,7 +770,7 @@ public class TransientSpaceTest {
 
                 @Override
                 public boolean matchesSafely(MicroKernel mk) {
-                    JsonObject node = parseJson(mk.getNodes(path.getParent().getMkPath(), mk.getHeadRevision()));
+                    JsonObject node = parseJson(mk.getNodes(path.getParent().toMkPath(), mk.getHeadRevision()));
                     JsonValue prop = node.get(path.getName());
                     return prop != null && prop.type() == Type.NUMBER
                             && Integer.parseInt(prop.asAtom().value()) == value;
@@ -788,7 +788,7 @@ public class TransientSpaceTest {
 
                 @Override
                 public boolean matchesSafely(MicroKernel mk) {
-                    JsonObject node = parseJson(mk.getNodes(path.getParent().getMkPath(), mk.getHeadRevision()));
+                    JsonObject node = parseJson(mk.getNodes(path.getParent().toMkPath(), mk.getHeadRevision()));
                     JsonValue prop = node.get(path.getName());
                     return prop != null && prop.type() == Type.STRING
                             && prop.asAtom().value().equals(value);
@@ -807,7 +807,7 @@ public class TransientSpaceTest {
                 @Override
                 public boolean matchesSafely(MicroKernel mk) {
                     try {
-                        JsonObject node = parseJson(mk.getNodes(path.getParent().getMkPath(), mk.getHeadRevision()));
+                        JsonObject node = parseJson(mk.getNodes(path.getParent().toMkPath(), mk.getHeadRevision()));
                         JsonValue prop = node.get(path.getName());
                         return prop != null;
                     }



Mime
View raw message