com.gitee.l0km.codegen.thrift.ThriftSchema Maven / Gradle / Ivy
package com.gitee.l0km.codegen.thrift;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.gitee.l0km.aocache.annotations.AoCacheable;
import com.gitee.l0km.codegen.base.CodeGenUtils;
import com.gitee.l0km.codegen.thrift.ThriftServiceDecoratorConfiguration.TaskType;
import com.gitee.l0km.com4j.base.NameStringUtils;
import com.gitee.l0km.com4j.basex.bean.BeanRelativeUtilits;
import com.gitee.l0km.xthrift.base.BaseThriftUtils;
import com.gitee.l0km.xthrift.base.exception.ServiceRuntimeException;
import com.gitee.l0km.xthrift.base.metadata.DecoratorThriftEnumMetadata;
import com.gitee.l0km.xthrift.base.metadata.DecoratorThriftEnumMetadata.ExtensiveEnumItem;
import com.gitee.l0km.xthrift.base.metadata.DecoratorThriftStructMetadata;
import static com.gitee.l0km.xthrift.base.metadata.Decorators.javadocCommentProviderFactory;
import com.gitee.l0km.xthrift.base.metadata.ErpcProxyReturnCode;
import com.gitee.l0km.xthrift.base.metadata.ErpcType;
import com.gitee.l0km.xthrift.base.metadata.ThriftCatalogWithTransformer;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import com.google.common.reflect.TypeToken;
/**
* @author guyadong
*
*/
public class ThriftSchema implements ThriftConstants {
private final Set thriftStructDecorators = Sets.newLinkedHashSet();
private final Set thriftStructs = Sets.newLinkedHashSet();
private final Set collectionStructs = Sets.newTreeSet();
private final List> thriftServiceDecorators = Lists.newLinkedList();
@SuppressWarnings({ "rawtypes", "unchecked" })
public ThriftSchema(Map, Class>> interfaceClasses) {
for(Entry, Class>> entry:interfaceClasses.entrySet()){
Class> interfaceClass = entry.getKey();
Class> refClass = entry.getValue();
if(refClass == ThriftServiceDecoratorConfiguration.DEF_REF_CLASS){
refClass = null;
}
ThriftServiceDecorator service = new ThriftServiceDecorator(interfaceClass,refClass);
thriftServiceDecorators.add(service);
}
if(!compile()){
throw new IllegalStateException("compile fail");
}
}
public List getAllStructDecorators() {
return Lists.newArrayList(thriftStructDecorators);
}
public List getExceptionDecorators(){
return Lists.newArrayList(Sets.filter(thriftStructDecorators, ThriftStructDecorator::isException));
}
public List getEnumDecorators(){
return Lists.newArrayList(Sets.filter(thriftStructDecorators, ThriftStructDecorator::isEnum));
}
public List getBeanDecorators(){
return Lists.newArrayList(Sets.filter(thriftStructDecorators, ThriftStructDecorator::isBean));
}
public List> getThriftServiceDecorators() {
return thriftServiceDecorators;
}
private boolean compile(){
for(ThriftServiceDecorator> newSourceInfo:getThriftServiceDecorators()){
if (!newSourceInfo.compile()){
return false;
}
thriftStructDecorators.addAll(newSourceInfo.getDecorateTypes());
thriftStructs.addAll(newSourceInfo.getThriftTypes());
}
for(ThriftStructDecorator newSourceInfo:getAllStructDecorators()){
if (!newSourceInfo.compile()){
return false;
}
thriftStructDecorators.addAll(newSourceInfo.getDecorateTypes());
thriftStructs.addAll(newSourceInfo.getThriftTypes());
}
return true;
}
public boolean isThriftBuildinType(Type type){
return BaseThriftUtils.isThriftBuildinType(type);
}
public boolean isCastType(Type type){
return BaseThriftUtils.isCastType(type);
}
public boolean isDecoratorType(final Type type) {
return getDecoratorType(type) != null;
}
public ThriftStructDecorator getDecoratorType(Type type) {
return Iterables.tryFind(thriftStructDecorators, struct->struct.getBaseClass().equals(type)).orNull();
}
public boolean isThriftStruct(Type type){
return BaseThriftUtils.isThriftStruct(type);
}
public boolean isPrimitivefloat(Type type){
return BaseThriftUtils.isPrimitivefloat(type);
}
public boolean isfloat(Type type){
return BaseThriftUtils.isfloat(type);
}
public boolean isPrimitiveArray(Type type){
return BaseThriftUtils.isPrimitiveArray(type);
}
public boolean isMap(Type type){
return TypeToken.of(type).getRawType() == Map.class;
}
public boolean isList(Type type){
return TypeToken.of(type).getRawType() == List.class;
}
public boolean isSet(Type type){
return TypeToken.of(type).getRawType() == Set.class;
}
public boolean isCollection(Type type){
return isList(type) || isSet(type);
}
public boolean isArray(Type type){
return isList(type) || isSet(type);
}
public boolean isBinary(Type type){
return type == byte[].class;
}
public final Type wrap(Type type){
return TypeToken.of(type).wrap().getType();
}
/**
* 对thrift IDL 关键字(binary,list,map,set,i32...)转义,以确保生成的IDL文件中成员名和参数名与thrift关键字不冲突
* @param name
*/
public String escapeThrift(String name){
return NameStringUtils.isThriftReserved(name)? name + "_" : name;
}
/**
* 字段名转义,避免java,thrift关键字冲突
* @param name
*/
public String escapeField(String name){
if(NameStringUtils.isJavaReserved(name)){
return "_" + name;
}else {
return escapeThrift(name);
}
}
public static boolean isIsLocalMethod(Method method){
return BaseThriftUtils.isIsLocalMethod(method);
}
public static boolean isIsLocalMethod(com.gitee.l0km.codegen.base.Method method){
return BaseThriftUtils.isIsLocalMethod(method.delegate());
}
public Type[] getActualTypeArguments(Type type){
if( type instanceof ParameterizedType){
return ((ParameterizedType)type).getActualTypeArguments();
}
return new Type[0];
}
public Class> getServiceRuntimeExceptionClass(){
return ServiceRuntimeException.class;
}
public String toStubType(Class> clazz){
checkArgument(null !=clazz,"clazz is null");
if(isThriftStruct(clazz) || Enum.class.isAssignableFrom(clazz) || this.isDecoratorType(clazz)){
return ThriftServiceDecoratorConfiguration.INSTANCE.getThriftClientPackage() + "." + clazz.getSimpleName();
}
throw new IllegalArgumentException(String.format("%s is not thrift stub type", clazz.getName()));
}
public String toStubCxxType(Class> clazz){
return CxxHelper.cxxNamespace("::"+toStubType(clazz),true);
}
/**
* 返回指定包名下的所有{@link ThriftStructDecorator}对象,按类名自然排序,没有找到则返回空表
* @param pkg
*/
public List getThriftStructDecorator(final String pkg){
ImmutableList list = FluentIterable.from(this.thriftStructDecorators)
.filter(struct->struct.getBaseClass().getPackage().getName().equals(pkg)).toList();
return Ordering.natural().sortedCopy(list);
}
/**
* 根据{@link ThriftStructDecorator}对象之间的依赖关系返回{@link ThriftStructDecorator}队列
* @param thriftStructIncluded 是否包含thrift struct 类
*/
protected List getGenSequence(boolean thriftStructIncluded){
List types = getAllStructDecorators();
if(thriftStructIncluded){
types.addAll(thriftStructs);
for(Class> structType : ThriftServiceDecoratorConfiguration.INSTANCE.getExtStructs()){
types.add(TypeHelper.makeThriftStructDecorator(structType));
}
}
List list = BeanRelativeUtilits.sortByField(types,"name");
//List list = getAllStructDecorators();
ArrayDeque seq = new ArrayDeque<>();
for(ThriftStructDecorator struct:list){
traverseMember(struct,seq, thriftStructIncluded);
}
return Lists.newArrayList(seq.descendingIterator());
}
/**
* 生成结构类型序列,确保类型的成员类型如果为结构类型定义在父类型之前
* @param parent 父类型
* @param seq 生成的结构类型序列
* @param thriftStructIncluded
*/
private void traverseMember(ThriftStructDecorator parent,Deque seq, boolean thriftStructIncluded){
if(!seq.contains(parent)){
List decoratorMembers = BeanRelativeUtilits.sortByField(parent.getDecorateTypes(),"name");
for(ThriftStructDecorator struct:decoratorMembers){
traverseMember(struct,seq, thriftStructIncluded);
}
if(thriftStructIncluded){
List thriftMembers = BeanRelativeUtilits.sortByField(parent.getThriftTypes(),"name");
for(ThriftStructDecorator struct:thriftMembers){
traverseMember(struct,seq, thriftStructIncluded);
}
}
seq.push(parent);
}
}
/**
* 根据{@link ThriftStructDecorator}对象之间的依赖关系返回以package为key的 {@link ListMultimap}映射
* @param thriftStructIncluded 是否包含thrift struct 类
*/
public ListMultimap> getStructGenSequenceAsMultimap(boolean thriftStructIncluded){
List seqlist = getGenSequence(thriftStructIncluded);
seqlist.add(new ThriftStructDecorator(getServiceRuntimeExceptionClass()));
LinkedListMultimap> seq = LinkedListMultimap.>create();
String curPkg=null;
List sub = null;
for(ThriftStructDecorator struct:seqlist){
String pkg = struct.getPackage();
if(!pkg.equals(curPkg)){
if(null !=curPkg){
seq.put(curPkg, sub);
}
sub = Lists.newLinkedList();
curPkg = struct.getPackage();
}
sub.add(struct);
}
if(null !=curPkg){
seq.put(curPkg, sub);
}
return seq;
}
public boolean isUseStringInServices(){
return Iterables.tryFind(thriftServiceDecorators, ThriftServiceDecorator::isUseStringInService).isPresent();
}
public boolean isUseBinaryInServices(){
return Iterables.tryFind(thriftServiceDecorators, ThriftServiceDecorator::isUseBinaryInService).isPresent();
}
public boolean isUseStringInTypes(){
return Iterables.tryFind(thriftStructDecorators, ThriftStructDecorator::isUseString).isPresent();
}
public boolean isUseBinaryInTypes(){
return Iterables.tryFind(thriftStructDecorators, ThriftStructDecorator::isUseBinary).isPresent();
}
public boolean isUseMapInTypes(){
return Iterables.tryFind(thriftStructDecorators, ThriftStructDecorator::isUseMap).isPresent();
}
public boolean isUseSetInTypes(){
return Iterables.tryFind(thriftStructDecorators, ThriftStructDecorator::isUseSet).isPresent();
}
public boolean isUseVectorInTypes(){
return Iterables.tryFind(thriftStructDecorators, ThriftStructDecorator::isUseVector).isPresent() || isSql2java4x();
}
/**
* @since 2.3.5
*/
@AoCacheable
public boolean isSql2java4x(){
return thriftStructs.stream().anyMatch(ThriftStructDecorator::isSql2java4x);
}
public boolean isUseExceptionInTypes(){
return Iterables.tryFind(thriftStructDecorators, ThriftStructDecorator::isException).isPresent();
}
@AoCacheable
public boolean isCanMove(CxxType cxxType){
if(null == cxxType){
return false;
}
CxxTypeMeta uiType = cxxType.getUiType();
if(uiType.isCanMove() && !uiType.isStruct()){
return true;
}
ThriftStructDecorator memSturct = getDecoratorType(cxxType.getJavaType());
return null !=memSturct && memSturct.isHasCanMoveField();
}
@AoCacheable
public boolean isCommonType(final Type type){
if(type instanceof Class>){
Set commonTypes = ThriftServiceDecoratorConfiguration.INSTANCE.getCommonTypes();
return FluentIterable.from(commonTypes).anyMatch(str->{
Class> clazz = (Class>)type;
return clazz.getName().equals(str)
|| clazz.getSimpleName().equals(str)
|| clazz.getPackage().getName().startsWith(str);
});
}
return false;
}
public String getProgramName(){
return ThriftServiceDecoratorConfiguration.INSTANCE.getProgramName();
}
public String getPortPrefix(){
return ThriftServiceDecoratorConfiguration.INSTANCE.getPortPrefix();
}
/**
* @param thriftServiceClasses 要设置的 thriftServiceClasses
* @return 当前对象
*/
public ThriftSchema setThriftServiceClasses(Map, Class>> thriftServiceClasses) {
if(thriftServiceClasses != null){
for(ThriftServiceDecorator> decorator:thriftServiceDecorators){
decorator.setThriftServiceClass(thriftServiceClasses.get(decorator.getInterfaceClass())).erpcProxyInit();
}
}
return this;
}
public DecoratorThriftEnumMetadata> getThriftEnumMetadata(Type type){
if(type instanceof Class>){
return (DecoratorThriftEnumMetadata>) ThriftCatalogWithTransformer.CATALOG.getThriftEnumMetadata((Class>) type);
}
return null;
}
public DecoratorThriftEnumMetadata> getThriftEnumMetadata(String className) throws ClassNotFoundException{
return getThriftEnumMetadata(CodeGenUtils.forName(className));
}
public DecoratorThriftStructMetadata getThriftStructMetadata(Type type){
return (DecoratorThriftStructMetadata) ThriftCatalogWithTransformer.CATALOG.getThriftStructMetadata(type);
}
public DecoratorThriftStructMetadata getThriftStructMetadata(String className) throws ClassNotFoundException{
return getThriftStructMetadata(CodeGenUtils.forName(className));
}
/**
* @return collectionStructs
*/
public List getCollectionStructs() {
return Lists.newArrayList(collectionStructs);
}
/**
* @return collectionStructs
*/
public List getCollectionStructs(final boolean structElement) {
Iterable filtered = Iterables.filter(collectionStructs,
c->{
boolean isStruct = isThriftStruct(c.getValueType().getJavaType());
return structElement ? isStruct : !isStruct;
});
ArrayList types = Lists.newArrayList(filtered);
return types;
}
public int getExistsListString(){
return Iterables.tryFind(collectionStructs, c->c.getValueType().getProtocolType().isString()).isPresent() ? 1 : 0;
}
public int getExistsListBinary(){
return Iterables.tryFind(collectionStructs, c->c.getValueType().getProtocolType().isBinary()).isPresent() ? 1 : 0;
}
public ThriftSchema erpcProxyInit(){
if(TaskType.ERPC_PROXY.equals(ThriftServiceDecoratorConfiguration.INSTANCE.getTaskType())){
for(ThriftServiceDecorator> newSourceInfo:getThriftServiceDecorators()){
collectionStructs.addAll(newSourceInfo.getCollectionTypes());
}
DecoratorThriftEnumMetadata.beforeExtensiveEnumItems = createBeforeExtensiveEnumItem();
// 添加到列表头部
thriftStructs.add(new ThriftStructDecorator(ErpcProxyReturnCode.class));
}
return this;
}
private ImmutableMap>, List> createBeforeExtensiveEnumItem(){
ArrayList items = Lists.newArrayList();
for(ThriftStructDecorator type:thriftStructDecorators){
Class> javaType = type.getBaseClass();
if(javaType instanceof Class> && Exception.class.isAssignableFrom(javaType)){
ImmutableList comment = null;
if(javadocCommentProviderFactory != null){
comment = ImmutableList.copyOf(javadocCommentProviderFactory.apply(javaType).commentOfClass());
}
items.add(new ExtensiveEnumItem(javaType.getSimpleName(),null,comment));
}
}
return ImmutableMap.>, List>of(ErpcProxyReturnCode.class,items);
}
public int getErpcForwardPort(){
return ThriftServiceDecoratorConfiguration.INSTANCE.getErpcForwardPort();
}
public int getErpcProxyPort(){
return ThriftServiceDecoratorConfiguration.INSTANCE.getErpcProxyPort();
}
public int getDefaultMaxLength(){
return ThriftServiceDecoratorConfiguration.INSTANCE.getDefaultMaxLength();
}
public int getErrmsgMaxLength(){
return ThriftServiceDecoratorConfiguration.INSTANCE.getErrmsgMaxLength();
}
public int getBinaryOutputSize(){
return ThriftServiceDecoratorConfiguration.INSTANCE.getBinaryOutputSize();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy