Package com.em.validation.rebind.reflector

Source Code of com.em.validation.rebind.reflector.RuntimeReflectorImpl

package com.em.validation.rebind.reflector;

/*
GWT Validation Framework - A JSR-303 validation framework for GWT

(c) 2008 gwt-validation contributors (http://code.google.com/p/gwt-validation/)

Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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.
*/

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.GroupSequence;
import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.metadata.ConstraintDescriptor;
import javax.validation.metadata.Scope;

import com.em.validation.client.reflector.IReflector;
import com.em.validation.client.reflector.Reflector;
import com.em.validation.rebind.metadata.PropertyMetadata;
import com.em.validation.rebind.resolve.PropertyResolver;

public class RuntimeReflectorImpl extends Reflector {

  Map<String,PropertyMetadata> metadataMap = new HashMap<String, PropertyMetadata>();
 
  private RuntimeReflectorImpl() {
   
  }
 
  public RuntimeReflectorImpl(Class<?> targetClass) {
    this();
    this.targetClass = targetClass;
    this.metadataMap = PropertyResolver.INSTANCE.getPropertyMetadata(targetClass);
    for(String prop : this.metadataMap.keySet()) {
      //don't include class level annotations in the property set
      if(targetClass.getName().equals(prop)) continue;
      //add properties
      this.properties.add(prop);
    }
   
    //set group sequence from metadata
    GroupSequence sequence = targetClass.getAnnotation(GroupSequence.class);
    if(sequence != null) {
      this.groupSequence = sequence.value();
      if(this.groupSequence == null) {
        this.groupSequence = new Class<?>[0];
      }
    }
  }
 
  @Override
  public Object getValue(String name, Object target) {
    //get property metadata
    PropertyMetadata metadata = this.metadataMap.get(name);
   
    Object value = null;
   
    if(metadata != null && metadata.getAccessor() != null) {
      String accessor = metadata.getAccessor();
      if(metadata.isField()) {
          try {
            Field field = this.targetClass.getDeclaredField(accessor);
            field.setAccessible(true);
            value = field.get(target);
          } catch (SecurityException e) {
            throw new ValidationException("A security exception occurred during validation.  Please inspect your class definition and security configuration.",e);
          } catch (NoSuchFieldException e) {
            throw new ValidationException("The field \"" + accessor + "\" does not exist.  Please inspect your class definition.",e);
          } catch (IllegalArgumentException e) {
            throw new ValidationException("Illegal arguments were provided to a property during validation.",e);
          } catch (IllegalAccessException e) {
            throw new ValidationException("Illegal access exception caught during validation.  Only accessible properties can be validated.",e);
          } catch (Exception e) {
            throw new ValidationException("An exception was thrown during validation: " + e.getMessage(),e);
          }
      } else {
        try {
          accessor = accessor.substring(0, accessor.lastIndexOf('('));
          Method method = this.targetClass.getDeclaredMethod(accessor, new Class<?>[]{});
          method.setAccessible(true);
          value = method.invoke(target, new Object[]{});
        } catch (IllegalArgumentException e) {
          throw new ValidationException("Illegal arguments were provided to a method during validation.  Only no-argument properties are accepted.",e);
        } catch (IllegalAccessException e) {
          throw new ValidationException("Illegal access exception caught during validation.  Only accessible properties can be validated.",e);
        } catch (InvocationTargetException e) {
          throw new ValidationException("Invocation target exception caught during validation.  Only accessible classes can be validated.",e);
        } catch (SecurityException e) {
          throw new ValidationException("A security exception occurred during validation.  Please inspect your class definition and security configuration.",e);
        } catch (NoSuchMethodException e) {
          throw new ValidationException("The method \"" + accessor + "\" does not exist.  Please inspect your class definition.",e);
        } catch (Exception e) {
          throw new ValidationException("An exception was thrown during validation: " + e.getMessage(),e);
        }
      }
    }
   
    if(value == null) {
      value = this.getSuperValues(name, target);
    }
   
    return value;
  }
 
  public void setConstraintDescriptorMap(Map<String, Set<ConstraintDescriptor<?>>> constraintDescriptors) {
    this.constraintDescriptors = constraintDescriptors;
  }

