You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ju...@apache.org on 2014/06/17 15:12:55 UTC

svn commit: r1603159 - in /sling/trunk/bundles/extensions/models/impl/src: main/java/org/apache/sling/models/impl/injectors/ test/java/org/apache/sling/models/impl/ test/java/org/apache/sling/models/testmodels/classes/

Author: justin
Date: Tue Jun 17 13:12:54 2014
New Revision: 1603159

URL: http://svn.apache.org/r1603159
Log:
SLING-3674 - automatically wrapping/unwrapping arrays where possible during value map injection

Added:
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ArrayPrimitivesModel.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ArrayWrappersModel.java
Modified:
    sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ValueMapInjector.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java

Modified: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ValueMapInjector.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ValueMapInjector.java?rev=1603159&r1=1603158&r2=1603159&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ValueMapInjector.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ValueMapInjector.java Tue Jun 17 13:12:54 2014
@@ -17,6 +17,7 @@
 package org.apache.sling.models.impl.injectors;
 
 import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Array;
 import java.lang.reflect.Type;
 
 import org.apache.commons.lang.StringUtils;
@@ -54,7 +55,33 @@ public class ValueMapInjector implements
         if (map == null) {
             return null;
         } else if (type instanceof Class<?>) {
-            return map.get(name, (Class<?>) type);
+            Class<?> clazz = (Class<?>) type;
+            try {
+                return map.get(name, clazz);
+            } catch (ClassCastException e) {
+                // handle case of primitive/wrapper arrays
+                if (clazz.isArray()) {
+                    Class<?> componentType = clazz.getComponentType();
+                    if (componentType.isPrimitive()) {
+                        Class<?> wrapper = getWrapperForPrimitive(componentType);
+                        if (wrapper != null) {
+                            Object wrapperArray = map.get(name, Array.newInstance(wrapper, 0).getClass());
+                            if (wrapperArray != null) {
+                                return unwrapArray(wrapperArray, componentType);
+                            }
+                        }
+                    } else {
+                        Class<?> primitiveType = getPrimitiveForWrapper(componentType);
+                        if (primitiveType != null) {
+                            Object primitiveArray = map.get(name, Array.newInstance(primitiveType, 0).getClass());
+                            if (primitiveArray != null) {
+                                return wrapArray(primitiveArray, componentType);
+                            }
+                        }
+                    }
+                }
+                return null;
+            }
         } else {
             log.debug("ValueMapInjector doesn't support non-class types {}", type);
             return null;
@@ -72,6 +99,76 @@ public class ValueMapInjector implements
         }
     }
 
+    private Object unwrapArray(Object wrapperArray, Class<?> primitiveType) {
+        int length = Array.getLength(wrapperArray);
+        Object primitiveArray = Array.newInstance(primitiveType, length);
+        for (int i = 0; i < length; i++) {
+            Array.set(primitiveArray, i, Array.get(wrapperArray, i));
+        }
+        return primitiveArray;
+    }
+
+    private Object wrapArray(Object primitiveArray, Class<?> wrapperType) {
+        int length = Array.getLength(primitiveArray);
+        Object wrapperArray = Array.newInstance(wrapperType, length);
+        for (int i = 0; i < length; i++) {
+            Array.set(wrapperArray, i, Array.get(primitiveArray, i));
+        }
+        return wrapperArray;
+    }
+
+    private Class<?> getPrimitiveForWrapper(Class<?> clazz) {
+        if (clazz == Integer.class) {
+            return Integer.TYPE;
+        }
+        if (clazz == Long.class) {
+            return Long.TYPE;
+        }
+        if (clazz == Boolean.class) {
+            return Boolean.TYPE;
+        }
+        if (clazz == Double.class) {
+            return Double.TYPE;
+        }
+        if (clazz == Float.class) {
+            return Float.TYPE;
+        }
+        if (clazz == Short.class) {
+            return Short.TYPE;
+        }
+        if (clazz == Character.class) {
+            return Character.TYPE;
+        }
+
+        return null;
+    }
+
+    private Class<?> getWrapperForPrimitive(Class<?> clazz) {
+        if (clazz == Integer.TYPE) {
+            return Integer.class;
+        }
+        if (clazz == Long.TYPE) {
+            return Long.class;
+        }
+        if (clazz == Boolean.TYPE) {
+            return Boolean.class;
+        }
+        if (clazz == Double.TYPE) {
+            return Double.class;
+        }
+        if (clazz == Float.TYPE) {
+            return Float.class;
+        }
+        if (clazz == Short.TYPE) {
+            return Short.class;
+        }
+        if (clazz == Character.TYPE) {
+            return Character.class;
+        }
+
+        return null;
+    }
+
     @Override
     public InjectAnnotationProcessor createAnnotationProcessor(Object adaptable, AnnotatedElement element) {
         // check if the element has the expected annotation

Modified: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java?rev=1603159&r1=1603158&r2=1603159&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java Tue Jun 17 13:12:54 2014
@@ -29,6 +29,8 @@ import org.apache.sling.api.resource.Val
 import org.apache.sling.api.wrappers.ValueMapDecorator;
 import org.apache.sling.models.impl.injectors.ChildResourceInjector;
 import org.apache.sling.models.impl.injectors.ValueMapInjector;
+import org.apache.sling.models.testmodels.classes.ArrayPrimitivesModel;
+import org.apache.sling.models.testmodels.classes.ArrayWrappersModel;
 import org.apache.sling.models.testmodels.classes.ChildModel;
 import org.apache.sling.models.testmodels.classes.ChildResourceModel;
 import org.apache.sling.models.testmodels.classes.ChildValueMapModel;
@@ -93,6 +95,50 @@ public class ResourceModelClassesTest {
     }
 
     @Test
+    public void testArrayPrimitivesModel() {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("intArray", new int[] { 1, 2, 9, 8 });
+        map.put("secondIntArray", new Integer[] {1, 2, 9, 8});
+
+        ValueMap vm = new ValueMapDecorator(map);
+        Resource res = mock(Resource.class);
+        when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+
+        ArrayPrimitivesModel model = factory.getAdapter(res, ArrayPrimitivesModel.class);
+        assertNotNull(model);
+
+        int[] primitiveIntArray = model.getIntArray();
+        assertEquals(4, primitiveIntArray.length);
+        assertEquals(2, primitiveIntArray[1]);
+
+        int[] secondPrimitiveIntArray = model.getSecondIntArray();
+        assertEquals(4, secondPrimitiveIntArray.length);
+        assertEquals(2, secondPrimitiveIntArray[1]);
+    }
+
+    @Test
+    public void testArrayWrappersModel() {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("intArray", new Integer[] {1, 2, 9, 8});
+        map.put("secondIntArray", new int[] {1, 2, 9, 8});
+
+        ValueMap vm = new ValueMapDecorator(map);
+        Resource res = mock(Resource.class);
+        when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+
+        ArrayWrappersModel model = factory.getAdapter(res, ArrayWrappersModel.class);
+        assertNotNull(model);
+
+        Integer[] intArray = model.getIntArray();
+        assertEquals(4, intArray.length);
+        assertEquals(new Integer(2), intArray[1]);
+
+        Integer[] secondIntArray = model.getSecondIntArray();
+        assertEquals(4, secondIntArray.length);
+        assertEquals(new Integer(2), secondIntArray[1]);
+    }
+
+    @Test
     public void testRequiredPropertyModel() {
         Map<String, Object> map = new HashMap<String, Object>();
         map.put("first", "first-value");

Added: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ArrayPrimitivesModel.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ArrayPrimitivesModel.java?rev=1603159&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ArrayPrimitivesModel.java (added)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ArrayPrimitivesModel.java Tue Jun 17 13:12:54 2014
@@ -0,0 +1,40 @@
+/*
+ * 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.sling.models.testmodels.classes;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+
+import javax.inject.Inject;
+
+@Model(adaptables = Resource.class)
+public class ArrayPrimitivesModel {
+
+    @Inject
+    private int[] intArray;
+
+    @Inject
+    private int[] secondIntArray;
+
+    public int[] getIntArray() {
+        return intArray;
+    }
+
+    public int[] getSecondIntArray() {
+        return secondIntArray;
+    }
+}
\ No newline at end of file

Added: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ArrayWrappersModel.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ArrayWrappersModel.java?rev=1603159&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ArrayWrappersModel.java (added)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ArrayWrappersModel.java Tue Jun 17 13:12:54 2014
@@ -0,0 +1,40 @@
+/*
+ * 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.sling.models.testmodels.classes;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+
+import javax.inject.Inject;
+
+@Model(adaptables = Resource.class)
+public class ArrayWrappersModel {
+
+    @Inject
+    private Integer[] intArray;
+
+    @Inject
+    private Integer[] secondIntArray;
+
+    public Integer[] getIntArray() {
+        return intArray;
+    }
+
+    public Integer[] getSecondIntArray() {
+        return secondIntArray;
+    }
+}
\ No newline at end of file