You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2015/01/24 00:05:14 UTC

svn commit: r1654430 - in /sling/trunk/bundles/extensions/models: api/src/main/java/org/apache/sling/models/annotations/ api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ impl/src/main/java/org/apache/sling/models/impl/injectors/ ...

Author: sseifert
Date: Fri Jan 23 23:05:13 2015
New Revision: 1654430

URL: http://svn.apache.org/r1654430
Log:
SLING-4212 Sling Models: Allow multiple values from ValueMap in the resource-path injector (applied patch by santiago garcĂ­a pimentel with some modifications)

Added:
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathPartialModel.java   (with props)
Modified:
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Path.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ResourcePath.java
    sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/AbstractInjector.java
    sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ChildResourceInjector.java
    sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ResourcePathInjector.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourcePathInjectionTest.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathAllOptionalModel.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathModel.java

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Path.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Path.java?rev=1654430&r1=1654429&r2=1654430&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Path.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Path.java Fri Jan 23 23:05:13 2015
@@ -24,7 +24,7 @@ import java.lang.annotation.Target;
 import javax.inject.Qualifier;
 
 /**
- * Provide a path on an @Inject. Not necessarily tied to the Resource Path injector (thus no
+ * Provide path(s) on an @Inject. Not necessarily tied to the Resource Path injector (thus no
  * @Source annotation), may be reused for other injector types.
  */
 @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@@ -32,6 +32,7 @@ import javax.inject.Qualifier;
 @Qualifier
 public @interface Path {
 
-    public String value();
+    public String value() default "";
+    public String[] paths() default {};
 
 }

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ResourcePath.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ResourcePath.java?rev=1654430&r1=1654429&r2=1654430&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ResourcePath.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ResourcePath.java Fri Jan 23 23:05:13 2015
@@ -29,7 +29,7 @@ import org.apache.sling.models.spi.injec
 
 /**
  * Annotation to be used on either methods, fields or constructor parameters to let Sling Models inject a
- * resource by path. The path may be either in the path attribute or in a value map property with the given name.
+ * resource by path(s). The path may be either in the path/paths attribute or in a value map property with the given name.
  */
 @Target({ METHOD, FIELD, PARAMETER })
 @Retention(RUNTIME)
@@ -41,6 +41,11 @@ public @interface ResourcePath {
      * Specifies the path of the resource. If not provided, the path is derived from the property name.
      */
     public String path() default "";
+    
+    /**
+     * Specifies more than one path for the resource. If not provided, a single path is derived from the property name.
+     */
+    public String[] paths() default {};
 
     /**
      * Specifies the name of the property containing the resource path. If empty or not set, then the name

Modified: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/AbstractInjector.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/AbstractInjector.java?rev=1654430&r1=1654429&r2=1654430&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/AbstractInjector.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/AbstractInjector.java Fri Jan 23 23:05:13 2015
@@ -18,6 +18,11 @@
  */
 package org.apache.sling.models.impl.injectors;
 
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.List;
+
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.adapter.Adaptable;
 import org.apache.sling.api.resource.Resource;
@@ -49,5 +54,16 @@ abstract class AbstractInjector {
             return null;
         }
     }
+    
+    protected boolean isDeclaredTypeCollection(Type declaredType) {
+        boolean isCollection = false;
+        if (declaredType instanceof ParameterizedType) {
+            ParameterizedType type = (ParameterizedType) declaredType;
+            Class<?> collectionType = (Class<?>) type.getRawType();
+            isCollection = collectionType.equals(Collection.class)
+                    || collectionType.equals(List.class);
+        }
+        return isCollection;
+    }
 
 }

Modified: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ChildResourceInjector.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ChildResourceInjector.java?rev=1654430&r1=1654429&r2=1654430&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ChildResourceInjector.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ChildResourceInjector.java Fri Jan 23 23:05:13 2015
@@ -20,7 +20,6 @@ import java.lang.reflect.AnnotatedElemen
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
@@ -42,7 +41,7 @@ import org.osgi.framework.Constants;
 @Component
 @Service
 @Property(name = Constants.SERVICE_RANKING, intValue = 3000)