  @Override
  public boolean isCascaded(String propertyName) {
    //default to non-cascaded
    boolean result = false;
   
    //get property metadata
    PropertyMetadata metadata = this.metadataMap.get(propertyName);
    String accessor = null;
    if(metadata != null) {
      accessor = metadata.getAccessor();
    }
 
    //check method names for property that is cascaded
    Method method = null;//part of fix for issue #69, starts as null
   
    try {
      if(method == null) {
        method = this.targetClass.getDeclaredMethod(propertyName, new Class<?>[]{});
      }
    } catch (Exception ex) {
      //result will still be false
    }
   
    try {
      if(method == null && accessor != null) {
        method = this.targetClass.getDeclaredMethod(accessor, new Class<?>[]{});
      }     
    } catch (Exception ex) {
      //result will still be false     
    }

    try {
      if(method == null) {
        method = this.targetClass.getDeclaredMethod("get" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1), new Class<?>[]{});
      }
    } catch (Exception ex) {
      //result will still be false     
    }

    try {
      if(method != null) {
        result = method.getAnnotation(Valid.class) != null;
      }
    } catch (Exception ex) {
      //result will still be false
    }
   
    //check fields for property that is cascaded (only if still false)
    if(result == false) {
      try {
        Field field = this.targetClass.getDeclaredField(propertyName);
        if(field != null) {
          result = field.getAnnotation(Valid.class) != null;
        }
      } catch (Exception ex) {
        //result will still be false
      }
    }
   
    //if still false after checking property and field, continue to check other values
    if(result == false) {
      if(this.superReflector != null) {
        result = this.superReflector.isCascaded(propertyName);
      }
      if(result == false) {
        for(IReflector iface : this.reflectorInterfaces) {
          result = iface.isCascaded(propertyName);
          if(result) break;
        }
      }     
    }
   
    return result;
  }

  @Override
  public Class<?> getPropertyType(String name) {
    Class<?> result = null;
   
    //check method names for property that is cascaded
    try {
      Method method = this.targetClass.getDeclaredMethod(name, new Class<?>[]{});
      if(method != null) {
        result = method.getReturnType();
      }
    } catch (Exception ex) {
      //result will still be false     
    }
   
    //check fields for property that is cascaded (only if still false)
    if(result == null) {
      try {
        Field field = this.targetClass.getDeclaredField(name);
        if(field != null) {
          result = field.getType();
        }
      } catch (Exception ex) {
        //result will still be false
      }
    }
   
    //if still false after checking property and field, continue to check other values
    if(result == null) {
      if(this.superReflector != null) {
        result = this.superReflector.getPropertyType(name);
      }
      if(result == null) {
        for(IReflector iface : this.reflectorInterfaces) {
          result = iface.getPropertyType(name);
          if(result != null) break;
        }
      }     
    }
    return result;
  }

  @Override
  public Set<ElementType> declaredOn(Scope scope, String property, ConstraintDescriptor<?> descriptor) {
    Set<ElementType> results = new LinkedHashSet<ElementType>();

    //return if the property string is null or the descriptor is null
    if(property == null || descriptor == null) return results;
   
    //get property descriptor from introspection
    BeanInfo targetInfo = null;
    try {
      targetInfo = Introspector.getBeanInfo(targetClass);
    } catch (IntrospectionException e) {
      //do nothing
    }
   
    //get annotation instance
    Annotation annotation = descriptor.getAnnotation();
   
    //find the property descriptor by name
    PropertyDescriptor prop = null;
    if(targetInfo != null) {
      for(PropertyDescriptor check : targetInfo.getPropertyDescriptors()) {
        if(property.equals(check.getName())) {
          prop = check;
          break;
        }
      }
    }
   
    //check the property and field for the declared annotation
    if(prop != null) {
     
      try {
        Field field = this.targetClass.getDeclaredField(property);
        List<Annotation> annotationList = PropertyResolver.INSTANCE.getContstraintAnnotations(Arrays.asList(field.getAnnotations()));
        for(Annotation checking : annotationList) {
          if(checking.toString().equals(annotation.toString())) {
            results.add(ElementType.FIELD);
          }
        }
      } catch (Exception ex) {
       
      }
     
      try {
        Method method = this.targetClass.getDeclaredMethod(prop.getReadMethod().getName(),new Class<?>[]{});
        List<Annotation> annotationList = PropertyResolver.INSTANCE.getContstraintAnnotations(Arrays.asList(method.getAnnotations()));
        for(Annotation checking : annotationList) {
          if(checking.toString().equals(annotation.toString())) {
            results.add(ElementType.METHOD);
          }
        }
      } catch (Exception ex) {
       
      }
    }
   
    if(Scope.HIERARCHY.equals(scope)) {
      if(this.superReflector != null) {
        results.addAll(this.superReflector.declaredOn(scope, property, descriptor));
      }
      for(IReflector iface : this.reflectorInterfaces) {
        if(iface != null){
          results.addAll(iface.declaredOn(scope, property, descriptor));
        }
      }
    }
   
    return results;
 
}
TOP

Related Classes of com.em.validation.rebind.reflector.RuntimeReflectorImpl

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.