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 2013/03/22 15:57:58 UTC

svn commit: r1459821 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype: DefinitionProvider.java EffectiveNodeType.java NodeTypeImpl.java ReadOnlyNodeTypeManager.java

Author: jukka
Date: Fri Mar 22 14:57:58 2013
New Revision: 1459821

URL: http://svn.apache.org/r1459821
Log:
OAK-702: Optimize access to node type information

Streamline effective type construction and access to property and child node definitions

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/DefinitionProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeType.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/DefinitionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/DefinitionProvider.java?rev=1459821&r1=1459820&r2=1459821&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/DefinitionProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/DefinitionProvider.java Fri Mar 22 14:57:58 2013
@@ -22,7 +22,6 @@ import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.nodetype.NodeDefinition;
-import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.PropertyDefinition;
 
 import org.apache.jackrabbit.oak.api.PropertyState;
@@ -68,22 +67,6 @@ public interface DefinitionProvider {
             throws ConstraintViolationException, RepositoryException;
 
     /**
-     * Calculates the applicable definition for the child node with the
-     * specified name and node type under the given parent node.
-     *
-     * @param parentNodeTypes The node types of the parent node.
-     * @param nodeName The internal oak name of the child node.
-     * @param nodeType The target node type of the child.
-     * @return the applicable definition for the child node with the specified
-     * name and primary type.
-     * @throws ConstraintViolationException If no matching definition can be found.
-     * @throws RepositoryException If another error occurs.
-     */
-    @Nonnull
-    NodeDefinition getDefinition(Iterable<NodeType> parentNodeTypes, String nodeName,
-                                 NodeType nodeType) throws ConstraintViolationException, RepositoryException;
-
-    /**
      * Calculates the definition of the specified property.
      *
      * @param parent The parent node.
@@ -151,21 +134,4 @@ public interface DefinitionProvider {
                                      int type, boolean exactTypeMatch)
             throws ConstraintViolationException, RepositoryException;
 
-    /**
-     * Calculates the applicable definition for the property with the specified
-     * characteristics under a parent with the specified node types.
-     *
-     * @param nodeTypes The node types of the parent tree.
-     * @param propertyName The internal oak name of the property for which the
-     * definition should be retrieved.
-     * @param isMultiple {@code true} if the target property is multi-valued.
-     * @param type The target type of the property.
-     * @param exactTypeMatch {@code true} if the required type of the definition
-     * must exactly match the type of the target property.
-     * @return the applicable definition for the target property.
-     * @throws ConstraintViolationException If no matching definition can be found.
-     * @throws RepositoryException If another error occurs.
-     */
-    @Nonnull
-    PropertyDefinition getDefinition(Iterable<NodeType> nodeTypes, String propertyName, boolean isMultiple, int type, boolean exactTypeMatch) throws ConstraintViolationException, RepositoryException;
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeType.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeType.java?rev=1459821&r1=1459820&r2=1459821&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeType.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeType.java Fri Mar 22 14:57:58 2013
@@ -16,13 +16,13 @@
  */
 package org.apache.jackrabbit.oak.plugins.nodetype;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static javax.jcr.PropertyType.UNDEFINED;
+import static org.apache.jackrabbit.JcrConstants.NT_BASE;
 
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
+import java.util.Map;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -44,6 +44,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
 
 /**
  * EffectiveNodeType... TODO
@@ -52,28 +53,44 @@ public class EffectiveNodeType {
 
     private static final Logger log = LoggerFactory.getLogger(EffectiveNodeType.class);
 
-    private final Collection<NodeType> nodeTypes;
+    private static final NodeType[] NO_MIXINS = new NodeType[0];
+
+    private final Map<String, NodeType> nodeTypes = Maps.newLinkedHashMap();
+
     private final ReadOnlyNodeTypeManager ntMgr;
 
-    private EffectiveNodeType(Collection<NodeType> nodeTypes, ReadOnlyNodeTypeManager ntMgr) {
-        this.nodeTypes = nodeTypes;
+    EffectiveNodeType(
+            NodeType primary, NodeType[] mixins,
+            ReadOnlyNodeTypeManager ntMgr) {
         this.ntMgr = ntMgr;
-    }
 
-    static EffectiveNodeType create(Collection<NodeType> nodeTypes, ReadOnlyNodeTypeManager ntMgr) throws ConstraintViolationException {
-        if (!isValid(nodeTypes)) {
-            throw new ConstraintViolationException("Invalid effective node type");
+        addNodeType(checkNotNull(primary));
+        for (NodeType mixin : checkNotNull(mixins)) {
+            addNodeType(mixin);
         }
-        return new EffectiveNodeType(nodeTypes, ntMgr);
     }
 
-    private static boolean isValid(Collection<NodeType> nodeTypes) {
-        // FIXME: add validation
-        return true;
+    EffectiveNodeType(NodeType primary, ReadOnlyNodeTypeManager ntMgr) {
+        this(primary, NO_MIXINS, ntMgr);
     }
 
-    public Iterable<NodeType> getAllNodeTypes() {
-        return nodeTypes;
+    private void addNodeType(NodeType type) {
+        String name = type.getName();
+        if (!nodeTypes.containsKey(name)) {
+            nodeTypes.put(name, type);
+            NodeType[] supertypes = type.getDeclaredSupertypes();
+            if (supertypes.length > 1) {
+                for (NodeType supertype : supertypes) {
+                    addNodeType(supertype);
+                }
+            } else if (!type.isMixin() && !nodeTypes.containsKey(NT_BASE)) {
+                try {
+                    addNodeType(ntMgr.getNodeType(NT_BASE));
+                } catch (RepositoryException e) {
+                    // TODO: ignore/warning/error?
+                }
+            }
+        }
     }
 
     /**
@@ -84,7 +101,7 @@ public class EffectiveNodeType {
      * @return {@code true} if the given node type is included, otherwise {@code false}.
      */
     public boolean includesNodeType(String nodeTypeName) {
-        for (NodeType type : nodeTypes) {
+        for (NodeType type : nodeTypes.values()) {
             if (type.isNodeType(nodeTypeName)) {
                 return true;
             }
@@ -131,17 +148,12 @@ public class EffectiveNodeType {
             log.debug("Unknown mixin type " + mixin);
         }
 
-        if (mixinType != null) {
-            Set<NodeType> newTypes = new HashSet<NodeType>(nodeTypes);
-            newTypes.add(mixinType);
-            return isValid(newTypes);
-        }
-        return false;
+        return true;
     }
 
     public Iterable<NodeDefinition> getNodeDefinitions() {
         List<NodeDefinition> definitions = new ArrayList<NodeDefinition>();
-        for (NodeType nt : nodeTypes) {
+        for (NodeType nt : nodeTypes.values()) {
             definitions.addAll(((NodeTypeImpl) nt).internalGetChildDefinitions());
         }
         return definitions;
@@ -149,7 +161,7 @@ public class EffectiveNodeType {
 
     public Iterable<PropertyDefinition> getPropertyDefinitions() {
         List<PropertyDefinition> definitions = new ArrayList<PropertyDefinition>();
-        for (NodeType nt : nodeTypes) {
+        for (NodeType nt : nodeTypes.values()) {
             definitions.addAll(((NodeTypeImpl) nt).internalGetPropertyDefinitions());
         }
         return definitions;
@@ -305,7 +317,7 @@ public class EffectiveNodeType {
     }
 
     public void checkMandatoryItems(Tree tree) throws ConstraintViolationException {
-        for (NodeType nodeType : nodeTypes) {
+        for (NodeType nodeType : nodeTypes.values()) {
             for (PropertyDefinition pd : nodeType.getPropertyDefinitions()) {
                 String name = pd.getName();
                 if (pd.isMandatory() && !pd.isProtected() && tree.getProperty(name) == null) {
@@ -324,8 +336,7 @@ public class EffectiveNodeType {
     }
 
     public void checkOrderableChildNodes() throws UnsupportedRepositoryOperationException {
-        Iterable<NodeType> nts = getAllNodeTypes();
-        for (NodeType nt : nts) {
+        for (NodeType nt : nodeTypes.values()) {
             if (nt.hasOrderableChildNodes()) {
                 return;
             }
@@ -335,13 +346,18 @@ public class EffectiveNodeType {
     }
 
     /**
+     * Calculates the applicable definition for the property with the specified
+     * characteristics under a parent with this effective type.
      *
-     * @param propertyName The internal oak name of the property.
-     * @param isMultiple
-     * @param type
-     * @param exactTypeMatch
-     * @return
-     * @throws ConstraintViolationException
+     * @param propertyName The internal oak name of the property for which the
+     * definition should be retrieved.
+     * @param isMultiple {@code true} if the target property is multi-valued.
+     * @param type The target type of the property.
+     * @param exactTypeMatch {@code true} if the required type of the definition
+     * must exactly match the type of the target property.
+     * @return the applicable definition for the target property.
+     * @throws ConstraintViolationException If no matching definition can be found.
+     * @throws RepositoryException If another error occurs.
      */
     public PropertyDefinition getPropertyDefinition(
             String propertyName, boolean isMultiple,
@@ -413,16 +429,29 @@ public class EffectiveNodeType {
         return getPropertyDefinition(propertyName, isMultiple, propertyType, true);
     }
 
-    private NodeDefinition getDefinition(String nodeName, NodeType nodeType) throws ConstraintViolationException {
+    /**
+     * Calculates the applicable definition for the child node with the
+     * specified name and node type.
+     *
+     * @param nodeName The internal oak name of the child node.
+     * @param nodeType The target node type of the child.
+     * @return the applicable definition for the child node with the specified
+     * name and primary type.
+     * @throws ConstraintViolationException If no matching definition can be found.
+     * @throws RepositoryException If another error occurs.
+     */
+    private NodeDefinition getDefinition(String nodeName, NodeType nodeType)
+            throws ConstraintViolationException {
         // FIXME: ugly hack to workaround sns-hack that was used to map sns-item definitions with node types.
         String nameToCheck = nodeName;
-        if (nodeName.startsWith("jcr:childNodeDefinition") && !nodeName.equals("jcr:childNodeDefinition")) {
+        if (nodeName.startsWith("jcr:childNodeDefinition")) {
             nameToCheck = nodeName.substring(0, "jcr:childNodeDefinition".length());
         }
-        if (nodeName.startsWith("jcr:propertyDefinition") && !nodeName.equals("jcr:propertyDefinition")) {
+        if (nodeName.startsWith("jcr:propertyDefinition")) {
             nameToCheck = nodeName.substring(0, "jcr:propertyDefinition".length());
         }
-        return ntMgr.getDefinition(nodeTypes, nameToCheck, nodeType);
+        return getNodeDefinition(
+                nameToCheck, new EffectiveNodeType(nodeType, ntMgr));
     }
 
     private static class DefinitionNamePredicate implements Predicate<ItemDefinition> {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeImpl.java?rev=1459821&r1=1459820&r2=1459821&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeImpl.java Fri Mar 22 14:57:58 2013
@@ -21,7 +21,6 @@ import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -305,8 +304,10 @@ class NodeTypeImpl extends AbstractTypeD
         }
 
         try {
-            Iterable<NodeType> nts = Collections.singleton((NodeType) this);
-            PropertyDefinition def = getManager().getDefinition(nts, propertyName, false, value.getType(), false);
+            EffectiveNodeType effective =
+                    new EffectiveNodeType(this, getManager());
+            PropertyDefinition def = effective.getPropertyDefinition(
+                    propertyName, false, value.getType(), false);
             return !def.isProtected() &&
                     meetsTypeConstraints(value, def.getRequiredType()) &&
                     meetsValueConstraints(value, def.getValueConstraints());
@@ -323,9 +324,11 @@ class NodeTypeImpl extends AbstractTypeD
         }
 
         try {
-            Iterable<NodeType> nts = Collections.singleton((NodeType) this);
             int type = (values.length == 0) ? PropertyType.STRING : values[0].getType();
-            PropertyDefinition def = getManager().getDefinition(nts, propertyName, true, type, false);
+            EffectiveNodeType effective =
+                    new EffectiveNodeType(this, getManager());
+            PropertyDefinition def = effective.getPropertyDefinition(
+                    propertyName, true, type, false);
             return !def.isProtected() &&
                     meetsTypeConstraints(values, def.getRequiredType()) &&
                     meetsValueConstraints(values, def.getValueConstraints());

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java?rev=1459821&r1=1459820&r2=1459821&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java Fri Mar 22 14:57:58 2013
@@ -16,12 +16,8 @@
  */
 package org.apache.jackrabbit.oak.plugins.nodetype;
 
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
-import java.util.Queue;
 import java.util.Set;
 
 import javax.annotation.CheckForNull;
@@ -32,7 +28,6 @@ import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
-import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.nodetype.NoSuchNodeTypeException;
 import javax.jcr.nodetype.NodeDefinition;
 import javax.jcr.nodetype.NodeDefinitionTemplate;
@@ -45,8 +40,6 @@ import javax.jcr.nodetype.PropertyDefini
 import javax.jcr.nodetype.PropertyDefinitionTemplate;
 
 import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Queues;
 import com.google.common.collect.Sets;
 
 import org.apache.jackrabbit.JcrConstants;
@@ -66,7 +59,6 @@ import static javax.jcr.PropertyType.UND
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
 import static org.apache.jackrabbit.oak.api.Type.STRING;
-import static org.apache.jackrabbit.oak.api.Type.STRINGS;
 import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.NODE_TYPES_PATH;
 
@@ -347,22 +339,16 @@ public abstract class ReadOnlyNodeTypeMa
      * @param node node instance
      * @return all types of the given node
      * @throws RepositoryException if the type information can not be accessed
-     * @param node
-     * @return
-     * @throws RepositoryException
      */
     @Override
-    public EffectiveNodeType getEffectiveNodeType(Node node) throws RepositoryException {
-        Queue<NodeType> queue = Queues.newArrayDeque();
-        queue.add(node.getPrimaryNodeType());
-        queue.addAll(Arrays.asList(node.getMixinNodeTypes()));
-
-        return getEffectiveNodeType(queue);
+    public EffectiveNodeType getEffectiveNodeType(Node node)
+            throws RepositoryException {
+        return new EffectiveNodeType(
+                node.getPrimaryNodeType(), node.getMixinNodeTypes(), this);
     }
 
     @Override
     public EffectiveNodeType getEffectiveNodeType(Tree tree) throws RepositoryException {
-        Queue<NodeType> queue = Queues.newArrayDeque();
 
         NodeType primaryType;
         PropertyState jcrPrimaryType = tree.getProperty(JCR_PRIMARYTYPE);
@@ -372,18 +358,17 @@ public abstract class ReadOnlyNodeTypeMa
         } else {
             throw new RepositoryException("Node at "+tree.getPath()+" has no primary type.");
         }
-        queue.add(primaryType);
 
-        List<NodeType> mixinTypes = Lists.newArrayList();
         PropertyState jcrMixinType = tree.getProperty(JCR_MIXINTYPES);
-        if (jcrMixinType != null) {
-            for (String ntName : jcrMixinType.getValue(STRINGS)) {
-                mixinTypes.add(internalGetNodeType(ntName));
+        if (jcrMixinType == null) {
+            return new EffectiveNodeType(primaryType, this);
+        } else {
+            NodeType[] mixinTypes = new NodeType[jcrMixinType.count()];
+            for (int i = 0; i < mixinTypes.length; i++) {
+                mixinTypes[i] = getNodeType(jcrMixinType.getValue(Type.NAME, i));
             }
+            return new EffectiveNodeType(primaryType, mixinTypes, this);
         }
-        queue.addAll(mixinTypes);
-
-        return getEffectiveNodeType(queue);
     }
 
     //-------------------------------------------------< DefinitionProvider >---
@@ -415,14 +400,6 @@ public abstract class ReadOnlyNodeTypeMa
     }
 
     @Override
-    public NodeDefinition getDefinition(Iterable<NodeType> parentNodeTypes,
-                                        String nodeName, NodeType nodeType)
-            throws ConstraintViolationException {
-        EffectiveNodeType eff = getEffectiveNodeType(Queues.newArrayDeque(parentNodeTypes));
-        return eff.getNodeDefinition(nodeName, getEffectiveNodeType(Queues.newArrayDeque(Collections.singleton(nodeType))));
-    }
-
-    @Override
     public PropertyDefinition getDefinition(Node parent, Property targetProperty) throws RepositoryException {
         String name = targetProperty.getName();
         boolean isMultiple = targetProperty.isMultiple();
@@ -460,15 +437,6 @@ public abstract class ReadOnlyNodeTypeMa
         return effective.getPropertyDefinition(propertyName, isMultiple, type, exactTypeMatch);
     }
 
-    @Nonnull
-    @Override
-    public PropertyDefinition getDefinition(Iterable<NodeType> nodeTypes, String propertyName, boolean isMultiple,
-            int type, boolean exactTypeMatch) throws RepositoryException {
-        Queue<NodeType> queue = Queues.newArrayDeque(nodeTypes);
-        EffectiveNodeType effective = getEffectiveNodeType(queue);
-        return effective.getPropertyDefinition(propertyName, isMultiple, type, exactTypeMatch);
-    }
-
     //-----------------------------------------------------------< internal >---
 
     NodeTypeImpl internalGetNodeType(String oakName) throws NoSuchNodeTypeException {
@@ -482,19 +450,4 @@ public abstract class ReadOnlyNodeTypeMa
         throw new NoSuchNodeTypeException(getNamePathMapper().getJcrName(oakName));
     }
 
-    //------------------------------------------------------------< private >---
-
-    private EffectiveNodeType getEffectiveNodeType(Queue<NodeType> queue) throws ConstraintViolationException {
-        Map<String, NodeType> types = Maps.newHashMap();
-        while (!queue.isEmpty()) {
-            NodeType type = queue.remove();
-            String name = type.getName();
-            if (!types.containsKey(name)) {
-                types.put(name, type);
-                queue.addAll(Arrays.asList(type.getDeclaredSupertypes()));
-            }
-        }
-        return EffectiveNodeType.create(types.values(), this);
-    }
-
 }