All Downloads are FREE. Search and download functionalities are using the official Maven repository.

leap.lang.reflect.ReflectField Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2012 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 leap.lang.reflect;

import leap.lang.*;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;

public class ReflectField extends ReflectMember implements ReflectValued {
	
	private final Field    field;
	private final Class type;

	private final ReflectMethod setter;
	private final ReflectMethod getter;
	
	private final int fieldAccessorIndex;
	private final int setterAccessorIndex;
	private final int getterAccessorIndex;
	
	private final ReflectAccessor accessor;
	
	protected ReflectField(ReflectClass reflectiveClass, Field field){
		super(reflectiveClass,field);

		this.field      = field;
		this.type       = field.getType();
		this.setter     = findSetter();
		this.getter     = findGetter();
		this.accessor   = reflectiveClass.getAccessor();

		if(null != setter){
			setter.setSetterOf(this);
		}
		
		if(null != getter){
			getter.setGetterOf(this);
		}
		
		this.fieldAccessorIndex  = null == accessor ? -1 : accessor.getFieldIndex(field);
		this.setterAccessorIndex = null == setter || null == accessor ? -1 : accessor.getMethodIndex(setter.getReflectedMethod());
		this.getterAccessorIndex = null == getter || null == accessor ? -1 : accessor.getMethodIndex(getter.getReflectedMethod());
		
		this.initialize();
	}
	
	public String getName() {
	    return field.getName();
    }

    public Class getType(){
        return type;
    }

    public Type getGenericType(){
        return field.getGenericType();
    }
    
    public Annotation[] getAnnotations() {
    	return field.getAnnotations();
    }
    
	public Field getReflectedField(){
		return field;
	}
	
	public Class getDeclaringClass(){
		return field.getDeclaringClass();
	}
	
	public boolean isAnnotationPresent(Class annotationType){
		return field.isAnnotationPresent(annotationType);
	}
	
	public  T getAnnotation(Class annotationType) {
		return field.getAnnotation(annotationType);
	}
	
	public boolean isSynthetic(){
		return field.isSynthetic();
	}
	
	public boolean isStatic(){
		return Modifier.isStatic(field.getModifiers());
	}	
	
	public boolean isFinal(){
		return Modifier.isFinal(field.getModifiers());
	}
	
	public boolean isTransient(){
		return Modifier.isTransient(field.getModifiers());
	}
	
	public boolean hasGetter(){
		return null != getter;
	}
	
	public boolean hasSetter(){
		return null != setter;
	}
	
	public ReflectMethod getGetter(){
		return getter;
	}
	
	public ReflectMethod getSetter(){
		return setter;
	}
	
	public boolean isPublicGet(){
		return Modifier.isPublic(field.getModifiers()) || (null != getter && getter.isPublic());
	}
	
	public boolean isPublicSet(){
		return Modifier.isPublic(field.getModifiers()) || (null != setter && setter.isPublic());
	}
	
	public boolean isPublicGetSet(){
		return Modifier.isPublic(field.getModifiers()) || (
				(null != setter && setter.isPublic()) && (null != getter && getter.isPublic())); 
	}
	
	public void setValue(Object instance, Object value) {
		setValue(instance,value,false);
	}
	
	public void setValue(Object instance, Object value, boolean useSetter) {
        try {
        	if(field.isSynthetic() || isFinal()){
        		field.set(instance, safeValue(value));
        	}else{
            	if(useSetter && null != setter){
            		if(setterAccessorIndex != -1){
            			accessor.invokeMethod(instance, setterAccessorIndex, safeValue(value));
            		}else{
            			setter.invoke(instance, safeValue(value));
            		}
            	}else{
            		if(fieldAccessorIndex != -1){
                    	accessor.setFieldValue(instance, fieldAccessorIndex, safeValue(value));
                    }else{
                        field.set(instance, safeValue(value));
                    }
            	}
        	}
        } catch (Exception e) {
        	throw new ReflectException(Strings.format("Error setting value '{0}' to field '{1}'",value,getName()),e);
        }
	}
	
	public Object getValue(Object instance) {
		return getValue(instance,false);
	}
	
