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/02/28 14:58:26 UTC

svn commit: r1451200 - /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/

Author: jukka
Date: Thu Feb 28 13:58:26 2013
New Revision: 1451200

URL: http://svn.apache.org/r1451200
Log:
OAK-652: ItemImpl.checkProtected() is too slow

First take on optimizing the node type code

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/AbstractTypeDefinition.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ItemDefinitionImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeDefinitionImpl.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/PropertyDefinitionImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/AbstractTypeDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/AbstractTypeDefinition.java?rev=1451200&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/AbstractTypeDefinition.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/AbstractTypeDefinition.java Thu Feb 28 13:58:26 2013
@@ -0,0 +1,133 @@
+/*
+ * 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.nodetype;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.jcr.ValueFactory;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+
+/**
+ * Abstract base class for the various kinds of type definition classes
+ * in this package.
+ */
+abstract class AbstractTypeDefinition {
+
+    private static final String[] NO_STRINGS = new String[0];
+
+    protected final Tree definition;
+
+    protected final ValueFactory factory;
+
+    protected final NamePathMapper mapper;
+
+    protected AbstractTypeDefinition(
+            Tree definition, ValueFactory factory, NamePathMapper mapper) {
+        this.definition = checkNotNull(definition);
+        this.factory = factory;
+        this.mapper = checkNotNull(mapper);
+    }
+
+    /**
+     * Returns the boolean value of the named property.
+     *
+     * @param name property name
+     * @return property value, or {@code false} if the property does not exist
+     */
+    protected boolean getBoolean(@Nonnull String name) {
+        PropertyState property = definition.getProperty(checkNotNull(name));
+        return property != null && property.getValue(Type.BOOLEAN);
+    }
+
+    /**
+     * Returns the string value of the named property.
+     *
+     * @param oakName property name
+     * @return property value, or {@code null} if the property does not exist
+     */
+    @CheckForNull
+    protected String getString(@Nonnull String oakName) {
+        return getValue(oakName, Type.STRING);
+    }
+
+    /**
+     * Returns the string values of the named property.
+     *
+     * @param oakName property name
+     * @return property values, or {@code null} if the property does not exist
+     */
+    @CheckForNull
+    protected String[] getStrings(@Nonnull String oakName) {
+        return getValues(oakName, Type.STRING);
+    }
+    /**
+     * Returns the name value of the named property.
+     *
+     * @param oakName property name
+     * @return property value, or {@code null} if the property does not exist
+     */
+    @CheckForNull
+    protected String getName(@Nonnull String oakName) {
+        return getValue(oakName, Type.NAME);
+    }
+
+    /**
+     * Returns the name values of the named property.
+     *
+     * @param oakName property name
+     * @return property values, or {@code null} if the property does not exist
+     */
+    @CheckForNull
+    protected String[] getNames(@Nonnull String oakName) {
+        return getValues(oakName, Type.NAME);
+    }
+
+    private String getValue(String oakName, Type<String> type) {
+        PropertyState property = definition.getProperty(checkNotNull(oakName));
+        if (property != null) {
+            return property.getValue(type);
+        } else {
+            return null;
+        }
+    }
+
+    private String[] getValues(String oakName, Type<String> type) {
+        String[] values = null;
+
+        PropertyState property = definition.getProperty(checkNotNull(oakName));
+        if (property != null) {
+            int n = property.count();
+            if (n > 0) {
+                values = new String[n];
+                for (int i = 0; i < n; i++) {
+                    values[i] = property.getValue(type, i);
+                }
+            } else {
+                values = NO_STRINGS;
+            }
+        }
+
+        return values;
+    }
+
+}

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ItemDefinitionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ItemDefinitionImpl.java?rev=1451200&r1=1451199&r2=1451200&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ItemDefinitionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ItemDefinitionImpl.java Thu Feb 28 13:58:26 2013
@@ -16,14 +16,14 @@
  */
 package org.apache.jackrabbit.oak.plugins.nodetype;
 
+import javax.jcr.ValueFactory;
 import javax.jcr.nodetype.ItemDefinition;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.version.OnParentVersionAction;
 
 import org.apache.jackrabbit.JcrConstants;
-import org.apache.jackrabbit.oak.util.NodeUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 
 /**
  * <pre>
@@ -37,55 +37,62 @@ import org.slf4j.LoggerFactory;
  *   ...
  * </pre>
  */
-class ItemDefinitionImpl implements ItemDefinition {
+class ItemDefinitionImpl extends AbstractTypeDefinition
+        implements ItemDefinition {
 
-    private static final Logger log = LoggerFactory.getLogger(ItemDefinitionImpl.class);
-
-    private final NodeType type;
-
-    protected final NodeUtil node;
+    protected ItemDefinitionImpl(
+            Tree definition, ValueFactory factory, NamePathMapper mapper) {
+        super(definition, factory, mapper);
+    }
 
-    protected ItemDefinitionImpl(NodeType type, NodeUtil node) {
-        this.type = type;
-        this.node = node;
+    String getOakName() {
+        String oakName = getName(JcrConstants.JCR_NAME);
+        if (oakName == null) {
+            oakName = NodeTypeConstants.RESIDUAL_NAME;
+        }
+        return oakName;
     }
 
     //-----------------------------------------------------< ItemDefinition >---
+
     @Override
     public NodeType getDeclaringNodeType() {
-        return type;
+        return new NodeTypeImpl(definition.getParent(), factory, mapper);
     }
 
     @Override
     public String getName() {
-        return node.getName(JcrConstants.JCR_NAME, NodeTypeConstants.RESIDUAL_NAME);
+        String oakName = getName(JcrConstants.JCR_NAME);
+        if (oakName != null) {
+            return mapper.getJcrName(oakName);
+        } else {
+            return NodeTypeConstants.RESIDUAL_NAME;
+        }
     }
 
     @Override
     public boolean isAutoCreated() {
-        return node.getBoolean(JcrConstants.JCR_AUTOCREATED);
+        return getBoolean(JcrConstants.JCR_AUTOCREATED);
     }
 
     @Override
     public boolean isMandatory() {
-        return node.getBoolean(JcrConstants.JCR_MANDATORY);
+        return getBoolean(JcrConstants.JCR_MANDATORY);
     }
 
     @Override
     public int getOnParentVersion() {
-        try {
-            return OnParentVersionAction.valueFromName(node.getString(
-                    "jcr:onParentVersion",
-                    OnParentVersionAction.ACTIONNAME_COPY));
-        } catch (IllegalArgumentException e) {
-            log.warn("Unexpected jcr:onParentVersion value", e);
+        String action = getString(JcrConstants.JCR_ONPARENTVERSION);
+        if (action != null) {
+            return OnParentVersionAction.valueFromName(action);
+        } else {
             return OnParentVersionAction.COPY;
         }
     }
 
     @Override
     public boolean isProtected() {
-        return node.getBoolean(JcrConstants.JCR_PROTECTED);
+        return getBoolean(JcrConstants.JCR_PROTECTED);
     }
 
     @Override
@@ -93,8 +100,4 @@ class ItemDefinitionImpl implements Item
         return getName();
     }
 
-    //-----------------------------------------------------------< internal >---
-    String getOakName() {
-        return node.getString(JcrConstants.JCR_NAME, NodeTypeConstants.RESIDUAL_NAME);
-    }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeDefinitionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeDefinitionImpl.java?rev=1451200&r1=1451199&r2=1451200&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeDefinitionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeDefinitionImpl.java Thu Feb 28 13:58:26 2013
@@ -16,18 +16,15 @@
  */
 package org.apache.jackrabbit.oak.plugins.nodetype;
 
-import java.util.ArrayList;
-import java.util.List;
+import static com.google.common.base.Preconditions.checkState;
 
-import javax.jcr.RepositoryException;
+import javax.jcr.ValueFactory;
 import javax.jcr.nodetype.NodeDefinition;
 import javax.jcr.nodetype.NodeType;
-import javax.jcr.nodetype.NodeTypeManager;
 
 import org.apache.jackrabbit.JcrConstants;
-import org.apache.jackrabbit.oak.util.NodeUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 
 /**
  * <pre>
@@ -40,57 +37,68 @@ import org.slf4j.LoggerFactory;
  */
 class NodeDefinitionImpl extends ItemDefinitionImpl implements NodeDefinition {
 
-    private static final Logger log = LoggerFactory.getLogger(NodeDefinitionImpl.class);
-
-    private final NodeTypeManager manager;
-
-    protected NodeDefinitionImpl(NodeTypeManager manager, NodeType type, NodeUtil node) {
-        super(type, node);
-        this.manager = manager;
+    protected NodeDefinitionImpl(
+            Tree definition, ValueFactory factory, NamePathMapper mapper) {
+        super(definition, factory, mapper);
     }
 
     //-----------------------------------------------------< NodeDefinition >---
+
     @Override
     public String[] getRequiredPrimaryTypeNames() {
-        return node.getNames(JcrConstants.JCR_REQUIREDPRIMARYTYPES, JcrConstants.NT_BASE);
+        String[] names = getNames(JcrConstants.JCR_REQUIREDPRIMARYTYPES);
+        if (names == null) {
+            names = new String[] { JcrConstants.NT_BASE };
+        }
+        for (int i = 0; i < names.length; i++) {
+            names[i] = mapper.getJcrName(names[i]);
+        }
+        return names;
     }
 
     @Override
     public NodeType[] getRequiredPrimaryTypes() {
-        String[] names = getRequiredPrimaryTypeNames();
-        List<NodeType> types = new ArrayList<NodeType>(names.length);
-        for (String name : names) {
-            try {
-                types.add(manager.getNodeType(name));
-            } catch (RepositoryException e) {
-                log.warn("Unable to access required primary type "
-                        + name + " of node " + getName(), e);
-            }
+        String[] oakNames = getNames(JcrConstants.JCR_REQUIREDPRIMARYTYPES);
+        if (oakNames == null) {
+            oakNames = new String[] { JcrConstants.NT_BASE };
         }
-        return types.toArray(new NodeType[types.size()]);
+
+        NodeType[] types = new NodeType[oakNames.length];
+        Tree root = definition.getParent().getParent();
+        for (int i = 0; i < oakNames.length; i++) {
+            Tree type = root.getChild(oakNames[i]);
+            checkState(type != null);
+            types[i] = new NodeTypeImpl(type, factory, mapper);
+        }
+        return types;
     }
 
     @Override
     public String getDefaultPrimaryTypeName() {
-        return node.getName(JcrConstants.JCR_DEFAULTPRIMARYTYPE, null);
+        String oakName = getName(JcrConstants.JCR_DEFAULTPRIMARYTYPE);
+        if (oakName != null) {
+            return mapper.getJcrName(oakName);
+        } else {
+            return null;
+        }
     }
 
     @Override
     public NodeType getDefaultPrimaryType() {
-        String name = getDefaultPrimaryTypeName();
-        if (name != null) {
-            try {
-                return manager.getNodeType(name);
-            } catch (RepositoryException e) {
-                log.warn("Unable to access default primary type "
-                        + name + " of node " + getName(), e);
-            }
+        String oakName = getName(JcrConstants.JCR_DEFAULTPRIMARYTYPE);
+        if (oakName != null) {
+            Tree root = definition.getParent().getParent();
+            Tree type = root.getChild(oakName);
+            checkState(type != null);
+            return new NodeTypeImpl(type, factory, mapper);
+        } else {
+            return null;
         }
-        return null;
     }
 
     @Override
     public boolean allowsSameNameSiblings() {
-        return node.getBoolean(JcrConstants.JCR_SAMENAMESIBLINGS);
+        return getBoolean(JcrConstants.JCR_SAMENAMESIBLINGS);
     }
-}
\ No newline at end of file
+
+}

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=1451200&r1=1451199&r2=1451200&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 Thu Feb 28 13:58:26 2013
@@ -22,11 +22,11 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedList;
 import java.util.List;
-import java.util.Queue;
+import java.util.Map;
 import java.util.Set;
+
+import javax.annotation.CheckForNull;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
@@ -38,14 +38,22 @@ import javax.jcr.nodetype.NodeTypeIterat
 import javax.jcr.nodetype.PropertyDefinition;
 
 import org.apache.jackrabbit.commons.iterator.NodeTypeIteratorAdapter;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.namepath.JcrNameParser;
 import org.apache.jackrabbit.oak.namepath.JcrPathParser;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
 import org.apache.jackrabbit.oak.plugins.nodetype.constraint.Constraints;
-import org.apache.jackrabbit.oak.util.NodeUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+import static com.google.common.base.Preconditions.checkState;
 import static org.apache.jackrabbit.JcrConstants.JCR_CHILDNODEDEFINITION;
 import static org.apache.jackrabbit.JcrConstants.JCR_HASORDERABLECHILDNODES;
 import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
@@ -71,161 +79,214 @@ import static org.apache.jackrabbit.oak.
  * + jcr:childNodeDefinition (nt:childNodeDefinition) = nt:childNodeDefinition protected sns
  * </pre>
  */
-class NodeTypeImpl implements NodeType {
+class NodeTypeImpl extends AbstractTypeDefinition implements NodeType {
 
     private static final Logger log = LoggerFactory.getLogger(NodeTypeImpl.class);
 
-    private final ReadOnlyNodeTypeManager manager;
+    private static final PropertyDefinition[] NO_PROPERTY_DEFINITIONS =
+            new PropertyDefinition[0];
+
+    private static final NodeDefinition[] NO_NODE_DEFINITIONS =
+            new NodeDefinition[0];
+
+    private static final NodeType[] NO_NODE_TYPES = new NodeType[0];
 
-    private final ValueFactory factory;
+    private static final String[] NO_NAMES = new String[0];
 
-    private final NodeUtil node;
+    NodeTypeImpl(Tree type, ValueFactory factory, NamePathMapper mapper) {
+        super(type, factory, mapper);
+    }
+
+    private String getOakName() {
+        return getOakName(definition);
+    }
 
-    public NodeTypeImpl(ReadOnlyNodeTypeManager manager, ValueFactory factory, NodeUtil node) {
-        this.manager = manager;
-        this.factory = factory;
-        this.node = node;
+    private String getOakName(Tree tree) {
+        PropertyState property = tree.getProperty(JCR_NODETYPENAME);
+        if (property != null) {
+            return property.getValue(Type.NAME);
+        } else {
+            return tree.getName();
+        }
     }
 
     //-----------------------------------------------------------< NodeType >---
+
     @Override
     public String getName() {
-        String name = node.getName(JCR_NODETYPENAME);
-        if (name == null) {
-            name = node.getName();
-        }
-        return name;
+        return mapper.getJcrName(getOakName());
     }
 
     @Override
     public String[] getDeclaredSupertypeNames() {
-        return node.getNames(JCR_SUPERTYPES);
+        String[] names = getNames(JCR_SUPERTYPES);
+        if (names != null) {
+            for (int i = 0; i < names.length; i++) {
+                names[i] = mapper.getJcrName(names[i]);
+            }
+        } else {
+            names = NO_NAMES;
+        }
+        return names;
     }
 
     @Override
     public boolean isAbstract() {
-        return node.getBoolean(JCR_IS_ABSTRACT);
+        return getBoolean(JCR_IS_ABSTRACT);
     }
 
     @Override
     public boolean isMixin() {
-        return node.getBoolean(JCR_ISMIXIN);
+        return getBoolean(JCR_ISMIXIN);
     }
 
     @Override
     public boolean hasOrderableChildNodes() {
-        return node.getBoolean(JCR_HASORDERABLECHILDNODES);
+        return getBoolean(JCR_HASORDERABLECHILDNODES);
     }
 
     @Override
     public boolean isQueryable() {
-        return node.getBoolean(JCR_IS_QUERYABLE);
+        return getBoolean(JCR_IS_QUERYABLE);
     }
 
     @Override
     public String getPrimaryItemName() {
-        return node.getName(JCR_PRIMARYITEMNAME);
+        String oakName = getName(JCR_PRIMARYITEMNAME);
+        if (oakName != null) {
+            return mapper.getJcrName(oakName);
+        } else {
+            return null;
+        }
     }
 
     @Override
     public PropertyDefinition[] getDeclaredPropertyDefinitions() {
-        List<NodeUtil> nodes = node.getNodes(JCR_PROPERTYDEFINITION);
-        PropertyDefinition[] definitions = new PropertyDefinition[nodes.size()];
-        for (int i = 0; i < nodes.size(); i++) {
-            definitions[i] = new PropertyDefinitionImpl(
-                    this, factory, nodes.get(i));
+        List<PropertyDefinition> definitions = Lists.newArrayList();
+        for (Tree child : definition.getChildren()) {
+            if (child.getName().startsWith(JCR_PROPERTYDEFINITION)) {
+                definitions.add(
+                        new PropertyDefinitionImpl(child, factory, mapper));
+            }
         }
-        return definitions;
+        return definitions.toArray(NO_PROPERTY_DEFINITIONS);
     }
 
     @Override
     public NodeDefinition[] getDeclaredChildNodeDefinitions() {
-        List<NodeUtil> nodes = node.getNodes(JCR_CHILDNODEDEFINITION);
-        NodeDefinition[] definitions = new NodeDefinition[nodes.size()];
-        for (int i = 0; i < nodes.size(); i++) {
-            definitions[i] = new NodeDefinitionImpl(manager, this, nodes.get(i));
+        List<NodeDefinition> definitions = Lists.newArrayList();
+        for (Tree child : definition.getChildren()) {
+            if (child.getName().startsWith(JCR_CHILDNODEDEFINITION)) {
+                definitions.add(
+                        new NodeDefinitionImpl(child, factory, mapper));
+            }
         }
-        return definitions;
+        return definitions.toArray(NO_NODE_DEFINITIONS);
     }
 
     @Override
     public NodeType[] getSupertypes() {
-        Collection<NodeType> types = new ArrayList<NodeType>();
-        Set<String> added = new HashSet<String>();
-        Queue<String> queue = new LinkedList<String>(Arrays.asList(getDeclaredSupertypeNames()));
-        while (!queue.isEmpty()) {
-            String name = queue.remove();
-            if (added.add(name)) {
-                try {
-                    NodeType type = manager.getNodeType(name);
-                    types.add(type);
-                    queue.addAll(Arrays.asList(type.getDeclaredSupertypeNames()));
-                } catch (RepositoryException e) {
-                    throw new IllegalStateException("Inconsistent node type: " + this, e);
+        Map<String, NodeType> supertypes = Maps.newLinkedHashMap();
+        addSupertypes(definition, supertypes);
+        return supertypes.values().toArray(NO_NODE_TYPES);
+    }
+
+    private void addSupertypes(Tree type, Map<String, NodeType> supertypes) {
+        PropertyState property = type.getProperty(JCR_SUPERTYPES);
+        if (property != null) {
+            Tree root = definition.getParent();
+            for (String oakName : property.getValue(Type.NAMES)) {
+                if (!supertypes.containsKey(oakName)) {
+                    Tree supertype = root.getChild(oakName);
+                    checkState(supertype != null);
+                    supertypes.put(
+                            oakName, new NodeTypeImpl(supertype, factory, mapper));
+                    addSupertypes(supertype, supertypes);
                 }
             }
         }
-        return types.toArray(new NodeType[types.size()]);
     }
 
     @Override
     public NodeType[] getDeclaredSupertypes() {
-        String[] names = getDeclaredSupertypeNames();
-        List<NodeType> types = new ArrayList<NodeType>(names.length);
-        for (String name : names) {
-            try {
-                NodeType type = manager.getNodeType(name);
-                types.add(type);
-            }
-            catch (RepositoryException e) {
-                log.warn("Unable to access declared supertype "
-                        + name + " of " + getName(), e);
+        NodeType[] supertypes = NO_NODE_TYPES;
+        String[] oakNames = getNames(JCR_SUPERTYPES);
+        if (oakNames != null && oakNames.length > 0) {
+            supertypes = new NodeType[oakNames.length];
+            Tree root = definition.getParent();
+            for (int i = 0; i < oakNames.length; i++) {
+                Tree type = root.getChild(oakNames[i]);
+                checkState(type != null);
+                supertypes[i] = new NodeTypeImpl(type, factory, mapper);
             }
         }
-        return types.toArray(new NodeType[types.size()]);
+        return supertypes;
     }
 
     @Override
     public NodeTypeIterator getSubtypes() {
-        Collection<NodeType> types = new ArrayList<NodeType>();
-        try {
-            NodeTypeIterator iterator = manager.getAllNodeTypes();
-            while (iterator.hasNext()) {
-                NodeType type = iterator.nextNodeType();
-                if (type.isNodeType(getName()) && !isNodeType(type.getName())) {
-                    types.add(type);
+        Map<String, Set<String>> inheritance = Maps.newHashMap();
+        
+        Tree root = definition.getParent();
+        for (Tree child : root.getChildren()) {
+            String oakName = getOakName(child);
+            PropertyState supertypes = child.getProperty(JCR_SUPERTYPES);
+            if (supertypes != null) {
+                for (String supername : supertypes.getValue(Type.NAMES)) {
+                    Set<String> subtypes = inheritance.get(supername);
+                    if (subtypes == null) {
+                        subtypes = Sets.newHashSet();
+                        inheritance.put(supername, subtypes);
+                    }
+                    subtypes.add(oakName);
+                }
+            }
+        }
+
+        Map<String, NodeType> subtypes = Maps.newHashMap();
+        addSubtypes(getOakName(), subtypes, root, inheritance);
+        return new NodeTypeIteratorAdapter(subtypes.values());
+    }
+
+    private void addSubtypes(
+            String typeName, Map<String, NodeType> subtypes,
+            Tree root, Map<String, Set<String>> inheritance) {
+        Set<String> subnames = inheritance.get(typeName);
+        if (subnames != null) {
+            for (String subname : subnames) {
+                if (!subtypes.containsKey(subname)) {
+                    Tree tree = root.getChild(subname);
+                    subtypes.put(
+                            subname, new NodeTypeImpl(tree, factory, mapper));
                 }
             }
-        } catch (RepositoryException e) {
-            log.warn("Unable to access subtypes of " + getName(), e);
         }
-        return new NodeTypeIteratorAdapter(types);
     }
 
     @Override
     public NodeTypeIterator getDeclaredSubtypes() {
-        Collection<NodeType> types = new ArrayList<NodeType>();
-        try {
-            NodeTypeIterator iterator = manager.getAllNodeTypes();
-            while (iterator.hasNext()) {
-                NodeType type = iterator.nextNodeType();
-                String name = type.getName();
-                if (type.isNodeType(getName()) && !isNodeType(name)) {
-                    List<String> declaredSuperTypeNames = Arrays.asList(type.getDeclaredSupertypeNames());
-                    if (declaredSuperTypeNames.contains(name)) {
-                        types.add(type);
+        List<NodeType> subtypes = Lists.newArrayList();
+
+        String oakName = getOakName();
+        Tree root = definition.getParent();
+        for (Tree child : root.getChildren()) {
+            PropertyState supertypes = child.getProperty(JCR_SUPERTYPES);
+            if (supertypes != null) {
+                for (String name : supertypes.getValue(Type.NAMES)) {
+                    if (oakName.equals(name)) {
+                        subtypes.add(new NodeTypeImpl(child, factory, mapper));
+                        break;
                     }
                 }
             }
-        } catch (RepositoryException e) {
-            log.warn("Unable to access declared subtypes of " + getName(), e);
         }
-        return new NodeTypeIteratorAdapter(types);
+
+        return new NodeTypeIteratorAdapter(subtypes);
     }
 
     @Override
     public boolean isNodeType(String nodeTypeName) {
-        String oakName = node.getNameMapper().getOakNameOrNull(nodeTypeName);
+        String oakName = mapper.getOakNameOrNull(nodeTypeName);
         return internalIsNodeType(oakName);
     }
 
@@ -249,7 +310,7 @@ class NodeTypeImpl implements NodeType {
 
         try {
             Iterable<NodeType> nts = Collections.singleton((NodeType) this);
-            PropertyDefinition def = manager.getDefinition(nts, propertyName, false, value.getType(), false);
+            PropertyDefinition def = getManager().getDefinition(nts, propertyName, false, value.getType(), false);
             return !def.isProtected() &&
                     meetsTypeConstraints(value, def.getRequiredType()) &&
                     meetsValueConstraints(value, def.getValueConstraints());
@@ -268,7 +329,7 @@ class NodeTypeImpl implements NodeType {
         try {
             Iterable<NodeType> nts = Collections.singleton((NodeType) this);
             int type = (values.length == 0) ? PropertyType.STRING : values[0].getType();
-            PropertyDefinition def = manager.getDefinition(nts, propertyName, true, type, false);
+            PropertyDefinition def = getManager().getDefinition(nts, propertyName, true, type, false);
             return !def.isProtected() &&
                     meetsTypeConstraints(values, def.getRequiredType()) &&
                     meetsValueConstraints(values, def.getValueConstraints());
@@ -294,7 +355,7 @@ class NodeTypeImpl implements NodeType {
     public boolean canAddChildNode(String childNodeName, String nodeTypeName) {
         NodeType type;
         try {
-            type = manager.getNodeType(nodeTypeName);
+            type = getManager().getNodeType(nodeTypeName);
             if (type.isAbstract()) {
                 return false;
             }
@@ -363,8 +424,15 @@ class NodeTypeImpl implements NodeType {
     }
 
     //-----------------------------------------------------------< internal >---
-    String getOakName() {
-        return node.getTree().getName();
+
+    private ReadOnlyNodeTypeManager getManager() {
+        final Tree types = definition.getParent();
+        return new ReadOnlyNodeTypeManager() {
+            @Override @CheckForNull
+            protected Tree getTypes() {
+                return types;
+            }
+        };
     }
 
     boolean internalIsNodeType(String oakName) {
@@ -499,8 +567,8 @@ class NodeTypeImpl implements NodeType {
     }
 
     private boolean matches(String childNodeName, String name) {
-        String oakChildName = node.getNameMapper().getOakNameOrNull(childNodeName);
-        String oakName = node.getNameMapper().getOakNameOrNull(name);
+        String oakChildName = mapper.getOakNameOrNull(childNodeName);
+        String oakName = mapper.getOakNameOrNull(name);
         // TODO need a better way to handle SNS
         return oakChildName != null && oakChildName.startsWith(oakName);
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/PropertyDefinitionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/PropertyDefinitionImpl.java?rev=1451200&r1=1451199&r2=1451200&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/PropertyDefinitionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/PropertyDefinitionImpl.java Thu Feb 28 13:58:26 2013
@@ -16,16 +16,18 @@
  */
 package org.apache.jackrabbit.oak.plugins.nodetype;
 
+import java.util.List;
+
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
-import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.PropertyDefinition;
 import javax.jcr.query.qom.QueryObjectModelConstants;
 
 import org.apache.jackrabbit.JcrConstants;
-import org.apache.jackrabbit.oak.util.NodeUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
 
 import static javax.jcr.PropertyType.BINARY;
 import static javax.jcr.PropertyType.BOOLEAN;
@@ -37,19 +39,6 @@ import static javax.jcr.PropertyType.NAM
 import static javax.jcr.PropertyType.PATH;
 import static javax.jcr.PropertyType.REFERENCE;
 import static javax.jcr.PropertyType.STRING;
-import static javax.jcr.PropertyType.TYPENAME_BINARY;
-import static javax.jcr.PropertyType.TYPENAME_BOOLEAN;
-import static javax.jcr.PropertyType.TYPENAME_DATE;
-import static javax.jcr.PropertyType.TYPENAME_DECIMAL;
-import static javax.jcr.PropertyType.TYPENAME_DOUBLE;
-import static javax.jcr.PropertyType.TYPENAME_LONG;
-import static javax.jcr.PropertyType.TYPENAME_NAME;
-import static javax.jcr.PropertyType.TYPENAME_PATH;
-import static javax.jcr.PropertyType.TYPENAME_REFERENCE;
-import static javax.jcr.PropertyType.TYPENAME_STRING;
-import static javax.jcr.PropertyType.TYPENAME_UNDEFINED;
-import static javax.jcr.PropertyType.TYPENAME_URI;
-import static javax.jcr.PropertyType.TYPENAME_WEAKREFERENCE;
 import static javax.jcr.PropertyType.UNDEFINED;
 import static javax.jcr.PropertyType.URI;
 import static javax.jcr.PropertyType.WEAKREFERENCE;
@@ -72,13 +61,11 @@ import static javax.jcr.PropertyType.WEA
  */
 class PropertyDefinitionImpl extends ItemDefinitionImpl implements PropertyDefinition {
 
-    private static final Logger log = LoggerFactory.getLogger(PropertyDefinitionImpl.class);
-
-    private final ValueFactory factory;
+    private static final Value[] NO_VALUES = new Value[0];
 
-    public PropertyDefinitionImpl(NodeType type, ValueFactory factory, NodeUtil node) {
-        super(type, node);
-        this.factory = factory;
+    public PropertyDefinitionImpl(
+            Tree definition, ValueFactory factory, NamePathMapper mapper) {
+        super(definition, factory, mapper);
     }
 
     /**
@@ -90,47 +77,48 @@ class PropertyDefinitionImpl extends Ite
      *
      * @param name the name of the property type.
      * @return the numeric constant value.
-     * @throws IllegalArgumentException if {@code name} is not a valid property type name.
+     * @throws IllegalStateException if {@code name} is not a valid property type name.
      */
     public static int valueFromName(String name) {
-        if (name.equals(TYPENAME_STRING.toUpperCase())) {
+        if ("STRING".equals(name)) {
             return STRING;
-        } else if (name.equals(TYPENAME_BINARY.toUpperCase())) {
+        } else if ("BINARY".equals(name)) {
             return BINARY;
-        } else if (name.equals(TYPENAME_BOOLEAN.toUpperCase())) {
+        } else if ("BOOLEAN".equals(name)) {
             return BOOLEAN;
-        } else if (name.equals(TYPENAME_LONG.toUpperCase())) {
+        } else if ("LONG".equals(name)) {
             return LONG;
-        } else if (name.equals(TYPENAME_DOUBLE.toUpperCase())) {
+        } else if ("DOUBLE".equals(name)) {
             return DOUBLE;
-        } else if (name.equals(TYPENAME_DECIMAL.toUpperCase())) {
+        } else if ("DECIMAL".equals(name)) {
             return DECIMAL;
-        } else if (name.equals(TYPENAME_DATE.toUpperCase())) {
+        } else if ("DATE".equals(name)) {
             return DATE;
-        } else if (name.equals(TYPENAME_NAME.toUpperCase())) {
+        } else if ("NAME".equals(name)) {
             return NAME;
-        } else if (name.equals(TYPENAME_PATH.toUpperCase())) {
+        } else if ("PATH".equals(name)) {
             return PATH;
-        } else if (name.equals(TYPENAME_REFERENCE.toUpperCase())) {
+        } else if ("REFERENCE".equals(name)) {
             return REFERENCE;
-        } else if (name.equals(TYPENAME_WEAKREFERENCE.toUpperCase())) {
+        } else if ("WEAKREFERENCE".equals(name)) {
             return WEAKREFERENCE;
-        } else if (name.equals(TYPENAME_URI.toUpperCase())) {
+        } else if ("URI".equals(name)) {
             return URI;
-        } else if (name.equals(TYPENAME_UNDEFINED.toUpperCase())) {
+        } else if ("UNDEFINED".equals(name)) {
             return UNDEFINED;
         } else {
-            throw new IllegalArgumentException("unknown type: " + name);
+            throw new IllegalStateException("unknown property type: " + name);
         }
     }
 
     //-------------------------------------------------< PropertyDefinition >---
+
     @Override
     public int getRequiredType() {
-        try {
-            return valueFromName(node.getString(JcrConstants.JCR_REQUIREDTYPE, TYPENAME_UNDEFINED));
-        } catch (IllegalArgumentException e) {
-            log.warn("Unexpected jcr:requiredType value", e);
+        String string = getString(JcrConstants.JCR_REQUIREDTYPE);
+        if (string != null) {
+            return valueFromName(string);
+        } else {
             return UNDEFINED;
         }
     }
@@ -138,33 +126,35 @@ class PropertyDefinitionImpl extends Ite
     @Override
     public String[] getValueConstraints() {
         // TODO: namespace mapping?
-        String[] constraints = node.getStrings(JcrConstants.JCR_VALUECONSTRAINTS);
-        if (constraints == null) {
-            constraints = new String[0];
-        }
-        return constraints;
+        return getStrings(JcrConstants.JCR_VALUECONSTRAINTS);
     }
 
     @Override
     public Value[] getDefaultValues() {
-        if (factory != null) {
-            return node.getValues(JcrConstants.JCR_DEFAULTVALUES, factory);
-        } else {
-            log.warn("Cannot create default values: no value factory");
+        PropertyState property =
+                definition.getProperty(JcrConstants.JCR_DEFAULTVALUES);
+        if (property == null) {
             return null;
+        } else if (property.isArray()) {
+            List<Value> values = ValueFactoryImpl.createValues(property, mapper);
+            return values.toArray(NO_VALUES);
+        } else {
+            Value value = ValueFactoryImpl.createValue(property, mapper);
+            return new Value[] { value };
         }
     }
 
     @Override
     public boolean isMultiple() {
-        return node.getBoolean(JcrConstants.JCR_MULTIPLE);
+        return getBoolean(JcrConstants.JCR_MULTIPLE);
     }
 
     @Override
     public String[] getAvailableQueryOperators() {
-        String[] ops = node.getStrings(NodeTypeConstants.JCR_AVAILABLE_QUERY_OPERATORS);
-        if (ops == null) {
-            ops = new String[] {
+        String[] operators =
+                getStrings(NodeTypeConstants.JCR_AVAILABLE_QUERY_OPERATORS);
+        if (operators == null) {
+            operators = new String[] {
                     QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO,
                     QueryObjectModelConstants.JCR_OPERATOR_NOT_EQUAL_TO,
                     QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN,
@@ -173,16 +163,17 @@ class PropertyDefinitionImpl extends Ite
                     QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO,
                     QueryObjectModelConstants.JCR_OPERATOR_LIKE };
         }
-        return ops;
+        return operators;
     }
 
     @Override
     public boolean isFullTextSearchable() {
-        return node.getBoolean(NodeTypeConstants.JCR_IS_FULLTEXT_SEARCHABLE);
+        return getBoolean(NodeTypeConstants.JCR_IS_FULLTEXT_SEARCHABLE);
     }
 
     @Override
     public boolean isQueryOrderable() {
-        return node.getBoolean(NodeTypeConstants.JCR_IS_QUERY_ORDERABLE);
+        return getBoolean(NodeTypeConstants.JCR_IS_QUERY_ORDERABLE);
     }
-}
\ No newline at end of file
+
+}

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=1451200&r1=1451199&r2=1451200&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 Thu Feb 28 13:58:26 2013
@@ -61,7 +61,6 @@ import org.apache.jackrabbit.oak.namepat
 import org.apache.jackrabbit.oak.namepath.NamePathMapperImpl;
 import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.util.NodeUtil;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static javax.jcr.PropertyType.UNDEFINED;
@@ -191,10 +190,10 @@ public abstract class ReadOnlyNodeTypeMa
         List<NodeType> list = Lists.newArrayList();
         Tree types = getTypes();
         if (types != null) {
+            ValueFactory factory = getValueFactory();
+            NamePathMapper mapper = getNamePathMapper();
             for (Tree type : types.getChildren()) {
-                list.add(new NodeTypeImpl(this, getValueFactory(),
-                        new NodeUtil(type, getNamePathMapper())));
-
+                list.add(new NodeTypeImpl(type, factory, mapper));
             }
         }
         return new NodeTypeIteratorAdapter(list);
@@ -470,14 +469,17 @@ public abstract class ReadOnlyNodeTypeMa
     //-----------------------------------------------------------< internal >---
 
     NodeTypeImpl internalGetNodeType(String oakName) throws NoSuchNodeTypeException {
+        ValueFactory factory = getValueFactory();
+        NamePathMapper mapper = getNamePathMapper();
+
         Tree types = getTypes();
         if (types != null) {
             Tree type = types.getChild(oakName);
             if (type != null) {
-                return new NodeTypeImpl(this, getValueFactory(), new NodeUtil(type, getNamePathMapper()));
+                return new NodeTypeImpl(type, factory, mapper);
             }
         }
-        throw new NoSuchNodeTypeException(getNamePathMapper().getJcrName(oakName));
+        throw new NoSuchNodeTypeException(mapper.getJcrName(oakName));
     }
 
     //------------------------------------------------------------< private >---