| /* | |
| * Copyright 2010 Google Inc. | |
| * | |
| * Licensed 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 com.google.gwt.validation.client.impl; | |
| import com.google.gwt.validation.client.BaseMessageInterpolator.ContextImpl; | |
| import java.lang.annotation.Annotation; | |
| import java.util.Collection; | |
| import java.util.Collections; | |
| import java.util.HashMap; | |
| import java.util.HashSet; | |
| import java.util.Map; | |
| import java.util.Set; | |
| import javax.validation.ConstraintValidator; | |
| import javax.validation.ConstraintViolation; | |
| import javax.validation.MessageInterpolator; | |
| import javax.validation.groups.Default; | |
| /** | |
| * <strong>EXPERIMENTAL</strong> and subject to change. Do not use this in | |
| * production code. | |
| * <p> | |
| * Base methods for implementing a {@link GwtSpecificValidator}. | |
| * <p> | |
| * All methods that do not need to be generated go here. | |
| * | |
| * @param <G> the type object to validate | |
| */ | |
| public abstract class AbstractGwtSpecificValidator<G> implements | |
| GwtSpecificValidator<G> { | |
| /** | |
| * Builds attributes one at a time. | |
| * <p> | |
| * Used to create a attribute map for annotations. | |
| */ | |
| public static final class AttributeBuilder { | |
| private final HashMap<String, Object> tempMap = new HashMap<String, Object>(); | |
| private AttributeBuilder() { | |
| } | |
| public Map<String, Object> build() { | |
| return Collections.unmodifiableMap(tempMap); | |
| } | |
| public AttributeBuilder put(String key, Object value) { | |
| tempMap.put(key, value); | |
| return this; | |
| } | |
| } | |
| public static AttributeBuilder attributeBuilder() { | |
| return new AttributeBuilder(); | |
| } | |
| 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) { | |
| validator.initialize(constraintDescriptor.getAnnotation()); | |
| ConstraintValidatorContextImpl<A, V> constraintValidatorContext = | |
| context.createConstraintValidatorContext(constraintDescriptor); | |
| // TODO(nchalko) set empties to Default earlier. | |
| Set<Class<?>> constraintGroup = constraintDescriptor.getGroups(); | |
| if (groups.length == 0) { | |
| groups = new Class<?>[]{Default.class}; | |
| } | |
| if (constraintGroup.isEmpty()) { | |
| constraintGroup = new HashSet<Class<?>>(); | |
| constraintGroup.add(Default.class); | |
| } | |
| // check group | |
| if (!containsAny(groups, constraintGroup)) { | |
| return false; | |
| } | |
| if (!validator.isValid(value, constraintValidatorContext)) { | |
| addViolations(// | |
| context, // | |
| violations, // | |
| object, // | |
| value, // | |
| constraintDescriptor, // | |
| constraintValidatorContext); | |
| return true; | |
| } | |
| return false; | |
| } | |
| private <V, T, A extends Annotation> void addViolations( | |
| GwtValidationContext<T> context, Set<ConstraintViolation<T>> violations, | |
| G object, V value, ConstraintDescriptorImpl<A> constraintDescriptor, | |
| ConstraintValidatorContextImpl<A, V> constraintValidatorContext) { | |
| Set<MessageAndPath> mps = constraintValidatorContext.getMessageAndPaths(); | |
| for (MessageAndPath messageAndPath : mps) { | |
| ConstraintViolation<T> violation = createConstraintViolation(// | |
| context, // | |
| object, // | |
| value, // | |
| constraintDescriptor, // | |
| messageAndPath); | |
| violations.add(violation); | |
| } | |
| } | |
| private <T> boolean containsAny(T[] left, Collection<T> right) { | |
| for (T t : left) { | |
| if (right.contains(t)) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| private <T, V, A extends Annotation> ConstraintViolation<T> createConstraintViolation( | |
| GwtValidationContext<T> context, G object, V value, | |
| ConstraintDescriptorImpl<A> constraintDescriptor, | |
| MessageAndPath messageAndPath) { | |
| MessageInterpolator messageInterpolator = context.getMessageInterpolator(); | |
| ContextImpl messageContext = new ContextImpl(constraintDescriptor, value); | |
| String message = messageInterpolator.interpolate( | |
| messageAndPath.getMessage(), messageContext); | |
| ConstraintViolation<T> violation = ConstraintViolationImpl.<T> builder() // | |
| .setConstraintDescriptor(constraintDescriptor) // | |
| .setInvalidValue(value) // | |
| .setLeafBean(object) // | |
| .setMessage(message) // | |
| .setMessageTemplate(messageAndPath.getMessage()) // | |
| .setPropertyPath(messageAndPath.getPath()) // | |
| .setRootBean(context.getRootBean()) // | |
| .setRootBeanClass(context.getRootBeanClass()) // | |
| .build(); | |
| return violation; | |
| } | |
| } |