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/10/10 15:55:43 UTC

svn commit: r1764135 - in /felix/trunk/converter/converter/src/main/java/org: apache/felix/converter/impl/AdapterImpl.java apache/felix/converter/impl/ConvertingImpl.java osgi/converter/Converting.java

Author: davidb
Date: Mon Oct 10 15:55:42 2016
New Revision: 1764135

URL: http://svn.apache.org/viewvc?rev=1764135&view=rev
Log:
Felix Converter - initial implementation of supporting the as() method.

The as() method is used to disabiguate input objects when these potentially match multiple rules.

Modified:
    felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/AdapterImpl.java
    felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/ConvertingImpl.java
    felix/trunk/converter/converter/src/main/java/org/osgi/converter/Converting.java

Modified: felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/AdapterImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/AdapterImpl.java?rev=1764135&r1=1764134&r2=1764135&view=diff
==============================================================================
--- felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/AdapterImpl.java (original)
+++ felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/AdapterImpl.java Mon Oct 10 15:55:42 2016
@@ -80,6 +80,7 @@ public class AdapterImpl implements Inte
         private final InternalConverting del;
         private final Object object;
         private volatile Object defaultValue;
+        private volatile Class<?> treatAsClass;
         private volatile boolean hasDefault;
 
         ConvertingWrapper(Object obj, InternalConverting c) {
@@ -88,6 +89,13 @@ public class AdapterImpl implements Inte
         }
 
         @Override
