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/02/17 16:21:15 UTC
svn commit: r1783423 - in /felix/trunk/converter/converter/src:
main/java/org/apache/felix/converter/impl/
test/java/org/apache/felix/converter/impl/
Author: davidb
Date: Fri Feb 17 16:21:15 2017
New Revision: 1783423
URL: http://svn.apache.org/viewvc?rev=1783423&view=rev
Log:
Felix Converter: allow the specification of an error handler with a converter Rule
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/apache/felix/converter/impl/InternalConverter.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/AdapterImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/AdapterImpl.java?rev=1783423&r1=1783422&r2=1783423&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 Fri Feb 17 16:21:15 2017
@@ -180,45 +180,59 @@ public class AdapterImpl implements Inte
@SuppressWarnings("unchecked")
@Override
public Object to(Type type) {
- if (object != null) {
- Set<Type> fromTypes = assignableTypes(treatAsClass != null ? treatAsClass : object.getClass());
- Set<Type> toTypes = assignableTypes(type);
+ List<ConvertFunction<Object, Object>> converters = new ArrayList<>();
+ try {
+ if (object != null) {
+ Set<Type> fromTypes = assignableTypes(treatAsClass != null ? treatAsClass : object.getClass());
+ Set<Type> toTypes = assignableTypes(type);
- List<ConvertFunction<Object, Object>> converters = new ArrayList<>();
- for (Type fromType : fromTypes) {
+ for (Type fromType : fromTypes) {
+ for (Type toType : toTypes) {
+ // TODO what exactly do we use as order here?
+ converters.add(classRules.get(new TypePair(fromType, Util.primitiveToBoxed(toType))));
+ }
+ }
+ for (Type fromType : fromTypes) {
+ converters.add(classRules.get(new TypePair(fromType, Object.class)));
+ }
for (Type toType : toTypes) {
- // TODO what exactly do we use as order here?
- converters.add(classRules.get(new TypePair(fromType, Util.primitiveToBoxed(toType))));
+ converters.add(classRules.get(new TypePair(Object.class, Util.primitiveToBoxed(toType))));
}
- }
- for (Type fromType : fromTypes) {
- converters.add(classRules.get(new TypePair(fromType, Object.class)));
- }
- for (Type toType : toTypes) {
- converters.add(classRules.get(new TypePair(Object.class, Util.primitiveToBoxed(toType))));
- }
- for (Iterator<ConvertFunction<Object, Object>> it = converters.iterator(); it.hasNext(); ) {
- ConvertFunction<Object, Object> func = it.next();
- it.remove();
- if (func == null)
- continue;
+ for (Iterator<ConvertFunction<Object, Object>> it = converters.iterator(); it.hasNext(); ) {
+ // remove null values
+ ConvertFunction<Object, Object> func = it.next();
+ if (func == null)
+ it.remove();
+ }
- try {
- Object res = func.convert(object, type, root, keys.toArray());
- if (res != null) {
- return res;
+ for (ConvertFunction<Object,Object> cf : converters) {
+ try {
+ Object res = cf.convert(object, type, root, keys.toArray());
+ if (res != null) {
+ return res;
+ }
+ } catch (Exception ex) {
+ if (hasDefault)
+ // TODO override this too!
+ return defaultValue;
+ else
+ throw new ConversionException("Cannot convert " + object + " to " + type, ex);
}
- } catch (Exception ex) {
- if (hasDefault)
- return defaultValue;
- else
- throw new ConversionException("Cannot convert " + object + " to " + type, ex);
}
}
- }
- return del.to(type);
+ return del.to(type);
+ } catch (Exception ex) {
+ // do custom error handling
+ for (ConvertFunction<Object, Object> cf : converters) {
+ Object eh = cf.handleError(object, type, root, keys.toArray());
+ if (eh != null)
+ return eh;
+ }
+ // No error handler, throw the original exception
+ throw ex;
+ }
}
@Override
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=1783423&r1=1783422&r2=1783423&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 Fri Feb 17 16:21:15 2017
@@ -481,14 +481,19 @@ public class ConvertingImpl implements C
Object val = m.get(propName);
// If no value is available take the default if specified
+ boolean defaultUsed = false; // TODO maybe we don't need this...
if (val == null) {
if (targetCls.isAnnotation()) {
val = method.getDefaultValue();
+ defaultUsed = true;
}
- if (val == null && args != null && args.length == 1)
+ if (val == null && args != null && args.length == 1) {
val = args[0];
+ defaultUsed = true;
+ }
}
+
return converter.convert(val).to(targetType);
}
});
Modified: felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/InternalConverter.java
URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/InternalConverter.java?rev=1783423&r1=1783422&r2=1783423&view=diff
==============================================================================
--- felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/InternalConverter.java (original)
+++ felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/InternalConverter.java Fri Feb 17 16:21:15 2017
@@ -19,5 +19,5 @@ package org.apache.felix.converter.impl;
import org.osgi.util.converter.Converter;
public interface InternalConverter extends Converter {
- public InternalConverting convert(Object obj);
+ InternalConverting convert(Object obj);
}
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=1783423&r1=1783422&r2=1783423&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 Fri Feb 17 16:21:15 2017
@@ -56,8 +56,10 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.osgi.util.converter.ConversionException;
+import org.osgi.util.converter.ConvertFunction;
import org.osgi.util.converter.Converter;
import org.osgi.util.converter.ConverterBuilder;
+import org.osgi.util.converter.Rule;
import org.osgi.util.converter.StandardConverter;
import org.osgi.util.converter.TypeReference;
@@ -342,9 +344,74 @@ public class ConverterTest {
int[] ia = {1, 2};
assertEquals("1,2", adapted.convert(ia).to(String.class));
assertArrayEquals(ia, adapted.convert("1,2").to(int[].class));
+ }
+
+ @Test
+ public void testCustomErrorHandling() {
+ ConvertFunction<String,Integer> func = new ConvertFunction<String,Integer>() {
+ @Override
+ public Integer convert(String obj, Type targetType, Object root, Object[] keyPath) throws Exception {
+ return null;
+ }
+
+ @Override
+ public Integer handleError(String obj, Type targetType, Object root, Object[] keyPath) {
+ if ("hello".equals(obj)) {
+ return -1;
+ }
+ return null;
+ }
+ };
+ ConverterBuilder cb = converter.newConverterBuilder();
+ cb.rule(new Rule<>(String.class, Integer.class, func));
+ Converter adapted = cb.build();
+
+ assertEquals(new Integer(12), adapted.convert("12").to(Integer.class));
+ assertEquals(new Integer(-1), adapted.convert("hello").to(Integer.class));
+
+ // This is with the non-adapted converter
+ try {
+ converter.convert("hello").to(Integer.class);
+ fail("Should have thrown a Conversion Exception when converting 'hello' to a number");
+ } catch (ConversionException ce) {
+ // good
+ }
}
+ /*
+ @Test
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public void testCustomDefaultHandling() {
+ // TODO re-enable
+ Map<String, String> m = new HashMap<>();
+// MyAnnotation ann = converter.convert(m).to(MyAnnotation.class);
+// assertEquals(17, ann.value());
+
+ // Now register a custom default handler
+ ConvertFunction<Map,MyAnnotation> func = new ConvertFunction<Map,MyAnnotation>() {
+ @Override
+ public MyAnnotation convert(Map obj, Type targetType, Object root, Object[] keyPath) throws Exception {
+ return null;
+ }
+
+ @Override
+ public MyAnnotation handleDefault(Map obj, Class<?> targetType, Object root, Object[] keyPath) {
+ return 42;
+ }
+ };
+
+ ConverterBuilder cb = converter.newConverterBuilder();
+ Rule r = new Rule(Map.class, MyAnnotation.class, func);
+ cb.rule(r);
+ Converter adapted = cb.build();
+
+ MyAnnotation ann2 = adapted.convert(m).to(MyAnnotation.class);
+ assertEquals("The default value from the annotation should have been overridden by the default handler",
+ 42, ann2.value());
+ }
+ */
+
@Test
public void testUUIDConversion() {
UUID uuid = UUID.randomUUID();
@@ -889,5 +956,9 @@ public class ConverterTest {
}
}
+ static @interface MyAnnotation {
+ int value() default 17;
+ }
+
enum SomeEnum { VALUE, GETVALUE };
}