com.agimatec.validation.jsr303.AgimatecValidatorFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.agimatec.validation.jsr303.AgimatecValidatorFactory.java

Source

/*
 * 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 com.agimatec.validation.jsr303;

import com.agimatec.validation.jsr303.util.SecureActions;
import com.agimatec.validation.jsr303.xml.AnnotationIgnores;
import com.agimatec.validation.jsr303.xml.MetaConstraint;
import com.agimatec.validation.jsr303.xml.ValidationMappingParser;
import com.agimatec.validation.util.AccessStrategy;
import org.apache.commons.lang.ClassUtils;

import javax.validation.*;
import javax.validation.bootstrap.ProviderSpecificBootstrap;
import javax.validation.spi.ConfigurationState;
import java.lang.annotation.Annotation;
import java.util.*;

/**
 * Description: a factory is a complete configurated object that can create validators<br/>
 * this instance is not thread-safe<br/>
 * User: roman.stumm <br/>
 * Date: 29.10.2008 <br/>
 * Time: 17:06:20 <br/>
 * Copyright: Agimatec GmbH
 */
public class AgimatecValidatorFactory implements ValidatorFactory, Cloneable {
    private static AgimatecValidatorFactory DEFAULT_FACTORY;
    private static final ConstraintDefaults defaultConstraints = new ConstraintDefaults();

    private MessageInterpolator messageResolver;
    private TraversableResolver traversableResolver;
    private ConstraintValidatorFactory constraintValidatorFactory;
    private final Map<String, String> properties;

    /** information from xml parsing */
    private final AnnotationIgnores annotationIgnores = new AnnotationIgnores();
    private final ConstraintCached constraintsCache = new ConstraintCached();
    private final Map<Class<?>, Class<?>[]> defaultSequences;
    /**
     * access strategies for properties with cascade validation @Valid support
     */
    private final Map<Class<?>, List<AccessStrategy>> validAccesses;
    private final Map<Class<?>, List<MetaConstraint<?, ? extends Annotation>>> constraintMap;

    /** convenience to retrieve a default global AgimatecValidatorFactory */
    public static AgimatecValidatorFactory getDefault() {
        if (DEFAULT_FACTORY == null) {
            ProviderSpecificBootstrap<AgimatecValidatorConfiguration> provider = Validation
                    .byProvider(AgimatecValidationProvider.class);
            AgimatecValidatorConfiguration configuration = provider.configure();
            DEFAULT_FACTORY = (AgimatecValidatorFactory) configuration.buildValidatorFactory();
        }
        return DEFAULT_FACTORY;
    }

    public AgimatecValidatorFactory() {
        properties = new HashMap<String, String>();
        defaultSequences = new HashMap();
        validAccesses = new HashMap();
        constraintMap = new HashMap();
    }

    public void configure(ConfigurationState configuration) {
        getProperties().putAll(configuration.getProperties());
        setMessageInterpolator(configuration.getMessageInterpolator());
        setTraversableResolver(configuration.getTraversableResolver());
        setConstraintValidatorFactory(configuration.getConstraintValidatorFactory());
        ValidationMappingParser parser = new ValidationMappingParser(this);
        parser.processMappingConfig(configuration.getMappingStreams());
    }

    public Map<String, String> getProperties() {
        return properties;
    }

    protected MessageInterpolator getDefaultMessageInterpolator() {
        return messageResolver;
    }

    /**
     * shortcut method to create a new Validator instance with factory's settings
     *
     * @return the new validator instance
     */
    public Validator getValidator() {
        return usingContext().getValidator();
    }

    /** @return the validator factory's context */
    public AgimatecFactoryContext usingContext() {
        return new AgimatecFactoryContext(this);
    }

    @SuppressWarnings({ "CloneDoesntDeclareCloneNotSupportedException" })
    @Override
    public synchronized AgimatecValidatorFactory clone() {
        try {
            return (AgimatecValidatorFactory) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(); // VM bug.
        }
    }

    public final void setMessageInterpolator(MessageInterpolator messageResolver) {
        this.messageResolver = messageResolver;
    }

    public MessageInterpolator getMessageInterpolator() {
        return ((messageResolver != null) ? messageResolver : getDefaultMessageInterpolator());
    }

    public final void setTraversableResolver(TraversableResolver traversableResolver) {
        this.traversableResolver = traversableResolver;
    }

    public TraversableResolver getTraversableResolver() {
        return traversableResolver;
    }

    public ConstraintValidatorFactory getConstraintValidatorFactory() {
        return constraintValidatorFactory;
    }

    public final void setConstraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
        this.constraintValidatorFactory = constraintValidatorFactory;
    }

    /**
     * Return an object of the specified type to allow access to the
     * provider-specific API.  If the Bean Validation provider
     * implementation does not support the specified class, the
     * ValidationException is thrown.
     *
     * @param type the class of the object to be returned.
     * @return an instance of the specified class
     * @throws ValidationException if the provider does not
     *                             support the call.
     */
    public <T> T unwrap(Class<T> type) {
        if (type.isAssignableFrom(getClass())) {
            return (T) this;
        } else if (!type.isInterface()) {
            return SecureActions.newInstance(type);
        } else {
            try {
                Class<T> cls = ClassUtils.getClass(type.getName() + "Impl");
                return SecureActions.newInstance(cls);
            } catch (ClassNotFoundException e) {
                throw new ValidationException("Type " + type + " not supported");
            }
        }
    }

    public ConstraintDefaults getDefaultConstraints() {
        return defaultConstraints;
    }

    public AnnotationIgnores getAnnotationIgnores() {
        return annotationIgnores;
    }

    public ConstraintCached getConstraintsCache() {
        return constraintsCache;
    }

    public void addMetaConstraint(Class<?> beanClass, MetaConstraint<?, ?> metaConstraint) {
        List<MetaConstraint<?, ? extends Annotation>> slot = constraintMap.get(beanClass);
        if (slot != null) {
            slot.add(metaConstraint);
        } else {
            List<MetaConstraint<?, ? extends Annotation>> constraintList = new ArrayList<MetaConstraint<?, ? extends Annotation>>();
            constraintList.add(metaConstraint);
            constraintMap.put(beanClass, constraintList);
        }
    }

    public void addValid(Class<?> beanClass, AccessStrategy accessStategy) {
        List<AccessStrategy> slot = validAccesses.get(beanClass);
        if (slot != null) {
            slot.add(accessStategy);
        } else {
            List<AccessStrategy> tmpList = new ArrayList();
            tmpList.add(accessStategy);
            validAccesses.put(beanClass, tmpList);
        }
    }

    public void addDefaultSequence(Class<?> beanClass, Class<?>[] groupSequence) {
        defaultSequences.put(beanClass, groupSequence);
    }

    public <T> List<MetaConstraint<T, ? extends Annotation>> getMetaConstraints(Class<T> beanClass) {
        List<MetaConstraint<?, ? extends Annotation>> slot = constraintMap.get(beanClass);
        if (slot != null) {
            //noinspection RedundantCast
            return (List) slot;
        } else {
            return Collections.EMPTY_LIST;
        }
    }

    public List<AccessStrategy> getValidAccesses(Class<?> beanClass) {
        List<AccessStrategy> slot = validAccesses.get(beanClass);
        if (slot != null) {
            return slot;
        } else {
            return Collections.EMPTY_LIST;
        }
    }

    public Class<?>[] getDefaultSequence(Class<?> beanClass) {
        return defaultSequences.get(beanClass);
    }

}