+        public Converting as(Class<?> cls) {
+            treatAsClass = cls;
+            del.as(cls);
+            return this;
+        }
+
+        @Override
         public Converting defaultValue(Object defVal) {
             del.defaultValue(defVal);
             defaultValue = defVal;
@@ -116,6 +124,7 @@ public class AdapterImpl implements Inte
         @Override
         public Object to(Type type) {
             if (object != null) {
+                // TODO use treatAsClass
                 Set<Type> fromTypes = assignableTypes(object.getClass());
                 Set<Type> toTypes = assignableTypes(type);
 

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=1764135&r1=1764134&r2=1764135&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 Oct 10 15:55:42 2016
@@ -60,6 +60,7 @@ public class ConvertingImpl implements C
 
     private volatile Converter converter;
     private volatile Object object;
+    private volatile Class<?> treatAsClass;
     private volatile Object defaultValue;
     private volatile boolean hasDefault;
 
@@ -69,6 +70,12 @@ public class ConvertingImpl implements C
     }
 
     @Override
+    public Converting as(Class<?> type) {
+        treatAsClass = type;
+        return this;
+    }
+
+    @Override
     public Converting defaultValue(Object defVal) {
         defaultValue = defVal;
         hasDefault = true;
@@ -115,8 +122,9 @@ public class ConvertingImpl implements C
             return handleNull(cls);
 
         Class<?> targetCls = Util.primitiveToBoxed(cls);
+        Class<?> sourceCls = treatAsClass != null ? treatAsClass : object.getClass();
 
-        if (!isCopyRequiredType(targetCls) && targetCls.isAssignableFrom(object.getClass())) {
+        if (!isCopyRequiredType(targetCls) && targetCls.isAssignableFrom(sourceCls)) {
                 return object;
         }
 
@@ -129,13 +137,13 @@ public class ConvertingImpl implements C
         } else if (Collection.class.isAssignableFrom(targetCls)) {
             return convertToCollection(targetCls, typeArguments);
         } else if (DTO.class.isAssignableFrom(targetCls)) {
-            return convertToDTO(targetCls);
+            return convertToDTO(sourceCls, targetCls);
         } else if (isMapType(targetCls)) {
-            return convertToMapType(targetCls, typeArguments);
+            return convertToMapType(sourceCls, targetCls, typeArguments);
         }
 
         // At this point we know that the target is a 'singular' type: not a map, collection or array
-        if (object instanceof Collection) {
+        if (Collection.class.isAssignableFrom(sourceCls)) {
             return convertCollectionToSingleValue(cls);
         } else if ((object = asBoxedArray(object)) instanceof Object[]) {
             return convertArrayToSingleValue(cls);
@@ -217,8 +225,8 @@ public class ConvertingImpl implements C
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    private <T> T convertToDTO(Class<T> targetCls) {
-        Map m = mapView(object, converter);
+    private <T> T convertToDTO(Class<?> sourceCls, Class<T> targetCls) {
+        Map m = mapView(object, sourceCls, converter);
 
         try {
             T dto = targetCls.newInstance();
@@ -248,8 +256,8 @@ public class ConvertingImpl implements C
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    private Map convertToMap(Class<?> targetCls, Type[] typeArguments) {
-        Map m = mapView(object, converter);
+    private Map convertToMap(Class<?> sourceCls, Class<?> targetCls, Type[] typeArguments) {
+        Map m = mapView(object, sourceCls, converter);
         if (m == null)
             return null;
         Type targetKeyType = null, targetValueType = null;
@@ -289,19 +297,19 @@ public class ConvertingImpl implements C
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    private Object convertToMapType(Class<?> targetCls, Type[] typeArguments) {
+    private Object convertToMapType(Class<?> sourceCls, Class<?> targetCls, Type[] typeArguments) {
         if (Map.class.isAssignableFrom(targetCls))
-            return convertToMap(targetCls, typeArguments);
+            return convertToMap(sourceCls, targetCls, typeArguments);
         else if (Dictionary.class.isAssignableFrom(targetCls))
-            return new Hashtable(convertToMap(Map.class, typeArguments));
+            return new Hashtable(convertToMap(sourceCls, Map.class, typeArguments));
         else if (targetCls.isInterface())
-            return createProxy(targetCls);
-        return createJavaBean(targetCls);
+            return createProxy(sourceCls, targetCls);
+        return createJavaBean(sourceCls, targetCls);
     }
 
-    private Object createJavaBean(Class<?> targetCls) {
+    private Object createJavaBean(Class<?> sourceCls, Class<?> targetCls) {
         @SuppressWarnings("rawtypes")
-        Map m = mapView(object, converter);
+        Map m = mapView(object, sourceCls, converter);
         try {
             Object res = targetCls.getConstructor().newInstance();
             for (Method setter : getSetters(targetCls)) {
@@ -321,8 +329,8 @@ public class ConvertingImpl implements C
     }
 
     @SuppressWarnings("rawtypes")
-    private Object createProxy(Class<?> targetCls) {
-        Map m = mapView(object, converter);
+    private Object createProxy(Class<?> sourceCls, Class<?> targetCls) {
+        Map m = mapView(object, sourceCls, converter);
         return Proxy.newProxyInstance(targetCls.getClassLoader(), new Class[] {targetCls},
             new InvocationHandler() {
                 @Override
@@ -477,14 +485,14 @@ public class ConvertingImpl implements C
     }
 
     @SuppressWarnings("rawtypes")
-    private static Map createMapFromBeanAccessors(Object obj) {
+    private static Map createMapFromBeanAccessors(Object obj, Class<?> sourceCls) {
         Set<String> invokedMethods = new HashSet<>();
 
         Map result = new HashMap();
-        for (Method md : obj.getClass().getDeclaredMethods()) {
+        for (Method md : sourceCls.getDeclaredMethods()) {
             handleBeanMethod(obj, md, invokedMethods, result);
         }
-        for (Method md : obj.getClass().getMethods()) {
+        for (Method md : sourceCls.getMethods()) {
             handleBeanMethod(obj, md, invokedMethods, result);
         }
 
@@ -670,17 +678,20 @@ public class ConvertingImpl implements C
         }
     }
 
-    private static Map<?,?> mapView(Object obj, Converter converter) {
-        if (obj instanceof Map)
+    private static Map<?,?> mapView(Object obj, Class<?> sourceCls, Converter converter) {
+        if (Map.class.isAssignableFrom(sourceCls))
             return (Map<?,?>) obj;
-        else if (obj instanceof Dictionary)
+        else if (Dictionary.class.isAssignableFrom(sourceCls))
             return null; // TODO
         else if (obj instanceof DTO)
+            // TODO inspect if its a DTO, rather than instanceof
             return createMapFromDTO(obj, converter);
-        else if (obj.getClass().getInterfaces().length > 0)
-            return createMapFromInterface(obj);
-        else
-            return createMapFromBeanAccessors(obj);
+        else {
+            Map<?,?> m = createMapFromBeanAccessors(obj, sourceCls);
+            if (m.size() > 0)
+                return m;
+        }
+        return createMapFromInterface(obj);// TODO, sourceCls);
     }
 
     private static boolean isCopyRequiredType(Class<?> cls) {

Modified: felix/trunk/converter/converter/src/main/java/org/osgi/converter/Converting.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/main/java/org/osgi/converter/Converting.java?rev=1764135&r1=1764134&r2=1764135&view=diff
==============================================================================
--- felix/trunk/converter/converter/src/main/java/org/osgi/converter/Converting.java (original)
+++ felix/trunk/converter/converter/src/main/java/org/osgi/converter/Converting.java Mon Oct 10 15:55:42 2016
@@ -29,6 +29,16 @@ import org.osgi.annotation.versioning.Pr
  */
 @ProviderType
 public interface Converting {
+    /**
+     * Convert the source object based on rules for the class being passed in.
+     * This method can be used to disambiguate objects that would match multiple
+     * conversion rules.
+     * @param type The type or class to be used as the source type for the conversion
+     * @return The current {@code Converting} object so that additional calls
+     *         can be chained.
+     */
+    Converting as(Class<?> type);
+
 	/**
 	 * The default value to use when the object cannot be converted or in case
 	 * of conversion from a {@code null} value.