org.springmodules.validation.valang.parser.DefaultVisitor Maven / Gradle / Ivy
/*
* 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.validation.valang.parser;
import javax.servlet.ServletContext;
import org.apache.commons.collections.Predicate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.*;
import org.springframework.core.JdkVersion;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.context.ServletContextAware;
import org.springmodules.validation.util.date.DefaultDateParser;
import org.springmodules.validation.valang.ValangException;
import org.springmodules.validation.valang.functions.*;
import org.springmodules.validation.valang.predicates.GenericTestPredicate;
import org.springmodules.validation.valang.predicates.Operator;
/**
* Allows registration of custom functions. Custom functions can overwrite default functions.
*
* Default functions are:
*
*
* - len, length, size
*
- upper
*
- lower
*
- !
*
*
* @author Steven Devijver
* @since Apr 23, 2005
*/
public class DefaultVisitor implements ValangVisitor, BeanFactoryAware, ApplicationContextAware, ResourceLoaderAware, MessageSourceAware, ApplicationEventPublisherAware, ServletContextAware {
private final static Log logger = LogFactory.getLog(DefaultVisitor.class);
private ValangVisitor visitor = null;
private DefaultDateParser dateParser = null;
private BeanFactory beanFactory = null;
private ApplicationContext applicationContext = null;
private ResourceLoader resourceLoader = null;
private MessageSource messageSource = null;
private ApplicationEventPublisher applicationEventPublisher = null;
private ServletContext servletContext = null;
public DefaultVisitor() {
if (JdkVersion.getMajorJavaVersion() != JdkVersion.JAVA_13) {
this.dateParser = new DefaultDateParser();
}
}
public Function getFunction(String name, Function[] arguments, int line, int column) {
return lifeCycleCallbacks(doGetFunction(name, arguments, line, column), line, column);
}
private Function doGetFunction(String name, Function[] arguments, int line, int column) {
Function function = resolveCustomFunction(name, arguments, line, column);
if (function != null) {
return function;
}
function = resolveFunctionFromApplicationContext(name, arguments, line, column);
if (function != null) {
return function;
}
function = resolveDefaultFunction(name, arguments, line, column);
if (function != null) {
return function;
}
throw new ValangException("Could not find function [" + name + "]", line, column);
}
private Function resolveCustomFunction(String name, Function[] arguments, int line, int column) {
if (getVisitor() == null) {
return null;
}
return getVisitor().getFunction(name, arguments, line, column);
}
private Function resolveFunctionFromApplicationContext(String name, Function[] arguments, int line, int column) {
if (applicationContext == null || !applicationContext.containsBean(name)) {
return null;
}
Object bean = applicationContext.getBean(name);
if (!AbstractInitializableFunction.class.isInstance(bean)) {
logger.warn("Bean '" + name + "' is not of a '" + AbstractInitializableFunction.class.getName() + "' type");
return null;
}
AbstractInitializableFunction function = (AbstractInitializableFunction) bean;
function.init(arguments, line, column);
return function;
}
private Function resolveDefaultFunction(String name, Function[] arguments, int line, int column) {
if ("len".equals(name) || "length".equals(name) || "size".equals(name) || "count".equals(name)) {
return new LengthOfFunction(arguments, line, column);
} else if ("upper".equals(name)) {
return new UpperCaseFunction(arguments, line, column);
} else if ("lower".equals(name)) {
return new LowerCaseFunction(arguments, line, column);
} else if ("!".equals(name)) {
return new NotFunction(arguments, line, column);
} else if ("resolve".equals(name)) {
return new ResolveFunction(arguments, line, column);
} else if ("match".equals(name) || "matches".equals(name)) {
return new RegExFunction(arguments, line, column);
} else if ("inRole".equals(name)) {
return new InRoleFunction(arguments, line, column);
} else if ("email".equals(name)) {
return new EmailFunction(arguments, line, column);
}
return null;
}
private Function lifeCycleCallbacks(Function function, int line, int column) {
if (function instanceof BeanFactoryAware) {
((BeanFactoryAware) function).setBeanFactory(beanFactory);
}
if (function instanceof ApplicationContextAware) {
((ApplicationContextAware) function).setApplicationContext(applicationContext);
}
if (function instanceof ResourceLoaderAware) {
((ResourceLoaderAware) function).setResourceLoader(resourceLoader);
}
if (function instanceof MessageSourceAware) {
((MessageSourceAware) function).setMessageSource(messageSource);
}
if (function instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) function).setApplicationEventPublisher(applicationEventPublisher);
}
if (function instanceof ServletContextAware) {
((ServletContextAware) function).setServletContext(servletContext);
}
if (function instanceof AbstractFunction) {
AbstractFunction abstractFunction = (AbstractFunction) function;
AutowireCapableBeanFactory autowireCapableBeanFactory = null;
if (abstractFunction.isAutowireByName() || abstractFunction.isAutowireByType()) {
if (applicationContext instanceof ConfigurableApplicationContext) {
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
autowireCapableBeanFactory = configurableApplicationContext.getBeanFactory();
} else if (beanFactory instanceof AutowireCapableBeanFactory) {
autowireCapableBeanFactory = (AutowireCapableBeanFactory) beanFactory;
} else if (applicationContext == null && beanFactory == null) {
throw new ValangException("Could not autowire function: no application context or bean factory available", line, column);
} else {
throw new ValangException("Could not autowire function: application context or bean factory does not support autowiring", line, column);
}
}
if (abstractFunction.isAutowireByName()) {
autowireCapableBeanFactory.autowireBeanProperties(function, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false);
}
if (abstractFunction.isAutowireByType()) {
autowireCapableBeanFactory.autowireBeanProperties(function, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
}
try {
abstractFunction.init();
} catch (Exception e) {
throw new ValangException("Error initializing function", e, line, column);
}
}
return function;
}
/**
* Register a custom visitor to look up custom functions. Lookup of functions
* will first be delegated to this visitor. If no function has been returned (null)
* lookup will be handled by DefaultVisitor.
*
* @param visitor the custom visitor
*/
public void setVisitor(ValangVisitor visitor) {
this.visitor = visitor;
}
public ValangVisitor getVisitor() {
return this.visitor;
}
public Predicate getPredicate(Function leftFunction, Operator operator, Function rightFunction, int line, int column) {
return new GenericTestPredicate(leftFunction, operator, rightFunction, line, column);
}
public DefaultDateParser getDateParser() {
if (this.dateParser == null) {
throw new IllegalStateException("Date parser not supported in Java 1.3 or older.");
}
return this.dateParser;
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}