Package org.strecks.validator.internal

Source Code of org.strecks.validator.internal.ValidationAnnotationReader

/*
* Copyright 2005-2006 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.strecks.validator.internal;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.strecks.bind.internal.BindConvertInfo;
import org.strecks.converter.Converter;
import org.strecks.converter.SafeBeanUtilsConverter;
import org.strecks.converter.handler.ConversionHandler;
import org.strecks.converter.handler.DefaultConversionHandler;
import org.strecks.exceptions.ApplicationConfigurationException;
import org.strecks.util.ReflectHelper;
import org.strecks.validator.Validator;
import org.strecks.validator.annotation.ValidatorFactoryClass;
import org.strecks.validator.factory.ValidatorFactory;
import org.strecks.validator.strategy.DefaultValidationStrategy;

/**
* Looks for <code>ValidatorFactory</code> in the <code>ValidBindingForm</code> form bean. Identifies these as
* annotations which themselves are annotated using the <code>ValidatorFactoryClass</code> annotation
* @author Phil Zoio
*/
public class ValidationAnnotationReader
{

  /**
   * @param bean
   *            the bean being validated
   * @param info
   *            contains the bind handlers and converters for the bean
   */
  public ValidationInfo readValidationHandlers(Object bean, BindConvertInfo info)
  {

    Class thisClass = bean.getClass();

    Map<OrderedProperty, MethodValidators> map = new TreeMap<OrderedProperty, MethodValidators>();

    for (Method method : thisClass.getMethods())
    {

      String setterName = method.getName();
      String propertyName = ReflectHelper.getPropertyName(setterName);
      Converter converter = getConverter(thisClass, propertyName, info);

      MethodValidators methodValidators = readMethodAnnotations(method, propertyName, converter);
      if (methodValidators != null)
        map.put(methodValidators.getOrderedProperty(), methodValidators);

    }

    ConversionHandler conversionHandler = getConversionHandler(info);

    ValidationInfo vi = new ValidationInfo(map, new DefaultValidationStrategy(), conversionHandler);
    return vi;
  }

  MethodValidators readMethodAnnotations(Method method, String propertyName, Converter converter)
  {

    List<ValidatorWrapper> validators = null;

    Annotation[] annotations = method.getAnnotations();

    int minOrder = 999;

    boolean foundValidator = false;

    for (Annotation annotation : annotations)
    {

      Class<? extends Annotation> annotationType = annotation.annotationType();
      ValidatorFactoryClass factory = annotationType.getAnnotation(ValidatorFactoryClass.class);

      if (factory != null)
      {

        checkIsSetter(method);

        foundValidator = true;

        Class validatorFactoryClass = factory.value();

        ValidatorFactory v = ReflectHelper.createInstance(validatorFactoryClass, ValidatorFactory.class);

        Method getter = getGetter(method);
        ValidatorWrapper wrapper = v.create(annotation, getter);
        Validator validator = wrapper.getValidator();

        // if we using the raw type, we can check that the generic type matches the
        if (!wrapper.getUsesConvertedValue())
        {
          checkValidatorType(propertyName, getter, validator.getClass(), Validator.class, annotationType);
        }

        validators = addValidator(validators, wrapper);

        minOrder = updateMinOrder(minOrder, wrapper);

      }

      // sort the validators internally according to order
      if (foundValidator)
        Collections.sort(validators);
    }

    if (validators != null)
    {
      OrderedProperty orderedProperty = new OrderedProperty(propertyName, minOrder);
      return newMethodValidators(method.getDeclaringClass(), orderedProperty, validators, converter);
    }
    else
      return null;

  }

  ConversionHandler getConversionHandler(BindConvertInfo info)
  {
    ConversionHandler conversionHandler = null;

    if (info != null)
    {
      conversionHandler = info.getConversionHandler();
    }
    else
    {
      conversionHandler = new DefaultConversionHandler();
    }
    return conversionHandler;
  }

  List<ValidatorWrapper> addValidator(List<ValidatorWrapper> validators, ValidatorWrapper wrapper)
  {
    if (validators == null)
    {
      validators = new ArrayList<ValidatorWrapper>();
    }
    validators.add(wrapper);
    return validators;
  }

  private int updateMinOrder(int minOrder, ValidatorWrapper wrapper)
  {
    minOrder = Math.min(wrapper.getOrder(), minOrder);
    return minOrder;
  }

  MethodValidators newMethodValidators(Class<?> declaringClass, OrderedProperty orderedProperty,
      List<ValidatorWrapper> validators, Converter converter)
  {
    ConvertedTypeValidationChecker checker = new ConvertedTypeValidationChecker(declaringClass, orderedProperty,
        validators);
    boolean usesConvertedValue = checker.checkConvertedValueTypes();
   
    Class<?> converterType = null;
    if (usesConvertedValue)
    {
      converterType = checker.getConverterType();
      converter.setTargetClass(converterType);
    }
    return new MethodValidators(orderedProperty, validators, converter, usesConvertedValue, converterType);
  }

  Converter getConverter(Class thisClass, String propertyName, BindConvertInfo info)
  {
    Converter converter = null;
    if (info != null)
    {
      Map<String, Converter> converterMap = info.getConverterMap();

      if (converterMap != null)
        converter = converterMap.get(propertyName);

    }
    if (converter == null)
    {
      //log.info("No converter available for property name " + propertyName + " in class " + thisClass.getName()
      //    + ". Validation may not work correctly if converting validator is not present");
      converter = new SafeBeanUtilsConverter();
    }
    return converter;
  }

  Method getGetter(Method method)
  {
    Method getter = ReflectHelper.getGetter(method);

    if (getter == null)
    {
      throw new ApplicationConfigurationException("Setter method " + method
          + " has no corresponding getter method");
    }
    return getter;
  }

  void checkValidatorType(String propertyName, Method getter, Class validatorClass, Class interfaceClass,
      Class<? extends Annotation> annotationType)
  {

    boolean isTypeCompatible = ReflectHelper.checkGenericType(validatorClass, interfaceClass, getter
        .getReturnType());

    if (!isTypeCompatible)
    {
      Class genericClass = ReflectHelper.getGenericType(validatorClass, interfaceClass);

      throw new ApplicationConfigurationException("Class " + getter.getDeclaringClass().getName()
          + " has property " + propertyName + " whose return type " + getter.getReturnType().getName()
          + " does not match the type " + genericClass.getName() + " of the validator used by annotation @"
          + annotationType.getSimpleName());

    }

  }

  private void checkIsSetter(Method method)
  {
    if (!ReflectHelper.isSetter(method))
    {
      throw new ApplicationConfigurationException("Invalid Validation annotation for method " + method
          + ": annotation only supports setter properties");
    }
  }

}
TOP

Related Classes of org.strecks.validator.internal.ValidationAnnotationReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.