/*
* 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);
}
}