Add Support for @ReportAsSingleViolation. [JSR 303 TCK Result] 119 of 257 (46.30%) Pass with 12 Failures and 8 Errors. Review at http://gwt-code-reviews.appspot.com/1388801 Review by: rchandia@google.com git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9865 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/validation/client/impl/AbstractGwtSpecificValidator.java b/user/src/com/google/gwt/validation/client/impl/AbstractGwtSpecificValidator.java index 62b482d..1481d98 100644 --- a/user/src/com/google/gwt/validation/client/impl/AbstractGwtSpecificValidator.java +++ b/user/src/com/google/gwt/validation/client/impl/AbstractGwtSpecificValidator.java
@@ -65,7 +65,24 @@ return new AttributeBuilder(); } - protected <A extends Annotation, T, V> void validate( + protected <V, T, A extends Annotation> void addSingleViolation( + GwtValidationContext<T> context, Set<ConstraintViolation<T>> violations, + G object, V value, ConstraintDescriptorImpl<A> constraintDescriptor) { + ConstraintValidatorContextImpl<A, V> constraintValidatorContext = + context.createConstraintValidatorContext(constraintDescriptor); + addViolations(context, violations, object, value, constraintDescriptor, + constraintValidatorContext); + } + + /** + * Perform the actual validation of a single {@link ConstraintValidator}. + * <p> + * As a side effect {@link ConstraintViolation}s may be added to + * {@code violations}. + * + * @return true if there was any constraint violations + */ + protected <A extends Annotation, T, V> boolean validate( GwtValidationContext<T> context, Set<ConstraintViolation<T>> violations, G object, V value, ConstraintValidator<A, ? super V> validator, ConstraintDescriptorImpl<A> constraintDescriptor, Class<?>[] groups) { @@ -85,7 +102,7 @@ // check group if (!containsAny(groups, constraintGroup)) { - return; + return false; } if (!validator.isValid(value, constraintValidatorContext)) { @@ -96,7 +113,9 @@ value, // constraintDescriptor, // constraintValidatorContext); + return true; } + return false; } private <V, T, A extends Annotation> void addViolations(
diff --git a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java index ea587d6..9a4eee5 100644 --- a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java +++ b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
@@ -80,15 +80,16 @@ * This class is not thread safe. */ public class GwtSpecificValidatorCreator extends AbstractCreator { - private static enum Stage { OBJECT, PROPERTY, VALUE } - private static final Annotation[] NO_ANNOTATIONS = new Annotation[]{}; - static final JType[] NO_ARGS = new JType[]{}; + private static final String DEFAULT_VIOLATION_VAR = "violations"; + + private static final Annotation[] NO_ANNOTATIONS = new Annotation[]{}; + private static Function<java.beans.PropertyDescriptor, String> PROPERTY_DESCRIPTOR_TO_NAME = new Function<java.beans.PropertyDescriptor, String>() { @@ -845,12 +846,18 @@ } private void writeNewViolations(SourceWriter sw) { + writeNewViolations(sw, DEFAULT_VIOLATION_VAR); + } + + private void writeNewViolations(SourceWriter sw, String violationName) { // Set<ConstraintViolation<T>> violations = - // new HashSet<ConstraintViolation<T>>(); - sw.println("Set<ConstraintViolation<T>> violations = "); + sw.print("Set<ConstraintViolation<T>> "); + sw.print(violationName); + sw.println(" = "); sw.indent(); sw.indent(); + // new HashSet<ConstraintViolation<T>>(); sw.println("new HashSet<ConstraintViolation<T>>();"); sw.outdent(); sw.outdent(); @@ -999,8 +1006,52 @@ private void writeValidateConstraint(SourceWriter sw, PropertyDescriptor p, Class<?> elementClass, ConstraintDescriptor<?> constraint, String constraintDescriptorVar) throws UnableToCompleteException { - if (!constraint.getConstraintValidatorClasses().isEmpty()) { + writeValidateConstraint(sw, p, elementClass, constraint, + constraintDescriptorVar, DEFAULT_VIOLATION_VAR); + } + /** + * Writes the call to actually validate a constraint, including its composite + * constraints. + * <p> + * If the constraint is annotated as + * {@link javax.validation.ReportAsSingleViolation ReportAsSingleViolation}, + * then is called recursively and the {@code violationsVar} is changed to + * match the the {@code constraintDescriptorVar}. + * + * @param sw the Source Writer + * @param p the property + * @param elementClass The class of the Element + * @param constraint the constraint to validate. + * @param constraintDescriptorVar the name of the constraintDescriptor + * variable. + * @param violationsVar the name of the variable to hold violations + * @throws UnableToCompleteException + */ + private void writeValidateConstraint(SourceWriter sw, PropertyDescriptor p, + Class<?> elementClass, ConstraintDescriptor<?> constraint, + String constraintDescriptorVar, String violationsVar) + throws UnableToCompleteException { + boolean isComposite = !constraint.getComposingConstraints().isEmpty(); + boolean firstReportAsSingleViolation = + constraint.isReportAsSingleViolation() + && violationsVar.equals(DEFAULT_VIOLATION_VAR) && isComposite; + boolean reportAsSingleViolation = firstReportAsSingleViolation + || !violationsVar.equals(DEFAULT_VIOLATION_VAR); + boolean hasValidator = !constraint.getConstraintValidatorClasses() + .isEmpty(); + String compositeViolationsVar = constraintDescriptorVar + "_violations"; + + // Only do this the first time in a constraint composition. + if (firstReportAsSingleViolation) { + // Report myConstraint as Single Violation + sw.print("// Report "); + sw.print(constraint.getAnnotation().annotationType().getCanonicalName()); + sw.println(" as Single Violation"); + writeNewViolations(sw, compositeViolationsVar); + } + + if (hasValidator) { Class<? extends ConstraintValidator<? extends Annotation, ?>> validatorClass; try { validatorClass = getValidatorForType(constraint, elementClass); @@ -1008,25 +1059,87 @@ throw error(logger, e); } - // validate(myContext, violations, object, value, new MyValidator(), - // constraintDescriptor, groups); - sw.print("validate(myContext, violations, object, value, "); + if (firstReportAsSingleViolation) { + // if (! + sw.println("if (!"); + sw.indent(); + sw.indent(); + } + + // validate(myContext, violations object, value, new MyValidator(), + // constraintDescriptor, groups)); + sw.print("validate(myContext, "); + sw.print(violationsVar); + sw.print(", object, value, "); sw.print("new "); // TODO(nchalko) use ConstraintValidatorFactory sw.print(validatorClass.getCanonicalName()); sw.print("(), "); sw.print(constraintDescriptorVar); - sw.println(", groups);"); - } else if (constraint.getComposingConstraints().isEmpty()) { - // TODO(nchalko) What does the spec say to do here. - logger.log(Type.WARN, "No ConstraintValidator of " + constraint - + " for " + p.getPropertyName() + " of type " + elementClass); + sw.print(", groups)"); + if (firstReportAsSingleViolation) { + // ) { + sw.println(") {"); + sw.outdent(); + + } else if (!reportAsSingleViolation) { + // ; + sw.println(";"); + } else if (isComposite) { + // || + sw.println(" ||"); + } + } else if (!isComposite) { + // TODO(nchalko) What does the spec say to do here. + logger.log(Type.WARN, "No ConstraintValidator of " + constraint + " for " + + p.getPropertyName() + " of type " + elementClass); } - // TODO(nchalko) handle constraint.isReportAsSingleViolation() + + if (firstReportAsSingleViolation) { + // if ( + sw.print("if ("); + sw.indent(); + sw.indent(); + } int count = 0; - for (ConstraintDescriptor<?> compositeConstraint : constraint.getComposingConstraints()) { + + for (ConstraintDescriptor<?> compositeConstraint : constraint + .getComposingConstraints()) { String compositeVar = constraintDescriptorVar + "_" + count++; writeValidateConstraint(sw, p, elementClass, compositeConstraint, - compositeVar); + compositeVar, firstReportAsSingleViolation ? compositeViolationsVar + : violationsVar); + if (!reportAsSingleViolation) { + // ; + sw.println(";"); + } else { + // || + sw.println(" ||"); + } + } + if (isComposite && reportAsSingleViolation) { + // false + sw.print("false"); + } + if (firstReportAsSingleViolation) { + // ) { + sw.println(" ) {"); + sw.outdent(); + + // addSingleViolation(myContext, violations, object, value, + // constraintDescriptor); + sw.print("addSingleViolation(myContext, violations, object, value, "); + sw.print(constraintDescriptorVar); + sw.println(");"); + + // } + sw.outdent(); + sw.println("}"); + + if (hasValidator) { + // } + sw.outdent(); + sw.println("}"); + } } }
diff --git a/user/test/org/hibernate/jsr303/tck/tests/constraints/constraintcomposition/ConstraintCompositionGwtTest.java b/user/test/org/hibernate/jsr303/tck/tests/constraints/constraintcomposition/ConstraintCompositionGwtTest.java index 859183a..4256dd1 100644 --- a/user/test/org/hibernate/jsr303/tck/tests/constraints/constraintcomposition/ConstraintCompositionGwtTest.java +++ b/user/test/org/hibernate/jsr303/tck/tests/constraints/constraintcomposition/ConstraintCompositionGwtTest.java
@@ -17,8 +17,6 @@ import com.google.gwt.junit.client.GWTTestCase; -import org.hibernate.jsr303.tck.util.client.Failing; - /** * Wraps {@link ConstraintCompositionTest}. */ @@ -51,7 +49,6 @@ delegate.testGroupsDefinedOnMainAnnotationAreInherited(); } - @Failing(issue = 5799) public void testOnlySingleConstraintViolation() { delegate.testOnlySingleConstraintViolation(); }
diff --git a/user/test/org/hibernate/jsr303/tck/tests/validation/ValidateGwtTest.java b/user/test/org/hibernate/jsr303/tck/tests/validation/ValidateGwtTest.java index 2d129f7..fe6d48b 100644 --- a/user/test/org/hibernate/jsr303/tck/tests/validation/ValidateGwtTest.java +++ b/user/test/org/hibernate/jsr303/tck/tests/validation/ValidateGwtTest.java
@@ -44,7 +44,6 @@ delegate.testGraphValidationWithList(); } - @Failing(issue = 5930) public void testMultipleConstraintViolationOfDifferentTypes() { delegate.testMultipleConstraintViolationOfDifferentTypes(); }