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

com.tsc9526.monalisa.tools.clazz.MelpClass Maven / Gradle / Ivy

There is a newer version: 2.2.0
Show newest version
/*******************************************************************************************
 *	Copyright (c) 2016, zzg.zhou([email protected])
 * 
 *  Monalisa is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU Lesser General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.

 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU Lesser General Public License for more details.

 *	You should have received a copy of the GNU Lesser General Public License
 *	along with this program.  If not, see .
 *******************************************************************************************/
package com.tsc9526.monalisa.tools.clazz;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import com.google.gson.JsonObject;
import com.tsc9526.monalisa.orm.datasource.DbProp;
import com.tsc9526.monalisa.tools.annotation.Alias;
import com.tsc9526.monalisa.tools.converters.TypeConverter;
import com.tsc9526.monalisa.tools.parser.Parser;
import com.tsc9526.monalisa.tools.parser.impl.BeanParser;
import com.tsc9526.monalisa.tools.parser.impl.JsonObjectParser;
import com.tsc9526.monalisa.tools.parser.impl.MapParser;
import com.tsc9526.monalisa.tools.parser.impl.ServletRequestParser;
import com.tsc9526.monalisa.tools.parser.impl.StringParser;
import com.tsc9526.monalisa.tools.string.MelpString;
 
/**
 * 
 * @author zzg.zhou([email protected])
 */
public class MelpClass {
	public static TypeConverter converter=new TypeConverter();	
	 
	private static ConcurrentHashMap hBeanClasses = new ConcurrentHashMap();
	 
	public static long getVersion(String className){
		try{
			return getVersion(Class.forName(className));
		}catch(ClassNotFoundException e){
			return -1;
		}
	} 
	
	public static long getVersion(Class clazz){
		try{
			Field f=null;
			try{
				f=clazz.getDeclaredField(DbProp.CFG_FIELD_VERSION+"$");
			}catch(NoSuchFieldException e){
				f=clazz.getDeclaredField(DbProp.CFG_FIELD_VERSION);
			}
			
			if(f!=null){
				f.setAccessible(true);
				return f.getLong(null);
			} 
		}catch(NoSuchFieldException e){
			 
		}catch( IllegalArgumentException e){
			e.printStackTrace();
		}catch(IllegalAccessException e){
			e.printStackTrace();
		}
		return -1;
	}
	 
	/**
	 * @param m method. 
	 * @return parameter name of the method. JRE class method maybe return [null,null...]
	 */
	public static String[] getMethodParamNames(Method m) {
		return MelpAsm.getMethodParamNames(m);
	}
	
	public static ClassHelper getClassHelper(Class clazz) {
		if(clazz==null){
			return null;
		}
				
		String name = clazz.getName();
		ClassHelper mc = hBeanClasses.get(name);
		if (mc == null) {
			mc = loadMetaClass(clazz);
		}
		return mc;
	}
	 
	public static ClassHelper getClassHelper(Object bean) {
		return getClassHelper(bean.getClass());
	}
	 
	
	public static Collection getFields(Class clazz){
		return getClassHelper(clazz).getFields();	
	}
	
	public static Collection getFields(Object bean){
		if(bean instanceof Specifiable){
			return ((Specifiable)bean).fields();
		}else{
			return getClassHelper(bean).getFields();
		}
	}
	
	public static Class forName(String className)throws ClassNotFoundException{
		try{
			return Class.forName(className);
		}catch(ClassNotFoundException cnf){
			return Class.forName(className,true,Thread.currentThread().getContextClassLoader());
		}
	}
  	
	public static  T findAnnotation(Class clazz, Class annotationClass) {
		T a=null;
				 
		Class c=findClassWithAnnotation(clazz,annotationClass);
		if(c!=null){
			a=c.getAnnotation(annotationClass);
		}
		 			
		return a;
	}
	
	public static Method[] findDeclaredMethods(Class theClass, Class baseClass) {
		Class clazz = theClass;
		Method[] allMethods = null;

		while (!clazz.equals(baseClass)) {
			Method[] thisMethods = clazz.getDeclaredMethods();
			if (allMethods != null && allMethods.length > 0) {
				Method[] subClassMethods = allMethods;
				allMethods = new Method[thisMethods.length + subClassMethods.length];
				System.arraycopy(thisMethods, 0, allMethods, 0, thisMethods.length);
				System.arraycopy(subClassMethods, 0, allMethods, thisMethods.length, subClassMethods.length);
			} else {
				allMethods = thisMethods;
			}

			clazz = clazz.getSuperclass();
		}

		return ((allMethods != null) ? allMethods : new Method[0]);
	}
	
