001package net.gdface.codegen.thrift; 002 003import java.lang.reflect.Type; 004import java.util.ArrayList; 005import java.util.Arrays; 006import java.util.Collections; 007import java.util.List; 008import com.google.common.base.Strings; 009 010import com.google.common.base.Joiner; 011 012import com.google.common.base.MoreObjects; 013import com.google.common.base.Predicate; 014import com.google.common.collect.Iterables; 015import com.google.common.collect.Lists; 016 017import static com.google.common.base.Preconditions.*; 018 019public class CxxHelper { 020 021 public CxxHelper() { 022 } 023 private static ThreadLocal<ArrayList<String>> tlsPackageName=new ThreadLocal<ArrayList<String>>() ; 024 private static ThreadLocal<Boolean> tlsMultiline = new ThreadLocal<Boolean>(); 025 private static String getCurrent(String separator){ 026 ArrayList<String> pkg = tlsPackageName.get(); 027 if(null == pkg){ 028 return ""; 029 } 030 return Joiner.on(separator).join(pkg); 031 } 032 public static String getCurrentNamespace(){ 033 return getCurrent("::"); 034 } 035 public static String getCurrentPackageAsJava(){ 036 return getCurrent("."); 037 } 038 public static boolean isCurrentPackage(Class<?> clazz){ 039 return null == clazz 040 ? false 041 : clazz.getPackage().getName().equals(getCurrentPackageAsJava()); 042 } 043 /** 044 * @param packageName java package或c++ namespace 045 * @param multiline 046 * @return 047 */ 048 public static String namespaceBegin(String packageName, boolean multiline){ 049 packageName = MoreObjects.firstNonNull(packageName, ""); 050 ArrayList<String> names = Lists.newArrayList(Iterables.filter(Arrays.asList(packageName.split("(\\.|::)")),new Predicate<String>(){ 051 @Override 052 public boolean apply(String input) { 053 return !input.trim().isEmpty(); 054 }})); 055 tlsPackageName.set(names); 056 tlsMultiline.set(multiline); 057 StringBuilder builder=new StringBuilder(); 058 for(String name:names){ 059 builder.append(String.format("namespace %s{",name)); 060 if(multiline){ 061 builder.append("\n"); 062 } 063 } 064 return builder.toString(); 065 } 066 public static String namespaceBegin(Class<?> clazz){ 067 return null==clazz ? "// class is null\n" : namespaceBegin(clazz.getPackage().getName(), true); 068 } 069 public static String namespaceBegin(Class<?> clazz,boolean multiline){ 070 return null==clazz ? "// class is null\n" : namespaceBegin(clazz.getPackage().getName(), multiline); 071 } 072 public static String namespaceEnd(){ 073 List<String> names = MoreObjects.firstNonNull(tlsPackageName.get(),Collections.<String>emptyList()); 074 StringBuilder builder=new StringBuilder(); 075 for(String name:Lists.reverse(names)){ 076 builder.append(String.format("} /* namespace %s */",name)); 077 } 078 if(Boolean.TRUE.equals(tlsMultiline.get())){ 079 builder.append("\n"); 080 } 081 tlsPackageName.remove(); 082 tlsMultiline.remove(); 083 return builder.toString(); 084 } 085 086 /** 087 * java 包名或类名转为c++ namespace或类名 088 * @param javaName package或类名 089 * @param isfull 为{@code false}返回空串,{@code javaName}为类名时必须为{@code true},否则无法返回正确结果 090 * @return 091 */ 092 public static String cxxNamespace(String javaName,boolean isfull){ 093 if(null==javaName || !isfull){ 094 return ""; 095 } 096 // . $ 都替换为 :: 097 return javaName.replaceAll("[\\.\\$]", "::"); 098 } 099 public static String cxxNamespace(Class<?>clazz,boolean isfull ){ 100 return null==clazz ? "// class is null\n" : cxxNamespace(clazz.getPackage().getName(),isfull); 101 } 102 public static String cxxNamespace(String packageName){ 103 return cxxNamespace(packageName,true); 104 } 105 106 public static String cxxNamespace(Class<?>clazz){ 107 return cxxNamespace(clazz,true); 108 } 109 public static String cxxClassName(Class<?>clazz,boolean isfull ){ 110 if(null==clazz){ 111 return ""; 112 } 113 return isfull ? cxxNamespace(clazz.getName(),true) : clazz.getSimpleName(); 114 } 115 116 public static String cxxClassName(Class<?>clazz){ 117 return getTypeName(cxxClassName(clazz,true)); 118 } 119 /** 120 * 返回一个c++类名的简单类名,类似 {@link Class#getSimpleName()} 121 * @param cxxType 122 * @return 123 */ 124 public static String simpleName(String cxxType){ 125 if(null != cxxType){ 126 return cxxType.replaceAll("^(?:::)?(?:\\w+::)*", ""); 127 } 128 return cxxType; 129 } 130 public static String getCxxNamespace(String cxxType){ 131 if(null == cxxType){ 132 return ""; 133 } 134 return cxxType.replaceAll("::\\w+$", ""); 135 } 136 public static String getCxxNamespaceOfJava(String javaClassName){ 137 if(null == javaClassName){ 138 return ""; 139 } 140 return getCxxNamespace(cxxNamespace(javaClassName,true)); 141 } 142 /** 143 * 根据当前namespace返回最简单的类型名 144 * @param cxxType cxx类名 145 * @return 146 */ 147 public static String getTypeName(String cxxType){ 148 checkArgument((!Strings.isNullOrEmpty(cxxType)) && cxxType.indexOf('.') == -1, 149 "invalid c++ Type %s",cxxType); 150 String cns = getCurrentNamespace(); 151 if(!cns.isEmpty()){ 152 cns = getCurrentNamespace() + "::"; 153 } 154 return cxxType.replaceFirst(cns, ""); 155 } 156/* public static String getTypeName(Class<?>clazz){ 157 return getTypeName(cxxClassName(clazz,true)); 158 }*/ 159 public CxxType getCxxType(Type type){ 160 return CxxType.getThriftType(type); 161 } 162}