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 2017/01/23 02:41:12 UTC

svn commit: r1779874 - in /felix/trunk/converter/converter/src: main/java/org/apache/felix/converter/impl/ConvertingImpl.java test/java/org/apache/felix/converter/impl/ConverterTest.java test/java/org/apache/felix/converter/impl/MyDTO8.java

Author: davidb
Date: Mon Jan 23 02:41:12 2017
New Revision: 1779874

URL: http://svn.apache.org/viewvc?rev=1779874&view=rev
Log:
FELIX-5475 Implement sourceAsDTO() and targetAsDTO()

Patch applied on behalf of David Leangen with many thanks!

Added:
    felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/MyDTO8.java
Modified:
    felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.java
    felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/ConverterTest.java

Modified: felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.java?rev=1779874&r1=1779873&r2=1779874&view=diff
==============================================================================
--- felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.java (original)
+++ felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.java Mon Jan 23 02:41:12 2017
@@ -70,6 +70,10 @@ public class ConvertingImpl implements C
     private List<Object> keys = new ArrayList<>();
     private volatile Object root;
     private volatile boolean sourceAsJavaBean = false;
+    @SuppressWarnings( "unused" )
+    private volatile boolean targetAsJavaBean = false;
+    private volatile boolean sourceAsDTO = false;
+    private volatile boolean targetAsDTO = false;
 
     ConvertingImpl(InternalConverter c, Object obj) {
         converter = c;
@@ -84,13 +88,17 @@ public class ConvertingImpl implements C
 
     @Override
     public Converting sourceAsBean() {
+        // To avoid ambiguity, reset any instruction to sourceAsDTO
+        sourceAsDTO = false;
         sourceAsJavaBean = true;
         return this;
     }
 
     @Override
     public Converting sourceAsDTO() {
-        // TODO Implement
+        // To avoid ambiguity, reset any instruction to sourceAsJavaBean
+        sourceAsJavaBean = false;
+        sourceAsDTO = true;
         return this;
     }
 
@@ -102,13 +110,17 @@ public class ConvertingImpl implements C
 
     @Override
     public Converting targetAsBean() {
-        // TODO not yet implemented
+        // To avoid ambiguity, reset any instruction to targetAsDTO
+        targetAsDTO = false;
+        targetAsJavaBean = true;
         return this;
     }
 
     @Override
     public Converting targetAsDTO() {
-        // TODO Implement
+        // To avoid ambiguity, reset any instruction to targetAsJavaBean
+        targetAsJavaBean = false;
+        targetAsDTO = true;
         return this;
     }
 
@@ -142,6 +154,7 @@ public class ConvertingImpl implements C
         return this;
     }
 
+    @SuppressWarnings( "unchecked" )
     @Override
     public void setConverter(Converter c) {
         if (c instanceof InternalConverter)
@@ -190,6 +203,11 @@ public class ConvertingImpl implements C
 
         sourceClass = sourceAsClass != null ? sourceAsClass : object.getClass();
 
+        // Temporary - to remove next commit!!
+        // This is just to catch any old code that may still be using {source|target}As(DTO.class)
+        if(DTO.class.equals(sourceClass) || DTO.class.equals(targetAsClass))
+            throw new RuntimeException("To update!!");
+
         if (!isCopyRequiredType(targetAsClass) && targetAsClass.isAssignableFrom(sourceClass)) {
                 return object;
         }
@@ -202,7 +220,7 @@ public class ConvertingImpl implements C
             return convertToArray();
         } else if (Collection.class.isAssignableFrom(targetAsClass)) {
             return convertToCollection();
-        } else if (isDTOType(targetAsClass)) {
+        } else if (isDTOType(targetAsClass) || ((sourceAsDTO || targetAsDTO) && DTO.class.isAssignableFrom(targetActualClass))) {
             return convertToDTO();
         } else if (isMapType(targetAsClass)) {
             return convertToMapType();
@@ -292,16 +310,19 @@ public class ConvertingImpl implements C
     private <T> T convertToDTO() {
         Map m = mapView(object, sourceClass, converter);
 
+        Class<?> cls = targetAsClass;
+        if (targetAsDTO)
+            cls = targetActualClass;
         try {
             T dto = (T) targetActualClass.newInstance();
 
             for (Map.Entry entry : (Set<Map.Entry>) m.entrySet()) {
                 Field f = null;
                 try {
-                    f = targetAsClass.getDeclaredField(mangleName(entry.getKey().toString()));
+                    f = cls.getDeclaredField(mangleName(entry.getKey().toString()));
                 } catch (NoSuchFieldException e) {
                     try {
-                        f = targetAsClass.getField(mangleName(entry.getKey().toString()));
+                        f = cls.getField(mangleName(entry.getKey().toString()));
                     } catch (NoSuchFieldException e1) {
                         // There is not field with this name
                     }
@@ -309,7 +330,11 @@ public class ConvertingImpl implements C
 
                 if (f != null) {
                     Object val = entry.getValue();
-                    f.set(dto, converter.convert(val).to(f.getType()));
+                    if (sourceAsDTO && DTO.class.isAssignableFrom(f.getType()))
+                        val = converter.convert(val).sourceAsDTO().to(f.getType());
+                    else
+                        val = converter.convert(val).to(f.getType());
+                    f.set(dto, val);
                 }
             }
 
@@ -355,7 +380,11 @@ public class ConvertingImpl implements C
                     if (isCopyRequiredType(cls)) {
                         cls = getConstructableType(cls);
                     }
-                    value = converter.convert(value).key(ka).to(cls);
+                    if (sourceAsDTO && DTO.class.isAssignableFrom(cls))
+                        // sourceAsDTO or sourceAsClass???
+                        value = converter.convert(value).key(ka).sourceAsDTO().to(cls);
+                    else
+                        value = converter.convert(value).key(ka).to(cls);
                 }
             }
             instance.put(key, value);
@@ -839,11 +868,11 @@ public class ConvertingImpl implements C
     }
 
     private Map<?,?> mapView(Object obj, Class<?> sourceCls, InternalConverter converter) {
-        if (Map.class.isAssignableFrom(sourceCls))
+        if (Map.class.isAssignableFrom(sourceCls) || (DTO.class.isAssignableFrom(sourceCls) && obj instanceof Map))
             return (Map<?,?>) obj;
         else if (Dictionary.class.isAssignableFrom(sourceCls))
             return null; // TODO
-        else if (isDTOType(sourceCls))
+        else if (isDTOType(sourceCls) || sourceAsDTO)
             return createMapFromDTO(obj, converter);
         else {
             if (sourceAsJavaBean) {
@@ -856,6 +885,8 @@ public class ConvertingImpl implements C
     }
 
     private static boolean isCopyRequiredType(Class<?> cls) {
+        if (cls.isEnum())
+            return false;
         return Map.class.isAssignableFrom(cls) ||
                 Collection.class.isAssignableFrom(cls) ||
                 DTO.class.isAssignableFrom(cls) ||

Modified: felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/ConverterTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/ConverterTest.java?rev=1779874&r1=1779873&r2=1779874&view=diff
==============================================================================
--- felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/ConverterTest.java (original)
+++ felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/ConverterTest.java Mon Jan 23 02:41:12 2017
@@ -52,6 +52,7 @@ import org.apache.felix.converter.impl.M
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.osgi.dto.DTO;
 import org.osgi.util.converter.ConversionException;
 import org.osgi.util.converter.Converter;
 import org.osgi.util.converter.ConverterBuilder;
@@ -462,6 +463,72 @@ public class ConverterTest {
         assertEquals(Alpha.A, e.get("alpha"));
     }
 
+    @Test
+    public void testDTO2Map2() {
+        MyEmbeddedDTO embedded = new MyEmbeddedDTO();
+        embedded.marco = "hohoho";
+        embedded.polo = Long.MAX_VALUE;
+        embedded.alpha = Alpha.A;
+
+        MyDTO dto = new MyDTO();
+        dto.ping = "lalala";
+        dto.pong = Long.MIN_VALUE;
+        dto.count = Count.ONE;
+        dto.embedded = embedded;
+
+        @SuppressWarnings("rawtypes")
+        Map m = converter.convert(dto).sourceAsDTO().to(Map.class);
+        assertEquals(4, m.size());
+        assertEquals("lalala", m.get("ping"));
+        assertEquals(Long.MIN_VALUE, m.get("pong"));
+        assertEquals(Count.ONE, m.get("count"));
+        assertNotNull(m.get("embedded"));
+        @SuppressWarnings("rawtypes")
+        Map e = (Map)m.get("embedded");
+        assertEquals("hohoho", e.get("marco"));
+        assertEquals(Long.MAX_VALUE, e.get("polo"));
+        assertEquals(Alpha.A, e.get("alpha"));
+    }
+
+    @Test
+    public void testDTO2Map3() {
+        MyEmbeddedDTO embedded2 = new MyEmbeddedDTO();
+        embedded2.marco = "hohoho";
+        embedded2.polo = Long.MAX_VALUE;
+        embedded2.alpha = Alpha.A;
+
+        MyDTOWithMethods embedded = new MyDTOWithMethods();
+        embedded.ping = "lalala";
+        embedded.pong = Long.MIN_VALUE;
+        embedded.count = Count.ONE;
+        embedded.embedded = embedded2;
+
+        MyDTO8 dto = new MyDTO8();
+        dto.ping = "lalala";
+        dto.pong = Long.MIN_VALUE;
+        dto.count = MyDTO8.Count.ONE;
+        dto.embedded = embedded;
+
+        @SuppressWarnings("rawtypes")
+        Map m = converter.convert(dto).sourceAsDTO().to(Map.class);
+        assertEquals(4, m.size());
+        assertEquals("lalala", m.get("ping"));
+        assertEquals(Long.MIN_VALUE, m.get("pong"));
+        assertEquals(MyDTO8.Count.ONE, m.get("count"));
+        assertNotNull(m.get("embedded"));
+        assertTrue(m.get( "embedded" ) instanceof MyDTOWithMethods);
+        MyDTOWithMethods e = (MyDTOWithMethods)m.get("embedded");
+        assertEquals("lalala", e.ping);
+        assertEquals(Long.MIN_VALUE, e.pong);
+        assertEquals(Count.ONE, e.count);
+        assertNotNull(e.embedded);
+        assertTrue(e.embedded instanceof MyEmbeddedDTO);
+        MyEmbeddedDTO e2 = (MyEmbeddedDTO)e.embedded;
+        assertEquals("hohoho", e2.marco);
+        assertEquals(Long.MAX_VALUE, e2.polo);
+        assertEquals(Alpha.A, e2.alpha);
+    }
+
     @Test @SuppressWarnings({ "rawtypes", "unchecked" })
     public void testDTOFieldShadowing() {
         MySubDTO dto = new MySubDTO();
@@ -603,7 +670,7 @@ public class ConverterTest {
     }
 
     @Test
-    public void testConvertAs1() {
+    public void testConvertAsInterface() {
         MyBean mb = new MyBean();
         mb.intfVal = 17;
         mb.beanVal = "Hello";
@@ -613,7 +680,7 @@ public class ConverterTest {
     }
 
     @Test
-    public void testConvertAs2() {
+    public void testConvertAsBean() {
         MyBean mb = new MyBean();
         mb.intfVal = 17;
         mb.beanVal = "Hello";
@@ -623,6 +690,14 @@ public class ConverterTest {
     }
 
     @Test
+    public void testConvertAsDTO() {
+        MyClass3 mc3 = new MyClass3(17);
+
+        assertEquals(17,
+                converter.convert(mc3).sourceAsDTO().to(Map.class).get("value"));
+    }
+
+    @Test
     public void testDTONameMangling() {
         Map<String,String> m = new HashMap<>();
         m.put("org.osgi.framework.uuid", "test123");
@@ -680,4 +755,17 @@ public class ConverterTest {
             return beanVal;
         }
     }
+
+    static class MyClass3 {
+        public int value;
+        public String string = "String";
+
+        public MyClass3( int value ) {
+            this.value = value;
+        }
+
+        public int value() {
+            return value;
+        }
+    }
 }

Added: felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/MyDTO8.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/MyDTO8.java?rev=1779874&view=auto
==============================================================================
--- felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/MyDTO8.java (added)
+++ felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/MyDTO8.java Mon Jan 23 02:41:12 2017
@@ -0,0 +1,32 @@
+/*
+ * 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 org.osgi.dto.DTO;
+
+public class MyDTO8 extends DTO {
+    public enum Count { ONE, TWO, THREE }
+
+    public Count count;
+
+    public String ping;
+
+    public long pong;
+
+    public MyDTOWithMethods embedded;
+}
+