/**********************************************************************
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:
...
**********************************************************************/
package org.datanucleus.api.jpa.beanvalidation;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.PersistenceConfiguration;
import org.datanucleus.state.CallbackHandler;
import org.datanucleus.store.ExecutionContext;
import org.datanucleus.util.StringUtils;
/**
* Handles the integration of javax.validation.
* Should only be invoked if Validation Mode != none
* Implements only the methods preDelete, preStore, prePersist
*/
class BeanValidatorHandler implements CallbackHandler
{
Validator validator;
ClassLoaderResolver clr;
PersistenceConfiguration conf;
/**
*
* @param clr
* @param conf
*/
public BeanValidatorHandler(ExecutionContext ec)
{
ValidatorFactory factory;
conf = ec.getNucleusContext().getPersistenceConfiguration();
clr = ec.getClassLoaderResolver();
if (conf.hasPropertyNotNull("javax.persistence.validation.factory"))
{
//create from javax.persistence.validation.factory if given
factory = (ValidatorFactory) conf.getProperty("javax.persistence.validation.factory");
}
else
{
factory = Validation.buildDefaultValidatorFactory();
}
validator = factory.usingContext().traversableResolver(new JPATraversalResolver(ec)).getValidator();
}
/**
* Validate the constraints of an object
* @param pc the object
* @param groups the validation groups
*/
public void validate(Object pc, String callbackName, Class<?>[] groups)
{
if (validator==null)
{
return;
}
Set<ConstraintViolation<Object>> 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",
(Set <ConstraintViolation<?>>)(Object)(violations));
}
}
public void addListener(Object listener, Class[] classes)
{
//no-op
}
public void close()
{
//no-op
}
public void postAttach(Object pc, Object detachedPC)
{
//no-op
}
public void postClear(Object pc)
{
//no-op
}
public void postCreate(Object pc)
{
//no-op
}
public void postDelete(Object pc)
{
//no-op
}
public void postDetach(Object pc, Object detachedPC)
{
//no-op
}
public void postDirty(Object pc)
{
//no-op
}
public void postLoad(Object pc)
{
//no-op
}
public void postRefresh(Object pc)
{
//no-op
}
public void postStore(Object pc)
{
//no-op
}
public void preAttach(Object detachedPC)
{
//no-op
}
public void preClear(Object pc)
{
//no-op
}
public void preDelete(Object pc)
{
validate(pc, "pre-remove", getGroups(conf.getStringProperty("javax.persistence.validation.group.pre-remove")));
}
public void preDetach(Object pc)
{
//no-op
}
public void preDirty(Object pc)
{
//no-op
}
public void preStore(Object pc)
{
validate(pc, "pre-update", getGroups(conf.getStringProperty("javax.persistence.validation.group.pre-update")));
}
public void removeListener(Object listener)
{
//no-op
}
public void prePersist(Object pc)
{
validate(pc, "pre-persist", getGroups(conf.getStringProperty("javax.persistence.validation.group.pre-persist")));
}
/**
* 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)
{
if (property == null || property.trim().length() == 0)
{
return new Class<?>[] {javax.validation.groups.Default.class};
}
else
{
String[] classNames = property.trim().split(",");
Class<?>[] groups = new Class<?>[classNames.length];
for (int i=0; i<classNames.length; i++)
{
groups[i] = clr.classForName(classNames[i].trim());
}
return groups;
}
}
}