/* * 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; import org.apache.jackrabbit.test.AbstractJCRTest; import org.apache.jackrabbit.test.NotExecutableException; import javax.jcr.ItemNotFoundException; import javax.jcr.ItemVisitor; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.PropertyIterator; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.Value; import javax.jcr.ValueFormatException; import java.util.NoSuchElementException; /** * <code>PropertyReadMethodsTest</code>... * */ public class PropertyReadMethodsTest extends AbstractJCRTest { /** * Session to access the workspace */ private Session session; /** * A property of the root node */ private Property property; /** * Sets up the fixture for this test. */ protected void setUp() throws Exception { isReadOnly = true; super.setUp(); session = getHelper().getReadOnlySession(); testRootNode = session.getRootNode().getNode(testPath); PropertyIterator properties = testRootNode.getProperties(); try { property = properties.nextProperty(); } catch (NoSuchElementException e) { fail("Any node must have at least one property set: jcr:primaryType"); } } /** * Releases the session aquired in {@link #setUp()}. */ protected void tearDown() throws Exception { if (session != null) { session.logout(); session = null; } property = null; super.tearDown(); } // -----------< tests of methods inherited of Item >------------------------ /** * Tests if getPath() returns the correct path. */ public void testGetPath() throws NotExecutableException, RepositoryException { assertEquals("getPath returns wrong result", testRoot + "/" + property.getName(), property.getPath()); } /** * Tests if getName() returns same as last name returned by getPath() */ public void testGetName() throws RepositoryException { String path = property.getPath(); String name = path.substring(path.lastIndexOf("/") + 1); assertEquals("getName() must be the same as the last item in the path", name, property.getName()); } /** * Test if the ancestor at depth = n, where n is the depth of this * <code>Item</code>, returns this <code>Property</code> itself. * * @throws RepositoryException */ public void testGetAncestorOfItemDepth() throws RepositoryException { Property propertyAtDepth = (Property) property.getAncestor(property.getDepth()); assertTrue("The ancestor of depth = n, where n is the depth of this " + "Property must be the item itself.", property.isSame(propertyAtDepth)); } /** * Test if getting the ancestor of depth = n, where n is greater than depth * of this <code>Property</code>, throws an <code>ItemNotFoundException</code>. * * @throws RepositoryException */ public void testGetAncestorOfGreaterDepth() throws RepositoryException { try { int greaterDepth = property.getDepth() + 1; property.getAncestor(greaterDepth); fail("Getting ancestor of depth n, where n is greater than depth of" + "this Property must throw an ItemNotFoundException"); } catch (ItemNotFoundException e) { // success } } /** * Test if getting the ancestor of negative depth throws an * <code>ItemNotFoundException</code>. * * @throws RepositoryException */ public void testGetAncestorOfNegativeDepth() throws RepositoryException { try { property.getAncestor(-1); fail("Getting ancestor of depth < 0 must throw an ItemNotFoundException."); } catch (ItemNotFoundException e) { // success } } /** * Tests if getParent() returns parent node */ public void testGetParent() throws RepositoryException { assertTrue("getParent() of a property must return the parent node.", testRootNode.isSame(property.getParent())); } /** * Tests if depth of a property of depth of node + 1 */ public void testGetDepth() throws RepositoryException { assertEquals("getDepth() of a property of root must be 1", testRootNode.getDepth() + 1, property.getDepth()); } /** * Tests if getSession() is same as through which the Property was acquired */ public void testGetSession() throws RepositoryException { assertSame("getSession must return the Session through which " + "the Property was acquired.", property.getSession(), session); } /** * Tests if isMultiple() is consistent with PropertyDefinition.isMultiple(). */ public void testIsMultiple() throws RepositoryException { assertEquals("Property.isMultiple() must be consistent with PropertyDefinition.isMultiple()", property.isMultiple(), property.getDefinition().isMultiple()); } /** * Tests if isNode() returns false */ public void testIsNode() { assertFalse("isNode() must return false.", property.isNode()); } /** * Tests if isSame() returns true when retrieving a property through * different sessions */ public void testIsSame() throws RepositoryException { // access same property through different session Session otherSession = getHelper().getReadOnlySession(); try { Property otherProperty = otherSession.getRootNode().getNode(testPath).getProperty(property.getName()); assertTrue("isSame must return true for the same " + "property retrieved through different sessions.", property.isSame(otherProperty)); } finally { otherSession.logout(); } } /** * Tests if a Property calls the correct visit method on an {@link * ItemVisitor}. */ public void testAccept() throws RepositoryException { final Property p = property; ItemVisitor itemVisitor = new ItemVisitor() { public void visit(Property property) throws RepositoryException { assertTrue("Visited Property is not the same as the one returned by visit(Property).", p.isSame(property)); } public void visit(Node node) { fail("Wrong accept method executed."); } }; p.accept(itemVisitor); } /** * Tests that no null value property exists in a given node tree. */ public void testNoNullValue() throws RepositoryException { assertFalse("Single property with null value found.", PropertyUtil.nullValues(testRootNode)); } /** * Tests that all values of a multivalue property have the same property * type. */ public void testMultiValueType() throws RepositoryException, NotExecutableException { Property multiValProp = PropertyUtil.searchMultivalProp(testRootNode); if (multiValProp != null) { Value[] vals = multiValProp.getValues(); if (vals.length > 0) { int type = vals[0].getType(); for (int i = 1; i < vals.length; i++) { assertEquals("Multivalue property has values with different types.", type, vals[i].getType()); } } } else { throw new NotExecutableException(); } } /** * Tests failure of Property.getValue() method for a multivalue property. */ public void testGetValue() throws RepositoryException, NotExecutableException { Property multiValProp = PropertyUtil.searchMultivalProp(testRootNode); if (multiValProp != null) { try { multiValProp.getValue(); fail("Property.getValue() called on a multivalue property " + "should throw a ValueFormatException."); } catch (ValueFormatException vfe) { // ok } } else { throw new NotExecutableException(); } } /** * Tests failure of Property.getValues() method for a single value * property. */ public void testGetValues() throws RepositoryException, NotExecutableException { Property singleProp = PropertyUtil.searchSingleValuedProperty(testRootNode); if (singleProp == null) { throw new NotExecutableException("No single valued property found."); } try { singleProp.getValues(); fail("Property.getValues() called on a single property " + "should throw a ValueFormatException."); } catch (ValueFormatException vfe) { // ok } } /** * Tests if <code>Property.getValues()</code> returns an array that is a copy * of the stored values, so changes to it are not reflected in internal storage. */ public void testGetValueCopyStoredValues() throws NotExecutableException, RepositoryException { Property prop = PropertyUtil.searchMultivalProp(testRootNode); if (prop == null) { throw new NotExecutableException("No multivalued property found."); } // acquire the values of the property and change the zeroth value Value[] values = prop.getValues(); if (values.length == 0) { throw new NotExecutableException("No testable property found."); } values[0] = null; // re-acquire the values and check if nulled value still exists Value[] values2 = prop.getValues(); assertNotNull("Changes on the array returned by Property.getValues() must " + "not be reflected in the internal storage.", values2[0]); } /** * Tests if Property.getNode() fails with ValueFormatException for * multivalued properties. * * @throws RepositoryException * @throws NotExecutableException */ public void testGetNode() throws RepositoryException, NotExecutableException { Property prop = PropertyUtil.searchMultivalProp(testRootNode); if (prop == null) { throw new NotExecutableException("Test Property.getNode is throwing a " + "ValueFormaException not executable in case of a multivalued property."); } else { try { prop.getNode(); fail("Property.getNode should throw a ValueFormatException in case of " + "a multivalued property."); } catch (ValueFormatException vfe) { // ok } } } }