/* * 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.NotExecutableException; import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.ValueFormatException; import javax.jcr.Value; import java.io.IOException; import java.io.BufferedInputStream; /** * <code>StringPropertyTest</code> tests a String property against the * conversions to other Properties (except Name and Path property). If no String * property is found or only a multivalue String property with an empty array, a * NotExecutableException is thrown on setUp. More precisely, the tests are: * <p> * - Value.getString() should return a string equals to Property.getString(), * and in case of a multivalue property the failure of Property.getString() is * checked. * <p> * - Value.getBoolean() Conversion to Boolean property. * <p> * - Value.getDate() Conversion to Date property is only valid when the String * follows the required Date pattern (6.2.5.1 of jsr170 specification). * <p> * - Value.getDouble() Conversion to Double are only valid when the String * follows the correct patterns as required by the according Java classes. * <p> * - Value.getLong() Conversion to Double are only valid when the String follows * the correct patterns as required by the according Java classes. * <p> * - Value.getStream() Conversion to a Binary property follows the rules of * Value.getStream() as explained in chapter 6.2.7 of the jsr170 specification. * The required encoding is utf-8. * <p> * - Property.getNode() Conversion to a Reference property is tested with * Property.getNode. The String should match the UUID pattern but this doesn't * guarantee to be a reference (which especially requires integrity). * <p> * - Property.getLength() . * <p> * - Property.getLengths() . * <p> * - Property.getType() is compared to Value.getType() . * */ public class StringPropertyTest extends AbstractPropertyTest { /** * Returns {@link javax.jcr.PropertyType#STRING}. * * @return {@link javax.jcr.PropertyType#STRING}. */ protected int getPropertyType() { return PropertyType.STRING; } /** * Returns "does not matter" (<code>null</code>). * @return <code>null</code>. */ protected Boolean getPropertyIsMultivalued() { return null; } /** * Tests that Property.getString() delivers a string equal to the string * received with Value.getString(). */ public void testValue() throws RepositoryException { if (multiple) { try { prop.getString(); fail("Property.getString() called on a multivalue property " + "should throw a ValueFormatException."); } catch (ValueFormatException vfe) { // ok } } else { assertEquals("Value.getString() and Property.getString() return different values.", prop.getValue().getString(), prop.getString()); } } /** * Tests conversion from String type to Boolean type. */ public void testGetBoolean() throws RepositoryException { Value val = PropertyUtil.getValue(prop); String str = val.getString(); boolean bool = val.getBoolean(); assertEquals("Wrong conversion from String to Boolean.", new Boolean(bool), Boolean.valueOf(str)); } /** * Tests conversion from String type to Date type. */ public void testGetDate() throws RepositoryException { Value val = PropertyUtil.getValue(prop); if (PropertyUtil.isDateFormat(val.getString())) { val.getDate(); } else { try { val.getDate(); fail("Conversion from a malformed String to a Date " + "should throw a ValueFormatException."); } catch (ValueFormatException vfe) { // ok } } } /** * Tests conversion from String type to Double type. */ public void testGetDouble() throws RepositoryException { Value val = PropertyUtil.getValue(prop); String str = val.getString(); // double try { Double.parseDouble(str); double d = val.getDouble(); assertEquals("Wrong conversion from String to Double.", new Double(d), Double.valueOf(str)); } catch (NumberFormatException nfe) { try { val.getDouble(); fail("Conversion from malformed String to Double should throw ValueFormatException."); } catch (ValueFormatException vfe) { // ok } } } /** * Tests conversion from String type to Long type. */ public void testGetLong() throws RepositoryException { Value val = PropertyUtil.getValue(prop); String str = val.getString(); try { Long.parseLong(str); long l = val.getLong(); assertEquals("Wrong conversion from String to Long.", new Long(l), Long.valueOf(str)); } catch (NumberFormatException nfe) { try { val.getLong(); fail("Conversion from malformed String to Long " + "should throw ValueFormatException."); } catch (ValueFormatException vfe) { // ok } } } /** * Tests conversion from String type to Binary type. */ public void testGetStream() throws RepositoryException, IOException { Value val = PropertyUtil.getValue(prop); BufferedInputStream in = new BufferedInputStream(val.getStream()); Value otherVal = PropertyUtil.getValue(prop); byte[] utf8bytes = otherVal.getString().getBytes(UTF8); // compare the bytearray with the bytes received from a Stream created with this String int i = 0; byte b[] = new byte[1]; while (in.read(b) != -1) { assertEquals("String as a Stream is not utf-8 encoded", utf8bytes[i], b[0]); i++; } try { val.getString(); } catch (IllegalStateException ise) { fail("Non stream method call after stream method call " + "should not throw an IllegalStateException."); } try { otherVal.getStream(); } catch (IllegalStateException ise) { fail("Stream method call after a non stream method call " + "should not throw an IllegalStateException."); } in.close(); } /** * Tests conversion from String type to Reference or Path type. */ public void testGetNode() throws RepositoryException, NotExecutableException { if (!multiple) { // not testable since format of ID is implementation specific } else { try { prop.getNode(); fail("Property.getNode() called on a multivalue property " + "should throw a ValueFormatException."); } catch (ValueFormatException vfe) { // ok } } } /** * Tests conversion from String type to Reference or Path type. */ public void testGetProperty() throws RepositoryException, NotExecutableException { if (!multiple) { // not testable as a STRING may or may not be convertable to Path or Reference } else { try { prop.getProperty(); fail("Property.getNode() called on a multivalue property " + "should throw a ValueFormatException."); } catch (ValueFormatException vfe) { // ok } } } /** * Tests the Property.getLength() method. The length returned is either -1 * or it is the length of the string. */ public void testGetLength() throws RepositoryException { if (multiple) { try { prop.getLength(); fail("Property.getLength() called on a multivalue property " + "should throw a ValueFormatException."); } catch (ValueFormatException vfe) { // ok } } else { long length = prop.getLength(); if (length > -1) { assertEquals("Property.getLength() returns wrong number of bytes.", length, prop.getString().length()); } } } /** * Tests the Property.getLengths() method. The returned values are either -1 * or the lengths of the according strings. */ public void testGetLengths() throws RepositoryException { if (multiple) { Value[] values = prop.getValues(); long[] lengths = prop.getLengths(); for (int i = 0; i < lengths.length; i++) { if (lengths[i] > -1) { assertEquals("Property.getLengths() returns " + "wrong array of the lengths of a multivalue property.", values[i].getString().length(), lengths[i]); } } } else { try { prop.getLengths(); fail("Property.getLengths() called on a sinlge value property " + "should throw a ValueFormatException."); } catch (ValueFormatException vfe) { // ok } } } /** * Tests if Value.getType() returns the same as Property.getType() and also * tests that prop.getDefinition().getRequiredType() returns the same type * in case it is not of Undefined type. */ public void testGetType() throws RepositoryException { assertTrue("Value.getType() returns wrong type.", PropertyUtil.checkGetType(prop, PropertyType.STRING)); } }