blob: 9d3cce88faf2af6e38c7d5c458860c1f9d801e4f [file] [log] [blame]
/*
* 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.sling.jcr.resource.internal;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.util.ISO9075;
import org.apache.jackrabbit.util.Text;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
import org.apache.sling.jcr.resource.JcrPropertyMap;
public class JcrPropertyMapTest extends RepositoryTestBase {
private static final String PROP_NAME = "prop_name";
private static final String PROP_NAME_NIL = "prop_name_nil";
private String rootPath;
private Node rootNode;
@Override
protected void setUp() throws Exception {
super.setUp();
rootPath = "/test" + System.currentTimeMillis();
rootNode = getSession().getRootNode().addNode(rootPath.substring(1),
"nt:unstructured");
session.save();
}
@Override
protected void tearDown() throws Exception {
if (rootNode != null) {
rootNode.remove();
session.save();
}
super.tearDown();
}
public void testJCRType() throws Exception {
this.rootNode.getSession().refresh(false);
testValue(rootNode, "A String");
testValue(rootNode, Calendar.getInstance());
testValue(rootNode, 5L);
testValue(rootNode, 1.4D);
testValue(rootNode, true);
testValue(rootNode, BigDecimal.TEN);
}
public void testTypeByClass() throws Exception {
this.rootNode.getSession().refresh(false);
testValue(rootNode, "A String Value", String.class);
testValue(rootNode, 1l, Byte.class);
testValue(rootNode, 1l, Short.class);
testValue(rootNode, 1l, Integer.class);
testValue(rootNode, 1l, Long.class);
testValue(rootNode, 1.0d, Float.class);
testValue(rootNode, 1.0d, Double.class);
testValue(rootNode, 1.0d, BigDecimal.class);
Calendar cal = Calendar.getInstance();
testValue(rootNode, cal, Calendar.class);
testValue(rootNode, cal, Date.class);
testValue(rootNode, cal, Long.class);
testValue(rootNode, BigDecimal.TEN, BigDecimal.class);
}
public void testTypeByDefaultValue() throws Exception {
this.rootNode.getSession().refresh(false);
testValue(rootNode, "A String Value", "default");
testValue(rootNode, 1l, (byte) 10);
testValue(rootNode, 1l, (short) 10);
testValue(rootNode, 1l, 10);
testValue(rootNode, 1l, 10l);
testValue(rootNode, 1.0d, 10.0f);
testValue(rootNode, 1.0d, 10.0d);
testValue(rootNode, 1.0d, new BigDecimal("1.0"));
testValue(rootNode, BigDecimal.TEN, 10.0f);
testValue(rootNode, BigDecimal.TEN, 10.0d);
testValue(rootNode, BigDecimal.TEN, BigDecimal.TEN);
long refTime = 1000l;
Date refDate = new Date(refTime);
Calendar refCal = Calendar.getInstance();
refCal.setTimeInMillis(refTime);
Calendar cal = Calendar.getInstance();
testValue(rootNode, cal, refCal);
testValue(rootNode, cal, refDate);
testValue(rootNode, cal, refTime);
testValue(rootNode, BigDecimal.TEN, BigDecimal.ONE);
}
public void testDefaultValue() throws Exception {
this.rootNode.getSession().refresh(false);
testDefaultValue(rootNode, "default");
testDefaultValue(rootNode, (byte) 10);
testDefaultValue(rootNode, (short) 10);
testDefaultValue(rootNode, 10);
testDefaultValue(rootNode, 10l);
testDefaultValue(rootNode, 10.0f);
testDefaultValue(rootNode, 10.0d);
testDefaultValue(rootNode, new BigDecimal("50.50"));
long refTime = 1000l;
Date refDate = new Date(refTime);
Calendar refCal = Calendar.getInstance();
refCal.setTimeInMillis(refTime);
testDefaultValue(rootNode, refCal);
testDefaultValue(rootNode, refDate);
testDefaultValue(rootNode, refTime);
testDefaultValue(rootNode, BigDecimal.TEN);
}
public void testProperty() throws Exception {
this.rootNode.getSession().refresh(false);
ValueMap map = createProperty(rootNode, "Sample Value For Prop");
Property prop = rootNode.getProperty(PROP_NAME);
// explicit type
Property result = map.get(PROP_NAME, Property.class);
assertTrue(prop.isSame(result));
// type by default value
Property defaultValue = rootNode.getProperty("jcr:primaryType");
result = map.get(PROP_NAME, defaultValue);
assertTrue(prop.isSame(result));
// default value
result = map.get(PROP_NAME_NIL, defaultValue);
assertSame(defaultValue, result);
}
public void testInputStream() throws Exception {
this.rootNode.getSession().refresh(false);
InputStream instream = new ByteArrayInputStream("this too shall pass".getBytes());
ValueFactory valueFactory = rootNode.getSession().getValueFactory();
rootNode.setProperty("bin", valueFactory.createBinary(instream));
rootNode.getSession().save();
ValueMap map = new JcrPropertyMap(rootNode);
instream = map.get("bin", InputStream.class);
assertNotNull(instream);
String read = IOUtils.toString(instream);
assertEquals("Stream read successfully", "this too shall pass", read);
instream = map.get("bin", InputStream.class);
assertNotNull(instream);
read = IOUtils.toString(instream);
assertEquals("Stream read successfully a second time", "this too shall pass", read);
}
// ---------- internal
private void testValue(Node node, Object value, Object defaultValue) throws RepositoryException {
ValueMap map = createProperty(rootNode, value);
assertValueType(value, map.get(PROP_NAME, defaultValue), defaultValue.getClass());
}
private void testDefaultValue(Node node, Object defaultValue) {
JcrPropertyMap map = createPropertyMap(rootNode);
assertSame(defaultValue, map.get(PROP_NAME_NIL, defaultValue));
}
private void testValue(Node node, Object value, Class<?> type) throws RepositoryException {
ValueMap map = createProperty(rootNode, value);
assertValueType(value, map.get(PROP_NAME, type), type);
}
private void assertValueType(Object value, Object result, Class<?> type) {
assertTrue(type.isInstance(result));
if (value instanceof Long && result instanceof Number) {
assertEquals(((Number) value).longValue(), ((Number) result).longValue());
} else if (value instanceof Double && result instanceof Number) {
assertEquals(((Number) value).doubleValue(), ((Number) result).doubleValue());
} else if (value instanceof BigDecimal && result instanceof Number) {
assertEquals(((BigDecimal) value).doubleValue(), ((Number) result).doubleValue());
} else if (value instanceof Calendar) {
long resultTime;
if (result instanceof Date) {
resultTime = ((Date) result).getTime();
} else if (result instanceof Calendar) {
resultTime = ((Calendar) result).getTimeInMillis();
} else if (result instanceof Number) {
resultTime = ((Number) result).longValue();
} else {
fail("unexpected result type for Calendar: " + type);
return;
}
assertEquals(((Calendar) value).getTimeInMillis(), resultTime);
} else {
assertEquals(value, result);
}
}
protected JcrPropertyMap createPropertyMap(final Node node) {
return new JcrPropertyMap(node);
}
private void testValue(Node node, Object value) throws RepositoryException {
ValueMap map = createProperty(node, value);
assertEquals(value, map.get(PROP_NAME));
}
private ValueMap createProperty(Node node, Object value)
throws RepositoryException {
if (node.hasProperty(PROP_NAME)) {
node.getProperty(PROP_NAME).remove();
}
Value jcrValue;
ValueFactory fac = session.getValueFactory();
if (value instanceof String) {
jcrValue = fac.createValue((String) value);
} else if (value instanceof Calendar) {
jcrValue = fac.createValue((Calendar) value);
} else if (value instanceof Date) {
Calendar cal = Calendar.getInstance();
cal.setTime((Date) value);
jcrValue = fac.createValue(cal);
} else if (value instanceof Boolean) {
jcrValue = fac.createValue(((Boolean) value).booleanValue());
} else if (value instanceof Double) {
jcrValue = fac.createValue(((Double) value).doubleValue());
} else if (value instanceof Long) {
jcrValue = fac.createValue(((Long) value).longValue());
} else if (value instanceof BigDecimal) {
jcrValue = fac.createValue((BigDecimal) value);
} else {
fail("Cannot create JCR value from " + value);
return null;
}
node.setProperty(PROP_NAME, jcrValue);
node.getSession().save();
return createPropertyMap(node);
}
private static final String TEST_PATH = "a<a";
private static final String VALUE = "value";
private static final String VALUE1 = "value";
private static final String VALUE2 = "value";
private static final String VALUE3 = "my title";
private static final String PROP1 = "-prop";
private static final String PROP2 = "1prop";
private static final String PROP3 = "jcr:title";
private static final String PROP4 = ":prop";
public void testNames() throws Exception {
this.rootNode.getSession().refresh(false);
this.rootNode.setProperty(Text.escapeIllegalJcrChars(TEST_PATH), VALUE);
this.rootNode.setProperty(PROP1, VALUE1);
this.rootNode.setProperty(PROP2, VALUE2);
this.rootNode.setProperty(PROP3, VALUE3);
final ValueMap vm = this.createPropertyMap(this.rootNode);
assertEquals(VALUE, vm.get(TEST_PATH));
assertEquals(VALUE1, vm.get(PROP1));
assertEquals(VALUE2, vm.get(PROP2));
assertEquals(VALUE3, vm.get(PROP3));
vm.get(PROP4);
}
public void testColon() throws Exception {
this.rootNode.getSession().refresh(false);
final ValueMap vm = this.createPropertyMap(this.rootNode);
assertNull(vm.get(":prop"));
assertNull(vm.get("prop:"));
assertNull(vm.get("jcr:title"));
assertNull(vm.get("unknown:prefix"));
}
public void testIerators() throws Exception {
this.rootNode.getSession().refresh(false);
this.rootNode.setProperty(Text.escapeIllegalJcrChars(TEST_PATH), VALUE);
this.rootNode.setProperty(PROP1, VALUE1);
this.rootNode.setProperty(PROP2, VALUE2);
final ValueMap vm = this.createPropertyMap(this.rootNode);
assertTrue(vm.containsKey(TEST_PATH));
search(vm.keySet().iterator(), TEST_PATH);
search(vm.keySet().iterator(), PROP1);
search(vm.keySet().iterator(), PROP2);
search(vm.values().iterator(), VALUE);
search(vm.values().iterator(), VALUE1);
search(vm.values().iterator(), VALUE2);
}
public void testContainsKeyEmpty() {
final JcrPropertyMap map = createPropertyMap(rootNode);
assertFalse(map.containsKey(""));
assertNull(map.get(""));
}
public void testNamesOld() throws Exception {
this.rootNode.getSession().refresh(false);
this.rootNode.setProperty(ISO9075.encodePath(TEST_PATH), VALUE);
final ValueMap vm = this.createPropertyMap(this.rootNode);
assertEquals(VALUE, vm.get(TEST_PATH));
}
public void testIeratorsOld() throws Exception {
this.rootNode.getSession().refresh(false);
this.rootNode.setProperty(ISO9075.encodePath(TEST_PATH), VALUE);
final ValueMap vm = this.createPropertyMap(this.rootNode);
assertTrue(vm.containsKey(TEST_PATH));
search(vm.keySet().iterator(), TEST_PATH);
search(vm.values().iterator(), VALUE);
}
public void testDotSlash() throws Exception {
this.rootNode.getSession().refresh(false);
final String prop = "myProp";
final String value = "value";
this.rootNode.setProperty(prop, value);
final ValueMap vm = this.createPropertyMap(this.rootNode);
assertEquals(value, vm.get(prop));
assertEquals(value, vm.get("./" + prop));
assertTrue(vm.containsKey("./" + prop));
}
protected void search(Iterator<?> i, Object value) {
boolean found = false;
while ( !found && i.hasNext() ) {
final Object current = i.next();
found = current.equals(value);
}
if ( !found ) {
fail("Value " + value + " is not found in iterator.");
}
}
}