blob: 4fcd193e1779e3b8d475f1bad6913a7b54b6317c [file] [log] [blame]
/*
* Copyright 2000-2014 Vaadin Ltd.
*
* 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.
*
* Contribution:
* Florian Pirchner - OSGi support
*/
package org.eclipse.osbp.ecview.core.common.editpart.emf.validation.validator;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.util.Locale;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.MessageInterpolator;
import javax.validation.MessageInterpolator.Context;
import javax.validation.Validator;
import javax.validation.ValidatorContext;
import javax.validation.ValidatorFactory;
import javax.validation.metadata.ConstraintDescriptor;
import org.apache.commons.beanutils.PropertyUtils;
import org.eclipse.osbp.ecview.core.common.validation.AbstractCollectingValidator;
import org.eclipse.osbp.ecview.core.common.validation.IValidator;
import org.eclipse.osbp.runtime.common.i18n.II18nService;
import org.eclipse.osbp.runtime.common.validation.IStatus;
import org.eclipse.osbp.runtime.common.validation.Status;
import org.eclipse.osbp.runtime.jsr303.validation.common.ValidationUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// TODO: Auto-generated Javadoc
/**
* The Class BeanValidationValidator.
*/
public class BeanValidationValidator extends AbstractCollectingValidator implements IValidator {
/** The Constant LOGGER. */
private static final Logger LOGGER = LoggerFactory.getLogger(BeanValidationValidator.class);
/** The bean class. */
private final Class<?> beanClass;
/** The property name. */
private final String propertyName;
/** The property class. */
private final Class<?> propertyClass;
/** The locale. */
private Locale locale;
/** The i18n service. */
@SuppressWarnings("unused")
private II18nService i18nService;
/** The javax bean validator factory. */
@SuppressWarnings("unused")
private final ValidatorFactory javaxBeanValidatorFactory;
/** The javax bean validator. */
private Validator javaxBeanValidator;
/** The field id. */
private final String fieldId;
/** The field i18n key. */
private final String fieldI18nKey;
private MessageInterpolator messageInterpolator;
/**
* Instantiates a new bean validation validator.
*
* @param beanClass
* the bean class
* @param propertyName
* the property name
* @param jsr303ValidatorFactory
* the jsr303 validator factory
* @param fieldId
* the field id
* @param fieldI18nKey
* the field i18n key
* @param locale
*/
public BeanValidationValidator(Class<?> beanClass, String propertyName, ValidatorFactory jsr303ValidatorFactory,
String fieldId, String fieldI18nKey, Locale locale) {
this.javaxBeanValidatorFactory = jsr303ValidatorFactory;
messageInterpolator = ValidationUtil.createNewMessageInterpolator(locale);
ValidatorContext usingContext = jsr303ValidatorFactory.usingContext();
usingContext.messageInterpolator(messageInterpolator);
this.javaxBeanValidator = usingContext.getValidator();
this.beanClass = beanClass;
this.propertyClass = getPropertyType(beanClass, propertyName);
this.propertyName = propertyName;
locale = Locale.getDefault();
this.fieldId = fieldId;
this.fieldI18nKey = fieldI18nKey;
}
/**
* Gets the property type.
*
* @param beanClass
* the bean class
* @param propertyName
* the property name
* @return the property type
*/
protected Class<?> getPropertyType(Class<?> beanClass, String propertyName) {
for (PropertyDescriptor desc : PropertyUtils.getPropertyDescriptors(beanClass)) {
if (desc.getName().equals(propertyName)) {
return desc.getPropertyType();
}
}
throw new IllegalStateException("Property " + propertyName + " not available in class " + beanClass.getName());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.core.common.validation.IValidator#getType()
*/
@Override
public Class<?> getType() {
return propertyClass;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.core.common.validation.IValidator#
* isCheckValidType()
*/
@Override
public boolean isCheckValidType() {
return false;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.osbp.ecview.core.common.validation.IValidator#validateValue(
* java.lang.Object)
*/
@SuppressWarnings("rawtypes")
@Override
public IStatus validateValue(Object value) {
if (javaxBeanValidator == null) {
return Status.createStatus("", BeanValidationValidator.class, IStatus.Severity.ERROR,
"Error occured: javaxBeanValidator was null.");
}
Set<?> violations = null;
try {
Object convertedValue = value;
if (value != null && value instanceof Number && !propertyClass.isAssignableFrom(value.getClass())) {
convertedValue = convertNumber((Number) value);
}
violations = javaxBeanValidator.validateValue(beanClass, propertyName, convertedValue);
} catch (Exception e) {
IStatus status = Status.createErrorStatus(e);
resetCurrentStatus();
addCurrentStatus(status);
return status;
}
if (violations.isEmpty()) {
resetCurrentStatus();
return IStatus.OK;
}
@SuppressWarnings("unchecked")
Set<IStatus> status = ValidationUtil.getStatus(getClass(), (Set<ConstraintViolation>) violations);
// fix the field id
for (IStatus s : status) {
s.putProperty(IStatus.PROP_FIELD_ID, fieldId);
s.putProperty(IStatus.PROP_FIELD_I18N_KEY, fieldI18nKey);
}
resetCurrentStatus();
addCurrentStatus(status);
return status.size() > 0 ? status.iterator().next() : IStatus.OK;
}
/**
* Convert number.
*
* @param value
* the value
* @return the object
*/
private Object convertNumber(Number value) {
if (propertyClass == Byte.class || propertyClass == Byte.TYPE) {
return value.byteValue();
} else if (propertyClass == Short.class || propertyClass == Short.TYPE) {
return value.shortValue();
} else if (propertyClass == Integer.class || propertyClass == Integer.TYPE) {
return value.intValue();
} else if (propertyClass == Double.class || propertyClass == Double.TYPE) {
return value.doubleValue();
} else if (propertyClass == Float.class || propertyClass == Float.TYPE) {
return value.floatValue();
} else if (propertyClass == Long.class || propertyClass == Long.TYPE) {
return value.longValue();
}
return null;
}
/**
* Sets the locale used for validation error messages.
*
* Revalidation is not automatically triggered by setting the locale.
*
* @param locale
* the new locale
*/
public void setLocale(Locale locale) {
this.locale = locale;
ValidationUtil.updateLocale(messageInterpolator, locale);
}
/**
* Gets the locale used for validation error messages.
*
* @return locale used for validation
*/
public Locale getLocale() {
return locale;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.osbp.ecview.core.common.validation.IValidator#updateParameter
* (java.lang.Object)
*/
@Override
public void updateParameter(Object model) {
// not supported yet
LOGGER.error("Update parameter for BeanValidationValidator not allowed yet!");
}
/*
* (non-Javadoc)
*
* @see org.eclipse.osbp.ecview.core.common.validation.
* AbstractCollectingValidator#internalDispose()
*/
@Override
protected void internalDispose() {
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.osbp.ecview.core.common.validation.IValidator#setI18nService(
* org.eclipse.osbp.runtime.common.i18n.II18nService)
*/
@Override
public void setI18nService(II18nService i18nService) {
this.i18nService = i18nService;
};
/**
* Simple implementation of a message interpolator context that returns
* fixed values.
*/
@SuppressWarnings("serial")
protected static class SimpleContext implements Context, Serializable {
/** The value. */
private final Object value;
/** The descriptor. */
private final ConstraintDescriptor<?> descriptor;
/**
* Create a simple immutable message interpolator context.
*
* @param value
* value being validated
* @param descriptor
* ConstraintDescriptor corresponding to the constraint being
* validated
*/
public SimpleContext(Object value, ConstraintDescriptor<?> descriptor) {
this.value = value;
this.descriptor = descriptor;
}
/*
* (non-Javadoc)
*
* @see
* javax.validation.MessageInterpolator.Context#getConstraintDescriptor(
* )
*/
@Override
public ConstraintDescriptor<?> getConstraintDescriptor() {
return descriptor;
}
/*
* (non-Javadoc)
*
* @see javax.validation.MessageInterpolator.Context#getValidatedValue()
*/
@Override
public Object getValidatedValue() {
return value;
}
/*
* (non-Javadoc)
*
* @see
* javax.validation.MessageInterpolator.Context#unwrap(java.lang.Class)
*/
public <T> T unwrap(Class<T> arg0) {
return null;
}
}
}