/* * 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 static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.List; import javax.jcr.Binary; import javax.jcr.ImportUUIDBehavior; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.Property; import javax.jcr.PropertyType; import javax.jcr.Value; import javax.jcr.ValueFormatException; import javax.jcr.nodetype.NodeTypeManager; import javax.jcr.nodetype.NodeTypeTemplate; import javax.jcr.nodetype.PropertyDefinition; import javax.jcr.nodetype.PropertyDefinitionTemplate; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.modeshape.jcr.api.value.DateTime; import org.modeshape.jcr.value.ValueFactory; public class JcrSingleValuePropertyTest extends MultiUseAbstractTest { private org.modeshape.jcr.api.Property prop; private byte[] binaryValue; private DateTime dateValue; private double doubleValue; private long longValue; private String stringValue; private boolean booleanValue; private String nameValue; private String pathValue; private ValueFactory<String> stringFactory; protected AbstractJcrNode cars; protected AbstractJcrNode altima; /** * Initialize the expensive activities, and in particular the RepositoryNodeTypeManager instance. * * @throws Exception */ @BeforeClass public static void beforeAll() throws Exception { MultiUseAbstractTest.beforeAll(); // Import the node types and the data ... registerNodeTypes("cars.cnd"); importContent("/", "io/cars-system-view-with-uuids.xml", ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW); // Now define a namespace we'll use in the tests ... session.getWorkspace().getNamespaceRegistry().registerNamespace("acme", "http://example.com"); NodeTypeManager mgr = session.getWorkspace().getNodeTypeManager(); // Define the node definition that will have all the different kinds of properties ... NodeTypeTemplate nodeType = mgr.createNodeTypeTemplate(); nodeType.setMixin(true); nodeType.setName("mixinWithAllPropTypes"); @SuppressWarnings( "unchecked" ) List<PropertyDefinitionTemplate> propDefns = nodeType.getPropertyDefinitionTemplates(); // Add a property for each type ... PropertyDefinitionTemplate binaryDefn = mgr.createPropertyDefinitionTemplate(); binaryDefn.setName("binaryProperty"); binaryDefn.setRequiredType(PropertyType.BINARY); propDefns.add(binaryDefn); PropertyDefinitionTemplate booleanDefn = mgr.createPropertyDefinitionTemplate(); booleanDefn.setName("booleanProperty"); booleanDefn.setRequiredType(PropertyType.BOOLEAN); propDefns.add(booleanDefn); PropertyDefinitionTemplate dateDefn = mgr.createPropertyDefinitionTemplate(); dateDefn.setName("dateProperty"); dateDefn.setRequiredType(PropertyType.DATE); propDefns.add(dateDefn); PropertyDefinitionTemplate doubleDefn = mgr.createPropertyDefinitionTemplate(); doubleDefn.setName("doubleProperty"); doubleDefn.setRequiredType(PropertyType.DOUBLE); propDefns.add(doubleDefn); PropertyDefinitionTemplate longDefn = mgr.createPropertyDefinitionTemplate(); longDefn.setName("longProperty"); longDefn.setRequiredType(PropertyType.LONG); propDefns.add(longDefn); PropertyDefinitionTemplate nameDefn = mgr.createPropertyDefinitionTemplate(); nameDefn.setName("nameProperty"); nameDefn.setRequiredType(PropertyType.NAME); propDefns.add(nameDefn); PropertyDefinitionTemplate pathDefn = mgr.createPropertyDefinitionTemplate(); pathDefn.setName("pathProperty"); pathDefn.setRequiredType(PropertyType.PATH); propDefns.add(pathDefn); PropertyDefinitionTemplate refDefn = mgr.createPropertyDefinitionTemplate(); refDefn.setName("referenceProperty"); refDefn.setRequiredType(PropertyType.REFERENCE); propDefns.add(refDefn); PropertyDefinitionTemplate stringDefn = mgr.createPropertyDefinitionTemplate(); stringDefn.setName("stringProperty"); stringDefn.setRequiredType(PropertyType.STRING); propDefns.add(stringDefn); PropertyDefinitionTemplate undefinedDefn = mgr.createPropertyDefinitionTemplate(); undefinedDefn.setName("undefinedProperty"); undefinedDefn.setRequiredType(PropertyType.UNDEFINED); propDefns.add(undefinedDefn); // Add the node type ... mgr.registerNodeType(nodeType, true); } @Override @Before public void beforeEach() throws Exception { super.beforeEach(); stringFactory = session.stringFactory(); binaryValue = "This is a binary value".getBytes(); dateValue = session.dateFactory().create(); doubleValue = 3.14159d; longValue = 100L; booleanValue = true; stringValue = "stringValue"; nameValue = "acme:SomeName"; pathValue = "/Cars/Hybrid/Toyota Highlander/acme:SomethingElse"; // Add the mixin to the 'Cars' node ... cars = session.getNode("/Cars"); cars.addMixin("mixinWithAllPropTypes"); altima = session.getNode("/Cars/Hybrid/Nissan Altima"); altima.addMixin("mix:referenceable"); // Set each property ... cars.setProperty("booleanProperty", booleanValue); cars.setProperty("dateProperty", dateValue.toCalendar()); cars.setProperty("doubleProperty", doubleValue); cars.setProperty("binaryProperty", new ByteArrayInputStream(binaryValue)); cars.setProperty("longProperty", longValue); cars.setProperty("referenceProperty", altima); cars.setProperty("stringProperty", stringValue); cars.setProperty("pathProperty", pathValue); cars.setProperty("nameProperty", nameValue); cars.setProperty("undefinedProperty", "100"); } @Test public void shouldIndicateHasSingleValue() throws Exception { prop = cars.getProperty("booleanProperty"); PropertyDefinition def = prop.getDefinition(); assertThat(def.isMultiple(), is(false)); } @Test public void shouldProvideBoolean() throws Exception { prop = cars.getProperty("booleanProperty"); assertThat(prop.getBoolean(), is(booleanValue)); assertThat(prop.getAs(Boolean.class), is(booleanValue)); assertThat(prop.getType(), is(PropertyType.BOOLEAN)); assertThat(prop.getString(), is(stringFactory.create(booleanValue))); assertThat(prop.getLength(), is((long)stringFactory.create(booleanValue).length())); checkValue(prop); } @Test public void shouldProvideDate() throws Exception { prop = cars.getProperty("dateProperty"); // see ModeShape-527 for reasons asserts are commented // assertThat(prop.getDate(), is(dateValue.toCalendar())); assertThat(prop.getLong(), is(dateValue.getMilliseconds())); // assertThat(prop.getString(), is(stringFactory.create(dateValue))); assertThat(prop.getType(), is(PropertyType.DATE)); // assertThat(prop.getLength(), is((long)stringFactory.create(dateValue).length())); assertThat(prop.getAs(DateTime.class), notNullValue()); checkValue(prop); } @Test public void shouldProvideNode() throws Exception { prop = cars.getProperty("referenceProperty"); assertThat(prop.getNode(), is((Node)altima)); assertThat(prop.getAs(Node.class), is((Node)altima)); NodeIterator nodeIterator = prop.getAs(NodeIterator.class); assertThat(nodeIterator.getSize(), is(1l)); assertThat(nodeIterator.nextNode(), is((Node)altima)); assertThat(prop.getType(), is(PropertyType.REFERENCE)); assertThat(prop.getString(), is(altima.getIdentifier())); assertThat(prop.getLength(), is((long) altima.getIdentifier().length())); checkValue(prop); } @Test public void shouldProvideDouble() throws Exception { prop = cars.getProperty("doubleProperty"); assertThat(prop.getDouble(), is(doubleValue)); assertThat(prop.getAs(Double.class), is(doubleValue)); assertThat(prop.getString(), is(stringFactory.create(doubleValue))); assertThat(prop.getType(), is(PropertyType.DOUBLE)); assertThat(prop.getLength(), is((long)stringFactory.create(doubleValue).length())); checkValue(prop); } @Test public void shouldProvideLong() throws Exception { prop = cars.getProperty("longProperty"); assertThat(prop.getLong(), is(longValue)); assertThat(prop.getAs(Long.class), is(longValue)); assertThat(prop.getString(), is(stringFactory.create(longValue))); assertThat(prop.getType(), is(PropertyType.LONG)); assertThat(prop.getLength(), is((long)stringFactory.create(longValue).length())); checkValue(prop); } @SuppressWarnings( "deprecation" ) @Test public void shouldProvideStream() throws Exception { prop = cars.getProperty("binaryProperty"); assertThat(prop.getType(), is(PropertyType.BINARY)); InputStream stream = prop.getStream(); try { assertThat(stream, notNullValue()); } finally { if (stream != null) { stream.close(); } } stream = prop.getAs(InputStream.class); try { assertThat(stream, notNullValue()); } finally { if (stream != null) { stream.close(); } } assertThat(prop.getString(), is(stringFactory.create(binaryValue))); assertThat(prop.getLength(), is((long)binaryValue.length)); // note this value!! checkValue(prop); } @Test public void shouldProvideBinary() throws Exception { prop = cars.getProperty("binaryProperty"); assertThat(prop.getType(), is(PropertyType.BINARY)); Binary binary = prop.getBinary(); InputStream stream = binary.getStream(); try { assertThat(stream, notNullValue()); } finally { if (stream != null) { stream.close(); } } assertThat(prop.getAs(Binary.class), notNullValue()); assertThat(prop.getAs(org.modeshape.jcr.api.Binary.class), notNullValue()); assertThat(prop.getString(), is(stringFactory.create(binaryValue))); assertThat(prop.getLength(), is((long)binaryValue.length)); // note this value!! assertThat(binary.getSize(), is((long)binaryValue.length)); // note this value!! checkValue(prop); } @Test public void shouldProvideString() throws Exception { prop = cars.getProperty("stringProperty"); assertThat(prop.getString(), is(stringValue)); assertThat(prop.getAs(String.class), is(stringValue)); assertThat(prop.getType(), is(PropertyType.STRING)); assertThat(prop.getLength(), is((long)stringValue.length())); checkValue(prop); } @Test public void shouldAllowNameValue() throws Exception { prop = cars.getProperty("nameProperty"); assertThat(prop.getType(), is(PropertyType.NAME)); assertThat(prop.getString(), is(nameValue)); assertThat(prop.getAs(String.class), is(nameValue)); assertThat(prop.getLength(), is((long)nameValue.length())); // Change the namespace registry ... session.setNamespacePrefix("acme2", "http://example.com"); assertThat(prop.getString(), is("acme2:SomeName")); checkValue(prop); } @Test public void shouldAllowPathValue() throws Exception { prop = cars.getProperty("pathProperty"); assertThat(prop.getType(), is(PropertyType.PATH)); assertThat(prop.getString(), is(pathValue)); assertThat(prop.getAs(String.class), is(pathValue)); // Change the namespace registry ... session.setNamespacePrefix("acme2", "http://example.com"); assertThat(prop.getString(), is("/Cars/Hybrid/Toyota Highlander/acme2:SomethingElse")); checkValue(prop); } public void checkValue( Property prop ) throws Exception { // Should provide a value and not multiple values ... Value val = prop.getValue(); assertThat(val, notNullValue()); assertThat(prop.getDefinition(), notNullValue()); // Should not allow multiple-value methods ... try { prop.getValues(); fail("Should not be able to call 'getValues()' on a single-value property"); } catch (ValueFormatException e) { // expected } try { prop.getLengths(); fail("Should not be able to call 'getValues()' on a single-value property"); } catch (ValueFormatException e) { // expected } } }