Package org.jboss.dna.jcr

Source Code of org.jboss.dna.jcr.TypeRegistrationTest

/*
* JBoss DNA (http://www.jboss.org/dna)
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.  Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
* See the AUTHORS.txt file in the distribution for a full listing of
* individual contributors.
*
* JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
* is licensed to you under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* JBoss DNA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.dna.jcr;

import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import java.util.Arrays;
import java.util.List;
import javax.jcr.PropertyType;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.PropertyDefinition;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.NameFactory;
import org.jboss.dna.graph.property.NamespaceRegistry;
import org.jboss.dna.jcr.nodetype.InvalidNodeTypeDefinitionException;
import org.jboss.dna.jcr.nodetype.NodeDefinitionTemplate;
import org.jboss.dna.jcr.nodetype.NodeTypeDefinition;
import org.jboss.dna.jcr.nodetype.NodeTypeExistsException;
import org.jboss.dna.jcr.nodetype.NodeTypeTemplate;
import org.jboss.dna.jcr.nodetype.PropertyDefinitionTemplate;
import org.junit.Before;
import org.junit.Test;

public class TypeRegistrationTest extends AbstractSessionTest {

    private static final String TEST_TYPE_NAME = "dna:testNode";
    private static final String TEST_TYPE_NAME2 = "dna:testNode2";
    private static final String TEST_PROPERTY_NAME = "dna:testProperty";
    private static final String TEST_CHILD_NODE_NAME = "dna:testChildNode";

    private JcrNodeTypeTemplate ntTemplate;
    private NamespaceRegistry registry;
    private NameFactory nameFactory;

    @Override
    @Before
    public void beforeEach() throws Exception {
        super.beforeEach();
        ntTemplate = new JcrNodeTypeTemplate(context);
        registry = context.getNamespaceRegistry();
        nameFactory = context.getValueFactories().getNameFactory();
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowNodeTypeWithNoName() throws Exception {
        ntTemplate.setName(null);
        repoTypeManager.registerNodeType(ntTemplate, false);
    }

    @Test
    public void shouldAllowNewDefinitionWithNoChildNodesOrProperties() throws Exception {
        Name testTypeName = nameFactory.create(TEST_TYPE_NAME);
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base"});

        JcrNodeType testNodeType = repoTypeManager.registerNodeType(ntTemplate, false);

        assertThat(testNodeType.getName(), is(TEST_TYPE_NAME));
        JcrNodeType nodeTypeFromRepo = repoTypeManager.getNodeType(testTypeName);
        assertThat(nodeTypeFromRepo, is(notNullValue()));
        assertThat(nodeTypeFromRepo.getName(), is(TEST_TYPE_NAME));
    }

    @Test( expected = NodeTypeExistsException.class )
    public void shouldNotAllowModificationIfAllowUpdatesIsFalse() throws Exception {
        ntTemplate.setName("nt:base");
        repoTypeManager.registerNodeType(ntTemplate, false);
    }

    @Test( expected = NodeTypeExistsException.class )
    public void shouldNotAllowRedefinitionOfNewTypeIfAllowUpdatesIsFalse() throws Exception {
        Name testTypeName = nameFactory.create(TEST_TYPE_NAME);
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base"});

        JcrNodeType testNodeType = repoTypeManager.registerNodeType(ntTemplate, false);

        assertThat(testNodeType.getName(), is(TEST_TYPE_NAME));
        JcrNodeType nodeTypeFromRepo = repoTypeManager.getNodeType(testTypeName);
        assertThat(nodeTypeFromRepo, is(notNullValue()));
        assertThat(nodeTypeFromRepo.getName(), is(TEST_TYPE_NAME));

        testNodeType = repoTypeManager.registerNodeType(ntTemplate, false);
    }

    @Test
    public void shouldAllowDefinitionWithExistingSupertypes() throws Exception {
        Name testTypeName = nameFactory.create(TEST_TYPE_NAME);
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrNodeType testNodeType = repoTypeManager.registerNodeType(ntTemplate, false);

        assertThat(testNodeType.getName(), is(TEST_TYPE_NAME));
        JcrNodeType nodeTypeFromRepo = repoTypeManager.getNodeType(testTypeName);
        assertThat(nodeTypeFromRepo, is(notNullValue()));
        assertThat(nodeTypeFromRepo.getName(), is(TEST_TYPE_NAME));

    }

    @Test
    public void shouldAllowDefinitionWithSupertypesFromTypesRegisteredInSameCall() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrNodeTypeTemplate ntTemplate2 = new JcrNodeTypeTemplate(context);
        ntTemplate2.setName(TEST_TYPE_NAME2);
        ntTemplate2.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate, ntTemplate2});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowDefinitionWithSupertypesFromTypesRegisteredInSameCallInWrongOrder() throws Exception {
        // Try to register the supertype AFTER the class that registers it
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrNodeTypeTemplate ntTemplate2 = new JcrNodeTypeTemplate(context);
        ntTemplate2.setName(TEST_TYPE_NAME2);
        ntTemplate2.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        repoTypeManager.registerNodeTypes(Arrays.asList(new NodeTypeDefinition[] {ntTemplate2, ntTemplate}), false);
    }

    @Test
    public void shouldAllowDefinitionWithAProperty() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setRequiredType(PropertyType.LONG);

        ntTemplate.getPropertyDefinitionTemplates().add(prop);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test
    public void shouldAllowDefinitionWithProperties() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setRequiredType(PropertyType.LONG);
        ntTemplate.getPropertyDefinitionTemplates().add(prop);

        JcrPropertyDefinitionTemplate prop2 = new JcrPropertyDefinitionTemplate(this.context);
        prop2.setRequiredType(PropertyType.STRING);
        prop2.setMultiple(true);
        ntTemplate.getPropertyDefinitionTemplates().add(prop2);

        JcrPropertyDefinitionTemplate prop3 = new JcrPropertyDefinitionTemplate(this.context);
        prop3.setName(TEST_PROPERTY_NAME);
        prop3.setRequiredType(PropertyType.STRING);
        ntTemplate.getPropertyDefinitionTemplates().add(prop3);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowAutocreatedPropertyWithNoDefault() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.LONG);
        prop.setAutoCreated(true);
        ntTemplate.getPropertyDefinitionTemplates().add(prop);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowAutocreatedResidualProperty() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setRequiredType(PropertyType.UNDEFINED);
        prop.setAutoCreated(true);
        ntTemplate.getPropertyDefinitionTemplates().add(prop);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test
    public void shouldAllowAutocreatedNamedPropertyWithDefault() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.STRING);
        prop.setAutoCreated(true);
        prop.setDefaultValues(new String[] {"<default>"});
        ntTemplate.getPropertyDefinitionTemplates().add(prop);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowSingleValuedPropertyWithMultipleDefaults() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.STRING);
        prop.setAutoCreated(true);
        prop.setDefaultValues(new String[] {"<default>", "too many values"});
        ntTemplate.getPropertyDefinitionTemplates().add(prop);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowMandatoryResidualProperty() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setRequiredType(PropertyType.UNDEFINED);
        prop.setMandatory(true);
        ntTemplate.getPropertyDefinitionTemplates().add(prop);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test
    public void shouldAllowTypeWithChildNode() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrNodeDefinitionTemplate child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(TEST_CHILD_NODE_NAME);
        child.setRequiredPrimaryTypes(new String[] {"nt:base"});
        child.setSameNameSiblings(true);

        ntTemplate.getNodeDefinitionTemplates().add(child);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test
    public void shouldAllowTypeWithMultipleChildNodes() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrNodeDefinitionTemplate child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(TEST_CHILD_NODE_NAME);
        child.setRequiredPrimaryTypes(new String[] {"nt:base"});
        child.setSameNameSiblings(true);
        ntTemplate.getNodeDefinitionTemplates().add(child);

        child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(TEST_CHILD_NODE_NAME);
        child.setRequiredPrimaryTypes(new String[] {"nt:unstructured"});
        child.setSameNameSiblings(false);
        ntTemplate.getNodeDefinitionTemplates().add(child);

        child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(TEST_CHILD_NODE_NAME + "2");
        child.setRequiredPrimaryTypes(new String[] {"nt:base"});
        child.setSameNameSiblings(true);
        ntTemplate.getNodeDefinitionTemplates().add(child);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowAutocreatedChildNodeWithNoDefaultPrimaryType() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrNodeDefinitionTemplate child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(TEST_CHILD_NODE_NAME);
        child.setRequiredPrimaryTypes(new String[] {"nt:base"});
        child.setAutoCreated(true);
        ntTemplate.getNodeDefinitionTemplates().add(child);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowMandatoryResidualChildNode() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrNodeDefinitionTemplate child = new JcrNodeDefinitionTemplate(this.context);
        child.setRequiredPrimaryTypes(new String[] {"nt:base"});
        child.setMandatory(true);
        ntTemplate.getNodeDefinitionTemplates().add(child);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowOverridingProtectedProperty() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base", "mix:referenceable"});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(JcrLexicon.PRIMARY_TYPE.getString(registry));
        prop.setRequiredType(PropertyType.NAME);
        ntTemplate.getPropertyDefinitionTemplates().add(prop);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowOverridingProtectedChildNode() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"dna:root", "mix:referenceable"});

        JcrNodeDefinitionTemplate child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(JcrLexicon.SYSTEM.getString(registry));
        child.setRequiredPrimaryTypes(new String[] {"nt:base"});
        ntTemplate.getNodeDefinitionTemplates().add(child);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowOverridingMandatoryChildNodeWithOptionalChildNode() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"jcr:versionHistory",});

        JcrNodeDefinitionTemplate child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(JcrLexicon.SYSTEM.getString(registry));
        child.setRequiredPrimaryTypes(new String[] {"nt:base"});
        ntTemplate.getNodeDefinitionTemplates().add(child);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test
    public void shouldAllowOverridingPropertyFromCommonAncestor() throws Exception {
        /*
         * testNode declares prop testProperty
         * testNodeB extends testNode
         * testNodeC extends testNode
         * testNodeD extends testNodeB and testNodeC and overrides testProperty --> LEGAL
         */
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base",});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.UNDEFINED);
        ntTemplate.getPropertyDefinitionTemplates().add(prop);

        JcrNodeTypeTemplate nodeBTemplate = new JcrNodeTypeTemplate(this.context);
        nodeBTemplate.setName(TEST_TYPE_NAME + "B");
        nodeBTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        JcrNodeTypeTemplate nodeCTemplate = new JcrNodeTypeTemplate(this.context);
        nodeCTemplate.setName(TEST_TYPE_NAME + "C");
        nodeCTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        JcrNodeTypeTemplate nodeDTemplate = new JcrNodeTypeTemplate(this.context);
        nodeDTemplate.setName(TEST_TYPE_NAME + "D");
        nodeDTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME + "B", TEST_TYPE_NAME + "C"});

        prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.STRING);
        nodeDTemplate.getPropertyDefinitionTemplates().add(prop);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate, nodeBTemplate, nodeCTemplate,
            nodeDTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowOverridingPropertyFromDifferentAncestors() throws Exception {
        /*
         * testNode
         * testNodeB extends testNode and declares prop testProperty
         * testNodeC extends testNode and declares prop testProperty
         * testNodeD extends testNodeB and testNodeC and overrides testProperty --> ILLEGAL
         */
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base",});

        JcrNodeTypeTemplate nodeBTemplate = new JcrNodeTypeTemplate(this.context);
        nodeBTemplate.setName(TEST_TYPE_NAME + "B");
        nodeBTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.UNDEFINED);
        nodeBTemplate.getPropertyDefinitionTemplates().add(prop);

        JcrNodeTypeTemplate nodeCTemplate = new JcrNodeTypeTemplate(this.context);
        nodeCTemplate.setName(TEST_TYPE_NAME + "C");
        nodeCTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.UNDEFINED);
        nodeCTemplate.getPropertyDefinitionTemplates().add(prop);

        JcrNodeTypeTemplate nodeDTemplate = new JcrNodeTypeTemplate(this.context);
        nodeDTemplate.setName(TEST_TYPE_NAME + "D");
        nodeDTemplate.setDeclaredSupertypeNames(new String[] {nodeBTemplate.getName(), nodeCTemplate.getName()});

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate, nodeBTemplate, nodeCTemplate,
            nodeDTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test
    public void shouldAllowOverridingChildNodeFromCommonAncestor() throws Exception {
        /*
         * testNode declares node testChildNode
         * testNodeB extends testNode
         * testNodeC extends testNode
         * testNodeD extends testNodeB and testNodeC and overrides testChildNode --> LEGAL
         */
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base",});

        JcrNodeDefinitionTemplate child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(JcrLexicon.SYSTEM.getString(registry));
        child.setRequiredPrimaryTypes(new String[] {"nt:base"});
        ntTemplate.getNodeDefinitionTemplates().add(child);

        JcrNodeTypeTemplate nodeBTemplate = new JcrNodeTypeTemplate(this.context);
        nodeBTemplate.setName(TEST_TYPE_NAME + "B");
        nodeBTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        JcrNodeTypeTemplate nodeCTemplate = new JcrNodeTypeTemplate(this.context);
        nodeCTemplate.setName(TEST_TYPE_NAME + "C");
        nodeCTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        JcrNodeTypeTemplate nodeDTemplate = new JcrNodeTypeTemplate(this.context);
        nodeDTemplate.setName(TEST_TYPE_NAME + "D");
        nodeDTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME + "B", TEST_TYPE_NAME + "C"});

        child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(JcrLexicon.SYSTEM.getString(registry));
        child.setRequiredPrimaryTypes(new String[] {"nt:unstructured"});
        nodeDTemplate.getNodeDefinitionTemplates().add(child);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate, nodeBTemplate, nodeCTemplate,
            nodeDTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowOverridingChildNodeFromDifferentAncestors() throws Exception {
        /*
         * testNode
         * testNodeB extends testNode and declares node testChildNode
         * testNodeC extends testNode and declares node testChildNode
         * testNodeD extends testNodeB and testNodeC and overrides testChildNode --> ILLEGAL
         */
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base",});

        JcrNodeTypeTemplate nodeBTemplate = new JcrNodeTypeTemplate(this.context);
        nodeBTemplate.setName(TEST_TYPE_NAME + "B");
        nodeBTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        JcrNodeDefinitionTemplate child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(JcrLexicon.SYSTEM.getString(registry));
        child.setRequiredPrimaryTypes(new String[] {"nt:base"});
        nodeBTemplate.getNodeDefinitionTemplates().add(child);

        JcrNodeTypeTemplate nodeCTemplate = new JcrNodeTypeTemplate(this.context);
        nodeCTemplate.setName(TEST_TYPE_NAME + "C");
        nodeCTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(JcrLexicon.SYSTEM.getString(registry));
        child.setRequiredPrimaryTypes(new String[] {"nt:base"});
        nodeCTemplate.getNodeDefinitionTemplates().add(child);

        JcrNodeTypeTemplate nodeDTemplate = new JcrNodeTypeTemplate(this.context);
        nodeDTemplate.setName(TEST_TYPE_NAME + "D");
        nodeDTemplate.setDeclaredSupertypeNames(new String[] {nodeBTemplate.getName(), nodeCTemplate.getName()});

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate, nodeBTemplate, nodeCTemplate,
            nodeDTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test
    public void shouldAllowExtendingPropertyIfMultipleChanges() throws Exception {
        /*
         * testNode declares SV property testProperty
         * testNodeB extends testNode with MV property testProperty with incompatible type -> LEGAL
         * testNodeC extends testNode, testNodeB -> LEGAL
         */
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base",});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.DOUBLE);
        prop.setMultiple(false);
        ntTemplate.getPropertyDefinitionTemplates().add(prop);

        JcrNodeTypeTemplate nodeBTemplate = new JcrNodeTypeTemplate(this.context);
        nodeBTemplate.setName(TEST_TYPE_NAME + "B");
        nodeBTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.BOOLEAN);
        prop.setMultiple(true);
        nodeBTemplate.getPropertyDefinitionTemplates().add(prop);

        JcrNodeTypeTemplate nodeCTemplate = new JcrNodeTypeTemplate(this.context);
        nodeCTemplate.setName(TEST_TYPE_NAME + "C");
        nodeCTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME, nodeBTemplate.getName()});

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate, nodeBTemplate, nodeCTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test
    public void shouldAllowOverridingPropertyIfTypeNarrows() throws Exception {
        /*
         * testNode declares SV property testProperty of type UNDEFINED
         * testNodeB extends testNode with SV property testProperty of type STRING -> LEGAL
         */
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base",});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.UNDEFINED);
        prop.setMultiple(false);
        ntTemplate.getPropertyDefinitionTemplates().add(prop);

        JcrNodeTypeTemplate nodeBTemplate = new JcrNodeTypeTemplate(this.context);
        nodeBTemplate.setName(TEST_TYPE_NAME + "B");
        nodeBTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.STRING);
        prop.setMultiple(false);
        nodeBTemplate.getPropertyDefinitionTemplates().add(prop);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate, nodeBTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowOverridingPropertyIfTypeDoesNotNarrow() throws Exception {
        /*
         * testNode declares SV property testProperty of type BOOLEAN
         * testNodeB extends testNode with SV property testProperty of type DOUBLE -> ILLEGAL
         */
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base",});

        JcrPropertyDefinitionTemplate prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.BOOLEAN);
        prop.setMultiple(false);
        ntTemplate.getPropertyDefinitionTemplates().add(prop);

        JcrNodeTypeTemplate nodeBTemplate = new JcrNodeTypeTemplate(this.context);
        nodeBTemplate.setName(TEST_TYPE_NAME + "B");
        nodeBTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        prop = new JcrPropertyDefinitionTemplate(this.context);
        prop.setName(TEST_PROPERTY_NAME);
        prop.setRequiredType(PropertyType.DOUBLE);
        prop.setMultiple(false);
        nodeBTemplate.getPropertyDefinitionTemplates().add(prop);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate, nodeBTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test
    public void shouldAllowOverridingChildNodeIfRequiredTypesNarrow() throws Exception {
        /*
         * testNode declares No-SNS childNode testChildNode requiring type nt:hierarchy
         * testNodeB extends testNode with No-SNS childNode testChildNode requiring type nt:file -> LEGAL
         */
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base",});

        JcrNodeDefinitionTemplate child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(TEST_CHILD_NODE_NAME);
        child.setRequiredPrimaryTypes(new String[] {"nt:hierarchyNode"});
        child.setSameNameSiblings(false);
        ntTemplate.getNodeDefinitionTemplates().add(child);

        JcrNodeTypeTemplate nodeBTemplate = new JcrNodeTypeTemplate(this.context);
        nodeBTemplate.setName(TEST_TYPE_NAME + "B");
        nodeBTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(TEST_CHILD_NODE_NAME);
        child.setRequiredPrimaryTypes(new String[] {"nt:file"});
        child.setSameNameSiblings(false);
        nodeBTemplate.getNodeDefinitionTemplates().add(child);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate, nodeBTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowOverridingChildNodeIfRequiredTypesDoNotNarrow() throws Exception {
        /*
         * testNode declares No-SNS childNode testChildNode requiring type nt:hierarchy
         * testNodeB extends testNode with No-SNS childNode testChildNode requiring type nt:base -> ILLEGAL
         */
        ntTemplate.setName(TEST_TYPE_NAME);
        ntTemplate.setDeclaredSupertypeNames(new String[] {"nt:base",});

        JcrNodeDefinitionTemplate child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(TEST_CHILD_NODE_NAME);
        child.setRequiredPrimaryTypes(new String[] {"nt:hierarchyNode"});
        child.setSameNameSiblings(false);
        ntTemplate.getNodeDefinitionTemplates().add(child);

        JcrNodeTypeTemplate nodeBTemplate = new JcrNodeTypeTemplate(this.context);
        nodeBTemplate.setName(TEST_TYPE_NAME + "B");
        nodeBTemplate.setDeclaredSupertypeNames(new String[] {TEST_TYPE_NAME});

        child = new JcrNodeDefinitionTemplate(this.context);
        child.setName(TEST_CHILD_NODE_NAME);
        child.setRequiredPrimaryTypes(new String[] {"nt:base"});
        child.setSameNameSiblings(false);
        nodeBTemplate.getNodeDefinitionTemplates().add(child);

        List<NodeTypeDefinition> templates = Arrays.asList(new NodeTypeDefinition[] {ntTemplate, nodeBTemplate});
        compareTemplatesToNodeTypes(templates, repoTypeManager.registerNodeTypes(templates, false));
    }

    /*
     * Unregistration tests
     */

    @Test( expected = IllegalArgumentException.class )
    public void shouldNotAllowUnregisteringNullCollection() throws Exception {
        repoTypeManager.unregisterNodeType(null);
    }

    @Test( expected = NoSuchNodeTypeException.class )
    public void shouldNotAllowUnregisteringInvalidTypeNames() throws Exception {
        repoTypeManager.unregisterNodeType(Arrays.asList(new Name[] {JcrNtLexicon.FILE, JcrLexicon.DATA}));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowUnregisteringSupertype() throws Exception {
        repoTypeManager.unregisterNodeType(Arrays.asList(new Name[] {JcrNtLexicon.HIERARCHY_NODE,}));

    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowUnregisteringRequiredPrimaryType() throws Exception {
        repoTypeManager.unregisterNodeType(Arrays.asList(new Name[] {JcrNtLexicon.FROZEN_NODE,}));
    }

    @Test( expected = InvalidNodeTypeDefinitionException.class )
    public void shouldNotAllowUnregisteringDefaultPrimaryType() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);

        JcrNodeDefinitionTemplate childNode = new JcrNodeDefinitionTemplate(this.context);
        childNode.setDefaultPrimaryType(JcrNtLexicon.FILE.getString(this.registry));
        ntTemplate.getNodeDefinitionTemplates().add(childNode);

        try {
            repoTypeManager.registerNodeType(ntTemplate, false);
        } catch (Exception ex) {
            fail(ex.getMessage());
        }

        repoTypeManager.unregisterNodeType(Arrays.asList(new Name[] {JcrNtLexicon.FILE,}));
    }

    @Test
    public void shouldAllowUnregisteringUnusedType() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);

        JcrNodeDefinitionTemplate childNode = new JcrNodeDefinitionTemplate(this.context);
        childNode.setDefaultPrimaryType(JcrNtLexicon.FILE.getString(this.registry));
        ntTemplate.getNodeDefinitionTemplates().add(childNode);

        try {
            repoTypeManager.registerNodeType(ntTemplate, false);
        } catch (Exception ex) {
            fail(ex.getMessage());
        }

        Name typeNameAsName = nameFactory.create(TEST_TYPE_NAME);
        int nodeTypeCount = repoTypeManager.getAllNodeTypes().size();
        repoTypeManager.unregisterNodeType(Arrays.asList(new Name[] {typeNameAsName}));
        assertThat(repoTypeManager.getAllNodeTypes().size(), is(nodeTypeCount - 1));
        assertThat(repoTypeManager.getNodeType(typeNameAsName), is(nullValue()));
    }

    @Test
    public void shouldAllowUnregisteringUnusedTypesWithMutualDependencies() throws Exception {
        ntTemplate.setName(TEST_TYPE_NAME);

        JcrNodeDefinitionTemplate childNode = new JcrNodeDefinitionTemplate(this.context);
        childNode.setDefaultPrimaryType(TEST_TYPE_NAME2);
        ntTemplate.getNodeDefinitionTemplates().add(childNode);

        NodeTypeTemplate ntTemplate2 = new JcrNodeTypeTemplate(this.context);
        ntTemplate2.setName(TEST_TYPE_NAME2);

        JcrNodeDefinitionTemplate childNode2 = new JcrNodeDefinitionTemplate(this.context);
        childNode2.setDefaultPrimaryType(TEST_TYPE_NAME);
        ntTemplate2.getNodeDefinitionTemplates().add(childNode2);

        try {
            repoTypeManager.registerNodeTypes(Arrays.asList(new NodeTypeDefinition[] {ntTemplate, ntTemplate2}), false);
        } catch (Exception ex) {
            fail(ex.getMessage());
        }

        Name typeNameAsName = nameFactory.create(TEST_TYPE_NAME);
        Name type2NameAsName = nameFactory.create(TEST_TYPE_NAME2);
        int nodeTypeCount = repoTypeManager.getAllNodeTypes().size();
        repoTypeManager.unregisterNodeType(Arrays.asList(new Name[] {typeNameAsName, type2NameAsName}));
        assertThat(repoTypeManager.getAllNodeTypes().size(), is(nodeTypeCount - 2));
        assertThat(repoTypeManager.getNodeType(typeNameAsName), is(nullValue()));
        assertThat(repoTypeManager.getNodeType(type2NameAsName), is(nullValue()));

    }

    private void compareTemplatesToNodeTypes( List<NodeTypeDefinition> templates,
                                              List<JcrNodeType> nodeTypes ) {
        assertThat(templates.size(), is(nodeTypes.size()));

        for (int i = 0; i < nodeTypes.size(); i++) {
            JcrNodeTypeTemplate jntt = (JcrNodeTypeTemplate)templates.get(i);
            compareTemplateToNodeType(jntt, null);
            compareTemplateToNodeType(jntt, nodeTypes.get(i));
        }
    }

    private void compareTemplateToNodeType( JcrNodeTypeTemplate template,
                                            JcrNodeType nodeType ) {
        Name nodeTypeName = nameFactory.create(template.getName());
        if (nodeType == null) {
            nodeType = repoTypeManager.getNodeType(nodeTypeName);
            assertThat(nodeType.nodeTypeManager(), is(notNullValue()));
        }

        assertThat(nodeType, is(notNullValue()));
        assertThat(nodeType.getName(), is(template.getName()));
        assertThat(nodeType.getDeclaredSupertypes().length, is(template.getDeclaredSupertypes().length));
        for (int i = 0; i < template.getDeclaredSupertypes().length; i++) {
            assertThat(template.getDeclaredSupertypes()[i], is(nodeType.getDeclaredSupertypes()[i].getName()));
        }
        assertThat(template.isMixin(), is(nodeType.isMixin()));
        assertThat(template.hasOrderableChildNodes(), is(nodeType.hasOrderableChildNodes()));

        PropertyDefinition[] propertyDefs = nodeType.getDeclaredPropertyDefinitions();
        List<PropertyDefinitionTemplate> propertyTemplates = template.getPropertyDefinitionTemplates();

        assertThat(propertyDefs.length, is(propertyTemplates.size()));
        for (PropertyDefinitionTemplate pt : propertyTemplates) {
            JcrPropertyDefinitionTemplate propertyTemplate = (JcrPropertyDefinitionTemplate)pt;

            PropertyDefinition matchingDefinition = null;
            for (int i = 0; i < propertyDefs.length; i++) {
                PropertyDefinition pd = propertyDefs[i];

                String ptName = propertyTemplate.getName() == null ? JcrNodeType.RESIDUAL_ITEM_NAME : propertyTemplate.getName();
                if (pd.getName().equals(ptName) && pd.getRequiredType() == propertyTemplate.getRequiredType()
                    && pd.isMultiple() == propertyTemplate.isMultiple()) {
                    matchingDefinition = pd;
                    break;
                }
            }

            comparePropertyTemplateToPropertyDefinition(propertyTemplate, (JcrPropertyDefinition)matchingDefinition);
        }

        NodeDefinition[] childNodeDefs = nodeType.getDeclaredChildNodeDefinitions();
        List<NodeDefinitionTemplate> childNodeTemplates = template.getNodeDefinitionTemplates();

        assertThat(childNodeDefs.length, is(childNodeTemplates.size()));
        for (NodeDefinitionTemplate nt : childNodeTemplates) {
            JcrNodeDefinitionTemplate childNodeTemplate = (JcrNodeDefinitionTemplate)nt;

            NodeDefinition matchingDefinition = null;
            for (int i = 0; i < childNodeDefs.length; i++) {
                NodeDefinition nd = childNodeDefs[i];

                String ntName = childNodeTemplate.getName() == null ? JcrNodeType.RESIDUAL_ITEM_NAME : childNodeTemplate.getName();
                if (nd.getName().equals(ntName) && nd.allowsSameNameSiblings() == childNodeTemplate.allowsSameNameSiblings()) {

                    if (nd.getRequiredPrimaryTypes().length != childNodeTemplate.getRequiredPrimaryTypeNames().length) continue;

                    boolean matchesOnRequiredTypes = true;
                    for (int j = 0; j < nd.getRequiredPrimaryTypes().length; j++) {
                        String ndName = nd.getRequiredPrimaryTypes()[j].getName();
                        String tempName = childNodeTemplate.getRequiredPrimaryTypeNames()[j];
                        if (!ndName.equals(tempName)) {
                            matchesOnRequiredTypes = false;
                            break;
                        }
                    }

                    if (matchesOnRequiredTypes) {
                        matchingDefinition = nd;
                        break;
                    }
                }
            }

            compareNodeTemplateToNodeDefinition(childNodeTemplate, (JcrNodeDefinition)matchingDefinition);
        }

    }

    private void comparePropertyTemplateToPropertyDefinition( JcrPropertyDefinitionTemplate template,
                                                              JcrPropertyDefinition definition ) {

        assertThat(definition, is(notNullValue()));
        assertThat(definition.getDeclaringNodeType(), is(notNullValue()));
        // Had to match on name to even get to the definition
        // assertThat(template.getName(), is(definition.getName()));

        assertThat(template.getValueConstraints(), is(definition.getValueConstraints()));
        assertThat(template.getOnParentVersion(), is(definition.getOnParentVersion()));
        assertThat(template.getRequiredType(), is(definition.getRequiredType()));
        assertThat(template.isAutoCreated(), is(definition.isAutoCreated()));
        assertThat(template.isMandatory(), is(definition.isMandatory()));
        assertThat(template.isMultiple(), is(definition.isMultiple()));
        assertThat(template.isProtected(), is(definition.isProtected()));
    }

    private void compareNodeTemplateToNodeDefinition( JcrNodeDefinitionTemplate template,
                                                      JcrNodeDefinition definition ) {
        assertThat(definition, is(notNullValue()));
        assertThat(definition.getDeclaringNodeType(), is(notNullValue()));
        // Had to match on name to even get to the definition
        // assertThat(template.getName(), is(definition.getName()));

        assertThat(template.getOnParentVersion(), is(definition.getOnParentVersion()));
        assertThat(template.isAutoCreated(), is(definition.isAutoCreated()));
        assertThat(template.isMandatory(), is(definition.isMandatory()));
        assertThat(template.isProtected(), is(definition.isProtected()));

        assertThat(template.getDefaultPrimaryType(), is(definition.getDefaultPrimaryType()));
        assertThat(template.allowsSameNameSiblings(), is(definition.allowsSameNameSiblings()));

        // assertThat(template.getRequiredPrimaryTypeNames(), is(definition.getRequiredPrimaryTypeNames()));

    }

}
TOP

Related Classes of org.jboss.dna.jcr.TypeRegistrationTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.