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

leap.lang.reflect.ReflectClass 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.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class ReflectClass implements Named {
	
	//protected static final Map, ReflectClass> cache = java.util.Collections.synchronizedMap(new WeakHashMap, ReflectClass>());
    protected static final Map, ReflectClass> cache = new ConcurrentHashMap, ReflectClass>();
    
	public static ReflectClass of(Class clazz) {
		ReflectClass rclass = cache.get(clazz);
		
		if(null == rclass){
			rclass = new ReflectClass(clazz);
			cache.put(clazz, rclass);
		}
		
		return (ReflectClass)rclass;
	}
	
	private final Class        clazz;
	private final ReflectAccessor accessor;
	private final boolean      	  innerClass;

	private ReflectConstructor[]  constructors;
	private ReflectField[]		  fields;
	private ReflectMethod[]		  methods;
	private ReflectField[]		  declaredFields;
	private ReflectMethod[]		  declaredMethods;	
	private ReflectConstructor    defaultConstructor;	
	private boolean			      defaultConstructorInner = false;
	
	protected ReflectClass(Class clazz){
		this.clazz      = clazz;
		this.accessor   = Reflection.factory().createAccessor(this.clazz);
		this.innerClass = Classes.isInnerClass(clazz);
		
		this.initialize();
	}
	
	public String getName() {
	    return clazz.getName();
    }
	
	public boolean hasDefaultConstructor(){
		return null != defaultConstructor;
	}

	@SuppressWarnings("unchecked")
	public  T newInstance() throws ReflectException{
		if(null == defaultConstructor){
			throw new ReflectException(Strings.format("there is no default constructor available in class '{0}'",getName()));	
		}
		
		if(defaultConstructorInner){
			return (T)defaultConstructor.newInstance(Reflection.newInstance(clazz.getEnclosingClass()));
		}else{
			if(null != accessor && accessor.canNewInstance()){
				return (T)accessor.newInstance();	
			}else{
				return (T)defaultConstructor.newInstance((Object[])null);
			}
		}
	}
	
	@SuppressWarnings("unchecked")
	public  T[] newArray(int length){
		return null != accessor ? (T[])accessor.newArray(length) : (T[])Array.newInstance(this.clazz, length);
	}
	
	public int getArrayLength(Object array){
		return null != accessor ? accessor.getArrayLength(array) : Array.getLength(array);
	}
	
	public Object getArrayItem(Object array,int index){
		return null != accessor ? accessor.getArrayItem(array, index) : Array.get(array, index);
	}
	
	public void setArrayItem(Object array,int index,Object value){
		if(null != accessor) {
			accessor.setArrayItem(array, index, value);	
		}else{
			Array.set(array, index, value);
		}
	}
	
	public boolean isMap(){
		return Map.class.isAssignableFrom(clazz);
	}
	
	public boolean isArray() {
		return clazz.isArray();
	}
	
	public boolean isAbstract() {
		return Modifier.isAbstract(clazz.getModifiers());
	}
	
	public boolean isInterface() {
		return clazz.isInterface();
	}
	
	public boolean isEnum(){
		return clazz.isEnum();
	}
	
	public boolean isConcrete(){
		return !clazz.isInterface() && !isAbstract();
	}
	
	public boolean isInnerClass(){
		return innerClass;
	}
	
	public Class getReflectedClass() {
    	return clazz;
    }
	
	public Annotation[] getAnnotations(){
		return clazz.getAnnotations();
	}
	
	public ReflectConstructor[] getConstructors(){
		return constructors;
	}
	
	public ReflectConstructor getDefaultConstructor(){
		return defaultConstructor;
	}
	
	public ReflectConstructor getConstructor(Class... parameterTypes) {
		if(null == parameterTypes || parameterTypes.length == 0){
			return defaultConstructor;
		}
		
		for(ReflectConstructor c : constructors) {
			Constructor jc = c.getReflectedConstructor();

			if(jc.getParameterTypes().length == parameterTypes.length){
				
				boolean match = true;
				
				for(int i=0;i() {
			public boolean test(ReflectField object) {
	            return object.getName().equals(name);
            }
		});
	}
	
	public ReflectField getField(final String name,final Class fieldType){
		return Arrays2.firstOrNull(fields,Predicates.nameEquals(name));
	}
	
	public ReflectField getFieldIgnorecase(final String name){
		return Arrays2.firstOrNull(fields,Predicates.nameEqualsIgnoreCase(name));
	}
	
	public ReflectMethod[] getMethods(){
		return methods;
	}
	
	public ReflectMethod[] getDeclaredMethods(){
		return declaredMethods;
	}
	
	public ReflectMethod getMethod(final String name){
		return Arrays2.firstOrNull(methods, Predicates.nameEquals(name));
	}
	
	public ReflectMethod getMethod(final Method m){
		for(ReflectMethod rm : methods){
			if(rm.getReflectedMethod().equals(m)){
				return rm;
			}
		}
		return null;
	}
	
	public ReflectMethod getMethod(final String name,final Class... argumentTypes){
		for(ReflectMethod rm : methods){
			if(rm.getName().equals(name)){
				Method m = rm.getReflectedMethod();
				
				//Avoids NullPointerException
				if(null == argumentTypes || argumentTypes.length == 0){
					if(m.getParameterTypes().length == 0){
						return rm;
					}
					break;
				}
            	
            	if(m.getParameterTypes().length == argumentTypes.length){
                    boolean matched = true;
                    
                    for(int i=0;i returnType,Class... argumentTypes){
		ReflectMethod m = getMethod(name, argumentTypes);
		
		return null == m ? null : (m.getReflectedMethod().getReturnType().equals(returnType) ? m : null);
	}	
	
	public ReflectMethod[] getMethods(final String name) {
		return Arrays2.filter(methods, new Predicate() {
			public boolean test(ReflectMethod object) {
	            return object.getName().equals(name);
            }
		}).toArray(new ReflectMethod[]{});
	}
	
	ReflectAccessor getAccessor(){
		return accessor;
	}
	
	private void initialize(){
		//constructors
		this.createConstructors();
		
		//methods
		this.createMethods();	 //must create methods firstly , will be used in createFields()
		
		//fields
		this.createFields();
	}

	private void createConstructors(){
		//new an empty ArrayList.
		List constructorList = new ArrayList();
		
		//iterate all declared constructors.
		Constructor[] constructors = clazz.getDeclaredConstructors();
		for(int i=0;i c = constructors[i];
			if(!c.isSynthetic()){
				ReflectConstructor rc = new ReflectConstructor(this,c);
				
				constructorList.add(rc);
				
				if(innerClass && !Modifier.isStatic(clazz.getModifiers())){
					if(c.getParameterTypes().length == 1 
							&& c.getParameterTypes()[0].equals(clazz.getEnclosingClass())){
						defaultConstructor      = rc;
						defaultConstructorInner = true;
					}
					
				}else if(c.getParameterTypes().length == 0){
					defaultConstructor = rc;
				}
			}
		}
		
		this.constructors = constructorList.toArray(new ReflectConstructor[constructorList.size()]);
	}
	
	private void createFields(){
		List fieldList = new ArrayList();
		
		for(Field f : Reflection.getFields(clazz)){
			fieldList.add(new ReflectField(this,f));
		}
		
		this.fields = fieldList.toArray(new ReflectField[fieldList.size()]);
		this.declaredFields = getDeclaredMembers(fieldList).toArray(new ReflectField[]{});
	}
	
	private void createMethods(){
		List methodList = new ArrayList();
		
		for(Method m : Reflection.getMethods(clazz)){
			if(Object.class.equals(m.getDeclaringClass())){
				continue;
			}
			
			methodList.add(new ReflectMethod(this,m));
		}
		
		this.methods = methodList.toArray(new ReflectMethod[methodList.size()]);
		this.declaredMethods = getDeclaredMembers(methodList).toArray(new ReflectMethod[]{});
	}
	
	@Override
    public String toString() {
		return clazz.toString();
    }
	
	private static  List getDeclaredMembers(List members){
		return members.stream().filter((m) -> {return m.isDeclared();}).collect(Collectors.toList());
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy