You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by da...@apache.org on 2016/04/18 12:31:25 UTC

svn commit: r1739734 - in /felix/trunk/converter/src: main/java/org/apache/felix/converter/impl/ main/java/org/osgi/service/converter/ test/java/org/apache/felix/converter/impl/

Author: davidb
Date: Mon Apr 18 10:31:25 2016
New Revision: 1739734

URL: http://svn.apache.org/viewvc?rev=1739734&view=rev
Log:
Felix Converter Service - Support for some special cases and interface-based conversions.

Added:
    felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/ConverterService.java
    felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterServiceTest.java
Modified:
    felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/AdapterImpl.java
    felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.java
    felix/trunk/converter/src/main/java/org/osgi/service/converter/Converting.java
    felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterMapTest.java
    felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterTest.java

Modified: felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/AdapterImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/AdapterImpl.java?rev=1739734&r1=1739733&r2=1739734&view=diff
==============================================================================
--- felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/AdapterImpl.java (original)
+++ felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/AdapterImpl.java Mon Apr 18 10:31:25 2016
@@ -17,6 +17,8 @@
 package org.apache.felix.converter.impl;
 
 import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.Arrays;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
@@ -30,7 +32,7 @@ import org.osgi.service.converter.TypeRe
 
 public class AdapterImpl implements Adapter {
     private final Converter delegate;
-    private final Map<ClassPair, Function<Object, Object>> classRules =
+    private final Map<TypePair, Function<Object, Object>> classRules =
             new ConcurrentHashMap<>();
 
     public AdapterImpl(Converter converter) {
@@ -55,8 +57,8 @@ public class AdapterImpl implements Adap
         if (fromCls.equals(toCls))
             throw new IllegalArgumentException();
 
-        classRules.put(new ClassPair(fromCls, toCls), (Function<Object, Object>) toFun);
-        classRules.put(new ClassPair(toCls, fromCls), (Function<Object, Object>) fromFun);
+        classRules.put(new TypePair(fromCls, toCls), (Function<Object, Object>) toFun);
+        classRules.put(new TypePair(toCls, fromCls), (Function<Object, Object>) fromFun);
         return this;
     }
 
@@ -69,15 +71,15 @@ public class AdapterImpl implements Adap
 
     @Override
     public <F, T> Adapter rule(Function<F, T> toFun, Function<T, F> fromFun) {
-//        Type[] t = toFun.getClass().getGenericInterfaces();
-//
-//        TypeVariable<?>[] tp = toFun.getClass().getTypeParameters();
-//        System.out.println("*** " + Arrays.toString(tp));
-//
-//        TypeReference<Map<String, Adapter>> tr = new TypeReference<Map<String,Adapter>>(){};
-//        System.out.println("### " + tr);
-//        Type type = tr.getType();
-//        System.out.println("### " + type);
+        Type[] t = toFun.getClass().getGenericInterfaces();
+
+        TypeVariable<?>[] tp = toFun.getClass().getTypeParameters();
+        System.out.println("*** " + Arrays.toString(tp));
+
+        TypeReference<Map<String, Adapter>> tr = new TypeReference<Map<String,Adapter>>(){};
+        System.out.println("### " + tr);
+        Type type = tr.getType();
+        System.out.println("### " + type);
 
         // TODO Auto-generated method stub
         return this;
@@ -92,34 +94,28 @@ public class AdapterImpl implements Adap
             del = c;
         }
 
-        @SuppressWarnings("unchecked")
         @Override
-        public <T> T to(Class<T> cls) {
-            Function<Object, Object> f = classRules.get(new ClassPair(object.getClass(), cls));
-            if (f != null)
-                return (T) f.apply(object);
-
-            return del.to(cls);
-        }
+        public Object to(Type type) {
+            if (object != null) {
+                Function<Object, Object> f = classRules.get(new TypePair(object.getClass(), type));
+                if (f != null)
+                    return f.apply(object);
+            }
 
-        @Override
-        public <T> T to(TypeReference<T> ref) {
-            // TODO Auto-generated method stub
-            return null;
+            return del.to(type);
         }
 
         @Override
-        public Object to(Type type) {
-            // TODO Auto-generated method stub
-            return null;
+        public String toString() {
+            return to(String.class);
         }
     }
 
-    static class ClassPair {
-        private final Class<?> from;
-        private final Class<?> to;
+    static class TypePair {
+        private final Type from;
+        private final Type to;
 
-        ClassPair(Class<?> from, Class<?> to) {
+        TypePair(Type from, Type to) {
             this.from = from;
             this.to = to;
         }
@@ -133,10 +129,10 @@ public class AdapterImpl implements Adap
         public boolean equals(Object obj) {
             if (obj == this)
                 return true;
-            if (!(obj instanceof ClassPair))
+            if (!(obj instanceof TypePair))
                 return false;
 
-            ClassPair o = (ClassPair) obj;
+            TypePair o = (TypePair) obj;
             return Objects.equals(from, o.from) &&
                     Objects.equals(to, o.to);
         }

Added: felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/ConverterService.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/ConverterService.java?rev=1739734&view=auto
==============================================================================
--- felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/ConverterService.java (added)
+++ felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/ConverterService.java Mon Apr 18 10:31:25 2016
@@ -0,0 +1,57 @@
+/*
+ * 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.felix.converter.impl;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.ZonedDateTime;
+import java.util.UUID;
+import java.util.regex.Pattern;
+
+import org.osgi.service.converter.Adapter;
+import org.osgi.service.converter.Converter;
+import org.osgi.service.converter.Converting;
+
+public class ConverterService implements Converter {
+    private final Adapter adapter;
+
+    public ConverterService() {
+        Adapter a = new ConverterImpl().getAdapter();
+        a.rule(UUID.class, String.class, UUID::toString, UUID::fromString);
+        a.rule(Pattern.class, String.class, Pattern::toString, Pattern::compile);
+        a.rule(LocalDateTime.class, String.class, LocalDateTime::toString, LocalDateTime::parse);
+        a.rule(LocalDate.class, String.class, LocalDate::toString, LocalDate::parse);
+        a.rule(LocalTime.class, String.class, LocalTime::toString, LocalTime::parse);
+        a.rule(OffsetDateTime.class, String.class, OffsetDateTime::toString, OffsetDateTime::parse);
+        a.rule(OffsetTime.class, String.class, OffsetTime::toString, OffsetTime::parse);
+        a.rule(ZonedDateTime.class, String.class, ZonedDateTime::toString, ZonedDateTime::parse);
+        adapter = a;
+    }
+
+    @Override
+    public Converting convert(Object obj) {
+        return adapter.convert(obj);
+    }
+
+    @Override
+    public Adapter getAdapter() {
+        return adapter.getAdapter();
+    }
+}

Modified: felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.java?rev=1739734&r1=1739733&r2=1739734&view=diff
==============================================================================
--- felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.java (original)
+++ felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.java Mon Apr 18 10:31:25 2016
@@ -18,8 +18,10 @@ package org.apache.felix.converter.impl;
 
 import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Proxy;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -27,17 +29,18 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Dictionary;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.Map.Entry;
+import java.util.Set;
 
 import org.osgi.service.converter.Converter;
 import org.osgi.service.converter.Converting;
-import org.osgi.service.converter.TypeReference;
 
 public class ConvertingImpl implements Converting {
     private static final Map<Class<?>, Class<?>> boxedClasses;
@@ -72,13 +75,6 @@ public class ConvertingImpl implements C
         object = obj;
     }
 
-    @SuppressWarnings("unchecked")
-    @Override
-    public <T> T to(Class<T> cls) {
-        Type type = cls;
-        return (T) to(type);
-    }
-
     @Override
     public Object to(Type type) {
         Class<?> cls = null;
@@ -123,17 +119,9 @@ public class ConvertingImpl implements C
 
         // At this point we know that the target is a 'singular' type: not a map, collection or array
         if (object instanceof Collection) {
-            Collection<?> coll = (Collection<?>) object;
-            if (coll.size() == 0)
-                return null;
-            else
-                return converter.convert(coll.iterator().next()).to(cls);
+            return convertCollectionToSingleValue(cls);
         } else if (object instanceof Object[]) {
-            Object[] arr = (Object[]) object;
-            if (arr.length == 0)
-                return null;
-            else
-                return converter.convert(arr[0]).to(cls);
+            return convertArrayToSingleValue(cls);
         }
 
         Object res2 = tryStandardMethods(targetCls);
@@ -144,10 +132,47 @@ public class ConvertingImpl implements C
         }
     }
 
+    private Object convertArrayToSingleValue(Class<?> cls) {
+        Object[] arr = (Object[]) object;
+        if (arr.length == 0)
+            return null;
+        else
+            return converter.convert(arr[0]).to(cls);
+    }
+
+    private Object convertCollectionToSingleValue(Class<?> cls) {
+        Collection<?> coll = (Collection<?>) object;
+        if (coll.size() == 0)
+            return null;
+        else
+            return converter.convert(coll.iterator().next()).to(cls);
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     private Object convertToMapType(Class<?> targetCls, Type[] typeArguments) {
         if (Map.class.isAssignableFrom(targetCls))
             return convertToMap(targetCls, typeArguments);
-        return null;
+        else if (Dictionary.class.isAssignableFrom(targetCls))
+            return new Hashtable(convertToMap(Map.class, typeArguments));
+        return createProxy(targetCls);
+    }
+
+    @SuppressWarnings("rawtypes")
+    private Object createProxy(Class<?> targetCls) {
+        Map m = mapView(object);
+        return Proxy.newProxyInstance(targetCls.getClassLoader(), new Class[] {targetCls},
+            new InvocationHandler() {
+                @Override
+                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                    String propName = getAccessorPropertyName(method);
+                    if (propName == null)
+                        return null;
+
+                    Class<?> targetType = method.getReturnType();
+
+                    return converter.convert(m.get(propName)).to(targetType);
+                }
+            });
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
@@ -186,7 +211,70 @@ public class ConvertingImpl implements C
     private static Map<?,?> mapView(Object obj) {
         if (obj instanceof Map)
             return (Map<?,?>) obj;
-        return null;
+        else if (obj instanceof Dictionary)
+            return null; // TODO
+        else
+            return createMapFromBeanAccessors(obj);
+    }
+
+    @SuppressWarnings("rawtypes")
+    private static Map createMapFromBeanAccessors(Object obj) {
+        Set<String> invokedMethods = new HashSet<>();
+
+        Map result = new HashMap();
+        for (Method md : obj.getClass().getDeclaredMethods()) {
+            handleMethod(obj, md, invokedMethods, result);
+        }
+        for (Method md : obj.getClass().getMethods()) {
+            handleMethod(obj, md, invokedMethods, result);
+        }
+
+        return result;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private static void handleMethod(Object obj, Method md, Set<String> invokedMethods, Map res) {
+        String mn = md.getName();
+        if (invokedMethods.contains(mn))
+            return; // method with this name already invoked
+
+        String propName = getAccessorPropertyName(md);
+
+        try {
+            res.put(propName.toString(), md.invoke(obj));
+            invokedMethods.add(mn);
+        } catch (Exception e) {
+        }
+    }
+
+    private static String getAccessorPropertyName(Method md) {
+        if (md.getReturnType().equals(Void.class))
+            return null; // not an accessor
+
+        if (md.getParameterTypes().length > 0)
+            return null; // not an accessor
+
+        if (Object.class.equals(md.getDeclaringClass()))
+            return null; // do not use any methods on the Object class as a accessor
+
+        String mn = md.getName();
+        int prefix;
+        if (mn.startsWith("get"))
+            prefix = 3;
+        else if (mn.startsWith("is"))
+            prefix = 2;
+        else
+            return null; // not an accessor prefix
+
+        if (mn.length() <= prefix)
+            return null; // just 'get' or 'is': not an accessor
+        String propStr = mn.substring(prefix);
+        StringBuilder propName = new StringBuilder(propStr.length());
+        propName.append(Character.toLowerCase(propStr.charAt(0)));
+        if (propStr.length() > 1)
+            propName.append(propStr.substring(1));
+
+        return propName.toString();
     }
 
     private boolean isMapType(Class<?> targetCls) {
@@ -285,13 +373,9 @@ public class ConvertingImpl implements C
             return cls;
     }
 
-    @SuppressWarnings("unchecked")
-    @Override
-    public <T> T to(TypeReference<T> ref) {
-        return (T) to(ref.getType());
-    }
-
     private Object trySpecialCases(Class<?> targetCls) {
+        // TODO some of these can probably be implemented as an adapter
+
         if (Boolean.class.equals(targetCls)) {
             if (object instanceof Character) {
                 return ((Character) object).charValue() != (char) 0;

Modified: felix/trunk/converter/src/main/java/org/osgi/service/converter/Converting.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/src/main/java/org/osgi/service/converter/Converting.java?rev=1739734&r1=1739733&r2=1739734&view=diff
==============================================================================
--- felix/trunk/converter/src/main/java/org/osgi/service/converter/Converting.java (original)
+++ felix/trunk/converter/src/main/java/org/osgi/service/converter/Converting.java Mon Apr 18 10:31:25 2016
@@ -31,7 +31,11 @@ public interface Converting {
 	 * @param cls The class to convert to.
 	 * @return The converted object.
 	 */
-    <T> T to(Class<T> cls);
+    @SuppressWarnings("unchecked")
+    default <T> T to(Class<T> cls) {
+        Type type = cls;
+        return (T) to(type);
+    }
 
 	/**
 	 * Specify the target object type as a {@link TypeReference}. If the target
@@ -48,7 +52,10 @@ public interface Converting {
 	 * @param ref A type reference to the object being converted to.
 	 * @return The converted object.
 	 */
-	<T> T to(TypeReference<T> ref);
+	@SuppressWarnings("unchecked")
+    default <T> T to(TypeReference<T> ref) {
+        return (T) to(ref.getType());
+	}
 
 	/**
 	 * Specify the target object type as a Java Refelection Type object.

Modified: felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterMapTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterMapTest.java?rev=1739734&r1=1739733&r2=1739734&view=diff
==============================================================================
--- felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterMapTest.java (original)
+++ felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterMapTest.java Mon Apr 18 10:31:25 2016
@@ -16,7 +16,11 @@
  */
 package org.apache.felix.converter.impl;
 
+import java.math.BigInteger;
+import java.net.URL;
 import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashMap;
 import java.util.Map;
 
 import org.junit.After;
@@ -26,6 +30,10 @@ import org.osgi.service.converter.Conver
 import org.osgi.service.converter.TypeReference;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 
 public class ConverterMapTest {
     private Converter converter;
@@ -47,4 +55,107 @@ public class ConverterMapTest {
         assertEquals(1, m2.size());
         assertEquals(987654321L, (long) m2.get("42"));
     }
+
+    @Test
+    public void testConvertMapToDictionary() throws Exception {
+        Map<BigInteger, URL> m = new HashMap<>();
+        BigInteger bi = new BigInteger("123");
+        URL url = new URL("http://0.0.0.0:123");
+        m.put(bi, url);
+
+        @SuppressWarnings("unchecked")
+        Dictionary<BigInteger, URL> d = converter.convert(m).to(Dictionary.class);
+        assertEquals(1, d.size());
+        assertSame(bi, d.keys().nextElement());
+        assertSame(url, d.get(bi));
+    }
+
+    @Test
+    public void testInterfaceToMap() {
+        Object obj = new Object();
+        TestInterface impl = new TestInterface() {
+            @Override
+            public String getFoo() {
+                return "Chocolate!";
+            }
+
+            @Override
+            public int getbar() {
+                return 76543;
+            }
+
+            @SuppressWarnings("unused")
+            public long getL() {
+                return 1L;
+            }
+
+            @SuppressWarnings("unused")
+            public boolean isSomething() {
+                return true;
+            }
+
+            @SuppressWarnings("unused")
+            public Object getBlah() {
+                return obj;
+            }
+
+            @SuppressWarnings("unused")
+            private byte getByte() {
+                return (byte) 12;
+            }
+
+            @SuppressWarnings("unused")
+            public String getAlt(int arg) {
+                return "some value";
+            }
+        };
+
+        @SuppressWarnings("rawtypes")
+        Map m = converter.convert(impl).to(Map.class);
+        assertEquals(5, m.size());
+        assertEquals("Chocolate!", m.get("foo"));
+        assertEquals(76543, (int) m.get("bar"));
+        assertEquals(1L, (long) m.get("l"));
+        assertTrue((boolean) m.get("something"));
+        assertSame(obj, m.get("blah"));
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Test
+    public void testMapToInterface1() {
+        Map m = new HashMap<>();
+        m.put("foo", 12345);
+        m.put("bar", "999");
+        m.put("alt", "someval");
+
+        TestInterface ti = converter.convert(m).to(TestInterface.class);
+        assertEquals("12345", ti.getFoo());
+        assertEquals(999, ti.getbar());
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Test
+    public void testMapToInterface2() {
+        Map m = new HashMap<>();
+
+        TestInterface ti = converter.convert(m).to(TestInterface.class);
+        assertNull(ti.getFoo());
+        assertEquals(0, ti.getbar());
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void testCopyMap() {
+        Object obj = new Object();
+        Map m = new HashMap<>();
+        m.put("key", obj);
+        Map cm = converter.convert(m).to(Map.class);
+        assertNotSame(m, cm);
+        assertSame(m.get("key"), cm.get("key"));
+    }
+
+    interface TestInterface {
+        String getFoo();
+        int getbar();
+    }
 }

Added: felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterServiceTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterServiceTest.java?rev=1739734&view=auto
==============================================================================
--- felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterServiceTest.java (added)
+++ felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterServiceTest.java Mon Apr 18 10:31:25 2016
@@ -0,0 +1,122 @@
+/*
+ * 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.felix.converter.impl;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.ZonedDateTime;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ConverterServiceTest {
+    private ConverterService cs;
+
+    @Before
+    public void setUp() {
+        cs = new ConverterService();
+    }
+
+    @After
+    public void tearDown() {
+        cs = null;
+    }
+
+    @Test
+    public void testUUIDConversion() {
+        ConverterService cs = new ConverterService();
+        UUID uuid = UUID.randomUUID();
+        String s = cs.convert(uuid).to(String.class);
+        assertTrue("UUID should be something", s.length() > 0);
+        UUID uuid2 = cs.convert(s).to(UUID.class);
+        assertEquals(uuid, uuid2);
+    }
+
+    @Test
+    public void testPatternConversion() {
+        String p = "\\S*";
+        Pattern pattern = cs.convert(p).to(Pattern.class);
+        Matcher matcher = pattern.matcher("hi");
+        assertTrue(matcher.matches());
+        String p2 = cs.convert(pattern).to(String.class);
+        assertEquals(p, p2);
+    }
+
+    @Test
+    public void testLocalDateTime() {
+        LocalDateTime ldt = LocalDateTime.now();
+        String s = cs.convert(ldt).to(String.class);
+        assertTrue(s.length() > 0);
+        LocalDateTime ldt2 = cs.convert(s).to(LocalDateTime.class);
+        assertEquals(ldt, ldt2);
+    }
+
+    @Test
+    public void testLocalDate() {
+        LocalDate ld = LocalDate.now();
+        String s = cs.convert(ld).to(String.class);
+        assertTrue(s.length() > 0);
+        LocalDate ld2 = cs.convert(s).to(LocalDate.class);
+        assertEquals(ld, ld2);
+    }
+
+    @Test
+    public void testLocalTime() {
+        LocalTime lt = LocalTime.now();
+        String s = cs.convert(lt).to(String.class);
+        assertTrue(s.length() > 0);
+        LocalTime lt2 = cs.convert(s).to(LocalTime.class);
+        assertEquals(lt, lt2);
+    }
+
+    @Test
+    public void testOffsetDateTime() {
+        OffsetDateTime ot = OffsetDateTime.now();
+        String s = cs.convert(ot).to(String.class);
+        assertTrue(s.length() > 0);
+        OffsetDateTime ot2 = cs.convert(s).to(OffsetDateTime.class);
+        assertEquals(ot, ot2);
+    }
+
+    @Test
+    public void testOffsetTime() {
+        OffsetTime ot = OffsetTime.now();
+        String s = cs.convert(ot).to(String.class);
+        assertTrue(s.length() > 0);
+        OffsetTime ot2 = cs.convert(s).to(OffsetTime.class);
+        assertEquals(ot, ot2);
+    }
+
+    @Test
+    public void testZonedDateTime() {
+        ZonedDateTime zdt = ZonedDateTime.now();
+        String s = cs.convert(zdt).to(String.class);
+        assertTrue(s.length() > 0);
+        ZonedDateTime zdt2 = cs.convert(s).to(ZonedDateTime.class);
+        assertEquals(zdt, zdt2);
+    }
+}

Modified: felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterTest.java?rev=1739734&r1=1739733&r2=1739734&view=diff
==============================================================================
--- felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterTest.java (original)
+++ felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterTest.java Mon Apr 18 10:31:25 2016
@@ -33,7 +33,6 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.osgi.service.converter.Adapter;
-import org.osgi.service.converter.Converter;
 import org.osgi.service.converter.TypeReference;
 
 import static org.junit.Assert.assertArrayEquals;
@@ -44,11 +43,11 @@ import static org.junit.Assert.assertSam
 import static org.junit.Assert.assertTrue;
 
 public class ConverterTest {
-    private Converter converter;
+    private ConverterService converter;
 
     @Before
     public void setUp() {
-        converter = new ConverterImpl();
+        converter = new ConverterService();
     }
 
     @After
@@ -77,6 +76,7 @@ public class ConverterTest {
         assertTrue(converter.convert("TRUE").to(boolean.class));
         assertTrue(converter.convert('x').to(boolean.class));
         assertTrue(converter.convert(Long.MIN_VALUE).to(boolean.class));
+        assertTrue(converter.convert(72).to(boolean.class));
         assertFalse(converter.convert("false").to(boolean.class));
         assertFalse(converter.convert("bleh").to(boolean.class));
         assertFalse(converter.convert((char) 0).to(boolean.class));
@@ -86,6 +86,7 @@ public class ConverterTest {
         // Converstions to integer
         assertEquals(Integer.valueOf(123), converter.convert("123").to(int.class));
         assertEquals(1, (int) converter.convert(true).to(int.class));
+        assertEquals(0, (int) converter.convert(false).to(int.class));
 
         // Conversions to Class
         assertEquals(BigDecimal.class, converter.convert("java.math.BigDecimal").to(Class.class));