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

org.iworkz.common.helper.ReflectionHelper Maven / Gradle / Ivy

The newest version!
package org.iworkz.common.helper;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Predicate;

import javax.inject.Singleton;

import org.iworkz.common.reflection.PropertyInfo;


@Singleton
public class ReflectionHelper {
	
	protected static final Set> FINAL_IMMUTABLES = new HashSet<>();
	
	static {
		FINAL_IMMUTABLES.add(String.class);
		FINAL_IMMUTABLES.add(Boolean.class);
		FINAL_IMMUTABLES.add(Character.class);
		FINAL_IMMUTABLES.add(Byte.class);
		FINAL_IMMUTABLES.add(Short.class);
		FINAL_IMMUTABLES.add(Integer.class);
		FINAL_IMMUTABLES.add(Long.class);
		FINAL_IMMUTABLES.add(Float.class);
		FINAL_IMMUTABLES.add(Double.class);
		FINAL_IMMUTABLES.add(Locale.class);
		FINAL_IMMUTABLES.add(UUID.class);
		FINAL_IMMUTABLES.add(BigInteger.class);
		FINAL_IMMUTABLES.add(BigDecimal.class);
		FINAL_IMMUTABLES.add(LocalDate.class);
		FINAL_IMMUTABLES.add(LocalDateTime.class);
		FINAL_IMMUTABLES.add(OffsetDateTime.class);
		FINAL_IMMUTABLES.add(ZonedDateTime.class);
	}
	
	public Map getFieldMap(Class objectClass) {
		Map fieldMap = new HashMap<>();
		for (Field field : getAllFields(objectClass)) {
			fieldMap.putIfAbsent(field.getName(), field);
		}
		return fieldMap;
	}

    public Field[] getAllFields(Class objectClass) {
        List fields = new ArrayList();
        addAllFields(fields,objectClass);
        return fields.toArray(new Field[fields.size()]);
    }
    
    protected void addAllFields(List fields, Class objectClass) {
        fields.addAll(Arrays.asList(objectClass.getDeclaredFields()));
        if (objectClass.getSuperclass() != null) {
            addAllFields(fields, objectClass.getSuperclass());
        }
    }
    
    /**
     * Find the first declared method for which the predicate evaluates to true.
     * The search starts in in the object class and continues recursively in super classes.
     * 
     * @param objectClass
     * @param predicate
     * @return
     */
    public Method findFirstDeclaredMethod(Class objectClass, Predicate predicate) {
	    	if (objectClass != null) {
	    		Class currentClass = objectClass;
	    		while (currentClass != null) {
	    			for (Method method : currentClass.getDeclaredMethods()) {
	    				if (predicate.test(method)) {
	    					return method;
	    				}
	    			}
	    			currentClass = currentClass.getSuperclass();
	    		}
	    	}
	    	return null;
    }
    
    public T createObject(Class objectClass) {
        try {
            Constructor defaultConstructor = objectClass.getConstructor();
            T obj = defaultConstructor.newInstance();
            return obj;
        } catch (Exception ex) {
            throw new RuntimeException("Can not create instance for class '"+objectClass.getName()+"'",ex);
        }
    }
    
	public  Class findClassWithPostfix(ClassLoader classLoader, Class type, String packagePostFix, String namePostFix) {
		String className = type.getName();
		
		String packagePart;
		String classPart;
		
		int lastDotIndex = className.lastIndexOf('.');
		if (lastDotIndex >= 0) {
			packagePart = className.substring(0,lastDotIndex);
			classPart = className.substring(lastDotIndex+1);
		} else {
			packagePart = null;
			classPart = className;
		}
		
		String parentClassPart;
		
		int lastDollarIndex = classPart.lastIndexOf('$');
		if (lastDollarIndex >= 0) {
			parentClassPart = classPart.substring(0,lastDollarIndex);
			classPart = classPart.substring(lastDollarIndex+1);
		} else {
			parentClassPart = null;
		}
			
		String customPackage = null;
		if (packagePart != null && packagePart.length() > 0 ) {
			if (packagePostFix != null) {
				customPackage = packagePart+"."+packagePostFix;
			} else {
				customPackage = packagePart;
			}
		} else if (packagePostFix != null) {
			customPackage = packagePostFix;
		}
		
		String customClass = null;
		if (namePostFix != null) {
			customClass = classPart+namePostFix;
		} else {
			customClass = classPart;
		}
		
		if (parentClassPart != null) {
			customClass = parentClassPart + "$" + customClass;
		}
		
		String customClassName = null;
		if (customPackage != null) {
			customClassName = customPackage+"."+customClass;
		} else {
			customClassName=customClass;
		}
		

		try {
			return load(classLoader, customClassName);
		} catch (ClassNotFoundException ex) {
			// ignore (and return null)
		} catch (Exception ex) {
			throw new RuntimeException("Can not find class with postfix '"+customClassName+"'");
		}
		return null;
	}
    
	@SuppressWarnings("unchecked")
	public  Class load(ClassLoader classLoader, String className) throws ClassNotFoundException {
		return (Class) classLoader.loadClass(className);
	}
	
	public List createPropertyInfos(final Class sourceClass) {
		try {
			/* get propertyInfos again but this time synchronized */
				List propertyInfoList = new ArrayList<>();
				BeanInfo beanInfo = Introspector.getBeanInfo(sourceClass);
				PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
				Map fields = getFieldMap(sourceClass);
				
				for (PropertyDescriptor pd : propertyDescriptors) {
					PropertyInfo propertyInfo = createPropertyInfo(pd);
					if (propertyInfo != null) {
						Field field = fields.get(pd.getName());
						if (field != null) {
							propertyInfo.setField(field);
						}
						propertyInfoList.add(propertyInfo);
					}
				}
				return propertyInfoList;
		} catch (Exception ex) {
			throw new RuntimeException("Can not create property info list",ex);
		}
	}
	
	public PropertyInfo createPropertyInfo(PropertyDescriptor pd) {
		Method readMethod = pd.getReadMethod();
		if (readMethod != null) {
			Method writeMethod = pd.getWriteMethod();
			if (writeMethod != null) {
				Class valueClass = pd.getPropertyType();
				return createPropertyInfo(valueClass,readMethod,writeMethod);
			}
		}
		return null;
	}
	
	public PropertyInfo createPropertyInfo(final Class valueClass, Method readMethod, Method writeMethod) {
		PropertyInfo propertyInfo = new PropertyInfo();
		propertyInfo.setReadMethod(readMethod);
		propertyInfo.setWriteMethod(writeMethod);
		if (valueClass.isArray()) {
			propertyInfo.setArray(true);
			propertyInfo.setComponentImmutable(isImmutable(valueClass.getComponentType()));
		} else if (Collection.class.isAssignableFrom(valueClass)) {
			propertyInfo.setCollection(true);
		} else if (Map.class.isAssignableFrom(valueClass)) {
			propertyInfo.setMap(true);
		}  else if (isImmutable(valueClass)) {
			propertyInfo.setImmutable(isImmutable(valueClass));
		}
		return propertyInfo;
	}
	
	public boolean isImmutable(Class valueClass) {
		if (valueClass.isPrimitive()) {
			return false;
		}
		if (valueClass.isEnum()) {
			return false;
		}
		return FINAL_IMMUTABLES.contains(valueClass);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy