All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.datanucleus.BeanValidationHandler Maven / Gradle / Ivy

Go to download

DataNucleus Core provides the primary components of a heterogenous Java persistence solution. It supports persistence API's being layered on top of the core functionality.

There is a newer version: 6.0.9
Show newest version
/**********************************************************************
Copyright (c) 2009 Erik Bengtson and others. All rights reserved. 
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.

Contributors:
2012 Andy Jefferson - fix default groups
    ...
**********************************************************************/
package org.datanucleus;

import java.lang.annotation.ElementType;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Path;
import javax.validation.TraversableResolver;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.datanucleus.metadata.AbstractClassMetaData;
import org.datanucleus.metadata.AbstractMemberMetaData;
import org.datanucleus.metadata.FieldPersistenceModifier;
import org.datanucleus.util.StringUtils;

/**
 * Handles the integration of "javax.validation" Bean Validation API (JSR 303).
 * Note that this is the only class referring to BeanValidation classes so that it is usable in environments without BeanValidation present.
 */
public class BeanValidationHandler
{
    Validator validator;

    ClassLoaderResolver clr;

    Configuration conf;

    /**
     * Constructor for a validation handler.
     * @param ec ExecutionContext that we are persisting in
     * @param validatorFactory Validation factory
     */
    public BeanValidationHandler(ExecutionContext ec, Object validatorFactory)
    {
        conf = ec.getNucleusContext().getConfiguration();
        clr = ec.getClassLoaderResolver();

        validator = ((ValidatorFactory)validatorFactory).usingContext().traversableResolver(new PersistenceTraversalResolver(ec)).getValidator();
    }

    public void close()
    {
    }

    /**
     * Validate the constraints of an object
     * @param pc the object
     * @param callbackName Name of the callback
     * @param groups the validation groups
     */
    public void validate(Object pc, String callbackName, Class[] groups)
    {
        if (validator == null)
        {
            return;
        }

        Set> violations = validator.validate(pc, groups);
        if (!violations.isEmpty())
        {
            throw new javax.validation.ConstraintViolationException(
                "Validation failed for " + StringUtils.toJVMIDString(pc) + " during " + callbackName +
                " for groups "+StringUtils.objectArrayToString(groups) + " - exceptions are attached", violations); 
        }
    }

    public void preDelete(Object pc)
    {
        Class[] groups = getGroups(conf.getStringProperty(PropertyNames.PROPERTY_VALIDATION_GROUP_PREREMOVE), "pre-remove");
        if (groups != null)
        {
            validate(pc, "pre-remove", groups);
        }
    }

    public void preStore(Object pc)
    {
        Class[] groups = getGroups(conf.getStringProperty(PropertyNames.PROPERTY_VALIDATION_GROUP_PREUPDATE), "pre-update");
        if (groups != null)
        {
            validate(pc, "pre-update", groups);
        }
    }

    public void prePersist(Object pc)
    {
        Class[] groups = getGroups(conf.getStringProperty(PropertyNames.PROPERTY_VALIDATION_GROUP_PREPERSIST), "pre-persist");
        if (groups != null)
        {
            validate(pc, "pre-persist", groups);
        }
    }

    /**
     * Parse comma separated string of class names and return a corresponding array of classes
     * @param property the string with comma separated class names
     * @return The groups
     */
    private Class[] getGroups(String property, String eventName)
    {
        if (property == null || property.trim().length() == 0)
        {
            // Default to Default for pre-persist/pre-update and nothing otherwise
            if (eventName.equals("pre-persist") || eventName.equals("pre-update"))
            {
                return new Class[] {javax.validation.groups.Default.class};
            }
            return null;
        }

        String[] classNames = property.trim().split(",");
        Class[] groups = new Class[classNames.length];
        for (int i=0; i@Valid. Note that this method is called only if isReachable
         * returns true for the same set of arguments and if the property is marked as @Valid
         * @param traversableObject object hosting traversableProperty or null if validateValue is called
         * @param traversableProperty the traversable property.
         * @param rootBeanType type of the root object passed to the Validator.
         * @param pathToTraversableObject path from the root object to traversableObject (using the path specification defined by Bean Validator).
         * @param elementType either FIELD or METHOD.
         * @return true if the Bean Validation provider is allowed to cascade validation, false otherwise.
         */
        public boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType)
        {
            // we do not cascade
            return false;
        }

        /**
         * Determine if the Bean Validation provider is allowed to reach the property state
         * @param traversableObject object hosting traversableProperty or null if validateValue is called
         * @param traversableProperty the traversable property.
         * @param rootBeanType type of the root object passed to the Validator.
         * @param pathToTraversableObject path from the root object to traversableObject (using the path specification defined by Bean Validator).
         * @param elementType either FIELD or METHOD.
         * @return true if the Bean Validation provider is allowed to reach the property state, false otherwise.
         */
        public boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType)
        {
            AbstractClassMetaData acmd = ec.getMetaDataManager().getMetaDataForClass(traversableObject.getClass(), ec.getClassLoaderResolver());
            if (acmd == null)
            {
                return false;
            }

            AbstractMemberMetaData mmd = acmd.getMetaDataForMember(traversableProperty.getName());
            if (mmd.getPersistenceModifier() == FieldPersistenceModifier.NONE)
            {
                // Just pass through for non-persistent fields
                return true;
            }

            // Return whether the field is loaded (and don't cause its loading)
            return ec.findStateManager(traversableObject).isFieldLoaded(mmd.getAbsoluteFieldNumber());
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy