| /* | |
| * 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; | |
| import com.google.gwt.core.client.GWT; | |
| import java.util.List; | |
| import javax.validation.Configuration; | |
| import javax.validation.ValidationException; | |
| import javax.validation.ValidationProviderResolver; | |
| import javax.validation.ValidatorFactory; | |
| import javax.validation.bootstrap.GenericBootstrap; | |
| import javax.validation.bootstrap.ProviderSpecificBootstrap; | |
| import javax.validation.spi.BootstrapState; | |
| import javax.validation.spi.ValidationProvider; | |
| /** | |
| * <strong>EXPERIMENTAL</strong> and subject to change. Do not use this in | |
| * production code. | |
| * <p> | |
| * This class is the entry point for Bean Validation. There are three ways to | |
| * bootstrap it: | |
| * <ul> | |
| * <li> | |
| * The easiest approach is to build the default <code>ValidatorFactory</code>. | |
| * | |
| * <pre>{@code ValidatorFactory factory = Validation.buildDefaultValidatorFactory();}</pre> | |
| * In this case, the default validation provider resolver will be used to locate | |
| * available providers. The chosen provider is defined as followed: | |
| * <ul> | |
| * <li>Since GWT does not support XML configuration, the first provider returned | |
| * by the <code>ValidationProviderResolver</code> instance is used.</li> | |
| * </ul> | |
| * </li> | |
| * <li> | |
| * The second bootstrap approach allows to choose a custom | |
| * <code>ValidationProviderResolver</code>. The chosen | |
| * <code>ValidationProvider</code> is then determined in the same way as in the | |
| * default bootstrapping case (see above). | |
| * | |
| * <pre>{@code | |
| * Configuration<?> configuration = Validation | |
| * .byDefaultProvider() | |
| * .providerResolver( new MyResolverStrategy() ) | |
| * .configure(); | |
| * ValidatorFactory factory = configuration.buildValidatorFactory();} | |
| * </pre> | |
| * </li> | |
| * <li> | |
| * The third approach allows you to specify explicitly and in a type safe | |
| * fashion the expected provider. | |
| * <p/> | |
| * Optionally you can choose a custom <code>ValidationProviderResolver</code>. | |
| * | |
| * <pre>{@code | |
| * ACMEConfiguration configuration = Validation | |
| * .byProvider(ACMEProvider.class) | |
| * .providerResolver( new MyResolverStrategy() ) // optionally set the provider resolver | |
| * .configure(); | |
| * ValidatorFactory factory = configuration.buildValidatorFactory();} | |
| * </pre> | |
| * </li> | |
| * </ul> | |
| * Note:<br/> | |
| * <ul> | |
| * <li> | |
| * The <code>ValidatorFactory</code> object built by the bootstrap process | |
| * should be cached and shared amongst <code>Validator</code> consumers.</li> | |
| * <li> | |
| * This class is thread-safe.</li> | |
| * </ul> | |
| * | |
| * This class was modified by Google from the original | |
| * javax.validation.Validation source to make it suitable for GWT. | |
| */ | |
| public class Validation { | |
| // private class, not exposed | |
| private static class GenericBootstrapImpl implements GenericBootstrap, | |
| BootstrapState { | |
| private ValidationProviderResolver defaultResolver; | |
| private ValidationProviderResolver resolver; | |
| public Configuration<?> configure() { | |
| ValidationProviderResolver aResolver = this.resolver == null | |
| ? getDefaultValidationProviderResolver() : this.resolver; | |
| List<ValidationProvider<?>> resolvers; | |
| try { | |
| resolvers = aResolver.getValidationProviders(); | |
| } catch (RuntimeException re) { | |
| throw new ValidationException( | |
| "Unable to get available provider resolvers.", re); | |
| } | |
| if (resolvers.size() == 0) { | |
| // FIXME looks like an assertion error almost | |
| throw new ValidationException("Unable to find a default provider"); | |
| } | |
| Configuration<?> config; | |
| try { | |
| config = aResolver.getValidationProviders().get(0).createGenericConfiguration( | |
| this); | |
| } catch (RuntimeException re) { | |
| throw new ValidationException("Unable to instantiate Configuration.", | |
| re); | |
| } | |
| return config; | |
| } | |
| public ValidationProviderResolver getDefaultValidationProviderResolver() { | |
| if (defaultResolver == null) { | |
| defaultResolver = GWT.create(ValidationProviderResolver.class); | |
| } | |
| return defaultResolver; | |
| } | |
| public ValidationProviderResolver getValidationProviderResolver() { | |
| return resolver; | |
| } | |
| public GenericBootstrap providerResolver(ValidationProviderResolver resolver) { | |
| this.resolver = resolver; | |
| return this; | |
| } | |
| } | |
| // private class, not exposed | |
| private static class ProviderSpecificBootstrapImpl | |
| <T extends Configuration<T>, U extends ValidationProvider<T>> | |
| implements ProviderSpecificBootstrap<T> { | |
| private ValidationProviderResolver resolver; | |
| private final Class<U> validationProviderClass; | |
| public ProviderSpecificBootstrapImpl(Class<U> validationProviderClass) { | |
| this.validationProviderClass = validationProviderClass; | |
| } | |
| /** | |
| * Determine the provider implementation suitable for byProvider(Class) and | |
| * delegate the creation of this specific Configuration subclass to the | |
| * provider. | |
| * | |
| * @return a Configuration sub interface implementation | |
| */ | |
| public T configure() { | |
| if (validationProviderClass == null) { | |
| throw new ValidationException( | |
| "builder is mandatory. Use Validation.byDefaultProvider() to use the generic provider discovery mechanism"); | |
| } | |
| // used mostly as a BootstrapState | |
| GenericBootstrapImpl state = new GenericBootstrapImpl(); | |
| if (resolver == null) { | |
| resolver = state.getDefaultValidationProviderResolver(); | |
| } else { | |
| // stay null if no resolver is defined | |
| state.providerResolver(resolver); | |
| } | |
| List<ValidationProvider<?>> resolvers; | |
| try { | |
| resolvers = resolver.getValidationProviders(); | |
| } catch (RuntimeException re) { | |
| throw new ValidationException( | |
| "Unable to get available provider resolvers.", re); | |
| } | |
| for (ValidationProvider<?> provider : resolvers) { | |
| // GWT validation only support exact matches. | |
| if (validationProviderClass.equals(provider.getClass())) { | |
| @SuppressWarnings("unchecked") | |
| ValidationProvider<T> specificProvider = (ValidationProvider<T>) provider; | |
| return specificProvider.createSpecializedConfiguration(state); | |
| } | |
| } | |
| throw new ValidationException("Unable to find provider: " | |
| + validationProviderClass); | |
| } | |
| /** | |
| * Optionally define the provider resolver implementation used. If not | |
| * defined, use the default ValidationProviderResolver | |
| * | |
| * @param resolver ValidationProviderResolver implementation used | |
| * | |
| * @return self | |
| */ | |
| public ProviderSpecificBootstrap<T> providerResolver( | |
| ValidationProviderResolver resolver) { | |
| this.resolver = resolver; | |
| return this; | |
| } | |
| } | |
| /** | |
| * Build and return a <code>ValidatorFactory</code> instance based on the | |
| * default Bean Validation provider. | |
| * <p/> | |
| * The provider list is resolved using the default validation provider | |
| * resolver logic. | |
| * <p/> | |
| * The code is semantically equivalent to | |
| * <code>Validation.byDefaultProvider().configure().buildValidatorFactory()</code> | |
| * | |
| * @return <code>ValidatorFactory</code> instance. | |
| * | |
| * @throws ValidationException if the ValidatorFactory cannot be built | |
| */ | |
| public static ValidatorFactory buildDefaultValidatorFactory() { | |
| return byDefaultProvider().configure().buildValidatorFactory(); | |
| } | |
| /** | |
| * Build a <code>Configuration</code>. The provider list is resolved using the | |
| * strategy provided to the bootstrap state. | |
| * | |
| * <pre> | |
| * Configuration<?> configuration = Validation | |
| * .byDefaultProvider() | |
| * .providerResolver( new MyResolverStrategy() ) | |
| * .configure(); | |
| * ValidatorFactory factory = configuration.buildValidatorFactory(); | |
| * </pre> | |
| * | |
| * The first available provider will be returned. | |
| * | |
| * @return instance building a generic <code>Configuration</code> complaint | |
| * with the bootstrap state provided. | |
| */ | |
| public static GenericBootstrap byDefaultProvider() { | |
| return new GenericBootstrapImpl(); | |
| } | |
| /** | |
| * Build a <code>Configuration</code> for a particular provider | |
| * implementation. Optionally overrides the provider resolution strategy used | |
| * to determine the provider. | |
| * <p/> | |
| * Used by applications targeting a specific provider programmatically. | |
| * <p/> | |
| * | |
| * <pre> | |
| * ACMEConfiguration configuration = | |
| * Validation.byProvider(ACMEProvider.class) | |
| * .providerResolver( new MyResolverStrategy() ) | |
| * .configure(); | |
| * </pre> | |
| * , where <code>ACMEConfiguration</code> is the <code>Configuration</code> | |
| * sub interface uniquely identifying the ACME Bean Validation provider. and | |
| * <code>ACMEProvider</code> is the <code>ValidationProvider</code> | |
| * implementation of the ACME provider. | |
| * | |
| * @param providerType the <code>ValidationProvider</code> implementation type | |
| * | |
| * @return instance building a provider specific <code>Configuration</code> | |
| * sub interface implementation. | |
| */ | |
| public static <T extends Configuration<T>,U extends ValidationProvider<T>> | |
| ProviderSpecificBootstrap<T> byProvider(Class<U> providerType) { | |
| return new ProviderSpecificBootstrapImpl<T, U>(providerType); | |
| } | |
| } |