001package net.gdface.codegen.thrift; 002 003import java.lang.reflect.Method; 004import java.lang.reflect.ParameterizedType; 005import java.lang.reflect.Type; 006import java.util.ArrayDeque; 007import java.util.ArrayList; 008import java.util.Collection; 009import java.util.Deque; 010import java.util.List; 011import java.util.Map; 012import java.util.Map.Entry; 013import java.util.Set; 014import static com.google.common.base.Preconditions.*; 015 016import com.google.common.base.Optional; 017import com.google.common.base.Predicate; 018import com.google.common.collect.Iterables; 019import com.google.common.collect.LinkedListMultimap; 020import com.google.common.collect.ListMultimap; 021import com.google.common.collect.Lists; 022import com.google.common.collect.Ordering; 023import com.google.common.collect.Sets; 024import com.google.common.reflect.TypeToken; 025 026import net.gdface.thrift.ThriftUtils; 027import net.gdface.thrift.TypeTransformer; 028import net.gdface.thrift.exception.ServiceRuntimeException; 029import net.gdface.utils.BeanRelativeUtilits; 030import net.gdface.utils.NameStringUtils; 031 032/** 033 * @author guyadong 034 * 035 */ 036public class ThriftSchema implements ThriftConstants { 037 private final Set<ThriftStructDecorator> thriftStructDecorators = Sets.newLinkedHashSet(); 038 private final Set<ThriftStructDecorator> thriftStructs = Sets.newLinkedHashSet(); 039 private final List<ThriftServiceDecorator<?>> thriftServiceDecorators = Lists.newLinkedList(); 040 private final Predicate<ThriftStructDecorator> exceptionFilter = new Predicate<ThriftStructDecorator>(){ 041 @Override 042 public boolean apply(ThriftStructDecorator input) { 043 return input.isException(); 044 }}; 045 private final Predicate<ThriftStructDecorator> enumFilter = new Predicate<ThriftStructDecorator>(){ 046 @Override 047 public boolean apply(ThriftStructDecorator input) { 048 return input.isEnum(); 049 }}; 050 private final Predicate<ThriftStructDecorator> beanFilter = new Predicate<ThriftStructDecorator>(){ 051 @Override 052 public boolean apply(ThriftStructDecorator input) { 053 return input.isBean(); 054 }}; 055 private final Predicate<ThriftStructDecorator> findString = new Predicate<ThriftStructDecorator>(){ 056 @Override 057 public boolean apply(ThriftStructDecorator input) { 058 return null!=input && input.isUseString(); 059 }}; 060 private final Predicate<ThriftStructDecorator> findMap = new Predicate<ThriftStructDecorator>(){ 061 @Override 062 public boolean apply(ThriftStructDecorator input) { 063 return null!=input && input.isUseMap(); 064 }}; 065 private final Predicate<ThriftStructDecorator> findSet = new Predicate<ThriftStructDecorator>(){ 066 @Override 067 public boolean apply(ThriftStructDecorator input) { 068 return null!=input && input.isUseSet(); 069 }}; 070 private final Predicate<ThriftStructDecorator> findVector = new Predicate<ThriftStructDecorator>(){ 071 @Override 072 public boolean apply(ThriftStructDecorator input) { 073 return null!=input && input.isUseVector(); 074 }}; 075 private final Predicate<ThriftStructDecorator> findException = new Predicate<ThriftStructDecorator>(){ 076 @Override 077 public boolean apply(ThriftStructDecorator input) { 078 return null!=input && input.isException(); 079 }}; 080 @SuppressWarnings({ "rawtypes", "unchecked" }) 081 public ThriftSchema(Map<Class<?>, Class<?>> interfaceClasses) { 082 for(Entry<Class<?>, Class<?>> entry:interfaceClasses.entrySet()){ 083 Class<?> interfaceClass = entry.getKey(); 084 Class<?> refClass = entry.getValue(); 085 if(refClass == ThriftServiceDecoratorConfiguration.DEF_REF_CLASS){ 086 refClass = null; 087 } 088 ThriftServiceDecorator service = new ThriftServiceDecorator(interfaceClass,refClass); 089 thriftServiceDecorators.add(service); 090 } 091 if(!compile()){ 092 throw new IllegalStateException("compile fail"); 093 } 094 } 095 public List<ThriftStructDecorator> getAllStructDecorators() { 096 return Lists.newArrayList(thriftStructDecorators); 097 } 098 public List<ThriftStructDecorator> getExceptionDecorators(){ 099 return Lists.newArrayList(Sets.filter(thriftStructDecorators, exceptionFilter)); 100 } 101 public List<ThriftStructDecorator> getEnumDecorators(){ 102 return Lists.newArrayList(Sets.filter(thriftStructDecorators, enumFilter)); 103 } 104 public List<ThriftStructDecorator> getBeanDecorators(){ 105 return Lists.newArrayList(Sets.filter(thriftStructDecorators, beanFilter)); 106 } 107 public List<ThriftServiceDecorator<?>> getThriftServiceDecorators() { 108 return thriftServiceDecorators; 109 } 110 private boolean compile(){ 111 for(ThriftServiceDecorator<?> newSourceInfo:getThriftServiceDecorators()){ 112 if (!newSourceInfo.compile()){ 113 return false; 114 } 115 thriftStructDecorators.addAll(newSourceInfo.getDecorateTypes()); 116 thriftStructs.addAll(newSourceInfo.getThriftTypes()); 117 } 118 for(ThriftStructDecorator newSourceInfo:getAllStructDecorators()){ 119 if (!newSourceInfo.compile()){ 120 return false; 121 } 122 thriftStructDecorators.addAll(newSourceInfo.getDecorateTypes()); 123 thriftStructs.addAll(newSourceInfo.getThriftTypes()); 124 } 125 return true; 126 } 127 public boolean isThriftBuildinType(Type type){ 128 return ThriftUtils.isThriftBuildinType(type); 129 } 130 public boolean isCastType(Type type){ 131 return ThriftUtils.isCastType(type); 132 } 133 public boolean isDecoratorType(final Type type) { 134 return getDecoratorType(type) != null; 135 } 136 public ThriftStructDecorator getDecoratorType(final Type type) { 137 Optional<ThriftStructDecorator> result = Iterables.tryFind(thriftStructDecorators, new Predicate<ThriftStructDecorator>(){ 138 139 @Override 140 public boolean apply(ThriftStructDecorator input) { 141 return input.getBaseClass().equals(type); 142 }}); 143 return result.isPresent() ? result.get() : null; 144 } 145 public boolean isThriftStruct(Type type){ 146 return ThriftUtils.isThriftStruct(type); 147 } 148 public boolean isPrimitivefloat(Type type){ 149 return ThriftUtils.isPrimitivefloat(type); 150 } 151 public boolean isfloat(Type type){ 152 return ThriftUtils.isfloat(type); 153 } 154 public boolean isPrimitiveArray(Type type){ 155 return ThriftUtils.isPrimitiveArray(type); 156 } 157 public boolean isMap(Type type){ 158 return TypeToken.of(type).getRawType() == Map.class; 159 } 160 public boolean isList(Type type){ 161 return TypeToken.of(type).getRawType() == List.class; 162 } 163 public boolean isSet(Type type){ 164 return TypeToken.of(type).getRawType() == Set.class; 165 } 166 public boolean isCollection(Type type){ 167 return isList(type) || isSet(type); 168 } 169 public boolean isArray(Type type){ 170 return isList(type) || isSet(type); 171 } 172 public boolean isBinary(Type type){ 173 return type == byte[].class; 174 } 175 public final Type wrap(Type type){ 176 return TypeToken.of(type).wrap().getType(); 177 } 178 /** 179 * 对thrift IDL 关键字(binary,list,map,set,i32...)转义,以确保生成的IDL文件中成员名和参数名与thrift关键字不冲突 180 * @param name 181 * @return 182 */ 183 public String escapeThrift(String name){ 184 return NameStringUtils.isThriftReserved(name)? name + "_" : name; 185 } 186 /** 187 * 字段名转义,避免java,thrift关键字冲突 188 * @param name 189 * @return 190 */ 191 public String escapeField(String name){ 192 if(NameStringUtils.isJavaReserved(name)){ 193 return "_" + name; 194 }else { 195 return escapeThrift(name); 196 } 197 } 198 public static boolean isIsLocalMethod(Method method){ 199 return ThriftUtils.isIsLocalMethod(method); 200 } 201 public static boolean isIsLocalMethod(net.gdface.codegen.Method method){ 202 return ThriftUtils.isIsLocalMethod(method.delegate()); 203 } 204 public Type[] getActualTypeArguments(Type type){ 205 if( type instanceof ParameterizedType){ 206 return ((ParameterizedType)type).getActualTypeArguments(); 207 } 208 return new Type[0]; 209 } 210 public Class<?> getServiceRuntimeExceptionClass(){ 211 return ServiceRuntimeException.class; 212 } 213 public Class<?> getTypeTransformerClass(){ 214 return TypeTransformer.class; 215 } 216 public String toStubType(Class<?> clazz){ 217 checkArgument(null !=clazz,"clazz is null"); 218 if(isThriftStruct(clazz) || Enum.class.isAssignableFrom(clazz) || this.isDecoratorType(clazz)){ 219 return ThriftServiceDecoratorConfiguration.INSTANCE.getThriftClientPackage() + "." + clazz.getSimpleName(); 220 } 221 throw new IllegalArgumentException(String.format("%s is not thrift stub type", clazz.getName())); 222 } 223 public String toStubCxxType(Class<?> clazz){ 224 return CxxHelper.cxxNamespace("::"+toStubType(clazz),true); 225 } 226 /** 227 * 返回指定包名下的所有{@link ThriftStructDecorator}对象,,按类名自然排序,没有找到则返回空表 228 * @param pkg 229 * @return 230 */ 231 public List<ThriftStructDecorator> getThriftStructDecorator(final String pkg){ 232 ArrayList<ThriftStructDecorator> list = Lists.newArrayList(Iterables.filter(this.thriftStructDecorators, new Predicate<ThriftStructDecorator>(){ 233 @Override 234 public boolean apply(ThriftStructDecorator input) { 235 return input.getBaseClass().getPackage().getName().equals(pkg); 236 }})); 237 return Ordering.natural().sortedCopy(list); 238 } 239 /** 240 * 根据{@link ThriftStructDecorator}对象之间的依赖关系返回{@link ThriftStructDecorator}队列 241 * @param thriftStructIncluded 是否包含thrift struct 类 242 * @return 243 */ 244 protected List<ThriftStructDecorator> getGenSequence(boolean thriftStructIncluded){ 245 List<ThriftStructDecorator> types = getAllStructDecorators(); 246 if(thriftStructIncluded){ 247 types.addAll(thriftStructs); 248 } 249 List<ThriftStructDecorator> list = BeanRelativeUtilits.sortByField(types,"name"); 250 //List<ThriftStructDecorator> list = getAllStructDecorators(); 251 ArrayDeque<ThriftStructDecorator> seq = new ArrayDeque<>(); 252 for(ThriftStructDecorator struct:list){ 253 traverseMember(struct,seq); 254 } 255 return Lists.newArrayList(seq.descendingIterator()); 256 } 257 private void traverseMember(ThriftStructDecorator parent,Deque<ThriftStructDecorator> seq){ 258 if(!seq.contains(parent)){ 259 List<ThriftStructDecorator> members = BeanRelativeUtilits.sortByField(parent.getDecorateTypes(),"name"); 260 for(ThriftStructDecorator struct:members){ 261 traverseMember(struct,seq); 262 } 263 seq.push(parent); 264 } 265 } 266 /** 267 * 根据{@link ThriftStructDecorator}对象之间的依赖关系返回以package为key的 {@link ListMultimap}映射 268 * @param thriftStructIncluded 是否包含thrift struct 类 269 * @return 270 */ 271 public ListMultimap<String,Collection<ThriftStructDecorator>> getStructGenSequenceAsMultimap(boolean thriftStructIncluded){ 272 List<ThriftStructDecorator> seqlist = getGenSequence(thriftStructIncluded); 273 seqlist.add(new ThriftStructDecorator(getServiceRuntimeExceptionClass())); 274 LinkedListMultimap<String, Collection<ThriftStructDecorator>> seq = LinkedListMultimap.<String, Collection<ThriftStructDecorator>>create(); 275 String curPkg=null; 276 List<ThriftStructDecorator> sub = null; 277 for(ThriftStructDecorator struct:seqlist){ 278 String pkg = struct.getPackage(); 279 if(!pkg.equals(curPkg)){ 280 if(null !=curPkg){ 281 seq.put(curPkg, sub); 282 } 283 sub = Lists.newLinkedList(); 284 curPkg = struct.getPackage(); 285 } 286 sub.add(struct); 287 } 288 if(null !=curPkg){ 289 seq.put(curPkg, sub); 290 } 291 return seq; 292 } 293 public boolean isUseStringInTypes(){ 294 return Iterables.tryFind(thriftStructDecorators, findString).isPresent(); 295 } 296 public boolean isUseMapInTypes(){ 297 return Iterables.tryFind(thriftStructDecorators, findMap).isPresent(); 298 } 299 public boolean isUseSetInTypes(){ 300 return Iterables.tryFind(thriftStructDecorators, findSet).isPresent(); 301 } 302 public boolean isUseVectorInTypes(){ 303 return Iterables.tryFind(thriftStructDecorators, findVector).isPresent(); 304 } 305 public boolean isUseExceptionInTypes(){ 306 return Iterables.tryFind(thriftStructDecorators, findException).isPresent(); 307 } 308 public boolean isCanMove(CxxType cxxType){ 309 if(null == cxxType){ 310 return false; 311 } 312 CxxTypeMeta uiType = cxxType.getUiType(); 313 if(uiType.isCanMove() && !uiType.isStruct()){ 314 return true; 315 } 316 ThriftStructDecorator memSturct = getDecoratorType(cxxType.getJavaType()); 317 return null !=memSturct && memSturct.isHasCanMoveField(); 318 } 319}