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

com.gitee.l0km.casban.ctor.AnnotConstructors Maven / Gradle / Ivy

There is a newer version: 1.4.1
Show newest version
package com.gitee.l0km.casban.ctor;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.gitee.l0km.casban.CasbanScanners;
import com.gitee.l0km.casban.CommonFunctions;
import com.gitee.l0km.casban.CommonPredicates;
import com.gitee.l0km.casban.ctor.annotations.ConstructType;
import com.gitee.l0km.casban.ctor.annotations.CtorArg;
import com.gitee.l0km.casban.ctor.annotations.Setter;
import com.gitee.l0km.casban.exception.PackageScanException;
import com.gitee.l0km.com4j.base.NameStringUtils;
import com.gitee.l0km.com4j.basex.reflection.MethodUtils;
import com.gitee.l0km.common.spring.core.annotation.AnnotationUtils;
import com.gitee.l0km.common.spring.core.annotation.MergedAnnotation;
import com.gitee.l0km.common.spring.core.annotation.TypeMappedAnnotations;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.gitee.l0km.aocache.Singleton.weakSingletonOf;
import static com.gitee.l0km.aocache.Singleton.newInstance;
/**
 * @author guyadong
 * @since 1.1.0
 */
public class AnnotConstructors {
	
	private AnnotConstructors() {
	}

	private static class CtorFieldHelper implements Predicate,Comparator{
		private final Map attrs;
		public CtorFieldHelper(final MergedAnnotation mergedAnnotation, boolean ignoreDefault) {
			attrs = mergedAnnotation.filterAttributes(!ignoreDefault ? Predicates.alwaysTrue(): new Predicate() {

				@Override
				public boolean apply(String input) {
					return mergedAnnotation.hasNonDefaultValue(input);
				}
			}).asMap();
		}
		@Override
		public int compare(Method o1, Method o2) {
			ConstructType c1 = AnnotationUtils.getAnnotation(o1, ConstructType.class);
			ConstructType c2 = AnnotationUtils.getAnnotation(o1, ConstructType.class);
			return Integer.compare(c1.value(), c2.value());
		}
		@Override
		public boolean apply(Method input) {
			return attrs.containsKey(input.getName());
		}
	}
	/** 
	 * 查找 {@link ConstructType} 标记的字段定义的要构建的类 
	 * @param mergedAnnotation
	 * @param ignoreDefault 为{@code true}忽略为默认值的字段
	 */
	public static Class getConstructType(MergedAnnotation mergedAnnotation, boolean ignoreDefault) {
		checkArgument(mergedAnnotation != null && mergedAnnotation.isPresent(),"mergedAnnotation is null or no present");
			LinkedHashSet methods = CasbanScanners.findMembersOfClass(
					mergedAnnotation.getType(),
					CommonFunctions.asMethodOrnull(),
					CommonPredicates.hasAnnotationMemberFilter(ConstructType.class));
			CtorFieldHelper helper = new CtorFieldHelper(mergedAnnotation,ignoreDefault);
			ImmutableList ctorMembers = FluentIterable.from(methods).filter(helper).toSortedList(helper);
			for(Method method:ctorMembers) {
				Object value = mergedAnnotation.getValue(method.getName()).get();
				Class clazz = null;
				if(value instanceof String) {
					if(!((String)value).isEmpty()) {
						try {
							clazz = Class.forName((String)value);
						} catch (ClassNotFoundException e) {
							throw new IllegalArgumentException(e);
						}
					}
				}else if (value instanceof Class) {
					clazz = (Class)value;
				}else {
					throw new IllegalArgumentException(String.format("Class Or String  required for @%s.%s() from %s",
						mergedAnnotation.getType().getName(),
						method.getName(),
						mergedAnnotation.getSource()));
				}
				if(null != clazz && !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) {
					Class expect= method.getAnnotation(ConstructType.class).expect();
					checkArgument(expect.isAssignableFrom(clazz),"%s not subtype of %s  for @%s.%s() from %s",
							clazz.getName(),
							expect.getName(),
							mergedAnnotation.getType().getName(),
							method.getName(),
							mergedAnnotation.getSource());
					return clazz;
				}
			}
			throw new IllegalArgumentException(String.format(
					"NOT FOUND MATCHED valid field to fetch Class with @%s in [%s] of %s from %s",
					ConstructType.class.getSimpleName(),
					Joiner.on(',').join(FluentIterable.from(methods).transform(CommonFunctions.getNameFun())),
					mergedAnnotation.synthesize(),mergedAnnotation.getSource()));
	}
	/** 
	 * 查找 {@link ConstructType} 标记的字段定义的要构建的类 
	 * @param annot
	 * @see #getConstructType(MergedAnnotation, boolean)
	 */
	public static Class getConstructType(Annotation annot) {
		return getConstructType(TypeMappedAnnotations.from(checkNotNull(annot,"annot is null")), true);
	}

	/**
	 * 从注解中查找 {@link CtorArg}标记的构造方法参数
* @param mergedAnnotation * @return 以构造方法参数定义顺序返回参数名(注解字段名)-参数值的映射,输入参数为{@code null}返回空Map * @since 1.2.9 */ public static LinkedHashMap getConstructorArgsAsLinkedHashMap( MergedAnnotation mergedAnnotation) { LinkedHashMap args = new LinkedHashMap<>(); if (null != mergedAnnotation) { int index = 0; try { for (;; ++index) { Method method = CasbanScanners.findAccessibleObject(mergedAnnotation.getType(), false, CommonFunctions.asMethodOrnull(), CommonPredicates.containedEntryMemberFilter(CtorArg.class, "value", index)); if (null == method) { break; } args.put(method.getName(), mergedAnnotation.getValue(method.getName()).get()); } } catch (PackageScanException e) { throw new PackageScanException(String.format("FOUND MULTI field with @%s(%s) in %s \ncaused by %s", CtorArg.class.getSimpleName(), index, mergedAnnotation, e.getMessage()), e); } } return args; } /** * 从注解中查找 {@link CtorArg}标记的构造方法参数 * @param mergedAnnotation * @return 构造方法参数数组,输入参数为{@code null}返回空数组 * @see #getConstructorArgsAsLinkedHashMap(MergedAnnotation) */ public static Object[] getConstructorArgs(MergedAnnotation mergedAnnotation){ return getConstructorArgsAsLinkedHashMap(mergedAnnotation).values().toArray(new Object[0]); } /** * @see #getConstructorArgs(MergedAnnotation) */ public static Object[] getConstructorArgs(Annotation annot){ return getConstructorArgs(null == annot ? null : TypeMappedAnnotations.from(annot)); } /** * 从注解中查找 {@link Setter}标记的赋值参数定义 * @param mergedAnnotation * @return 赋值参数数组,输入参数为{@code null}返回空数组 */ public static List> settersOf(MergedAnnotation mergedAnnotation){ if(null != mergedAnnotation) { LinkedHashSet args = CasbanScanners.findMembersOfClass(mergedAnnotation.getType(), CommonFunctions.asMethodOrnull(), CommonPredicates.hasAnnotationMemberFilter(Setter.class)); return FluentIterable.from(args).transform(CommonFunctions.getMeragedAnnotationFun(Setter.class)) .filter(new Predicate>() { @Override public boolean apply(MergedAnnotation input) { return input.hasNonDefaultValue("value"); }}) .toList(); } return Collections.emptyList(); } /** * 对象赋值,将{@code sourceAnnotation}中由{@code setter}标记的字段值以反射方式赋值到{@code instance}的指定字段 * @param instance * @param sourceAnnotation * @param setter * @throws ReflectiveOperationException */ public static void assign(Object instance,Annotation sourceAnnotation, MergedAnnotationsetter) throws ReflectiveOperationException{ if(null != instance && null != setter) { Object source = setter.getSource(); Setter annot = setter.synthesize(); checkArgument(source instanceof Method,"Method required for source of %s",annot); Method method = (Method)source; checkArgument(Annotation.class.isAssignableFrom(method.getDeclaringClass()),"Annotation method required for source of %s",annot); String name; if(annot.name().isEmpty()) { name = "set"+NameStringUtils.firstUpperCase(method.getName()); }else { name = annot.name(); } Object value = method.invoke(sourceAnnotation); MethodUtils.invokeMethod(instance, name, new Object[] {value}); } } /** * 对象赋值,将{@code sourceAnnotation}中由{@code setters}标记的字段值以反射方式赋值到{@code instance}的指定字段 * @param instance * @param sourceAnnotation * @param setters * @throws ReflectiveOperationException */ public static void assign(Object instance,Annotation sourceAnnotation, Iterable>setters) throws ReflectiveOperationException{ if(null != instance && null != sourceAnnotation && null !=setters) { for(MergedAnnotation setter:setters) { assign(instance,sourceAnnotation, setter); } } } /** * 根据注解中{@link ConstructType}标记字段定义的的类型创建实例
* 如果注解为元注解,则尝试从元注解所在的注解中查找{@link CtorArg}标记的字段作为构造方法参数。 * * @param mergedAnnotation * @param ctorArgStrategy 参见 {@link CtorArgStrategy} * @param modfier 用于对从{@code mergedAnnotation}生成的{@link CtorArgInfo}进行修改,为{@code null}忽略 * @return 返回构建的对象 * @throws ReflectiveOperationException * @since 1.2.9 */ @SuppressWarnings("unchecked") public static T construct(MergedAnnotation mergedAnnotation, Function, CtorArgInfo> ctorArgStrategy, Function modfier) throws ReflectiveOperationException { Class clazz = getConstructType(mergedAnnotation, true); CtorArgInfo argInfo = checkNotNull(ctorArgStrategy, "ctorArgStrategy is null").apply(mergedAnnotation); if (null != modfier) { argInfo = modfier.apply(argInfo); } /** 注解中获取构造方法参数列表 */ Object[] args = argInfo.args(); List> setters = settersOf(argInfo.source); if (setters.isEmpty()) { return (T) weakSingletonOf(clazz, args); } Object instance = newInstance(clazz, args); assign(instance, argInfo.source.synthesize(), setters); return (T) instance; } /** * 根据注解中{@link ConstructType}标记字段定义的的类型创建实例
* 如果注解为元注解,则尝试从元注解所在的注解中查找{@link CtorArg}标记的字段作为构造方法参数。 * @param mergedAnnotation * @param ctorArgStrategy 参见 {@link CtorArgStrategy} * @return 返回构建的对象 * @throws ReflectiveOperationException * @see #construct(MergedAnnotation, Function, Function) */ public static T construct(MergedAnnotation mergedAnnotation, Function, CtorArgInfo> ctorArgStrategy)throws ReflectiveOperationException { return construct(mergedAnnotation,ctorArgStrategy,null); } /** * 根据注解中{@link ConstructType}标记字段定义的的类型创建实例
* 构造方法参数从当前注解查找,参见 {@link CtorArgStrategy#SELF_ONLY} * @param mergedAnnotation * @return 返回构建的对象 * @throws ReflectiveOperationException */ public static T construct(MergedAnnotation mergedAnnotation)throws ReflectiveOperationException { return construct(mergedAnnotation,CtorArgStrategy.SELF_ONLY); } /** * 从{@link MergedAnnotation}获取{@link CtorArg}标记的构造方法参数的策略,
* 返回对象列表永不为空,,第一个元素为参数所在注解,之后的其他元素是构造方法参数 * @see AnnotConstructors#getConstructorArgs(MergedAnnotation) * @author guyadong */ public static enum CtorArgStrategy implements Function, CtorArgInfo>{ /** * 只从当前注解查找 */ SELF_ONLY, /** * 自上而下返回查找所有注解,直到找到或达到root */ UNTIL_ROOT { @Override public CtorArgInfo apply(MergedAnnotation input) { CtorArgInfo argInfo; while((argInfo =getCtorArgInfoOf(input)).size()==0 && null != input && input.isMetaPresent()) { input = input.getMetaSource(); } return argInfo; } }, /** * 从第一个非元注解的源注解对象查找 */ NOMETA { @Override public CtorArgInfo apply(MergedAnnotation input) { while(null != input && input.isMetaPresent()) { input = input.getMetaSource(); } return getCtorArgInfoOf(input); } }, /** * 先查找当前注解如果找不到则从第一个非元注解的源注解对象查找 */ SELF_OR_NOMETA{ @Override public CtorArgInfo apply(MergedAnnotation input) { CtorArgInfo argInfo; if((argInfo =SELF_ONLY.apply(input)).size()==0) { argInfo = NOMETA.apply(input); } return argInfo; } }, /*** * 从根注解查找 */ ROOT { @Override public CtorArgInfo apply(MergedAnnotation input) { return getCtorArgInfoOf(null != input ? input.getRoot() : input); } }; @Override public CtorArgInfo apply(MergedAnnotation input) { return getCtorArgInfoOf(input); } private static CtorArgInfo getCtorArgInfoOf(MergedAnnotation mergedAnnotation){ return new CtorArgInfo(mergedAnnotation,getConstructorArgsAsLinkedHashMap(mergedAnnotation)); } } /** * 封装从注解中获取的构造方法参数名参数值及注解对象 * @author guyadong * @since 1.2.9 */ public static class CtorArgInfo{ /** * 数据来源注解对象 */ public final MergedAnnotation source; /** * 以构造方法参数定义顺序返回参数名(注解字段名)-参数值的映射 */ public final Map argsMap; public CtorArgInfo(MergedAnnotation source, LinkedHashMap argsMap) { this.source = source; this.argsMap = new LinkedHashMap<>(argsMap); } /** * 以数组形式返回构造方法参数 */ public Object[] args() { return argsMap.values().toArray(new Object[argsMap.size()]); } /** * 以数组形式返回注解中定义构造方法参数的字段名 */ public String[] argNames() { return argsMap.keySet().toArray(new String[argsMap.size()]); } /** * 返回构造参数数量 */ public int size() { return argsMap.size(); } @Override public int hashCode() { return Objects.hash(argsMap, source); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; CtorArgInfo other = (CtorArgInfo) obj; return Objects.equals(argsMap, other.argsMap) && Objects.equals(source, other.source); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("CtorArgInfo [source=").append(source).append(", argsMap=").append(argsMap).append("]"); return builder.toString(); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy