Author: kwin
Date: Tue Mar 21 12:03:33 2017
New Revision: 1787945

URL: http://svn.apache.org/viewvc?rev=1787945&view=rev
Log:
SLING-6659 detect modification to validator.id, service.ranking and/or 
validator.severity a run-time

Also did some major refactoring to hold references to validator services only 
from the ValidationServiceImpl

Added:
    
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ValidatorInvocation.java
      - copied, changed from r1787156, 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ParameterizedValidator.java
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidatorMap.java
   (with props)
    
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidatorMapTest.java
   (with props)
Removed:
    
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ParameterizedValidator.java
    
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ValidatorAndSeverity.java
Modified:
    
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/ValidationService.java
    
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ResourceProperty.java
    
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/spi/ValidationModelProvider.java
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ResourceToValidationResultAdapterFactory.java
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationModelRetrieverImpl.java
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java
    
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ParameterizedValidatorImpl.java
    
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/resourcemodel/ResourceValidationModelProviderImpl.java
    
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationModelRetrieverImplTest.java
    
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java
    
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/resourcemodel/ResourceValidationModelProviderImplTest.java

Modified: 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/ValidationService.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/ValidationService.java?rev=1787945&r1=1787944&r2=1787945&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/ValidationService.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/ValidationService.java
 Tue Mar 21 12:03:33 2017
@@ -68,8 +68,9 @@ public interface ValidationService {
      * @param model    the model with which to perform the validation
      * @return a {@link ValidationResult} that provides the necessary 
information
      * @throws SlingValidationException if one validator was called with 
invalid arguments
+     * @throws IllegalArgumentException if a validator id referenced in the 
given model could not be resolved
      */
-    @Nonnull ValidationResult validate(@Nonnull Resource resource, @Nonnull 
ValidationModel model) throws SlingValidationException;
+    @Nonnull ValidationResult validate(@Nonnull Resource resource, @Nonnull 
ValidationModel model) throws SlingValidationException, 
IllegalArgumentException;
 
     /**
      * Validates a {@link ValueMap} or any object adaptable to a {@code 
ValueMap} using a specific {@link ValidationModel}. Since the

Modified: 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ResourceProperty.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ResourceProperty.java?rev=1787945&r1=1787944&r2=1787945&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ResourceProperty.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ResourceProperty.java
 Tue Mar 21 12:03:33 2017
@@ -48,9 +48,8 @@ public interface ResourceProperty {
     @CheckForNull Pattern getNamePattern();
 
     /**
-     * Returns {@code true} if this property is expected to be a multiple 
property (e.g. array of values).
      *
-     * @return {@code true} if the  property is multiple, {@code false} 
otherwise
+     * @return {@code true} if the property is expected to contain multiple 
values, {@code false} otherwise
      */
     boolean isMultiple();
 
@@ -62,9 +61,9 @@ public interface ResourceProperty {
     boolean isRequired();
 
     /**
-     * Returns a list of {@link ParameterizedValidator}s which should be 
applied on this property.
+     * Returns a list of {@link ValidatorInvocation}s which should be applied 
on this property.
      *
-     * @return the list of validators
+     * @return the {@link List} of {@link ValidatorInvocation}s
      */
-    @Nonnull List<ParameterizedValidator> getValidators();
+    @Nonnull List<ValidatorInvocation> getValidatorInvocations();
 }

Copied: 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ValidatorInvocation.java
 (from r1787156, 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ParameterizedValidator.java)
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ValidatorInvocation.java?p2=sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ValidatorInvocation.java&p1=sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ParameterizedValidator.java&r1=1787156&r2=1787945&rev=1787945&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ParameterizedValidator.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/ValidatorInvocation.java
 Tue Mar 21 12:03:33 2017
@@ -27,35 +27,26 @@ import org.osgi.annotation.versioning.Pr
 
 
 /**
- * Defines a validator instance with information about the type and the 
parameterization of the validator.
- *
+ * Defines a specific validator invocation for a given property (without 
actually exposing a reference to the underlying {@link Validator}).
  */
 @ProviderType
-public interface ParameterizedValidator {
+public interface ValidatorInvocation {
 
     /**
      * 
-     * @return the validator. Never {@code null}.
+     * @return the validator id of the {@link Validator} which is supposed to 
be called.
      */
-    @Nonnull Validator<?> getValidator();
+    @Nonnull String getValidatorId();
 
     /**
      * 
-     * @return the parameterization of the validator (never {@code null}, but 
might be empty map)
+     * @return the parameterization of the {@link Validator#validate(Object, 
org.apache.sling.validation.spi.ValidationContext, ValueMap)} call (never 
{@code null}, but might be empty map)
      */
     @Nonnull ValueMap getParameters();
 
     /**
-     * 
-     * @return the type of the validator (i.e. the type of the data it can 
handle)
-     */
-    @Nonnull Class<?> getType();
-
-    /**
-     *
-     * @return the severity of validation failures emitted by this validator.
-     * Was either set on the model or on the {@link Validator} itself.
-     * May be {@code null} in case it was set on none of them.
+     * @return the severity of validation failures emitted for this usage of 
the validator (as being set in the model).
+     * May be {@code null} in case it was not set on the model.
      */
     @CheckForNull Integer getSeverity();
 

Modified: 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/spi/ValidationModelProvider.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/spi/ValidationModelProvider.java?rev=1787945&r1=1787944&r2=1787945&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/spi/ValidationModelProvider.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/api/src/main/java/org/apache/sling/validation/model/spi/ValidationModelProvider.java
 Tue Mar 21 12:03:33 2017
@@ -19,13 +19,11 @@
 package org.apache.sling.validation.model.spi;
 
 import java.util.List;
-import java.util.Map;
 
 import javax.annotation.Nonnull;
 
 import org.apache.sling.validation.ValidationService;
 import org.apache.sling.validation.model.ValidationModel;
-import org.apache.sling.validation.model.ValidatorAndSeverity;
 import org.osgi.annotation.versioning.ProviderType;
 
 
@@ -42,16 +40,12 @@ public interface ValidationModelProvider
      * Retrieves the models responsible for validating the given resourceType.
      * 
      * @param relativeResourceType the relative resource (relative to one of 
the resource resolver's search paths)
-     * @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. The order 
which model gets active is mostly determined by {@link 
ValidationModel#getApplicablePaths()} (longest path match wins) 
      *         but in case there are multiple models having the same 
applicable path, the order being returned here is considered (i.e. the first 
one is taken).
      * @throws IllegalStateException
      *             in case a validation model was found but it is invalid
      */
-    @Nonnull List<ValidationModel> getModels(@Nonnull String 
relativeResourceType,
-            @Nonnull Map<String, ValidatorAndSeverity<?>> validatorsMap) 
throws IllegalStateException;
+    @Nonnull List<ValidationModel> getModels(@Nonnull String 
relativeResourceType) throws IllegalStateException;
 
 }

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ResourceToValidationResultAdapterFactory.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ResourceToValidationResultAdapterFactory.java?rev=1787945&r1=1787944&r2=1787945&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ResourceToValidationResultAdapterFactory.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ResourceToValidationResultAdapterFactory.java
 Tue Mar 21 12:03:33 2017
@@ -22,7 +22,6 @@ import javax.annotation.Nonnull;
 
 import org.apache.sling.api.adapter.AdapterFactory;
 import org.apache.sling.api.resource.Resource;
-import org.apache.sling.validation.ValidationFailure;
 import org.apache.sling.validation.ValidationResult;
 import org.osgi.service.component.annotations.Component;
 import org.slf4j.Logger;

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationModelRetrieverImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationModelRetrieverImpl.java?rev=1787945&r1=1787944&r2=1787945&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationModelRetrieverImpl.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationModelRetrieverImpl.java
 Tue Mar 21 12:03:33 2017
@@ -21,9 +21,7 @@ package org.apache.sling.validation.impl
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 import java.util.SortedMap;
-import java.util.concurrent.ConcurrentHashMap;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
@@ -35,12 +33,9 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.validation.impl.model.MergedValidationModel;
 import org.apache.sling.validation.model.ValidationModel;
-import org.apache.sling.validation.model.ValidatorAndSeverity;
 import org.apache.sling.validation.model.spi.ValidationModelProvider;
 import org.apache.sling.validation.model.spi.ValidationModelRetriever;
-import org.apache.sling.validation.spi.Validator;
 import org.osgi.framework.ServiceReference;
-import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.FieldOption;
 import org.osgi.service.component.annotations.Reference;
@@ -64,13 +59,6 @@ public class ValidationModelRetrieverImp
     @Reference(policy = ReferencePolicy.DYNAMIC, cardinality = 
ReferenceCardinality.MULTIPLE, policyOption = ReferencePolicyOption.GREEDY, 
fieldOption = FieldOption.REPLACE)
     protected volatile List<ValidationModelProvider> modelProviders;
 
-    /** List of all known validators (key=id of validator) */
-    @Nonnull
-    Map<String, ValidatorAndSeverity<?>> validators = new 
ConcurrentHashMap<>();
-
-    @Nonnull
-    Map<String, ServiceReference<Validator<?>>> validatorServiceReferences = 
new ConcurrentHashMap<>();
-
     @Reference
     ResourceResolverFactory resourceResolverFactory;
 
@@ -145,7 +133,7 @@ public class ValidationModelRetrieverImp
         // lowest ranked model provider inserts first (i.e. higher ranked 
should overwrite)
         for (ValidationModelProvider modelProvider : modelProviders) {
             LOG.debug("Retrieving validation models with resource type {} from 
provider {}...", resourceType, modelProvider.getClass().getName());
-            List<ValidationModel> models = 
modelProvider.getModels(resourceType, validators);
+            List<ValidationModel> models = 
modelProvider.getModels(resourceType);
             for (ValidationModel model : models) {
                 for (String applicablePath : model.getApplicablePaths()) {
                     LOG.debug("Found validation model for resource type {} for 
applicable path {}", resourceType, applicablePath);
@@ -159,70 +147,4 @@ public class ValidationModelRetrieverImp
         return modelsForResourceType;
     }
 
-    @Reference(cardinality = ReferenceCardinality.MULTIPLE, policyOption = 
ReferencePolicyOption.GREEDY)
-    protected void addValidator(@Nonnull Validator<?> validator, Map<String, 
Object> properties, ServiceReference<Validator<?>> serviceReference) {
-        String validatorId = getValidatorIdFromServiceProperties(properties, 
validator, serviceReference);
-        Integer severity = 
getValidatorSeverityFromServiceProperties(properties, validator, 
serviceReference);
-        if (validators.containsKey(validatorId)) {
-            ServiceReference<Validator<?>> existingServiceReference = 
validatorServiceReferences.get(validatorId);
-            if (existingServiceReference == null) {
-                throw new IllegalStateException("Could not find service 
reference for validator with id " + validatorId);
-            }
-            if (serviceReference.compareTo(existingServiceReference) == 1) {
-                LOG.info("Overwriting already existing validator {} from 
bundle {} with validator {} from bundle {},"
-                        + " because it has the same id '{}' and a higher 
service ranking",
-                        validators.get(validatorId), 
existingServiceReference.getBundle().getBundleId(), validator,
-                        serviceReference.getBundle().getBundleId(), 
validatorId);
-                validators.put(validatorId, new 
ValidatorAndSeverity<>(validator, severity));
-                validatorServiceReferences.put(validatorId, serviceReference);
-            } else {
-                LOG.info(
-                        "A Validator for the same id '{}' is already 
registered with class '{}' from bundle {} and has a higher service ranking",
-                        validatorId, validators.get(validatorId), 
existingServiceReference.getBundle().getBundleId());
-            }
-        } else {
-            validators.put(validatorId, new ValidatorAndSeverity<>(validator, 
severity));
-            validatorServiceReferences.put(validatorId, serviceReference);
-        }
-    }
-
-    // no need for an unbind method for validators, as those are static, i.e. 
component is deactivated first
-    @Activate
-    protected void activate() {
-        LOG.info("Starting service...");
-    }
-
-    private String getValidatorIdFromServiceProperties(Map<String, Object> 
properties, Validator<?> validator,
-            ServiceReference<Validator<?>> serviceReference) {
-        Object id = properties.get(Validator.PROPERTY_VALIDATOR_ID);
-        if (id == null) {
-            throw new IllegalArgumentException("Validator '" + 
validator.getClass().getName() + "' provided from bundle "
-                    + serviceReference.getBundle().getBundleId() +
-                    " is lacking the mandatory service property " + 
Validator.PROPERTY_VALIDATOR_ID);
-        }
-        if (!(id instanceof String)) {
-            throw new IllegalArgumentException("Validator '" + 
validator.getClass().getName() + "' provided from bundle "
-                    + serviceReference.getBundle().getBundleId() +
-                    " is providing the mandatory service property " + 
Validator.PROPERTY_VALIDATOR_ID + " with the wrong type "
-                    + id.getClass() + " (must be of type String)");
-        }
-        return (String) id;
-    }
-    
-    private Integer getValidatorSeverityFromServiceProperties(Map<String, 
Object> properties, Validator<?> validator,
-            ServiceReference<Validator<?>> serviceReference) {
-        Object severity = 
properties.get(Validator.PROPERTY_VALIDATOR_SEVERITY);
-        if (severity == null) {
-            LOG.debug("Validator '{}' is not setting an explicit severity via 
the OSGi service property {}", validator.getClass().getName(), 
Validator.PROPERTY_VALIDATOR_SEVERITY);
-            return null;
-        }
-        if (!(severity instanceof Integer)) {
-            throw new IllegalArgumentException("Validator '" + 
validator.getClass().getName() + "' provided from bundle "
-                    + serviceReference.getBundle().getBundleId() +
-                    " is providing the optional service property " + 
Validator.PROPERTY_VALIDATOR_SEVERITY + " with the wrong type "
-                    + severity.getClass() + " (must be of type Integer)");
-        }
-        return (Integer) severity;
-    }
-
 }

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java?rev=1787945&r1=1787944&r2=1787945&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java
 Tue Mar 21 12:03:33 2017
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.ResourceBundle;
 import java.util.function.Predicate;
 import java.util.regex.Matcher;
@@ -44,7 +45,7 @@ import org.apache.sling.validation.Sling
 import org.apache.sling.validation.ValidationResult;
 import org.apache.sling.validation.ValidationService;
 import org.apache.sling.validation.model.ChildResource;
-import org.apache.sling.validation.model.ParameterizedValidator;
+import org.apache.sling.validation.model.ValidatorInvocation;
 import org.apache.sling.validation.model.ResourceProperty;
 import org.apache.sling.validation.model.ValidationModel;
 import org.apache.sling.validation.model.spi.ValidationModelRetriever;
@@ -78,6 +79,10 @@ public class ValidationServiceImpl imple
     @Reference
     ValidationModelRetriever modelRetriever;
     
+    /** List of all known validators (key=id of validator) */
+    @Nonnull
+    ValidatorMap validatorMap;
+    
     Collection<String> searchPaths;
     
     ValidationServiceConfiguration configuration;
@@ -98,7 +103,8 @@ public class ValidationServiceImpl imple
     private ServiceUserMapped serviceUserMapped;
 
     @Activate
-    public void activate(ValidationServiceConfiguration configuration) {
+    protected void activate(ValidationServiceConfiguration configuration) {
+        this.validatorMap = new ValidatorMap();
         this.configuration = configuration;
         ResourceResolver rr = null;
         try {
@@ -113,6 +119,28 @@ public class ValidationServiceImpl imple
         }
     }
 
+    @Reference(cardinality = ReferenceCardinality.MULTIPLE, policyOption = 
ReferencePolicyOption.GREEDY, policy=ReferencePolicy.DYNAMIC)
+    protected void addValidator(@Nonnull Validator<?> validator, Map<String, 
Object> properties, ServiceReference<Validator<?>> serviceReference) {
+        validatorMap.put(properties, validator, serviceReference);
+    }
+
+    protected void removeValidator(@Nonnull Validator<?> validator, 
Map<String, Object> properties, ServiceReference<Validator<?>> 
serviceReference) {
+        validatorMap.remove(properties, validator, serviceReference);
+    }
+    
+    /** 
+     * Necessary to deal with property changes which do not lead to service 
restarts (when a modified method is provided)
+     * 
+     * @param validator
+     * @param properties
+     * @param serviceReference
+     */
+    protected void updatedValidator(@Nonnull Validator<?> validator, 
Map<String, Object> properties, ServiceReference<Validator<?>> 
serviceReference) {
+        validatorMap.update(properties, validator, serviceReference);
+    }
+
+
+
     // ValidationService 
###################################################################################################################
     
     public @CheckForNull ValidationModel getValidationModel(@Nonnull String 
validatedResourceType, String resourcePath, boolean 
considerResourceSuperTypeModels) {
@@ -173,13 +201,14 @@ public class ValidationServiceImpl imple
         throw new IllegalStateException("There is no resource provider in the 
system, providing a resource bundle for locale");
     }
 
-    private int getSeverityForValidator(ParameterizedValidator validator) {
-        Integer validatorSeverity = validator.getSeverity();
-        if (validatorSeverity == null) {
-            return configuration.defaultSeverity();
-        } else {
-            return validatorSeverity;
+    private int getSeverityForValidator(Integer severityFromModel, Integer 
severityFromValidator) {
+        if (severityFromModel != null) {
+            return severityFromModel;
+        }
+        if (severityFromValidator != null) {
+            return severityFromValidator;
         }
+        return configuration.defaultSeverity();
     }
 
     protected @Nonnull ValidationResult validate(@Nonnull Resource resource, 
@Nonnull ValidationModel model, @Nonnull String relativePath) {
@@ -306,7 +335,7 @@ public class ValidationServiceImpl imple
             }
             return;
         }
-        List<ParameterizedValidator> validators = 
resourceProperty.getValidators();
+        List<ValidatorInvocation> validatorInvocations = 
resourceProperty.getValidatorInvocations();
         if (resourceProperty.isMultiple()) {
             if (!fieldValues.getClass().isArray()) {
                 result.addFailure(relativePath + property, 
configuration.defaultSeverity(), defaultResourceBundle, 
I18N_KEY_EXPECTED_MULTIVALUE_PROPERTY);
@@ -314,10 +343,16 @@ public class ValidationServiceImpl imple
             }
         }
         
-        for (ParameterizedValidator validator : validators) {
-            int severity = getSeverityForValidator(validator);
+        for (ValidatorInvocation validatorInvocation : validatorInvocations) {
+            // lookup validator by id
+            ValidatorMap.ValidatorMetaData validatorMetaData = 
validatorMap.get(validatorInvocation.getValidatorId());
+            if (validatorMetaData == null) {
+                throw new IllegalStateException("Could not find validator with 
id '" + validatorInvocation.getValidatorId() + "'");
+            }
+            int severity = 
getSeverityForValidator(validatorInvocation.getSeverity(), 
validatorMetaData.getSeverity());
+            
             // convert the type always to an array
-            Class<?> type = validator.getType();
+            Class<?> type = validatorMetaData.getType();
             if (!type.isArray()) {
                 try {
                     // 
https://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#getName%28%29 
has some hints on class names
@@ -331,23 +366,23 @@ public class ValidationServiceImpl imple
             // see https://issues.apache.org/jira/browse/SLING-4178 for why 
the second check is necessary
             if (typedValue == null || (typedValue.length > 0 && typedValue[0] 
== null)) {
                 // here the missing required property case was already treated 
in validateValueMap
-                result.addFailure(relativePath + property, severity, 
defaultResourceBundle, I18N_KEY_WRONG_PROPERTY_TYPE, validator.getType());
+                result.addFailure(relativePath + property, severity, 
defaultResourceBundle, I18N_KEY_WRONG_PROPERTY_TYPE, 
validatorMetaData.getType());
                 return;
             }
             
             // see https://issues.apache.org/jira/browse/SLING-662 for a 
description on how multivalue properties are treated with ValueMap
-            if (validator.getType().isArray()) {
+            if (validatorMetaData.getType().isArray()) {
                 // ValueMap already returns an array in both cases (property 
is single value or multivalue)
-                validateValue(result, typedValue, property, relativePath, 
valueMap, resource, validator, defaultResourceBundle, severity);
+                validateValue(result, typedValue, property, relativePath, 
valueMap, resource, validatorMetaData.getValidator(), 
validatorInvocation.getParameters(), defaultResourceBundle, severity);
             } else {
                 // call validate for each entry in the array (supports both 
singlevalue and multivalue)
                 @Nonnull Object[] array = (Object[])typedValue;
                 if (array.length == 1) {
-                   validateValue(result, array[0], property, relativePath, 
valueMap, resource, validator, defaultResourceBundle, severity);
+                   validateValue(result, array[0], property, relativePath, 
valueMap, resource, validatorMetaData.getValidator(), 
validatorInvocation.getParameters(), defaultResourceBundle, severity);
                 } else {
                     int n = 0;
                     for (Object item : array) {
-                        validateValue(result, item, property + "[" + n++ + 
"]", relativePath, valueMap, resource, validator, defaultResourceBundle, 
severity);
+                        validateValue(result, item, property + "[" + n++ + 
"]", relativePath, valueMap, resource, validatorMetaData.getValidator(), 
validatorInvocation.getParameters(), defaultResourceBundle, severity);
                     }
                 }
             }
@@ -355,10 +390,10 @@ public class ValidationServiceImpl imple
     }
     
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    private void validateValue(CompositeValidationResult result, @Nonnull 
Object value, String property, String relativePath, @Nonnull ValueMap valueMap, 
Resource resource, ParameterizedValidator validator, @Nonnull ResourceBundle 
defaultResourceBundle, int severity) {
+    private void validateValue(CompositeValidationResult result, @Nonnull 
Object value, String property, String relativePath, @Nonnull ValueMap valueMap, 
Resource resource, @Nonnull Validator validator, ValueMap validatorParameters, 
@Nonnull ResourceBundle defaultResourceBundle, int severity) {
         try {
             ValidationContext validationContext = new 
ValidationContextImpl(relativePath + property, severity, valueMap, resource, 
defaultResourceBundle);
-            ValidationResult validatorResult = 
((Validator)validator.getValidator()).validate(value, validationContext, 
validator.getParameters());
+            ValidationResult validatorResult = 
((Validator)validator).validate(value, validationContext, validatorParameters);
             result.addValidationResult(validatorResult);
         } catch (SlingValidationException e) {
             // wrap in another SlingValidationException to include information 
about the property

Added: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidatorMap.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidatorMap.java?rev=1787945&view=auto
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidatorMap.java
 (added)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidatorMap.java
 Tue Mar 21 12:03:33 2017
@@ -0,0 +1,236 @@
+/*
+ * 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.validation.impl;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+import org.apache.sling.validation.impl.util.ValidatorTypeUtil;
+import org.apache.sling.validation.spi.Validator;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helper class which encapsulates a map of {@link Validator}s with their meta 
information.
+ *
+ */
+public class ValidatorMap {
+
+    final static class ValidatorMetaData implements 
Comparable<ValidatorMetaData> {
+        protected final @Nonnull Validator<?> validator;
+        // default severity of the validator
+        protected final Integer severity;
+        protected final @Nonnull Class<?> type;
+        /** used for comparison, to sort by service ranking and id */
+        protected final @Nonnull ServiceReference<Validator<?>> 
serviceReference;
+
+        public ValidatorMetaData(Validator<?> validator, 
ServiceReference<Validator<?>> serviceReference, Integer severity) {
+            this.validator = validator;
+            this.severity = severity;
+            this.serviceReference = serviceReference;
+            // cache validator's type (as this is using reflection)
+            type = ValidatorTypeUtil.getValidatorType(validator);
+        }
+
+        @Override
+        public int compareTo(ValidatorMetaData o) {
+            return serviceReference.compareTo(o.serviceReference);
+        }
+
+        
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((serviceReference == null) ? 0 : 
serviceReference.hashCode());
+            result = prime * result + ((severity == null) ? 0 : 
severity.hashCode());
+            result = prime * result + ((validator == null) ? 0 : 
validator.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            ValidatorMetaData other = (ValidatorMetaData) obj;
+            if (serviceReference == null) {
+                if (other.serviceReference != null)
+                    return false;
+            } else if (!serviceReference.equals(other.serviceReference))
+                return false;
+            if (severity == null) {
+                if (other.severity != null)
+                    return false;
+            } else if (!severity.equals(other.severity))
+                return false;
+            if (validator == null) {
+                if (other.validator != null)
+                    return false;
+            } else if (!validator.equals(other.validator))
+                return false;
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "Entry [validator=" + validator + ", severity=" + severity 
+ ", type=" + type + ", from bundle '" + 
serviceReference.getBundle().getSymbolicName() + "'"
+                    + "]";
+        }
+
+        public @Nonnull Validator<?> getValidator() {
+            return validator;
+        }
+
+        public @CheckForNull Integer getSeverity() {
+            return severity;
+        }
+
+        public @Nonnull Class<?> getType() {
+            return type;
+        }
+        
+    }
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(ValidationServiceImpl.class);
+    private final Map<String, ValidatorMetaData> validatorMap;
+    
+    public ValidatorMap() {
+        validatorMap = new ConcurrentHashMap<>();
+    }
+
+    private String getValidatorIdFromServiceProperties(Map<String, Object> 
properties, @SuppressWarnings("rawtypes") Class<? extends Validator> 
validatorClass,
+            ServiceReference<Validator<?>> serviceReference) {
+        Object id = properties.get(Validator.PROPERTY_VALIDATOR_ID);
+        if (id == null) {
+            throw new IllegalArgumentException("Validator '" + 
validatorClass.getName() + "' provided from bundle "
+                    + serviceReference.getBundle().getBundleId() +
+                    " is lacking the mandatory service property " + 
Validator.PROPERTY_VALIDATOR_ID);
+        }
+        if (!(id instanceof String)) {
+            throw new IllegalArgumentException("Validator '" + 
validatorClass.getName() + "' provided from bundle "
+                    + serviceReference.getBundle().getBundleId() +
+                    " is providing the mandatory service property " + 
Validator.PROPERTY_VALIDATOR_ID + " with the wrong type "
+                    + id.getClass() + " (must be of type String)");
+        }
+        return (String) id;
+    }
+    
+    private Integer getValidatorSeverityFromServiceProperties(Map<String, 
Object> properties, Validator<?> validator,
+            ServiceReference<Validator<?>> serviceReference) {
+        Object severity = 
properties.get(Validator.PROPERTY_VALIDATOR_SEVERITY);
+        if (severity == null) {
+            LOG.debug("Validator '{}' is not setting an explicit severity via 
the OSGi service property {}", validator.getClass().getName(), 
Validator.PROPERTY_VALIDATOR_SEVERITY);
+            return null;
+        }
+        if (!(severity instanceof Integer)) {
+            throw new IllegalArgumentException("Validator '" + 
validator.getClass().getName() + "' provided from bundle "
+                    + serviceReference.getBundle().getBundleId() +
+                    " is providing the optional service property " + 
Validator.PROPERTY_VALIDATOR_SEVERITY + " with the wrong type "
+                    + severity.getClass() + " (must be of type Integer)");
+        }
+        return (Integer) severity;
+    }
+
+    public void put(@Nonnull Map<String, Object> properties, @Nonnull 
Validator<?> validator, ServiceReference<Validator<?>> serviceReference) {
+        String validatorId = getValidatorIdFromServiceProperties(properties, 
validator.getClass(), serviceReference);
+        Integer severity = 
getValidatorSeverityFromServiceProperties(properties, validator, 
serviceReference);
+        put(validatorId, validator, serviceReference, severity);
+    }
+
+    void put(@Nonnull String id, @Nonnull Validator<?> validator, 
ServiceReference<Validator<?>> serviceReference, Integer severity) {
+        // create new entry
+        ValidatorMetaData entry = new ValidatorMetaData(validator, 
serviceReference, severity);
+        if (validatorMap.containsKey(id)) {
+            ValidatorMetaData existingEntry = validatorMap.get(id);
+            if (entry.compareTo(existingEntry) > 0) {
+                LOG.info("Overwriting already existing validator {} with {}, 
because it has the same id '{}' and a higher service ranking",
+                        existingEntry, entry, id);
+            } else {
+                LOG.info(
+                        "A Validator for the same id '{}' is already 
registered {} and it has a higher service ranking, therefore ignoring {}",
+                        id, existingEntry, entry);
+                return;
+            }
+        } else {
+            LOG.debug("New validator with id '{}' added: {}", id, entry);
+        }
+        validatorMap.put(id, entry);
+    }
+
+    public void update(@Nonnull Map<String, Object> properties, @Nonnull 
Validator<?> validator, ServiceReference<Validator<?>> serviceReference) {
+        String validatorId = getValidatorIdFromServiceProperties(properties, 
validator.getClass(), serviceReference);
+        Integer severity = 
getValidatorSeverityFromServiceProperties(properties, validator, 
serviceReference);
+        update(validatorId, validator, serviceReference, severity);
+    }
+
+    void update(@Nonnull String id, @Nonnull Validator<?> validator, 
ServiceReference<Validator<?>> serviceReference, Integer severity) {
+        LOG.info("Updating validator with id '{}'", id);
+        // the id might have been changed, therefore remove old entry by 
looking up the service reference!
+        remove(serviceReference);
+        put(id, validator, serviceReference, severity);
+    }
+
+    private boolean remove(ServiceReference<Validator<?>> serviceReference) {
+        for (java.util.Iterator<ValidatorMetaData> iterator = 
validatorMap.values().iterator(); iterator.hasNext();) {
+            ValidatorMetaData value = iterator.next();
+            if (value.serviceReference.equals(serviceReference)) {
+               iterator.remove();
+               return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean remove(@Nonnull Map<String, Object> properties, @Nonnull 
Validator<?> validator, ServiceReference<Validator<?>> serviceReference) {
+        String validatorId = getValidatorIdFromServiceProperties(properties, 
validator.getClass(), serviceReference);
+        return remove(validatorId, serviceReference);
+    }
+    
+    public boolean remove(String id, ServiceReference<Validator<?>> 
serviceReference) {
+        // only actually remove if the service reference is equal
+        if (id == null) {
+            // find by service reference
+        }
+        ValidatorMetaData entry = validatorMap.get(id);
+        if (entry == null) {
+            LOG.warn("Could not remove validator with id '{}' from map, 
because it is not there!", id);
+            return false;
+        } else {
+            // only actually remove if the service reference is equal
+            if (entry.serviceReference.equals(serviceReference)) {
+                return true;
+            } else {
+                LOG.warn("Could not remove validator with id '{}' from map 
because it is only contained with a different service reference!", id);
+                return false;
+            }
+        }
+    }
+
+    public ValidatorMetaData get(String id) {
+        return validatorMap.get(id);
+    }
+}

Propchange: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidatorMap.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ParameterizedValidatorImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ParameterizedValidatorImpl.java?rev=1787945&r1=1787944&r2=1787945&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ParameterizedValidatorImpl.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/model/ParameterizedValidatorImpl.java
 Tue Mar 21 12:03:33 2017
@@ -25,15 +25,11 @@ import javax.annotation.Nonnull;
 
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.wrappers.ValueMapDecorator;
-import org.apache.sling.validation.impl.util.ValidatorTypeUtil;
-import org.apache.sling.validation.model.ParameterizedValidator;
-import org.apache.sling.validation.model.ValidatorAndSeverity;
-import org.apache.sling.validation.spi.Validator;
+import org.apache.sling.validation.model.ValidatorInvocation;
 
-public class ParameterizedValidatorImpl implements ParameterizedValidator {
-    private final @Nonnull Validator<?> validator;
+public class ParameterizedValidatorImpl implements ValidatorInvocation {
+    private final @Nonnull String id; 
     private final @Nonnull Map<String, Object> parameters;
-    private final @Nonnull Class<?> type;
     private final Integer severity;
     
     /**
@@ -43,27 +39,20 @@ public class ParameterizedValidatorImpl
      * @param parameters
      * @param severity
      */
-    public ParameterizedValidatorImpl(@Nonnull ValidatorAndSeverity<?> 
validator, @Nonnull Map<String, Object> parameters, Integer severity) {
+    public ParameterizedValidatorImpl(@Nonnull String id, @Nonnull Map<String, 
Object> parameters, Integer severity) {
         super();
-        this.validator = validator.getValidator();
+        this.id = id;
         this.parameters = parameters;
-        // cache type information as this is using reflection
-        this.type = ValidatorTypeUtil.getValidatorType(this.validator);
-        if (severity == null) {
-            this.severity = validator.getSeverity();
-        } else {
-            this.severity = severity;
-        }
+        this.severity = severity;
     }
+    
 
-    /* (non-Javadoc)
-     * @see 
org.apache.sling.validation.impl.ParameterizedValidator#getValidator()
-     */
     @Override
-    public @Nonnull Validator<?> getValidator() {
-        return validator;
+    public String getValidatorId() {
+        return id;
     }
-    
+
+
     /* (non-Javadoc)
      * @see 
org.apache.sling.validation.impl.ParameterizedValidator#getParameters()
      */
@@ -71,14 +60,6 @@ public class ParameterizedValidatorImpl
     public @Nonnull ValueMap getParameters() {
         return new ValueMapDecorator(parameters);
     }
-    
-    /* (non-Javadoc)
-     * @see org.apache.sling.validation.impl.ParameterizedValidator#getType()
-     */
-    @Override
-    public @Nonnull Class<?> getType() {
-        return type;
-    }
 
     @Override
     @CheckForNull
@@ -86,23 +67,18 @@ public class ParameterizedValidatorImpl
         return severity;
     }
 
-    @Override
-    public String toString() {
-        return "ParameterizedValidatorImpl [validator=" + validator + ", 
parameters=" + parameters + ", type=" + type
-                + ", severity=" + severity + "]";
-    }
 
-     @Override
+    @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
+        result = prime * result + ((id == null) ? 0 : id.hashCode());
         result = prime * result + ((parameters == null) ? 0 : 
parameters.hashCode());
-        result = prime * result + ((type == null) ? 0 : type.hashCode());
-        result = prime * result + ((validator == null) ? 0 : 
validator.hashCode());
         result = prime * result + ((severity == null) ? 0 : 
severity.hashCode());
         return result;
     }
 
+
     @Override
     public boolean equals(Object obj) {
         if (this == obj)
@@ -112,19 +88,28 @@ public class ParameterizedValidatorImpl
         if (getClass() != obj.getClass())
             return false;
         ParameterizedValidatorImpl other = (ParameterizedValidatorImpl) obj;
-        if (!parameters.equals(other.parameters))
-            return false;
-        if (!type.equals(other.type))
-            return false;
-        if 
(!validator.getClass().getName().equals(other.validator.getClass().getName()))
-            return false;
-        if (severity == null && other.severity != null) {
-            return false;
-        } else if (severity != null && other.severity == null) {
+        if (id == null) {
+            if (other.id != null)
+                return false;
+        } else if (!id.equals(other.id))
+            return false;
+        if (parameters == null) {
+            if (other.parameters != null)
+                return false;
+        } else if (!parameters.equals(other.parameters))
             return false;
-        } else if (severity != null && other.severity != null && 
!severity.equals(other.severity)) {
+        if (severity == null) {
+            if (other.severity != null)
+                return false;
+        } else if (!severity.equals(other.severity))
             return false;
-        }
         return true;
     }
+
+
+    @Override
+    public String toString() {
+        return "ParameterizedValidatorImpl [id=" + id + ", parameters=" + 
parameters + ", severity=" + severity + "]";
+    }
+
 }

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=1787945&r1=1787944&r2=1787945&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
 Tue Mar 21 12:03:33 2017
@@ -25,19 +25,18 @@ import java.util.Map;
 
 import javax.annotation.Nonnull;
 
-import org.apache.sling.validation.model.ParameterizedValidator;
+import org.apache.sling.validation.model.ValidatorInvocation;
 import org.apache.sling.validation.model.ResourceProperty;
-import org.apache.sling.validation.model.ValidatorAndSeverity;
 
 public class ResourcePropertyBuilder {
 
     private boolean optional;
     private boolean multiple;
     private String nameRegex;
-    private final @Nonnull List<ParameterizedValidator> validators;
+    private final @Nonnull List<ValidatorInvocation> validators;
 
     public ResourcePropertyBuilder() {
-        validators = new ArrayList<ParameterizedValidator>();
+        validators = new ArrayList<ValidatorInvocation>();
         this.nameRegex = null;
         this.optional = false;
         this.multiple = false;
@@ -51,15 +50,7 @@ public class ResourcePropertyBuilder {
     /** 
      * should only be used from test classes 
      */
-    public @Nonnull ResourcePropertyBuilder validator(@Nonnull 
ValidatorAndSeverity<?> 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 
ValidatorAndSeverity<?> validator, Integer severity, String... 
parametersNamesAndValues) {
+    public @Nonnull ResourcePropertyBuilder validator(@Nonnull String id, 
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)");
         }
@@ -68,11 +59,11 @@ public class ResourcePropertyBuilder {
         for (int i=0; i<parametersNamesAndValues.length; i=i+2) {
             parameterMap.put(parametersNamesAndValues[i], 
parametersNamesAndValues[i+1]);
         }
-        return validator(validator, severity, parameterMap);
+        return validator(id, severity, parameterMap);
     }
     
-    public @Nonnull ResourcePropertyBuilder validator(@Nonnull 
ValidatorAndSeverity<?> validator, Integer severity, @Nonnull Map<String, 
Object> parameters) {
-        validators.add(new ParameterizedValidatorImpl(validator, parameters, 
severity));
+    public @Nonnull ResourcePropertyBuilder validator(@Nonnull String id, 
Integer severity, @Nonnull Map<String, Object> parameters) {
+        validators.add(new ParameterizedValidatorImpl(id, 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=1787945&r1=1787944&r2=1787945&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
 Tue Mar 21 12:03:33 2017
@@ -24,7 +24,7 @@ import java.util.regex.PatternSyntaxExce
 
 import javax.annotation.Nonnull;
 
-import org.apache.sling.validation.model.ParameterizedValidator;
+import org.apache.sling.validation.model.ValidatorInvocation;
 import org.apache.sling.validation.model.ResourceProperty;
 
 public class ResourcePropertyImpl implements ResourceProperty {
@@ -32,7 +32,7 @@ public class ResourcePropertyImpl implem
     private final @Nonnull String name;
     private final boolean isMultiple;
     private final boolean isRequired;
-    private final @Nonnull List<ParameterizedValidator> validators;
+    private final @Nonnull List<ValidatorInvocation> validators;
     private final Pattern namePattern;
 
     /**
@@ -45,7 +45,7 @@ public class ResourcePropertyImpl implem
      * @throws IllegalArgumentException
      */
     protected ResourcePropertyImpl(@Nonnull String name, String nameRegex, 
boolean isMultiple, boolean isRequired,
-            @Nonnull List<ParameterizedValidator> validators) throws 
IllegalArgumentException {
+            @Nonnull List<ValidatorInvocation> validators) throws 
IllegalArgumentException {
         if (nameRegex != null) {
             try {
                 this.namePattern = Pattern.compile(nameRegex);
@@ -82,7 +82,7 @@ public class ResourcePropertyImpl implem
     }
 
     @Override
-    public @Nonnull List<ParameterizedValidator> getValidators() {
+    public @Nonnull List<ValidatorInvocation> getValidatorInvocations() {
         return validators;
     }
 

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=1787945&r1=1787944&r2=1787945&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
 Tue Mar 21 12:03:33 2017
@@ -46,9 +46,7 @@ import org.apache.sling.validation.impl.
 import org.apache.sling.validation.model.ChildResource;
 import org.apache.sling.validation.model.ResourceProperty;
 import org.apache.sling.validation.model.ValidationModel;
-import org.apache.sling.validation.model.ValidatorAndSeverity;
 import org.apache.sling.validation.model.spi.ValidationModelProvider;
-import org.apache.sling.validation.spi.Validator;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.annotations.Activate;
@@ -215,14 +213,13 @@ public class ResourceValidationModelProv
     /*
      * (non-Javadoc)
      * 
-     * @see 
org.apache.sling.validation.model.spi.ValidationModelProvider#getModels(java.lang.String,
 java.util.Map)
+     * @see 
org.apache.sling.validation.model.spi.ValidationModelProvider#getModels(java.lang.String)
      */
     @Override
-    public @Nonnull List<ValidationModel> getModels(@Nonnull String 
relativeResourceType,
-            @Nonnull Map<String, ValidatorAndSeverity<?>> validatorsMap) {
+    public @Nonnull List<ValidationModel> getModels(@Nonnull String 
relativeResourceType) {
         List<ValidationModel> cacheEntry = 
validationModelCacheByResourceType.get(relativeResourceType);
         if (cacheEntry == null) {
-            cacheEntry = doGetModels(relativeResourceType, validatorsMap);
+            cacheEntry = doGetModels(relativeResourceType);
             validationModelCacheByResourceType.put(relativeResourceType, 
cacheEntry);
         } else {
             LOG.debug("Found entry in cache for resource type {}", 
relativeResourceType);
@@ -233,13 +230,11 @@ public class ResourceValidationModelProv
     /** 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".
      * @throws IllegalStateException in case a validation model is found but 
it is invalid */
     @Nonnull
-    private List<ValidationModel> doGetModels(@Nonnull String 
relativeResourceType, @Nonnull Map<String, ValidatorAndSeverity<?>> 
validatorsMap) {
+    private List<ValidationModel> doGetModels(@Nonnull String 
relativeResourceType) {
         List<ValidationModel> validationModels = new 
ArrayList<ValidationModel>();
         ResourceResolver resourceResolver = null;
         try {
@@ -258,8 +253,8 @@ public class ResourceValidationModelProv
                         ValueMap validationModelProperties = 
model.getValueMap();
                         
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));
+                        
modelBuilder.resourceProperties(buildProperties(propertiesResource));
+                        modelBuilder.childResources(buildChildren(model, 
model));
                         ValidationModel vm = 
modelBuilder.build(relativeResourceType, resourcePath);
                         validationModels.add(vm);
                     } catch (IllegalArgumentException e) {
@@ -286,11 +281,10 @@ public class ResourceValidationModelProv
 
     /** Creates a set of the properties that a resource is expected to have, 
together with the associated validators.
      *
-     * @param validatorsMap a map containing {@link Validator}s as values and 
their id's as keys
      * @param propertiesResource the resource identifying the properties node 
from a validation model's structure (might be {@code null})
      * @return a set of properties or an empty set if no properties are defined
      * @see ResourceProperty */
-    private @Nonnull List<ResourceProperty> buildProperties(@Nonnull 
Map<String, ValidatorAndSeverity<?>> validatorsMap, Resource 
propertiesResource) {
+    private @Nonnull List<ResourceProperty> buildProperties(@Nonnull Resource 
propertiesResource) {
         List<ResourceProperty> properties = new ArrayList<ResourceProperty>();
         if (propertiesResource != null) {
             for (Resource propertyResource : propertiesResource.getChildren()) 
{
@@ -318,10 +312,7 @@ public class ResourceValidationModelProv
                                     "Could not adapt resource at '" + 
validatorResource.getPath() + "' to ValueMap");
                         }
                         String validatorId = validatorResource.getName();
-                        ValidatorAndSeverity<?> validator = 
validatorsMap.get(validatorId);
-                        if (validator == null) {
-                            throw new IllegalArgumentException("Could not find 
validator with id '" + validatorId + "'");
-                        }
+                        
                         // get arguments for validator
                         String[] validatorArguments = 
validatorProperties.get(ResourceValidationModelProviderImpl.VALIDATOR_ARGUMENTS,
                                 String[].class);
@@ -357,7 +348,7 @@ public class ResourceValidationModelProv
                         }
                         // get severity
                         Integer severity = validatorProperties.get(SEVERITY, 
Integer.class);
-                        resourcePropertyBuilder.validator(validator, severity, 
validatorArgumentsMap);
+                        resourcePropertyBuilder.validator(validatorId, 
severity, validatorArgumentsMap);
                     }
                 }
                 properties.add(resourcePropertyBuilder.build(fieldName));
@@ -372,10 +363,8 @@ public class ResourceValidationModelProv
      * @param modelResource the resource describing a {@link 
org.apache.sling.validation.api.ValidationModel}
      * @param rootResource the model's resource from which to search for 
children (this resource has to have a
      *            {@link ResourceValidationModelProviderImpl#CHILDREN} node 
directly underneath it)
-     * @param validatorsMap a map containing {@link Validator}s as values and 
their class names as values
      * @return a list of all the children resources; the list will be empty if 
there are no children resources */
-    private @Nonnull List<ChildResource> buildChildren(@Nonnull Resource 
modelResource, @Nonnull Resource rootResource,
-            @Nonnull Map<String, ValidatorAndSeverity<?>> validatorsMap) {
+    private @Nonnull List<ChildResource> buildChildren(@Nonnull Resource 
modelResource, @Nonnull Resource rootResource) {
         List<ChildResource> children = new ArrayList<ChildResource>();
         Resource childrenResource = 
rootResource.getChild(ResourceValidationModelProviderImpl.CHILDREN);
         if (childrenResource != null) {
@@ -395,8 +384,8 @@ public class ResourceValidationModelProv
                 }
                 boolean isRequired = 
!childrenProperties.get(ResourceValidationModelProviderImpl.OPTIONAL, false);
                 ChildResource childResource = new ChildResourceImpl(name, 
nameRegex, isRequired,
-                        buildProperties(validatorsMap, 
child.getChild(ResourceValidationModelProviderImpl.PROPERTIES)),
-                        buildChildren(modelResource, child, validatorsMap));
+                        
buildProperties(child.getChild(ResourceValidationModelProviderImpl.PROPERTIES)),
+                        buildChildren(modelResource, child));
                 children.add(childResource);
             }
         }

Modified: 
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationModelRetrieverImplTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationModelRetrieverImplTest.java?rev=1787945&r1=1787944&r2=1787945&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationModelRetrieverImplTest.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationModelRetrieverImplTest.java
 Tue Mar 21 12:03:33 2017
@@ -21,7 +21,6 @@ package org.apache.sling.validation.impl
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -36,11 +35,8 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.validation.impl.model.ResourcePropertyBuilder;
 import org.apache.sling.validation.impl.model.ValidationModelBuilder;
 import org.apache.sling.validation.impl.util.ResourcePropertyNameMatcher;
-import org.apache.sling.validation.impl.util.examplevalidators.DateValidator;
-import org.apache.sling.validation.impl.util.examplevalidators.StringValidator;
 import org.apache.sling.validation.model.ResourceProperty;
 import org.apache.sling.validation.model.ValidationModel;
-import org.apache.sling.validation.model.ValidatorAndSeverity;
 import org.apache.sling.validation.model.spi.ValidationModelProvider;
 import org.apache.sling.validation.spi.Validator;
 import org.hamcrest.Matchers;
@@ -51,14 +47,11 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.ServiceReference;
 
 @RunWith(MockitoJUnitRunner.class)
 public class ValidationModelRetrieverImplTest {
 
     private ValidationModelRetrieverImpl validationModelRetriever;
-    private Validator<Date> dateValidator;
     private MultiValuedMap<String, String> applicablePathPerResourceType;
     private TestModelProvider modelProvider;
     
@@ -66,15 +59,9 @@ public class ValidationModelRetrieverImp
     private ResourceResolver resourceResolver;
     @Mock
     private ResourceResolverFactory resourceResolverFactory;
-    @Mock
-    private ServiceReference<Validator<?>> validatorServiceReference;
-    @Mock
-    private ServiceReference<Validator<?>> newValidatorServiceReference;
-    @Mock
-    private Bundle providingBundle;
-    
-    private static final String DATE_VALIDATOR_ID = "DateValidator";
 
+
+    private static final String DATE_VALIDATOR_ID = "DateValidator";
     /**
      * Test model provider which only provides models for all resource types 
in map applicablePathPerResourceType with their according applicablePath!
      * In addition those models have an (empty) resource property with a name 
equal to validated resource type.
@@ -87,12 +74,7 @@ public class ValidationModelRetrieverImp
         }
         
         @Override
-        public @Nonnull List<ValidationModel> getModels(@Nonnull String 
relativeResourceType,
-                @Nonnull Map<String, ValidatorAndSeverity<?>> validatorsMap) {
-            // make sure the date validator is passed along
-            Assert.assertThat(validatorsMap,
-                    Matchers.<String, ValidatorAndSeverity<?>> 
hasEntry(DATE_VALIDATOR_ID, new ValidatorAndSeverity<Date>(dateValidator, 1)));
-
+        public @Nonnull List<ValidationModel> getModels(@Nonnull String 
relativeResourceType) {
             List<ValidationModel> models = new ArrayList<ValidationModel>();
             Collection<String> applicablePaths = 
applicablePathPerResourceType.get(relativeResourceType);
             if (applicablePaths != null) {
@@ -111,60 +93,19 @@ public class ValidationModelRetrieverImp
 
     @Before
     public void setup() throws LoginException {
-        dateValidator =  new DateValidator();
         applicablePathPerResourceType = new ArrayListValuedHashMap<>();
         validationModelRetriever = new ValidationModelRetrieverImpl();
         modelProvider = new TestModelProvider("source1");
         validationModelRetriever.modelProviders = new ArrayList<>();
         validationModelRetriever.modelProviders.add(modelProvider);
-        Mockito.doReturn(1l).when(providingBundle).getBundleId();
-        
Mockito.doReturn(providingBundle).when(validatorServiceReference).getBundle();
-        
Mockito.doReturn(providingBundle).when(newValidatorServiceReference).getBundle();
+        
         Map<String, Object> validatorProperties = new HashMap<>();
         validatorProperties.put(Validator.PROPERTY_VALIDATOR_ID, 
DATE_VALIDATOR_ID);
         validatorProperties.put(Validator.PROPERTY_VALIDATOR_SEVERITY, 1);
-        validationModelRetriever.addValidator(dateValidator, 
validatorProperties, validatorServiceReference);
         validationModelRetriever.resourceResolverFactory = 
resourceResolverFactory;
         
Mockito.when(resourceResolverFactory.getServiceResourceResolver(Mockito.anyObject())).thenReturn(resourceResolver);
     }
     
-    @Test(expected=IllegalArgumentException.class)
-    public void testAddValidatorWithoutValidatorIdProperty() {
-        Map<String, Object> validatorProperties = new HashMap<>();
-        validationModelRetriever.addValidator(dateValidator, 
validatorProperties, validatorServiceReference);
-    }
-    
-    @Test(expected=IllegalArgumentException.class)
-    public void testAddValidatorWithWronglyTypedValidatorId() {
-        Map<String, Object> validatorProperties = new HashMap<>();
-        validatorProperties.put(Validator.PROPERTY_VALIDATOR_ID, new 
String[]{"some", "value"});
-        validationModelRetriever.addValidator(dateValidator, 
validatorProperties, validatorServiceReference);
-    }
-
-    @Test
-    public void 
testAddOverloadingValidatorWithSameValidatorIdAndHigherRanking() {
-        Map<String, Object> validatorProperties = new HashMap<>();
-        validatorProperties.put(Validator.PROPERTY_VALIDATOR_ID, 
DATE_VALIDATOR_ID);
-        validatorProperties.put(Validator.PROPERTY_VALIDATOR_SEVERITY, 2);
-        
Mockito.doReturn(1).when(newValidatorServiceReference).compareTo(Mockito.anyObject());
-        Validator<String> stringValidator = new StringValidator();
-        validationModelRetriever.addValidator(stringValidator, 
validatorProperties, newValidatorServiceReference);
-        Assert.assertEquals(new ValidatorAndSeverity<>(stringValidator, 2), 
validationModelRetriever.validators.get(DATE_VALIDATOR_ID));
-        Assert.assertEquals(newValidatorServiceReference, 
validationModelRetriever.validatorServiceReferences.get(DATE_VALIDATOR_ID));
-    }
-    
-    @Test
-    public void 
testAddOverloadingValidatorWithSameValidatorIdAndLowerRanking() {
-        Map<String, Object> validatorProperties = new HashMap<>();
-        validatorProperties.put(Validator.PROPERTY_VALIDATOR_ID, 
DATE_VALIDATOR_ID);
-        validatorProperties.put(Validator.PROPERTY_VALIDATOR_SEVERITY, 2);
-        
Mockito.doReturn(-1).when(newValidatorServiceReference).compareTo(Mockito.anyObject());
-        Validator<String> stringValidator = new StringValidator();
-        validationModelRetriever.addValidator(stringValidator, 
validatorProperties, newValidatorServiceReference);
-        Assert.assertEquals(new ValidatorAndSeverity<>(dateValidator, 1), 
validationModelRetriever.validators.get(DATE_VALIDATOR_ID));
-        Assert.assertEquals(validatorServiceReference, 
validationModelRetriever.validatorServiceReferences.get(DATE_VALIDATOR_ID));
-    }
-
     @Test
     public void testGetModel() {
         applicablePathPerResourceType.put("test/type", "/content/site1");

Modified: 
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java?rev=1787945&r1=1787944&r2=1787945&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java
 (original)
+++ 
sling/trunk/bundles/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java
 Tue Mar 21 12:03:33 2017
@@ -1,20 +1,20 @@
 /*
-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
+ * 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
+ * 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.
+ * 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.validation.impl;
 
@@ -44,9 +44,9 @@ import org.apache.sling.api.wrappers.Val
 import org.apache.sling.i18n.ResourceBundleProvider;
 import org.apache.sling.jcr.resource.JcrResourceConstants;
 import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.apache.sling.validation.SlingValidationException;
 import org.apache.sling.validation.ValidationFailure;
 import org.apache.sling.validation.ValidationResult;
-import org.apache.sling.validation.SlingValidationException;
 import org.apache.sling.validation.impl.model.ChildResourceImpl;
 import org.apache.sling.validation.impl.model.ResourcePropertyBuilder;
 import org.apache.sling.validation.impl.model.ValidationModelBuilder;
@@ -55,7 +55,6 @@ import org.apache.sling.validation.impl.
 import org.apache.sling.validation.model.ChildResource;
 import org.apache.sling.validation.model.ResourceProperty;
 import org.apache.sling.validation.model.ValidationModel;
-import org.apache.sling.validation.model.ValidatorAndSeverity;
 import org.apache.sling.validation.model.spi.ValidationModelRetriever;
 import org.apache.sling.validation.spi.DefaultValidationFailure;
 import org.apache.sling.validation.spi.DefaultValidationResult;
@@ -70,6 +69,8 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
 
 @RunWith(MockitoJUnitRunner.class)
 public class ValidationServiceImplTest {
@@ -94,27 +95,75 @@ public class ValidationServiceImplTest {
     
     @Mock
     private ResourceBundleProvider resourceBundleProvider;
-
+    
+    @Mock
+    private ValidationModelRetriever modelRetriever;
+    private Validator<Date> dateValidator;
+    
+    @Mock
+    private ServiceReference<Validator<?>> validatorServiceReference;
+    @Mock
+    private ServiceReference<Validator<?>> newValidatorServiceReference;
+    @Mock
+    private Bundle providingBundle;
+    
+    private static final String DATE_VALIDATOR_ID = "DateValidator";
+    private static final String REGEX_VALIDATOR_ID = "RegexValidator";
+    
     @Before
     public void setUp() throws LoginException, PersistenceException, 
RepositoryException {
         validationService = new ValidationServiceImpl();
         validationService.searchPaths = 
Arrays.asList(context.resourceResolver().getSearchPath());
         validationService.configuration = configuration;
+        validationService.validatorMap = new ValidatorMap();
         Mockito.doReturn(20).when(configuration).defaultSeverity();
         validationService.resourceBundleProviders = 
Collections.singletonList(resourceBundleProvider);
         
Mockito.doReturn(defaultResourceBundle).when(resourceBundleProvider).getResourceBundle(Mockito.anyObject());
         modelBuilder = new ValidationModelBuilder();
         propertyBuilder = new ResourcePropertyBuilder();
+        dateValidator =  new DateValidator();
+        Mockito.doReturn(1l).when(providingBundle).getBundleId();
+        
Mockito.doReturn(providingBundle).when(validatorServiceReference).getBundle();
+        
Mockito.doReturn(providingBundle).when(newValidatorServiceReference).getBundle();
+        validationService.validatorMap.put(DATE_VALIDATOR_ID, dateValidator, 
validatorServiceReference, 10);
+        validationService.validatorMap.put(REGEX_VALIDATOR_ID, new 
RegexValidator(), validatorServiceReference, 10);
+        validationService.modelRetriever = modelRetriever;
+    }
+
+    @Test
+    public void testGetValidationModelWithAbsolutePath() throws Exception {
+        // check conversion to relative resource type
+        validationService.getValidationModel("/libs/some/type", "some path", 
true);
+        Mockito.verify(modelRetriever).getModel("some/type", "some path", 
true);
     }
 
     @Test
-    public void testGetValidationModel() throws Exception {
+    public void testGetValidationModelWithRelativePath() throws Exception {
+        // check conversion to relative resource type
+        validationService.getValidationModel("some/type", "some path", true);
+        Mockito.verify(modelRetriever).getModel("some/type", "some path", 
true);
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void testGetValidationModelWithAbsolutePathOutsideSearchPath() 
throws Exception {
+        // check conversion to relative resource type
+        validationService.getValidationModel("/content/some/type", "some 
path", true);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testValidateWithInvalidValidatorId() throws Exception {
+        propertyBuilder.validator("invalidid", 10);
+        modelBuilder.resourceProperty(propertyBuilder.build("field1"));
+        ValidationModel vm = modelBuilder.build("sling/validation/test", "some 
source");
 
+        HashMap<String, Object> hashMap = new HashMap<String, Object>();
+        hashMap.put("field1", "1");
+        validationService.validate(new ValueMapDecorator(hashMap), vm);
     }
 
     @Test()
     public void testValueMapWithWrongDataType() throws Exception {
-        propertyBuilder.validator(new ValidatorAndSeverity<Date>(new 
DateValidator(), 10));
+        propertyBuilder.validator(DATE_VALIDATOR_ID, 10);
         modelBuilder.resourceProperty(propertyBuilder.build("field1"));
         ValidationModel vm = modelBuilder.build("sling/validation/test", "some 
source");
 
@@ -138,7 +187,8 @@ public class ValidationServiceImplTest {
                 return DefaultValidationResult.VALID;
             }
         };
-        propertyBuilder.validator(new 
ValidatorAndSeverity<String>(myValidator, 10));
+        validationService.validatorMap.put("someId", myValidator, 
validatorServiceReference, 10);
+        propertyBuilder.validator("someId", 20);
         modelBuilder.resourceProperty(propertyBuilder.build("field1"));
         ValidationModel vm = modelBuilder.build("sling/validation/test", "some 
source");
 
@@ -182,7 +232,7 @@ public class ValidationServiceImplTest {
     @Test()
     public void testValueMapWithEmptyOptionalValue() throws Exception {
         propertyBuilder.optional();
-        propertyBuilder.validator(new ValidatorAndSeverity<String>(new 
RegexValidator(), 2), null, RegexValidator.REGEX_PARAM, "abc");
+        propertyBuilder.validator(REGEX_VALIDATOR_ID, null, 
RegexValidator.REGEX_PARAM, "abc");
         modelBuilder.resourceProperty(propertyBuilder.build("field1"));
         ValidationModel vm = modelBuilder.build("sling/validation/test", "some 
source");
 
@@ -190,17 +240,17 @@ public class ValidationServiceImplTest {
         hashMap.put("field1", "");
         ValidationResult vr = validationService.validate(new 
ValueMapDecorator(hashMap), vm);
 
-        Assert.assertFalse(vr.isValid()); // check for correct error message 
Map<String, List<String>>
-        Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(new DefaultValidationFailure("field1", 2, 
defaultResourceBundle, RegexValidator.I18N_KEY_PATTERN_DOES_NOT_MATCH, "abc")));
+        Assert.assertFalse(vr.isValid());
+        Assert.assertThat(vr.getFailures(), 
Matchers.<ValidationFailure>contains(new DefaultValidationFailure("field1", 10, 
defaultResourceBundle, RegexValidator.I18N_KEY_PATTERN_DOES_NOT_MATCH, "abc")));
     }
 
     @Test
     public void testValueMapWithCorrectDataType() throws Exception {
-        propertyBuilder.validator(new ValidatorAndSeverity<String>(new 
RegexValidator(), 2), 0, RegexValidator.REGEX_PARAM, "abc");
+        propertyBuilder.validator(REGEX_VALIDATOR_ID, 0, 
RegexValidator.REGEX_PARAM, "abc");
         modelBuilder.resourceProperty(propertyBuilder.build("field1"));
         propertyBuilder = new ResourcePropertyBuilder();
         final String TEST_REGEX = "^test$";
-        propertyBuilder.validator(new ValidatorAndSeverity<String>(new 
RegexValidator(), 2), 0, RegexValidator.REGEX_PARAM, TEST_REGEX);
+        propertyBuilder.validator(REGEX_VALIDATOR_ID, 0, 
RegexValidator.REGEX_PARAM, TEST_REGEX);
         modelBuilder.resourceProperty(propertyBuilder.build("field2"));
         ValidationModel vm = modelBuilder.build("sling/validation/test", "some 
source");
 
@@ -217,7 +267,7 @@ public class ValidationServiceImplTest {
     // see https://issues.apache.org/jira/browse/SLING-5674
     @Test
     public void testNonExistingResource() throws Exception {
-        propertyBuilder.validator(new ValidatorAndSeverity<String>(new 
RegexValidator(), 2), 0, RegexValidator.REGEX_PARAM, "\\d"); // accept any 
digits
+        propertyBuilder.validator(REGEX_VALIDATOR_ID, 0, 
RegexValidator.REGEX_PARAM, "\\d"); // accept any digits
         ResourceProperty property = propertyBuilder.build("field1");
         modelBuilder.resourceProperty(property);
         
@@ -241,7 +291,7 @@ public class ValidationServiceImplTest {
     // see https://issues.apache.org/jira/browse/SLING-5749
     @Test
     public void testSyntheticResource() throws Exception {
-        propertyBuilder.validator(new ValidatorAndSeverity<String>(new 
RegexValidator(), 2), 0, RegexValidator.REGEX_PARAM, "\\d"); // accept any 
digits
+        propertyBuilder.validator(REGEX_VALIDATOR_ID, 0, 
RegexValidator.REGEX_PARAM, "\\d"); // accept any digits
         ResourceProperty property = propertyBuilder.build("field1");
         modelBuilder.resourceProperty(property);
         
@@ -264,7 +314,7 @@ public class ValidationServiceImplTest {
 
     @Test
     public void testResourceWithMissingGrandChildProperty() throws Exception {
-        propertyBuilder.validator(new ValidatorAndSeverity<String>(new 
RegexValidator(), 2), 0, RegexValidator.REGEX_PARAM, "\\d"); // accept any 
digits
+        propertyBuilder.validator(REGEX_VALIDATOR_ID, 0, 
RegexValidator.REGEX_PARAM, "\\d"); // accept any digits
         ResourceProperty property = propertyBuilder.build("field1");
         modelBuilder.resourceProperty(property);
 
@@ -296,7 +346,7 @@ public class ValidationServiceImplTest {
 
     @Test
     public void testResourceWithMissingOptionalChildResource() throws 
Exception {
-        propertyBuilder.validator(new ValidatorAndSeverity<String>(new 
RegexValidator(), 2), 0, RegexValidator.REGEX_PARAM, "\\d"); // accept any 
digits
+        propertyBuilder.validator(REGEX_VALIDATOR_ID, 0, 
RegexValidator.REGEX_PARAM, "\\d"); // accept any digits
         ResourceProperty property = propertyBuilder.build("field1");
 
         ChildResource child = new ChildResourceImpl("child", null, false, 
Collections.singletonList(property),
@@ -316,7 +366,7 @@ public class ValidationServiceImplTest {
 
     @Test
     public void testResourceWithNestedChildren() throws Exception {
-        propertyBuilder.validator(new ValidatorAndSeverity<String>(new 
RegexValidator(), 2), 0, RegexValidator.REGEX_PARAM, "\\d"); // accept any 
digits
+        propertyBuilder.validator(REGEX_VALIDATOR_ID, 0, 
RegexValidator.REGEX_PARAM, "\\d"); // accept any digits
         ResourceProperty property = propertyBuilder.build("field1");
 
         ChildResource modelGrandChild = new ChildResourceImpl("grandchild", 
null, true,
@@ -342,7 +392,7 @@ public class ValidationServiceImplTest {
 
     @Test
     public void testResourceWithValidatorLeveragingTheResource() throws 
Exception {
-        ValidatorAndSeverity<String> extendedValidator = new 
ValidatorAndSeverity<String>(new Validator<String>() {
+        Validator<String> extendedValidator = new Validator<String>() {
             @Override
             @Nonnull
             public ValidationResult validate(@Nonnull String data, @Nonnull 
ValidationContext context, @Nonnull ValueMap arguments)
@@ -356,8 +406,10 @@ public class ValidationServiceImplTest {
                 return DefaultValidationResult.VALID;
             }
             
-        }, 0);
-        propertyBuilder.validator(extendedValidator); // accept any digits
+        };
+        // register validator
+        validationService.validatorMap.put("myid", extendedValidator, 
newValidatorServiceReference, null);
+        propertyBuilder.validator("myid", null); // accept any digits
         modelBuilder.resourceProperty(propertyBuilder.build("field1"));
         ValidationModel vm = modelBuilder.build("sometype", "some source");
 
@@ -373,7 +425,7 @@ public class ValidationServiceImplTest {
 
     @Test
     public void testResourceWithNestedChildrenAndPatternMatching() throws 
Exception {
-        propertyBuilder.validator(new ValidatorAndSeverity<String>(new 
RegexValidator(), 2), 0, RegexValidator.REGEX_PARAM, "\\d"); // accept any 
digits
+        propertyBuilder.validator(REGEX_VALIDATOR_ID, 0, 
RegexValidator.REGEX_PARAM, "\\d"); // accept any digits
         ResourceProperty property = propertyBuilder.build("field1");
 
         ChildResource modelGrandChild = new ChildResourceImpl("grandchild", 
"grandchild.*", true,
@@ -398,7 +450,7 @@ public class ValidationServiceImplTest {
         // child2 is lacking its mandatory sub resource
         rr.create(testResource, "child2", properties);
         rr.create(testResource, "child3", null);
-        // siblingchild is not there at all (although mandatory)
+        // sibling child is not there at all (although mandatory)
 
         ValidationResult vr = validationService.validate(testResource, vm);
         Assert.assertFalse("resource should have been considered invalid", 
vr.isValid());
@@ -412,7 +464,7 @@ public class ValidationServiceImplTest {
 
     @Test
     public void testResourceWithPropertyPatternMatching() throws Exception {
-        propertyBuilder.validator(new ValidatorAndSeverity<String>(new 
RegexValidator(), 2), 1, RegexValidator.REGEX_PARAM, "\\d"); // accept any 
digits
+        propertyBuilder.validator(REGEX_VALIDATOR_ID, 1, 
RegexValidator.REGEX_PARAM, "\\d"); // accept any digits
         propertyBuilder.nameRegex("field.*");
         modelBuilder.resourceProperty(propertyBuilder.build("field"));
         propertyBuilder.nameRegex("otherfield.*");
@@ -441,7 +493,7 @@ public class ValidationServiceImplTest {
 
     @Test
     public void testResourceWithMultivalueProperties() throws Exception {
-        propertyBuilder.validator(new ValidatorAndSeverity<String>(new 
RegexValidator(), 2), 0, RegexValidator.REGEX_PARAM, "\\d"); // accept any 
digits
+        propertyBuilder.validator(REGEX_VALIDATOR_ID, 0, 
RegexValidator.REGEX_PARAM, "\\d"); // accept any digits
         propertyBuilder.multiple();
         modelBuilder.resourceProperty(propertyBuilder.build("field"));
         ValidationModel vm = modelBuilder.build("type", "some source");


Reply via email to