Package org.crank.validation.validators

Source Code of org.crank.validation.validators.DomainValidator

package org.crank.validation.validators;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.crank.core.AnnotationData;
import org.crank.core.AnnotationUtils;
import org.crank.core.MapUtils;
import org.crank.validation.ValidationContext;
import org.crank.validation.ValidatorMessage;
import org.crank.validation.ValidatorMessageHolder;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

/**
* This validator is designed for domain-driven validation
* of a group of child objects from a parent.  For instance, a parent
* with a OneToMany relationship with a child may need to validate
* the child against the other children associated with the parent.
* In this scenario, the validation framework will invoke this
* validator when the @DomainValidation annotation is used on a field
* in the child object by invoking the parent object validation
* method identified by the "method" attribute.  The parent object
* is identified by the "parentProperty" attribute.  If the parent
* attribute is null or missing, then the validation method
* is presumed to exist in the child. 
*
* The validation method will be passed the child object and the
* field value as method.invoke(child, fieldValue)
*
* @author Paul Tabor
*
*/
public class DomainValidator extends AbstractValidator {
  private static final long serialVersionUID = 1L;
  private Logger log = Logger.getLogger(this.getClass());

  private Object rootObject;
 
  public void setRootObject(Object rootObject) {
    this.rootObject = rootObject;
  }
 
    private static Set<String> allowedPackages = new HashSet<String>();
    static {
        allowedPackages.add( "org.crank.annotations.validation" );
   
 
    public DomainValidator() {
    }
   
  @SuppressWarnings("unchecked")
  public ValidatorMessageHolder validate(Object fieldValue, String fieldLabel) {
    // So, we already know that this field has been decorated with @DomainValidation annotation. 
    // That's why we're here. We need to read the validation attributes to find the appropriate 
    // template method (parent or child) to invoke for validation.

    String detailMessage = "";
    String summaryMessage = "";
    this.noMessages = true;
    boolean error = false;
    Object child;
   
    // The first "parent" is actually the child decorated with the validation annotation
    if (rootObject == null) {
      // Grab it from the validation context if it hasn't been provided
          child = ValidationContext.getCurrentInstance().getParentObject();
    } else {
      // Useful if the rootObject is injected, i.e. from a Unit test
          child = rootObject;
    }
   
    log.info("child object = " + (child==null?"null" : child.getClass().getName()));
    log.info("field label = " + fieldLabel);
       
        List<AnnotationData> annotationDataForProperty = AnnotationUtils.getAnnotationDataForProperty( child.getClass(), fieldLabel, false, allowedPackages );
        if (annotationDataForProperty.size()==0) {
            annotationDataForProperty = AnnotationUtils.getAnnotationDataForField( child.getClass(), fieldLabel, allowedPackages );
        }
       
        Map map = MapUtils.convertListToMap( "name", annotationDataForProperty);
       
        boolean found = map.get( "domainValidation" ) != null;
        boolean sameLevel = false;
        boolean noArgs = false;

        if (found) {
            AnnotationData ad = (AnnotationData) map.get( "domainValidation" );
            Object parentReference = ad.getValues().get("parentProperty");
            Object validator = null;

            if ((parentReference != null) && (!"".equals(parentReference))) {
                // If the parentProperty is specified, then find the parent class
             
                BeanWrapper wrapper = new BeanWrapperImpl(child);
                validator = wrapper.getPropertyValue( (String)parentReference );

            } else {
              // Otherwise, the validation method is assumed to be in the child
              validator = child;
              sameLevel = true;
            }
           
            noArgs = (Boolean) ad.getValues().get("global");
           
            // Make sure the method exists
          Method m = null;

          if (validator != null) {
              try {
               
                String methodName = (String)ad.getValues().get("method");

                if (noArgs) {
                    m = validator.getClass().getDeclaredMethod(methodName);
                } else if (sameLevel) {
                    Class[] parameters=new Class[1];
                    BeanWrapper wrapper = new BeanWrapperImpl(child);
                    parameters[0]=wrapper.getPropertyType( fieldLabel );
                    m = validator.getClass().getDeclaredMethod(methodName, parameters);
                } else {
                    Class[] parameters=new Class[2];
                    parameters[0]=child.getClass();
                    BeanWrapper wrapper = new BeanWrapperImpl(child);
                    parameters[1]=wrapper.getPropertyType( fieldLabel );
                    m = validator.getClass().getDeclaredMethod(methodName, parameters);
                }

              } catch (NoSuchMethodException nsme) {
                detailMessage = nsme.getMessage();
                summaryMessage = nsme.getMessage();
                error = true;
                log.error("no method", nsme);
              } catch (Exception e) {
                detailMessage = e.getMessage();
                summaryMessage = e.getMessage();
                error = true;
                log.error("general exception", e);
              }             
            }

          // Invoke the validation method and watch for any exceptions
          try {
            if (noArgs) {
                m.invoke(validator);
            } else if (sameLevel) {
                m.invoke(validator, new Object[]{fieldValue});
            } else {
                m.invoke(validator, new Object[]{child,fieldValue});
            }
          } catch (IllegalAccessException iae) {
            detailMessage = iae.getCause().getMessage();
            summaryMessage = iae.getCause().getMessage();
            error = true;
            log.error("illegal access", iae);
          } catch (InvocationTargetException ite) {
            detailMessage = ite.getCause().getMessage();
            summaryMessage = ite.getCause().getMessage();
            error = true;
            log.error("invocation target exception", ite);
          } catch (Exception e) {
            detailMessage = e.getCause().getMessage();
            summaryMessage = e.getCause().getMessage();
            error = true;
            log.error("general exception", e);
          }             
        }

        ValidatorMessage message = new ValidatorMessage();
       
        // If there were any errors, populate the validation message
        if (error) {
          log.error("There were errors in validation: " + summaryMessage);
          message = new ValidatorMessage(summaryMessage, detailMessage);
          populateMessage(message, (noArgs ? null : fieldLabel));
        }

        return message;
  }
 
}
TOP

Related Classes of org.crank.validation.validators.DomainValidator

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.