br.com.anteros.bean.validation.util.ValidationContextTraversal Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Anteros-Bean-Validation Show documentation
Show all versions of Anteros-Bean-Validation Show documentation
Anteros Bean Validation for Java.
/*******************************************************************************
* Copyright 2012 Anteros Tecnologia
*
* 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 br.com.anteros.bean.validation.util;
import java.lang.reflect.Type;
import br.com.anteros.bean.validation.DynamicMetaBean;
import br.com.anteros.bean.validation.Jsr303MetaBeanFactory;
import br.com.anteros.bean.validation.UnknownPropertyException;
import br.com.anteros.bean.validation.model.MetaBean;
import br.com.anteros.bean.validation.model.MetaProperty;
import br.com.anteros.bean.validation.model.ValidationContext;
import br.com.anteros.bean.validation.util.PathNavigation.CallbackProcedure;
import br.com.anteros.core.utils.ObjectUtils;
import br.com.anteros.core.utils.TypeUtils;
/**
* {@link ValidationContext} traversal {@link CallbackProcedure}.
*
* @version $Rev: 1137074 $ $Date: 2011-06-17 18:20:30 -0500 (Fri, 17 Jun 2011) $
*/
public class ValidationContextTraversal extends CallbackProcedure {
private static class NullSafePropertyAccess extends PropertyAccess {
/**
* Create a new NullSafePropertyAccess instance.
*
* @param clazz
* @param propertyName
*/
public NullSafePropertyAccess(Class> clazz, String propertyName) {
super(clazz, propertyName);
}
/**
* {@inheritDoc}
*/
@Override
public Object get(Object bean) {
return bean == null ? null : super.get(bean);
}
}
private final ValidationContext> validationContext;
private Type type;
private Class> rawType;
/**
* Create a new {@link ValidationContextTraversal} instance.
*
* @param validationContext
*/
public ValidationContextTraversal(ValidationContext> validationContext) {
this.validationContext = validationContext;
init();
}
/**
* Initialize from {@link ValidationContext}.
*/
public void init() {
this.rawType = validationContext.getMetaBean().getBeanClass();
this.type = this.rawType;
}
/**
* {@inheritDoc}
*/
public void handleIndexOrKey(String token) {
moveDownIfNecessary();
AccessStrategy access;
if (IndexedAccess.getJavaElementType(type) != null) {
try {
Integer index = token == null ? null : Integer.valueOf(token);
access = new IndexedAccess(type, index);
validationContext.setCurrentIndex(index);
} catch (NumberFormatException e) {
throw new UnknownPropertyException(String.format("Cannot parse %s as an array/iterable index", token),
e);
}
} else if (KeyedAccess.getJavaElementType(type) != null) {
access = new KeyedAccess(type, token);
validationContext.setCurrentKey(token);
} else {
throw new UnknownPropertyException(String.format("Cannot determine index/key type for %s", type));
}
Object value = validationContext.getBean();
Object child = value == null ? null : access.get(value);
setType(child == null ? access.getJavaType() : child.getClass());
validationContext.setBean(child,
validationContext.getMetaBean().resolveMetaBean(child == null ? rawType : child));
}
/**
* {@inheritDoc}
*/
public void handleProperty(String token) {
moveDownIfNecessary();
MetaBean metaBean = validationContext.getMetaBean();
if (metaBean instanceof DynamicMetaBean) {
metaBean = metaBean.resolveMetaBean(ObjectUtils.defaultIfNull(validationContext.getBean(), rawType));
validationContext.setMetaBean(metaBean);
}
MetaProperty mp = metaBean.getProperty(token);
if (mp == null) {
// TODO this could indicate a property hosted on a superclass; should we shunt the context traversal down a path based on that type?
PropertyAccess access = new PropertyAccess(rawType, token);
if (access.isKnown()) {
// add heretofore unknown, but valid, property on the fly:
mp = Jsr303MetaBeanFactory.addMetaProperty(metaBean, access);
} else {
throw new UnknownPropertyException("unknown property '" + token + "' in " + metaBean.getId());
}
}
validationContext.setMetaProperty(mp);
setType(mp.getType());
}
/**
* If we currently have a property, navigate the context such that the property becomes the bean, in preparation for
* another property.
*
* @param validationContext
*/
public void moveDownIfNecessary() {
MetaProperty mp = validationContext.getMetaProperty();
if (mp != null) {
if (mp.getMetaBean() == null) {
throw new UnknownPropertyException(String.format("Property %s.%s is not cascaded", mp
.getParentMetaBean().getId(), mp.getName()));
}
validationContext.moveDown(mp, new NullSafePropertyAccess(validationContext.getMetaBean().getBeanClass(),
mp.getName()));
}
}
/**
* Set the type of the expression processed thus far.
*
* @param type
*/
protected void setType(Type type) {
this.rawType = TypeUtils.getRawType(type, this.type);
this.type = type;
}
/**
* {@inheritDoc}
*/
public void handleGenericInIterable() {
throw new UnsupportedOperationException("Cannot navigate a ValidationContext to []");
}
/**
* @return the type
*/
public Type getType() {
return type;
}
/**
* @return the rawType
*/
public Class> getRawType() {
return rawType;
}
/**
* {@inheritDoc}
*/
@Override
protected void complete() {
super.complete();
if (validationContext.getMetaProperty() != null) {
return;
}
if (validationContext.getMetaBean() instanceof DynamicMetaBean) {
validationContext.setMetaBean(validationContext.getMetaBean().resolveMetaBean(
ObjectUtils.defaultIfNull(validationContext.getBean(), rawType)));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy