/*
* Copyright 2004-2005 the original author or authors.
*
* 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 org.springmodules.orm.support.validation;
import java.util.Iterator;
import java.util.Map;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.BeansException;
import org.springframework.util.StringUtils;
import org.springframework.validation.Validator;
import org.springmodules.orm.hibernate3.support.PolevValidatingInterceptor;
/**
* <p>This method interceptor supports the validation of domain objects before or after ORM life-cycle events, also
* called the persistent object life-cycle event validation (POLEV) pattern.
*
* <p>Most ORM products have hooks to receive notification of well defined life-cycle events for persistent and transient
* domain objects. This class supports declarative configuration of rules to configure the validation of domain objects
* for certain life-cycle events. Which life-cycle events are supported is determined by vendor specific notification implementations.
*
* <p>To configure validation rules a map must be provided with rules as keys and validator instances as values.
*
* @author Steven Devijver
* @since Jun 17, 2005
* @see org.springmodules.orm.support.validation.ValidatingSupport
* @see org.springmodules.orm.hibernate.support.PolevValidatingInterceptor
* @see org.springmodules.orm.hibernate3.support.PolevValidatingInterceptor
*/
public class PolevValidatingMethodInterceptor extends ValidatingSupport implements
MethodInterceptor {
public PolevValidatingMethodInterceptor() {
super();
}
/**
* <p>The [validators] property takes a map containing rules and
* validator instances.
*
* <p>The rule notation allows you to specify class names and optionally the life-cycle events
* they should be used for. Consult vendor specific documentation for a list of supported life-cycle
* events for your ORM product.
*
* <p>Some rule notation examples:
*
* <ul>
* <li>foo.Bar - objects assignable to foo.Bar will be validated by the associated validator for all life-cycle events.
* <li>foo.Bar,onFlushDirty - same as above except only for onFlushDirty life-cycle event
* <li>foo.Bar,onFlushDirty,onSave - same as above except only for onFlushDirty and onSave life-cycle events
* </ul>
*
* <p>A Spring configuration example:
*
* <pre>
* <property name="validators">
* <map>
* <entry key="foo.Bar,onFlushDirty,onSave" ref="myValidator"/>
* <entry key="foo.Bar,onDelete" ref="myOtherValidator"/>
* </map>
* </property>
* </pre>
*
* @param validators map containing rules and validators.
* @see Validator
* @see PolevValidatingInterceptor
* @see org.springmodules.orm.hibernate.support.PolevValidatingInterceptor
*/
public final void setValidators(Map validators) {
for (Iterator iter = validators.keySet().iterator(); iter.hasNext();) {
Object key = iter.next();
Object value = validators.get(key);
Class clazz = null;
Validator validator = null;
if (value != null) {
if (value instanceof Validator) {
validator = (Validator)value;
} else {
throw new BeansException("Instance for class [" + clazz + "] is not of type org.springframework.validation.Validator!") {};
}
} else {
throw new BeansException("Validator for class [" + clazz + "] is not specified!") {};
}
if (key instanceof Class) {
clazz = (Class)key;
addValidator(ALL, clazz, validator);
} else if (key instanceof String) {
String s = (String)key;
String[] strings = StringUtils.tokenizeToStringArray(s, ",", true, true);
if (strings.length > 0) {
clazz = loadClass(strings[0]);
}
if (strings.length == 1) {
addValidator(ALL, clazz, validator);
} else {
for (int i = 1; i < strings.length; i++) {
addValidator(strings[i], clazz, validator);
}
}
}
}
}
/**
* <p>This method binds and unbinds the validator maps configured in the validators
* property.
*
* @param methodInvocation the method invocation
* @return the result of the method invocation
*/
public Object invoke(MethodInvocation invocation) throws Throwable {
try {
bindValidators();
return invocation.proceed();
} finally {
unbindValidators();
}
}
}