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

com.gitee.l0km.codegen.base.NewSourceInfoAbstract Maven / Gradle / Ivy

There is a newer version: 3.5.0
Show newest version
package com.gitee.l0km.codegen.base;

import static com.gitee.l0km.com4j.basex.bean.jdk.BeanPropertySupportImpl.BEAN_SUPPORT;

import java.beans.PropertyDescriptor;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitee.l0km.codegen.base.Method.Parameter;
import com.gitee.l0km.com4j.base.Assert;
import com.gitee.l0km.com4j.base.BaseParameterNames;
import com.gitee.l0km.com4j.base.Judge;
import com.gitee.l0km.com4j.base.ParameterNames;
import com.gitee.l0km.com4j.basex.AnnotationProxy;
import com.gitee.l0km.com4j.basex.ReflectionUtils;
import com.gitee.l0km.com4j.basex.reflection.generics.EnhancedTypeResolver;
import com.gitee.l0km.javadocreader.JavadocParameterNames;
import com.gitee.l0km.javadocreader.JavadocReader;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

/**
 * {@link NewSourceInfo}抽象实现
 * @author guyadong
 *
 * @param 
 */
public abstract class NewSourceInfoAbstract extends AbstractSchema implements NewSourceInfo {
	private static final Logger logger = LoggerFactory.getLogger(NewSourceInfoAbstract.class);

	protected final Class interfaceClass;
	protected final Class refClass;
	protected final List methodsNeedGenerated = new ArrayList();
	protected final BaseParameterNames paramTable;

	protected final Map properties;
	/**
	 * 当前生成的类型的泛型变量与实际类型参数的映射,非泛型类为空
	 */
	protected final EnhancedTypeResolver typeResolver;

	private final AnnotationHelper annotationHelper = new AnnotationHelper();
	abstract protected void createMethodsNeedGenerated();
	
	protected AnnotationHelper getAnnHelper() {
		return annotationHelper;
	}

	@Override
	protected void addImportedClassFromMethod(Method method, boolean importExceptions, boolean importReturn, boolean importAnnotation) {
		addImportedClass(typeResolver.resolveTypes(method.getGenericParameterTypes()));
		if(importExceptions) {
			addImportedClass(typeResolver.resolveTypes(method.getGenericExceptionTypes()));
		}
		if(importReturn) {
			addImportedClass(typeResolver.resolveType(method.getGenericReturnType()));
		}
	}

