Author: angela
Date: Tue Oct 30 17:36:00 2012
New Revision: 1403796

URL: http://svn.apache.org/viewvc?rev=1403796&view=rev
Log:
OAK-250 : Enforce jcr constraints for 'protected' items 

- modified TypeValidator such that it uses functionality exposed by the 
nt-manager instead of
   having yet another place where matching property definitions are collected.
  
- added TODO regarding validations of nodes that don't have a primary node type 
set.

- NodeTypeCreationTest#unregister subsequently failed because nt:base could be 
unregistered.
   further investigation showed that didn't work properly before... the test 
succeeded because
   there was an illegalstateexception triggered by invalid node type 
definition, which looked pretty
   strange to me and might be related to the TODO above.

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/EffectiveNodeTypeProvider.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
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadWriteNodeTypeManager.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeValidator.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=1403796&r1=1403795&r2=1403796&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
 Tue Oct 30 17:36:00 2012
@@ -36,11 +36,14 @@ public interface DefinitionProvider {
     NodeDefinition getDefinition(Node parent, Node targetNode) throws 
RepositoryException;
 
     @Nonnull
+    NodeDefinition getDefinition(Iterable<NodeType> parentNodeTypes, String 
nodeName, NodeType nodeType) throws RepositoryException;
+
+    @Nonnull
     PropertyDefinition getDefinition(Node parent, Property targetProperty) 
throws RepositoryException;
 
     @Nonnull
     PropertyDefinition getDefinition(Node parent, String propertyName, boolean 
isMultiple, int type, boolean exactTypeMatch) throws RepositoryException;
 
     @Nonnull
-    PropertyDefinition getDefinition(NodeType nodeType, String propertyName, 
boolean isMultiple, int type, boolean exactTypeMatch) throws 
RepositoryException;
+    PropertyDefinition getDefinition(Iterable<NodeType> nodeTypes, String 
propertyName, boolean isMultiple, int type, boolean exactTypeMatch) throws 
RepositoryException;
 }
\ No newline at end of file

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeProvider.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeProvider.java?rev=1403796&r1=1403795&r2=1403796&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeProvider.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeProvider.java
 Tue Oct 30 17:36:00 2012
@@ -20,6 +20,8 @@ import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.nodetype.NodeType;
 
+import org.apache.jackrabbit.oak.api.Tree;
+
 /**
  * EffectiveNodeTypeProvider... TODO
  *
@@ -35,4 +37,13 @@ public interface EffectiveNodeTypeProvid
      * @throws RepositoryException if the type information can not be accessed
      */
     Iterable<NodeType> getEffectiveNodeTypes(Node targetNode) throws 
RepositoryException;
+
+    /**
+     * Calculates and returns all effective node types of the given tree.
+     *
+     * @param tree
+     * @return all node types of the given tree
+     * @throws RepositoryException if the type information can not be accessed
+     */
+    Iterable<NodeType> getEffectiveNodeTypes(Tree tree) throws 
RepositoryException;
 }
\ 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=1403796&r1=1403795&r2=1403796&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
 Tue Oct 30 17:36:00 2012
@@ -21,6 +21,7 @@ import java.net.URISyntaxException;
 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;
@@ -270,7 +271,8 @@ class NodeTypeImpl implements NodeType {
         }
 
         try {
-            PropertyDefinition def = manager.getDefinition(this, propertyName, 
false, value.getType(), false);
+            Iterable<NodeType> nts = Collections.singleton((NodeType) this);
+            PropertyDefinition def = manager.getDefinition(nts, propertyName, 
false, value.getType(), false);
             return !def.isProtected() &&
                     meetsTypeConstraints(value, def.getRequiredType()) &&
                     meetsValueConstraints(value, def.getValueConstraints());
@@ -287,8 +289,9 @@ 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(this, propertyName, 
true, type, false);
+            PropertyDefinition def = manager.getDefinition(nts, 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=1403796&r1=1403795&r2=1403796&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
 Tue Oct 30 17:36:00 2012
@@ -46,12 +46,20 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Queues;
 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.namepath.NameMapper;
 import org.apache.jackrabbit.oak.namepath.NamePathMapperImpl;
 import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import static javax.jcr.PropertyType.UNDEFINED;
+import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
+import static org.apache.jackrabbit.oak.api.Type.STRING;
+import static org.apache.jackrabbit.oak.api.Type.STRINGS;
 
 /**
  * Base implementation of a {@link NodeTypeManager} with support for reading
@@ -61,6 +69,8 @@ import static javax.jcr.PropertyType.UND
  */
 public abstract class ReadOnlyNodeTypeManager implements NodeTypeManager, 
EffectiveNodeTypeProvider, DefinitionProvider {
 
+    private static final Logger log = 
LoggerFactory.getLogger(ReadOnlyNodeTypeManager.class);
+
     /**
      * Returns the internal name for the specified JCR name.
      *
@@ -243,6 +253,32 @@ public abstract class ReadOnlyNodeTypeMa
         return getEffectiveNodeTypes(queue);
     }
 
+    @Override
+    public Iterable<NodeType> getEffectiveNodeTypes(Tree tree) throws 
RepositoryException {
+        Queue<NodeType> queue = Queues.newArrayDeque();
+
+        NodeType primaryType;
+        PropertyState jcrPrimaryType = tree.getProperty(JCR_PRIMARYTYPE);
+        if (jcrPrimaryType != null) {
+            String ntName = jcrPrimaryType.getValue(STRING);
+            primaryType = getNodeType(ntName);
+        } else {
+            log.warn("Item at {} has no primary type. Assuming 
nt:unstructured", tree.getPath());
+            primaryType = getNodeType(NT_UNSTRUCTURED);
+        }
+        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(getNodeType(ntName));
+            }
+        }
+        queue.addAll(mixinTypes);
+
+        return getEffectiveNodeTypes(queue);
+    }
 
     //-------------------------------------------------< DefinitionProvider 
>---
 
@@ -294,6 +330,51 @@ public abstract class ReadOnlyNodeTypeMa
     }
 
     @Override
+    public NodeDefinition getDefinition(Iterable<NodeType> parentNodeTypes, 
String nodeName, NodeType nodeType) throws RepositoryException {
+        List<NodeDefinition> residualDefs = new ArrayList<NodeDefinition>();
+        // TODO: This may need to be optimized
+        // TODO: cleanup redundancy with getDefinition(Node, Node)
+        for (NodeType nt : parentNodeTypes) {
+            for (NodeDefinition def : nt.getDeclaredChildNodeDefinitions()) {
+                String defName = def.getName();
+                if (nodeName.equals(defName)) {
+                    boolean match = true;
+                    // TODO: check again if passing null nodeType is legal.
+                    if (nodeType != null) {
+                        for (String type : def.getRequiredPrimaryTypeNames()) {
+                            if (!nodeType.isNodeType(type)) {
+                                match = false;
+                            }
+                        }
+                    }
+                    if (match) {
+                        return def;
+                    }
+                } else if ("*".equals(defName)) {
+                    residualDefs.add(def);
+                }
+            }
+        }
+
+        for (NodeDefinition def : residualDefs) {
+            String defName = def.getName();
+            if ("*".equals(defName)) {
+                boolean match = true;
+                for (String type : def.getRequiredPrimaryTypeNames()) {
+                    if (!nodeType.isNodeType(type)) {
+                        match = false;
+                    }
+                }
+                if (match) {
+                    return def;
+                }
+            }
+        }
+
+        throw new RepositoryException("No matching node definition found for " 
+ this);
+    }
+
+    @Override
     public PropertyDefinition getDefinition(Node parent, Property 
targetProperty) throws RepositoryException {
         String name = targetProperty.getName();
         boolean isMultiple = targetProperty.isMultiple();
@@ -354,9 +435,11 @@ public abstract class ReadOnlyNodeTypeMa
     }
 
     @Override
-    public PropertyDefinition getDefinition(NodeType nodeType, String 
propertyName, boolean isMultiple, int type, boolean exactTypeMatch) throws 
RepositoryException {
+    public PropertyDefinition getDefinition(Iterable<NodeType> nodeTypes, 
String propertyName, boolean isMultiple, int type, boolean exactTypeMatch) 
throws RepositoryException {
         Queue<NodeType> queue = Queues.newArrayDeque();
-        queue.add(nodeType);
+        for (NodeType nt : nodeTypes) {
+            queue.add(nt);
+        }
         Collection<NodeType> effective = getEffectiveNodeTypes(queue);
         return getPropertyDefinition(effective, propertyName, isMultiple, 
type, exactTypeMatch);
     }
@@ -364,7 +447,7 @@ public abstract class ReadOnlyNodeTypeMa
     //------------------------------------------------------------< private 
>---
 
     private Collection<NodeType> getEffectiveNodeTypes(Queue<NodeType> queue) {
-        Map<String, NodeType> types = Maps.<String, NodeType>newHashMap();
+        Map<String, NodeType> types = Maps.newHashMap();
         while (!queue.isEmpty()) {
             NodeType type = queue.remove();
             String name = type.getName();

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadWriteNodeTypeManager.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadWriteNodeTypeManager.java?rev=1403796&r1=1403795&r2=1403796&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadWriteNodeTypeManager.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadWriteNodeTypeManager.java
 Tue Oct 30 17:36:00 2012
@@ -354,6 +354,13 @@ public abstract class ReadWriteNodeTypeM
 
     @Override
     public void unregisterNodeType(String name) throws RepositoryException {
+        // TODO: review again. added to make tck happy.
+        // TODO  before refactoring the type-validation removing nt:based fail 
with
+        // TODO  IllegalStateException: Inconsistent node type: 
org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeImpl@55ab3cda
+        if (NT_BASE.equals(name)) {
+            throw new RepositoryException("nt:base cannot be removed.");
+        }
+
         Tree type = null;
         Root root = getWriteRoot();
         Tree types = root.getTree(NODE_TYPES_PATH);
@@ -383,6 +390,13 @@ public abstract class ReadWriteNodeTypeM
 
         try {
             for (String name : names) {
+                // TODO: review again. added to make tck happy.
+                // TODO  before refactoring the type-validation removing 
nt:based fail with
+                // TODO  IllegalStateException: Inconsistent node type: 
org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeImpl@55ab3cda
+                if (NT_BASE.equals(name)) {
+                    throw new RepositoryException("nt:base cannot be 
removed.");
+                }
+
                 Tree type = types.getChild(getOakName(name));
                 if (type == null) {
                     throw new NoSuchNodeTypeException("Node type " + name + " 
can not be unregistered.");

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeValidator.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeValidator.java?rev=1403796&r1=1403795&r2=1403796&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeValidator.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeValidator.java
 Tue Oct 30 17:36:00 2012
@@ -16,35 +16,30 @@
  */
 package org.apache.jackrabbit.oak.plugins.nodetype;
 
-import java.util.Collections;
 import java.util.List;
-
+import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.nodetype.NodeDefinition;
 import javax.jcr.nodetype.NodeType;
-import javax.jcr.nodetype.NodeTypeManager;
 import javax.jcr.nodetype.PropertyDefinition;
 
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.core.ReadOnlyTree;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
 import org.apache.jackrabbit.oak.spi.commit.Validator;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
-import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
 import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
-import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
 import static org.apache.jackrabbit.oak.api.Type.STRING;
 import static org.apache.jackrabbit.oak.api.Type.STRINGS;
 
@@ -60,7 +55,7 @@ import static org.apache.jackrabbit.oak.
 class TypeValidator implements Validator {
     private static final Logger log = 
LoggerFactory.getLogger(TypeValidator.class);
 
-    private final NodeTypeManager ntm;
+    private final ReadOnlyNodeTypeManager ntm;
     private final ReadOnlyTree parent;
     private final NamePathMapper mapper;
 
@@ -74,7 +69,7 @@ class TypeValidator implements Validator
         return parentType;
     }
 
-    public TypeValidator(NodeTypeManager ntm, ReadOnlyTree parent, 
NamePathMapper mapper) {
+    public TypeValidator(ReadOnlyNodeTypeManager ntm, ReadOnlyTree parent, 
NamePathMapper mapper) {
         this.ntm = ntm;
         this.parent = parent;
         this.mapper = mapper;
@@ -129,13 +124,7 @@ class TypeValidator implements Validator
     @Override
     public Validator childNodeAdded(String name, NodeState after) throws 
CommitFailedException {
         try {
-            PropertyState type = after.getProperty(JCR_PRIMARYTYPE);
-            if (type == null || type.count() == 0) {
-                getParentType().canAddChildNode(name);
-            } else {
-                String ntName = type.getValue(STRING, 0);
-                getParentType().checkAddChildNode(name, ntName);
-            }
+            getParentType().checkAddChildNode(name, getNodeType(after));
 
             ReadOnlyTree addedTree = new ReadOnlyTree(parent, name, after);
             EffectiveNodeType addedType = getEffectiveNodeType(addedTree);
@@ -156,7 +145,7 @@ class TypeValidator implements Validator
     @Override
     public Validator childNodeDeleted(String name, NodeState before) throws 
CommitFailedException {
         try {
-            getParentType().checkRemoveNode(name);
+            getParentType().checkRemoveNode(name, getNodeType(before));
             return null;
         } catch (RepositoryException e) {
             throw new CommitFailedException("Cannot remove node '" + name + "' 
at " + parent.getPath(), e);
@@ -186,129 +175,95 @@ class TypeValidator implements Validator
         }
     }
 
-    private NodeType getPrimaryType(Tree tree) throws RepositoryException {
-        PropertyState jcrPrimaryType = tree.getProperty(JCR_PRIMARYTYPE);
-        if (jcrPrimaryType != null) {
-            String ntName = jcrPrimaryType.getValue(STRING);
-            return ntm.getNodeType(ntName);
+    @CheckForNull
+    private NodeType getNodeType(NodeState state) throws RepositoryException {
+        PropertyState type = state.getProperty(JCR_PRIMARYTYPE);
+        if (type == null || type.count() == 0) {
+            // TODO: review again
+            return null;
         } else {
-            log.warn("Item at {} has no primary type. Assuming 
nt:unstructured", tree.getPath());
-            return ntm.getNodeType(NT_UNSTRUCTURED);
+            String ntName = type.getValue(STRING, 0);
+            return ntm.getNodeType(ntName);
         }
     }
 
-    private List<NodeType> getMixinTypes(Tree tree) throws RepositoryException 
{
-        List<NodeType> types = Lists.newArrayList();
-        PropertyState jcrMixinType = tree.getProperty(JCR_MIXINTYPES);
-        if (jcrMixinType != null) {
-            for (String ntName : jcrMixinType.getValue(STRINGS)) {
-                types.add(ntm.getNodeType(ntName));
-            }
-        }
-        return types;
+    private static boolean isHidden(PropertyState state) {
+        return NodeStateUtils.isHidden(state.getName());
     }
 
     // FIXME: the same is also required on JCR level. probably keeping that in 
1 single location would be preferable.
     private EffectiveNodeType getEffectiveNodeType(Tree tree) throws 
RepositoryException {
-        return new EffectiveNodeType(getPrimaryType(tree), 
getMixinTypes(tree));
+        return new EffectiveNodeType(ntm.getEffectiveNodeTypes(tree));
     }
 
     private class EffectiveNodeType {
         private final Iterable<NodeType> allTypes;
 
-        public EffectiveNodeType(NodeType primaryType, List<NodeType> 
mixinTypes) {
-            this.allTypes = Iterables.concat(mixinTypes, 
Collections.singleton(primaryType));
+        public EffectiveNodeType(Iterable<NodeType> allTypes) {
+            this.allTypes = allTypes;
         }
 
-        public void checkSetProperty(PropertyState property) throws 
ConstraintViolationException {
-            if (isProtectedProperty(property.getName())) {
+        public void checkSetProperty(PropertyState property) throws 
RepositoryException {
+            PropertyDefinition definition = getDefinition(property);
+            if (definition.isProtected()) {
                 return;
             }
-            if (property.isArray()) {
+
+            NodeType nt = definition.getDeclaringNodeType();
+            if (definition.isMultiple()) {
                 List<Value> values = ValueFactoryImpl.createValues(property, 
mapper);
-                checkSetProperty(property.getName(), values);
+                if (!nt.canSetProperty(property.getName(), values.toArray(new 
Value[values.size()]))) {
+                    throw new ConstraintViolationException("Cannot set 
property '" + property.getName() + "' to '" + values + '\'');
+                }
             } else {
-                Value value = ValueFactoryImpl.createValue(property, mapper);
-                checkSetProperty(property.getName(), value);
-            }
-        }
-
-        private void checkSetProperty(final String propertyName, List<Value> 
values)
-                throws ConstraintViolationException {
-            if (isProtectedProperty(propertyName)) {
-                return;
-            }
-            Value[] valueArray = values.toArray(new Value[values.size()]);
-            for (NodeType nodeType : allTypes) {
-                if (nodeType.canSetProperty(propertyName, valueArray)) {
-                    return;
+                Value v = ValueFactoryImpl.createValue(property, mapper);
+                if (!nt.canSetProperty(property.getName(), v)) {
+                    throw new ConstraintViolationException("Cannot set 
property '" + property.getName() + "' to '" + v + '\'');
                 }
             }
-            throw new ConstraintViolationException("Cannot set property '" + 
propertyName + "' to '" + values + '\'');
         }
 
-        private void checkSetProperty(final String propertyName, Value value) 
throws ConstraintViolationException {
-            if (isProtectedProperty(propertyName)) {
+        public void checkRemoveProperty(PropertyState property) throws 
RepositoryException {
+            PropertyDefinition definition = getDefinition(property);
+            if (definition.isProtected()) {
                 return;
             }
-            for (NodeType nodeType : allTypes) {
-                if (nodeType.canSetProperty(propertyName, value)) {
-                    return;
-                }
-            }
-            throw new ConstraintViolationException("Cannot set property '" + 
propertyName + "' to '" + value + '\'');
-        }
 
-        public void checkRemoveProperty(PropertyState property) throws 
ConstraintViolationException {
-            if (isProtectedProperty(property.getName())) {
-                return;
+            if 
(!definition.getDeclaringNodeType().canRemoveProperty(property.getName())) {
+                throw new ConstraintViolationException("Cannot remove property 
'" + property.getName() + '\'');
             }
-            final String name = property.getName();
-            for (NodeType nodeType : allTypes) {
-                if (nodeType.canRemoveProperty(name)) {
-                    return;
-                }
-            }
-            throw new ConstraintViolationException("Cannot remove property '" 
+ property.getName() + '\'');
         }
 
-        public void checkRemoveNode(final String name) throws 
ConstraintViolationException {
-            if (isProtectedNode(name)) {
+        public void checkRemoveNode(String name, NodeType nodeType) throws 
RepositoryException {
+            NodeDefinition definition = getDefinition(name, nodeType);
+            if (definition.isProtected()) {
                 return;
             }
-            for (NodeType nodeType : allTypes) {
-                if (nodeType.canRemoveNode(name)) {
-                    return;
-                }
-            }
-            throw new ConstraintViolationException("Cannot remove node '" + 
name + '\'');
-        }
 
-        public void canAddChildNode(final String name) throws 
ConstraintViolationException {
-            if (isProtectedNode(name)) {
-                return;
+            if (!definition.getDeclaringNodeType().canRemoveNode(name)) {
+                throw new ConstraintViolationException("Cannot remove node '" 
+ name + '\'');
             }
-            for (NodeType nodeType : allTypes) {
-                if (nodeType.canAddChildNode(name)) {
-                    return;
-                }
-            }
-            throw new ConstraintViolationException("Cannot add node '" + name 
+ '\'');
         }
 
-        public void checkAddChildNode(final String name, final String ntName) 
throws ConstraintViolationException {
-            if (isProtectedNode(name)) {
+        public void checkAddChildNode(String name, NodeType nodeType) throws 
RepositoryException {
+            NodeDefinition definition = getDefinition(name, nodeType);
+            if (definition.isProtected()) {
                 return;
             }
-            for (NodeType nodeType : allTypes) {
-                if (nodeType.canAddChildNode(name, ntName)) {
-                    return;
+
+            if (nodeType == null) {
+                if (!definition.getDeclaringNodeType().canAddChildNode(name)) {
+                    throw new ConstraintViolationException("Cannot add node '" 
+ name + '\'');
+                }
+            } else {
+                if (!definition.getDeclaringNodeType().canAddChildNode(name, 
nodeType.getName())) {
+                    throw new ConstraintViolationException("Cannot add node '" 
+ name + "' of type '" + nodeType.getName() + '\'');
                 }
             }
-            throw new ConstraintViolationException("Cannot add node '" + name 
+ "' of type '" + ntName + '\'');
+
         }
 
-        public void checkMandatoryItems(final ReadOnlyTree tree) throws 
ConstraintViolationException {
+        public void checkMandatoryItems(ReadOnlyTree tree) throws 
ConstraintViolationException {
             for (NodeType nodeType : allTypes) {
                 for (PropertyDefinition pd : 
nodeType.getPropertyDefinitions()) {
                     String name = pd.getName();
@@ -327,26 +282,15 @@ class TypeValidator implements Validator
             }
         }
 
-        private boolean isProtectedProperty(String propertyName) {
-            // FIXME: duplicated code. we should use one common way to 
determine a matching definition (DefinitionProvider)
-            for (NodeType nodeType : allTypes) {
-                for (PropertyDefinition pd : 
nodeType.getPropertyDefinitions()) {
-                    if (propertyName.equals(pd.getName()) && pd.isProtected()) 
{
-                        return true;
-                    }
-                }
-            }
-            for (NodeType nodeType : allTypes) {
-                for (PropertyDefinition pd : 
nodeType.getPropertyDefinitions()) {
-                    if ("*".equals(pd.getName()) && pd.isProtected()) {
-                        return true;
-                    }
-                }
-            }
-            return false;
+        private PropertyDefinition getDefinition(PropertyState property) 
throws RepositoryException {
+            String propertyName = property.getName();
+            int propertyType = property.getType().tag();
+            boolean isMultiple = property.isArray();
+
+            return ntm.getDefinition(allTypes, propertyName, isMultiple, 
propertyType, true);
         }
 
-        private boolean isProtectedNode(String nodeName) {
+        private NodeDefinition getDefinition(String nodeName, NodeType 
nodeType) throws RepositoryException {
             // 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")) {
@@ -355,27 +299,9 @@ class TypeValidator implements Validator
             if (nodeName.startsWith("jcr:propertyDefinition") && 
!nodeName.equals("jcr:propertyDefinition")) {
                 nameToCheck = nodeName.substring(0, 
"jcr:propertyDefinition".length());
             }
-            // FIXME: duplicated code. we should use one common way to 
determine a matching definition (DefinitionProvider)
-            for (NodeType nodeType : allTypes) {
-                for (NodeDefinition nd : nodeType.getChildNodeDefinitions()) {
-                    if (nameToCheck.equals(nd.getName()) && nd.isProtected()) {
-                        return true;
-                    }
-                }
-            }
-            for (NodeType nodeType : allTypes) {
-                for (NodeDefinition nd : nodeType.getChildNodeDefinitions()) {
-                    if ("*".equals(nd.getName()) && nd.isProtected()) {
-                        return true;
-                    }
-                }
-            }
-            return false;
+            return ntm.getDefinition(allTypes, nameToCheck, nodeType);
         }
 
-    }
 
-    private static boolean isHidden(PropertyState state) {
-        return NodeStateUtils.isHidden(state.getName());
     }
 }


Reply via email to