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

org.sfm.reflect.SetterFactory Maven / Gradle / Ivy

package org.sfm.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.sfm.jdbc.AsmHelper;
import org.sfm.reflect.asm.AsmFactory;
import org.sfm.reflect.primitive.BooleanFieldSetter;
import org.sfm.reflect.primitive.BooleanMethodSetter;
import org.sfm.reflect.primitive.BooleanSetter;
import org.sfm.reflect.primitive.ByteFieldSetter;
import org.sfm.reflect.primitive.ByteMethodSetter;
import org.sfm.reflect.primitive.ByteSetter;
import org.sfm.reflect.primitive.CharacterFieldSetter;
import org.sfm.reflect.primitive.CharacterMethodSetter;
import org.sfm.reflect.primitive.CharacterSetter;
import org.sfm.reflect.primitive.DoubleFieldSetter;
import org.sfm.reflect.primitive.DoubleMethodSetter;
import org.sfm.reflect.primitive.DoubleSetter;
import org.sfm.reflect.primitive.FloatFieldSetter;
import org.sfm.reflect.primitive.FloatMethodSetter;
import org.sfm.reflect.primitive.FloatSetter;
import org.sfm.reflect.primitive.IntFieldSetter;
import org.sfm.reflect.primitive.IntMethodSetter;
import org.sfm.reflect.primitive.IntSetter;
import org.sfm.reflect.primitive.LongFieldSetter;
import org.sfm.reflect.primitive.LongMethodSetter;
import org.sfm.reflect.primitive.LongSetter;
import org.sfm.reflect.primitive.ShortFieldSetter;
import org.sfm.reflect.primitive.ShortMethodSetter;
import org.sfm.reflect.primitive.ShortSetter;
import org.sfm.utils.PropertyNameMatcher;

public final class SetterFactory {
	
	private final AsmFactory asmFactory;
	
	public SetterFactory(final AsmFactory asmSetterFactory) {
		this.asmFactory = asmSetterFactory;
	}
	
	public SetterFactory() {
		this.asmFactory = AsmHelper.getAsmSetterFactory();
	}

	public AsmFactory getAsmFactory() {
		return asmFactory;
	}

	public  Setter getSetter(final Class target, final String property) {
		// first look for method
		final Method method = lookForMethod(target, property);
		
		if (method == null) {
			return getFieldSetter(target, property);
		} else {
			return getMethodSetter(method);
		}
	}

	private  Setter getMethodSetter(final Method method) {
		if (asmFactory != null) {
			try {
				return asmFactory.createSetter(method);
			} catch(Exception e) {
				return new MethodSetter(method);
			}
		} else {
			return new MethodSetter(method);
		}
	}

	public  FieldSetter getFieldSetter(final Class target, final String property) {
		// look for field
		final Field field = lookForField(target, property);
		
		if (field != null) {
			field.setAccessible(true);
			return new FieldSetter(field);
		} else {
			return null;
		}
	}

	private Method lookForMethod(final Class target, final String property) {
		
		for(Method m : target.getDeclaredMethods()) {
			if(methodModifiersMatches(m.getModifiers())
					&& methodNameMatchesProperty(m.getName(), property)) {
				return m;
			}
		}
		
		if (!Object.class.equals(target)) {
			return lookForMethod(target.getSuperclass(), property);
		}
		
		return null;
	}
	

	private Field lookForField(final Class target, final String property) {
		for(Field field : target.getDeclaredFields()) {
			if(fieldModifiersMatches(field.getModifiers())
					&& fieldNameMatchesProperty(field.getName(), property)) {
				return field;
			}
		}
		
		if (!Object.class.equals(target)) {
			return lookForField(target.getSuperclass(), property);
		}
		
		return null;
	}
	
	private boolean methodModifiersMatches(final int modifiers) {
		return !Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers);
	}

	private boolean methodNameMatchesProperty(final String name, final String property) {
		return (isSetter(name) && name.regionMatches(true, 3, property, 0, property.length())) 
				|| name.equalsIgnoreCase(property);
	}
	
	private boolean fieldModifiersMatches(final int modifiers) {
		return !Modifier.isStatic(modifiers) &&  ! Modifier.isFinal(modifiers);
	}

	private boolean fieldNameMatchesProperty(final String name, final String property) {
		return  name.equalsIgnoreCase(property);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public  BooleanSetter toBooleanSetter(final Setter setter) {
		if (setter instanceof BooleanSetter) {
			return (BooleanSetter) setter;
		} else if (setter instanceof MethodSetter) {
			return new BooleanMethodSetter(((MethodSetter) setter).getMethod());
		} else if (setter instanceof FieldSetter) {
			return new BooleanFieldSetter(((FieldSetter) setter).getField());
		} else {
			throw new IllegalArgumentException("Invalid type " + setter);
		}
	}
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public  ByteSetter toByteSetter(final Setter setter) {
		if (setter instanceof ByteSetter) {
			return (ByteSetter) setter;
		} else if (setter instanceof MethodSetter) {
			return new ByteMethodSetter(((MethodSetter) setter).getMethod());
		} else if (setter instanceof FieldSetter) {
			return new ByteFieldSetter(((FieldSetter) setter).getField());
		} else {
			throw new IllegalArgumentException("Invalid type " + setter);
		}
	}
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public  CharacterSetter toCharacterSetter(final Setter setter) {
		if (setter instanceof CharacterSetter) {
			return (CharacterSetter) setter;
		} else if (setter instanceof MethodSetter) {
			return new CharacterMethodSetter(((MethodSetter) setter).getMethod());
		} else if (setter instanceof FieldSetter) {
			return new CharacterFieldSetter(((FieldSetter) setter).getField());
		} else {
			throw new IllegalArgumentException("Invalid type " + setter);
		}
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public  ShortSetter toShortSetter(final Setter setter) {
		if (setter instanceof ShortSetter) {
			return (ShortSetter) setter;
		} else if (setter instanceof MethodSetter) {
			return new ShortMethodSetter(((MethodSetter) setter).getMethod());
		} else if (setter instanceof FieldSetter) {
			return new ShortFieldSetter(((FieldSetter) setter).getField());
		} else {
			throw new IllegalArgumentException("Invalid type " + setter);
		}
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public  IntSetter toIntSetter(final Setter setter) {
		if (setter instanceof IntSetter) {
			return (IntSetter) setter;
		} else if (setter instanceof MethodSetter) {
			return new IntMethodSetter(((MethodSetter) setter).getMethod());
		} else if (setter instanceof FieldSetter) {
			return new IntFieldSetter(((FieldSetter) setter).getField());
		} else {
			throw new IllegalArgumentException("Invalid type " + setter);
		}
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public  LongSetter toLongSetter(final Setter setter) {
		if (setter instanceof LongSetter) {
			return (LongSetter) setter;
		} else if (setter instanceof MethodSetter) {
			return new LongMethodSetter(((MethodSetter) setter).getMethod());
		} else if (setter instanceof FieldSetter) {
			return new LongFieldSetter(((FieldSetter) setter).getField());
		} else {
			throw new IllegalArgumentException("Invalid type " + setter);
		}
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public  FloatSetter toFloatSetter(final Setter setter) {
		if (setter instanceof FloatSetter) {
			return (FloatSetter) setter;
		} else if (setter instanceof MethodSetter) {
			return new FloatMethodSetter(((MethodSetter) setter).getMethod());
		} else if (setter instanceof FieldSetter) {
			return new FloatFieldSetter(((FieldSetter) setter).getField());
		} else {
			throw new IllegalArgumentException("Invalid type " + setter);
		}
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public  DoubleSetter toDoubleSetter(final Setter setter) {
		if (setter instanceof DoubleSetter) {
			return (DoubleSetter) setter;
		} else if (setter instanceof MethodSetter) {
			return new DoubleMethodSetter(((MethodSetter) setter).getMethod());
		} else if (setter instanceof FieldSetter) {
			return new DoubleFieldSetter(((FieldSetter) setter).getField());
		} else {
			throw new IllegalArgumentException("Invalid type " + setter);
		}
	}

	public  Map> getAllSetters(final Class target) {
		final Map> setters = new HashMap>();
		
		visitSetters(new SetterVisitor() {
			@Override
			public boolean visitSetter(final String property, final Setter setter) {
				setters.put(property, setter);
				return true;
			}
		}, target);
		
		return setters;
	}
	
	public  Setter findSetter(final PropertyNameMatcher matcher, final Class target) {
		return visitSetters(new PropertyMatchingSetterVisitor(matcher), target).setter();
	}
	
	public > C visitSetters(final C visitor, final Class target) {
		final Set properties = new HashSet();
		Class currentClass = target;
		
		while(!Object.class.equals(currentClass)) {
			
			for(Method method : currentClass.getDeclaredMethods()) {
				final String name = method.getName();
				if (methodModifiersMatches(method.getModifiers()) && isSetter(name)) {
					final String propertyName = name.substring(3,4).toLowerCase() +  name.substring(4);
					if (!properties.contains(propertyName)) {
						final Setter setter = getMethodSetter(method);
						if (!visitor.visitSetter(propertyName, setter)) {
							return visitor;
						}
						properties.add(propertyName);
					}
				}
			}
			
			for(Field field : currentClass.getDeclaredFields()) {
				final String name = field.getName();
				if (fieldModifiersMatches(field.getModifiers())) {
					if (!properties.contains(name)) {
						field.setAccessible(true);
						final Setter setter = new FieldSetter(field);
						if (!visitor.visitSetter(name, setter)) {
							return visitor;
						}
						properties.add(name);
					}
				}
			}
			
			currentClass = currentClass.getSuperclass();
		}
		
		return visitor;
	}

	private boolean isSetter(final String name) {
		return name.length() > 3 && name.startsWith("set");
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy