Return-Path: X-Original-To: apmail-jackrabbit-oak-commits-archive@minotaur.apache.org Delivered-To: apmail-jackrabbit-oak-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 656B1D57F for ; Wed, 12 Dec 2012 11:34:00 +0000 (UTC) Received: (qmail 84255 invoked by uid 500); 12 Dec 2012 11:34:00 -0000 Delivered-To: apmail-jackrabbit-oak-commits-archive@jackrabbit.apache.org Received: (qmail 84197 invoked by uid 500); 12 Dec 2012 11:33:58 -0000 Mailing-List: contact oak-commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: oak-dev@jackrabbit.apache.org Delivered-To: mailing list oak-commits@jackrabbit.apache.org Received: (qmail 84153 invoked by uid 99); 12 Dec 2012 11:33:57 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 12 Dec 2012 11:33:57 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 12 Dec 2012 11:33:48 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 56C15238899C; Wed, 12 Dec 2012 11:33:26 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1420622 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ Date: Wed, 12 Dec 2012 11:33:24 -0000 To: oak-commits@jackrabbit.apache.org From: angela@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20121212113326.56C15238899C@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: angela Date: Wed Dec 12 11:33:23 2012 New Revision: 1420622 URL: http://svn.apache.org/viewvc?rev=1420622&view=rev Log: OAK-494 : Cleanup ReadOnlyNodeTypeManager (Work in Progress) Added: 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/EffectiveNodeTypeImpl.java Modified: 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 jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java Added: 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=1420622&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeType.java (added) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeType.java Wed Dec 12 11:33:23 2012 @@ -0,0 +1,94 @@ +/* + * 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 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; +import org.apache.jackrabbit.oak.api.Tree; + +/** + * EffectiveNodeType... TODO + */ +public interface EffectiveNodeType { + + Iterable getAllNodeTypes(); + + //Iterable getInheritedNodeTypes(); + //Iterable getMergedNodeTypes(); + + /** + * Determines whether this effective node type representation includes + * (either through inheritance or aggregation) the given node type. + * + * @param nodeTypeName name of node type + * @return {@code true} if the given node type is included, otherwise {@code false}. + */ + boolean includesNodeType(String nodeTypeName); + + /** + * Determines whether this effective node type representation includes + * (either through inheritance or aggregation) all of the given node types. + * + * @param nodeTypeNames array of node type names + * @return {@code true} if all of the given node types are included, + * otherwise {@code false} + */ + boolean includesNodeTypes(String[] nodeTypeNames); + + /** + * Determines whether this effective node type supports adding + * the specified mixin. + * @param mixin name of mixin type + * @return {@code true} if the mixin type is supported, otherwise {@code false} + */ + boolean supportsMixin(String mixin); + + Iterable getNodeDefinitions(); + + Iterable getPropertyDefinitions(); + + Iterable getAutoCreateNodeDefinitions(); + + Iterable getAutoCreatePropertyDefinitions(); + + Iterable getMandatoryNodeDefinitions(); + + Iterable getMandatoryPropertyDefinitions(); + + Iterable getNamedNodeDefinitions(String name); + + Iterable getNamedPropertyDefinitions(String name); + + Iterable getUnnamedNodeDefinitions(); + + Iterable getUnnamedPropertyDefinitions(); + + void checkSetProperty(PropertyState property) throws RepositoryException; + + void checkRemoveProperty(PropertyState property) throws RepositoryException; + + void checkAddChildNode(String name, NodeType nodeType) throws RepositoryException; + + void checkRemoveNode(String name, NodeType nodeType) throws RepositoryException; + + void checkMandatoryItems(Tree tree) throws ConstraintViolationException; +} Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeImpl.java?rev=1420622&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeImpl.java (added) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeImpl.java Wed Dec 12 11:33:23 2012 @@ -0,0 +1,291 @@ +/* + * 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 java.util.ArrayList; +import java.util.Collection; +import java.util.List; +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.PropertyDefinition; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import org.apache.jackrabbit.oak.api.PropertyState; +import org.apache.jackrabbit.oak.api.Tree; +import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl; + +/** + * EffectiveNodeTypeImpl... TODO implementation needs optimization + */ +class EffectiveNodeTypeImpl implements EffectiveNodeType { + + private final Collection nodeTypes; + private final ReadOnlyNodeTypeManager ntMgr; + + EffectiveNodeTypeImpl(Collection nodeTypes, ReadOnlyNodeTypeManager ntMgr) { + this.nodeTypes = nodeTypes; + this.ntMgr = ntMgr; + } + + @Override + public Iterable getAllNodeTypes() { + return nodeTypes; + } + + @Override + public boolean includesNodeType(String nodeTypeName) { + for (NodeType type : nodeTypes) { + if (type.isNodeType(nodeTypeName)) { + return true; + } + } + return false; + } + + @Override + public boolean includesNodeTypes(String[] nodeTypeNames) { + for (String ntName : nodeTypeNames) { + if (!includesNodeType(ntName)) { + return false; + } + } + return true; + } + + @Override + public boolean supportsMixin(String mixin) { + // TODO: add implementation (-> OAK-505) + return false; + } + + @Override + public Iterable getNodeDefinitions() { + List definitions = new ArrayList(); + for (NodeType nt : nodeTypes) { + definitions.addAll(((NodeTypeImpl) nt).internalGetChildDefinitions()); + } + return definitions; + } + + @Override + public Iterable getPropertyDefinitions() { + List definitions = new ArrayList(); + for (NodeType nt : nodeTypes) { + definitions.addAll(((NodeTypeImpl) nt).internalGetPropertyDefinitions()); + } + return definitions; + } + + @Override + public Iterable getAutoCreateNodeDefinitions() { + return Iterables.filter(getNodeDefinitions(), new Predicate() { + @Override + public boolean apply(NodeDefinition nodeDefinition) { + return nodeDefinition.isAutoCreated(); + } + }); + } + + @Override + public Iterable getAutoCreatePropertyDefinitions() { + return Iterables.filter(getPropertyDefinitions(), new Predicate() { + @Override + public boolean apply(PropertyDefinition propertyDefinition) { + return propertyDefinition.isAutoCreated(); + } + }); + } + + @Override + public Iterable getMandatoryNodeDefinitions() { + return Iterables.filter(getNodeDefinitions(), new Predicate() { + @Override + public boolean apply(NodeDefinition nodeDefinition) { + return nodeDefinition.isMandatory(); + } + }); + } + + @Override + public Iterable getMandatoryPropertyDefinitions() { + return Iterables.filter(getPropertyDefinitions(), new Predicate() { + @Override + public boolean apply(PropertyDefinition propertyDefinition) { + return propertyDefinition.isMandatory(); + } + }); + } + + @Override + public Iterable getNamedNodeDefinitions(final String name) { + return Iterables.filter(getNodeDefinitions(), new Predicate() { + @Override + public boolean apply(NodeDefinition nodeDefinition) { + String childName = nodeDefinition.getName(); + return childName.equals(name); + } + }); + } + + @Override + public Iterable getNamedPropertyDefinitions(final String name) { + return Iterables.filter(getPropertyDefinitions(), new Predicate() { + @Override + public boolean apply(PropertyDefinition propertyDefinition) { + String propName = propertyDefinition.getName(); + return propName.equals(name); + } + }); + } + + @Override + public Iterable getUnnamedNodeDefinitions() { + return Iterables.filter(getNodeDefinitions(), new Predicate() { + @Override + public boolean apply(NodeDefinition nodeDefinition) { + return "*".equals(nodeDefinition.getName()); + } + }); + } + + @Override + public Iterable getUnnamedPropertyDefinitions() { + return Iterables.filter(getPropertyDefinitions(), new Predicate() { + @Override + public boolean apply(PropertyDefinition propertyDefinition) { + return "*".equals(propertyDefinition.getName()); + } + }); + } + + @Override + public void checkSetProperty(PropertyState property) throws RepositoryException { + PropertyDefinition definition = getDefinition(property); + if (definition.isProtected()) { + return; + } + + NodeType nt = definition.getDeclaringNodeType(); + if (definition.isMultiple()) { + List values = ValueFactoryImpl.createValues(property, ntMgr.getNamePathMapper()); + if (!nt.canSetProperty(property.getName(), values.toArray(new Value[values.size()]))) { + throw new ConstraintViolationException("Cannot set property '" + property.getName() + "' to '" + values + '\''); + } + } else { + Value v = ValueFactoryImpl.createValue(property, ntMgr.getNamePathMapper()); + if (!nt.canSetProperty(property.getName(), v)) { + throw new ConstraintViolationException("Cannot set property '" + property.getName() + "' to '" + v + '\''); + } + } + } + + @Override + public void checkRemoveProperty(PropertyState property) throws RepositoryException { + PropertyDefinition definition = getDefinition(property); + if (definition.isProtected()) { + return; + } + + if (!definition.getDeclaringNodeType().canRemoveProperty(property.getName())) { + throw new ConstraintViolationException("Cannot remove property '" + property.getName() + '\''); + } + } + + @Override + public void checkAddChildNode(String name, NodeType nodeType) throws RepositoryException { + NodeDefinition definition = getDefinition(name, nodeType); + if (definition == null) { + throw new ConstraintViolationException("No matching node definition found for " + name); + } + + if (definition.isProtected()) { + 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() + '\''); + } + } + } + + @Override + public void checkRemoveNode(String name, NodeType nodeType) throws RepositoryException { + NodeDefinition definition = getDefinition(name, nodeType); + if (definition == null) { + throw new ConstraintViolationException("No matching node definition found for " + name); + } + + if (definition.isProtected()) { + return; + } + + if (!definition.getDeclaringNodeType().canRemoveNode(name)) { + throw new ConstraintViolationException("Cannot remove node '" + name + '\''); + } + } + + @Override + public void checkMandatoryItems(Tree tree) throws ConstraintViolationException { + for (NodeType nodeType : nodeTypes) { + for (PropertyDefinition pd : nodeType.getPropertyDefinitions()) { + String name = pd.getName(); + if (pd.isMandatory() && !pd.isProtected() && tree.getProperty(name) == null) { + throw new ConstraintViolationException( + "Property '" + name + "' in '" + nodeType.getName() + "' is mandatory"); + } + } + for (NodeDefinition nd : nodeType.getChildNodeDefinitions()) { + String name = nd.getName(); + if (nd.isMandatory() && !nd.isProtected() && tree.getChild(name) == null) { + throw new ConstraintViolationException( + "Node '" + name + "' in '" + nodeType.getName() + "' is mandatory"); + } + } + } + } + + //------------------------------------------------------------< private >--- + + private PropertyDefinition getDefinition(PropertyState property) throws RepositoryException { + String propertyName = property.getName(); + int propertyType = property.getType().tag(); + boolean isMultiple = property.isArray(); + + return ntMgr.getDefinition(nodeTypes, propertyName, isMultiple, propertyType, true); + } + + 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")) { + nameToCheck = nodeName.substring(0, "jcr:childNodeDefinition".length()); + } + if (nodeName.startsWith("jcr:propertyDefinition") && !nodeName.equals("jcr:propertyDefinition")) { + nameToCheck = nodeName.substring(0, "jcr:propertyDefinition".length()); + } + return ntMgr.getDefinition(nodeTypes, nameToCheck, nodeType); + } +} 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=1420622&r1=1420621&r2=1420622&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 Wed Dec 12 11:33:23 2012 @@ -19,14 +19,11 @@ package org.apache.jackrabbit.oak.plugin import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.nodetype.NoSuchNodeTypeException; -import javax.jcr.nodetype.NodeType; import org.apache.jackrabbit.oak.api.Tree; /** * EffectiveNodeTypeProvider... TODO - * - * FIXME: see also TypeValidator which has it's own private EffectiveNodeType class. See OAK-412 */ public interface EffectiveNodeTypeProvider { @@ -46,8 +43,7 @@ public interface EffectiveNodeTypeProvid boolean isNodeType(Tree tree, String nodeTypeName) throws NoSuchNodeTypeException, RepositoryException; /** - * FIXME in contrast what the method name implies this method returns the transitive closure of the super types - * Calculates and returns all effective node types of the given node. + * Calculates and returns the effective node types of the given node. * * @param targetNode the node for which the types should be calculated. * @return all types of the given node @@ -55,11 +51,10 @@ public interface EffectiveNodeTypeProvid * @see JCR 2.0 Specification, * Section 3.7.6.5 for the definition of the effective node type. */ - Iterable getEffectiveNodeTypes(Node targetNode) throws RepositoryException; + EffectiveNodeType getEffectiveNodeType(Node targetNode) throws RepositoryException; /** - * FIXME in contrast what the method name implies this method returns the transitive closure of the super types - * Calculates and returns all effective node types of the given tree. + * Calculates and returns the effective node types of the given tree. * * @param tree * @return all node types of the given tree @@ -67,5 +62,5 @@ public interface EffectiveNodeTypeProvid * @see JCR 2.0 Specification, * Section 3.7.6.5 for the definition of the effective node type. */ - Iterable getEffectiveNodeTypes(Tree tree) throws RepositoryException; + EffectiveNodeType getEffectiveNodeType(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=1420622&r1=1420621&r2=1420622&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 Wed Dec 12 11:33:23 2012 @@ -86,6 +86,7 @@ class NodeTypeImpl implements NodeType { this.node = node; } + //-----------------------------------------------------------< NodeType >--- @Override public String getName() { String name = node.getName(JCR_NODETYPENAME); @@ -240,27 +241,13 @@ class NodeTypeImpl implements NodeType { @Override public PropertyDefinition[] getPropertyDefinitions() { - // TODO distinguish between additive and overriding property definitions. See 3.7.6.8 Item Definitions in Subtypes - Collection definitions = - new ArrayList(); - for (NodeType type : getSupertypes()) { - definitions.addAll(Arrays.asList( - type.getDeclaredPropertyDefinitions())); - } - definitions.addAll(Arrays.asList(getDeclaredPropertyDefinitions())); + Collection definitions = internalGetPropertyDefinitions(); return definitions.toArray(new PropertyDefinition[definitions.size()]); } @Override public NodeDefinition[] getChildNodeDefinitions() { - // TODO distinguish between additive and overriding node definitions. See 3.7.6.8 Item Definitions in Subtypes - Collection definitions = - new ArrayList(); - for (NodeType type : getSupertypes()) { - definitions.addAll(Arrays.asList( - type.getDeclaredChildNodeDefinitions())); - } - definitions.addAll(Arrays.asList(getDeclaredChildNodeDefinitions())); + Collection definitions = internalGetChildDefinitions(); return definitions.toArray(new NodeDefinition[definitions.size()]); } @@ -301,15 +288,116 @@ class NodeTypeImpl implements NodeType { } } + @Override + public boolean canAddChildNode(String childNodeName) { + // FIXME: properly calculate matching definition + for (NodeDefinition definition : getChildNodeDefinitions()) { + String name = definition.getName(); + if (matches(childNodeName, name) || "*".equals(name)) { + return !definition.isProtected() && definition.getDefaultPrimaryType() != null; + } + } + return false; + } + + @Override + public boolean canAddChildNode(String childNodeName, String nodeTypeName) { + NodeType type; + try { + type = manager.getNodeType(nodeTypeName); + if (type.isAbstract()) { + return false; + } + } catch (NoSuchNodeTypeException e) { + return false; + } catch (RepositoryException e) { + log.warn("Unable to access node type " + nodeTypeName, e); + return false; + } + // FIXME: properly calculate matching definition + for (NodeDefinition definition : getChildNodeDefinitions()) { + String name = definition.getName(); + if (matches(childNodeName, name) || "*".equals(name)) { + if (definition.isProtected()) { + return false; + } + for (String required : definition.getRequiredPrimaryTypeNames()) { + if (type.isNodeType(required)) { + return true; + } + } + } + } + return false; + } + + @Override + public boolean canRemoveItem(String itemName) { + return canRemoveNode(itemName) || canRemoveProperty(itemName); + } + + @Override + public boolean canRemoveNode(String nodeName) { + // FIXME: properly calculate matching definition taking residual definitions into account. + NodeDefinition[] childNodeDefinitions = getChildNodeDefinitions(); + for (NodeDefinition definition : childNodeDefinitions) { + String name = definition.getName(); + if (matches(nodeName, name)) { + if (definition.isMandatory() || definition.isProtected()) { + return false; + } + } + } + return childNodeDefinitions.length > 0; + } + + @Override + public boolean canRemoveProperty(String propertyName) { + // FIXME: should properly calculate matching definition taking residual definitions into account. + PropertyDefinition[] propertyDefinitions = getPropertyDefinitions(); + for (PropertyDefinition definition : propertyDefinitions) { + String name = definition.getName(); + if (propertyName.equals(name)) { + if (definition.isMandatory() || definition.isProtected()) { + return false; + } + } + } + return propertyDefinitions.length > 0; + } + + //-------------------------------------------------------------< Object >--- @Override public String toString() { return getName(); } - private String getOakName() { + //-----------------------------------------------------------< internal >--- + String getOakName() { return node.getTree().getName(); } + Collection internalGetChildDefinitions() { + // TODO distinguish between additive and overriding node definitions. See 3.7.6.8 Item Definitions in Subtypes + Collection definitions = new ArrayList(); + definitions.addAll(Arrays.asList(getDeclaredChildNodeDefinitions())); + for (NodeType type : getSupertypes()) { + definitions.addAll(Arrays.asList(type.getDeclaredChildNodeDefinitions())); + } + return definitions; + } + + Collection internalGetPropertyDefinitions() { + // TODO distinguish between additive and overriding property definitions. See 3.7.6.8 Item Definitions in Subtypes + Collection definitions = new ArrayList(); + definitions.addAll(Arrays.asList(getDeclaredPropertyDefinitions())); + for (NodeType type : getSupertypes()) { + definitions.addAll(Arrays.asList(type.getDeclaredPropertyDefinitions())); + } + return definitions; + } + + //-------------------------------------------------------------------------- private static boolean meetsTypeConstraints(Value value, int requiredType) { try { switch (requiredType) { @@ -410,84 +498,6 @@ class NodeTypeImpl implements NodeType { return true; } - @Override - public boolean canAddChildNode(String childNodeName) { - // FIXME: properly calculate matching definition - for (NodeDefinition definition : getChildNodeDefinitions()) { - String name = definition.getName(); - if (matches(childNodeName, name) || "*".equals(name)) { - return !definition.isProtected() && definition.getDefaultPrimaryType() != null; - } - } - return false; - } - - @Override - public boolean canAddChildNode(String childNodeName, String nodeTypeName) { - NodeType type; - try { - type = manager.getNodeType(nodeTypeName); - if (type.isAbstract()) { - return false; - } - } catch (NoSuchNodeTypeException e) { - return false; - } catch (RepositoryException e) { - log.warn("Unable to access node type " + nodeTypeName, e); - return false; - } - // FIXME: properly calculate matching definition - for (NodeDefinition definition : getChildNodeDefinitions()) { - String name = definition.getName(); - if (matches(childNodeName, name) || "*".equals(name)) { - if (definition.isProtected()) { - return false; - } - for (String required : definition.getRequiredPrimaryTypeNames()) { - if (type.isNodeType(required)) { - return true; - } - } - } - } - return false; - } - - @Override - public boolean canRemoveItem(String itemName) { - return canRemoveNode(itemName) || canRemoveProperty(itemName); - } - - @Override - public boolean canRemoveNode(String nodeName) { - // FIXME: properly calculate matching definition taking residual definitions into account. - NodeDefinition[] childNodeDefinitions = getChildNodeDefinitions(); - for (NodeDefinition definition : childNodeDefinitions) { - String name = definition.getName(); - if (matches(nodeName, name)) { - if (definition.isMandatory() || definition.isProtected()) { - return false; - } - } - } - return childNodeDefinitions.length > 0; - } - - @Override - public boolean canRemoveProperty(String propertyName) { - // FIXME: should properly calculate matching definition taking residual definitions into account. - PropertyDefinition[] propertyDefinitions = getPropertyDefinitions(); - for (PropertyDefinition definition : propertyDefinitions) { - String name = definition.getName(); - if (propertyName.equals(name)) { - if (definition.isMandatory() || definition.isProtected()) { - return false; - } - } - } - return propertyDefinitions.length > 0; - } - private static boolean matches(String childNodeName, String name) { // TODO need a better way to handle SNS return childNodeName.startsWith(name); 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=1420622&r1=1420621&r2=1420622&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 Wed Dec 12 11:33:23 2012 @@ -16,9 +16,8 @@ */ package org.apache.jackrabbit.oak.plugins.nodetype; -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.Queue; @@ -31,6 +30,7 @@ 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; @@ -85,7 +85,7 @@ public abstract class ReadOnlyNodeTypeMa */ @Nonnull protected final String getOakName(String jcrName) throws RepositoryException { - String oakName = getNameMapper().getOakName(jcrName); + String oakName = getNamePathMapper().getOakName(jcrName); if (oakName == null) { throw new RepositoryException("Invalid JCR name " + jcrName); } @@ -118,7 +118,7 @@ public abstract class ReadOnlyNodeTypeMa * @return {@link NameMapper} instance. */ @Nonnull - protected NameMapper getNameMapper() { + protected NamePathMapper getNamePathMapper() { return NamePathMapperImpl.DEFAULT; } @@ -141,7 +141,7 @@ public abstract class ReadOnlyNodeTypeMa @Nonnull @Override - protected NameMapper getNameMapper() { + protected NamePathMapper getNamePathMapper() { return namePathMapper; } }; @@ -167,7 +167,7 @@ public abstract class ReadOnlyNodeTypeMa if (types != null) { for (Tree type : types.getChildren()) { list.add(new NodeTypeImpl(this, getValueFactory(), - new NodeUtil(type, getNameMapper()))); + new NodeUtil(type, getNamePathMapper()))); } } @@ -202,22 +202,22 @@ public abstract class ReadOnlyNodeTypeMa @Override public NodeTypeTemplate createNodeTypeTemplate() throws RepositoryException { - return new NodeTypeTemplateImpl(this, getNameMapper(), getValueFactory()); + return new NodeTypeTemplateImpl(this, getNamePathMapper(), getValueFactory()); } @Override public NodeTypeTemplate createNodeTypeTemplate(NodeTypeDefinition ntd) throws RepositoryException { - return new NodeTypeTemplateImpl(this, getNameMapper(), getValueFactory(), ntd); + return new NodeTypeTemplateImpl(this, getNamePathMapper(), getValueFactory(), ntd); } @Override public NodeDefinitionTemplate createNodeDefinitionTemplate() { - return new NodeDefinitionTemplateImpl(getNameMapper()); + return new NodeDefinitionTemplateImpl(getNamePathMapper()); } @Override public PropertyDefinitionTemplate createPropertyDefinitionTemplate() { - return new PropertyDefinitionTemplateImpl(getNameMapper()); + return new PropertyDefinitionTemplateImpl(getNamePathMapper()); } /** @@ -291,16 +291,16 @@ public abstract class ReadOnlyNodeTypeMa * @throws RepositoryException */ @Override - public Iterable getEffectiveNodeTypes(Node node) throws RepositoryException { + public EffectiveNodeType getEffectiveNodeType(Node node) throws RepositoryException { Queue queue = Queues.newArrayDeque(); queue.add(node.getPrimaryNodeType()); queue.addAll(Arrays.asList(node.getMixinNodeTypes())); - return getEffectiveNodeTypes(queue); + return getEffectiveNodeType(queue); } @Override - public Iterable getEffectiveNodeTypes(Tree tree) throws RepositoryException { + public EffectiveNodeType getEffectiveNodeType(Tree tree) throws RepositoryException { Queue queue = Queues.newArrayDeque(); NodeType primaryType; @@ -322,7 +322,7 @@ public abstract class ReadOnlyNodeTypeMa } queue.addAll(mixinTypes); - return getEffectiveNodeTypes(queue); + return getEffectiveNodeType(queue); } //-------------------------------------------------< DefinitionProvider >--- @@ -339,130 +339,22 @@ public abstract class ReadOnlyNodeTypeMa throws RepositoryException { checkNotNull(parent); checkNotNull(nodeName); - List residualDefs = new ArrayList(); - for (NodeType nt : getEffectiveNodeTypes(parent)) { - for (NodeDefinition def : nt.getDeclaredChildNodeDefinitions()) { - String defName = def.getName(); - if (nodeName.equals(defName) - && def.getDefaultPrimaryTypeName() != null) { - return def; - } else if ("*".equals(defName)) { - residualDefs.add(def); - } - } - } - - for (NodeDefinition def : residualDefs) { - if (def.getDefaultPrimaryTypeName() != null) { - // return the first definition with a default primary type - return def; - } - } - - throw new RepositoryException("No matching node definition found for " + nodeName); + return getNodeDefinition(getEffectiveNodeType(parent), nodeName, null); } @Override public NodeDefinition getDefinition(@Nonnull Node parent, @Nonnull Node targetNode) throws RepositoryException { String name = targetNode.getName(); - List residualDefs = new ArrayList(); - // TODO: This may need to be optimized - for (NodeType nt : getEffectiveNodeTypes(parent)) { - for (NodeDefinition def : nt.getDeclaredChildNodeDefinitions()) { - String defName = def.getName(); - if (name.equals(defName)) { - boolean match = true; - for (String type : def.getRequiredPrimaryTypeNames()) { - if (!targetNode.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 (!targetNode.isNodeType(type)) { - match = false; - } - } - if (match) { - return def; - } - } - } - - throw new RepositoryException("No matching node definition found for " + targetNode.getName()); + EffectiveNodeType eff = getEffectiveNodeType(parent); + return getNodeDefinition(eff, name, getEffectiveNodeType(targetNode)); } @Override - public NodeDefinition getDefinition(Iterable parentNodeTypes, String nodeName, NodeType nodeType) - throws RepositoryException { - - NodeDefinition def = getDefinitionOrNull(parentNodeTypes, nodeName, nodeType); - if (def == null) { - throw new RepositoryException("No matching node definition found for " + nodeName); - } - - return def; - } - - /** - * Same as {@link #getDefinition(Iterable, String, javax.jcr.nodetype.NodeType)} but returns - * {@code null} if no matching definition could be found instead of throwing a - * {@code RepositoryException}. - */ - public NodeDefinition getDefinitionOrNull(Iterable parentNodeTypes, String nodeName, NodeType nodeType) { - List residualDefs = new ArrayList(); - // 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; - } - } - } - - return null; + public NodeDefinition getDefinition(Iterable parentNodeTypes, + String nodeName, NodeType nodeType) + throws ConstraintViolationException { + EffectiveNodeType eff = getEffectiveNodeType(Queues.newArrayDeque(parentNodeTypes)); + return getNodeDefinition(eff, nodeName, getEffectiveNodeType(Queues.newArrayDeque(Collections.singleton(nodeType)))); } @Override @@ -479,45 +371,7 @@ public abstract class ReadOnlyNodeTypeMa type = targetProperty.getValue().getType(); } - // TODO: This may need to be optimized - List residualDefs = new ArrayList(); - for (NodeType nt : getEffectiveNodeTypes(parent)) { - for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) { - String defName = def.getName(); - int defType = def.getRequiredType(); - if ((name.equals(defName)) - && (type == defType || UNDEFINED == type || UNDEFINED == defType) - && isMultiple == def.isMultiple()) { - return def; - } else if ("*".equals(defName)) { - residualDefs.add(def); - } - } - } - - for (PropertyDefinition def : residualDefs) { - String defName = def.getName(); - int defType = def.getRequiredType(); - if (("*".equals(defName)) - && (type == defType || UNDEFINED == type || UNDEFINED == defType) - && isMultiple == def.isMultiple()) { - return def; - } - } - - // FIXME: Shouldn't be needed - for (NodeType nt : getEffectiveNodeTypes(parent)) { - for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) { - String defName = def.getName(); - if ((name.equals(defName) || "*".equals(defName)) - && type == PropertyType.STRING - && isMultiple == def.isMultiple()) { - return def; - } - } - } - - throw new RepositoryException("No matching property definition found for " + targetProperty.getName()); + return getPropertyDefinition(getEffectiveNodeType(parent), name, isMultiple, type, true); } @Nonnull @@ -529,13 +383,13 @@ public abstract class ReadOnlyNodeTypeMa @Nonnull @Override public PropertyDefinition getDefinition(Node parent, String propertyName, boolean isMultiple, int type, boolean exactTypeMatch) throws RepositoryException { - return getPropertyDefinition(getEffectiveNodeTypes(parent), propertyName, isMultiple, type, exactTypeMatch); + return getPropertyDefinition(getEffectiveNodeType(parent), propertyName, isMultiple, type, exactTypeMatch); } @Nonnull @Override public PropertyDefinition getDefinition(Tree parent, String propertyName, boolean isMultiple, int type, boolean exactTypeMatch) throws RepositoryException { - return getPropertyDefinition(getEffectiveNodeTypes(parent), propertyName, isMultiple, type, exactTypeMatch); + return getPropertyDefinition(getEffectiveNodeType(parent), propertyName, isMultiple, type, exactTypeMatch); } @Nonnull @@ -543,8 +397,7 @@ public abstract class ReadOnlyNodeTypeMa public PropertyDefinition getDefinition(Iterable nodeTypes, String propertyName, boolean isMultiple, int type, boolean exactTypeMatch) throws RepositoryException { Queue queue = Queues.newArrayDeque(nodeTypes); - Collection effective = getEffectiveNodeTypes(queue); - return getPropertyDefinition(effective, propertyName, isMultiple, type, exactTypeMatch); + return getPropertyDefinition(getEffectiveNodeType(queue), propertyName, isMultiple, type, exactTypeMatch); } //------------------------------------------------------------< private >--- @@ -553,13 +406,13 @@ public abstract class ReadOnlyNodeTypeMa if (types != null) { Tree type = types.getChild(oakName); if (type != null) { - return new NodeTypeImpl(this, getValueFactory(), new NodeUtil(type, getNameMapper())); + return new NodeTypeImpl(this, getValueFactory(), new NodeUtil(type, getNamePathMapper())); } } - throw new NoSuchNodeTypeException(getNameMapper().getJcrName(oakName)); + throw new NoSuchNodeTypeException(getNamePathMapper().getJcrName(oakName)); } - private static Collection getEffectiveNodeTypes(Queue queue) { + private EffectiveNodeType getEffectiveNodeType(Queue queue) { Map types = Maps.newHashMap(); while (!queue.isEmpty()) { NodeType type = queue.remove(); @@ -569,41 +422,32 @@ public abstract class ReadOnlyNodeTypeMa queue.addAll(Arrays.asList(type.getDeclaredSupertypes())); } } - - return types.values(); + return new EffectiveNodeTypeImpl(types.values(), this); } - private static PropertyDefinition getPropertyDefinition(Iterable effectiveNodeTypes, + private static PropertyDefinition getPropertyDefinition(EffectiveNodeType effectiveNodeType, String propertyName, boolean isMultiple, - int type, boolean exactTypeMatch) throws RepositoryException { + int type, boolean exactTypeMatch) throws ConstraintViolationException { // TODO: This may need to be optimized - for (NodeType nt : effectiveNodeTypes) { - for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) { - String defName = def.getName(); - int defType = def.getRequiredType(); - if (propertyName.equals(defName) - && isMultiple == def.isMultiple() - &&(!exactTypeMatch || (type == defType || UNDEFINED == type || UNDEFINED == defType))) { - return def; - } + for (PropertyDefinition def : effectiveNodeType.getNamedPropertyDefinitions(propertyName)) { + int defType = def.getRequiredType(); + if (isMultiple == def.isMultiple() + &&(!exactTypeMatch || (type == defType || UNDEFINED == type || UNDEFINED == defType))) { + return def; } } // try if there is a residual definition - for (NodeType nt : effectiveNodeTypes) { - for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) { - String defName = def.getName(); - int defType = def.getRequiredType(); - if ("*".equals(defName) - && isMultiple == def.isMultiple() - && (!exactTypeMatch || (type == defType || UNDEFINED == type || UNDEFINED == defType))) { - return def; - } + for (PropertyDefinition def : effectiveNodeType.getUnnamedPropertyDefinitions()) { + int defType = def.getRequiredType(); + if (isMultiple == def.isMultiple() + && (!exactTypeMatch || (type == defType || UNDEFINED == type || UNDEFINED == defType))) { + return def; } } // FIXME: Shouldn't be needed - for (NodeType nt : effectiveNodeTypes) { + for (NodeType nt : effectiveNodeType.getAllNodeTypes()) { for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) { String defName = def.getName(); if ((propertyName.equals(defName) || "*".equals(defName)) @@ -613,6 +457,31 @@ public abstract class ReadOnlyNodeTypeMa } } } - throw new RepositoryException("No matching property definition found for " + propertyName); + throw new ConstraintViolationException("No matching property definition found for " + propertyName); + } + + private static NodeDefinition getNodeDefinition(EffectiveNodeType effectiveNodeType, + String childName, + EffectiveNodeType childEffective) throws ConstraintViolationException { + for (NodeDefinition def : effectiveNodeType.getNamedNodeDefinitions(childName)) { + boolean match = true; + if (childEffective != null && !childEffective.includesNodeTypes(def.getRequiredPrimaryTypeNames())) { + match = false; + } + if (match) { + return def; + } + } + + for (NodeDefinition def : effectiveNodeType.getUnnamedNodeDefinitions()) { + boolean match = true; + if (childEffective != null && !childEffective.includesNodeTypes(def.getRequiredPrimaryTypeNames())) { + match = false; + } + if (match) { + return def; + } + } + throw new ConstraintViolationException("No matching node definition found for " + childName); } } 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=1420622&r1=1420621&r2=1420622&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 Wed Dec 12 11:33:23 2012 @@ -100,7 +100,7 @@ import static org.apache.jackrabbit.oak. * {@link ReadOnlyNodeTypeManager} for the following methods: *
    *
  • {@link #getValueFactory()}
  • - *
  • {@link #getNameMapper()}
  • + *
  • {@link ReadOnlyNodeTypeManager#getNamePathMapper()}
  • *
*/ public abstract class ReadWriteNodeTypeManager extends ReadOnlyNodeTypeManager { @@ -249,7 +249,7 @@ public abstract class ReadWriteNodeTypeM } type = types.addChild(oakName); - NodeUtil node = new NodeUtil(type, getNameMapper()); + NodeUtil node = new NodeUtil(type, getNamePathMapper()); node.setName(JCR_PRIMARYTYPE, NT_NODETYPE); node.setName(JCR_NODETYPENAME, jcrName); node.setNames(JCR_SUPERTYPES, ntd.getDeclaredSupertypeNames()); 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=1420622&r1=1420621&r2=1420622&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 Wed Dec 12 11:33:23 2012 @@ -16,22 +16,16 @@ */ package org.apache.jackrabbit.oak.plugins.nodetype; -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.PropertyDefinition; 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.spi.state.NodeStateUtils; @@ -64,7 +58,7 @@ class TypeValidator implements Validator @Nonnull private EffectiveNodeType getParentType() throws RepositoryException { if (parentType == null) { - parentType = getEffectiveNodeType(parent); + parentType = ntm.getEffectiveNodeType(parent); } return parentType; } @@ -127,7 +121,7 @@ class TypeValidator implements Validator getParentType().checkAddChildNode(name, getNodeType(after)); ReadOnlyTree addedTree = new ReadOnlyTree(parent, name, after); - EffectiveNodeType addedType = getEffectiveNodeType(addedTree); + EffectiveNodeType addedType = ntm.getEffectiveNodeType(addedTree); addedType.checkMandatoryItems(addedTree); return new TypeValidator(ntm, new ReadOnlyTree(parent, name, after), mapper); } catch (RepositoryException e) { @@ -190,126 +184,4 @@ class TypeValidator implements Validator 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(ntm.getEffectiveNodeTypes(tree)); - } - - private class EffectiveNodeType { - private final Iterable allTypes; - - public EffectiveNodeType(Iterable allTypes) { - this.allTypes = allTypes; - } - - public void checkSetProperty(PropertyState property) throws RepositoryException { - PropertyDefinition definition = getDefinition(property); - if (definition.isProtected()) { - return; - } - - NodeType nt = definition.getDeclaringNodeType(); - if (definition.isMultiple()) { - List values = ValueFactoryImpl.createValues(property, mapper); - if (!nt.canSetProperty(property.getName(), values.toArray(new Value[values.size()]))) { - throw new ConstraintViolationException("Cannot set property '" + property.getName() + "' to '" + values + '\''); - } - } else { - Value v = ValueFactoryImpl.createValue(property, mapper); - if (!nt.canSetProperty(property.getName(), v)) { - throw new ConstraintViolationException("Cannot set property '" + property.getName() + "' to '" + v + '\''); - } - } - } - - public void checkRemoveProperty(PropertyState property) throws RepositoryException { - PropertyDefinition definition = getDefinition(property); - if (definition.isProtected()) { - return; - } - - if (!definition.getDeclaringNodeType().canRemoveProperty(property.getName())) { - throw new ConstraintViolationException("Cannot remove property '" + property.getName() + '\''); - } - } - - public void checkRemoveNode(String name, NodeType nodeType) throws RepositoryException { - NodeDefinition definition = getDefinition(name, nodeType); - if (definition == null) { - throw new ConstraintViolationException("No matching node definition found for " + name); - } - - if (definition.isProtected()) { - return; - } - - if (!definition.getDeclaringNodeType().canRemoveNode(name)) { - throw new ConstraintViolationException("Cannot remove node '" + name + '\''); - } - } - - public void checkAddChildNode(String name, NodeType nodeType) throws RepositoryException { - NodeDefinition definition = getDefinition(name, nodeType); - if (definition == null) { - throw new ConstraintViolationException("No matching node definition found for " + name); - } - - if (definition.isProtected()) { - 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() + '\''); - } - } - - } - - public void checkMandatoryItems(ReadOnlyTree tree) throws ConstraintViolationException { - for (NodeType nodeType : allTypes) { - for (PropertyDefinition pd : nodeType.getPropertyDefinitions()) { - String name = pd.getName(); - if (pd.isMandatory() && !pd.isProtected() && tree.getProperty(name) == null) { - throw new ConstraintViolationException( - "Property '" + name + "' in '" + nodeType.getName() + "' is mandatory"); - } - } - for (NodeDefinition nd : nodeType.getChildNodeDefinitions()) { - String name = nd.getName(); - if (nd.isMandatory() && !nd.isProtected() && tree.getChild(name) == null) { - throw new ConstraintViolationException( - "Node '" + name + "' in '" + nodeType.getName() + "' is mandatory"); - } - } - } - } - - 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 NodeDefinition getDefinition(String nodeName, NodeType nodeType) { - // 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")) { - nameToCheck = nodeName.substring(0, "jcr:childNodeDefinition".length()); - } - if (nodeName.startsWith("jcr:propertyDefinition") && !nodeName.equals("jcr:propertyDefinition")) { - nameToCheck = nodeName.substring(0, "jcr:propertyDefinition".length()); - } - return ntm.getDefinitionOrNull(allTypes, nameToCheck, nodeType); - } - - - } } Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java?rev=1420622&r1=1420621&r2=1420622&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java Wed Dec 12 11:33:23 2012 @@ -74,6 +74,7 @@ import org.apache.jackrabbit.oak.api.Tre import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager; import org.apache.jackrabbit.oak.plugins.nodetype.DefinitionProvider; +import org.apache.jackrabbit.oak.plugins.nodetype.EffectiveNodeType; import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants; import org.apache.jackrabbit.oak.util.TODO; import org.apache.jackrabbit.value.ValueHelper; @@ -1313,23 +1314,19 @@ public class NodeImpl extends ItemImpl types = dlg.sessionDelegate.getEffectiveNodeTypeProvider().getEffectiveNodeTypes(this); - for (NodeType nt : types) { - for (PropertyDefinition pd : nt.getPropertyDefinitions()) { - if (pd.isAutoCreated() && dlg.getProperty(pd.getName()) == null) { - if (pd.isMultiple()) { - dlg.setProperty(pd.getName(), getAutoCreatedValues(pd)); - } else { - dlg.setProperty(pd.getName(), getAutoCreatedValue(pd)); - } + EffectiveNodeType effective = dlg.sessionDelegate.getEffectiveNodeTypeProvider().getEffectiveNodeType(this); + for (PropertyDefinition pd : effective.getAutoCreatePropertyDefinitions()) { + if (dlg.getProperty(pd.getName()) == null) { + if (pd.isMultiple()) { + dlg.setProperty(pd.getName(), getAutoCreatedValues(pd)); + } else { + dlg.setProperty(pd.getName(), getAutoCreatedValue(pd)); } } } - for (NodeType nt : types) { - for (NodeDefinition nd : nt.getChildNodeDefinitions()) { - if (nd.isAutoCreated() && dlg.getChild(nd.getName()) == null) { - autoCreateNode(nd); - } + for (NodeDefinition nd : effective.getAutoCreateNodeDefinitions()) { + if (dlg.getChild(nd.getName()) == null) { + autoCreateNode(nd); } } } @@ -1398,7 +1395,7 @@ public class NodeImpl extends ItemImpl