Author: davidb Date: Thu Aug 11 16:28:18 2016 New Revision: 1756008 URL: http://svn.apache.org/viewvc?rev=1756008&view=rev Log: Felix Converter: initial support for DTOs
Added: felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/MyDTO.java Modified: felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.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/ConvertingImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.java?rev=1756008&r1=1756007&r2=1756008&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 Thu Aug 11 16:28:18 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.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; import java.lang.reflect.Type; @@ -39,6 +41,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import org.osgi.dto.DTO; import org.osgi.service.converter.ConversionException; import org.osgi.service.converter.Converter; import org.osgi.service.converter.Converting; @@ -129,6 +132,8 @@ public class ConvertingImpl implements C return convertToArray(targetCls); } else if (Collection.class.isAssignableFrom(targetCls)) { return convertToCollection(targetCls, typeArguments); + } else if (DTO.class.isAssignableFrom(targetCls)) { + return convertToDTO(targetCls); } else if (isMapType(targetCls)) { return convertToMapType(targetCls, typeArguments); } @@ -216,6 +221,27 @@ public class ConvertingImpl implements C } @SuppressWarnings({ "rawtypes", "unchecked" }) + private <T> T convertToDTO(Class<T> targetCls) { + Map m = mapView(object); + + try { + T dto = targetCls.newInstance(); + + for (Map.Entry entry : (Set<Map.Entry>) m.entrySet()) { + try { + Field f = targetCls.getField(entry.getKey().toString()); + f.set(dto, entry.getValue()); + } catch (NoSuchFieldException e) { + } + } + + return dto; + } catch (Exception e) { + throw new ConversionException("Cannot create DTO " + targetCls, e); + } + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) private Map convertToMap(Class<?> targetCls, Type[] typeArguments) { Map m = mapView(object); if (m == null) @@ -449,6 +475,22 @@ public class ConvertingImpl implements C return result; } + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static Map createMapFromDTO(Object obj) { + Map result = new HashMap(); + + for (Field f : obj.getClass().getFields()) { + if (Modifier.isStatic(f.getModifiers())) + continue; + + try { + result.put(f.getName(), f.get(obj)); // TODO handle escaping + } catch (Exception e) { + } + } + return result; + } + @SuppressWarnings("rawtypes") private static Map createMapFromInterface(Object obj) { Set<String> invokedMethods = new HashSet<>(); @@ -527,6 +569,9 @@ public class ConvertingImpl implements C @SuppressWarnings({ "rawtypes", "unchecked" }) private static void handleBeanMethod(Object obj, Method md, Set<String> invokedMethods, Map res) { + if (Modifier.isStatic(md.getModifiers())) + return; + String mn = md.getName(); if (invokedMethods.contains(mn)) return; // method with this name already invoked @@ -544,6 +589,9 @@ public class ConvertingImpl implements C @SuppressWarnings({ "rawtypes", "unchecked" }) private static void handleInterfaceMethod(Object obj, Method md, Set<String> invokedMethods, Map res) { + if (Modifier.isStatic(md.getModifiers())) + return; + String mn = md.getName(); if (invokedMethods.contains(mn)) return; // method with this name already invoked @@ -564,6 +612,8 @@ public class ConvertingImpl implements C return (Map<?,?>) obj; else if (obj instanceof Dictionary) return null; // TODO + else if (obj instanceof DTO) + return createMapFromDTO(obj); else if (obj.getClass().getInterfaces().length > 0) return createMapFromInterface(obj); else Modified: 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=1756008&r1=1756007&r2=1756008&view=diff ============================================================================== --- felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterServiceTest.java (original) +++ felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/ConverterServiceTest.java Thu Aug 11 16:28:18 2016 @@ -28,9 +28,11 @@ import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.regex.Matcher; @@ -384,6 +386,30 @@ public class ConverterServiceTest { assertEquals(12L, l); } + @Test + public void testDTO2Map() { + MyDTO dto = new MyDTO(); + dto.ping = "lalala"; + dto.pong = Long.MIN_VALUE; + + @SuppressWarnings("rawtypes") + Map m = converter.convert(dto).to(Map.class); + assertEquals(2, m.size()); + assertEquals("lalala", m.get("ping")); + assertEquals(Long.MIN_VALUE, m.get("pong")); + } + + @Test + public void testMap2DTO() { + Map<String, Object> m = new HashMap<>(); + m.put("ping", "abc xyz"); + m.put("pong", 42L); + + MyDTO dto = converter.convert(m).to(MyDTO.class); + assertEquals("abc xyz", dto.ping); + assertEquals(42L, dto.pong); + } + static class MyClass2 { private final String value; public MyClass2(String v) { Added: felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/MyDTO.java URL: http://svn.apache.org/viewvc/felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/MyDTO.java?rev=1756008&view=auto ============================================================================== --- felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/MyDTO.java (added) +++ felix/trunk/converter/src/test/java/org/apache/felix/converter/impl/MyDTO.java Thu Aug 11 16:28:18 2016 @@ -0,0 +1,25 @@ +/* + * 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 MyDTO extends DTO { + public String ping; + + public long pong; +}