	public static  Class findClassWithAnnotation(Class clazz, Class annotationClass) {
		T a=null;
				 
		while(a==null && clazz!=null){
			a=clazz.getAnnotation(annotationClass); 
			if(a==null){
				Class[] interfaces=clazz.getInterfaces();
				if(interfaces!=null){
					for(Class c:interfaces){
						a=c.getAnnotation(annotationClass);
						if(a!=null){
							return c;
						}
					}
				}					 					
				clazz=clazz.getSuperclass();
			}else {
				return clazz;
			}
		}							
		return null;
	}

	/**
	 * Copy object 
	 * 
	 * @param from source object
	 * @param to dest object
	 * @param  dest type
	 * 
	 * @return The to Object
	 */
	public static  T copy(Object from,T to){
		ClassHelper fm=getClassHelper(from);
		ClassHelper ft=getClassHelper(to);
		
		for(FGS fgs:fm.getFields()){
			FGS x=ft.getField(fgs.getFieldName());
			if(x!=null){
				Object value=fgs.getObject(from);
				
				x.setObject(to, value);
			}
		}
		
		return to;
	}
 	 
	public static  T convert(Object source, Class type) {
		return converter.convert(source, type);
	}
 
	private synchronized static ClassHelper loadMetaClass(Class clazz) {
		String name = clazz.getName();
		if (hBeanClasses.containsKey(name)) {
			return hBeanClasses.get(name);
		} else {
			ClassHelper mc = new ClassHelper(clazz);
			hBeanClasses.put(name, mc);
			return mc;
		}
	}
	
	public static List fetchFields(Class clazz){	
		List fs=new ArrayList();
		fetchFields(fs,clazz);
		return fs;
	}
	
	public static void fetchFields(List fields,Class clazz){			 
		Field[] fs=clazz.getDeclaredFields();
		for(Field f:fs){
			fields.add(f);
		}
		
		Class su=clazz.getSuperclass();
		if(su!=null){
			fetchFields(fields,su);
		}						
	}	
	
	
	private static Map,Parser> parsers=new LinkedHashMap,Parser>();
	   
	static{
		MelpLib.tryLoadGson();
		 
		registerParser(Map.class,new MapParser());
		registerParser(JsonObject.class,new JsonObjectParser());
		registerParser(String.class,new StringParser());
		
		try{
			Class servletRequestClass=Class.forName("javax.servlet.ServletRequest");
			registerParser(servletRequestClass,new ServletRequestParser());
		}catch(ClassNotFoundException e){}
	}
	  
	public static void registerParser(Class clazz, Parser parser){
		parsers.put(clazz, parser);
	}
	
	public static void removeParser(Class clazz){
		parsers.remove(clazz);
	}
	
	/**
	 * @param target the target object
	 * @param data  (ServletRequest|Map|JsonString|...) 
	 * @param mappings
	 *            [Options] Translate dataObject field to model field 
* For example:
* "user_id=id", ... // Parse dataObject.user_id to Model.id
* Another example:
* "~XXX." //Only parse dataObject's fields with prefix: "XXX." * @return true if parse from data to target ok, otherwise false */ @SuppressWarnings({"rawtypes","unchecked"}) public static boolean parse(Object target,Object data,String... mappings) { if(data!=null){ Parser parser=parsers.get(data.getClass()); if(parser==null){ for(Class clazz:parsers.keySet()){ if(clazz.isAssignableFrom(data.getClass())){ parser=parsers.get(clazz); break; } } } if(parser==null){ parser=new BeanParser(); } String[] xms=MelpString.splits(mappings); return parser.parse(target, data,xms); } return false; } /** * Parse multi-objects from ServletRequest * * @param targetTemplate one target object template * @param data ServletRequest data * @param mappings see #parse(Object,Object,String...) * @return list object * @param T the target type * * @see #parse(Object,Object,String...) */ public static List parseArrays(T targetTemplate, javax.servlet.ServletRequest data, String... mappings) { return ServletRequestParser.parseArrays(targetTemplate, data, mappings); } public static class ClassHelper { private Class clazz; private Map hFields = new LinkedHashMap(); private ReadWriteLock lock=new ReentrantReadWriteLock(); public ClassHelper(Class clazz) { this.clazz = clazz; loadClassInfo(); } private void loadClassInfo() { List fields=new ArrayList(); fetchFields(fields,clazz); for(Field f : fields) { int modifiers = f.getModifiers(); if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers)) { FGS fgs = new FGS(clazz,f); if(!hFields.containsKey(fgs.getFieldName())){ hFields.put(fgs.getFieldName(), fgs); } } } } /** * * @param fs Fields will be remove * * @return Removed fields in the class */ public List removeFields(List fs){ try{ lock.writeLock().lock(); List xs=new ArrayList(); for(FGS fgs:fs){ FGS x=hFields.remove(fgs.getFieldName()); if(x!=null){ xs.add(x); } } return xs; }finally{ lock.writeLock().unlock(); } } public List clearFields(){ try{ lock.writeLock().lock(); List xs=new ArrayList(); xs.addAll(hFields.values()); hFields.clear(); return xs; }finally{ lock.writeLock().unlock(); } } public void addFields(List fs){ try{ lock.writeLock().lock(); for(FGS fgs:fs){ hFields.put(fgs.getFieldName(), fgs); } }finally{ lock.writeLock().unlock(); } } public void replaceFields(List fs){ try{ lock.writeLock().lock(); hFields.clear(); for(FGS fgs:fs){ hFields.put(fgs.getFieldName(), fgs); } }finally{ lock.writeLock().unlock(); } } public FGS getField(String name){ try{ lock.readLock().lock(); FGS fgs=hFields.get(name); if(fgs==null){ for(FGS x:hFields.values()){ if(x.getAlias().contains(name)){ fgs=x; break; } } } return fgs; }finally{ lock.readLock().unlock(); } } public Collection getFields(){ try{ lock.readLock().lock(); return hFields.values(); }finally{ lock.readLock().unlock(); } } /** * Remove fields which field annotation with the annotationClass * * @param annotationClass annotationClass * @return Removed fields in the class */ public List removeFieldsWithAnnotation(Class annotationClass){ List fs=getFieldsWithAnnotation(annotationClass); return removeFields(fs); } /** * Get fields which field annotation with the annotationClass * * @param annotationClass annotationClass * * @return fields annotation with the annotationClass */ public List getFieldsWithAnnotation(Class annotationClass){ List fgs=new ArrayList(); for(FGS f:getFields()){ if(f.getAnnotation(annotationClass)!=null){ fgs.add(f); } } return fgs; } } @SuppressWarnings("rawtypes") public static class FGS { protected String fieldName; protected Set alias=new LinkedHashSet(); protected Class type; protected Field field; protected Method getMethod; protected Method setMethod; protected boolean nullNone=false; public FGS(Class type,String fieldName,String ... names){ this.fieldName=fieldName; this.type=type; setAlias(names); } public FGS(Class clazz,Field field){ this.field=field; this.type=field.getType(); fieldName = field.getName(); Alias alias=field.getAnnotation(Alias.class); if(alias!=null){ setAlias(alias.value()); } String m = fieldName.substring(0, 1).toUpperCase(); if (fieldName.length() > 1) { m += fieldName.substring(1); } String get = "get" + m; String set = "set" + m; if (field.getType() == Boolean.class || field.getType() == boolean.class) { get = "is" + m; } getMethod=getMethod(clazz,get); setMethod=getMethod(clazz,set, field.getType()); } protected void setAlias(String[] names){ for(String s:names){ alias.add(s); } } public Field getField(){ return this.field; } private Method getMethod(Class clazz,String name, Class... parameterTypes) { try { return clazz.getMethod(name, parameterTypes); } catch (NoSuchMethodException e) { return null; } } public T getAnnotation(Class annotationClass) { return field.getAnnotation(annotationClass); } public Class getType() { return field.getType(); } public Object getObject(Object bean){ try { if(field==null && bean instanceof Map){ return getMapObject((Map)bean); }else{ if(getMethod!=null){ getMethod.setAccessible(true); return getMethod.invoke(bean); }else{ field.setAccessible(true); return field.get(bean); } } } catch (Exception e) { throw new RuntimeException("Error get method from field: "+getFieldName(),e); } } public void setObject(Object target,Object value){ try { if(field==null && target instanceof Map){ setMapObject((Map)target,value); }else{ Class type=getType(); Object theValue=convert(value, type); if(setMethod!=null){ setMethod.invoke(target, theValue); }else{ field.setAccessible(true); field.set(target, theValue); } } } catch (Exception e) { throw new RuntimeException("Field: "+this.fieldName+", type: "+type.getName()+", value type: "+value.getClass().getName(),e); } } public void mapto(Map keymap,Object target){ String name=findKey(keymap); if(name!=null){ Object value=keymap.get(name); setObject(target, value); } } public String findKey(Map keymap){ String name =getFieldName(); if(keymap.containsKey(name)){ return name; }else{ for(String s:alias){ if(keymap.containsKey(s)){ return s; } } } return null; } protected Object getMapObject(Map m){ return m.get(fieldName); } @SuppressWarnings("unchecked") protected void setMapObject(Map m,Object v){ m.put(fieldName,v); } public boolean isNullNone() { return nullNone; } public void setNullNone(boolean nullNone) { this.nullNone = nullNone; } public String getFieldName() { return fieldName; } public Set getAlias(){ return alias; } public Method getSetMethod(){ return setMethod; } public Method getGetMethod(){ return getMethod; } } public static Set OBJECT_METHODS = new HashSet() { private static final long serialVersionUID = -4949935939426517392L; { add("equals"); add("getClass"); add("hashCode"); add("notify"); add("notifyAll"); add("toString"); add("wait"); } }; }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy