com.gitee.l0km.casban.ctor.AnnotConstructors Maven / Gradle / Ivy
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 extends Annotation> 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 extends Annotation> 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 extends Annotation> 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 extends Annotation> 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 extends Annotation> 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 extends Annotation> 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 extends Annotation> 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 extends Annotation> 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 extends Annotation> mergedAnnotation){
return new CtorArgInfo(mergedAnnotation,getConstructorArgsAsLinkedHashMap(mergedAnnotation));
}
}
/**
* 封装从注解中获取的构造方法参数名参数值及注解对象
* @author guyadong
* @since 1.2.9
*/
public static class CtorArgInfo{
/**
* 数据来源注解对象
*/
public final MergedAnnotation extends Annotation> source;
/**
* 以构造方法参数定义顺序返回参数名(注解字段名)-参数值的映射
*/
public final Map argsMap;
public CtorArgInfo(MergedAnnotation extends Annotation> 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