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