Merge pull request #17 from etugarev/improvement/SLING-8706
SLING-8706 - Injections for java.util.Optional<> should be automatically optional
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 b3b90ff..1ecd7f7 100644
--- a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
+++ b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
@@ -19,23 +19,8 @@
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.WeakHashMap;
+import java.lang.reflect.*;
+import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -74,6 +59,7 @@
import org.apache.sling.models.impl.model.InjectableMethod;
import org.apache.sling.models.impl.model.ModelClass;
import org.apache.sling.models.impl.model.ModelClassConstructor;
+import org.apache.sling.models.impl.model.OptionalTypedInjectableElement;
import org.apache.sling.models.spi.AcceptsNullName;
import org.apache.sling.models.spi.DisposalCallback;
import org.apache.sling.models.spi.DisposalCallbackRegistry;
@@ -504,12 +490,54 @@
}
}
+ private class OptionalWrappingCallback implements InjectCallback {
+
+ private final InjectCallback chainedCallback;
+ private final InjectableElement element;
+
+ private OptionalWrappingCallback(InjectCallback chainedCallback, InjectableElement element) {
+ this.chainedCallback = chainedCallback;
+ this.element = element;
+ }
+
+ @Override
+ public RuntimeException inject(InjectableElement element1, Object value) {
+ return chainedCallback.inject(element, value.equals(Optional.empty())
+ ? value // if the value is null it's already represented as Optional.empty(), return as is
+ : Optional.of(value)); // otherwise wrap in Optional
+ }
+ }
+
private
@Nullable
RuntimeException injectElement(final InjectableElement element, final Object adaptable,
final @NotNull DisposalCallbackRegistry registry, final InjectCallback callback,
final @NotNull Map<ValuePreparer, Object> preparedValues,
final @Nullable BundleContext modelContext) {
+ if (element instanceof InjectableField) {
+ Type genericType = ((InjectableField) element).getFieldGenericType();
+
+ if (genericType instanceof ParameterizedType) {
+ ParameterizedType pType = (ParameterizedType) genericType;
+
+ if (pType.getRawType().equals(Optional.class)) {
+ InjectableElement el = new OptionalTypedInjectableElement(element, pType.getActualTypeArguments()[0]);
+ InjectCallback wrappedCallback = new OptionalWrappingCallback(callback, element);
+
+ return injectElementInternal(el, adaptable, registry, wrappedCallback, preparedValues, modelContext);
+ }
+ }
+ }
+
+ return injectElementInternal(element, adaptable, registry, callback, preparedValues, modelContext);
+ }
+
+ private
+ @Nullable
+ RuntimeException injectElementInternal(final InjectableElement element, final Object adaptable,
+ final @NotNull DisposalCallbackRegistry registry, final InjectCallback callback,
+ final @NotNull Map<ValuePreparer, Object> preparedValues,
+ final @Nullable BundleContext modelContext) {
InjectAnnotationProcessor annotationProcessor = null;
String source = element.getSource();
diff --git a/src/main/java/org/apache/sling/models/impl/model/OptionalTypedInjectableElement.java b/src/main/java/org/apache/sling/models/impl/model/OptionalTypedInjectableElement.java
new file mode 100644
index 0000000..ba4f160
--- /dev/null
+++ b/src/main/java/org/apache/sling/models/impl/model/OptionalTypedInjectableElement.java
@@ -0,0 +1,86 @@
+/*
+ * 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.model;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Type;
+import java.util.Optional;
+
+import org.apache.sling.models.annotations.ViaProviderType;
+import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor;
+
+public class OptionalTypedInjectableElement implements InjectableElement {
+
+ private final InjectableElement element;
+ private final Type type;
+
+ public OptionalTypedInjectableElement(InjectableElement element, Type type) {
+ this.element = element;
+ this.type = type;
+ }
+
+ @Override
+ public AnnotatedElement getAnnotatedElement() {
+ return element.getAnnotatedElement();
+ }
+
+ @Override
+ public Type getType() {
+ return type;
+ }
+
+ @Override
+ public boolean isPrimitive() {
+ return element.isPrimitive();
+ }
+
+ @Override
+ public String getName() {
+ return element.getName();
+ }
+
+ @Override
+ public String getSource() {
+ return element.getSource();
+ }
+
+ @Override
+ public String getVia() {
+ return element.getVia();
+ }
+
+ @Override
+ public Class<? extends ViaProviderType> getViaProviderType() {
+ return element.getViaProviderType();
+ }
+
+ @Override
+ public boolean hasDefaultValue() {
+ return element.hasDefaultValue();
+ }
+
+ @Override
+ public Object getDefaultValue() {
+ // Default value injector will be evaluated last, make sure we return a value here so the injection is successful
+ return element.getDefaultValue() == null ? Optional.empty() : element.getDefaultValue();
+ }
+
+ @Override
+ public boolean isOptional(InjectAnnotationProcessor annotationProcessor) {
+ return true;
+ }
+}
diff --git a/src/test/java/org/apache/sling/models/impl/OptionalObjectsTest.java b/src/test/java/org/apache/sling/models/impl/OptionalObjectsTest.java
new file mode 100644
index 0000000..6fd0bfb
--- /dev/null
+++ b/src/test/java/org/apache/sling/models/impl/OptionalObjectsTest.java
@@ -0,0 +1,237 @@
+/*
+ * 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 java.util.*;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.api.wrappers.ValueMapDecorator;
+import org.apache.sling.models.impl.injectors.*;
+import org.apache.sling.models.impl.via.BeanPropertyViaProvider;
+import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessorFactory;
+import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessorFactory2;
+import org.apache.sling.models.testmodels.classes.OptionalObjectsModel;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class OptionalObjectsTest {
+
+ private ModelAdapterFactory factory;
+
+ private OSGiServiceInjector osgiInjector;
+
+ @Mock
+ private BundleContext bundleContext;
+
+ @Mock
+ private SlingHttpServletRequest request;
+
+ @Mock
+ private Logger log;
+
+ @Before
+ public void setup() {
+ factory = AdapterFactoryTest.createModelAdapterFactory();
+
+ osgiInjector = new OSGiServiceInjector();
+ osgiInjector.activate(bundleContext);
+
+ BindingsInjector bindingsInjector = new BindingsInjector();
+ ValueMapInjector valueMapInjector = new ValueMapInjector();
+ ChildResourceInjector childResourceInjector = new ChildResourceInjector();
+ RequestAttributeInjector requestAttributeInjector = new RequestAttributeInjector();
+
+ factory.bindInjector(bindingsInjector,
+ Collections.<String, Object>singletonMap(Constants.SERVICE_ID, 1L));
+ factory.bindInjector(valueMapInjector,
+ Collections.<String, Object>singletonMap(Constants.SERVICE_ID, 2L));
+ factory.bindInjector(childResourceInjector,
+ Collections.<String, Object>singletonMap(Constants.SERVICE_ID, 3L));
+ factory.bindInjector(requestAttributeInjector,
+ Collections.<String, Object>singletonMap(Constants.SERVICE_ID, 4L));
+ factory.bindInjector(osgiInjector, Collections.<String, Object>singletonMap(Constants.SERVICE_ID, 5L));
+
+ factory.bindStaticInjectAnnotationProcessorFactory(bindingsInjector,
+ Collections.<String, Object>singletonMap(Constants.SERVICE_ID, 1L));
+ factory.injectAnnotationProcessorFactories = Collections.<InjectAnnotationProcessorFactory>singletonList(valueMapInjector);
+ factory.injectAnnotationProcessorFactories2 = Collections.<InjectAnnotationProcessorFactory2>singletonList(childResourceInjector);
+ factory.bindStaticInjectAnnotationProcessorFactory(requestAttributeInjector,
+ Collections.<String, Object>singletonMap(Constants.SERVICE_ID, 4L));
+ factory.bindStaticInjectAnnotationProcessorFactory(osgiInjector,
+ Collections.<String, Object>singletonMap(Constants.SERVICE_ID, 5L));
+ factory.bindViaProvider(new BeanPropertyViaProvider(), null);
+
+ SlingBindings bindings = new SlingBindings();
+ bindings.setLog(log);
+ Mockito.when(request.getAttribute(SlingBindings.class.getName())).thenReturn(bindings);
+
+ factory.adapterImplementations.addClassesAsAdapterAndImplementation(OptionalObjectsModel.class);
+
+ }
+
+ @Test
+ public void testFieldInjectionClass() {
+ Map<String, Object> map = new HashMap<>();
+ map.put("optionalString", "foo bar baz");
+ map.put("optionalByte", Byte.valueOf("1"));
+ map.put("optionalInteger", Integer.valueOf("1"));
+ map.put("optionalShort", Short.valueOf("1"));
+ map.put("optionalLong", Long.valueOf("1"));
+ map.put("optionalShort", Short.valueOf("1"));
+ map.put("optionalDouble", Double.valueOf("1"));
+ map.put("optionalFloat", Float.valueOf("1"));
+ map.put("optionalChar", '1');
+ map.put("optionalBoolean", Boolean.valueOf("true"));
+
+ Resource res = mock(Resource.class);
+ when(res.adaptTo(ValueMap.class)).thenReturn(new ValueMapDecorator(map));
+
+ org.apache.sling.models.testmodels.classes.OptionalObjectsModel model = factory.getAdapter(res,
+ OptionalObjectsModel.class);
+ assertNotNull(model);
+
+ assertEquals(Optional.of("foo bar baz"), model.getOptionalString());
+ assertEquals(Optional.empty(), model.getOptionalNullString());
+
+ assertEquals(Optional.of(1), model.getOptionalInteger());
+ assertEquals(Optional.empty(), model.getOptionalNullInteger());
+
+ assertEquals(Optional.of(Byte.valueOf("1")), model.getOptionalByte());
+ assertEquals(Optional.empty(), model.getOptionalNullByte());
+
+ assertEquals(Optional.of(Long.valueOf("1")), model.getOptionalLong());
+ assertEquals(Optional.empty(), model.getOptionalNullLong());
+
+ assertEquals(Optional.of(Short.valueOf("1")), model.getOptionalShort());
+ assertEquals(Optional.empty(), model.getOptionalNullShort());
+
+ assertEquals(Optional.of(Double.valueOf("1")), model.getOptionalDouble());
+ assertEquals(Optional.empty(), model.getOptionalNullDouble());
+
+ assertEquals(Optional.of(Float.valueOf("1")), model.getOptionalFloat());
+ assertEquals(Optional.empty(), model.getOptionalNullFloat());
+
+ assertEquals(Optional.of(1L), model.getOptionalLong());
+ assertEquals(Optional.empty(), model.getOptionalNullLong());
+
+ assertEquals(Optional.of('1'), model.getOptionalChar());
+ assertEquals(Optional.empty(), model.getOptionalNullChar());
+
+ assertEquals(Optional.of(Boolean.valueOf("true")), model.getOptionalBoolean());
+ assertEquals(Optional.empty(), model.getOptionalNullBoolean());
+ }
+
+ @Test
+ public void testFieldInjectionListsAndArrays() {
+ Map<String, Object> map = new HashMap<>();
+
+ map.put("intList", new Integer[]{1, 2, 9, 8});
+ map.put("stringList", new String[]{"hello", "world"});
+ map.put("optionalList", Arrays.asList("foo", "bar", "baz"));
+ map.put("optionalArray", new String[]{"qux", "quux"});
+
+ ValueMap vm = new ValueMapDecorator(map);
+ Resource res = mock(Resource.class);
+ when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+
+ OptionalObjectsModel model = factory.getAdapter(res, OptionalObjectsModel.class);
+ assertNotNull(model);
+
+ assertEquals(4, model.getIntList().get().size());
+ assertEquals(new Integer(2), model.getIntList().get().get(1));
+
+ assertEquals(2, model.getStringList().get().size());
+ assertEquals("hello", model.getStringList().get().get(0));
+
+ assertEquals(Optional.of(Arrays.asList("foo", "bar", "baz")), model.getOptionalList());
+ assertEquals(Optional.empty(), model.getOptionalNullList());
+
+ assertTrue(model.getOptionalArray().isPresent());
+ assertTrue("qux".equalsIgnoreCase(model.getOptionalArray().get()[0]));
+ assertTrue("quux".equalsIgnoreCase(model.getOptionalArray().get()[1]));
+ assertEquals(Optional.empty(), model.getOptionalNullArray());
+ }
+
+ @Test
+ public void testFieldInjectionsChildResource() throws Exception {
+ Resource res = mock(Resource.class);
+ Resource child = mock(Resource.class);
+ when(child.getName()).thenReturn("child");
+ when(res.getChild(eq("child"))).thenReturn(child);
+
+ OptionalObjectsModel model = factory.getAdapter(res, OptionalObjectsModel.class);
+ assertNotNull(model);
+
+ assertEquals(child.getName(), model.getOptionalChild().get().getName());
+ assertEquals(Optional.empty(), model.getOptionalNullChild());
+ }
+
+ @Test
+ public void testFieldInjectionsScriptVariable() throws Exception {
+ SlingBindings bindings = new SlingBindings();
+ SlingScriptHelper helper = mock(SlingScriptHelper.class);
+ bindings.setSling(helper);
+ when(request.getAttribute(SlingBindings.class.getName())).thenReturn(bindings);
+
+ OptionalObjectsModel model = factory.getAdapter(request, OptionalObjectsModel.class);
+ assertNotNull(model);
+ assertEquals(helper, model.getOptionalHelper().get());
+ assertEquals(Optional.empty(), model.getOptionalNullHelper());
+ }
+
+ @Test
+ public void testFieldInjectionsOSGiService() throws InvalidSyntaxException {
+ ServiceReference ref = mock(ServiceReference.class);
+ Logger log = mock(Logger.class);
+ when(bundleContext.getServiceReferences(Logger.class.getName(), null)).thenReturn(
+ new ServiceReference[]{ref});
+ when(bundleContext.getService(ref)).thenReturn(log);
+
+ OptionalObjectsModel model = factory.getAdapter(request, OptionalObjectsModel.class);
+ assertNotNull(model);
+ assertEquals(log, model.getLog().get());
+ }
+
+ @Test
+ public void testFieldInjectionsRequestAttribute() throws InvalidSyntaxException {
+ Object attribute = new Object();
+ when(request.getAttribute("attribute")).thenReturn(attribute);
+
+ OptionalObjectsModel model = factory.getAdapter(request, OptionalObjectsModel.class);
+ assertNotNull(model);
+ assertEquals(attribute, model.getOptionalRequestAttribute().get());
+ assertEquals(Optional.empty(), model.getOptionalNullRequestAttribute());
+ }
+}
diff --git a/src/test/java/org/apache/sling/models/testmodels/classes/OptionalObjectsModel.java b/src/test/java/org/apache/sling/models/testmodels/classes/OptionalObjectsModel.java
new file mode 100644
index 0000000..5d20865
--- /dev/null
+++ b/src/test/java/org/apache/sling/models/testmodels/classes/OptionalObjectsModel.java
@@ -0,0 +1,253 @@
+/*
+ * 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 java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import javax.inject.Inject;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.ChildResource;
+import org.apache.sling.models.annotations.injectorspecific.OSGiService;
+import org.apache.sling.models.annotations.injectorspecific.RequestAttribute;
+import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;
+import org.slf4j.Logger;
+
+@Model(adaptables = {Resource.class, SlingHttpServletRequest.class})
+public class OptionalObjectsModel {
+
+ @Inject
+ private Optional<String> optionalString;
+
+ @Inject
+ private Optional<String> optionalNullString;
+
+ @Inject
+ private Optional<Byte> optionalByte;
+
+ @Inject
+ private Optional<Byte> optionalNullByte;
+
+ @Inject
+ private Optional<Short> optionalShort;
+
+ @Inject
+ private Optional<Short> optionalNullShort;
+
+ @Inject
+ private Optional<Integer> optionalInteger;
+
+ @Inject
+ private Optional<Integer> optionalNullInteger;
+
+ @Inject
+ private Optional<Long> optionalLong;
+
+ @Inject
+ private Optional<Long> optionalNullLong;
+
+ @Inject
+ private Optional<Float> optionalFloat;
+
+ @Inject
+ private Optional<Float> optionalNullFloat;
+
+ @Inject
+ private Optional<Double> optionalDouble;
+
+ @Inject
+ private Optional<Double> optionalNullDouble;
+
+ @Inject
+ private Optional<Character> optionalChar;
+
+ @Inject
+ private Optional<Character> optionalNullChar;
+
+ @Inject
+ private Optional<Boolean> optionalBoolean;
+
+ @Inject
+ private Optional<Boolean> optionalNullBoolean;
+
+ @Inject
+ private Optional<List> optionalList;
+
+ @Inject
+ private Optional<List> optionalNullList;
+
+ @Inject
+ private Optional<String[]> optionalArray;
+
+ @Inject
+ private Optional<String[]> optionalNullArray;
+
+ @Inject
+ private Optional<List<String>> stringList;
+
+ @Inject
+ private Optional<List<Integer>> intList;
+
+ @ChildResource(name = "child")
+ private Optional<Resource> optionalChild;
+
+ @ChildResource
+ private Optional<Resource> optionalNullChild;
+
+ @ScriptVariable(name = "sling")
+ private Optional<SlingScriptHelper> optionalHelper;
+
+ @ScriptVariable(name = "foo")
+ private Optional<SlingScriptHelper> optionalNullHelper;
+
+ @OSGiService
+ private Optional<Logger> log;
+
+ @RequestAttribute(name = "attribute")
+ private Optional<Object> optionalRequestAttribute;
+
+ @RequestAttribute(name = "foo")
+ private Optional<Object> optionalNullRequestAttribute;
+
+ public Optional<String> getOptionalString() {
+ return optionalString;
+ }
+
+ public Optional<String> getOptionalNullString() {
+ return optionalNullString;
+ }
+
+ public Optional<Byte> getOptionalByte() {
+ return optionalByte;
+ }
+
+ public Optional<Byte> getOptionalNullByte() {
+ return optionalNullByte;
+ }
+
+ public Optional<Short> getOptionalShort() {
+ return optionalShort;
+ }
+
+ public Optional<Short> getOptionalNullShort() {
+ return optionalNullShort;
+ }
+
+ public Optional<Integer> getOptionalInteger() {
+ return optionalInteger;
+ }
+
+ public Optional<Integer> getOptionalNullInteger() {
+ return optionalNullInteger;
+ }
+
+ public Optional<Long> getOptionalLong() {
+ return optionalLong;
+ }
+
+ public Optional<Long> getOptionalNullLong() {
+ return optionalNullLong;
+ }
+
+ public Optional<Float> getOptionalFloat() {
+ return optionalFloat;
+ }
+
+ public Optional<Float> getOptionalNullFloat() {
+ return optionalNullFloat;
+ }
+
+ public Optional<Double> getOptionalDouble() {
+ return optionalDouble;
+ }
+
+ public Optional<Double> getOptionalNullDouble() {
+ return optionalNullDouble;
+ }
+
+ public Optional<Character> getOptionalChar() {
+ return optionalChar;
+ }
+
+ public Optional<Character> getOptionalNullChar() {
+ return optionalNullChar;
+ }
+
+ public Optional<Boolean> getOptionalBoolean() {
+ return optionalBoolean;
+ }
+
+ public Optional<Boolean> getOptionalNullBoolean() {
+ return optionalNullBoolean;
+ }
+
+ public Optional<? extends Collection> getOptionalList() {
+ return optionalList;
+ }
+
+ public Optional<? extends Collection> getOptionalNullList() {
+ return optionalNullList;
+ }
+
+ public Optional<String[]> getOptionalArray() {
+ return optionalArray;
+ }
+
+ public Optional<String[]> getOptionalNullArray() {
+ return optionalNullArray;
+ }
+
+ public Optional<List<String>> getStringList() {
+ return stringList;
+ }
+
+ public Optional<List<Integer>> getIntList() {
+ return intList;
+ }
+
+ public Optional<Resource> getOptionalChild() {
+ return optionalChild;
+ }
+
+ public Optional<Resource> getOptionalNullChild() {
+ return optionalNullChild;
+ }
+
+ public Optional<SlingScriptHelper> getOptionalHelper() {
+ return optionalHelper;
+ }
+
+ public Optional<SlingScriptHelper> getOptionalNullHelper() {
+ return optionalNullHelper;
+ }
+
+ public Optional<Logger> getLog() {
+ return log;
+ }
+
+ public Optional<Object> getOptionalRequestAttribute() {
+ return optionalRequestAttribute;
+ }
+
+ public Optional<Object> getOptionalNullRequestAttribute() {
+ return optionalNullRequestAttribute;
+ }
+}