| /* |
| * 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); |
| } |
| } |