Author: kwin
Date: Fri Mar  3 15:59:06 2017
New Revision: 1785330

URL: http://svn.apache.org/viewvc?rev=1785330&view=rev
Log:
SLLING-6600 allow multivalue parameters for a validator

Modified:
    sling/trunk/bundles/extensions/validation/core/pom.xml
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ResourcePropertyBuilder.java
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ResourcePropertyImpl.java
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ValidationModelImpl.java
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/resourcemodel/ResourceValidationModelProviderImpl.java
    
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/resourcemodel/ResourceValidationModelProviderImplTest.java

Modified: sling/trunk/bundles/extensions/validation/core/pom.xml
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/pom.xml?rev=1785330&r1=1785329&r2=1785330&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/validation/core/pom.xml (original)
+++ sling/trunk/bundles/extensions/validation/core/pom.xml Fri Mar  3 15:59:06 
2017
@@ -149,12 +149,6 @@
             <artifactId>slf4j-api</artifactId>
             <scope>provided</scope>
         </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.jcr.resource</artifactId>
-            <version>2.2.8</version>
-            <scope>provided</scope>
-        </dependency>
         <!-- used for getting type information of validators -->
         <dependency>
             <groupId>org.apache.commons</groupId>

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ResourcePropertyBuilder.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ResourcePropertyBuilder.java?rev=1785330&r1=1785329&r2=1785330&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ResourcePropertyBuilder.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ResourcePropertyBuilder.java
 Fri Mar  3 15:59:06 2017
@@ -31,10 +31,10 @@ import org.apache.sling.validation.spi.V
 
 public class ResourcePropertyBuilder {
 
-    public boolean optional;
-    public boolean multiple;
-    String nameRegex;
-    final List<ParameterizedValidator> validators;
+    private boolean optional;
+    private boolean multiple;
+    private String nameRegex;
+    private final List<ParameterizedValidator> validators;
 
     public ResourcePropertyBuilder() {
         validators = new ArrayList<ParameterizedValidator>();
@@ -48,11 +48,17 @@ public class ResourcePropertyBuilder {
         return this;
     }
 
+    /** 
+     * should only be used from test classes 
+     */
     public @Nonnull ResourcePropertyBuilder validator(@Nonnull Validator<?> 
validator) {
         validators.add(new ParameterizedValidatorImpl(validator, new 
HashMap<String, Object>(), null));
         return this;
     }
 
+    /** 
+     * should only be used from test classes 
+     */
     public @Nonnull ResourcePropertyBuilder validator(@Nonnull Validator<?> 
validator, Integer severity, String... parametersNamesAndValues) {
         if (parametersNamesAndValues.length % 2 != 0) {
             throw new IllegalArgumentException("array parametersNamesAndValues 
must be even! (first specify name then value, separated by comma)");
@@ -62,7 +68,11 @@ public class ResourcePropertyBuilder {
         for (int i=0; i<parametersNamesAndValues.length; i=i+2) {
             parameterMap.put(parametersNamesAndValues[i], 
parametersNamesAndValues[i+1]);
         }
-        validators.add(new ParameterizedValidatorImpl(validator, parameterMap, 
severity));
+        return validator(validator, severity, parameterMap);
+    }
+    
+    public @Nonnull ResourcePropertyBuilder validator(@Nonnull Validator<?> 
validator, Integer severity, @Nonnull Map<String, Object> parameters) {
+        validators.add(new ParameterizedValidatorImpl(validator, parameters, 
severity));
         return this;
     }
 

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ResourcePropertyImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ResourcePropertyImpl.java?rev=1785330&r1=1785329&r2=1785330&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ResourcePropertyImpl.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ResourcePropertyImpl.java
 Fri Mar  3 15:59:06 2017
@@ -35,7 +35,16 @@ public class ResourcePropertyImpl implem
     private final @Nonnull List<ParameterizedValidator> validators;
     private final Pattern namePattern;
 
-    public ResourcePropertyImpl(@Nonnull String name, String nameRegex, 
boolean isMultiple, boolean isRequired,
+    /**
+     * Is only supposed to be used from {@link ResourcePropertyBuilder}.
+     * @param name
+     * @param nameRegex
+     * @param isMultiple
+     * @param isRequired
+     * @param validators
+     * @throws IllegalArgumentException
+     */
+    protected ResourcePropertyImpl(@Nonnull String name, String nameRegex, 
boolean isMultiple, boolean isRequired,
             @Nonnull List<ParameterizedValidator> validators) throws 
IllegalArgumentException {
         if (nameRegex != null) {
             try {

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ValidationModelImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ValidationModelImpl.java?rev=1785330&r1=1785329&r2=1785330&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ValidationModelImpl.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ValidationModelImpl.java
 Fri Mar  3 15:59:06 2017
@@ -52,7 +52,7 @@ public class ValidationModelImpl impleme
         this.validatedResourceType = validatedResourceType;
         
         if (resourceProperties.isEmpty() && children.isEmpty()) {
-            throw new IllegalStateException("Neither children nor properties 
set in validation model for " + validatedResourceType + "'");
+            throw new IllegalArgumentException("Neither children nor 
properties set in validation model for " + validatedResourceType + "'");
         }
         // if this collection is empty, make it contain on entry with the emty 
string (means no restriction)
         if (applicablePaths.isEmpty()) {

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/resourcemodel/ResourceValidationModelProviderImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/resourcemodel/ResourceValidationModelProviderImpl.java?rev=1785330&r1=1785329&r2=1785330&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/resourcemodel/ResourceValidationModelProviderImpl.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/resourcemodel/ResourceValidationModelProviderImpl.java
 Fri Mar  3 15:59:06 2017
@@ -19,6 +19,7 @@
 package org.apache.sling.validation.impl.resourcemodel;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -41,6 +42,7 @@ import org.apache.sling.api.resource.Val
 import org.apache.sling.serviceusermapping.ServiceUserMapped;
 import org.apache.sling.validation.impl.model.ChildResourceImpl;
 import org.apache.sling.validation.impl.model.ParameterizedValidatorImpl;
+import org.apache.sling.validation.impl.model.ResourcePropertyBuilder;
 import org.apache.sling.validation.impl.model.ResourcePropertyImpl;
 import org.apache.sling.validation.impl.model.ValidationModelBuilder;
 import org.apache.sling.validation.model.ChildResource;
@@ -167,17 +169,21 @@ public class ResourceValidationModelProv
                     LOG.warn("Could not get covered resource type of newly 
added validation model at " + path, e);
                 }
                 if (resourceTypeToInvalidate != null) {
-                    LOG.debug("Invalidate validation models for resource type 
{}, because resource at {} provides a new/modified validation model for that 
type", resourceType, path);
+                    LOG.debug(
+                            "Invalidate validation models for resource type 
{}, because resource at {} provides a new/modified validation model for that 
type",
+                            resourceType, path);
                     resourceTypesToInvalidate.add(resourceTypeToInvalidate);
                 } else {
-                    LOG.debug("Resource at {} provides a new/modified 
validation model but could not yet determine for which resource type", path);
+                    LOG.debug("Resource at {} provides a new/modified 
validation model but could not yet determine for which resource type",
+                            path);
                 }
             }
             // or paths already covered by the cache
             for (Entry<String, List<ValidationModel>> 
validationModelByResourceType : validationModelCacheByResourceType.entrySet()) {
                 for (ValidationModel model : 
validationModelByResourceType.getValue()) {
                     if (path.startsWith(model.getSource())) {
-                        LOG.debug("Invalidate validation model at {}, because 
resource below (at {}) has been modified", model.getSource(), path);
+                        LOG.debug("Invalidate validation model at {}, because 
resource below (at {}) has been modified", model.getSource(),
+                                path);
                         
resourceTypesToInvalidate.add(validationModelByResourceType.getKey());
                     }
                 }
@@ -207,10 +213,12 @@ public class ResourceValidationModelProv
 
     /*
      * (non-Javadoc)
+     * 
      * @see 
org.apache.sling.validation.model.spi.ValidationModelProvider#getModels(java.lang.String,
 java.util.Map)
      */
     @Override
-    public @Nonnull List<ValidationModel> getModels(@Nonnull String 
relativeResourceType, @Nonnull Map<String, Validator<?>> validatorsMap) {
+    public @Nonnull List<ValidationModel> getModels(@Nonnull String 
relativeResourceType,
+            @Nonnull Map<String, Validator<?>> validatorsMap) {
         List<ValidationModel> cacheEntry = 
validationModelCacheByResourceType.get(relativeResourceType);
         if (cacheEntry == null) {
             cacheEntry = doGetModels(relativeResourceType, validatorsMap);
@@ -220,14 +228,14 @@ public class ResourceValidationModelProv
         }
         return cacheEntry;
     }
-    
-    /** 
-     * Searches for validation models bound to a specific resource type 
through a search query. 
+
+    /** Searches for validation models bound to a specific resource type 
through a search query.
      *
      * @param relativeResourceType the resource type to look for
-     * @param validatorsMap  all known validators in a map (key=id of 
validator). Only one of those should be used in the returned validation models.
-     * @return a List of {@link ValidationModel}s. Never {@code null}, but 
might be empty collection in case no
-     *         model for the given resource type could be found. Returns the 
models below "/apps" before the models below "/libs".
+     * @param validatorsMap all known validators in a map (key=id of 
validator). Only one of those should be used in the returned validation
+     *            models.
+     * @return a List of {@link ValidationModel}s. Never {@code null}, but 
might be empty collection in case no model for the given resource
+     *         type could be found. Returns the models below "/apps" before 
the models below "/libs".
      * @throws IllegalStateException in case a validation model is found but 
it is invalid */
     @Nonnull
     private List<ValidationModel> doGetModels(@Nonnull String 
relativeResourceType, @Nonnull Map<String, Validator<?>> validatorsMap) {
@@ -247,7 +255,7 @@ public class ResourceValidationModelProv
                     try {
                         ValidationModelBuilder modelBuilder = new 
ValidationModelBuilder();
                         ValueMap validationModelProperties = 
model.adaptTo(ValueMap.class);
-                        
modelBuilder.addApplicablePaths(validationModelProperties.get(ResourceValidationModelProviderImpl.APPLICABLE_PATHS,
 new String[]{}));
+                        
modelBuilder.addApplicablePaths(validationModelProperties.get(ResourceValidationModelProviderImpl.APPLICABLE_PATHS,
 new String[] {}));
                         Resource propertiesResource = 
model.getChild(ResourceValidationModelProviderImpl.PROPERTIES);
                         
modelBuilder.resourceProperties(buildProperties(validatorsMap, 
propertiesResource));
                         modelBuilder.childResources(buildChildren(model, 
model, validatorsMap));
@@ -285,20 +293,28 @@ public class ResourceValidationModelProv
         List<ResourceProperty> properties = new ArrayList<ResourceProperty>();
         if (propertiesResource != null) {
             for (Resource property : propertiesResource.getChildren()) {
+                ResourcePropertyBuilder resourcePropertyBuilder = new 
ResourcePropertyBuilder();
                 String fieldName = property.getName();
                 ValueMap propertyValueMap = property.adaptTo(ValueMap.class);
-                Boolean propertyMultiple = 
propertyValueMap.get(ResourceValidationModelProviderImpl.PROPERTY_MULTIPLE, 
false);
-                Boolean propertyRequired = 
!propertyValueMap.get(ResourceValidationModelProviderImpl.OPTIONAL, false);
+                if 
(propertyValueMap.get(ResourceValidationModelProviderImpl.PROPERTY_MULTIPLE, 
false)) {
+                    resourcePropertyBuilder.multiple();
+                }
+                if 
(propertyValueMap.get(ResourceValidationModelProviderImpl.OPTIONAL, false)) {
+                    resourcePropertyBuilder.optional();
+                }
                 String nameRegex = 
propertyValueMap.get(ResourceValidationModelProviderImpl.NAME_REGEX, null);
+                if (nameRegex != null) {
+                    resourcePropertyBuilder.nameRegex(nameRegex);
+                }
                 Resource validators = 
property.getChild(ResourceValidationModelProviderImpl.VALIDATORS);
-                List<ParameterizedValidator> parameterizedValidators = new 
ArrayList<ParameterizedValidator>();
                 if (validators != null) {
                     Iterator<Resource> validatorsIterator = 
validators.listChildren();
                     while (validatorsIterator.hasNext()) {
                         Resource validatorResource = validatorsIterator.next();
                         ValueMap validatorProperties = 
validatorResource.adaptTo(ValueMap.class);
                         if (validatorProperties == null) {
-                            throw new IllegalStateException("Could not adapt 
resource " + validatorResource.getPath() + " to ValueMap");
+                            throw new IllegalStateException(
+                                    "Could not adapt resource at '" + 
validatorResource.getPath() + "' to ValueMap");
                         }
                         String validatorId = validatorResource.getName();
                         Validator<?> validator = 
validatorsMap.get(validatorId);
@@ -311,21 +327,39 @@ public class ResourceValidationModelProv
                         Map<String, Object> validatorArgumentsMap = new 
HashMap<String, Object>();
                         if (validatorArguments != null) {
                             for (String arg : validatorArguments) {
-                                String[] keyValuePair = arg.split("=");
-                                if (keyValuePair.length != 2) {
-                                    continue;
+                                int positionOfSeparator = arg.indexOf("=");
+                                if (positionOfSeparator < 1 || 
positionOfSeparator >= arg.length()-1) {
+                                    throw new 
IllegalArgumentException("Invalid validator argument '" + arg
+                                            + "' found, because it does not 
follow the format '<key>=<value>'");
+                                }
+                                String key = arg.substring(0, 
positionOfSeparator);
+                                String value = 
arg.substring(positionOfSeparator + 1);
+                                Object newValue;
+                                if (validatorArgumentsMap.containsKey(key)) {
+                                    Object oldValue = 
validatorArgumentsMap.get(key);
+                                    // either extend old array
+                                    if (oldValue instanceof String[]) {
+                                        String[] oldArray = (String[]) 
oldValue;
+                                        int newLength = oldArray.length + 1;
+                                        String[] newArray = 
Arrays.copyOf(oldArray, oldArray.length + 1);
+                                        newArray[newLength - 1] = value;
+                                        newValue = newArray;
+                                    } else {
+                                        // or turn the single value into a 
multi-value array
+                                        newValue = new String[] { (String) 
oldValue, value };
+                                    }
+                                } else {
+                                    newValue = value;
                                 }
-                                validatorArgumentsMap.put(keyValuePair[0], 
keyValuePair[1]);
+                                validatorArgumentsMap.put(key, newValue);
                             }
                         }
                         // get severity
                         Integer severity = validatorProperties.get(SEVERITY, 
Integer.class);
-                        parameterizedValidators.add(new 
ParameterizedValidatorImpl(validator, validatorArgumentsMap, severity));
+                        resourcePropertyBuilder.validator(validator, severity, 
validatorArgumentsMap);
                     }
                 }
-                ResourceProperty f = new ResourcePropertyImpl(fieldName, 
nameRegex, propertyMultiple, propertyRequired,
-                        parameterizedValidators);
-                properties.add(f);
+                properties.add(resourcePropertyBuilder.build(fieldName));
             }
         }
         return properties;

Modified: 
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/resourcemodel/ResourceValidationModelProviderImplTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/resourcemodel/ResourceValidationModelProviderImplTest.java?rev=1785330&r1=1785329&r2=1785330&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/resourcemodel/ResourceValidationModelProviderImplTest.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/resourcemodel/ResourceValidationModelProviderImplTest.java
 Fri Mar  3 15:59:06 2017
@@ -41,6 +41,7 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.jcr.resource.JcrResourceConstants;
 import org.apache.sling.testing.mock.jcr.MockJcr;
 import org.apache.sling.testing.mock.jcr.MockQuery;
@@ -244,8 +245,10 @@ public class ResourceValidationModelProv
         ValidationModel model1 = 
modelBuilder.resourceProperty(resourcePropertyBuilder.build("property1")).build("sling/validation/test",
 libsValidatorsRoot.getPath() + "/testValidationModel1");
         
         // build models in JCR
-        createValidationModelResource(rr, libsValidatorsRoot.getPath(), 
"testValidationModel1", model1, true);
-        
+        Resource modelResource = createValidationModelResource(rr, 
libsValidatorsRoot.getPath(), "testValidationModel1", model1);
+        ModifiableValueMap properties = 
modelResource.adaptTo(ModifiableValueMap.class);
+        properties.remove("applicablePaths");
+
         // check that both models are returned
         Collection<ValidationModel> models = 
modelProvider.getModels("sling/validation/test", validatorMap);
         Assert.assertThat(models, Matchers.containsInAnyOrder(model1));
@@ -259,7 +262,7 @@ public class ResourceValidationModelProv
         ValidationModel model1 = 
modelBuilder.resourceProperty(resourcePropertyBuilder.build("property1")).build("sling/validation/test",
 libsValidatorsRoot.getPath() + "/testValidationModel1");
         
         // build models in JCR
-        createValidationModelResource(rr, libsValidatorsRoot.getPath(), 
"testValidationModel1", model1, false);
+        createValidationModelResource(rr, libsValidatorsRoot.getPath(), 
"testValidationModel1", model1);
         
         // check that both models are returned
         Collection<ValidationModel> models = 
modelProvider.getModels("sling/validation/test", validatorMap);
@@ -321,7 +324,21 @@ public class ResourceValidationModelProv
     }
 
     @Test(expected = IllegalStateException.class)
-    public void testGetValidationModelsWithInvalidValidator() throws Exception 
{
+    public void testGetValidationModelsWithMissingChildrenAndProperties() 
throws Exception {
+        // create a model with properties (otherwise build() will already 
throw an exception)
+        modelBuilder = new ValidationModelBuilder();
+        modelBuilder.resourceProperty(new 
ResourcePropertyBuilder().build("field1"));
+        modelBuilder.addApplicablePath("content/site1");
+        ValidationModel model1 = modelBuilder.build("sling/validation/test", 
libsValidatorsRoot.getPath() + "/testValidationModel1");
+        
+        Resource resource = createValidationModelResource(rr, 
libsValidatorsRoot.getPath(), "testValidationModel1", model1);
+        // make created model invalid by removing the properties sub resource
+        rr.delete(resource.getChild("properties"));
+        modelProvider.getModels("sling/validation/test", validatorMap);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testGetValidationModelsWithInvalidValidatorId() throws 
Exception {
         // create one default model
         ValidationModel model1 = modelBuilder.build("sling/validation/test", 
libsValidatorsRoot.getPath() + "/testValidationModel1");
         createValidationModelResource(rr, libsValidatorsRoot.getPath(), 
"testValidationModel1", model1);
@@ -331,16 +348,64 @@ public class ResourceValidationModelProv
         modelProvider.getModels("sling/validation/test", validatorMap);
     }
 
-    @Test(expected = IllegalStateException.class)
-    public void testGetValidationModelsWithMissingChildrenAndProperties() 
throws Exception {
+    @Test
+    public void testGetValidationModelsWithComplexValidatorArguments() throws 
Exception {
         // create a model with neither children nor properties
+        Map<String, Object> validatorArguments = new HashMap<>();
+        validatorArguments.put("key1", "value1");
+        validatorArguments.put("key1", "value2");
+        validatorArguments.put("key1", "value3");
+        validatorArguments.put("key2", "value1");
+        validatorArguments.put("key3", "value1=value2");
         modelBuilder = new ValidationModelBuilder();
+        modelBuilder.resourceProperty(new 
ResourcePropertyBuilder().validator(new RegexValidator(), 10, 
validatorArguments).build("field1"));
         modelBuilder.addApplicablePath("content/site1");
         ValidationModel model1 = modelBuilder.build("sling/validation/test", 
libsValidatorsRoot.getPath() + "/testValidationModel1");
-        
         createValidationModelResource(rr, libsValidatorsRoot.getPath(), 
"testValidationModel1", model1);
+        Collection<ValidationModel> models = 
modelProvider.getModels("sling/validation/test", validatorMap);
+        Assert.assertThat(models, Matchers.contains(model1));
+    }
 
-        modelProvider.getModels("sling/validation/test", validatorMap);
+    @Test(expected=IllegalStateException.class)
+    public void testGetValidationModelsWithInvalidValidatorArguments1() throws 
Exception {
+        // create a model with neither children nor properties
+        ValidationModel model1 = modelBuilder.build("sling/validation/test", 
libsValidatorsRoot.getPath() + "/testValidationModel1");
+        // create valid model first
+        Resource modelResource = createValidationModelResource(rr, 
libsValidatorsRoot.getPath(), "testValidationModel1", model1);
+        // and make parametrization of validator invalid afterwards
+        Resource validatorResource = 
modelResource.getChild("properties/field1/validators/" + 
RegexValidator.class.getName());
+        ModifiableValueMap validatorArguments = 
validatorResource.adaptTo(ModifiableValueMap.class);
+        validatorArguments.put("validatorArguments", "key1"); // value without 
"="
+        Collection<ValidationModel> models = 
modelProvider.getModels("sling/validation/test", validatorMap);
+        Assert.assertThat(models, Matchers.contains(model1));
+    }
+
+    @Test(expected=IllegalStateException.class)
+    public void testGetValidationModelsWithInvalidValidatorArguments2() throws 
Exception {
+        // create a model with neither children nor properties
+        ValidationModel model1 = modelBuilder.build("sling/validation/test", 
libsValidatorsRoot.getPath() + "/testValidationModel1");
+        // create valid model first
+        Resource modelResource = createValidationModelResource(rr, 
libsValidatorsRoot.getPath(), "testValidationModel1", model1);
+        // and make parametrization of validator invalid afterwards
+        Resource validatorResource = 
modelResource.getChild("properties/field1/validators/" + 
RegexValidator.class.getName());
+        ModifiableValueMap validatorArguments = 
validatorResource.adaptTo(ModifiableValueMap.class);
+        validatorArguments.put("validatorArguments", "=value2"); // starting 
with "="
+        Collection<ValidationModel> models = 
modelProvider.getModels("sling/validation/test", validatorMap);
+        Assert.assertThat(models, Matchers.contains(model1));
+    }
+
+    @Test(expected=IllegalStateException.class)
+    public void testGetValidationModelsWithInvalidValidatorArguments3() throws 
Exception {
+        // create a model with neither children nor properties
+        ValidationModel model1 = modelBuilder.build("sling/validation/test", 
libsValidatorsRoot.getPath() + "/testValidationModel1");
+        // create valid model first
+        Resource modelResource = createValidationModelResource(rr, 
libsValidatorsRoot.getPath(), "testValidationModel1", model1);
+        // and make parametrization of validator invalid afterwards
+        Resource validatorResource = 
modelResource.getChild("properties/field1/validators/" + 
RegexValidator.class.getName());
+        ModifiableValueMap validatorArguments = 
validatorResource.adaptTo(ModifiableValueMap.class);
+        validatorArguments.put("validatorArguments", "key1="); // ending with 
"="
+        Collection<ValidationModel> models = 
modelProvider.getModels("sling/validation/test", validatorMap);
+        Assert.assertThat(models, Matchers.contains(model1));
     }
 
     @Test
@@ -362,19 +427,14 @@ public class ResourceValidationModelProv
         Assert.assertEquals("Due to caching both models should be actually the 
same instance", System.identityHashCode(models), 
System.identityHashCode(models2));
     }
 
-    private Resource createValidationModelResource(ResourceResolver rr, String 
root, String name, ValidationModel model) throws Exception {
-        return createValidationModelResource(rr, root, name, model, false);
-    }
+    /*--- the following methods create validation model resources from 
ValidationModel objects --*/
 
-    private Resource createValidationModelResource(ResourceResolver rr, String 
root, String name, ValidationModel model, boolean 
leaveOutApplicablePathProperty)
+    private Resource createValidationModelResource(ResourceResolver rr, String 
root, String name, ValidationModel model)
             throws Exception {
         Map<String, Object> modelProperties = new HashMap<String, Object>();
         
modelProperties.put(ResourceValidationModelProviderImpl.VALIDATED_RESOURCE_TYPE,
 model.getValidatedResourceType());
-        if (!leaveOutApplicablePathProperty) {
-            
modelProperties.put(ResourceValidationModelProviderImpl.APPLICABLE_PATHS, 
model.getApplicablePaths().toArray());
-        }
-        modelProperties
-                .put(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY, 
ResourceValidationModelProviderImpl.VALIDATION_MODEL_RESOURCE_TYPE);
+        
modelProperties.put(ResourceValidationModelProviderImpl.APPLICABLE_PATHS, 
model.getApplicablePaths().toArray());
+        modelProperties.put(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY, 
ResourceValidationModelProviderImpl.VALIDATION_MODEL_RESOURCE_TYPE);
         modelProperties.put(JcrConstants.JCR_PRIMARYTYPE, 
JcrConstants.NT_UNSTRUCTURED);
         Resource modelResource = ResourceUtil.getOrCreateResource(rr, root + 
"/" + name, modelProperties,
                 JcrResourceConstants.NT_SLING_FOLDER, true);
@@ -398,6 +458,12 @@ public class ResourceValidationModelProv
         return modelResource;
     }
 
+    /**
+     * Always uses the validator's class name as validator resource name.
+     * @param model
+     * @param properties
+     * @throws PersistenceException
+     */
     private void createValidationModelProperties(Resource model, @Nonnull 
Collection<ResourceProperty> properties)
             throws PersistenceException {
         ResourceResolver rr = model.getResourceResolver();
@@ -425,7 +491,7 @@ public class ResourceValidationModelProv
                     for (ParameterizedValidator validator : 
property.getValidators()) {
                         Map<String, Object> validatorProperties = new 
HashMap<String, Object>();
                         validatorProperties.put(JcrConstants.JCR_PRIMARYTYPE, 
JcrConstants.NT_UNSTRUCTURED);
-                        Map<String, Object> parameters = 
validator.getParameters();
+                        ValueMap parameters = validator.getParameters();
                         if (!parameters.isEmpty()) {
                             // convert to right format
                             
validatorProperties.put(ResourceValidationModelProviderImpl.VALIDATOR_ARGUMENTS,
@@ -435,6 +501,7 @@ public class ResourceValidationModelProv
                         if (severity != null) {
                             
validatorProperties.put(ResourceValidationModelProviderImpl.SEVERITY, severity);
                         }
+                        // TODO: get real validator id here!
                         ResourceUtil.getOrCreateResource(rr, 
validators.getPath() + "/"
                                 + 
validator.getValidator().getClass().getName(), validatorProperties, null, true);
                     }
@@ -449,10 +516,16 @@ public class ResourceValidationModelProv
      * @param map
      * @return
      */
-    private String[] convertMapToJcrValidatorArguments(Map<String, Object> 
map) {
+    private String[] convertMapToJcrValidatorArguments(ValueMap map) {
         List<String> parametersForJcr = new ArrayList<String>();
         for (Map.Entry<String, Object> entry : map.entrySet()) {
-            parametersForJcr.add(entry.getKey() + "=" + entry.getValue());
+            if (entry.getValue() instanceof String[]) {
+                for (String value : (String[]) entry.getValue()) {
+                    parametersForJcr.add(value + "=" + entry.getValue());
+                }
+            } else {
+                parametersForJcr.add(entry.getKey() + "=" + entry.getValue());
+            }
         }
         return parametersForJcr.toArray(new String[0]);
     }


Reply via email to