/*
* 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.test.api.nodetype;
import java.util.List;
import java.util.Arrays;
import javax.jcr.PropertyType;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.nodetype.NodeTypeTemplate;
import javax.jcr.nodetype.PropertyDefinitionTemplate;
import javax.jcr.nodetype.NodeDefinitionTemplate;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NodeTypeDefinition;
import javax.jcr.nodetype.PropertyDefinition;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeTypeExistsException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.query.qom.QueryObjectModelConstants;
import javax.jcr.version.OnParentVersionAction;
import org.apache.jackrabbit.test.AbstractJCRTest;
/**
* Tests the node type creation functionality of the {@link NodeTypeManager}.
*
*/
public class NodeTypeCreationTest extends AbstractJCRTest {
private String expandedPropName;
private String jcrPropName;
private NodeTypeManager ntm;
/**
* Sets up the fixture for the test cases.
*/
protected void setUp() throws Exception {
super.setUp();
ntm = superuser.getWorkspace().getNodeTypeManager();
super.checkSupportedOption(Repository.OPTION_NODE_TYPE_MANAGEMENT_SUPPORTED);
expandedPropName = "{" + NS_JCR_URI + "}" + "boolean";
jcrPropName = superuser.getNamespacePrefix(NS_JCR_URI) + ":boolean";
}
/**
* Releases the session aquired in {@link #setUp()}.
*/
protected void tearDown() throws Exception {
super.tearDown();
}
public void testEmptyNodeTypeTemplate() throws Exception {
NodeTypeTemplate ntt = ntm.createNodeTypeTemplate();
assertNull(ntt.getName());
assertFalse(ntt.isMixin());
assertFalse(ntt.isAbstract());
assertFalse(ntt.hasOrderableChildNodes());
// note: isQueryable cannot be tested as defautl value is defined
// by the implementation
assertNotNull(ntt.getDeclaredSupertypeNames());
assertEquals(0, ntt.getDeclaredSupertypeNames().length);
assertNull(ntt.getPrimaryItemName());
assertNull(ntt.getDeclaredChildNodeDefinitions());
assertNull(ntt.getDeclaredPropertyDefinitions());
assertNotNull(ntt.getNodeDefinitionTemplates());
assertTrue(ntt.getNodeDefinitionTemplates().isEmpty());
assertNotNull(ntt.getPropertyDefinitionTemplates());
assertTrue(ntt.getPropertyDefinitionTemplates().isEmpty());
}
public void testNonEmptyNodeTypeTemplate() throws Exception {
NodeTypeDefinition ntd = ntm.getNodeType("nt:address");
NodeTypeTemplate ntt = ntm.createNodeTypeTemplate(ntm.getNodeType("nt:address"));
assertEquals(ntt.getName(), ntd.getName());
assertEquals(ntt.isMixin(), ntd.isMixin());
assertEquals(ntt.isAbstract(), ntd.isAbstract());
assertEquals(ntt.hasOrderableChildNodes(), ntd.hasOrderableChildNodes());
assertEquals(ntt.isQueryable(), ntd.isQueryable());
assertEquals(ntt.getPrimaryItemName(), ntd.getPrimaryItemName());
assertTrue(Arrays.equals(ntt.getDeclaredSupertypeNames(), ntd.getDeclaredSupertypeNames()));
NodeDefinition[] nda = ntt.getDeclaredChildNodeDefinitions();
NodeDefinition[] nda1 = ntd.getDeclaredChildNodeDefinitions();
assertEquals(nda.length, nda1.length);
for (int i = 0; i < nda.length; i++) {
assertEquals(nda[i].getName(), nda1[i].getName());
assertEquals(nda[i].allowsSameNameSiblings(), nda1[i].allowsSameNameSiblings());
assertTrue(Arrays.equals(nda[i].getRequiredPrimaryTypeNames(), nda1[i].getRequiredPrimaryTypeNames()));
assertEquals(nda[i].getDefaultPrimaryTypeName(), nda1[i].getDefaultPrimaryTypeName());
assertEquals(nda[i].getRequiredPrimaryTypeNames(), nda1[i].getRequiredPrimaryTypeNames());
}
PropertyDefinition[] pda = ntt.getDeclaredPropertyDefinitions();
PropertyDefinition[] pda1 = ntd.getDeclaredPropertyDefinitions();
assertEquals(pda.length, pda1.length);
for (int i = 0; i < pda.length; i++) {
assertEquals(pda[i].getName(), pda1[i].getName());
assertEquals(pda[i].getRequiredType(), pda1[i].getRequiredType());
assertTrue(Arrays.equals(pda[i].getAvailableQueryOperators(), pda1[i].getAvailableQueryOperators()));
assertTrue(Arrays.equals(pda[i].getValueConstraints(), pda1[i].getValueConstraints()));
assertEquals(pda[i].isFullTextSearchable(), pda1[i].isFullTextSearchable());
assertEquals(pda[i].isMultiple(), pda1[i].isMultiple());
assertEquals(pda[i].isQueryOrderable(), pda1[i].isQueryOrderable());
}
}
public void testNewNodeTypeTemplate() throws Exception {
String expandedName = "{" + NS_MIX_URI + "}" + "littlemixin";
String jcrName = superuser.getNamespacePrefix(NS_MIX_URI) + ":littlemixin";
NodeTypeTemplate ntt = ntm.createNodeTypeTemplate();
ntt.setName(expandedName);
assertEquals(jcrName, ntt.getName());
ntt.setName(jcrName);
assertEquals(jcrName, ntt.getName());
ntt.setAbstract(false);
assertFalse(ntt.isAbstract());
try {
ntt.setDeclaredSuperTypeNames(null);
fail("null isn't a valid array of jcr name");
} catch (ConstraintViolationException e) {
// success
}
assertNotNull(ntt.getDeclaredSupertypeNames());
assertEquals(0, ntt.getDeclaredSupertypeNames().length);
ntt.setDeclaredSuperTypeNames(new String[] {mixReferenceable});
assertNotNull(ntt.getDeclaredSupertypeNames());
assertEquals(1, ntt.getDeclaredSupertypeNames().length);
assertEquals(mixReferenceable, ntt.getDeclaredSupertypeNames()[0]);
ntt.setMixin(true);
assertTrue(ntt.isMixin());
ntt.setOrderableChildNodes(true);
assertTrue(ntt.hasOrderableChildNodes());
ntt.setQueryable(false);
assertFalse(ntt.isQueryable());
ntt.setPrimaryItemName(null);
assertNull(ntt.getPrimaryItemName());
ntt.setPrimaryItemName(jcrPrimaryType);
assertEquals(jcrPrimaryType, ntt.getPrimaryItemName());
PropertyDefinitionTemplate pdTemplate = createBooleanPropTemplate();
List pdefs = ntt.getPropertyDefinitionTemplates();
pdefs.add(pdTemplate);
assertNotNull(ntt.getDeclaredPropertyDefinitions());
assertEquals(1, ntt.getDeclaredPropertyDefinitions().length);
assertEquals(pdTemplate, ntt.getDeclaredPropertyDefinitions()[0]);
pdefs = ntt.getPropertyDefinitionTemplates();
assertEquals(1, pdefs.size());
assertEquals(pdTemplate, pdefs.get(0));
NodeDefinitionTemplate ndTemplate = ntm.createNodeDefinitionTemplate();
List ndefs = ntt.getNodeDefinitionTemplates();
ndefs.add(ndTemplate);
assertNotNull(ntt.getDeclaredChildNodeDefinitions());
assertEquals(1, ntt.getDeclaredChildNodeDefinitions().length);
assertEquals(ndTemplate, ntt.getDeclaredChildNodeDefinitions()[0]);
ndefs = ntt.getNodeDefinitionTemplates();
assertEquals(1, ndefs.size());
assertEquals(ndTemplate, ndefs.get(0));
}
public void testEmptyPropertyDefinitionTemplate() throws Exception {
PropertyDefinitionTemplate pdt = ntm.createPropertyDefinitionTemplate();
assertNull(pdt.getName());
assertFalse(pdt.isAutoCreated());
assertFalse(pdt.isMandatory());
assertFalse(pdt.isProtected());
assertEquals(OnParentVersionAction.COPY, pdt.getOnParentVersion());
assertNull(pdt.getDeclaringNodeType());
assertEquals(PropertyType.STRING, pdt.getRequiredType());
assertFalse(pdt.isMultiple());
assertNull(pdt.getValueConstraints());
assertNull(pdt.getDefaultValues());
// the following methods cannot be tested as default value is
// implementation specific:
// - getAvailableQueryOperators
// - isFullTextSearchable
// - isQueryOrderable
}
public void testPropertyDefinitionTemplate() throws Exception {
PropertyDefinitionTemplate pdt = createBooleanPropTemplate();
assertEquals(jcrPropName, pdt.getName());
try {
pdt.setName(null);
fail("null isn't a valid JCR name");
} catch (ConstraintViolationException e) {
// success
}
assertEquals(false, pdt.isAutoCreated());
assertEquals(false, pdt.isMandatory());
assertEquals(OnParentVersionAction.IGNORE, pdt.getOnParentVersion());
assertEquals(false, pdt.isProtected());
assertEquals(PropertyType.BOOLEAN, pdt.getRequiredType());
assertEquals(null, pdt.getValueConstraints());
assertEquals(null, pdt.getDefaultValues());
assertEquals(false, pdt.isMultiple());
String[] qo = pdt.getAvailableQueryOperators();
assertEquals(1, qo.length);
assertEquals(QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, qo[0]);
assertEquals(false, pdt.isFullTextSearchable());
assertEquals(false, pdt.isQueryOrderable());
}
public void testSetDefaultValues() throws Exception {
PropertyDefinitionTemplate pdt = ntm.createPropertyDefinitionTemplate();
pdt.setRequiredType(PropertyType.LONG);
pdt.setDefaultValues(null);
assertNull(pdt.getDefaultValues());
pdt.setDefaultValues(new Value[0]);
assertNotNull(pdt.getDefaultValues());
assertEquals(0, pdt.getDefaultValues().length);
pdt.setDefaultValues(new Value[] { superuser.getValueFactory().createValue(24)});
assertNotNull(pdt.getDefaultValues());
assertEquals(1, pdt.getDefaultValues().length);
assertEquals(24, pdt.getDefaultValues()[0].getLong());
assertEquals(PropertyType.LONG, pdt.getDefaultValues()[0].getType());
}
public void testEmptyNodeDefinitionTemplate() throws Exception {
NodeDefinitionTemplate ndt = ntm.createNodeDefinitionTemplate();
assertNull(ndt.getName());
assertFalse(ndt.isAutoCreated());
assertFalse(ndt.isMandatory());
assertFalse(ndt.isProtected());
assertEquals(OnParentVersionAction.COPY, ndt.getOnParentVersion());
assertNull(ndt.getDeclaringNodeType());
assertNull(ndt.getRequiredPrimaryTypes());
assertNull(ndt.getRequiredPrimaryTypeNames());
assertNull(ndt.getDefaultPrimaryType());
assertNull(ndt.getDefaultPrimaryTypeName());
assertFalse(ndt.allowsSameNameSiblings());
}
public void testNodeDefinitionTemplate() throws Exception {
NodeDefinitionTemplate ndt = ntm.createNodeDefinitionTemplate();
try {
ndt.setName(null);
fail("null isn't a valid JCR name");
} catch (ConstraintViolationException e) {
// success
}
String expandedName = "{" + NS_JCR_URI + "}" + "content";
String jcrName = superuser.getNamespacePrefix(NS_JCR_URI) + ":content";
ndt.setName(expandedName);
assertEquals(jcrName, ndt.getName());
ndt.setName(jcrName);
assertEquals(jcrName, ndt.getName());
ndt.setSameNameSiblings(true);
assertTrue(ndt.allowsSameNameSiblings());
ndt.setAutoCreated(true);
assertTrue(ndt.isAutoCreated());
ndt.setMandatory(true);
assertTrue(ndt.isMandatory());
ndt.setProtected(true);
assertTrue(ndt.isProtected());
ndt.setOnParentVersion(OnParentVersionAction.VERSION);
assertEquals(OnParentVersionAction.VERSION, ndt.getOnParentVersion());
expandedName = "{" + NS_NT_URI + "}" + "folder";
jcrName = superuser.getNamespacePrefix(NS_NT_URI) + ":folder";
ndt.setDefaultPrimaryTypeName(expandedName);
assertEquals(jcrName, ndt.getDefaultPrimaryTypeName());
ndt.setDefaultPrimaryTypeName(null);
assertEquals("setting null must clear the name.", null, ndt.getDefaultPrimaryTypeName());
ndt.setRequiredPrimaryTypeNames(new String[] {expandedName});
assertNotNull(ndt.getRequiredPrimaryTypeNames());
assertEquals(1, ndt.getRequiredPrimaryTypeNames().length);
assertEquals(jcrName, ndt.getRequiredPrimaryTypeNames()[0]);
try {
ndt.setRequiredPrimaryTypeNames(null);
fail("null isn't a valid array of jcr name");
} catch (ConstraintViolationException e) {
// success
}
}
public void testResidualNames() throws Exception {
String residualName = "*";
NodeDefinitionTemplate ndt = ntm.createNodeDefinitionTemplate();
ndt.setName(residualName);
assertEquals(residualName, ndt.getName());
PropertyDefinitionTemplate pdt = ntm.createPropertyDefinitionTemplate();
pdt.setName(residualName);
assertEquals(residualName, pdt.getName());
}
public void testInvalidJCRNames() throws Exception {
String invalidName = ":ab[2]";
// invalid name(s) passed to NT-template methods
NodeTypeTemplate ntt = ntm.createNodeTypeTemplate();
try {
ntt.setName(invalidName);
fail("ConstraintViolationException expected. Nt-name is invalid");
} catch (ConstraintViolationException e) {
// success
}
try {
ntt.setDeclaredSuperTypeNames(new String[] {"{" + NS_MIX_URI + "}" + "littlemixin", invalidName});
fail("ConstraintViolationException expected. One of the super type names is invalid");
} catch (ConstraintViolationException e) {
// success
}
try {
ntt.setPrimaryItemName(invalidName);
fail("ConstraintViolationException expected. Primary item name is invalid");
} catch (ConstraintViolationException e) {
// success
}
// invalid name(s) passed to NodeDefinitionTemplate
NodeDefinitionTemplate ndt = ntm.createNodeDefinitionTemplate();
try {
ndt.setName(invalidName);
fail("ConstraintViolationException expected. Name is invalid");
} catch (ConstraintViolationException e) {
// success
}
try {
ndt.setRequiredPrimaryTypeNames(new String[] {"{" + NS_MIX_URI + "}" + "littlemixin", invalidName});
fail("ConstraintViolationException expected. One of the required primary type names is invalid");
} catch (ConstraintViolationException e) {
// success
}
try {
ndt.setDefaultPrimaryTypeName(invalidName);
fail("ConstraintViolationException expected. Default primary type name is invalid");
} catch (ConstraintViolationException e) {
// success
}
// invalid name(s) passed to PropertyDefinitionTemplate
PropertyDefinitionTemplate pdt = ntm.createPropertyDefinitionTemplate();
try {
pdt.setName(invalidName);
fail("ConstraintViolationException expected. Name is invalid");
} catch (ConstraintViolationException e) {
// success
}
}
public void testRegisterNodeType() throws Exception {
NodeTypeTemplate ntt = ntm.createNodeTypeTemplate();
ntt.setName("mix:foo");
ntt.setAbstract(false);
ntt.setMixin(true);
ntt.setOrderableChildNodes(false);
ntt.setQueryable(false);
PropertyDefinitionTemplate pdt = ntm.createPropertyDefinitionTemplate();
pdt.setAutoCreated(false);
pdt.setName("foo");
pdt.setMultiple(false);
pdt.setRequiredType(PropertyType.STRING);
List pdefs = ntt.getPropertyDefinitionTemplates();
pdefs.add(pdt);
ntm.registerNodeType(ntt, true);
try {
ntm.registerNodeType(ntt, false);
fail("NodeTypeExistsException expected.");
} catch (NodeTypeExistsException e) {
// success
}
}
public void testUnregisterNodeType() throws Exception {
try {
ntm.unregisterNodeType("unknownnodetype");
fail("NoSuchNodeTypeException expected.");
} catch (NoSuchNodeTypeException e) {
// success
}
try {
ntm.unregisterNodeType("nt:base");
fail("RepositoryException expected.");
} catch (RepositoryException e) {
// success
}
}
public void testUnregisterNodeTypes() throws Exception {
try {
ntm.unregisterNodeTypes(new String[] {"unknownnodetype1","unknownnodetype2"});
fail("NoSuchNodeTypeException expected.");
} catch (NoSuchNodeTypeException e) {
// success
}
try {
ntm.unregisterNodeTypes(new String[] {"nt:base", "nt:address"});
fail("RepositoryException expected.");
} catch (RepositoryException e) {
// success
}
}
public void testRegisterNodeTypes() throws Exception {
NodeTypeDefinition[] defs = new NodeTypeDefinition[5];
for (int i = 0; i < defs.length; i++) {
NodeTypeTemplate ntt = ntm.createNodeTypeTemplate();
ntt.setName("mix:foo" + i);
ntt.setAbstract(false);
ntt.setMixin(true);
ntt.setOrderableChildNodes(false);
ntt.setQueryable(false);
PropertyDefinitionTemplate pdt = ntm.createPropertyDefinitionTemplate();
pdt.setAutoCreated(false);
pdt.setName("foo" + i);
pdt.setMultiple(false);
pdt.setRequiredType(PropertyType.STRING);
List pdefs = ntt.getPropertyDefinitionTemplates();
pdefs.add(pdt);
defs[i] = ntt;
}
ntm.registerNodeTypes(defs, true);
try {
ntm.registerNodeTypes(defs, false);
fail("NodeTypeExistsException expected.");
} catch (NodeTypeExistsException e) {
// success
}
}
private PropertyDefinitionTemplate createBooleanPropTemplate() throws RepositoryException {
PropertyDefinitionTemplate pdt = ntm.createPropertyDefinitionTemplate();
pdt.setName(expandedPropName);
pdt.setAutoCreated(false);
pdt.setMandatory(false);
pdt.setOnParentVersion(OnParentVersionAction.IGNORE);
pdt.setProtected(false);
pdt.setRequiredType(PropertyType.BOOLEAN);
pdt.setValueConstraints(null);
pdt.setDefaultValues(null);
pdt.setMultiple(false);
pdt.setAvailableQueryOperators(new String[] { QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO });
pdt.setFullTextSearchable(false);
pdt.setQueryOrderable(false);
return pdt;
}
}