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/08/04 16:07:44 UTC
svn commit: r1755199 - in /felix/trunk/converter/src:
main/java/org/apache/felix/converter/impl/ConvertingImpl.java
test/java/org/apache/felix/converter/impl/ConverterMapTest.java
Author: davidb
Date: Thu Aug 4 16:07:44 2016
New Revision: 1755199
URL: http://svn.apache.org/viewvc?rev=1755199&view=rev
Log:
Felix Converter Service - support for annotations.
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/ConverterMapTest.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=1755199&r1=1755198&r2=1755199&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 4 16:07:44 2016
@@ -287,13 +287,24 @@ public class ConvertingImpl implements C
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- String propName = getAccessorPropertyName(method);
+ String propName = getInterfacePropertyName(method);
if (propName == null)
return null;
Class<?> targetType = method.getReturnType();
- return converter.convert(m.get(propName)).to(targetType);
+ Object val = m.get(propName);
+
+ // If no value is available take the default if specified
+ if (val == null) {
+ if (targetCls.isAnnotation()) {
+ val = method.getDefaultValue();
+ }
+
+ if (val == null && args != null && args.length == 1)
+ val = args[0];
+ }
+ return converter.convert(val).to(targetType);
}
});
}
@@ -425,10 +436,25 @@ public class ConvertingImpl implements C
Map result = new HashMap();
for (Method md : obj.getClass().getDeclaredMethods()) {
- handleMethod(obj, md, invokedMethods, result);
+ handleBeanMethod(obj, md, invokedMethods, result);
}
for (Method md : obj.getClass().getMethods()) {
- handleMethod(obj, md, invokedMethods, result);
+ handleBeanMethod(obj, md, invokedMethods, result);
+ }
+
+ return result;
+ }
+
+ @SuppressWarnings("rawtypes")
+ private static Map createMapFromInterface(Object obj) {
+ Set<String> invokedMethods = new HashSet<>();
+
+ Map result = new HashMap();
+ for (Method md : obj.getClass().getDeclaredMethods()) {
+ handleInterfaceMethod(obj, md, invokedMethods, result);
+ }
+ for (Method md : obj.getClass().getMethods()) {
+ handleInterfaceMethod(obj, md, invokedMethods, result);
}
return result;
@@ -482,8 +508,21 @@ public class ConvertingImpl implements C
return propName.toString();
}
+ private static String getInterfacePropertyName(Method md) {
+ if (md.getReturnType().equals(Void.class))
+ return null; // not an accessor
+
+ if (md.getParameterTypes().length > 1)
+ 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
+
+ return md.getName().replace('_', '.'); // TODO support all the escaping mechanisms.
+ }
+
@SuppressWarnings({ "rawtypes", "unchecked" })
- private static void handleMethod(Object obj, Method md, Set<String> invokedMethods, Map res) {
+ private static void handleBeanMethod(Object obj, Method md, Set<String> invokedMethods, Map res) {
String mn = md.getName();
if (invokedMethods.contains(mn))
return; // method with this name already invoked
@@ -499,11 +538,30 @@ public class ConvertingImpl implements C
}
}
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private static void handleInterfaceMethod(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 = getInterfacePropertyName(md);
+ if (propName == null)
+ return;
+
+ try {
+ res.put(propName.toString(), md.invoke(obj));
+ invokedMethods.add(mn);
+ } catch (Exception e) {
+ }
+ }
+
private static Map<?,?> mapView(Object obj) {
if (obj instanceof Map)
return (Map<?,?>) obj;
else if (obj instanceof Dictionary)
return null; // TODO
+ else if (obj.getClass().getInterfaces().length > 0)
+ return createMapFromInterface(obj);
else
return createMapFromBeanAccessors(obj);
}
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=1755199&r1=1755198&r2=1755199&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 Thu Aug 4 16:07:44 2016
@@ -42,7 +42,7 @@ public class ConverterMapTest {
@Before
public void setUp() {
- converter = new ConverterImpl();
+ converter = new ConverterService();
}
@After
@@ -117,52 +117,34 @@ public class ConverterMapTest {
@Test
public void testInterfaceToMap() {
- Object obj = new Object();
TestInterface impl = new TestInterface() {
@Override
- public String getFoo() {
+ public String foo() {
return "Chocolate!";
}
@Override
- public int getBar() {
+ public int bar() {
return 76543;
}
- @SuppressWarnings("unused")
- public long getL() {
- return 1L;
+ @Override
+ public int bar(String def) {
+ return 0;
}
- @SuppressWarnings("unused")
- public boolean isSomething() {
+ @Override
+ public Boolean za_za() {
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(3, 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"));
+ assertEquals(true, (boolean) m.get("za.za"));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -172,10 +154,12 @@ public class ConverterMapTest {
m.put("foo", 12345);
m.put("bar", "999");
m.put("alt", "someval");
+ m.put("za.za", true);
TestInterface ti = converter.convert(m).to(TestInterface.class);
- assertEquals("12345", ti.getFoo());
- assertEquals(999, ti.getBar());
+ assertEquals("12345", ti.foo());
+ assertEquals(999, ti.bar());
+ assertEquals(Boolean.TRUE, ti.za_za());
}
@SuppressWarnings("rawtypes")
@@ -184,8 +168,36 @@ public class ConverterMapTest {
Map m = new HashMap<>();
TestInterface ti = converter.convert(m).to(TestInterface.class);
- assertNull(ti.getFoo());
- assertEquals(0, ti.getBar());
+ assertNull(ti.foo());
+ assertEquals(999, ti.bar("999"));
+ assertNull(ti.za_za());
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testMapToAnnotation1() {
+ Map m = new HashMap<>();
+ m.put("foo", 12345);
+ m.put("bar", "999");
+ m.put("alt", "someval");
+ m.put("za.za", true);
+
+ TestAnnotation ta = converter.convert(m).to(TestAnnotation.class);
+ assertEquals("12345", ta.foo());
+ assertEquals(999, ta.bar());
+ assertTrue(ta.za_za());
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testMapToAnnotationDefaults() {
+ Map m = new HashMap<>();
+ m.put("alt", "someval");
+
+ TestAnnotation ta = converter.convert(m).to(TestAnnotation.class);
+ assertEquals("fooo!", ta.foo());
+ assertEquals(42, ta.bar());
+ assertFalse(ta.za_za());
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@@ -200,7 +212,15 @@ public class ConverterMapTest {
}
interface TestInterface {
- String getFoo();
- int getBar();
+ String foo();
+ int bar();
+ int bar(String def);
+ Boolean za_za();
+ }
+
+ @interface TestAnnotation {
+ String foo() default "fooo!";
+ int bar() default 42;
+ boolean za_za();
}
}