jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r1559816 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/ oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/
Date Mon, 20 Jan 2014 19:45:10 GMT
Author: jukka
Date: Mon Jan 20 19:45:09 2014
New Revision: 1559816

URL: http://svn.apache.org/r1559816
Log:
OAK-411: Validator for node type management

Avoid full content scan for node type updates that make no actual changes.
Also add more detailed toString() methods to the type templates.

Modified:
    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/write/ItemDefinitionTemplate.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/NodeDefinitionTemplateImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/NodeTypeTemplateImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/PropertyDefinitionTemplateImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/ReadWriteNodeTypeManager.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/NodeTypeTest.java

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=1559816&r1=1559815&r2=1559816&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
Mon Jan 20 19:45:09 2014
@@ -26,8 +26,11 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
@@ -59,6 +62,7 @@ import com.google.common.collect.Sets;
 
 import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Maps.newTreeMap;
 import static java.util.Collections.emptyList;
 import static org.apache.jackrabbit.JcrConstants.JCR_CHILDNODEDEFINITION;
 import static org.apache.jackrabbit.JcrConstants.JCR_HASORDERABLECHILDNODES;
@@ -100,6 +104,16 @@ class NodeTypeImpl extends AbstractTypeD
 
     private static final Logger log = LoggerFactory.getLogger(NodeTypeImpl.class);
 
+    /**
+     * Name pattern for the property and child node definition nodes.
+     * Used to pick out the SNS indices from the names so the definitions
+     * can be sorted in the same order they were created. This in turn
+     * makes accessing node type information more deterministic.
+     */
+    private final Pattern DEFINITION_PATTERN = Pattern.compile(
+            "(" + JCR_PROPERTYDEFINITION + "|" + JCR_CHILDNODEDEFINITION
+            + ")\\[([1-9][0-9]*)\\]");
+
     private static final PropertyDefinition[] NO_PROPERTY_DEFINITIONS =
             new PropertyDefinition[0];
 
@@ -177,26 +191,44 @@ class NodeTypeImpl extends AbstractTypeD
         }
     }
 
-    @Override
+    /**
+     * Returns the declared property definitions in their original order.
+     *
+     * @return declared property definitions
+     */
+    @Override @Nonnull
     public PropertyDefinition[] getDeclaredPropertyDefinitions() {
-        List<PropertyDefinition> definitions = Lists.newArrayList();
+        Map<Integer, PropertyDefinition> definitions = newTreeMap();
         for (Tree child : definition.getChildren()) {
-            if (child.getName().startsWith(JCR_PROPERTYDEFINITION)) {
-                definitions.add(new PropertyDefinitionImpl(child, this, mapper));
+            Matcher matcher = DEFINITION_PATTERN.matcher(child.getName());
+            if (matcher.matches()
+                    && JCR_PROPERTYDEFINITION.equals(matcher.group(1))) {
+                definitions.put(
+                        Integer.valueOf(matcher.group(2)),
+                        new PropertyDefinitionImpl(child, this, mapper));
             }
         }
-        return definitions.toArray(NO_PROPERTY_DEFINITIONS);
+        return definitions.values().toArray(NO_PROPERTY_DEFINITIONS);
     }
 
-    @Override
+    /**
+     * Returns the declared child node definitions in their original order.
+     *
+     * @return declared child node definitions
+     */
+    @Override @Nonnull
     public NodeDefinition[] getDeclaredChildNodeDefinitions() {
-        List<NodeDefinition> definitions = Lists.newArrayList();
+        Map<Integer, NodeDefinition> definitions = newTreeMap();
         for (Tree child : definition.getChildren()) {
-            if (child.getName().startsWith(JCR_CHILDNODEDEFINITION)) {
-                definitions.add(new NodeDefinitionImpl(child, this, mapper));
+            Matcher matcher = DEFINITION_PATTERN.matcher(child.getName());
+            if (matcher.matches()
+                    && JCR_CHILDNODEDEFINITION.equals(matcher.group(1))) {
+                definitions.put(
+                        Integer.valueOf(matcher.group(2)),
+                        new NodeDefinitionImpl(child, this, mapper));
             }
         }
-        return definitions.toArray(NO_NODE_DEFINITIONS);
+        return definitions.values().toArray(NO_NODE_DEFINITIONS);
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/ItemDefinitionTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/ItemDefinitionTemplate.java?rev=1559816&r1=1559815&r2=1559816&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/ItemDefinitionTemplate.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/ItemDefinitionTemplate.java
Mon Jan 20 19:45:09 2014
@@ -49,9 +49,9 @@ abstract class ItemDefinitionTemplate ex
 
     private int onParentVersion = OnParentVersionAction.COPY;
 
-    protected boolean isProtected = false;
+    private boolean isProtected = false;
 
-    protected boolean isMandatory = false;
+    private boolean isMandatory = false;
 
     protected ItemDefinitionTemplate(NameMapper mapper) {
         super(mapper);
@@ -82,6 +82,8 @@ abstract class ItemDefinitionTemplate ex
                 throw new RepositoryException("Unnamed item definition");
             }
             tree.setProperty(JCR_NAME, oakName, Type.NAME);
+        } else {
+            tree.removeProperty(JCR_NAME);
         }
 
         // TODO avoid (in validator?) unbounded recursive auto creation.

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/NodeDefinitionTemplateImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/NodeDefinitionTemplateImpl.java?rev=1559816&r1=1559815&r2=1559816&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/NodeDefinitionTemplateImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/NodeDefinitionTemplateImpl.java
Mon Jan 20 19:45:09 2014
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.plugin
 import static org.apache.jackrabbit.JcrConstants.JCR_DEFAULTPRIMARYTYPE;
 import static org.apache.jackrabbit.JcrConstants.JCR_REQUIREDPRIMARYTYPES;
 import static org.apache.jackrabbit.JcrConstants.JCR_SAMENAMESIBLINGS;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.RESIDUAL_NAME;
 
 import java.util.Arrays;
 
@@ -27,11 +28,14 @@ import javax.jcr.nodetype.ConstraintViol
 import javax.jcr.nodetype.NodeDefinition;
 import javax.jcr.nodetype.NodeDefinitionTemplate;
 import javax.jcr.nodetype.NodeType;
+import javax.jcr.version.OnParentVersionAction;
 
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.namepath.NameMapper;
 
+import com.google.common.base.Objects;
+
 class NodeDefinitionTemplateImpl extends ItemDefinitionTemplate
         implements NodeDefinitionTemplate {
 
@@ -71,12 +75,16 @@ class NodeDefinitionTemplateImpl extends
             tree.setProperty(
                     JCR_REQUIREDPRIMARYTYPES,
                     Arrays.asList(requiredPrimaryTypeOakNames), Type.NAMES);
+        } else {
+            tree.removeProperty(JCR_REQUIREDPRIMARYTYPES);
         }
 
         if (defaultPrimaryTypeOakName != null) {
             tree.setProperty(
                     JCR_DEFAULTPRIMARYTYPE,
                     defaultPrimaryTypeOakName, Type.NAME);
+        } else {
+            tree.removeProperty(JCR_DEFAULTPRIMARYTYPE);
         }
     }
 
@@ -140,8 +148,33 @@ class NodeDefinitionTemplateImpl extends
 
     //------------------------------------------------------------< Object >--
 
+    @Override
     public String toString() {
-        return String.format("PropertyDefinitionTemplate(%s)", getOakName());
+        StringBuilder builder = new StringBuilder("+ ");
+        if (getOakName() == null) {
+            builder.append(RESIDUAL_NAME);
+        } else {
+            builder.append(getOakName());
+        }
+        if (defaultPrimaryTypeOakName != null) {
+            builder.append(" (");
+            builder.append(defaultPrimaryTypeOakName);
+            builder.append(")");
+        }
+        if (isAutoCreated()) {
+            builder.append(" a");
+        }
+        if (isProtected()) {
+            builder.append(" p");
+        }
+        if (isMandatory()) {
+            builder.append(" m");
+        }
+        if (getOnParentVersion() != OnParentVersionAction.COPY) {
+            builder.append(" ");
+            builder.append(OnParentVersionAction.nameFromValue(getOnParentVersion()));
+        }
+        return builder.toString();
     }
 
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/NodeTypeTemplateImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/NodeTypeTemplateImpl.java?rev=1559816&r1=1559815&r2=1559816&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/NodeTypeTemplateImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/NodeTypeTemplateImpl.java
Mon Jan 20 19:45:09 2014
@@ -27,6 +27,7 @@ import static org.apache.jackrabbit.JcrC
 import static org.apache.jackrabbit.JcrConstants.NT_CHILDNODEDEFINITION;
 import static org.apache.jackrabbit.JcrConstants.NT_NODETYPE;
 import static org.apache.jackrabbit.JcrConstants.NT_PROPERTYDEFINITION;
+import static org.apache.jackrabbit.oak.api.Type.NAME;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_ABSTRACT;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_QUERYABLE;
 
@@ -45,6 +46,7 @@ import javax.jcr.nodetype.PropertyDefini
 import javax.jcr.nodetype.PropertyDefinitionTemplate;
 
 import com.google.common.collect.Lists;
+
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.namepath.NameMapper;
@@ -129,23 +131,22 @@ class NodeTypeTemplateImpl extends Named
         String oakName = getOakName();
 
         Tree type = parent.getChild(oakName);
-        if (type.exists()) {
-            if (allowUpdate) {
-                type.remove();
-            } else {
-                throw new NodeTypeExistsException(
-                        "Node type " + getName() + " already exists");
-            }
+        if (!type.exists()) {
+            type = parent.addChild(oakName);
+            type.setProperty(JCR_PRIMARYTYPE, NT_NODETYPE, Type.NAME);
+        } else if (!allowUpdate) {
+            throw new NodeTypeExistsException(
+                    "Node type " + getName() + " already exists");
         }
-        type = parent.addChild(oakName);
 
-        type.setProperty(JCR_PRIMARYTYPE, NT_NODETYPE, Type.NAME);
         type.setProperty(JCR_NODETYPENAME, oakName, Type.NAME);
 
         if (superTypeOakNames.length > 0) {
             type.setProperty(
                     JCR_SUPERTYPES,
                     Arrays.asList(superTypeOakNames), Type.NAMES);
+        } else {
+            type.removeProperty(JCR_SUPERTYPES);
         }
 
         type.setProperty(JCR_IS_ABSTRACT, isAbstract);
@@ -160,29 +161,50 @@ class NodeTypeTemplateImpl extends Named
         // See 3.7.6.7 Node Type Attribute Subtyping Rules (OAK-411)
         if (primaryItemOakName != null) {
             type.setProperty(JCR_PRIMARYITEMNAME, primaryItemOakName, Type.NAME);
+        } else {
+            type.removeProperty(JCR_PRIMARYITEMNAME);
         }
 
+        Tree tree;
         // TODO fail (in validator?) on invalid item definitions
         // See 3.7.6.8 Item Definitions in Subtypes (OAK-411)
+        int pdn = 1;
         if (propertyDefinitionTemplates != null) {
-            int pdn = 1;
             for (PropertyDefinitionTemplateImpl pdt : propertyDefinitionTemplates) {
-                Tree tree = type.addChild(JCR_PROPERTYDEFINITION + "[" + pdn++ + "]");
-                tree.setProperty(
-                        JCR_PRIMARYTYPE, NT_PROPERTYDEFINITION, Type.NAME);
+                String name = JCR_PROPERTYDEFINITION + "[" + pdn++ + "]";
+                tree = type.getChild(name);
+                if (!tree.exists()) {
+                    tree = type.addChild(name);
+                    tree.setProperty(
+                            JCR_PRIMARYTYPE, NT_PROPERTYDEFINITION, NAME);
+                }
                 pdt.writeTo(tree);
             }
         }
+        tree = type.getChild(JCR_PROPERTYDEFINITION + "[" + pdn++ + "]");
+        while (tree.exists()) {
+            tree.remove();
+            tree = type.getChild(JCR_PROPERTYDEFINITION + "[" + pdn++ + "]");
+        }
 
+        int ndn = 1;
         if (nodeDefinitionTemplates != null) {
-            int ndn = 1;
             for (NodeDefinitionTemplateImpl ndt : nodeDefinitionTemplates) {
-                Tree tree = type.addChild(JCR_CHILDNODEDEFINITION + "[" + ndn++ + "]");
-                tree.setProperty(
-                        JCR_PRIMARYTYPE, NT_CHILDNODEDEFINITION, Type.NAME);
+                String name = JCR_CHILDNODEDEFINITION + "[" + ndn++ + "]";
+                tree = type.getChild(name);
+                if (!tree.exists()) {
+                    tree = type.addChild(name);
+                    tree.setProperty(
+                            JCR_PRIMARYTYPE, NT_CHILDNODEDEFINITION, NAME);
+                }
                 ndt.writeTo(tree);
             }
         }
+        tree = type.getChild(JCR_CHILDNODEDEFINITION + "[" + ndn++ + "]");
+        while (tree.exists()) {
+            tree.remove();
+            tree = type.getChild(JCR_CHILDNODEDEFINITION + "[" + ndn++ + "]");
+        }
 
         return type;
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/PropertyDefinitionTemplateImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/PropertyDefinitionTemplateImpl.java?rev=1559816&r1=1559815&r2=1559816&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/PropertyDefinitionTemplateImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/PropertyDefinitionTemplateImpl.java
Mon Jan 20 19:45:09 2014
@@ -24,6 +24,7 @@ import static org.apache.jackrabbit.JcrC
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_AVAILABLE_QUERY_OPERATORS;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_FULLTEXT_SEARCHABLE;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_QUERY_ORDERABLE;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.RESIDUAL_NAME;
 
 import java.util.Arrays;
 
@@ -34,6 +35,7 @@ import javax.jcr.nodetype.ConstraintViol
 import javax.jcr.nodetype.PropertyDefinition;
 import javax.jcr.nodetype.PropertyDefinitionTemplate;
 import javax.jcr.query.qom.QueryObjectModelConstants;
+import javax.jcr.version.OnParentVersionAction;
 
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
@@ -109,11 +111,15 @@ class PropertyDefinitionTemplateImpl ext
             tree.setProperty(
                     JCR_VALUECONSTRAINTS,
                     Arrays.asList(valueConstraints), Type.STRINGS);
+        } else {
+            tree.removeProperty(JCR_VALUECONSTRAINTS);
         }
 
         if (defaultValues != null) {
             tree.setProperty(PropertyStates.createProperty(
                     JCR_DEFAULTVALUES, Arrays.asList(defaultValues)));
+        } else {
+            tree.removeProperty(JCR_DEFAULTVALUES);
         }
     }
 
@@ -205,8 +211,33 @@ class PropertyDefinitionTemplateImpl ext
 
     //------------------------------------------------------------< Object >--
 
+    @Override
     public String toString() {
-        return String.format("PropertyDefinitionTemplate(%s)", getOakName());
+        StringBuilder builder = new StringBuilder("- ");
+        if (getOakName() == null) {
+            builder.append(RESIDUAL_NAME);
+        } else {
+            builder.append(getOakName());
+        }
+        if (requiredType != PropertyType.STRING) {
+            builder.append(" (");
+            builder.append(Type.fromTag(requiredType, false).toString());
+            builder.append(")");
+        }
+        if (isAutoCreated()) {
+            builder.append(" a");
+        }
+        if (isProtected()) {
+            builder.append(" p");
+        }
+        if (isMandatory()) {
+            builder.append(" m");
+        }
+        if (getOnParentVersion() != OnParentVersionAction.COPY) {
+            builder.append(" ");
+            builder.append(OnParentVersionAction.nameFromValue(getOnParentVersion()));
+        }
+        return builder.toString();
     }
 
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/ReadWriteNodeTypeManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/ReadWriteNodeTypeManager.java?rev=1559816&r1=1559815&r2=1559816&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/ReadWriteNodeTypeManager.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/ReadWriteNodeTypeManager.java
Mon Jan 20 19:45:09 2014
@@ -128,8 +128,6 @@ public abstract class ReadWriteNodeTypeM
     public final NodeTypeIterator registerNodeTypes(
             NodeTypeDefinition[] ntds, boolean allowUpdate)
             throws RepositoryException {
-        // TODO proper node type registration... (OAK-66, OAK-411)
-        // TODO handle inter-type dependencies (OAK-66, OAK-411)
         Root root = getWriteRoot();
         try {
             Tree tree = getOrCreateNodeTypes(root);

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/NodeTypeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/NodeTypeTest.java?rev=1559816&r1=1559815&r2=1559816&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/NodeTypeTest.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/NodeTypeTest.java
Mon Jan 20 19:45:09 2014
@@ -20,11 +20,16 @@ package org.apache.jackrabbit.oak.jcr.no
 
 import static junit.framework.Assert.fail;
 
+import java.util.List;
+
 import javax.jcr.Node;
 import javax.jcr.Session;
 import javax.jcr.ValueFactory;
 import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NodeTypeDefinition;
 import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.nodetype.NodeTypeTemplate;
+import javax.jcr.nodetype.PropertyDefinitionTemplate;
 
 import org.apache.jackrabbit.oak.jcr.AbstractRepositoryTest;
 import org.apache.jackrabbit.oak.jcr.NodeStoreFixture;
@@ -66,6 +71,55 @@ public class NodeTypeTest extends Abstra
     }
 
     @Test
+    public void updateNodeType() throws Exception {
+        Session session = getAdminSession();
+        Node root = session.getRootNode();
+        ValueFactory vf = session.getValueFactory();
+        NodeTypeManager manager = session.getWorkspace().getNodeTypeManager();
+
+        Node n = root.addNode("q1", "nt:query");
+        n.setProperty("jcr:statement", vf.createValue("statement"));
+        session.save();
+
+        NodeTypeDefinition ntd = manager.getNodeType("nt:query");
+        NodeTypeTemplate ntt = manager.createNodeTypeTemplate(ntd);
+
+        try {
+            manager.registerNodeType(ntt, true);
+            // no changes to the type, so the registration should be a no-op
+        } catch (ConstraintViolationException unexpected) {
+            fail();
+        }
+
+        // make the (still missing) jcr:language property mandatory
+        @SuppressWarnings("unchecked")
+        List<PropertyDefinitionTemplate> pdts = ntt.getPropertyDefinitionTemplates();
+        for (PropertyDefinitionTemplate pdt : pdts) {
+            if ("jcr:language".equals(pdt.getName())) {
+                pdt.setMandatory(true);
+            }
+        }
+
+        try {
+            manager.registerNodeType(ntt, true);
+            fail();
+        } catch (ConstraintViolationException expected) {
+            // the registration fails because of the would-be invalid content
+        }
+
+        // add the jcr:language property so it can be made mandatory
+        n.setProperty("jcr:language", vf.createValue("language"));
+        session.save();
+
+        try {
+            manager.registerNodeType(ntt, true);
+            // now the mandatory property exists, so the type change is OK
+        } catch (ConstraintViolationException unexpected) {
+            fail();
+        }
+    }
+
+    @Test
     public void removeNodeType() throws Exception {
         Session session = getAdminSession();
         Node root = session.getRootNode();



Mime
View raw message