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

com.gitee.l0km.codegen.thrift.ThriftSchema Maven / Gradle / Ivy

There is a newer version: 3.5.0
Show newest version
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