Merge branch 'issue/SLING-5720'
diff --git a/bnd.bnd b/bnd.bnd
new file mode 100644
index 0000000..86d4ddc
--- /dev/null
+++ b/bnd.bnd
@@ -0,0 +1,2 @@
+Import-Package: javax.jcr;resolution:=optional;version="[2.0,3)", \\
+ *
diff --git a/pom.xml b/pom.xml
index e05a2d7..0755db9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,6 +76,15 @@
<version>16.0.2</version>
<scope>compile</scope>
</dependency>
+
+ <!-- This will be an optional import, needed for applying conversion rules in the ObjectConverter -->
+ <dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ <version>2.0</version>
+ <scope>provided</scope>
+ </dependency>
+
<!-- Testing -->
<dependency>
<groupId>junit</groupId>
diff --git a/src/main/java/org/apache/sling/api/wrappers/impl/JcrRules.java b/src/main/java/org/apache/sling/api/wrappers/impl/JcrRules.java
new file mode 100644
index 0000000..bbb54ff
--- /dev/null
+++ b/src/main/java/org/apache/sling/api/wrappers/impl/JcrRules.java
@@ -0,0 +1,95 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.api.wrappers.impl;
+
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.util.Calendar;
+
+import javax.jcr.Binary;
+import javax.jcr.Value;
+
+import org.osgi.util.converter.ConverterBuilder;
+import org.osgi.util.converter.ConverterFunction;
+import org.osgi.util.converter.TypeRule;
+
+public final class JcrRules {
+
+ private JcrRules(){}
+
+ static void addJcrRules(ConverterBuilder converterBuilder) {
+ converterBuilder.rule(new TypeRule<Value, String>(Value.class, String.class, value -> {
+ try {
+ return value.getString();
+ } catch (Exception e) {
+ return (String) ConverterFunction.CANNOT_HANDLE;
+ }
+ }));
+ converterBuilder.rule(new TypeRule<Value, InputStream>(Value.class, InputStream.class, value -> {
+ try {
+ return value.getStream();
+ } catch (Exception e) {
+ return (InputStream) ConverterFunction.CANNOT_HANDLE;
+ }
+ }));
+ converterBuilder.rule(new TypeRule<Value, Binary>(Value.class, Binary.class, value -> {
+ try {
+ return value.getBinary();
+ } catch (Exception e) {
+ return (Binary) ConverterFunction.CANNOT_HANDLE;
+ }
+ }));
+ converterBuilder.rule(new TypeRule<Value, Long>(Value.class, Long.class, value -> {
+ try {
+ return value.getLong();
+ } catch (Exception e) {
+ return (Long) ConverterFunction.CANNOT_HANDLE;
+ }
+ }));
+ converterBuilder.rule(new TypeRule<Value, Double>(Value.class, Double.class, value -> {
+ try {
+ return value.getDouble();
+ } catch (Exception e) {
+ return (Double) ConverterFunction.CANNOT_HANDLE;
+ }
+ }));
+ converterBuilder.rule(new TypeRule<Value, BigDecimal>(Value.class, BigDecimal.class, value -> {
+ try {
+ return value.getDecimal();
+ } catch (Exception e) {
+ return (BigDecimal) ConverterFunction.CANNOT_HANDLE;
+ }
+ }));
+ converterBuilder.rule(new TypeRule<Value, Calendar>(Value.class, Calendar.class, value -> {
+ try {
+ return value.getDate();
+ } catch (Exception e) {
+ return (Calendar) ConverterFunction.CANNOT_HANDLE;
+ }
+ }));
+ converterBuilder.rule(new TypeRule<Value, Boolean>(Value.class, Boolean.class, value -> {
+ try {
+ return value.getBoolean();
+ } catch (Exception e) {
+ return (Boolean) ConverterFunction.CANNOT_HANDLE;
+ }
+ }));
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/api/wrappers/impl/ObjectConverter.java b/src/main/java/org/apache/sling/api/wrappers/impl/ObjectConverter.java
index 9df344c..edd8982 100644
--- a/src/main/java/org/apache/sling/api/wrappers/impl/ObjectConverter.java
+++ b/src/main/java/org/apache/sling/api/wrappers/impl/ObjectConverter.java
@@ -27,6 +27,7 @@
import org.osgi.util.converter.ConversionException;
import org.osgi.util.converter.Converter;
+import org.osgi.util.converter.ConverterBuilder;
import org.osgi.util.converter.Converters;
import org.osgi.util.converter.TypeRule;
@@ -39,7 +40,7 @@
private static final Converter CONVERTER;
static {
- CONVERTER = Converters.newConverterBuilder()
+ ConverterBuilder converterBuilder = Converters.newConverterBuilder()
.rule(new TypeRule<String, Calendar>(String.class, Calendar.class,
ObjectConverter::toCalendar))
.rule(new TypeRule<Date, Calendar>(Date.class, Calendar.class,
@@ -52,8 +53,13 @@
ObjectConverter::toDate))
.rule(new TypeRule<>(Calendar.class, ZonedDateTime.class, ObjectConverter::toZonedDateTime))
.rule(new TypeRule<ZonedDateTime, Calendar>(ZonedDateTime.class, Calendar.class, ObjectConverter::toCalendar))
- .rule(new TypeRule<ZonedDateTime, String>(ZonedDateTime.class, String.class, ObjectConverter::toString))
- .build();
+ .rule(new TypeRule<ZonedDateTime, String>(ZonedDateTime.class, String.class, ObjectConverter::toString));
+ try {
+ JcrRules.addJcrRules(converterBuilder);
+ } catch (NoClassDefFoundError e) {
+ // do nothing if the JCR API is not present
+ }
+ CONVERTER = converterBuilder.build();
}
}
diff --git a/src/test/java/org/apache/sling/api/wrappers/impl/ObjectConverterTest.java b/src/test/java/org/apache/sling/api/wrappers/impl/ObjectConverterTest.java
index 7eab819..81f42a0 100644
--- a/src/test/java/org/apache/sling/api/wrappers/impl/ObjectConverterTest.java
+++ b/src/test/java/org/apache/sling/api/wrappers/impl/ObjectConverterTest.java
@@ -18,17 +18,25 @@
*/
package org.apache.sling.api.wrappers.impl;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertNull;
-
+import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
+import javax.jcr.Binary;
+import javax.jcr.Value;
+
import org.junit.Test;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
public class ObjectConverterTest {
private static final String STRING_1 = "item1";
@@ -240,5 +248,65 @@
assertArrayEquals(new byte[0], ObjectConverter.convert(new byte[0], byte[].class));
assertNull(ObjectConverter.convert(null, byte[].class));
}
-
+
+ @Test
+ public void testJcrStringValue() throws Exception {
+ Value stringValue = mock(Value.class);
+ when(stringValue.getString()).thenReturn("42");
+ when(stringValue.getLong()).thenReturn(42L);
+ when(stringValue.getDouble()).thenReturn(42.0);
+ BigDecimal bigDecimal = new BigDecimal(42);
+ when(stringValue.getDecimal()).thenReturn(bigDecimal);
+ assertEquals("42", ObjectConverter.convert(stringValue, String.class));
+ assertEquals(42L, (long) ObjectConverter.convert(stringValue, Long.class));
+ assertEquals(42.0, ObjectConverter.convert(stringValue, Double.class), 0);
+ assertEquals(bigDecimal, ObjectConverter.convert(stringValue, BigDecimal.class));
+ }
+
+ @Test
+ public void testJcrStreamValue() throws Exception {
+ Value streamValue = mock(Value.class);
+ InputStream stream = mock(InputStream.class);
+ when(streamValue.getStream()).thenReturn(stream);
+ assertEquals(stream, ObjectConverter.convert(streamValue, InputStream.class));
+ }
+
+ @Test
+ public void testJcrBinaryValue() throws Exception {
+ Value binaryValue = mock(Value.class);
+ Binary binary = mock(Binary.class);
+ when(binaryValue.getBinary()).thenReturn(binary);
+ assertEquals(binary, ObjectConverter.convert(binaryValue, Binary.class));
+ }
+
+ @Test
+ public void testJcrNumericValue() throws Exception {
+ Value numericValue = mock(Value.class);
+ when(numericValue.getLong()).thenReturn(42L);
+ when(numericValue.getString()).thenReturn("42");
+ when(numericValue.getDouble()).thenReturn(42.0);
+ BigDecimal bigDecimal = new BigDecimal(42);
+ when(numericValue.getDecimal()).thenReturn(bigDecimal);
+ assertEquals(42L, (long) ObjectConverter.convert(numericValue, Long.class));
+ assertEquals("42", ObjectConverter.convert(numericValue, String.class));
+ assertEquals(42.0, ObjectConverter.convert(numericValue, Double.class), 0);
+ assertEquals(bigDecimal, ObjectConverter.convert(numericValue, BigDecimal.class));
+ }
+
+ @Test
+ public void testJcrDateValue() throws Exception {
+ Value dateValue = mock(Value.class);
+ Calendar calendar = Calendar.getInstance();
+ when(dateValue.getDate()).thenReturn(calendar);
+ assertEquals(calendar, ObjectConverter.convert(dateValue, Calendar.class));
+ }
+
+ @Test
+ public void testBooleanValue() throws Exception {
+ Value value = mock(Value.class);
+ when(value.getBoolean()).thenReturn(true);
+ when(value.getString()).thenReturn("true");
+ assertTrue(ObjectConverter.convert(value, Boolean.class));
+ assertEquals("true", ObjectConverter.convert(value, String.class));
+ }
}