You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by mb...@apache.org on 2011/05/16 20:36:19 UTC

svn commit: r1103825 - in /incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src: main/java/org/apache/bval/jsr303/dynamic/NestedValidator.java test/java/org/apache/bval/jsr303/dynamic/NestedValidatorTest.java

Author: mbenson
Date: Mon May 16 18:36:19 2011
New Revision: 1103825

URL: http://svn.apache.org/viewvc?rev=1103825&view=rev
Log:
add NestedValidator class

Added:
    incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src/main/java/org/apache/bval/jsr303/dynamic/NestedValidator.java   (with props)
    incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src/test/java/org/apache/bval/jsr303/dynamic/NestedValidatorTest.java   (with props)

Added: incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src/main/java/org/apache/bval/jsr303/dynamic/NestedValidator.java
URL: http://svn.apache.org/viewvc/incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src/main/java/org/apache/bval/jsr303/dynamic/NestedValidator.java?rev=1103825&view=auto
==============================================================================
--- incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src/main/java/org/apache/bval/jsr303/dynamic/NestedValidator.java (added)
+++ incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src/main/java/org/apache/bval/jsr303/dynamic/NestedValidator.java Mon May 16 18:36:19 2011
@@ -0,0 +1,108 @@
+/*
+ *  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.bval.jsr303.dynamic;
+
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Type;
+
+import javax.validation.ConstraintViolation;
+
+import org.apache.bval.DynamicMetaBean;
+import org.apache.bval.jsr303.GroupValidationContext;
+import org.apache.bval.jsr303.util.PathNavigation;
+import org.apache.bval.jsr303.util.ValidationContextTraversal;
+import org.apache.bval.model.MetaBean;
+import org.apache.bval.model.MetaProperty;
+import org.apache.bval.util.AccessStrategy;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+
+/**
+ * {@code Validator} implementation to handle validations in a given context. This extension is only applicable because
+ * of the "branched constraints" supported by the dynamic bean validation APIs. Note that {@link ConstraintViolation}s
+ * returned from the various {@code validate...} methods of this class will <em>not</em> conform to expected type
+ * parameters. This is usually not a problem.
+ * 
+ * @version $Rev$ $Date$
+ */
+@SuppressWarnings({ "rawtypes", "unchecked" })
+public class NestedValidator extends DynamicClassValidator {
+    private final MetaBean rootBean;
+    private final String path;
+
+    /**
+     * Create a new NestedValidator instance.
+     * 
+     * @param context
+     *            dynamic validator context
+     * @param rootType
+     *            of real validation
+     * @param path
+     *            from rootType
+     */
+    public NestedValidator(DynamicValidatorContext context, Class<?> rootType, String path) {
+        super(context);
+        Validate.notNull(context, "context");
+        Validate.notNull(rootType, "rootType");
+        this.rootBean = getMetaBeanFinder().findForClass(rootType);
+        this.path = path;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected GroupValidationContext createContext(MetaBean metaBean, final Object object, Class objectClass,
+        Class... groups) {
+        if (StringUtils.isEmpty(path)) {
+            return super.createContext(metaBean, object, objectClass, groups);
+        }
+        GroupValidationContext result = super.createContext(rootBean, null, rootBean.getBeanClass(), groups);
+        ValidationContextTraversal validationContextTraversal = createValidationContextTraversal(result);
+        PathNavigation.navigate(path, validationContextTraversal);
+        final MetaProperty prop = result.getMetaProperty();
+        if (prop != null) {
+            result.moveDown(prop, new AccessStrategy() {
+
+                @Override
+                public String getPropertyName() {
+                    return prop.getName();
+                }
+
+                @Override
+                public Type getJavaType() {
+                    return prop.getType();
+                }
+
+                @Override
+                public ElementType getElementType() {
+                    return ElementType.LOCAL_VARIABLE;
+                }
+
+                @Override
+                public Object get(Object arg0) {
+                    return object;
+                }
+            });
+        } else {
+            result.setBean(object);
+        }
+        if (result.getMetaBean() instanceof DynamicMetaBean) {
+            result.setMetaBean(((DynamicMetaBean) result.getMetaBean()).resolveMetaBean(object));
+        }
+        return result;
+    }
+}

Propchange: incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src/main/java/org/apache/bval/jsr303/dynamic/NestedValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src/test/java/org/apache/bval/jsr303/dynamic/NestedValidatorTest.java
URL: http://svn.apache.org/viewvc/incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src/test/java/org/apache/bval/jsr303/dynamic/NestedValidatorTest.java?rev=1103825&view=auto
==============================================================================
--- incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src/test/java/org/apache/bval/jsr303/dynamic/NestedValidatorTest.java (added)
+++ incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src/test/java/org/apache/bval/jsr303/dynamic/NestedValidatorTest.java Mon May 16 18:36:19 2011
@@ -0,0 +1,146 @@
+/*
+ *  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.bval.jsr303.dynamic;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Locale;
+import java.util.Set;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+
+import org.apache.bval.jsr303.ApacheValidationProvider;
+import org.apache.bval.jsr303.ApacheValidatorConfiguration;
+import org.apache.bval.jsr303.DefaultMessageInterpolator;
+import org.apache.bval.jsr303.example.Address;
+import org.apache.bval.jsr303.example.Author;
+import org.apache.bval.jsr303.example.Book;
+import org.apache.bval.jsr303.example.Country;
+import org.apache.bval.jsr303.example.First;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test the {@code NestedValidator}.
+ * 
+ * @version $Rev$ $Date$
+ */
+public class NestedValidatorTest {
+    private DynamicValidatorContext validatorContext;
+    private Validator validator;
+
+    @Before
+    public void setup() {
+        DynamicValidatorFactory factory =
+            Validation
+                .byProvider(ApacheValidationProvider.class)
+                .configure()
+                .addProperty(ApacheValidatorConfiguration.Properties.VALIDATOR_FACTORY_CLASSNAME,
+                    DynamicValidatorFactory.class.getName()).buildValidatorFactory()
+                .unwrap(DynamicValidatorFactory.class);
+        ((DefaultMessageInterpolator) factory.getMessageInterpolator()).setLocale(Locale.ENGLISH);
+        validatorContext = factory.usingContext();
+        validator = validatorContext.getValidator();
+    }
+
+    @Test
+    public void testSimple() {
+        Author author = new Author();
+        author.setLastName("Baudelaire");
+        author.setFirstName("");
+        assertEquals(1, new NestedValidator(validatorContext, Author.class, "").validate(author, Book.All.class).size());
+    }
+
+    @Test
+    public void testNested() {
+        Author author = new Author();
+        author.setLastName("Baudelaire");
+        author.setFirstName("Chuck");
+        Book book = new Book();
+        book.setAuthor(author);
+        book.setTitle("foo");
+        Set<ConstraintViolation<Author>> errors = validator.validate(author, Book.All.class);
+        assertTrue(errors.isEmpty());
+
+        validatorContext.constrain(Book.class, "author.company",
+            StubConstraint.build().withGroups(First.class).build(NotNull.class));
+
+        errors = validator.validate(author, Book.All.class);
+        assertTrue(errors.isEmpty());
+
+        errors = new NestedValidator(validatorContext, Book.class, "author").validate(author, Book.All.class);
+        assertEquals(1, errors.size());
+        ConstraintViolation<Author> vio = errors.iterator().next();
+        assertEquals(NotNull.class, vio.getConstraintDescriptor().getAnnotation().annotationType());
+    }
+
+    @Test
+    public void testNestedIndexed() {
+        Author author = new Author();
+        author.setLastName("Baudelaire");
+        author.setFirstName("Chuck");
+        author.setAddresses(new ArrayList<Address>());
+        Country ham = new Country();
+        ham.setName("ham");
+        Address address0 = new Address();
+        address0.setCity("mouse");
+        address0.setCountry(ham);
+        address0.setAddressline1("100 some street");
+        Address address1 = new Address();
+        address1.setCity("mouse");
+        address1.setCountry(ham);
+        address1.setAddressline1("200 some other street");
+        author.getAddresses().add(address0);
+        author.getAddresses().add(address1);
+
+        Set<ConstraintViolation<Address>> errors = validator.validate(address0);
+        assertTrue(errors.isEmpty());
+
+        errors = validator.validate(address1);
+        assertTrue(errors.isEmpty());
+
+        validatorContext.constrain(Author.class, "addresses[].addressline2",
+            StubConstraint.build().withGroups(First.class).new CustomConfig<Pattern>() {
+                protected void customConfigure(Pattern stub) {
+                    when(stub.regexp()).thenReturn("[0..9]+.*");
+                }
+            }.build());
+
+        errors = validator.validate(address0, Book.All.class);
+        assertTrue(errors.isEmpty());
+
+        errors = validator.validate(address1, Book.All.class);
+        assertTrue(errors.isEmpty());
+
+        address1.setAddressline2("oops forgot the street number");
+
+        errors = validator.validate(address1, Book.All.class);
+        assertTrue(errors.isEmpty());
+
+        errors = new NestedValidator(validatorContext, Author.class, "addresses[0]").validate(address0, Book.All.class);
+        assertTrue(errors.isEmpty());
+
+        errors = new NestedValidator(validatorContext, Author.class, "addresses[1]").validate(address1, Book.All.class);
+        assertEquals(1, errors.size());
+    }
+}

Propchange: incubator/bval/sandbox/lang3-work/bval-jsr303-dynamic/provider/src/test/java/org/apache/bval/jsr303/dynamic/NestedValidatorTest.java
------------------------------------------------------------------------------
    svn:eol-style = native