You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:55:37 UTC
[sling-org-apache-sling-models-impl] 07/24: SLING-3863 - adding
initial values for primitives when injecting to fields and constructor
params. Thanks to Stefan Seifert for the original patch!
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to annotated tag org.apache.sling.models.impl-1.1.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-models-impl.git
commit ec0e0a1c7d32441f6e103695f5cee9710dee6df0
Author: Justin Edelson <ju...@apache.org>
AuthorDate: Wed Aug 20 18:42:24 2014 +0000
SLING-3863 - adding initial values for primitives when injecting to fields and constructor params. Thanks to Stefan Seifert for the original patch!
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/models/impl@1619199 13f79535-47bb-0310-9956-ffa450edef68
---
.../sling/models/impl/ModelAdapterFactory.java | 74 ++++++++++++-
.../sling/models/impl/OptionalPrimitivesTest.java | 119 +++++++++++++++++++++
.../classes/OptionalPrimitivesModel.java | 84 +++++++++++++++
.../OptionalPrimitivesModel.java | 89 +++++++++++++++
.../interfaces/OptionalPrimitivesModel.java | 52 +++++++++
5 files changed, 415 insertions(+), 3 deletions(-)
diff --git a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
index b77cce1..a81cc31 100644
--- a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
+++ b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
@@ -249,6 +249,8 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable {
* @return true if injection was successful otherwise false
*/
public boolean inject(AnnotatedElement element, Object value);
+
+ public boolean shouldInjectPrimitiveInitValue();
}
private static class SetFieldCallback implements InjectCallback {
@@ -263,6 +265,11 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable {
public boolean inject(AnnotatedElement element, Object value) {
return setField((Field) element, object, value);
}
+
+ @Override
+ public boolean shouldInjectPrimitiveInitValue() {
+ return false;
+ }
}
private static class SetMethodsCallback implements InjectCallback {
@@ -277,6 +284,11 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable {
public boolean inject(AnnotatedElement element, Object value) {
return setMethod((Method) element, methods, value);
}
+
+ @Override
+ public boolean shouldInjectPrimitiveInitValue() {
+ return true;
+ }
}
private static class SetConstructorParameterCallback implements InjectCallback {
@@ -291,6 +303,11 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable {
public boolean inject(AnnotatedElement element, Object value) {
return setConstructorParameter((ConstructorParameter)element, parameterValues, value);
}
+
+ @Override
+ public boolean shouldInjectPrimitiveInitValue() {
+ return true;
+ }
}
private boolean injectElement(final AnnotatedElement element, final Object adaptable, final Type type,
@@ -331,9 +348,16 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable {
}
// if default is not set, check if mandatory
- if (!wasInjectionSuccessful && !isOptional(element, modelAnnotation, annotationProcessor)) {
- return false;
+ if (!wasInjectionSuccessful) {
+ if (isOptional(element, modelAnnotation, annotationProcessor)) {
+ if (callback.shouldInjectPrimitiveInitValue()) {
+ injectPrimitiveInitialValue(element, type, callback);
+ }
+ } else {
+ return false;
+ }
}
+
return true;
}
@@ -613,6 +637,39 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable {
return callback.inject(point, value);
}
+ /**
+ * Injects the default initial value for the given primitive class which
+ * cannot be null (e.g. int = 0, boolean = false).
+ *
+ * @param point Annotated element
+ * @param wrapperType Non-primitive wrapper class for primitive class
+ * @param callback Inject callback
+ */
+ private void injectPrimitiveInitialValue(AnnotatedElement point, Type wrapperType, InjectCallback callback) {
+ Type primitiveType = mapWrapperClasses(wrapperType);
+ Object value = null;
+ if (primitiveType == int.class) {
+ value = Integer.valueOf(0);
+ } else if (primitiveType == long.class) {
+ value = Long.valueOf(0);
+ } else if (primitiveType == boolean.class) {
+ value = Boolean.FALSE;
+ } else if (primitiveType == double.class) {
+ value = Double.valueOf(0);
+ } else if (primitiveType == float.class) {
+ value = Float.valueOf(0);
+ } else if (primitiveType == short.class) {
+ value = Short.valueOf((short) 0);
+ } else if (primitiveType == byte.class) {
+ value = Byte.valueOf((byte) 0);
+ } else if (primitiveType == char.class) {
+ value = Character.valueOf('\u0000');
+ }
+ if (value != null) {
+ callback.inject(point, value);
+ };
+ }
+
private Object getAdaptable(Object adaptable, AnnotatedElement point, InjectAnnotationProcessor processor) {
String viaPropertyName = null;
if (processor != null) {
@@ -701,7 +758,7 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable {
}
}
- private Type mapPrimitiveClasses(Type type) {
+ private static Type mapPrimitiveClasses(Type type) {
if (type instanceof Class<?>) {
return ClassUtils.primitiveToWrapper((Class<?>) type);
} else {
@@ -709,6 +766,14 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable {
}
}
+ private static Type mapWrapperClasses(Type type) {
+ if (type instanceof Class<?>) {
+ return ClassUtils.wrapperToPrimitive((Class<?>) type);
+ } else {
+ return type;
+ }
+ }
+
private static boolean setField(Field field, Object createdObject, Object value) {
if (value != null) {
if (!isAcceptableType(field.getType(), field.getGenericType(), value)) {
@@ -831,6 +896,9 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable {
if (type == Short.TYPE) {
return Short.class.isInstance(value);
}
+ if (type == Byte.TYPE) {
+ return Byte.class.isInstance(value);
+ }
if (type == Character.TYPE) {
return Character.class.isInstance(value);
}
diff --git a/src/test/java/org/apache/sling/models/impl/OptionalPrimitivesTest.java b/src/test/java/org/apache/sling/models/impl/OptionalPrimitivesTest.java
new file mode 100644
index 0000000..7e7637a
--- /dev/null
+++ b/src/test/java/org/apache/sling/models/impl/OptionalPrimitivesTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.models.impl.injectors.ChildResourceInjector;
+import org.apache.sling.models.impl.injectors.ValueMapInjector;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * Validates that @Optional annotations works with primitive values which do not support null
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class OptionalPrimitivesTest {
+
+ @Mock
+ private ComponentContext componentCtx;
+
+ @Mock
+ private BundleContext bundleContext;
+
+ private ModelAdapterFactory factory;
+
+ @Before
+ public void setup() {
+ when(componentCtx.getBundleContext()).thenReturn(bundleContext);
+ factory = new ModelAdapterFactory();
+ factory.activate(componentCtx);
+ factory.bindInjector(new ValueMapInjector(), new ServicePropertiesMap(2, 2));
+ factory.bindInjector(new ChildResourceInjector(), new ServicePropertiesMap(1, 1));
+ }
+
+ @Test
+ public void testFieldInjectionClass() {
+ ValueMap vm = ValueMap.EMPTY;
+
+ Resource res = mock(Resource.class);
+ when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+
+ org.apache.sling.models.testmodels.classes.OptionalPrimitivesModel model
+ = factory.getAdapter(res, org.apache.sling.models.testmodels.classes.OptionalPrimitivesModel.class);
+ assertNotNull(model);
+ assertEquals(0, model.getByteValue());
+ assertEquals(0, model.getShortValue());
+ assertEquals(0, model.getIntValue());
+ assertEquals(0L, model.getLongValue());
+ assertEquals(0.0f, model.getFloatValue(), 0.00001d);
+ assertEquals(0.0d, model.getDoubleValue(), 0.00001d);
+ assertEquals('\u0000', model.getCharValue());
+ assertEquals(false, model.getBooleanValue());
+ }
+
+ @Test
+ public void testConstructorInjection() {
+ ValueMap vm = ValueMap.EMPTY;
+
+ Resource res = mock(Resource.class);
+ when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+
+ org.apache.sling.models.testmodels.classes.constructorinjection.OptionalPrimitivesModel model
+ = factory.getAdapter(res, org.apache.sling.models.testmodels.classes.constructorinjection.OptionalPrimitivesModel.class);
+ assertNotNull(model);
+ assertEquals(0, model.getByteValue());
+ assertEquals(0, model.getShortValue());
+ assertEquals(0, model.getIntValue());
+ assertEquals(0L, model.getLongValue());
+ assertEquals(0.0f, model.getFloatValue(), 0.00001d);
+ assertEquals(0.0d, model.getDoubleValue(), 0.00001d);
+ assertEquals('\u0000', model.getCharValue());
+ assertEquals(false, model.getBooleanValue());
+ }
+
+ @Test
+ public void testFieldInjectionInterface() {
+ ValueMap vm = ValueMap.EMPTY;
+
+ Resource res = mock(Resource.class);
+ when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+
+ org.apache.sling.models.testmodels.interfaces.OptionalPrimitivesModel model
+ = factory.getAdapter(res, org.apache.sling.models.testmodels.interfaces.OptionalPrimitivesModel.class);
+ assertNotNull(model);
+ assertEquals(0, model.getByteValue());
+ assertEquals(0, model.getShortValue());
+ assertEquals(0, model.getIntValue());
+ assertEquals(0L, model.getLongValue());
+ assertEquals(0.0f, model.getFloatValue(), 0.00001d);
+ assertEquals(0.0d, model.getDoubleValue(), 0.00001d);
+ assertEquals('\u0000', model.getCharValue());
+ assertEquals(false, model.getBooleanValue());
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/models/testmodels/classes/OptionalPrimitivesModel.java b/src/test/java/org/apache/sling/models/testmodels/classes/OptionalPrimitivesModel.java
new file mode 100644
index 0000000..f97afa9
--- /dev/null
+++ b/src/test/java/org/apache/sling/models/testmodels/classes/OptionalPrimitivesModel.java
@@ -0,0 +1,84 @@
+/*
+ * 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 javax.inject.Inject;
+
+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 OptionalPrimitivesModel {
+
+ @Inject @Optional
+ private byte byteValue;
+
+ @Inject @Optional
+ private short shortValue;
+
+ @Inject @Optional
+ private int intValue;
+
+ @Inject @Optional
+ private long longValue;
+
+ @Inject @Optional
+ private float floatValue;
+
+ @Inject @Optional
+ private double doubleValue;
+
+ @Inject @Optional
+ private char charValue;
+
+ @Inject @Optional
+ private boolean booleanValue;
+
+ public byte getByteValue() {
+ return this.byteValue;
+ }
+
+ public short getShortValue() {
+ return this.shortValue;
+ }
+
+ public int getIntValue() {
+ return this.intValue;
+ }
+
+ public long getLongValue() {
+ return this.longValue;
+ }
+
+ public float getFloatValue() {
+ return this.floatValue;
+ }
+
+ public double getDoubleValue() {
+ return this.doubleValue;
+ }
+
+ public char getCharValue() {
+ return this.charValue;
+ }
+
+ public boolean getBooleanValue() {
+ return this.booleanValue;
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/OptionalPrimitivesModel.java b/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/OptionalPrimitivesModel.java
new file mode 100644
index 0000000..c6f51c2
--- /dev/null
+++ b/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/OptionalPrimitivesModel.java
@@ -0,0 +1,89 @@
+/*
+ * 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.constructorinjection;
+
+import javax.inject.Inject;
+
+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 OptionalPrimitivesModel {
+
+ private final byte byteValue;
+ private final short shortValue;
+ private final int intValue;
+ private final long longValue;
+ private final float floatValue;
+ private final double doubleValue;
+ private final char charValue;
+ private final boolean booleanValue;
+
+ @Inject
+ public OptionalPrimitivesModel(
+ @Optional byte byteValue,
+ @Optional short shortValue,
+ @Optional int intValue,
+ @Optional long longValue,
+ @Optional float floatValue,
+ @Optional double doubleValue,
+ @Optional char charValue,
+ @Optional boolean booleanValue) {
+ this.byteValue = byteValue;
+ this.shortValue = shortValue;
+ this.intValue = intValue;
+ this.longValue = longValue;
+ this.floatValue = floatValue;
+ this.doubleValue = doubleValue;
+ this.charValue = charValue;
+ this.booleanValue = booleanValue;
+ }
+
+ public byte getByteValue() {
+ return this.byteValue;
+ }
+
+ public short getShortValue() {
+ return this.shortValue;
+ }
+
+ public int getIntValue() {
+ return this.intValue;
+ }
+
+ public long getLongValue() {
+ return this.longValue;
+ }
+
+ public float getFloatValue() {
+ return this.floatValue;
+ }
+
+ public double getDoubleValue() {
+ return this.doubleValue;
+ }
+
+ public char getCharValue() {
+ return this.charValue;
+ }
+
+ public boolean getBooleanValue() {
+ return this.booleanValue;
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/models/testmodels/interfaces/OptionalPrimitivesModel.java b/src/test/java/org/apache/sling/models/testmodels/interfaces/OptionalPrimitivesModel.java
new file mode 100644
index 0000000..8f8ed54
--- /dev/null
+++ b/src/test/java/org/apache/sling/models/testmodels/interfaces/OptionalPrimitivesModel.java
@@ -0,0 +1,52 @@
+/*
+ * 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.interfaces;
+
+import javax.inject.Inject;
+
+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 interface OptionalPrimitivesModel {
+
+ @Inject @Optional
+ public byte getByteValue();
+
+ @Inject @Optional
+ public short getShortValue();
+
+ @Inject @Optional
+ public int getIntValue();
+
+ @Inject @Optional
+ public long getLongValue();
+
+ @Inject @Optional
+ public float getFloatValue();
+
+ @Inject @Optional
+ public double getDoubleValue();
+
+ @Inject @Optional
+ public char getCharValue();
+
+ @Inject @Optional
+ public boolean getBooleanValue();
+
+}
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.