/* * ModeShape (http://www.modeshape.org) * * Licensed 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.modeshape.jcr; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.notNullValue; import static org.junit.Assert.assertThat; import java.util.Arrays; import java.util.Collections; import java.util.List; import javax.jcr.Node; import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.Value; import javax.jcr.ValueFormatException; import javax.jcr.nodetype.ConstraintViolationException; import javax.jcr.nodetype.NodeType; import javax.jcr.nodetype.NodeTypeDefinition; import javax.jcr.nodetype.NodeTypeManager; import javax.jcr.nodetype.NodeTypeTemplate; import javax.jcr.nodetype.PropertyDefinition; import javax.jcr.nodetype.PropertyDefinitionTemplate; import javax.jcr.version.OnParentVersionAction; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.modeshape.common.FixFor; import org.modeshape.jcr.cache.NodeKey; import org.modeshape.jcr.value.Name; import org.modeshape.jcr.value.NamespaceRegistry; public class JcrPropertyDefinitionTest extends MultiUseAbstractTest { protected static final String[] EXPECTED_BINARY_CONSTRAINTS = new String[] {"[,5)", "[10, 20)", "(30,40]", "[50,]"}; protected static final String[] EXPECTED_DATE_CONSTRAINTS = new String[] {"[,+1945-08-01T01:30:00.000Z]", "[+1975-08-01T01:30:00.000Z,)"}; protected static final String[] EXPECTED_DOUBLE_CONSTRAINTS = new String[] {"[,5.0)", "[10.1, 20.2)", "(30.3,40.4]", "[50.5,]"}; protected static final String[] EXPECTED_LONG_CONSTRAINTS = new String[] {"[,5)", "[10, 20)", "(30,40]", "[50,]"}; protected static final String[] EXPECTED_NAME_CONSTRAINTS = new String[] {"jcr:system", "modetest:constrainedType"}; protected static final String[] EXPECTED_PATH_CONSTRAINTS = new String[] {"/jcr:system/*", "b", "/a/b/c"}; protected static final String[] EXPECTED_REFERENCE_CONSTRAINTS = new String[] {"mode:root"}; protected static final String[] EXPECTED_STRING_CONSTRAINTS = new String[] {"foo", "bar*", ".*baz"}; protected NodeTypeManager nodeTypeManager; private ExecutionContext context; @BeforeClass public static final void beforeAll() throws Exception { MultiUseAbstractTest.beforeAll(); // Import the node types ... session.getWorkspace().getNamespaceRegistry().registerNamespace(TestLexicon.Namespace.PREFIX, TestLexicon.Namespace.URI); registerNodeTypes(getTestTypes()); // Create some initial content ... Node nodeA = session.getRootNode().addNode("a"); Node nodeB = nodeA.addNode("b"); Node nodeC = nodeB.addNode("c"); assertThat(nodeC, is(notNullValue())); nodeA.addMixin("mix:referenceable"); session.save(); } @AfterClass public static final void afterAll() throws Exception { MultiUseAbstractTest.afterAll(); } @Override @Before public void beforeEach() throws Exception { super.beforeEach(); nodeTypeManager = session.getWorkspace().getNodeTypeManager(); context = session.context(); } @SuppressWarnings( "unchecked" ) protected static List<NodeTypeDefinition> getTestTypes() throws RepositoryException, ConstraintViolationException { NodeTypeManager mgr = session.getWorkspace().getNodeTypeManager(); NodeTypeTemplate constrainedType = mgr.createNodeTypeTemplate(); constrainedType.setName("modetest:constrainedType"); PropertyDefinitionTemplate propBinary = mgr.createPropertyDefinitionTemplate(); propBinary.setName("modetest:constrainedBinary"); propBinary.setRequiredType(PropertyType.BINARY); propBinary.setValueConstraints(EXPECTED_BINARY_CONSTRAINTS); constrainedType.getPropertyDefinitionTemplates().add(propBinary); PropertyDefinitionTemplate propDate = mgr.createPropertyDefinitionTemplate(); propDate.setName("modetest:constrainedDate"); propDate.setRequiredType(PropertyType.DATE); propDate.setValueConstraints(EXPECTED_DATE_CONSTRAINTS); constrainedType.getPropertyDefinitionTemplates().add(propDate); PropertyDefinitionTemplate propDouble = mgr.createPropertyDefinitionTemplate(); propDouble.setName("modetest:constrainedDouble"); propDouble.setRequiredType(PropertyType.DOUBLE); propDouble.setValueConstraints(EXPECTED_DOUBLE_CONSTRAINTS); constrainedType.getPropertyDefinitionTemplates().add(propDouble); PropertyDefinitionTemplate propLong = mgr.createPropertyDefinitionTemplate(); propLong.setName("modetest:constrainedLong"); propLong.setRequiredType(PropertyType.LONG); propLong.setValueConstraints(EXPECTED_LONG_CONSTRAINTS); constrainedType.getPropertyDefinitionTemplates().add(propLong); PropertyDefinitionTemplate propName = mgr.createPropertyDefinitionTemplate(); propName.setName("modetest:constrainedName"); propName.setRequiredType(PropertyType.NAME); propName.setValueConstraints(EXPECTED_NAME_CONSTRAINTS); constrainedType.getPropertyDefinitionTemplates().add(propName); PropertyDefinitionTemplate propPath = mgr.createPropertyDefinitionTemplate(); propPath.setName("modetest:constrainedPath"); propPath.setRequiredType(PropertyType.PATH); propPath.setValueConstraints(EXPECTED_PATH_CONSTRAINTS); constrainedType.getPropertyDefinitionTemplates().add(propPath); PropertyDefinitionTemplate propReference = mgr.createPropertyDefinitionTemplate(); propReference.setName("modetest:constrainedReference"); propReference.setRequiredType(PropertyType.REFERENCE); propReference.setValueConstraints(EXPECTED_REFERENCE_CONSTRAINTS); constrainedType.getPropertyDefinitionTemplates().add(propReference); PropertyDefinitionTemplate propString = mgr.createPropertyDefinitionTemplate(); propString.setName("modetest:constrainedString"); propString.setRequiredType(PropertyType.STRING); propString.setValueConstraints(EXPECTED_STRING_CONSTRAINTS); constrainedType.getPropertyDefinitionTemplates().add(propString); return Collections.singletonList((NodeTypeDefinition)constrainedType); } private JcrPropertyDefinition propertyDefinitionFor( NodeType nodeType, Name propertyName ) { PropertyDefinition propertyDefs[] = nodeType.getPropertyDefinitions(); String property = propertyName.getString(context.getNamespaceRegistry()); for (int i = 0; i < propertyDefs.length; i++) { if (propertyDefs[i].getName().equals(property)) { return (JcrPropertyDefinition)propertyDefs[i]; } } throw new IllegalStateException("Could not find property definition name " + property + " for type " + nodeType.getName() + ". Test setup is invalid."); } private void checkConstraints( NodeType nodeType, Name propertyName, String[] expectedConstraints ) { PropertyDefinition propertyDefs[] = nodeType.getPropertyDefinitions(); String property = propertyName.getString(context.getNamespaceRegistry()); String[] constraints = null; for (int i = 0; i < propertyDefs.length; i++) { if (propertyDefs[i].getName().equals(property)) { constraints = propertyDefs[i].getValueConstraints(); break; } } if (!Arrays.equals(constraints, expectedConstraints)) { throw new IllegalStateException("Unexpected constraints for property: " + property); } } private NodeType validateTypeDefinition() throws Exception { NamespaceRegistry nsr = context.getNamespaceRegistry(); NodeType constrainedType = nodeTypeManager.getNodeType(TestLexicon.CONSTRAINED_TYPE.getString(nsr)); assertThat(constrainedType, notNullValue()); assertThat(propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_BINARY), notNullValue()); assertThat(propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_DATE), notNullValue()); assertThat(propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_DOUBLE), notNullValue()); assertThat(propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_LONG), notNullValue()); assertThat(propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_NAME), notNullValue()); assertThat(propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_PATH), notNullValue()); assertThat(propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_REFERENCE), notNullValue()); assertThat(propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_STRING), notNullValue()); checkConstraints(constrainedType, TestLexicon.CONSTRAINED_BINARY, EXPECTED_BINARY_CONSTRAINTS); checkConstraints(constrainedType, TestLexicon.CONSTRAINED_DATE, EXPECTED_DATE_CONSTRAINTS); checkConstraints(constrainedType, TestLexicon.CONSTRAINED_DOUBLE, EXPECTED_DOUBLE_CONSTRAINTS); checkConstraints(constrainedType, TestLexicon.CONSTRAINED_LONG, EXPECTED_LONG_CONSTRAINTS); checkConstraints(constrainedType, TestLexicon.CONSTRAINED_NAME, EXPECTED_NAME_CONSTRAINTS); checkConstraints(constrainedType, TestLexicon.CONSTRAINED_PATH, EXPECTED_PATH_CONSTRAINTS); checkConstraints(constrainedType, TestLexicon.CONSTRAINED_REFERENCE, EXPECTED_REFERENCE_CONSTRAINTS); checkConstraints(constrainedType, TestLexicon.CONSTRAINED_STRING, EXPECTED_STRING_CONSTRAINTS); return constrainedType; } private Value valueFor( Object value, int jcrType ) throws RepositoryException { return session.getValueFactory().createValue(value, jcrType); } private String stringOfLength( int length ) { StringBuilder buff = new StringBuilder(length); for (int i = 0; i < length; i++) { buff.append(i % 10); } return buff.toString(); } private boolean satisfiesConstraints( JcrPropertyDefinition property, Value[] values ) { for (int i = 0; i < values.length; i++) { if (!property.satisfiesConstraints(values[i], session)) { return false; } } return true; } @Test public void shouldAllowNullValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_BINARY); assertThat(prop.satisfiesConstraints((Value)null, session), is(false)); } @Test public void shouldAllowValidBinaryValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_BINARY); // Making assumption that String.getBytes().length = String.length() on the platform's default encoding assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(0), PropertyType.BINARY), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(4), PropertyType.BINARY), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(10), PropertyType.BINARY), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(19), PropertyType.BINARY), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(31), PropertyType.BINARY), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(40), PropertyType.BINARY), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(50), PropertyType.BINARY), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(99), PropertyType.BINARY), session), is(true)); } @Test public void shouldAllowValidBinaryValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_BINARY); // Making assumption that String.getBytes().length = String.length() on the platform's default encoding Value[] values = new Value[] {valueFor(stringOfLength(4), PropertyType.BINARY), valueFor(stringOfLength(10), PropertyType.BINARY), valueFor(stringOfLength(19), PropertyType.BINARY),}; assertThat(satisfiesConstraints(prop, new Value[] {}), is(true)); assertThat(satisfiesConstraints(prop, new Value[] {valueFor(stringOfLength(0), PropertyType.BINARY)}), is(true)); assertThat(satisfiesConstraints(prop, values), is(true)); } @Test public void shouldNotAllowInvalidBinaryValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_BINARY); // Making assumption that String.getBytes().length = String.length() on the platform's default encoding assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(5), PropertyType.BINARY), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(9), PropertyType.BINARY), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(20), PropertyType.BINARY), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(30), PropertyType.BINARY), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(41), PropertyType.BINARY), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(stringOfLength(49), PropertyType.BINARY), session), is(false)); } @Test public void shouldNotAllowInvalidBinaryValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_BINARY); // Making assumption that String.getBytes().length = String.length() on the platform's default encoding Value[] values = new Value[] {valueFor(stringOfLength(4), PropertyType.BINARY), valueFor(stringOfLength(10), PropertyType.BINARY), valueFor(stringOfLength(20), PropertyType.BINARY),}; assertThat(satisfiesConstraints(prop, new Value[] {valueFor(stringOfLength(9), PropertyType.BINARY)}), is(false)); assertThat(satisfiesConstraints(prop, values), is(false)); } @Test public void shouldAllowValidDateValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_DATE); assertThat(prop.satisfiesConstraints(valueFor("-1945-08-01T01:30:00.000Z", PropertyType.DATE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("+1945-07-31T01:30:00.000Z", PropertyType.DATE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("+0001-08-01T01:30:00.000Z", PropertyType.DATE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("+1975-08-01T01:30:00.000Z", PropertyType.DATE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("+1975-08-01T01:31:00.000Z", PropertyType.DATE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("+2009-08-01T01:30:00.000Z", PropertyType.DATE), session), is(true)); } @Test public void shouldAllowValidDateValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_DATE); Value[] values = new Value[] {valueFor("-1945-08-01T01:30:00.000Z", PropertyType.DATE), valueFor("+2009-08-01T01:30:00.000Z", PropertyType.DATE),}; assertThat(satisfiesConstraints(prop, new Value[] {}), is(true)); assertThat(satisfiesConstraints(prop, new Value[] {valueFor("+1975-08-01T01:31:00.000Z", PropertyType.DATE)}), is(true)); assertThat(satisfiesConstraints(prop, values), is(true)); } @Test public void shouldNotAllowInvalidDateValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_DATE); assertThat(prop.satisfiesConstraints(valueFor("+1945-08-01T01:30:00.001Z", PropertyType.DATE), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor("+1975-08-01T01:29:59.999Z", PropertyType.DATE), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor("+1945-08-01T01:30:00.000-05:00", PropertyType.DATE), session), is(false)); } @Test public void shouldNotAllowInvalidDateValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_DATE); Value[] values = new Value[] {valueFor("-1945-08-01T01:30:00.000", PropertyType.DATE), valueFor("+1945-08-01T01:30:00.000-05:00", PropertyType.DATE),}; assertThat(satisfiesConstraints(prop, new Value[] {valueFor("+1945-08-01T01:30:00.001Z", PropertyType.DATE)}), is(false)); assertThat(satisfiesConstraints(prop, values), is(false)); } @Test public void shouldAllowValidDoubleValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_DOUBLE); assertThat(prop.satisfiesConstraints(valueFor(Double.MIN_VALUE, PropertyType.DOUBLE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(0, PropertyType.DOUBLE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(0.1, PropertyType.DOUBLE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(4.99, PropertyType.DOUBLE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(10.100, PropertyType.DOUBLE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(20.19, PropertyType.DOUBLE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(30.31, PropertyType.DOUBLE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(40.4, PropertyType.DOUBLE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(50.5, PropertyType.DOUBLE), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(Double.MAX_VALUE, PropertyType.DOUBLE), session), is(true)); } @Test public void shouldAllowValidDoubleValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_DOUBLE); Value[] values = new Value[] {valueFor(0.1, PropertyType.DOUBLE), valueFor(20.19, PropertyType.DOUBLE), valueFor(50.5, PropertyType.DOUBLE)}; assertThat(satisfiesConstraints(prop, new Value[] {}), is(true)); assertThat(satisfiesConstraints(prop, new Value[] {valueFor(4.99, PropertyType.DOUBLE)}), is(true)); assertThat(satisfiesConstraints(prop, values), is(true)); } @Test public void shouldNotAllowInvalidDoubleValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_DOUBLE); assertThat(prop.satisfiesConstraints(valueFor(5, PropertyType.DOUBLE), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(9.99999999, PropertyType.DOUBLE), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(20.2, PropertyType.DOUBLE), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(30.3, PropertyType.DOUBLE), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(40.41, PropertyType.DOUBLE), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(49.9, PropertyType.DOUBLE), session), is(false)); } @Test public void shouldNotAllowInvalidDoubleValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_DOUBLE); Value[] values = new Value[] {valueFor(0.1, PropertyType.DOUBLE), valueFor(20.19, PropertyType.DOUBLE), valueFor(50.49, PropertyType.DOUBLE)}; assertThat(satisfiesConstraints(prop, new Value[] {valueFor(20.2, PropertyType.DOUBLE)}), is(false)); assertThat(satisfiesConstraints(prop, values), is(false)); } @Test public void shouldAllowValidLongValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_LONG); assertThat(prop.satisfiesConstraints(valueFor(Long.MIN_VALUE, PropertyType.LONG), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(0, PropertyType.LONG), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(0.1, PropertyType.LONG), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(4.99, PropertyType.LONG), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(10, PropertyType.LONG), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(10.100, PropertyType.LONG), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(19, PropertyType.LONG), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(31, PropertyType.LONG), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(40, PropertyType.LONG), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(50, PropertyType.LONG), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor(Long.MAX_VALUE, PropertyType.LONG), session), is(true)); } @Test public void shouldAllowValidLongValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_LONG); Value[] values = new Value[] {valueFor(0.1, PropertyType.LONG), valueFor(10, PropertyType.LONG), valueFor(50, PropertyType.LONG)}; assertThat(satisfiesConstraints(prop, new Value[] {}), is(true)); assertThat(satisfiesConstraints(prop, new Value[] {valueFor(4.99, PropertyType.LONG)}), is(true)); assertThat(satisfiesConstraints(prop, values), is(true)); } @Test public void shouldNotAllowInvalidLongValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_LONG); assertThat(prop.satisfiesConstraints(valueFor(5, PropertyType.LONG), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(9, PropertyType.LONG), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(20, PropertyType.LONG), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(30, PropertyType.LONG), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(41, PropertyType.LONG), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor(49, PropertyType.LONG), session), is(false)); } @Test public void shouldNotAllowInvalidLongValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_LONG); Value[] values = new Value[] {valueFor(0.1, PropertyType.LONG), valueFor(10, PropertyType.LONG), valueFor(49, PropertyType.LONG)}; assertThat(satisfiesConstraints(prop, new Value[] {valueFor(30, PropertyType.LONG)}), is(false)); assertThat(satisfiesConstraints(prop, values), is(false)); } @Test public void shouldAllowValidNameValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_NAME); assertThat(prop.satisfiesConstraints(valueFor("jcr:system", PropertyType.NAME), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("modetest:constrainedType", PropertyType.NAME), session), is(true)); // Test that names work across namespace remaps session.setNamespacePrefix("newprefix", TestLexicon.Namespace.URI); assertThat(prop.satisfiesConstraints(valueFor("newprefix:constrainedType", PropertyType.NAME), session), is(true)); } @Test public void shouldAllowValidNameValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_NAME); Value[] values = new Value[] {valueFor("jcr:system", PropertyType.NAME), valueFor("modetest:constrainedType", PropertyType.NAME),}; assertThat(satisfiesConstraints(prop, new Value[] {}), is(true)); assertThat(satisfiesConstraints(prop, new Value[] {valueFor("jcr:system", PropertyType.NAME)}), is(true)); assertThat(satisfiesConstraints(prop, values), is(true)); } @Test( expected = ValueFormatException.class ) public void shouldNotAllowInvalidNameValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_NAME); assertThat(prop.satisfiesConstraints(valueFor("system", PropertyType.NAME), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor("jcr:system2", PropertyType.NAME), session), is(false)); // Test that old names fail after namespace remaps session.setNamespacePrefix("newprefix", TestLexicon.Namespace.URI); assertThat(prop.satisfiesConstraints(valueFor("modetest:constrainedType", PropertyType.NAME), session), is(false)); } @Test public void shouldNotAllowInvalidNameValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_NAME); Value[] values = new Value[] {valueFor("jcr:system", PropertyType.NAME), valueFor("modetest:constrainedType2", PropertyType.NAME),}; assertThat(satisfiesConstraints(prop, new Value[] {valueFor("jcr:system2", PropertyType.NAME)}), is(false)); assertThat(satisfiesConstraints(prop, values), is(false)); } @Test public void shouldAllowValidStringValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_STRING); assertThat(prop.satisfiesConstraints(valueFor("foo", PropertyType.STRING), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("bar", PropertyType.STRING), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("barr", PropertyType.STRING), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("barrrrrrrrr", PropertyType.STRING), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("baz", PropertyType.STRING), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("shabaz", PropertyType.STRING), session), is(true)); } @Test public void shouldAllowValidStringValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_STRING); Value[] values = new Value[] {valueFor("foo", PropertyType.STRING), valueFor("barr", PropertyType.STRING),}; assertThat(satisfiesConstraints(prop, new Value[] {}), is(true)); assertThat(satisfiesConstraints(prop, new Value[] {valueFor("baz", PropertyType.STRING)}), is(true)); assertThat(satisfiesConstraints(prop, values), is(true)); } @Test public void shouldNotAllowInvalidStringValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_STRING); assertThat(prop.satisfiesConstraints(valueFor("", PropertyType.STRING), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor("foot", PropertyType.STRING), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor("abar", PropertyType.STRING), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor("bard", PropertyType.STRING), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor("baz!", PropertyType.STRING), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor("bazzat", PropertyType.STRING), session), is(false)); } @Test public void shouldNotAllowInvalidStringValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_STRING); Value[] values = new Value[] {valueFor("foo", PropertyType.STRING), valueFor("bard", PropertyType.STRING),}; assertThat(satisfiesConstraints(prop, new Value[] {valueFor("bazzat", PropertyType.STRING)}), is(false)); assertThat(satisfiesConstraints(prop, values), is(false)); } @Test public void shouldAllowValidPathValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_PATH); assertThat(prop.satisfiesConstraints(valueFor("b", PropertyType.PATH), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("/a/b/c", PropertyType.PATH), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("/jcr:system/mode:namespace", PropertyType.PATH), session), is(true)); assertThat(prop.satisfiesConstraints(valueFor("/a/b/c/", PropertyType.PATH), session), is(true)); // Test that constraints work after session rename session.setNamespacePrefix("jcr2", JcrLexicon.Namespace.URI); assertThat(prop.satisfiesConstraints(valueFor("/jcr2:system/mode:foo", PropertyType.PATH), session), is(true)); } @Test public void shouldAllowValidPathValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_PATH); Value[] values = new Value[] {valueFor("b", PropertyType.PATH), valueFor("/a/b/c", PropertyType.PATH),}; assertThat(satisfiesConstraints(prop, new Value[] {}), is(true)); assertThat(satisfiesConstraints(prop, new Value[] {valueFor("/a/b/c", PropertyType.PATH)}), is(true)); assertThat(satisfiesConstraints(prop, values), is(true)); } @Test public void shouldNotAllowInvalidPathValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_PATH); assertThat(prop.satisfiesConstraints(valueFor("a", PropertyType.PATH), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor("/a/b", PropertyType.PATH), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor("/jcr:system", PropertyType.PATH), session), is(false)); assertThat(prop.satisfiesConstraints(valueFor("/a/b/c/d", PropertyType.PATH), session), is(false)); } @Test public void shouldNotAllowInvalidPathValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_PATH); Value[] values = new Value[] {valueFor("b", PropertyType.PATH), valueFor("/a/b/c/d", PropertyType.PATH),}; assertThat(satisfiesConstraints(prop, new Value[] {valueFor("/a", PropertyType.PATH)}), is(false)); assertThat(satisfiesConstraints(prop, values), is(false)); } @Test public void shouldAllowValidReferenceValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_REFERENCE); Value value = session.getValueFactory().createValue(session.getRootNode()); assertThat(prop.satisfiesConstraints(value, session), is(true)); } @Test public void shouldAllowValidReferenceValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_REFERENCE); Value value = session.getValueFactory().createValue(session.getRootNode()); assertThat(satisfiesConstraints(prop, new Value[] {}), is(true)); assertThat(satisfiesConstraints(prop, new Value[] {value}), is(true)); } @Test public void shouldNotAllowInvalidReferenceValue() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_REFERENCE); Value value = session.getValueFactory().createValue(session.getRootNode().getNode("a")); assertThat(prop.satisfiesConstraints(value, session), is(false)); } @Test public void shouldNotAllowInvalidReferenceValues() throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, TestLexicon.CONSTRAINED_REFERENCE); Value value = session.getValueFactory().createValue(session.getRootNode().getNode("a")); assertThat(satisfiesConstraints(prop, new Value[] {value}), is(false)); } @FixFor( "MODE-1857" ) @Test public void shouldBeMoreConstrainedWithBinaryConstraints() throws Exception { assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[,4]"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[,4)"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[0,2]"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "(10,20)"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "(30,40)"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[31,40]"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[31,32)"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "(50,]"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[51,]"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[53,99]"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "(52,99)"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[,4)", "(10,20)", "[51,]"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[10, 20)", "(30,40]", "[50,]"); assertMoreConstrained(TestLexicon.CONSTRAINED_BINARY, EXPECTED_BINARY_CONSTRAINTS); // as-constrained // "[,5)", "[10, 20)", "(30,40]", "[50,]" assertNotMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[,5]"); assertNotMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[10,20]"); assertNotMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[30,40]"); assertNotMoreConstrained(TestLexicon.CONSTRAINED_BINARY, "[,]"); } @FixFor( "MODE-1857" ) @Test public void shouldBeMoreConstrainedWithDoubleConstraints() throws Exception { assertMoreConstrained(TestLexicon.CONSTRAINED_DOUBLE, "[,4.99999]"); assertMoreConstrained(TestLexicon.CONSTRAINED_DOUBLE, "[3,5)"); assertMoreConstrained(TestLexicon.CONSTRAINED_DOUBLE, "(10.1,20.2)"); assertMoreConstrained(TestLexicon.CONSTRAINED_DOUBLE, "[30.31,40.399999]"); assertMoreConstrained(TestLexicon.CONSTRAINED_DOUBLE, "(50.51,]"); assertMoreConstrained(TestLexicon.CONSTRAINED_DOUBLE, "[50.51,]"); assertMoreConstrained(TestLexicon.CONSTRAINED_DOUBLE, EXPECTED_DOUBLE_CONSTRAINTS); // as-constrained // "[,5.0)", "[10.1, 20.2)", "(30.3,40.4]", "[50.5,]" assertNotMoreConstrained(TestLexicon.CONSTRAINED_DOUBLE, "[,5.0]"); assertNotMoreConstrained(TestLexicon.CONSTRAINED_DOUBLE, "[10.0,20]"); } @FixFor( "MODE-1857" ) @Test public void shouldBeMoreConstrainedWithNameConstraints() throws Exception { assertMoreConstrained(TestLexicon.CONSTRAINED_NAME, EXPECTED_NAME_CONSTRAINTS[0]); assertMoreConstrained(TestLexicon.CONSTRAINED_NAME, EXPECTED_NAME_CONSTRAINTS[1]); assertMoreConstrained(TestLexicon.CONSTRAINED_NAME, EXPECTED_NAME_CONSTRAINTS); // as-constrained // "jcr:system", "modetest:constrainedType" assertNotMoreConstrained(TestLexicon.CONSTRAINED_NAME, EXPECTED_NAME_CONSTRAINTS[0] + "x"); assertNotMoreConstrained(TestLexicon.CONSTRAINED_NAME, ""); } @FixFor( "MODE-1857" ) @Test public void shouldBeMoreConstrainedWithPathConstraints() throws Exception { assertMoreConstrained(TestLexicon.CONSTRAINED_PATH, "/jcr:system"); assertMoreConstrained(TestLexicon.CONSTRAINED_PATH, "/jcr:system/jcr:namespaces"); assertMoreConstrained(TestLexicon.CONSTRAINED_PATH, "/a/b/c"); assertMoreConstrained(TestLexicon.CONSTRAINED_PATH, EXPECTED_PATH_CONSTRAINTS[0]); assertMoreConstrained(TestLexicon.CONSTRAINED_PATH, EXPECTED_PATH_CONSTRAINTS[1]); assertMoreConstrained(TestLexicon.CONSTRAINED_PATH, EXPECTED_PATH_CONSTRAINTS[2]); assertMoreConstrained(TestLexicon.CONSTRAINED_PATH, EXPECTED_PATH_CONSTRAINTS); // as-constrained // "/jcr:system/*", "b", "/a/b/c" assertNotMoreConstrained(TestLexicon.CONSTRAINED_PATH, "/"); assertNotMoreConstrained(TestLexicon.CONSTRAINED_PATH, "/jcr:somethingelse"); assertNotMoreConstrained(TestLexicon.CONSTRAINED_PATH, "b/c/d"); assertNotMoreConstrained(TestLexicon.CONSTRAINED_PATH, "/a/b/c/d"); } @FixFor( "MODE-1857" ) @Test public void shouldBeMoreConstrainedWithStringConstraints() throws Exception { assertMoreConstrained(TestLexicon.CONSTRAINED_STRING, EXPECTED_STRING_CONSTRAINTS[0]); assertMoreConstrained(TestLexicon.CONSTRAINED_STRING, EXPECTED_STRING_CONSTRAINTS[1]); assertMoreConstrained(TestLexicon.CONSTRAINED_STRING, EXPECTED_STRING_CONSTRAINTS); // as-constrained assertNotMoreConstrained(TestLexicon.CONSTRAINED_STRING, EXPECTED_STRING_CONSTRAINTS[0] + "x"); assertNotMoreConstrained(TestLexicon.CONSTRAINED_STRING, ""); } protected void assertMoreConstrained( Name defnName, String... constraints ) throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, defnName); JcrPropertyDefinition test = constraintDefinition(prop.getRequiredType(), constraints); assertThat(test.isAsOrMoreConstrainedThan(prop, context), is(true)); } protected void assertNotMoreConstrained( Name defnName, String... constraints ) throws Exception { NodeType constrainedType = validateTypeDefinition(); JcrPropertyDefinition prop = propertyDefinitionFor(constrainedType, defnName); JcrPropertyDefinition test = constraintDefinition(prop.getRequiredType(), constraints); assertThat(test.isAsOrMoreConstrainedThan(prop, context), is(false)); } protected JcrPropertyDefinition constraintDefinition( int type, String... constraints ) throws Exception { JcrNodeType nodeType = (JcrNodeType)validateTypeDefinition(); // Most of these don't matter ... NodeKey protoKey = new NodeKey("somethingElseEntirely"); Name name = context.getValueFactories().getNameFactory().create("dynTestProp"); int opv = OnParentVersionAction.COPY; boolean auto = false; boolean man = false; boolean prot = false; JcrValue[] defVals = null; boolean mult = false; boolean fts = false; boolean queryOrd = false; String[] queryOps = {}; return new JcrPropertyDefinition(context, nodeType, protoKey, name, opv, auto, man, prot, defVals, type, constraints, mult, fts, queryOrd, queryOps); } }