jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mdue...@apache.org
Subject svn commit: r1333010 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel: KernelNodeStateBuilder2.java KernelNodeStore2.java
Date Wed, 02 May 2012 12:09:56 GMT
Author: mduerig
Date: Wed May  2 12:09:55 2012
New Revision: 1333010

URL: http://svn.apache.org/viewvc?rev=1333010&view=rev
Log:
OAK-80: Implement batched writing for KernelNodeStore
Initial implementation. Not wired yet.

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateBuilder2.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore2.java

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateBuilder2.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateBuilder2.java?rev=1333010&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateBuilder2.java
(added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateBuilder2.java
Wed May  2 12:09:55 2012
@@ -0,0 +1,154 @@
+package org.apache.jackrabbit.oak.kernel;
+
+import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.kernel.KernelNodeStore2.NodeStateBuilderContext;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateBuilder;
+
+import java.util.List;
+
+public class KernelNodeStateBuilder2 implements NodeStateBuilder {
+    private final NodeStateBuilderContext context;
+
+    private String path;
+
+    private KernelNodeStateBuilder2(NodeStateBuilderContext context, String path) {
+        this.context = context;
+        this.path = path;
+    }
+
+    public static NodeStateBuilder create(NodeStateBuilderContext context) {
+        return new KernelNodeStateBuilder2(context, "");
+    }
+
+
+    @Override
+    public NodeState getNodeState() {
+        return context.getNodeState(path);
+    }
+
+    @Override
+    public NodeStateBuilder getChildBuilder(String name) {
+        return hasChild(name)
+            ? new KernelNodeStateBuilder2(context, PathUtils.concat(path, name))
+            : null;
+    }
+
+    @Override
+    public NodeStateBuilder addNode(String name, NodeState nodeState) {
+        if (hasChild(name)) {
+            return null;
+        }
+        else {
+            String targetPath = PathUtils.concat(path, name);
+            context.addNode(nodeState, targetPath);
+            return new KernelNodeStateBuilder2(context, targetPath);
+        }
+    }
+
+    @Override
+    public NodeStateBuilder addNode(String name) {
+        if (hasChild(name)) {
+            return null;
+        }
+        else {
+            String targetPath = PathUtils.concat(path, name);
+            context.addNode(targetPath);
+            return new KernelNodeStateBuilder2(context, targetPath);
+        }
+    }
+
+    @Override
+    public boolean removeNode(String name) {
+        if (hasChild(name)) {
+            context.removeNode(PathUtils.concat(path, name));
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
+
+    @Override
+    public void setProperty(String name, CoreValue value) {
+        PropertyState property = new PropertyStateImpl(name, value);
+        if (hasProperty(name)) {
+            context.setProperty(property, path);
+        }
+        else {
+            context.addProperty(property, path);
+        }
+    }
+
+    @Override
+    public void setProperty(String name, List<CoreValue> values) {
+        PropertyState property = new PropertyStateImpl(name, values);
+        if (hasProperty(name)) {
+            context.setProperty(property, path);
+        }
+        else {
+            context.addProperty(property, path);
+        }
+    }
+
+    @Override
+    public void removeProperty(String name) {
+        if (hasProperty(name)) {
+            context.removeProperty(PathUtils.concat(path, name));
+        }
+    }
+
+    @Override
+    public boolean moveTo(NodeStateBuilder destParent, String destName) {
+        if (!(destParent instanceof KernelNodeStateBuilder2)) {
+            throw new IllegalArgumentException("Alien builder for destParent");
+        }
+
+        if (destParent.getChildBuilder(destName) != null) {
+            return false;
+        }
+
+        KernelNodeStateBuilder2 destParentBuilder = (KernelNodeStateBuilder2) destParent;
+        String destPath = PathUtils.concat(destParentBuilder.path, destName);
+
+        context.moveNode(path, destPath);
+        path = destPath;
+        return true;
+    }
+
+    @Override
+    public boolean copyTo(NodeStateBuilder destParent, String destName) {
+        if (!(destParent instanceof KernelNodeStateBuilder2)) {
+            throw new IllegalArgumentException("Alien builder for destParent");
+        }
+
+        if (destParent.getChildBuilder(destName) != null) {
+            return false;
+        }
+
+        KernelNodeStateBuilder2 destParentBuilder = (KernelNodeStateBuilder2) destParent;
+        String destPath = PathUtils.concat(destParentBuilder.path, destName);
+
+        context.copyNode(path, destPath);
+        return true;
+    }
+
+    //------------------------------------------------------------< internal >---
+
+    NodeStateBuilderContext getContext() {
+        return context;
+    }
+
+    //------------------------------------------------------------< private >---
+
+    private boolean hasChild(String name) {
+        return getNodeState().getChildNode(name) != null;
+    }
+
+    private boolean hasProperty(String name) {
+        return getNodeState().getProperty(name) != null;
+    }
+
+}

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore2.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore2.java?rev=1333010&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore2.java
(added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore2.java
Wed May  2 12:09:55 2012
@@ -0,0 +1,624 @@
+package org.apache.jackrabbit.oak.kernel;
+
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.mk.api.MicroKernelException;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.CoreValueFactory;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.spi.state.AbstractChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
+import org.apache.jackrabbit.oak.spi.state.AbstractNodeStore;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateBuilder;
+import org.apache.jackrabbit.oak.util.Function1;
+import org.apache.jackrabbit.oak.util.Iterators;
+import org.apache.jackrabbit.oak.util.Predicate;
+
+import java.util.Iterator;
+
+public class KernelNodeStore2 extends AbstractNodeStore {
+    /**
+     * The {@link org.apache.jackrabbit.mk.api.MicroKernel} instance used to store the content
tree.
+     */
+    private final MicroKernel kernel;
+
+    /**
+     * Value factory backed by the {@link #kernel} instance.
+     */
+    private final CoreValueFactory valueFactory;
+
+    /**
+     * State of the current root node.
+     */
+    private KernelNodeState root;
+
+    public KernelNodeStore2(MicroKernel kernel) {
+        this.kernel = kernel;
+        this.valueFactory = new CoreValueFactoryImpl(kernel);
+        this.root = new KernelNodeState(
+                kernel, valueFactory, "/", kernel.getHeadRevision());
+    }
+
+    @Override
+    public synchronized NodeState getRoot() {
+        String revision = kernel.getHeadRevision();
+        if (!revision.equals(root.getRevision())) {
+            root = new KernelNodeState(
+                    kernel, valueFactory, "/", kernel.getHeadRevision());
+        }
+        return root;
+    }
+
+    @Override
+    public NodeStateBuilder getBuilder(NodeState base) {
+        if (!(base instanceof KernelNodeState)) {
+            throw new IllegalArgumentException("Alien node state");
+        }
+
+        KernelNodeState kernelNodeState = (KernelNodeState) base;
+        String branchRevision = kernel.branch(kernelNodeState.getRevision());
+        String path = kernelNodeState.getPath();
+        KernelNodeState branchRoot = new KernelNodeState(kernel, valueFactory, path, branchRevision);
+        return KernelNodeStateBuilder2.create(new NodeStateBuilderContext(branchRoot));
+    }
+
+    @Override
+    public void apply(NodeStateBuilder builder) throws CommitFailedException {
+        if (!(builder instanceof  KernelNodeStateBuilder2)) {
+            throw new IllegalArgumentException("Alien builder");
+        }
+
+        KernelNodeStateBuilder2 kernelNodeStateBuilder = (KernelNodeStateBuilder2) builder;
+        kernelNodeStateBuilder.getContext().applyPendingChanges();
+    }
+
+    @Override
+    public CoreValueFactory getValueFactory() {
+        return valueFactory;
+    }
+
+    //------------------------------------------------------------< internal >---
+
+    class NodeStateBuilderContext {
+        private static final int PURGE_LIMIT = 1024;  // TODO make configurable?
+
+        private final String path;
+
+        private NodeState root;
+        private String revision;
+
+        private StringBuilder jsop = new StringBuilder();
+
+        NodeStateBuilderContext(KernelNodeState root) {
+            this.path = root.getPath();
+            this.root = root;
+            this.revision = root.getRevision();
+        }
+
+        String getPath() {
+            return path;
+        }
+
+        NodeState getNodeState(String path) {
+            NodeState state = root;
+            for (String name : PathUtils.elements(path)) {
+                state = state.getChildNode(name);
+            }
+
+            return state;
+        }
+
+        void addNode(String relPath) {
+            jsop.append("+\"").append(relPath).append("\":{}");
+            root = addNode(root, EMPTY_STATE, PathUtils.elements(relPath).iterator());
+            purgeOnLimit();
+        }
+
+        void addNode(NodeState node, String relPath) {
+            buildJsop(relPath, node);
+            root = addNode(root, node, PathUtils.elements(relPath).iterator());
+            purgeOnLimit();
+        }
+
+        void removeNode(String relPath) {
+            jsop.append("-\"").append(relPath).append('"');
+            root = removeNode(root, PathUtils.elements(relPath).iterator());
+            purgeOnLimit();
+        }
+
+        void addProperty(PropertyState property, String parentPath) {
+            String path = PathUtils.concat(parentPath, property.getName());
+            String value = property.isArray()
+                    ? CoreValueMapper.toJsonArray(property.getValues())
+                    : CoreValueMapper.toJsonValue(property.getValue());
+            jsop.append("^\"").append(path).append("\":").append(value);
+            root = addProperty(root, property, PathUtils.elements(parentPath).iterator());
+            purgeOnLimit();
+        }
+
+        void setProperty(PropertyState property, String parentPath) {
+            String path = PathUtils.concat(parentPath, property.getName());
+            String value = property.isArray()
+                    ? CoreValueMapper.toJsonArray(property.getValues())
+                    : CoreValueMapper.toJsonValue(property.getValue());
+            jsop.append("^\"").append(path).append("\":").append(value);
+            root = setProperty(root, property, PathUtils.elements(parentPath).iterator());
+            purgeOnLimit();
+        }
+
+        void removeProperty(String relPath) {
+            jsop.append("^\"").append(relPath).append("\":null");
+            root = removeProperty(root, PathUtils.elements(relPath).iterator());
+            purgeOnLimit();
+        }
+
+        void moveNode(String sourcePath, String destPath) {
+            jsop.append(">\"").append(sourcePath).append("\":\"").append(destPath).append('"');
+            NodeState moveNode = getChildNode(root, sourcePath);
+            root = removeNode(root, PathUtils.elements(sourcePath).iterator());
+            root = addNode(root, moveNode, PathUtils.elements(destPath).iterator());
+            purgeOnLimit();
+        }
+
+        void copyNode(String sourcePath, String destPath) {
+            jsop.append("*\"").append(sourcePath).append("\":\"").append(destPath).append('"');
+            NodeState copyNode = getChildNode(root, sourcePath);
+            root = addNode(root, copyNode, PathUtils.elements(destPath).iterator());
+            purgeOnLimit();
+        }
+
+        void applyPendingChanges() throws CommitFailedException {
+            try {
+                purgePendingChanges();
+                kernel.merge(revision, null);
+                revision = null;
+            }
+            catch (MicroKernelException e) {
+                throw new CommitFailedException(e);
+            }
+        }
+
+        //------------------------------------------------------------< private >---
+
+        private void purgeOnLimit() {
+            if (jsop.length() > PURGE_LIMIT) {
+                purgePendingChanges();
+            }
+        }
+
+        private void purgePendingChanges() {
+            if (revision == null) {
+                throw new IllegalStateException("Branch has been merged already");
+            }
+
+            if (jsop.length() > 0) {
+                revision = kernel.commit(path, jsop.toString(), revision, null);
+                root = new KernelNodeState(kernel, valueFactory, path, revision);
+                jsop = new StringBuilder();
+            }
+        }
+
+        private void buildJsop(String path, NodeState nodeState) {
+            jsop.append("+\"").append(path).append("\":{}");
+
+            for (PropertyState property : nodeState.getProperties()) {
+                String targetPath = PathUtils.concat(path, property.getName());
+                String value = property.isArray()
+                        ? CoreValueMapper.toJsonArray(property.getValues())
+                        : CoreValueMapper.toJsonValue(property.getValue());
+
+                jsop.append("^\"").append(targetPath).append("\":").append(value);
+            }
+
+            for (ChildNodeEntry child : nodeState.getChildNodeEntries(0, -1)) {
+                String targetPath = PathUtils.concat(path, child.getName());
+                buildJsop(targetPath, child.getNodeState());
+            }
+        }
+
+        private NodeState addNode(NodeState parent, NodeState node, Iterator<String>
path) {
+            String name = path.next();
+            if (path.hasNext()) {
+                return setChildNode(parent, name, addNode(parent.getChildNode(name), node,
path));
+            }
+            else {
+                return addChildNode(parent, name, node);
+            }
+        }
+
+        private NodeState removeNode(NodeState parent, Iterator<String> path) {
+            String name = path.next();
+            if (path.hasNext()) {
+                return setChildNode(parent, name, removeNode(parent.getChildNode(name), path));
+            }
+            else {
+                return removeChildNode(parent, name);
+            }
+        }
+
+        private NodeState addProperty(NodeState parent, PropertyState added, Iterator<String>
parentPath) {
+            if (parentPath.hasNext()) {
+                String name = parentPath.next();
+                return setChildNode(parent, name, addProperty(parent.getChildNode(name),
added, parentPath));
+            }
+            else {
+                return addChildProperty(parent, added);
+            }
+        }
+
+        private NodeState setProperty(NodeState parent, PropertyState property, Iterator<String>
parentPath) {
+            if (parentPath.hasNext()) {
+                String name = parentPath.next();
+                return setChildNode(parent, name, setProperty(parent.getChildNode(name),
property, parentPath));
+            }
+            else {
+                return setChildProperty(parent, property);
+            }
+        }
+
+        private NodeState removeProperty(NodeState parent, Iterator<String> path) {
+            String name = path.next();
+            if (path.hasNext()) {
+                return setChildNode(parent, name, removeProperty(parent.getChildNode(name),
path));
+            }
+            else {
+                return removeChildProperty(parent, name);
+            }
+        }
+
+        private NodeState getChildNode(NodeState state, String relPath) {
+            for (String name : PathUtils.elements(relPath)) {
+                state = state.getChildNode(name);
+            }
+            return state;
+        }
+
+        private final NodeState EMPTY_STATE = new AbstractNodeState() {
+            @Override
+            public PropertyState getProperty(String name) {
+                return null;
+            }
+
+            @Override
+            public long getPropertyCount() {
+                return 0;
+            }
+
+            @Override
+            public Iterable<? extends PropertyState> getProperties() {
+                return new Iterable<PropertyState>() {
+                    @Override
+                    public Iterator<PropertyState> iterator() {
+                        return Iterators.empty();
+                    }
+                };
+            }
+
+            @Override
+            public NodeState getChildNode(String name) {
+                return null;
+            }
+
+            @Override
+            public long getChildNodeCount() {
+                return 0;
+            }
+
+            @Override
+            public Iterable<? extends ChildNodeEntry> getChildNodeEntries(long offset,
int count) {
+                return new Iterable<ChildNodeEntry>() {
+                    @Override
+                    public Iterator<ChildNodeEntry> iterator() {
+                        return Iterators.empty();
+                    }
+                };
+            }
+        };
+
+        private ChildNodeEntry createCNE(final String name, final NodeState state) {
+            return new AbstractChildNodeEntry() {
+                @Override
+                public String getName() {
+                    return name;
+                }
+
+                @Override
+                public NodeState getNodeState() {
+                    return state;
+                }
+            };
+        }
+
+        private NodeState addChildNode(final NodeState parent, final String childName, final
NodeState node) {
+            return new AbstractNodeState() {
+                @Override
+                public PropertyState getProperty(String name) {
+                    return parent.getProperty(name);
+                }
+
+                @Override
+                public long getPropertyCount() {
+                    return parent.getPropertyCount();
+                }
+
+                @Override
+                public Iterable<? extends PropertyState> getProperties() {
+                    return parent.getProperties();
+                }
+
+                @Override
+                public NodeState getChildNode(String name) {
+                    return childName.equals(name) ? node : parent.getChildNode(name);
+                }
+
+                @Override
+                public long getChildNodeCount() {
+                    return 1 + parent.getChildNodeCount();
+                }
+
+                @Override
+                public Iterable<? extends ChildNodeEntry> getChildNodeEntries(final
long offset, final int count) {
+                    if (offset >= getChildNodeCount()) {
+                        return new Iterable<ChildNodeEntry>() {
+                            @Override
+                            public Iterator<ChildNodeEntry> iterator() {
+                                return Iterators.empty();
+                            }
+                        };
+                    }
+                    else if (count == -1 || offset + count > getChildNodeCount()) {
+                        return new Iterable<ChildNodeEntry>() {
+                            @Override
+                            public Iterator<ChildNodeEntry> iterator() {
+                                return Iterators.chain(
+                                    parent.getChildNodeEntries(offset, count).iterator(),
+                                    Iterators.singleton(createCNE(childName, node)));
+                            }
+                        };
+                    }
+                    else {
+                        return parent.getChildNodeEntries(offset, count);
+                    }
+                }
+
+            };
+        }
+
+        private NodeState setChildNode(final NodeState parent, final String childName, final
NodeState node) {
+            return new AbstractNodeState() {
+                @Override
+                public PropertyState getProperty(String name) {
+                    return parent.getProperty(name);
+                }
+
+                @Override
+                public long getPropertyCount() {
+                    return parent.getPropertyCount();
+                }
+
+                @Override
+                public Iterable<? extends PropertyState> getProperties() {
+                    return parent.getProperties();
+                }
+
+                @Override
+                public NodeState getChildNode(String name) {
+                    return childName.equals(name) ? node : parent.getChildNode(name);
+                }
+
+                @Override
+                public long getChildNodeCount() {
+                    return parent.getChildNodeCount();
+                }
+
+                @Override
+                public Iterable<? extends ChildNodeEntry> getChildNodeEntries(final
long offset, final int count) {
+                    return new Iterable<ChildNodeEntry>() {
+                        @Override
+                        public Iterator<ChildNodeEntry> iterator() {
+                            return Iterators.map(parent.getChildNodeEntries(offset, count).iterator(),
+                                new Function1<ChildNodeEntry, ChildNodeEntry>() {
+                                    @Override
+                                    public ChildNodeEntry apply(ChildNodeEntry cne) {
+                                        return childName.equals(cne.getName())
+                                                ? createCNE(childName, node)
+                                                : cne;
+                                    }
+                                });
+                        }
+                    };
+                }
+            };
+        }
+
+        private NodeState removeChildNode(final NodeState parent, final String childName)
{
+            return new AbstractNodeState() {
+                @Override
+                public PropertyState getProperty(String name) {
+                    return parent.getProperty(name);
+                }
+
+                @Override
+                public long getPropertyCount() {
+                    return parent.getPropertyCount();
+                }
+
+                @Override
+                public Iterable<? extends PropertyState> getProperties() {
+                    return parent.getProperties();
+                }
+
+                @Override
+                public NodeState getChildNode(String name) {
+                    return childName.equals(name) ? null : parent.getChildNode(name);
+                }
+
+                @Override
+                public long getChildNodeCount() {
+                    return parent.getChildNodeCount() - 1;
+                }
+
+                @Override
+                public Iterable<? extends ChildNodeEntry> getChildNodeEntries(final
long offset, final int count) {
+                    return new Iterable<ChildNodeEntry>() {
+                        @Override
+                        public Iterator<ChildNodeEntry> iterator() {
+                            return Iterators.filter(parent.getChildNodeEntries(offset, count).iterator(),
// FIXME offsetting doesn't compose with filtering
+                                new Predicate<ChildNodeEntry>() {
+                                    @Override
+                                    public boolean evaluate(ChildNodeEntry cne) {
+                                        return !childName.equals(cne.getName());
+                                    }
+                                }
+                            );
+                        }
+                    };
+                }
+            };
+        }
+
+        private NodeState addChildProperty(final NodeState parent, final PropertyState property)
{
+            return new AbstractNodeState() {
+                @Override
+                public PropertyState getProperty(String name) {
+                    return property.getName().equals(name)
+                        ? property
+                        : parent.getProperty(name);
+                }
+
+                @Override
+                public long getPropertyCount() {
+                    return parent.getPropertyCount() + 1;
+                }
+
+                @Override
+                public Iterable<? extends PropertyState> getProperties() {
+                    return new Iterable<PropertyState>() {
+                        @Override
+                        public Iterator<PropertyState> iterator() {
+                            return Iterators.chain(
+                                    parent.getProperties().iterator(),
+                                    Iterators.singleton(property));
+                        }
+                    };
+                }
+
+                @Override
+                public NodeState getChildNode(String name) {
+                    return parent.getChildNode(name);
+                }
+
+                @Override
+                public long getChildNodeCount() {
+                    return parent.getChildNodeCount();
+                }
+
+                @Override
+                public Iterable<? extends ChildNodeEntry> getChildNodeEntries(long
offset, int count) {
+                    return parent.getChildNodeEntries(offset, count);
+                }
+            };
+        }
+
+        private NodeState setChildProperty(final NodeState parent, final PropertyState property)
{
+            return new AbstractNodeState() {
+                @Override
+                public PropertyState getProperty(String name) {
+                    return property.getName().equals(name)
+                            ? property
+                            : parent.getProperty(name);
+                }
+
+                @Override
+                public long getPropertyCount() {
+                    return parent.getPropertyCount();
+                }
+
+                @Override
+                public Iterable<? extends PropertyState> getProperties() {
+                    return new Iterable<PropertyState>() {
+                        @Override
+                        public Iterator<PropertyState> iterator() {
+                            return Iterators.map(parent.getProperties().iterator(),
+                                    new Function1<PropertyState, PropertyState>() {
+                                        @Override
+                                        public PropertyState apply(PropertyState state) {
+                                            return property.getName().equals(state.getName())
+                                                    ? property
+                                                    : state;
+                                        }
+                                    }
+                            );
+                        }
+                    };
+                }
+
+                @Override
+                public NodeState getChildNode(String name) {
+                    return parent.getChildNode(name);
+                }
+
+                @Override
+                public long getChildNodeCount() {
+                    return parent.getChildNodeCount();
+                }
+
+                @Override
+                public Iterable<? extends ChildNodeEntry> getChildNodeEntries(long
offset, int count) {
+                    return parent.getChildNodeEntries(offset, count);
+                }
+            };
+        }
+
+        private NodeState removeChildProperty(final NodeState parent, final String propertyName)
{
+            return new AbstractNodeState() {
+                @Override
+                public PropertyState getProperty(String name) {
+                    return propertyName.equals(name)
+                        ? null
+                        : parent.getProperty(name);
+                }
+
+                @Override
+                public long getPropertyCount() {
+                    return parent.getPropertyCount() - 1;
+                }
+
+                @Override
+                public Iterable<? extends PropertyState> getProperties() {
+                    return new Iterable<PropertyState>() {
+                        @Override
+                        public Iterator<PropertyState> iterator() {
+                            return Iterators.filter(parent.getProperties().iterator(),
+                                    new Predicate<PropertyState>() {
+                                        @Override
+                                        public boolean evaluate(PropertyState prop) {
+                                            return !propertyName.equals(prop.getName());
+                                        }
+                                    }
+                            );
+                        }
+                    };
+                }
+
+                @Override
+                public NodeState getChildNode(String name) {
+                    return parent.getChildNode(name);
+                }
+
+                @Override
+                public long getChildNodeCount() {
+                    return parent.getChildNodeCount();
+                }
+
+                @Override
+                public Iterable<? extends ChildNodeEntry> getChildNodeEntries(long
offset, int count) {
+                    return parent.getChildNodeEntries(offset, count);
+                }
+            };
+        }
+
+    }
+}



Mime
View raw message