You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ju...@apache.org on 2012/05/07 14:41:35 UTC

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

Author: jukka
Date: Mon May  7 12:41:34 2012
New Revision: 1334977

URL: http://svn.apache.org/viewvc?rev=1334977&view=rev
Log:
OAK-68: Extension point for commit validation

Add the basics of an in-memory NodeStore implementation for easier testing of commit hooks.
Minor improvements to the abstract base classes.

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryChildNodeEntry.java   (contents, props changed)
      - copied, changed from r1334949, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelChildNodeEntry.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java   (with props)
Removed:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/EmptyNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelChildNodeEntry.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractChildNodeEntry.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java?rev=1334977&r1=1334976&r2=1334977&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java Mon May  7 12:41:34 2012
@@ -24,6 +24,7 @@ import org.apache.jackrabbit.mk.json.Jso
 import org.apache.jackrabbit.oak.api.CoreValue;
 import org.apache.jackrabbit.oak.api.CoreValueFactory;
 import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -203,9 +204,7 @@ class KernelNodeState extends AbstractNo
                 offset--;
             }
             while (count > 0 && iterator.hasNext()) {
-                Map.Entry<String, NodeState> entry = iterator.next();
-                entries.add(new KernelChildNodeEntry(
-                        entry.getKey(), entry.getValue()));
+                entries.add(new MemoryChildNodeEntry(iterator.next()));
                 count--;
             }
             offset = childNodes.size();
@@ -223,9 +222,9 @@ class KernelNodeState extends AbstractNo
                 if (reader.matches('{')) {
                     reader.read('}');
                     String childPath = getChildPath(name);
-                    NodeState child =
-                            new KernelNodeState(kernel, valueFactory, childPath, revision);
-                    entries.add(new KernelChildNodeEntry(name, child));
+                    NodeState child = new KernelNodeState(
+                            kernel, valueFactory, childPath, revision);
+                    entries.add(new MemoryChildNodeEntry(name, child));
                 } else {
                     reader.read();
                 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java?rev=1334977&r1=1334976&r2=1334977&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java Mon May  7 12:41:34 2012
@@ -22,6 +22,8 @@ import org.apache.jackrabbit.oak.api.Com
 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.plugins.memory.MemoryChildNodeEntry;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState;
 import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
 import org.apache.jackrabbit.oak.spi.state.AbstractNodeStore;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
@@ -167,7 +169,7 @@ public class KernelNodeStore extends Abs
          */
         void addNode(String relPath) {
             jsop.append("+\"").append(relPath).append("\":{}");
-            root = addNode(root, EmptyNodeState.INSTANCE, PathUtils.elements(relPath).iterator());
+            root = addNode(root, MemoryNodeState.EMPTY_NODE, PathUtils.elements(relPath).iterator());
             purgeOnLimit();
         }
 
@@ -495,7 +497,7 @@ public class KernelNodeStore extends Abs
                     public Iterator<ChildNodeEntry> iterator() {
                         return Iterators.chain(
                             parent.getChildNodeEntries().iterator(),
-                            Iterators.singleton(new KernelChildNodeEntry(childName, node)));
+                            Iterators.singleton(new MemoryChildNodeEntry(childName, node)));
                     }
                 };
             }
@@ -559,7 +561,7 @@ public class KernelNodeStore extends Abs
                                 @Override
                                 public ChildNodeEntry apply(ChildNodeEntry cne) {
                                     return childName.equals(cne.getName())
-                                            ? new KernelChildNodeEntry(childName, node)
+                                            ? new MemoryChildNodeEntry(childName, node)
                                             : cne;
                                 }
                             });

Copied: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryChildNodeEntry.java (from r1334949, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelChildNodeEntry.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryChildNodeEntry.java?p2=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryChildNodeEntry.java&p1=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelChildNodeEntry.java&r1=1334949&r2=1334977&rev=1334977&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelChildNodeEntry.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryChildNodeEntry.java Mon May  7 12:41:34 2012
@@ -16,22 +16,44 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.jackrabbit.oak.kernel;
+package org.apache.jackrabbit.oak.plugins.memory;
+
+import java.util.Map;
 
 import org.apache.jackrabbit.oak.spi.state.AbstractChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
-class KernelChildNodeEntry extends AbstractChildNodeEntry {
+/**
+ * Basic JavaBean implementation of a child node entry.
+ */
+public class MemoryChildNodeEntry extends AbstractChildNodeEntry {
 
     private final String name;
 
     private final NodeState node;
 
-    public KernelChildNodeEntry(String name, NodeState node) {
+    /**
+     * Creates a child node entry with the given name and referenced
+     * child node state.
+     *
+     * @param name child node name
+     * @param node child node state
+     */
+    public MemoryChildNodeEntry(String name, NodeState node) {
         this.name = name;
         this.node = node;
     }
 
+    /**
+     * Utility constructor that copies the name and referenced
+     * child node state from the given map entry.
+     *
+     * @param entry map entry
+     */
+    public MemoryChildNodeEntry(Map.Entry<String, NodeState> entry) {
+        this(entry.getKey(), entry.getValue());
+    }
+
     @Override
     public String getName() {
         return name;

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryChildNodeEntry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java?rev=1334977&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java Mon May  7 12:41:34 2012
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.memory;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.spi.state.AbstractNodeState;
+import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Basic in-memory node state implementation.
+ */
+public class MemoryNodeState extends AbstractNodeState
+        implements Iterable<ChildNodeEntry> {
+
+    /**
+     * Singleton instance of an empty node state, i.e. one with neither
+     * properties nor child nodes.
+     */
+    public static final NodeState EMPTY_NODE = new MemoryNodeState(
+            Collections.<String, PropertyState>emptyMap(),
+            Collections.<String, NodeState>emptyMap());
+
+    private final Map<String, PropertyState> properties;
+
+    private final Map<String, NodeState> nodes;
+
+    /**
+     * Creates a new node state with the given properties and child nodes.
+     * The given maps are stored as references, so their contents and
+     * iteration order must remain unmodified at least for as long as this
+     * node state instance is in use.
+     *
+     * @param properties properties
+     * @param nodes child nodes
+     */
+    public MemoryNodeState(
+            Map<String, PropertyState> properties,
+            Map<String, NodeState> nodes) {
+        assert Collections.disjoint(properties.keySet(), nodes.keySet());
+        this.properties = properties;
+        this.nodes = nodes;
+    }
+
+    @Override
+    public PropertyState getProperty(String name) {
+        return properties.get(name);
+    }
+
+    @Override
+    public long getPropertyCount() {
+        return properties.size();
+    }
+
+    @Override
+    public Iterable<? extends PropertyState> getProperties() {
+        return properties.values();
+    }
+
+    @Override
+    public NodeState getChildNode(String name) {
+        return nodes.get(name);
+    }
+
+    @Override
+    public long getChildNodeCount() {
+        return nodes.size();
+    }
+
+    @Override
+    public Iterable<ChildNodeEntry> getChildNodeEntries() {
+        return this;
+    }
+
+    @Override
+    public Iterator<ChildNodeEntry> iterator() {
+        final Iterator<Map.Entry<String, NodeState>> iterator =
+                nodes.entrySet().iterator();
+        return new Iterator<ChildNodeEntry>() {
+            @Override
+            public boolean hasNext() {
+                return iterator.hasNext();
+            }
+            @Override
+            public ChildNodeEntry next() {
+                return new MemoryChildNodeEntry(iterator.next());
+            }
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractChildNodeEntry.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractChildNodeEntry.java?rev=1334977&r1=1334976&r2=1334977&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractChildNodeEntry.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractChildNodeEntry.java Mon May  7 12:41:34 2012
@@ -25,6 +25,16 @@ package org.apache.jackrabbit.oak.spi.st
 public abstract class AbstractChildNodeEntry implements ChildNodeEntry {
 
     /**
+     * Returns a string representation of this child node entry.
+     *
+     * @return string representation
+     */
+    @Override
+    public String toString() {
+        return getName() + ": " + getNodeState();
+    }
+
+    /**
      * Checks whether the given object is equal to this one. Two child node
      * entries are considered equal if both their names and referenced node
      * states match. Subclasses may override this method with a more efficient

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java?rev=1334977&r1=1334976&r2=1334977&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java Mon May  7 12:41:34 2012
@@ -16,6 +16,9 @@
  */
 package org.apache.jackrabbit.oak.spi.state;
 
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicBoolean;
+
 import org.apache.jackrabbit.oak.api.PropertyState;
 
 /**
@@ -44,13 +47,8 @@ public abstract class AbstractNodeState 
     }
 
     @Override
-    @SuppressWarnings("unused")
     public long getPropertyCount() {
-        long count = 0;
-        for (PropertyState property : getProperties()) {
-            count++;
-        }
-        return count;
+        return count(getProperties());
     }
 
     @Override
@@ -64,13 +62,42 @@ public abstract class AbstractNodeState 
     }
 
     @Override
-    @SuppressWarnings("unused")
     public long getChildNodeCount() {
-        long count = 0;
+        return count(getChildNodeEntries());
+    }
+
+    private static long count(Iterable<?> iterable) {
+        long n = 0;
+        Iterator<?> iterator = iterable.iterator();
+        while (iterator.hasNext()) {
+            iterator.next();
+            n++;
+        }
+        return n;
+    }
+
+    /**
+     * Returns a string representation of this child node entry.
+     *
+     * @return string representation
+     */
+    public String toString() {
+        StringBuilder builder = new StringBuilder("{");
+        AtomicBoolean first = new AtomicBoolean(true);
+        for (PropertyState property : getProperties()) {
+            if (first.getAndSet(false)) {
+                builder.append(',');
+            }
+            builder.append(' ').append(property);
+        }
         for (ChildNodeEntry entry : getChildNodeEntries()) {
-            count++;
+            if (first.getAndSet(false)) {
+                builder.append(',');
+            }
+            builder.append(' ').append(entry);
         }
-        return count;
+        builder.append(" }");
+        return builder.toString();
     }
 
     /**
@@ -93,25 +120,25 @@ public abstract class AbstractNodeState 
 
         NodeState other = (NodeState) that;
 
-        long propertyCount = 0;
+        if (getPropertyCount() != other.getPropertyCount()
+                || getChildNodeCount() != other.getChildNodeCount()) {
+            return false;
+        }
+
         for (PropertyState property : getProperties()) {
             if (!property.equals(other.getProperty(property.getName()))) {
                 return false;
             }
-            propertyCount++;
-        }
-        if (propertyCount != other.getPropertyCount()) {
-            return false;
         }
 
-        long childNodeCount = 0;
         for (ChildNodeEntry entry : getChildNodeEntries()) {
-            if (!entry.getNodeState().equals(other.getChildNode(entry.getName()))) {
+            if (!entry.getNodeState().equals(
+                    other.getChildNode(entry.getName()))) {
                 return false;
             }
-            childNodeCount++;
         }
-        return childNodeCount == other.getChildNodeCount();
+
+        return true;
 
     }