	/**
	 * @param interfaceClass
	 * @param refClass
	 *            参考类
	 * @param baseClass
	 *            父类
	 */
	public NewSourceInfoAbstract(Class interfaceClass, Class refClass, Class baseClass) {
		checkClass(interfaceClass,refClass,baseClass);
		this.interfaceClass = interfaceClass;
		this.baseClass = baseClass;
		this.refClass = refClass;

		initImportList();
		try {
			if(refClass != null){
				paramTable = makeBaseParameterNames(refClass);
				typeResolver = new EnhancedTypeResolver(ReflectionUtils.getNormalizedTypeVariables(refClass, true));
			}else if(interfaceClass != null){
				paramTable = makeBaseParameterNames(interfaceClass);
				typeResolver = new EnhancedTypeResolver(Collections.emptyMap());
			}else if(baseClass != null && baseClass.isEnum()){
				// enum support 不需要paramTable
				paramTable = null;
				typeResolver = new EnhancedTypeResolver(Collections.emptyMap());
			}else if(baseClass != null){
				paramTable = makeBaseParameterNames(baseClass);
				typeResolver = new EnhancedTypeResolver(ReflectionUtils.getNormalizedTypeVariables(baseClass, true));
			}else{
				throw new IllegalStateException("cann't construct paramTable instance caused by interfaceClass and refClass both are null");
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		properties = readProperties();
	}
	
	@Override
	protected void initImportList() {
		if (null != baseClass){
			addImportedClass(baseClass);
			addImportedClass(baseClass.getTypeParameters());
		}
		else if(interfaceClass != null){
			addImportedClass(interfaceClass);
			addImportedClass(interfaceClass.getTypeParameters());
		}
	}
	private static BaseParameterNames makeBaseParameterNames(Class clazz) {
		return (clazz.isInterface() || !Modifier.isAbstract(clazz.getModifiers())) && JavadocReader.existSourceOf(clazz) 
				? new JavadocParameterNames(clazz) : new ParameterNames(clazz);
	}
	/**
	 * 检查构造方法传入的参数,子类可以重写此方法
	 * @param interfaceClass
	 * @param refClass
	 * @param baseClass
	 */
	protected void checkClass(Class interfaceClass, Class refClass, Class baseClass){
		Assert.notNull(interfaceClass, "interfaceClass");
		Assert.notNull(refClass, "refClass");
		if (!interfaceClass.isInterface()){
			throw new IllegalArgumentException("interfaceClass must be Interface(必须是接口)");
		}
		if (!interfaceClass.isAssignableFrom(refClass) 
				|| refClass.isInterface()
				|| Modifier.isAbstract(refClass.getModifiers())){
			throw new IllegalArgumentException(String.format(
					"refClass must  implement [%s] and not be abstract class(必须实现接口,且不能是抽象类)", 
					interfaceClass.getName()));
		}
		if (null != baseClass && (!interfaceClass.isAssignableFrom(baseClass) || baseClass.isInterface())) {
			throw new IllegalArgumentException(String.format("baseClass must  implement [%s](必须实现接口)",
					interfaceClass.getName()));
		}
	}

	protected final void addImportedClassFromMethods() {
		Iterator it = methodsNeedGenerated.iterator();
		while (it.hasNext()) {
			Method im = it.next();
			addImportedClassFromMethod(im, true, true, true);
		}
	}

	@Override
	public Class getInterfaceClass() {
		return interfaceClass;
	}

	@Override
	public List getMethodsNeedGenerated() {
		if (methodsNeedGenerated.isEmpty()){
			createMethodsNeedGenerated();
		}
		return methodsNeedGenerated;
	}

	protected final static boolean isImplementedMethod(java.lang.reflect.Method im, java.lang.reflect.Method m) {
		if (!Judge.hasNull(im, m)) {
			if ((im.getDeclaringClass().isAssignableFrom(m.getDeclaringClass()) && im.getName().equals(m.getName()))) {
				if (!im.getReturnType().equals(m.getReturnType()))
					return false;
				Class[] params1 = im.getParameterTypes();
				Class[] params2 = m.getParameterTypes();
				if (params1.length == params2.length) {
					for (int i = 0; i < params1.length; i++) {
						if (params1[i] != params2[i])
							return false;
					}
					return true;
				}
			}
		}
		return false;
	}

	protected final static boolean isImplemented(java.lang.reflect.Method[] methods, java.lang.reflect.Method im) {
		return getImplementedMethod(methods,im)!=null;
	}
	
	protected final static boolean isImplemented(Class claz, java.lang.reflect.Method im) {
		return getImplementedMethod(claz.getDeclaredMethods(),im)!=null;
	}
	
	protected final static java.lang.reflect.Method getImplementedMethod(java.lang.reflect.Method[] methods, java.lang.reflect.Method im) {
		for (java.lang.reflect.Method m : methods) {
			if (isImplementedMethod(im, m) && !Modifier.isAbstract(m.getModifiers())) {
				logger.debug("IMPLEMENTED METHOD:{}", im);
				return m;
			}
		}
		return null;
	}

	/**
	 * @return refClass
	 */
	@Override
	public Class getRefClass() {
		return refClass;
	}
	
	@Override
	public boolean compile() {
		boolean compileOk = false;
		try {
			createMethodsNeedGenerated();
			addImportedClassFromMethods();
			compileOk = true;
		} finally {

		}
		return compileOk;
	}

	private static final Method getMethod(java.lang.reflect.Method[] methods, String signature) {
		Assert.notEmpty(signature, "signature");
		for (java.lang.reflect.Method m : methods) {
			if (Method.getSignature(m).equals(signature)){
				ParameterNames pt = new ParameterNames(m.getDeclaringClass());
				try {
					return new Method(m,pt.getParameterNames(m.getName(), m.getParameterTypes()));
				} catch (NoSuchMethodException e) {
					throw new RuntimeException(e);
				}
			}
		}
		return null;
	}
	public final Method getMethod(Class clazz, String signature) {
		Assert.notNull(clazz, "methods");
		return getMethod(clazz.getMethods(),signature);		
	}
	public final Method getDeclaredMethods(Class clazz, String signature) {
		Assert.notNull(clazz, "methods");
		return getMethod(clazz.getDeclaredMethods(),signature);		
	}
	public final Method getMatchedGenericMethod(Class clazz, Method method, Class expectedType,
			String[] genericParamNames, Class targetType) throws MethodException {
		return getMatchedGenericMethod(clazz, method, expectedType, genericParamNames, targetType,null);
	}
	public final Method getMatchedGenericMethod(Class clazz, Method method, Class expectedType,
			String[] genericParamNames, Class targetType,String name) throws MethodException {
		Assert.notNull(clazz, "clzzz");
		Assert.notNull(method, "method");
		Assert.notNull(genericParamNames, "genericParamNames");
		Assert.notNull(targetType, "targetType");
		Assert.notNull(expectedType, "expectedType");
		if(Judge.hasEmpty(genericParamNames))
			throw new MethodException("the genericParamNames's element must not be empty");
		Parameter[] params = method.getParameters();
		Class[] parameterTypes = new Class[params.length];
		for(int i=0;i nameSet;
		if (null == (nameSet = CodeGenUtils.toSetIfnotDup(genericParamNames)))
			throw new MethodException("genericParamNames has duplicated elements");
		//代入期望类型
		for (int i = 0; i < parameterTypes.length; i++) {
			if (nameSet.contains(params[i].name)) {
				if (params[i].type != targetType)
					throw new MethodException(String.format(
							"the %s's type that from genericParamNames is not targetType %s", params[i].name,
							targetType.getName()));
				parameterTypes[i]=expectedType;
			}
		}
		try {
			return new Method(getGenericMethod(clazz, name==null||name.isEmpty()?method.getName():name, parameterTypes), method.getParameterNames());
		} catch (NoSuchMethodException e) {
			throw new MethodException(String.format("not found matched generic method for %s",
					method.getDocSignature()));
		}
	}

	protected Map readProperties() {
		return interfaceClass != null ? BEAN_SUPPORT.getProperties(this.interfaceClass, 0, true) : Collections.emptyMap();
	}

	/**
	 * @param excludePropertyMethod 是否排除属性的getter/setter方法,为{@code false}时效果同{@link #getMethodsNeedGenerated()}
	 * @return 需要生成的方法列表
	 * @see #getMethodsNeedGenerated()
	 */
	public List getMethodsNeedGenerated(final boolean excludePropertyMethod) {
		Predicate p = new Predicate() {
			@Override
			public boolean apply(Method input) {
				return excludePropertyMethod ? null == propertyDescriptorOf(input) : true;
			}
		};
		Iterable filtered = Iterables.filter(getMethodsNeedGenerated(),	p);
		return Lists.newArrayList(filtered);
	}

	/**
	 * 返回所有getter/setter方法定义的属性
	 * @return 属性名--PropertyDescriptor 映射,没有返回空
	 */
	public Map getProperties() {
		return properties;
	}

	public PropertyDescriptor propertyDescriptorOf(Method method) {
		if(null != method){
			for(PropertyDescriptor descriptor:properties.values()){
				if(method.delegate().equals(descriptor.getReadMethod())){
					return descriptor;
				}
				if(method.delegate().equals(descriptor.getWriteMethod())){
					return descriptor;
				}
			}
		}
		return null;
	}

	public boolean isReadable(PropertyDescriptor propertyDescriptor) {
		return propertyDescriptor != null && propertyDescriptor.getReadMethod() != null;
	}

	public boolean isWritable(PropertyDescriptor propertyDescriptor) {
		return propertyDescriptor != null && propertyDescriptor.getWriteMethod() != null;
	}

	public boolean isIs(java.lang.reflect.Method getter) {
	    return (getter != null &&
	            getter.getName().startsWith("is") &&
	            (getter.getReturnType().equals(Boolean.TYPE) ||
	             getter.getReturnType().equals(Boolean.class)));
	}
	/**
	 * 返回参数实际的类型
* @param parameter * @since 2.2.8 * @see EnhancedTypeResolver#resolveType(Type) */ public Type actualTypeOf(Parameter parameter) { return typeResolver.resolveType(parameter.getGenericType()); } /** * * @since 2.2.9 */ public EnhancedTypeResolver getTypeResolver() { return typeResolver; } /** * @since 2.3.0 */ public List> annotationOf(Method method) { return getAnnHelper().annotationOf(method, "SUPERCLASS"); } /** * @since 2.3.0 */ public List> annotationOf(Parameter parameter) { return getAnnHelper().annotationOf(parameter); } /** * @since 2.3.0 */ public String annoationCodeOf(Parameter parameter, String delim) { return getAnnHelper().annoationCodeOf(parameter, delim, fullNameInstanceByImportList); } /** * @since 2.3.0 */ public String annoationCodeOf(Method method, String delim) { return getAnnHelper().annoationCodeOf(method,delim, "SUPERCLASS", fullNameInstanceByImportList); } /** * @since 2.3.0 */ public List> annotationOf(AnnotatedElement element) { return getAnnHelper().annotationOf(element, "SUPERCLASS"); } /** * @since 2.3.0 */ public String annoationCodeOf(AnnotatedElement element, String delim) { return getAnnHelper().annoationCodeOf(element,delim, "SUPERCLASS", fullNameInstanceByImportList); } /** * @since 2.3.0 */ public boolean withAnnotation(Method method,String annotationType) { return getAnnHelper().withAnnotation(method, annotationType, "SUPERCLASS"); } /** * @since 2.3.0 */ public boolean withAnnotation(AnnotatedElement element,String annotationType) { return getAnnHelper().withAnnotation(element, annotationType, "SUPERCLASS"); } private static final Map, Class> PRIMITIVE_TYPE_MAP = new HashMap, Class>() { private static final long serialVersionUID = 2638066380035384674L; { put(int.class, Integer.class); put(boolean.class, Boolean.class); put(byte.class, Byte.class); put(short.class, Short.class); put(char.class, Character.class); put(long.class, Long.class); put(float.class, Float.class); put(double.class, Double.class); } }; /** * 查找指定的方法 * @param clazz 要搜索的类 * @param name 方法名 * @param parameterTypes 希望匹配的参数类型数组 * @throws NoSuchMethodException */ public static final java.lang.reflect.Method getGenericMethod(Classclazz,String name,Class... parameterTypes) throws NoSuchMethodException{ List methods=new ArrayList(); //查找同名且参数数目相同的所有方法 for (java.lang.reflect.Method m : clazz.getMethods()) if (m.getName().equals(name) && m.getParameterTypes().length == parameterTypes.length) methods.add(m); if (!methods.isEmpty()) { //过滤掉所有不能匹配的方法 for (int i = 0; i < parameterTypes.length; i++) { for (Iterator it = methods.iterator(); it.hasNext();) { if (!isConvert(it.next().getParameterTypes()[i], parameterTypes[i])) it.remove(); } if (methods.size() <= 1) break; } if (methods.size() > 1) { //如果还有多个方法满足条件,再过滤掉不能直接赋值的方法 for (int i = 0; i < parameterTypes.length; i++) { for (Iterator it = methods.iterator(); it.hasNext();) { if (!isAssignable(it.next().getParameterTypes()[i], parameterTypes[i])) it.remove(); } if (methods.size() <= 1) break; } } if (methods.size() == 1) return methods.iterator().next(); else if (methods.size() > 1){ //如果还有多个方法满足条件,再过滤掉类型不相等的方法 for (int i = 0; i < parameterTypes.length; i++) { for (Iterator it = methods.iterator(); it.hasNext();) { if (it.next().getParameterTypes()[i]!= parameterTypes[i]) it.remove(); } if (methods.size() <= 1) break; } if (methods.size() == 1) return methods.iterator().next(); else if (methods.size() > 1) throw new IllegalStateException("found more matched method"); } } throw new NoSuchMethodException(); } /** * from对象能否则直接赋值给to * @param to * @param from */ public static final boolean isAssignable(Class to,Classfrom){ if (from.isPrimitive()) { if (to != from && !to.isAssignableFrom(PRIMITIVE_TYPE_MAP.get(from))) return false; } else if (!to.isAssignableFrom(from)) return false; return true; } /** * from对象是否能转换成to * @param to * @param from */ public static final boolean isConvert(Class to, Class from) { if (!isAssignable(to, from)){ if (to.isPrimitive() && PRIMITIVE_TYPE_MAP.get(to) == from) { return true; } return false; } return true; } /** * 判断 {@code refClass}是否实现了{@code interfaceClass}的所有方法 * @param interfaceClass * @param refClass */ public static boolean isFullImplemented(ClassinterfaceClass,Class refClass){ if(null == interfaceClass || null == refClass){ return false; } if(!interfaceClass.isInterface()){ throw new IllegalArgumentException(String.format("the interface [%s] is not a interface", interfaceClass.getName())); } if(refClass.isInterface() || !interfaceClass.isAssignableFrom(refClass)){ throw new IllegalArgumentException(String.format("refClass must implement [%s]", refClass.getName())); } java.lang.reflect.Method[] interfaceMethods = interfaceClass.getMethods(); java.lang.reflect.Method[] refMethods = refClass.getMethods(); for(java.lang.reflect.Method im:interfaceMethods){ if(!isImplemented(refMethods,im)){ return false; } } return true; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy