Author: davidb Date: Mon Mar 20 15:25:16 2017 New Revision: 1787794 URL: http://svn.apache.org/viewvc?rev=1787794&view=rev Log: Felix Converter - Support prefixes for annotations and interfaces
Added: felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/PrefixAnnotation.java felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/PrefixInterface.java Modified: 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/DynamicMapLikeFacade.java felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/MapDelegate.java felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/Util.java felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/ConverterMapTest.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=1787794&r1=1787793&r2=1787794&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 Mar 20 15:25:16 2017 @@ -418,7 +418,7 @@ public class ConvertingImpl implements C } })); else if (targetAsClass.isInterface()) - return createProxy(sourceClass, targetAsClass); + return createInterface(sourceClass, targetAsClass); return createJavaBean(sourceClass, targetAsClass); } @@ -444,7 +444,7 @@ public class ConvertingImpl implements C } @SuppressWarnings("rawtypes") - private Object createProxy(Class<?> sourceCls, Class<?> targetCls) { + private Object createInterface(Class<?> sourceCls, Class<?> targetCls) { Map m = mapView(object, sourceCls, converter); return Proxy.newProxyInstance(targetCls.getClassLoader(), new Class[] {targetCls}, new InvocationHandler() { @@ -467,6 +467,9 @@ public class ConvertingImpl implements C if (val == null && args != null && args.length == 1) { val = args[0]; } + + if (val == null) + throw new ConversionException("No value for property: " + propName); } return converter.convert(val).to(targetType); Modified: felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/DynamicMapLikeFacade.java URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/DynamicMapLikeFacade.java?rev=1787794&r1=1787793&r2=1787794&view=diff ============================================================================== --- felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/DynamicMapLikeFacade.java (original) +++ felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/DynamicMapLikeFacade.java Mon Mar 20 15:25:16 2017 @@ -252,6 +252,8 @@ class DynamicInterfaceFacade extends Dyn try { return m.invoke(backingObject); } catch (Exception e) { + if (RuntimeException.class.isAssignableFrom(e.getCause().getClass())) + throw ((RuntimeException) e.getCause()); throw new RuntimeException(e); } } Modified: felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/MapDelegate.java URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/MapDelegate.java?rev=1787794&r1=1787793&r2=1787794&view=diff ============================================================================== --- felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/MapDelegate.java (original) +++ felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/MapDelegate.java Mon Mar 20 15:25:16 2017 @@ -137,8 +137,10 @@ class MapDelegate<K, V> implements Map<K public Set<K> keySet() { Set<K> keys = new HashSet<>(); - for (Map.Entry<K,V> entry : entrySet()) { - keys.add(entry.getKey()); + for (Object key : delegate.keySet()) { + @SuppressWarnings("unchecked") + K k = (K) findConvertedKey(internalKeySet(), key); + keys.add(k); } return keys; } Modified: felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/Util.java URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/Util.java?rev=1787794&r1=1787793&r2=1787794&view=diff ============================================================================== --- felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/Util.java (original) +++ felix/trunk/converter/converter/src/main/java/org/apache/felix/converter/impl/Util.java Mon Mar 20 15:25:16 2017 @@ -189,7 +189,7 @@ class Util { return null; } - return md.getName().replace('_', '.'); // TODO support all the escaping mechanisms. + return unMangleName(getPrefix(md.getDeclaringClass()), md.getName()); } private static boolean isInheritedMethodInProxy(Method md, Class<?> cls) { @@ -223,6 +223,15 @@ class Util { } catch (Exception ex) { // LOG no prefix field } + + if (!cls.isInterface()) { + for (Class<?> intf : cls.getInterfaces()) { + String prefix = getPrefix(intf); + if (prefix.length() > 0) + return prefix; + } + } + return ""; } Modified: felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/ConverterMapTest.java URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/ConverterMapTest.java?rev=1787794&r1=1787793&r2=1787794&view=diff ============================================================================== --- felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/ConverterMapTest.java (original) +++ felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/ConverterMapTest.java Mon Mar 20 15:25:16 2017 @@ -29,6 +29,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; +import org.osgi.util.converter.ConversionException; import org.osgi.util.converter.Converter; import org.osgi.util.converter.ConverterBuilder; import org.osgi.util.converter.Rule; @@ -42,6 +43,7 @@ import static org.junit.Assert.assertNot import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; public class ConverterMapTest { private Converter converter; @@ -200,9 +202,19 @@ public class ConverterMapTest { Map m = new HashMap<>(); TestInterface ti = converter.convert(m).to(TestInterface.class); - assertNull(ti.foo()); + try { + ti.foo(); + fail("Should have thrown a conversion exception"); + } catch (ConversionException ce) { + // good + } assertEquals(999, ti.bar("999")); - assertNull(ti.za_za()); + try { + assertNull(ti.za_za()); + fail("Should have thrown a conversion exception"); + } catch (ConversionException ce) { + // good + } } @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -229,7 +241,6 @@ public class ConverterMapTest { TestAnnotation ta = converter.convert(m).to(TestAnnotation.class); assertEquals("fooo!", ta.foo()); assertEquals(42, ta.bar()); - assertFalse(ta.za_za()); } @Test @@ -239,7 +250,12 @@ public class ConverterMapTest { assertEquals(3, m.size()); assertEquals("fooo!", m.get("foo")); assertEquals(42, m.get("bar")); - assertEquals(false, m.get("za.za")); + try { + assertEquals(false, m.get("za.za")); + fail("Should have thrown a conversion exception as there is no default for 'za.za'"); + } catch (ConversionException ce) { + // good + } } @SuppressWarnings({ "rawtypes", "unchecked" }) 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=1787794&r1=1787793&r2=1787794&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 Mar 20 15:25:16 2017 @@ -882,10 +882,11 @@ public class ConverterTest { public void testPrefixDTO() { Map<String, String> m = new HashMap<>(); m.put("org.foo.bar.width", "327"); + m.put("org.foo.bar.warp", "eeej"); m.put("length", "12"); PrefixDTO dto = converter.convert(m).to(PrefixDTO.class); - assertEquals(327, dto.width); + assertEquals(327L, dto.width); assertEquals("This one should not be set", 0, dto.length); Map<String, String> m2 = converter.convert(dto).to(new TypeReference<HashMap<String,String>>() {}); @@ -895,6 +896,59 @@ public class ConverterTest { assertEquals(expected, m2); } + @Test + public void testPrefixInterface() { + Map<String, String> m = new HashMap<>(); + m.put("org.foo.bar.width", "327"); + m.put("org.foo.bar.warp", "eeej"); + m.put("length", "12"); + + PrefixInterface i = converter.convert(m).to(PrefixInterface.class); + assertEquals(327L, i.width()); + try { + i.length(); + fail("Should have thrown an exception"); + } catch (ConversionException ce) { + // good + } + + PrefixInterface i2 = new PrefixInterface() { + @Override + public long width() { + return Long.MAX_VALUE; + } + + @Override + public int length() { + return Integer.MIN_VALUE; + } + }; + + Map<String, String> m2 = converter.convert(i2).to(new TypeReference<Map<String,String>>() {}); + Map<String, String> expected = new HashMap<>(); + expected.put("org.foo.bar.width", "" + Long.MAX_VALUE); + expected.put("org.foo.bar.length", "" + Integer.MIN_VALUE); + assertEquals(expected, m2); + } + + @Test + public void testAnnotationInterface() { + Map<String, String> m = new HashMap<>(); + m.put("org.foo.bar.width", "327"); + m.put("org.foo.bar.warp", "eeej"); + m.put("length", "12"); + + PrefixAnnotation pa = converter.convert(m).to(PrefixAnnotation.class); + assertEquals(327L, pa.width()); + assertEquals(51, pa.length()); + + Map<String, String> m2 = converter.convert(pa).to(new TypeReference<Map<String,String>>() {}); + Map<String, String> expected = new HashMap<>(); + expected.put("org.foo.bar.width", "327"); + expected.put("org.foo.bar.length", "51"); + assertEquals(expected, m2); + } + static class MyClass2 { private final String value; public MyClass2(String v) { Added: felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/PrefixAnnotation.java URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/PrefixAnnotation.java?rev=1787794&view=auto ============================================================================== --- felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/PrefixAnnotation.java (added) +++ felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/PrefixAnnotation.java Mon Mar 20 15:25:16 2017 @@ -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; + +public @interface PrefixAnnotation { + static final String PREFIX_ = "org.foo.bar."; + + long width() default 42L; + + int length() default 51; +} Added: felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/PrefixInterface.java URL: http://svn.apache.org/viewvc/felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/PrefixInterface.java?rev=1787794&view=auto ============================================================================== --- felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/PrefixInterface.java (added) +++ felix/trunk/converter/converter/src/test/java/org/apache/felix/converter/impl/PrefixInterface.java Mon Mar 20 15:25:16 2017 @@ -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; + +public interface PrefixInterface { + static final String PREFIX_ = "org.foo.bar."; + + long width(); + + int length(); +}