	public Object getValue(Object instance,boolean useGetter) {
        try {
        	if(useGetter && null != getter){
        		if(getterAccessorIndex != -1){
        			return accessor.invokeMethod(instance, getterAccessorIndex, Arrays2.EMPTY_OBJECT_ARRAY);
        		}else{
        			return getter.invoke(instance, Arrays2.EMPTY_OBJECT_ARRAY);
        		}
        	}else{
        		if(fieldAccessorIndex != -1){
                    return accessor.getFieldValue(instance, fieldAccessorIndex);
                }else {
                    return field.get(instance);
                }
        	}
        } catch (Throwable e) {
        	if(e instanceof InvocationTargetException){
        		e = e.getCause();
        	}
        	if(e instanceof RuntimeException){
        		throw (RuntimeException)e;
        	}
        	throw new ReflectException(Strings.format("Error getting value of field '{0}'",getName()),e);
        }
	}
	
	private void initialize(){
		this.setAccessiable();
	}
	
	private ReflectMethod findSetter(){
		String   fieldName  = field.getName().startsWith("_") ? field.getName().substring(1) : field.getName();
		String   nameToFind = "set" + Character.toUpperCase(fieldName.charAt(0)) + (fieldName.length() > 1 ? fieldName.substring(1) : "");
		Class fieldType  = Primitives.wrap(field.getType());
		
		ReflectMethod m = findSetter(fieldType, nameToFind);
		
		if(null == m && Classes.isBoolean(fieldType) && fieldName.startsWith("is") && fieldName.length() > 2){
			nameToFind = "set" + Character.toUpperCase(fieldName.charAt(2)) + (fieldName.length() > 3 ? fieldName.substring(3) : "");
			
			m = findSetter(fieldType,nameToFind);
		}
		
		if(null == m){
			m = findSetter(fieldType,fieldName);
		}
		
		return m;
	}
	
	private ReflectMethod findSetter(Class fieldType,String nameToFind){
		//iterate all public methods.
		for(ReflectMethod rm : reflectClass.getMethods()){
			Method m = rm.getReflectedMethod();
			if(m.getParameterTypes().length == 1 && 
					fieldType.isAssignableFrom(Primitives.wrap(m.getParameterTypes()[0]))){
				
				if(m.getName().equals(nameToFind)){
					return rm;
				}
			}
		}
		return null;		
	}
	
	private ReflectMethod findGetter(){
		String   fieldName  = field.getName().startsWith("_") ? field.getName().substring(1) : field.getName();
		String   nameToFind = "get" + Character.toUpperCase(fieldName.charAt(0)) + (fieldName.length() > 1 ? fieldName.substring(1) : "");
		Class fieldType  = Primitives.wrap(field.getType());
		
		ReflectMethod m = findGetter(fieldType,nameToFind);
		
		if(null == m && Classes.isBoolean(fieldType)){
			if(fieldName.startsWith("is") && fieldName.length() > 2){
				if(Boolean.class.equals(field.getType())){
					nameToFind = "get" + Strings.upperFirst(fieldName.substring(2));
					
					if(null != (m = findGetter(fieldType, nameToFind))){
						return m;
					}
				}
				
				nameToFind = fieldName;
			}else{
				nameToFind = "is" + Character.toUpperCase(fieldName.charAt(0)) + (fieldName.length() > 1 ? fieldName.substring(1) : "");
			}
			
			m = findGetter(fieldType,nameToFind);
		}

		return m;
	}
	
	private ReflectMethod findGetter(Class fieldType,String nameToFind){
		for(ReflectMethod rm : reflectClass.getMethods()){
			Method m = rm.getReflectedMethod();
			if(m.getParameterTypes().length == 0 && 
					Primitives.wrap(m.getReturnType()).isAssignableFrom(fieldType)){
				
				if(m.getName().equals(nameToFind)){
					return rm;
				}
			}
		}
		return null;		
	}
	
	private void setAccessiable(){
		try {
			if(!field.isAccessible()){
				this.field.setAccessible(true);
			}
        } catch (SecurityException e) {
        	;
        }
	}
	
    private Object safeValue(Object value){
        if(null == value){
        	return Classes.getDefaultValue(type);
        }
        return value;
    }
    
	@Override
    public String toString() {
		return field.toString();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy