This is an automated email from the ASF dual-hosted git repository.

sseifert pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-models-impl.git


The following commit(s) were added to refs/heads/master by this push:
     new 13ac778  SLING-11812 support default value injection for Collection 
and List types (#42)
13ac778 is described below

commit 13ac77895051340159a81d6ba8a43c1b495d8895
Author: Stefan Seifert <[email protected]>
AuthorDate: Tue Mar 28 13:16:59 2023 +0200

    SLING-11812 support default value injection for Collection and List types 
(#42)
---
 .../impl/model/AbstractInjectableElement.java      | 58 +++++++++++++++++++-
 .../models/impl/ResourceModelClassesTest.java      | 52 +++++++++++++++++-
 ...ListModel.java => CollectionDefaultsModel.java} | 23 ++++----
 .../{ListModel.java => ListDefaultsModel.java}     | 61 +++++++++++++++++++---
 .../sling/models/testmodels/classes/ListModel.java | 17 ++++--
 5 files changed, 189 insertions(+), 22 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/models/impl/model/AbstractInjectableElement.java
 
b/src/main/java/org/apache/sling/models/impl/model/AbstractInjectableElement.java
index 72ccb18..0f5c205 100644
--- 
a/src/main/java/org/apache/sling/models/impl/model/AbstractInjectableElement.java
+++ 
b/src/main/java/org/apache/sling/models/impl/model/AbstractInjectableElement.java
@@ -19,7 +19,12 @@
 package org.apache.sling.models.impl.model;
 
 import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Array;
+import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 
 import javax.inject.Named;
 
@@ -37,6 +42,7 @@ import org.apache.sling.models.impl.ReflectionUtil;
 import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor;
 import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor2;
 import 
org.apache.sling.models.spi.injectorspecific.StaticInjectAnnotationProcessorFactory;
+import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -148,7 +154,35 @@ abstract class AbstractInjectableElement implements 
InjectableElement {
 
         Object value = null;
 
-        if (type instanceof Class) {
+        if (type instanceof ParameterizedType) {
+            ParameterizedType parameterizedType = (ParameterizedType)type;
+            Type rawType = parameterizedType.getRawType();
+            if ((rawType == Collection.class || rawType == List.class)
+                    && parameterizedType.getActualTypeArguments().length > 0) {
+                Type itemType = parameterizedType.getActualTypeArguments()[0];
+                if (itemType == String.class) {
+                    value = arrayToTypedList(defaultAnnotation.values());
+                } else if (itemType == Integer.class) {
+                    value = arrayToTypedList(defaultAnnotation.intValues());
+                } else if (itemType == Long.class) {
+                    value = arrayToTypedList(defaultAnnotation.longValues());
+                } else if (itemType == Boolean.class) {
+                    value = 
arrayToTypedList(defaultAnnotation.booleanValues());
+                } else if (itemType == Short.class) {
+                    value = arrayToTypedList(defaultAnnotation.shortValues());
+                } else if (itemType == Float.class) {
+                    value = arrayToTypedList(defaultAnnotation.floatValues());
+                } else if (itemType == Double.class) {
+                    value = arrayToTypedList(defaultAnnotation.doubleValues());
+                } else {
+                    log.warn("Default values for {} List/Collection are not 
supported", itemType);
+                }
+            }
+            else {
+                log.warn("Cannot provide default for {}", type);
+            }
+        }
+        else if (type instanceof Class) {
             Class<?> injectedClass = (Class<?>) type;
             if (injectedClass.isArray()) {
                 Class<?> componentType = injectedClass.getComponentType();
@@ -206,6 +240,28 @@ abstract class AbstractInjectableElement implements 
InjectableElement {
         return value;
     }
 
+    /**
+     * Converts array to typed list of values.
+     * @param <T> Array/List type
+     * @param array Array
+     * @return Typed list or null if array is empty
+     */
+    @SuppressWarnings("unchecked")
+    private static <T> @Nullable List<T> arrayToTypedList(Object array) {
+        if (array != null && array.getClass().isArray()) {
+            int arrayLength = Array.getLength(array);
+            if (arrayLength > 0) {
+                List<T> result = new ArrayList<>();
+                for (int i=0; i<arrayLength; i++) {
+                    result.add((T)Array.get(array, i));
+                }
+                return result;
+            }
+
+        }
+        return null;
+    }
+
     private static boolean getOptional(AnnotatedElement element, 
InjectAnnotationProcessor annotationProcessor) {
         if (element.isAnnotationPresent(Optional.class)) {
             return true;
diff --git 
a/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java 
b/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java
index 8bbdbf8..f802baf 100644
--- a/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java
+++ b/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java
@@ -46,6 +46,8 @@ 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;
+import org.apache.sling.models.testmodels.classes.CollectionDefaultsModel;
+import org.apache.sling.models.testmodels.classes.ListDefaultsModel;
 import org.apache.sling.models.testmodels.classes.ListModel;
 import org.apache.sling.models.testmodels.classes.ParentModel;
 import 
org.apache.sling.models.testmodels.classes.ResourceModelWithRequiredField;
@@ -72,7 +74,18 @@ public class ResourceModelClassesTest {
         factory.bindInjector(new ChildResourceInjector(), new 
ServicePropertiesMap(1, 1));
 
         factory.injectAnnotationProcessorFactories = 
factory.injectAnnotationProcessorFactories = 
Collections.<InjectAnnotationProcessorFactory>singletonList(new 
ValueMapInjector());
-        
factory.adapterImplementations.addClassesAsAdapterAndImplementation(SimplePropertyModel.class,
 ArrayWrappersModel.class, ResourceModelWithRequiredField.class, 
ChildValueMapModel.class, ArrayPrimitivesModel.class, ChildResourceModel.class, 
ResourceModelWithRequiredFieldOptionalStrategy.class, ParentModel.class, 
ChildModel.class, ListModel.class);
+        
factory.adapterImplementations.addClassesAsAdapterAndImplementation(SimplePropertyModel.class,
+                ArrayWrappersModel.class,
+                ResourceModelWithRequiredField.class,
+                ChildValueMapModel.class,
+                ArrayPrimitivesModel.class,
+                ChildResourceModel.class,
+                ResourceModelWithRequiredFieldOptionalStrategy.class,
+                ParentModel.class,
+                ChildModel.class,
+                ListModel.class,
+                ListDefaultsModel.class,
+                CollectionDefaultsModel.class);
     }
 
     @Test
@@ -165,6 +178,43 @@ public class ResourceModelClassesTest {
 
         assertEquals(2, model.getStringList().size());
         assertEquals("hello", model.getStringList().get(0));
+
+        assertNull(model.getEmptyStringList());
+    }
+
+    @Test
+    public void testListDefaultsModel() {
+        Map<String, Object> map = new HashMap<>();
+
+        ValueMap vm = new ValueMapDecorator(map);
+        Resource res = mock(Resource.class);
+        when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+
+        ListDefaultsModel model = factory.getAdapter(res, 
ListDefaultsModel.class);
+        assertNotNull(model);
+
+        assertEquals(Arrays.asList("v1", "v2"), model.getStringList());
+        assertEquals(Arrays.asList(1,2,3), model.getIntList());
+        assertEquals(Arrays.asList(1L,2L), model.getLongList());
+        assertEquals(Arrays.asList(true,false), model.getBooleanList());
+        assertEquals(Arrays.asList((short)1), model.getShortList());
+        assertEquals(Arrays.asList(1.1f,1.2f), model.getFloatList());
+        assertEquals(Arrays.asList(1.1d,1.2d,1.3d), model.getDoubleList());
+    }
+
+    @Test
+    public void testCollectionDefaultsModel() {
+        Map<String, Object> map = new HashMap<>();
+
+        ValueMap vm = new ValueMapDecorator(map);
+        Resource res = mock(Resource.class);
+        when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+
+        CollectionDefaultsModel model = factory.getAdapter(res, 
CollectionDefaultsModel.class);
+        assertNotNull(model);
+
+        assertEquals(Arrays.asList(1,2,3), model.getIntCollection());
+        assertEquals(Arrays.asList("v1", "v2"), model.getStringCollection());
     }
 
     @SuppressWarnings({ "unused", "null" })
diff --git 
a/src/test/java/org/apache/sling/models/testmodels/classes/ListModel.java 
b/src/test/java/org/apache/sling/models/testmodels/classes/CollectionDefaultsModel.java
similarity index 74%
copy from 
src/test/java/org/apache/sling/models/testmodels/classes/ListModel.java
copy to 
src/test/java/org/apache/sling/models/testmodels/classes/CollectionDefaultsModel.java
index b2ec3aa..666f1c1 100644
--- a/src/test/java/org/apache/sling/models/testmodels/classes/ListModel.java
+++ 
b/src/test/java/org/apache/sling/models/testmodels/classes/CollectionDefaultsModel.java
@@ -16,26 +16,31 @@
  */
 package org.apache.sling.models.testmodels.classes;
 
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.models.annotations.Model;
+import java.util.Collection;
 
 import javax.inject.Inject;
-import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Default;
+import org.apache.sling.models.annotations.Model;
 
 @Model(adaptables = Resource.class)
-public class ListModel {
+public class CollectionDefaultsModel {
 
     @Inject
-    private List<Integer> intList;
+    @Default(intValues = {1,2,3})
+    private Collection<Integer> intList;
 
     @Inject
-    private List<String> stringList;
+    @Default(values = {"v1","v2"})
+    private Collection<String> stringList;
 
-    public List<Integer> getIntList() {
+    public Collection<Integer> getIntCollection() {
         return intList;
     }
 
-    public List<String> getStringList() {
+    public Collection<String> getStringCollection() {
         return stringList;
     }
-}
\ No newline at end of file
+
+}
diff --git 
a/src/test/java/org/apache/sling/models/testmodels/classes/ListModel.java 
b/src/test/java/org/apache/sling/models/testmodels/classes/ListDefaultsModel.java
similarity index 57%
copy from 
src/test/java/org/apache/sling/models/testmodels/classes/ListModel.java
copy to 
src/test/java/org/apache/sling/models/testmodels/classes/ListDefaultsModel.java
index b2ec3aa..f4b66e8 100644
--- a/src/test/java/org/apache/sling/models/testmodels/classes/ListModel.java
+++ 
b/src/test/java/org/apache/sling/models/testmodels/classes/ListDefaultsModel.java
@@ -16,26 +16,71 @@
  */
 package org.apache.sling.models.testmodels.classes;
 
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.models.annotations.Model;
+import java.util.List;
 
 import javax.inject.Inject;
-import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Default;
+import org.apache.sling.models.annotations.Model;
 
 @Model(adaptables = Resource.class)
-public class ListModel {
+public class ListDefaultsModel {
 
     @Inject
+    @Default(values = {"v1","v2"})
+    private List<String> stringList;
+
+    @Inject
+    @Default(intValues = {1,2,3})
     private List<Integer> intList;
 
     @Inject
-    private List<String> stringList;
+    @Default(longValues = {1,2})
+    private List<Long> longList;
+
+    @Inject
+    @Default(booleanValues = {true,false})
+    private List<Boolean> booleanList;
+
+    @Inject
+    @Default(shortValues = {1})
+    private List<Short> shortList;
+
+    @Inject
+    @Default(floatValues = {1.1f,1.2f})
+    private List<Float> floatList;
+
+    @Inject
+    @Default(doubleValues = {1.1d,1.2d,1.3d})
+    private List<Double> doubleList;
+
+    public List<String> getStringList() {
+        return stringList;
+    }
 
     public List<Integer> getIntList() {
         return intList;
     }
 
-    public List<String> getStringList() {
-        return stringList;
+    public List<Long> getLongList() {
+        return longList;
     }
-}
\ No newline at end of file
+
+    public List<Boolean> getBooleanList() {
+        return booleanList;
+    }
+
+    public List<Short> getShortList() {
+        return shortList;
+    }
+
+    public List<Float> getFloatList() {
+        return floatList;
+    }
+
+    public List<Double> getDoubleList() {
+        return doubleList;
+    }
+
+}
diff --git 
a/src/test/java/org/apache/sling/models/testmodels/classes/ListModel.java 
b/src/test/java/org/apache/sling/models/testmodels/classes/ListModel.java
index b2ec3aa..564f923 100644
--- a/src/test/java/org/apache/sling/models/testmodels/classes/ListModel.java
+++ b/src/test/java/org/apache/sling/models/testmodels/classes/ListModel.java
@@ -16,11 +16,13 @@
  */
 package org.apache.sling.models.testmodels.classes;
 
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.models.annotations.Model;
+import java.util.List;
 
 import javax.inject.Inject;
-import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Optional;
 
 @Model(adaptables = Resource.class)
 public class ListModel {
@@ -31,6 +33,10 @@ public class ListModel {
     @Inject
     private List<String> stringList;
 
+    @Inject
+    @Optional
+    private List<String> emptyStringList;
+
     public List<Integer> getIntList() {
         return intList;
     }
@@ -38,4 +44,9 @@ public class ListModel {
     public List<String> getStringList() {
         return stringList;
     }
+
+    public List<String> getEmptyStringList() {
+        return emptyStringList;
+    }
+
 }
\ No newline at end of file

Reply via email to