You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2014/11/27 15:52:30 UTC
svn commit: r1642166 - in /sling/trunk/contrib/extensions/validation:
api/src/main/java/org/apache/sling/validation/api/
core/src/main/java/org/apache/sling/validation/impl/
core/src/main/java/org/apache/sling/validation/impl/util/
core/src/test/java/o...
Author: kwin
Date: Thu Nov 27 14:52:29 2014
New Revision: 1642166
URL: http://svn.apache.org/r1642166
Log:
SLING-4011, allow pattern matching on properties and child resources
also some refactoring of the ValidationServiceImplTest
Modified:
sling/trunk/contrib/extensions/validation/api/src/main/java/org/apache/sling/validation/api/ChildResource.java
sling/trunk/contrib/extensions/validation/api/src/main/java/org/apache/sling/validation/api/ResourceProperty.java
sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ChildResourceImpl.java
sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/Constants.java
sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ResourcePropertyImpl.java
sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java
sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/util/JCRBuilder.java
sling/trunk/contrib/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java
Modified: sling/trunk/contrib/extensions/validation/api/src/main/java/org/apache/sling/validation/api/ChildResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/validation/api/src/main/java/org/apache/sling/validation/api/ChildResource.java?rev=1642166&r1=1642165&r2=1642166&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/validation/api/src/main/java/org/apache/sling/validation/api/ChildResource.java (original)
+++ sling/trunk/contrib/extensions/validation/api/src/main/java/org/apache/sling/validation/api/ChildResource.java Thu Nov 27 14:52:29 2014
@@ -18,7 +18,9 @@
*/
package org.apache.sling.validation.api;
+import java.util.List;
import java.util.Set;
+import java.util.regex.Pattern;
/**
* Defines the validation rules for a child resource, allowing {@link ValidationModel}s to be applied to {@link
@@ -27,11 +29,19 @@ import java.util.Set;
public interface ChildResource {
/**
- * Return this resource's name.
+ * Return this resource's name. This must match the name of the child resource which is validated through this section of the validation model.
+ * Either this method or {@link getNamePattern} must not return {@code null}
*
- * @return the name
+ * @return the name (if one is set) or {@code null)
*/
String getName();
+
+ /**
+ * Returns this resource's name pattern. Either this method or {@link getName} must not return {@code null}
+ *
+ * @return the name pattern (if one is set) or {@code null)
+ */
+ Pattern getNamePattern();
/**
* Returns the properties this child resource is expected to have.
@@ -39,4 +49,10 @@ public interface ChildResource {
* @return the properties set
*/
Set<ResourceProperty> getProperties();
+
+ /**
+ * Returns the child resources of this part of the Validation Model
+ * @return child resources. Never {@code null}.
+ */
+ List<ChildResource> getChildren();
}
Modified: sling/trunk/contrib/extensions/validation/api/src/main/java/org/apache/sling/validation/api/ResourceProperty.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/validation/api/src/main/java/org/apache/sling/validation/api/ResourceProperty.java?rev=1642166&r1=1642165&r2=1642166&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/validation/api/src/main/java/org/apache/sling/validation/api/ResourceProperty.java (original)
+++ sling/trunk/contrib/extensions/validation/api/src/main/java/org/apache/sling/validation/api/ResourceProperty.java Thu Nov 27 14:52:29 2014
@@ -19,6 +19,7 @@
package org.apache.sling.validation.api;
import java.util.List;
+import java.util.regex.Pattern;
/**
* Describes a {@link org.apache.sling.api.resource.Resource} property.
@@ -27,10 +28,18 @@ public interface ResourceProperty {
/**
* Returns the name of this property.
+ * Either this method or {@link getNamePattern} must not return {@code null}
*
- * @return the name
+ * @return the name or {@code null}
*/
String getName();
+
+ /**
+ * Returns the name pattern for this property. Either this method or {@link getName} must not return {@code null}
+ *
+ * @return the name pattern (if one is set) or {@code null)
+ */
+ Pattern getNamePattern();
/**
* Returns {@code true} if this property is expected to be a multiple property (e.g. array of values).
Modified: sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ChildResourceImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ChildResourceImpl.java?rev=1642166&r1=1642165&r2=1642166&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ChildResourceImpl.java (original)
+++ sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ChildResourceImpl.java Thu Nov 27 14:52:29 2014
@@ -1,9 +1,13 @@
package org.apache.sling.validation.impl;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.validation.api.ChildResource;
import org.apache.sling.validation.api.ResourceProperty;
import org.apache.sling.validation.api.Validator;
@@ -14,16 +18,37 @@ import org.apache.sling.validation.impl.
*/
public class ChildResourceImpl implements ChildResource {
- private String name;
- private Set<ResourceProperty> properties;
+ private final String name;
+ private final Pattern namePattern;
+ private final Set<ResourceProperty> properties;
+ private final List<ChildResource> children;
- public ChildResourceImpl(Resource modelResource, Resource childResource, Map<String, Validator<?>> validatorsMap) {
+ public ChildResourceImpl(Resource modelResource, Resource childResource, Map<String, Validator<?>> validatorsMap, List<ChildResource> children) {
String root = modelResource.getPath();
if (!childResource.getPath().startsWith(root)) {
throw new IllegalArgumentException("Expected resource " + childResource.getPath() + " to be under root path " + root);
}
- name = childResource.getPath().replaceFirst(root + "/", "").replaceAll(Constants.CHILDREN + "/", "");
+ // if pattern is set, always use that
+ ValueMap childrenProperties = childResource.adaptTo(ValueMap.class);
+ if (childrenProperties == null) {
+ throw new IllegalStateException("Could not adapt resource " + childResource.getPath() + " to ValueMap");
+ }
+ if (childrenProperties.containsKey(Constants.NAME_REGEX)) {
+ name = null;
+ String regex = childrenProperties.get(Constants.NAME_REGEX, String.class);
+ try {
+ namePattern = Pattern.compile(regex);
+ } catch (PatternSyntaxException e) {
+ throw new IllegalArgumentException("Given regular expression is invalid: " + regex);
+ }
+ } else {
+ // otherwise fall back to the name
+ name = childResource.getName();
+ namePattern = null;
+ }
+
properties = JCRBuilder.buildProperties(validatorsMap, childResource.getChild(Constants.PROPERTIES));
+ this.children = children;
}
@Override
@@ -35,4 +60,13 @@ public class ChildResourceImpl implement
public Set<ResourceProperty> getProperties() {
return properties;
}
+
+ @Override
+ public Pattern getNamePattern() {
+ return namePattern;
+ }
+
+ public List<ChildResource> getChildren() {
+ return children;
+ }
}
Modified: sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/Constants.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/Constants.java?rev=1642166&r1=1642165&r2=1642166&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/Constants.java (original)
+++ sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/Constants.java Thu Nov 27 14:52:29 2014
@@ -33,4 +33,5 @@ public final class Constants {
public static final String VALIDATORS = "validators";
public static final String VALIDATOR_ARGUMENTS = "validatorArguments";
public static final String CHILDREN = "children";
+ public static final String NAME_REGEX = "name-regex";
}
Modified: sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ResourcePropertyImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ResourcePropertyImpl.java?rev=1642166&r1=1642165&r2=1642166&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ResourcePropertyImpl.java (original)
+++ sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ResourcePropertyImpl.java Thu Nov 27 14:52:29 2014
@@ -19,6 +19,7 @@
package org.apache.sling.validation.impl;
import java.util.List;
+import java.util.regex.Pattern;
import org.apache.sling.validation.api.ParameterizedValidator;
import org.apache.sling.validation.api.ResourceProperty;
@@ -28,13 +29,16 @@ public class ResourcePropertyImpl implem
private String name;
private boolean isMultiple;
private List<ParameterizedValidator> validators;
-
- public ResourcePropertyImpl(String name, List<ParameterizedValidator> validators) {
- this(name, false, validators);
- }
-
- public ResourcePropertyImpl(String name, boolean isMultiple, List<ParameterizedValidator> validators) {
- this.name = name;
+ private Pattern namePattern;
+
+ public ResourcePropertyImpl(String name, String nameRegex, boolean isMultiple, List<ParameterizedValidator> validators) {
+ if (nameRegex != null) {
+ this.name = null;
+ this.namePattern = Pattern.compile(nameRegex);
+ } else {
+ this.name = name;
+ this.namePattern = null;
+ }
this.isMultiple = isMultiple;
this.validators = validators;
}
@@ -45,6 +49,11 @@ public class ResourcePropertyImpl implem
}
@Override
+ public Pattern getNamePattern() {
+ return namePattern;
+ }
+
+ @Override
public boolean isMultiple() {
return isMultiple;
}
@@ -53,4 +62,6 @@ public class ResourcePropertyImpl implem
public List<ParameterizedValidator> getValidators() {
return validators;
}
+
+
}
Modified: sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java?rev=1642166&r1=1642165&r2=1642166&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java (original)
+++ sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/ValidationServiceImpl.java Thu Nov 27 14:52:29 2014
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
import javax.jcr.query.Query;
@@ -119,18 +120,50 @@ public class ValidationServiceImpl imple
ValidationResultImpl result = new ValidationResultImpl();
// validate direct properties of the resource
- validateValueMap(resource.adaptTo(ValueMap.class), model.getResourceProperties(), result, "");
+ validateValueMap(resource.adaptTo(ValueMap.class), "", model.getResourceProperties(), result );
// validate children resources, if any
- for (ChildResource childResource : model.getChildren()) {
- Resource expectedResource = resource.getChild(childResource.getName());
- if (expectedResource != null) {
- validateValueMap(expectedResource.adaptTo(ValueMap.class), childResource.getProperties(), result, childResource.getName() + "/");
+ validateChildren(resource, "", model.getChildren(), result);
+ return result;
+ }
+
+ /**
+ * Validates a child resource with the help of the given {@code ChildResource} entry from the validation model
+ * @param resource
+ * @param relativePath relativePath of the resource (must be empty or end with "/")
+ * @param result
+ * @param childResources
+ */
+ private void validateChildren(Resource resource, String relativePath, List<ChildResource> childResources, ValidationResultImpl result) {
+ // validate children resources, if any
+ for (ChildResource childResource : childResources) {
+ // if a pattern is set we validate all children matching that pattern
+ if (childResource.getNamePattern() != null) {
+ boolean foundMatch = false;
+ for (Resource child : resource.getChildren()) {
+ Matcher matcher = childResource.getNamePattern().matcher(child.getName());
+ if (matcher.matches()) {
+ validateChildResource(child, relativePath, childResource, result);
+ foundMatch = true;
+ }
+ }
+ if (!foundMatch) {
+ result.addFailureMessage(relativePath + childResource.getNamePattern().pattern(), "Missing required child resource.");
+ }
} else {
- result.addFailureMessage(childResource.getName(), "Missing required child resource.");
- }
+ Resource expectedResource = resource.getChild(childResource.getName());
+ if (expectedResource != null) {
+ validateChildResource(expectedResource, relativePath, childResource, result);
+ } else {
+ result.addFailureMessage(relativePath + childResource.getName(), "Missing required child resource.");
+ }
+ }
}
- return result;
+ }
+
+ private void validateChildResource(Resource resource, String relativePath, ChildResource childResource, ValidationResultImpl result) {
+ validateValueMap(resource.adaptTo(ValueMap.class), relativePath + resource.getName() + "/", childResource.getProperties(), result);
+ validateChildren(resource, relativePath + resource.getName() + "/", childResource.getChildren(), result);
}
@Override
@@ -139,7 +172,7 @@ public class ValidationServiceImpl imple
throw new IllegalArgumentException("ValidationResult.validate - cannot accept null parameters");
}
ValidationResultImpl result = new ValidationResultImpl();
- validateValueMap(valueMap, model.getResourceProperties(), result, "");
+ validateValueMap(valueMap, "", model.getResourceProperties(), result);
return result;
}
@@ -202,27 +235,44 @@ public class ValidationServiceImpl imple
}
}
- private void validateValueMap(ValueMap valueMap, Set<ResourceProperty> resourceProperties,
- ValidationResultImpl result, String relativePathName) {
+ private void validateValueMap(ValueMap valueMap, String relativePath, Set<ResourceProperty> resourceProperties,
+ ValidationResultImpl result) {
if (valueMap == null) {
throw new IllegalArgumentException("ValueMap may not be null");
}
for (ResourceProperty resourceProperty : resourceProperties) {
- String property = resourceProperty.getName();
- Object fieldValues = valueMap.get(property);
- if (fieldValues == null) {
- result.addFailureMessage(relativePathName + property, "Missing required property.");
- return;
- }
- List<ParameterizedValidator> validators = resourceProperty.getValidators();
- if (resourceProperty.isMultiple()) {
- if (!fieldValues.getClass().isArray()) {
- result.addFailureMessage(relativePathName + property, "Expected multiple-valued property.");
- return;
+ if (resourceProperty.getNamePattern() != null) {
+ boolean foundMatch = false;
+ for (String key : valueMap.keySet()) {
+ if (resourceProperty.getNamePattern().matcher(key).matches()) {
+ foundMatch = true;
+ validateValueMap(key, valueMap, relativePath, resourceProperty, result);
+ }
+ }
+ if (!foundMatch) {
+ result.addFailureMessage(relativePath + resourceProperty.getNamePattern(), "Missing required property.");
}
+ } else {
+ validateValueMap(resourceProperty.getName(), valueMap, relativePath, resourceProperty, result);
+ }
+ }
+ }
+
+
+ private void validateValueMap(String property, ValueMap valueMap, String relativePath, ResourceProperty resourceProperty, ValidationResultImpl result) {
+ Object fieldValues = valueMap.get(property);
+ if (fieldValues == null) {
+ result.addFailureMessage(relativePath + property, "Missing required property.");
+ return;
+ }
+ List<ParameterizedValidator> validators = resourceProperty.getValidators();
+ if (resourceProperty.isMultiple()) {
+ if (!fieldValues.getClass().isArray()) {
+ result.addFailureMessage(relativePath + property, "Expected multiple-valued property.");
+ return;
}
- validatePropertyValue(result, property, relativePathName, valueMap, validators);
}
+ validatePropertyValue(result, property, relativePath, valueMap, validators);
}
/**
Modified: sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/util/JCRBuilder.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/util/JCRBuilder.java?rev=1642166&r1=1642165&r2=1642166&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/util/JCRBuilder.java (original)
+++ sling/trunk/contrib/extensions/validation/core/src/main/java/org/apache/sling/validation/impl/util/JCRBuilder.java Thu Nov 27 14:52:29 2014
@@ -59,6 +59,7 @@ public class JCRBuilder {
String fieldName = property.getName();
ValueMap propertyValueMap = property.adaptTo(ValueMap.class);
Boolean propertyMultiple = PropertiesUtil.toBoolean(propertyValueMap.get(Constants.PROPERTY_MULTIPLE), false);
+ String nameRegex = PropertiesUtil.toString(propertyValueMap.get(Constants.NAME_REGEX), null);
Resource validators = property.getChild(Constants.VALIDATORS);
List<ParameterizedValidator> parameterizedValidators = new ArrayList<ParameterizedValidator>();
if (validators != null) {
@@ -86,7 +87,7 @@ public class JCRBuilder {
parameterizedValidators.add(new ParameterizedValidatorImpl(v, new ValueMapDecorator(validatorArgumentsMap)));
}
}
- ResourceProperty f = new ResourcePropertyImpl(fieldName, propertyMultiple, parameterizedValidators);
+ ResourceProperty f = new ResourcePropertyImpl(fieldName, nameRegex, propertyMultiple, parameterizedValidators);
properties.add(f);
}
}
@@ -109,9 +110,8 @@ public class JCRBuilder {
Resource childrenResource = rootResource.getChild(Constants.CHILDREN);
if (childrenResource != null) {
for (Resource child : childrenResource.getChildren()) {
- ChildResource childResource = new ChildResourceImpl(modelResource, child, validatorsMap);
+ ChildResource childResource = new ChildResourceImpl(modelResource, child, validatorsMap, buildChildren(modelResource, child, validatorsMap));
children.add(childResource);
- children.addAll(buildChildren(modelResource, child, validatorsMap));
}
}
return children;
Modified: sling/trunk/contrib/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java?rev=1642166&r1=1642165&r2=1642166&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java (original)
+++ sling/trunk/contrib/extensions/validation/core/src/test/java/org/apache/sling/validation/impl/ValidationServiceImplTest.java Thu Nov 27 14:52:29 2014
@@ -32,6 +32,7 @@ import java.util.Map;
import org.apache.jackrabbit.JcrConstants;
import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
@@ -78,9 +79,9 @@ public class ValidationServiceImplTest {
});
ResourceResolver rr = rrf.getAdministrativeResourceResolver(null);
if (rr != null) {
- appsValidatorsRoot = ResourceUtil.getOrCreateResource(rr, APPS + "/" + VALIDATION_MODELS_RELATIVE_PATH, (Map) null,
+ appsValidatorsRoot = ResourceUtil.getOrCreateResource(rr, APPS + "/" + VALIDATION_MODELS_RELATIVE_PATH, (Map<String, Object>) null,
"sling:Folder", true);
- libsValidatorsRoot = ResourceUtil.getOrCreateResource(rr, LIBS + "/" + VALIDATION_MODELS_RELATIVE_PATH, (Map) null,
+ libsValidatorsRoot = ResourceUtil.getOrCreateResource(rr, LIBS + "/" + VALIDATION_MODELS_RELATIVE_PATH, (Map<String, Object>) null,
"sling:Folder", true);
rr.close();
}
@@ -113,20 +114,17 @@ public class ValidationServiceImplTest {
public void testGetValidationModel() throws Exception {
validationService.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new RegexValidator());
- List<TestProperty> properties = new ArrayList<TestProperty>();
- TestProperty property = new TestProperty();
- property.name = "field1";
- property.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", null);
- properties.add(property);
+ TestProperty property = new TestProperty("field1");
+ property.addValidator("org.apache.sling.validation.impl.validators.RegexValidator");
ResourceResolver rr = rrf.getAdministrativeResourceResolver(null);
Resource model1 = null, model2 = null;
try {
if (rr != null) {
model1 = createValidationModelResource(rr, libsValidatorsRoot.getPath(), "testValidationModel1", "sling/validation/test",
- new String[]{"/apps/validation"}, properties);
+ new String[]{"/apps/validation"}, property);
model2 = createValidationModelResource(rr, libsValidatorsRoot.getPath(), "testValidationModel2", "sling/validation/test",
new String[]{"/apps/validation/1",
- "/apps/validation/2"}, properties);
+ "/apps/validation/2"}, property);
}
// BEST MATCHING PATH = /apps/validation/1; assume the applicable paths contain /apps/validation/2
@@ -155,22 +153,19 @@ public class ValidationServiceImplTest {
public void testGetValidationModelWithOverlay() throws Exception {
validationService.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new RegexValidator());
- List<TestProperty> fields = new ArrayList<TestProperty>();
- TestProperty field = new TestProperty();
- field.name = "field1";
- field.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", null);
- fields.add(field);
+ TestProperty field = new TestProperty("field1");
+ field.addValidator("org.apache.sling.validation.impl.validators.RegexValidator");
ResourceResolver rr = rrf.getAdministrativeResourceResolver(null);
Resource model1 = null, model2 = null, model3 = null;
try {
if (rr != null) {
model1 = createValidationModelResource(rr, libsValidatorsRoot.getPath(), "testValidationModel1", "sling/validation/test",
- new String[]{"/apps/validation/1"}, fields);
+ new String[]{"/apps/validation/1"}, field);
model2 = createValidationModelResource(rr, appsValidatorsRoot.getPath(), "testValidationModel1", "sling/validation/test",
new String[]{"/apps/validation/1",
- "/apps/validation/2"}, fields);
+ "/apps/validation/2"}, field);
model3 = createValidationModelResource(rr, libsValidatorsRoot.getPath(), "testValidationModel2", "sling/validation/test",
- new String[]{"/apps/validation/3"}, fields);
+ new String[]{"/apps/validation/3"}, field);
}
// BEST MATCHING PATH = /apps/validation/1; assume the applicable paths contain /apps/validation/2
@@ -200,19 +195,16 @@ public class ValidationServiceImplTest {
@Test()
public void testValueMapWithWrongDataType() throws Exception {
validationService.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new RegexValidator());
-
- List<TestProperty> properties = new ArrayList<TestProperty>();
- TestProperty property = new TestProperty();
- property.name = "field1";
validationService.validators.put("org.apache.sling.validation.impl.util.examplevalidators.DateValidator",new DateValidator());
- property.validators.put("org.apache.sling.validation.impl.util.examplevalidators.DateValidator", null);
- properties.add(property);
+
+ TestProperty property = new TestProperty("field1");
+ property.addValidator("org.apache.sling.validation.impl.util.examplevalidators.DateValidator");
ResourceResolver rr = rrf.getAdministrativeResourceResolver(null);
Resource model1 = null;
try {
if (rr != null) {
model1 = createValidationModelResource(rr, libsValidatorsRoot.getPath(), "testValidationModel1", "sling/validation/test",
- new String[]{"/apps/validation"}, properties);
+ new String[]{"/apps/validation"}, property);
}
ValidationModel vm = validationService.getValidationModel("sling/validation/test", "/apps/validation/1/resource");
HashMap<String, Object> hashMap = new HashMap<String, Object>() {{
@@ -239,21 +231,17 @@ public class ValidationServiceImplTest {
public void testValueMapWithCorrectDataType() throws Exception {
validationService.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new RegexValidator());
- List<TestProperty> fields = new ArrayList<TestProperty>();
- TestProperty field = new TestProperty();
- field.name = "field1";
- field.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new String[] {"regex=^\\p{L}+$"});
- fields.add(field);
- field.name = "field2";
+ TestProperty field1 = new TestProperty("field1");
+ field1.addValidator("org.apache.sling.validation.impl.validators.RegexValidator", "regex=^\\p{L}+$");
+ TestProperty field2 = new TestProperty("field2");
final String TEST_REGEX = "^test$";
- field.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new String[] {"regex="+TEST_REGEX});
- fields.add(field);
+ field2.addValidator("org.apache.sling.validation.impl.validators.RegexValidator", "regex="+TEST_REGEX);
ResourceResolver rr = rrf.getAdministrativeResourceResolver(null);
Resource model1 = null;
try {
if (rr != null) {
model1 = createValidationModelResource(rr, libsValidatorsRoot.getPath(), "testValidationModel1", "sling/validation/test",
- new String[]{"/apps/validation"}, fields);
+ new String[]{"/apps/validation"}, field1, field2);
}
ValidationModel vm = validationService.getValidationModel("sling/validation/test", "/apps/validation/1/resource");
HashMap<String, Object> hashMap = new HashMap<String, Object>() {{
@@ -277,68 +265,179 @@ public class ValidationServiceImplTest {
}
}
}
+
@Test
public void testResourceWithMissingChildProperty() throws Exception {
validationService.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new RegexValidator());
- List<TestProperty> fields = new ArrayList<TestProperty>();
- TestProperty property = new TestProperty();
- property.name = "field1";
- property.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new String[] {RegexValidator.REGEX_PARAM + "=" + "\\d"});
- fields.add(property);
+ TestProperty property = new TestProperty("field1");
+ property.addValidator("org.apache.sling.validation.impl.validators.RegexValidator", RegexValidator.REGEX_PARAM + "=" + "\\d");
ResourceResolver rr = rrf.getAdministrativeResourceResolver(null);
Resource model1 = null;
Resource testResource = null;
try {
if (rr != null) {
model1 = createValidationModelResource(rr, libsValidatorsRoot.getPath(), "testValidationModel1", "sling/validation/test",
- new String[]{"/apps/validation"}, fields);
- Resource modelChildren = rr.create(model1, "children", new HashMap<String, Object>(){{
+ new String[]{"/apps/validation"}, property);
+
+ Resource child = createValidationModelChildResource(model1, "child1", null, new TestProperty("hello"));
+ createValidationModelChildResource(child, "grandChild1", null, new TestProperty("hello"));
+
+ testResource = ResourceUtil.getOrCreateResource(rr, "/apps/validation/1/resource", JcrConstants.NT_UNSTRUCTURED,
+ JcrConstants.NT_UNSTRUCTURED, true);
+ ModifiableValueMap mvm = testResource.adaptTo(ModifiableValueMap.class);
+ mvm.put("field1", "1");
+ rr.commit();
+
+ Resource childResource = rr.create(testResource, "child1", new HashMap<String, Object>(){{
put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
}});
- Resource child = rr.create(modelChildren, "child1", new HashMap<String, Object>(){{
+ rr.commit();
+
+
+ Resource resourceChild = rr.create(testResource, "child1", new HashMap<String, Object>(){{
put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
}});
- Resource childProperties = rr.create(child, "properties", new HashMap<String, Object>(){{
+ mvm = resourceChild.adaptTo(ModifiableValueMap.class);
+ mvm.put("hello", "1");
+ rr.commit();
+
+ // /apps/validation/1/resource/child1/grandChild1 will miss its mandatory "hello" property
+ Resource resourceGrandChild = rr.create(resourceChild, "grandChild1", new HashMap<String, Object>(){{
put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
}});
- Resource childProperty = rr.create(childProperties, "hello", new HashMap<String, Object>(){{
+ rr.commit();
+
+ mvm = resourceGrandChild.adaptTo(ModifiableValueMap.class);
+ mvm.put("field1", "1");
+ rr.commit();
+ }
+ ValidationModel vm = validationService.getValidationModel("sling/validation/test", "/apps/validation/1/resource");
+ ValidationResult vr = validationService.validate(testResource, vm);
+ assertFalse(vr.isValid());
+ assertThat(vr.getFailureMessages(), Matchers.hasKey("child1/grandChild1/hello"));
+ assertThat(vr.getFailureMessages().keySet(), Matchers.hasSize(1));
+ } finally {
+ if (rr != null) {
+ if (model1 != null) {
+ rr.delete(model1);
+ }
+ if (testResource != null) {
+ rr.delete(testResource);
+ }
+ rr.commit();
+ rr.close();
+ }
+ }
+ }
+
+ @Test
+ public void testResourceWithNestedChildren() throws Exception {
+ validationService.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new RegexValidator());
+
+ TestProperty property = new TestProperty("field1");
+ property.addValidator("org.apache.sling.validation.impl.validators.RegexValidator", RegexValidator.REGEX_PARAM + "=" + "\\d");
+ ResourceResolver rr = rrf.getAdministrativeResourceResolver(null);
+ Resource model1 = null;
+ Resource testResource = null;
+ try {
+ if (rr != null) {
+ model1 = createValidationModelResource(rr, libsValidatorsRoot.getPath(), "testValidationModel1", "sling/validation/test",
+ new String[]{"/apps/validation"}, property);
+
+ Resource child = createValidationModelChildResource(model1, "child1", null, new TestProperty("hello"));
+ createValidationModelChildResource(child, "grandChild1", null, new TestProperty("hello"));
+
+ testResource = ResourceUtil.getOrCreateResource(rr, "/apps/validation/1/resource", JcrConstants.NT_UNSTRUCTURED,
+ JcrConstants.NT_UNSTRUCTURED, true);
+ Resource childResource = rr.create(testResource, "child1", new HashMap<String, Object>(){{
put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
- put(Constants.PROPERTY_TYPE, "string");
}});
- Resource grandChildren = rr.create(child, "children", new HashMap<String, Object>(){{
+
+ ModifiableValueMap mvm = testResource.adaptTo(ModifiableValueMap.class);
+ mvm.put("field1", "1");
+
+ Resource resourceChild = rr.create(testResource, "child1", new HashMap<String, Object>(){{
put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
}});
- Resource grandChild = rr.create(grandChildren, "grandChild1", new HashMap<String, Object>(){{
+ mvm = resourceChild.adaptTo(ModifiableValueMap.class);
+ mvm.put("hello", "test");
+
+ Resource resourceGrandChild = rr.create(resourceChild, "grandChild1", new HashMap<String, Object>(){{
put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
}});
+ mvm = resourceGrandChild.adaptTo(ModifiableValueMap.class);
+ mvm.put("hello", "test");
+ rr.commit();
+ }
+ ValidationModel vm = validationService.getValidationModel("sling/validation/test", "/apps/validation/1/resource");
+ ValidationResult vr = validationService.validate(testResource, vm);
+ assertTrue(vr.isValid());
+ } finally {
+ if (rr != null) {
+ if (model1 != null) {
+ rr.delete(model1);
+ }
+ if (testResource != null) {
+ rr.delete(testResource);
+ }
+ rr.commit();
+ rr.close();
+ }
+ }
+ }
+
+ @Test
+ public void testResourceWithNestedChildrenAndPatternMatching() throws Exception {
+ validationService.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new RegexValidator());
+ TestProperty property = new TestProperty("field1");
+ property.addValidator("org.apache.sling.validation.impl.validators.RegexValidator", RegexValidator.REGEX_PARAM + "=" + "\\d");
+ ResourceResolver rr = rrf.getAdministrativeResourceResolver(null);
+ Resource model1 = null;
+ Resource testResource = null;
+ try {
+ if (rr != null) {
+ model1 = createValidationModelResource(rr, libsValidatorsRoot.getPath(), "testValidationModel1", "sling/validation/test",
+ new String[]{"/apps/validation"}, property);
+ Resource child = createValidationModelChildResource(model1, "child1", "child.*", new TestProperty("hello"));
+ createValidationModelChildResource(child, "grandChild", "grandChild.*", new TestProperty("hello"));
+ rr.commit();
+
testResource = ResourceUtil.getOrCreateResource(rr, "/apps/validation/1/resource", JcrConstants.NT_UNSTRUCTURED,
JcrConstants.NT_UNSTRUCTURED, true);
+ ModifiableValueMap mvm = testResource.adaptTo(ModifiableValueMap.class);
+ mvm.put("field1", "1");
+
Resource childResource = rr.create(testResource, "child1", new HashMap<String, Object>(){{
put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
}});
- rr.commit();
- ModifiableValueMap mvm = testResource.adaptTo(ModifiableValueMap.class);
- mvm.put("field1", "1");
- rr.commit();
+ mvm = childResource.adaptTo(ModifiableValueMap.class);
+ mvm.put("hello", "test");
- // /apps/validation/1/resource/child1 will miss its mandatory "hello" property
- Resource resourceChild = rr.create(testResource, "child1", new HashMap<String, Object>(){{
+ Resource resourceChild = rr.create(testResource, "child2", new HashMap<String, Object>(){{
put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
}});
+ mvm = resourceChild.adaptTo(ModifiableValueMap.class);
+ mvm.put("hello2", "test");
Resource resourceGrandChild = rr.create(resourceChild, "grandChild1", new HashMap<String, Object>(){{
put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
}});
+ mvm = resourceGrandChild.adaptTo(ModifiableValueMap.class);
+ mvm.put("hello", "test");
rr.commit();
}
ValidationModel vm = validationService.getValidationModel("sling/validation/test", "/apps/validation/1/resource");
ValidationResult vr = validationService.validate(testResource, vm);
assertFalse(vr.isValid());
- assertThat(vr.getFailureMessages(), Matchers.hasKey("child1/hello"));
+ // check for correct error message
+ Map<String, List<String>> expectedFailureMessages = new HashMap<String, List<String>>();
+ expectedFailureMessages.put("child2/hello", Arrays.asList("Missing required property."));
+ expectedFailureMessages.put("child1/grandChild.*", Arrays.asList("Missing required child resource."));
+ Assert.assertThat(vr.getFailureMessages().entrySet(), Matchers.equalTo(expectedFailureMessages.entrySet()));
} finally {
if (rr != null) {
if (model1 != null) {
@@ -354,21 +453,65 @@ public class ValidationServiceImplTest {
}
@Test
+ public void testResourceWithPropertyPatternMatching() throws Exception {
+ validationService.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new RegexValidator());
+
+ TestProperty property = new TestProperty("field1");
+ final String TEST_REGEX = "^testvalue.*$";
+ property.addValidator("org.apache.sling.validation.impl.validators.RegexValidator", "regex="+TEST_REGEX);
+ property.setNameRegex("property[1-4]");
+
+ TestProperty otherProperty = new TestProperty("field2");
+ otherProperty.addValidator("org.apache.sling.validation.impl.validators.RegexValidator", "regex="+TEST_REGEX);
+ otherProperty.setNameRegex("otherproperty[1-4]");
+ ResourceResolver rr = rrf.getAdministrativeResourceResolver(null);
+ Resource model1 = null;
+ try {
+ if (rr != null) {
+ model1 = createValidationModelResource(rr, libsValidatorsRoot.getPath(), "testValidationModel1", "sling/validation/test",
+ new String[]{"/apps/validation"}, property, otherProperty);
+ }
+ ValidationModel vm = validationService.getValidationModel("sling/validation/test", "/apps/validation/1/resource");
+ HashMap<String, Object> hashMap = new HashMap<String, Object>() {{
+ put("property1", "testvalue1");
+ put("property2", "test1value1"); // does not match validator pattern
+ put("property3", "testvalue1");
+ put("property4", "1testvalue1"); // does not match validator pattern
+ put("property5", "invalid"); // does not match property name pattern
+ }};
+ ValueMap map = new ValueMapDecorator(hashMap);
+ ValidationResult vr = validationService.validate(map, vm);
+ assertFalse(vr.isValid());
+ // check for correct error message
+ Map<String, List<String>> expectedFailureMessages = new HashMap<String, List<String>>();
+ expectedFailureMessages.put("property2", Arrays.asList("Property does not match the pattern " + TEST_REGEX));
+ expectedFailureMessages.put("property4", Arrays.asList("Property does not match the pattern " + TEST_REGEX));
+ expectedFailureMessages.put("otherproperty[1-4]", Arrays.asList("Missing required property."));
+ Assert.assertThat(vr.getFailureMessages().entrySet(), Matchers.equalTo(expectedFailureMessages.entrySet()));
+ } finally {
+ if (model1 != null) {
+ rr.delete(model1);
+ }
+ if (rr != null) {
+ rr.commit();
+ rr.close();
+ }
+ }
+ }
+
+ @Test
public void testResourceWithMultivalueProperties() throws Exception {
validationService.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new RegexValidator());
- List<TestProperty> fields = new ArrayList<TestProperty>();
- TestProperty property = new TestProperty();
- property.name = "field1";
+ TestProperty property = new TestProperty("field1");
final String TEST_REGEX = "^testvalue.*$";
- property.validators.put("org.apache.sling.validation.impl.validators.RegexValidator", new String[] {"regex="+TEST_REGEX});
- fields.add(property);
+ property.addValidator("org.apache.sling.validation.impl.validators.RegexValidator", "regex="+TEST_REGEX);
ResourceResolver rr = rrf.getAdministrativeResourceResolver(null);
Resource model1 = null;
try {
if (rr != null) {
model1 = createValidationModelResource(rr, libsValidatorsRoot.getPath(), "testValidationModel1", "sling/validation/test",
- new String[]{"/apps/validation"}, fields);
+ new String[]{"/apps/validation"}, property);
}
ValidationModel vm = validationService.getValidationModel("sling/validation/test", "/apps/validation/1/resource");
HashMap<String, Object> hashMap = new HashMap<String, Object>() {{
@@ -393,7 +536,7 @@ public class ValidationServiceImplTest {
}
private Resource createValidationModelResource(ResourceResolver rr, String root, String name, String validatedResourceType,
- String[] applicableResourcePaths, List<TestProperty> properties) throws Exception {
+ String[] applicableResourcePaths, TestProperty... properties) throws Exception {
Map<String, Object> modelProperties = new HashMap<String, Object>();
modelProperties.put(Constants.VALIDATED_RESOURCE_TYPE, validatedResourceType);
modelProperties.put(Constants.APPLICABLE_PATHS, applicableResourcePaths);
@@ -401,34 +544,59 @@ public class ValidationServiceImplTest {
modelProperties.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
Resource model = ResourceUtil.getOrCreateResource(rr, root + "/" + name, modelProperties, JcrResourceConstants.NT_SLING_FOLDER, true);
if (model != null) {
- Resource propertiesResource = ResourceUtil.getOrCreateResource(rr, model.getPath() + "/" + Constants
- .PROPERTIES, JcrConstants.NT_UNSTRUCTURED, null, true);
- if (propertiesResource != null) {
- for (TestProperty property : properties) {
- Map<String, Object> modelPropertyJCRProperties = new HashMap<String, Object>();
- modelPropertyJCRProperties.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
- Resource propertyResource = ResourceUtil.getOrCreateResource(rr, propertiesResource.getPath() + "/" + property.name,
- modelPropertyJCRProperties, null, true);
- if (propertyResource != null) {
- Resource validators = ResourceUtil.getOrCreateResource(rr,
- propertyResource.getPath() + "/" + Constants.VALIDATORS,
- JcrConstants.NT_UNSTRUCTURED, null, true);
- if (validators != null) {
- for (Map.Entry<String, String[]> v : property.validators.entrySet()) {
- Map<String, Object> validatorProperties = new HashMap<String, Object>();
- validatorProperties.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
- if (v.getValue() != null) {
- validatorProperties.put(Constants.VALIDATOR_ARGUMENTS, v.getValue());
- }
- ResourceUtil.getOrCreateResource(rr, validators.getPath() + "/" + v.getKey(), validatorProperties, null,
- true);
+ createValidationModelProperties(model, properties);
+ }
+ return model;
+ }
+
+ private void createValidationModelProperties(Resource model, TestProperty... properties) throws PersistenceException {
+ ResourceResolver rr = model.getResourceResolver();
+ Resource propertiesResource = ResourceUtil.getOrCreateResource(rr, model.getPath() + "/" + Constants
+ .PROPERTIES, JcrConstants.NT_UNSTRUCTURED, null, true);
+ if (propertiesResource != null) {
+ for (TestProperty property : properties) {
+ Map<String, Object> modelPropertyJCRProperties = new HashMap<String, Object>();
+ modelPropertyJCRProperties.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
+ Resource propertyResource = ResourceUtil.getOrCreateResource(rr, propertiesResource.getPath() + "/" + property.name,
+ modelPropertyJCRProperties, null, true);
+ if (propertyResource != null) {
+ if (property.nameRegex != null) {
+ ModifiableValueMap values = propertyResource.adaptTo(ModifiableValueMap.class);
+ values.put(Constants.NAME_REGEX, property.nameRegex);
+ }
+ Resource validators = ResourceUtil.getOrCreateResource(rr,
+ propertyResource.getPath() + "/" + Constants.VALIDATORS,
+ JcrConstants.NT_UNSTRUCTURED, null, true);
+ if (validators != null) {
+ for (Map.Entry<String, String[]> v : property.validators.entrySet()) {
+ Map<String, Object> validatorProperties = new HashMap<String, Object>();
+ validatorProperties.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
+ if (v.getValue() != null) {
+ validatorProperties.put(Constants.VALIDATOR_ARGUMENTS, v.getValue());
}
+ ResourceUtil.getOrCreateResource(rr, validators.getPath() + "/" + v.getKey(), validatorProperties, null,
+ true);
}
}
}
}
}
- return model;
+ }
+
+ private Resource createValidationModelChildResource(Resource parentResource, String name, String nameRegex, TestProperty... properties) throws PersistenceException {
+ ResourceResolver rr = parentResource.getResourceResolver();
+ Resource modelChildren = rr.create(parentResource, Constants.CHILDREN, new HashMap<String, Object>(){{
+ put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
+ }});
+ Resource child = rr.create(modelChildren, name, new HashMap<String, Object>(){{
+ put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
+ }});
+ if (nameRegex != null) {
+ ModifiableValueMap mvm = child.adaptTo(ModifiableValueMap.class);
+ mvm.put(Constants.NAME_REGEX, nameRegex);
+ }
+ createValidationModelProperties(child, properties);
+ return child;
}
private boolean arrayContainsString(String[] array, String string) {
@@ -445,16 +613,25 @@ public class ValidationServiceImplTest {
}
private class TestProperty {
- String name;
- Map<String, String[]> validators;
+ final String name;
+ String nameRegex;
+ final Map<String, String[]> validators;
- TestProperty() {
+ TestProperty(String name) {
validators = new HashMap<String, String[]>();
+ this.name = name;
+ this.nameRegex = null;
+ }
+
+ TestProperty setNameRegex(String nameRegex) {
+ this.nameRegex = nameRegex;
+ return this;
+ }
+
+ TestProperty addValidator(String name, String... parameters) {
+ validators.put(name, parameters);
+ return this;
}
- }
-
- private class TestChild {
-
}
}