-public class ChildResourceInjector implements Injector, InjectAnnotationProcessorFactory2 {
+public class ChildResourceInjector extends AbstractInjector implements Injector, InjectAnnotationProcessorFactory2 {
 
     @Override
     public String getName() {
@@ -91,16 +90,6 @@ public class ChildResourceInjector imple
        return null;
    }
 
-    private boolean isDeclaredTypeCollection(Type declaredType) {
-       boolean isCollection = false;
-       if (declaredType instanceof ParameterizedType) {
-           ParameterizedType type = (ParameterizedType) declaredType;
-           Class<?> collectionType = (Class<?>) type.getRawType();
-           isCollection = collectionType.equals(Collection.class)
-                   || collectionType.equals(List.class);
-       }
-       return isCollection;
-   }
 
     @Override
     public InjectAnnotationProcessor2 createAnnotationProcessor(Object adaptable, AnnotatedElement element) {

Modified: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ResourcePathInjector.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ResourcePathInjector.java?rev=1654430&r1=1654429&r2=1654430&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ResourcePathInjector.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/ResourcePathInjector.java Fri Jan 23 23:05:13 2015
@@ -20,10 +20,15 @@ package org.apache.sling.models.impl.inj
 
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
 
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.models.annotations.Path;
@@ -36,6 +41,8 @@ import org.apache.sling.models.spi.injec
 import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor2;
 import org.apache.sling.models.spi.injectorspecific.StaticInjectAnnotationProcessorFactory;
 import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @Component
 @Service
@@ -43,6 +50,8 @@ import org.osgi.framework.Constants;
 public class ResourcePathInjector extends AbstractInjector implements Injector, AcceptsNullName,
         StaticInjectAnnotationProcessorFactory {
 
+    private static final Logger LOG = LoggerFactory.getLogger(ResourcePathInjector.class);
+
     @Override
     public String getName() {
         return "resource-path";
@@ -51,36 +60,92 @@ public class ResourcePathInjector extend
     @Override
     public Object getValue(Object adaptable, String name, Type declaredType, AnnotatedElement element,
             DisposalCallbackRegistry callbackRegistry) {
-        String resourcePath = null;
+        String[] resourcePaths = null;
         Path pathAnnotation = element.getAnnotation(Path.class);
+        ResourcePath resourcePathAnnotation = element.getAnnotation(ResourcePath.class);
         if (pathAnnotation != null) {
-            resourcePath = pathAnnotation.value();
-        } else {
-            ResourcePath resourcePathAnnotation = element.getAnnotation(ResourcePath.class);
-            if (resourcePathAnnotation != null) {
-                resourcePath = resourcePathAnnotation.path();
-                if (resourcePath.isEmpty()) {
-                    resourcePath = null;
-                }
+            resourcePaths = getPathsFromAnnotation(pathAnnotation);
+        } else if (resourcePathAnnotation != null) {
+            resourcePaths = getPathsFromAnnotation(resourcePathAnnotation);
+        }
+        if (ArrayUtils.isEmpty(resourcePaths) && name != null) {
+            // try the valuemap
+            ValueMap map = getValueMap(adaptable);
+            if (map != null) {
+                resourcePaths = map.get(name, String[].class);
             }
+        }
+        if (ArrayUtils.isEmpty(resourcePaths)) {
+            // could not find a path to inject
+            return null;
+        }
 
-            if (resourcePath == null && name != null) {
-                // try to get from value map
-                ValueMap map = getValueMap(adaptable);
-                if (map != null) {
-                    resourcePath = map.get(name, String.class);
-                }
-            }
+        ResourceResolver resolver = getResourceResolver(adaptable);
+        if (resolver == null) {
+            return null;
         }
+        List<Resource> resources = getResources(resolver, resourcePaths, name);
 
-        if (resourcePath != null) {
-            ResourceResolver resolver = getResourceResolver(adaptable);
-            if (resolver != null) {
-                return resolver.getResource(resourcePath);
+        if (resources == null || resources.isEmpty()) {
+            return null;
+        }
+        // unwrap if necessary
+        if (isDeclaredTypeCollection(declaredType)) {
+            return resources;
+        } else if (resources.size() == 1) {
+            return resources.get(0);
+        } else {
+            // multiple resources to inject, but field is not a list
+            LOG.warn("Cannot inject multiple resources into field {} since it is not declared as a list", name);
+            return null;
+        }
+
+    }
+
+    private List<Resource> getResources(ResourceResolver resolver, String[] paths, String fieldName) {
+        List<Resource> resources = new ArrayList<Resource>();
+        for (String path : paths) {
+            Resource resource = resolver.getResource(path);
+            if (resource != null) {
+                resources.add(resource);
+            } else {
+                LOG.warn("Could not retrieve resource at path {} for field {}. Since it is required it won't be injected.",
+                        path, fieldName);
+                // all resources should've been injected. we stop
+                return null;
             }
         }
+        return resources;
+    }
 
-        return null;
+    /**
+     * Obtains the paths from the annotations
+     * @param annotation
+     * @return
+     */
+    private String[] getPathsFromAnnotation(Path pathAnnotation) {
+        String[] resourcePaths = null;
+        if (StringUtils.isNotEmpty(pathAnnotation.value())) {
+            resourcePaths = new String[] { pathAnnotation.value() };
+        } else {
+            resourcePaths = pathAnnotation.paths();
+        }
+        return resourcePaths;
+    }
+
+    /**
+     * Obtains the paths from the annotations
+     * @param annotation
+     * @return
+     */
+    private String[] getPathsFromAnnotation(ResourcePath resourcePathAnnotation) {
+        String[] resourcePaths = null;
+        if (StringUtils.isNotEmpty(resourcePathAnnotation.path())) {
+            resourcePaths = new String[] { resourcePathAnnotation.path() };
+        } else {
+            resourcePaths = resourcePathAnnotation.paths();
+        }
+        return resourcePaths;
     }
 
     @Override
@@ -103,8 +168,8 @@ public class ResourcePathInjector extend
 
         @Override
         public String getName() {
-            // since null is not allowed as default value in annotations, the empty string means, the default should be
-            // used!
+            // since null is not allowed as default value in annotations, the
+            // empty string means, the default should be used!
             if (annotation.name().isEmpty()) {
                 return null;
             }

Modified: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourcePathInjectionTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourcePathInjectionTest.java?rev=1654430&r1=1654429&r2=1654430&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourcePathInjectionTest.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourcePathInjectionTest.java Fri Jan 23 23:05:13 2015
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.*;
 
 import java.util.HashMap;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.sling.api.SlingHttpServletRequest;
@@ -35,6 +36,7 @@ import org.apache.sling.models.impl.inje
 import org.apache.sling.models.impl.injectors.ValueMapInjector;
 import org.apache.sling.models.testmodels.classes.ResourcePathAllOptionalModel;
 import org.apache.sling.models.testmodels.classes.ResourcePathModel;
+import org.apache.sling.models.testmodels.classes.ResourcePathPartialModel;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -56,6 +58,9 @@ public class ResourcePathInjectionTest {
 
     @Mock
     private Resource adaptable;
+    
+    @Mock
+    SlingHttpServletRequest nonResourceAdaptable;
 
     @Mock
     private Resource byPathResource;
@@ -77,6 +82,16 @@ public class ResourcePathInjectionTest {
         Map<String, Object> map = new HashMap<String, Object>();
         map.put("propertyContainingAPath", "/some/other/path");
         map.put("anotherPropertyContainingAPath", "/some/other/path2");
+        String[] paths= new String[2];
+        paths[0]="/some/other/path";
+        paths[1]="/some/other/path2";
+       
+        String[] invalidPaths= new String[3];
+        invalidPaths[0]="/does/not/exist";
+        invalidPaths[1]="/does/not/exist2";
+        invalidPaths[2]="/some/other/path";
+        map.put("propertyWithSeveralPaths",paths);
+        map.put("propertyWithMissingPaths", invalidPaths);
 
         ValueMap properties = new ValueMapDecorator(map);
 
@@ -111,7 +126,6 @@ public class ResourcePathInjectionTest {
 
     @Test
     public void testPathInjectionWithNonResourceAdaptable() {
-        SlingHttpServletRequest nonResourceAdaptable = mock(SlingHttpServletRequest.class);
         ResourcePathModel model = factory.getAdapter(nonResourceAdaptable, ResourcePathModel.class);
         // should be null because mandatory fields could not be injected
         assertNull(model);
@@ -119,7 +133,6 @@ public class ResourcePathInjectionTest {
 
     @Test
     public void testOptionalPathInjectionWithNonResourceAdaptable() {
-        SlingHttpServletRequest nonResourceAdaptable = mock(SlingHttpServletRequest.class);
         ResourcePathAllOptionalModel model = factory.getAdapter(nonResourceAdaptable, ResourcePathAllOptionalModel.class);
         // should not be null because resource paths fields are optional
         assertNotNull(model);
@@ -128,6 +141,47 @@ public class ResourcePathInjectionTest {
         assertNull(model.getByDerefProperty());
         assertNull(model.getFromPath2());
         assertNull(model.getByDerefProperty2());
-   }
+    }
+
+    @Test
+    public void testMultiplePathInjection() {
+        ResourcePathModel model = factory.getAdapter(adaptable, ResourcePathModel.class);
+        assertNotNull(model);
+        List<Resource> resources=model.getMultipleResources();
+        assertNotNull(resources);
+        assertEquals(2,resources.size());
+        assertEquals(byPropertyValueResource, resources.get(0));
+        assertEquals(byPropertyValueResource2, resources.get(1));
+        List<Resource> resourcesFromPathAnnotation= model.getManyFromPath();
+        assertNotNull(resourcesFromPathAnnotation);
+        assertEquals(byPathResource, resourcesFromPathAnnotation.get(0));
+        assertEquals(byPathResource2, resourcesFromPathAnnotation.get(1));
+        
+        List<Resource> resourcesFromResourcePathAnnotation= model.getManyFromPath2();
+        assertNotNull(resourcesFromResourcePathAnnotation);
+        assertEquals(byPathResource2, resourcesFromResourcePathAnnotation.get(0));
+        assertEquals(byPathResource, resourcesFromResourcePathAnnotation.get(1));
+        
+        assertNotNull(model.getPropertyWithSeveralPaths());
+        assertEquals(byPropertyValueResource, model.getPropertyWithSeveralPaths().get(0));
+        assertEquals(byPropertyValueResource2, model.getPropertyWithSeveralPaths().get(1));
+    }
+ 
+    @Test
+    public void testPartialInjectionFailure1() {
+        when(resourceResolver.getResource("/some/other/path")).thenReturn(null);
+        
+        ResourcePathPartialModel model = factory.getAdapter(adaptable, ResourcePathPartialModel.class);
+        assertNull(model);
+    }
+
+    @Test
+    public void testPartialInjectionFailure2() {       
+        when(resourceResolver.getResource("/some/other/path")).thenReturn(null);
+        when(resourceResolver.getResource("/some/other/path2")).thenReturn(null);
+        
+        ResourcePathPartialModel model = factory.getAdapter(adaptable, ResourcePathPartialModel.class);
+        assertNull(model);
+    }
 
 }
\ No newline at end of file

Modified: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathAllOptionalModel.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathAllOptionalModel.java?rev=1654430&r1=1654429&r2=1654430&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathAllOptionalModel.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathAllOptionalModel.java Fri Jan 23 23:05:13 2015
@@ -40,6 +40,11 @@ public class ResourcePathAllOptionalMode
     @Named("propertyContainingAPath")
     @Optional
     private Resource derefProperty;
+    
+    @Inject
+    @Path(paths={"/some/path", "/some/path2"})
+    @Optional
+    private Resource manyFromPathNonList;
 
     @ResourcePath(path = "/some/path2", optional=true)
     private Resource fromPath2;

Modified: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathModel.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathModel.java?rev=1654430&r1=1654429&r2=1654430&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathModel.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathModel.java Fri Jan 23 23:05:13 2015
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.models.testmodels.classes;
 
+import java.util.List;
+
 import javax.inject.Inject;
 import javax.inject.Named;
 
@@ -37,9 +39,22 @@ public class ResourcePathModel {
     @Inject
     @Named("propertyContainingAPath")
     private Resource derefProperty;
+    
+    @Inject
+    @Path(paths={"/some/path", "/some/path2"})
+    private List<Resource> manyFromPath;
+    
+    @ResourcePath(paths={"/some/path2","/some/path"})
+    private List<Resource> manyFromPath2;
 
     @ResourcePath(path = "/some/path2")
     private Resource fromPath2;
+    
+    @ResourcePath(name="propertyWithSeveralPaths")
+    private List<Resource> multipleResources;
+    
+    @ResourcePath
+    private List<Resource> propertyWithSeveralPaths;
 
     @ResourcePath(name = "anotherPropertyContainingAPath")
     private Resource derefProperty2;
@@ -59,5 +74,20 @@ public class ResourcePathModel {
     public Resource getByDerefProperty2() {
         return derefProperty2;
     }
+    
+    public List<Resource> getMultipleResources(){
+    	return this.multipleResources;
+    }
+    
+    public List<Resource> getManyFromPath(){
+        return this.manyFromPath;
+    }
+    
+    public List<Resource> getManyFromPath2(){
+        return this.manyFromPath2;
+    }
 
+    public List<Resource> getPropertyWithSeveralPaths(){
+        return this.propertyWithSeveralPaths;
+    }
 }

Added: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathPartialModel.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathPartialModel.java?rev=1654430&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathPartialModel.java (added)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathPartialModel.java Fri Jan 23 23:05:13 2015
@@ -0,0 +1,72 @@
+/*
+ * 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.List;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Optional;
+import org.apache.sling.models.annotations.Required;
+import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
+import org.apache.sling.models.annotations.injectorspecific.ResourcePath;
+
+@Model(adaptables = {Resource.class, SlingHttpServletRequest.class})
+public class ResourcePathPartialModel {
+    
+    @ResourcePath(name="propertyWithSeveralPaths", injectionStrategy=InjectionStrategy.REQUIRED)
+    private List<Resource> requiredResources;
+    
+    @ResourcePath(name="propertyWithSeveralPaths")
+    @Required
+    private List<Resource> requiredResources2;
+    
+    
+    @ResourcePath(name="propertyWithMissingPaths", injectionStrategy=InjectionStrategy.OPTIONAL)
+    private List<Resource> optionalResources;
+    
+    @Optional
+    @ResourcePath(name="propertyWithMissingPaths")
+    private List<Resource> optionalResources2;
+    
+    @ResourcePath(name="propertyWithMissingPaths", optional=true)
+    private List<Resource> optionalResources3;
+
+    public List<Resource> getRequiredResources() {
+        return requiredResources;
+    }
+
+    public List<Resource> getRequiredResources2() {
+        return requiredResources2;
+    }
+
+    public List<Resource> getOptionalResources() {
+        return optionalResources;
+    }
+
+    public List<Resource> getOptionalResources2() {
+        return optionalResources2;
+    }
+
+    public List<Resource> getOptionalResources3() {
+        return optionalResources3;
+    }
+
+}

Propchange: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathPartialModel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathPartialModel.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Fri Jan 23 23:05:13 2015
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathPartialModel.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain