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