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;
+}
+