Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.coodex.concrete.apitools.AbstractAngularRenderer Maven / Gradle / Ivy
/*
* Copyright (c) 2018 coodex.org ([email protected] )
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.coodex.concrete.apitools;
import org.coodex.concrete.apitools.jaxrs.angular.meta.*;
import org.coodex.concrete.common.modules.AbstractModule;
import org.coodex.concrete.common.modules.AbstractParam;
import org.coodex.concrete.common.modules.AbstractUnit;
import org.coodex.util.Common;
import java.io.IOException;
import java.lang.reflect.*;
import java.util.*;
import static org.coodex.concrete.common.ConcreteHelper.isConcreteService;
import static org.coodex.util.GenericTypeHelper.solveFromType;
public abstract class AbstractAngularRenderer, U extends AbstractUnit>>
extends AbstractRenderer {
protected static final ThreadLocal, TSClass>>> CLASSES = new ThreadLocal<>();
private static final Class>[] NUMBERS = new Class>[]{
byte.class, int.class, short.class, long.class, float.class, double.class
};
/// TODO: 处理方式不妥。如果Service method定义变换顺序后,会导致基于原版本的code全部出问题
@SuppressWarnings("WeakerAccess")
protected String getMethodName(String name, Set methods) {
String methodName = name;
int prefix = 0;
while (methods.contains(methodName)) {
methodName = name + prefix++;
}
methods.add(methodName);
return methodName;
}
protected abstract String getModuleType();
private Map, TSClass>> getClasses() {
return CLASSES.get();
}
protected String getModuleName(String moduleName) {
return moduleName.charAt(0) == '@' ? moduleName : ("@" + moduleName);
}
private String getContextPath(String key) {
StringBuilder builder = new StringBuilder();
for (char ch : key.toCharArray()) {
if (ch == '/') builder.append("../");
}
return builder.toString();
}
protected void packages(String contextPath) throws IOException {
Map> services = new HashMap<>();
Set providers = new HashSet<>();
Set packages = new HashSet<>();
for (String key : getClasses().keySet()) {
packages.add(key);
Map, TSClass> map = getClasses().get(key);
Map toWrite = new HashMap<>();
toWrite.put("contextPath", getContextPath(key));
Set> classSet = new HashSet<>();
for (Class> clz : map.keySet()) {
//ConcreteService.class.isAssignableFrom(clz)
if (isConcreteService(clz)) {
toWrite.put("includeServices", Boolean.TRUE);
providers.add(map.get(clz).getClassName());
Set set = services.containsKey(key) ? services.get(key) : new HashSet<>();
set.add(map.get(clz).getClassName());
services.put(key, set);
}
classSet.addAll(map.get(clz).getImports());
}
Map imports = new HashMap<>();
for (Class> clz : classSet) {
String packageName = getPackageKey(clz);
if (key.equals(packageName)) continue;
TSImport importSet = imports.get(packageName);
if (importSet == null) {
importSet = new TSImport();
importSet.setPackageName(packageName);
imports.put(packageName, importSet);
}
importSet.getClasses().add(clz.getSimpleName());
}
toWrite.put("imports", imports.values());
toWrite.put("classes", sort(map));
writeTo(contextPath + key + ".ts",
"tspackage.ftl",
toWrite);
}
Map toWrite = new HashMap<>();
toWrite.put("services", services);
toWrite.put("providers", providers);
toWrite.put("packages", packages);
toWrite.put("moduleType", getModuleType());
writeTo(contextPath + "Concrete" + getModuleType() + "Module.ts", "concrete.ftl", toWrite);
}
private String getPackageKey(Class> clz) {
return clz.getPackage().getName().replace('.', '/');
}
private Collection sort(Map, TSClass> classes) {
List ordered = new ArrayList<>();
Map, TSClass> cache = new HashMap<>(classes);
while (cache.keySet().size() > 0) {
Class>[] keys = cache.keySet().toArray(new Class>[0]);
for (Class> key : keys) {
TSClass tsClass = cache.get(key);
if (noDep(tsClass, cache)) {
cache.remove(key);
ordered.add(tsClass);
}
}
}
return ordered;
}
private boolean noDep(TSClass tsClass, Map, TSClass> cache) {
if (tsClass instanceof TSPojo) {
return cache.get(((TSPojo) tsClass).getSuperType()) == null;
}
for (Class> clz : tsClass.getImports()) {
if (cache.get(clz) != null) return false;
}
return true;
}
protected void process(String moduleName, AbstractModule module) {
Class> clz = module.getInterfaceClass();
Map, TSClass> moduleMap = getTSClassMap(clz);
// if (moduleMap == null) return;
TSModule tsModule = new TSModule(clz);
tsModule.setBelong(moduleName);
Set methods = new HashSet<>();
for (U unit : module.getUnits()) {
TSMethod method = new TSMethod();
method.setName(getMethodName(unit.getMethod().getName(), methods));
method.setHttpMethod(unit.getInvokeType());
method.setReturnType(getClassType(unit.getGenericReturnType(), tsModule, clz));
method.setMethodPath(getMethodPath(module, unit));
method.setBody(getBody(unit));
method.setParams(getParams(unit, tsModule));
tsModule.getMethods().add(method);
}
moduleMap.put(clz, tsModule);
}
protected abstract String getMethodPath(AbstractModule module, U unit);
private List getParams(U unit, TSClass clz) {
List fieldList = new ArrayList<>();
for (int i = 0; i < unit.getParameters().length; i++) {
AbstractParam param = unit.getParameters()[i];
TSParam field = new TSParam();
field.setName(param.getName());
field.setType(getClassType(param.getGenericType(), clz, unit.getDeclaringModule().getInterfaceClass()));
fieldList.add(field);
}
return fieldList;
}
private Map, TSClass> getTSClassMap(Class> clz) {
Map, TSClass>> classes = getClasses();
String packageName = clz.getPackage().getName().replace('.', '/');
// Map moduleMap = classes.get(packageName);
// if (moduleMap == null) {
// moduleMap = new HashMap<>();
// classes.put(packageName, moduleMap);
// }
// return moduleMap;
return classes.computeIfAbsent(packageName, k -> new HashMap<>());
}
private String getClassType(Type type, TSClass clz, Class> contextClass) {
if (type instanceof Class) {
Class> c = (Class>) type;
if (c.isArray()) {
return getClassType(c.getComponentType(), clz, contextClass) + "[]";
} else
return getClassType(c, clz);
} else if (type instanceof ParameterizedType) {
return getParameterizedType(clz, (ParameterizedType) type, contextClass);
} else if (type instanceof GenericArrayType) {
return getClassType(((GenericArrayType) type).getGenericComponentType(), clz, contextClass) + "[]";
} else if (type instanceof TypeVariable) {
if (contextClass != null) {
return getClassType(solveFromType((TypeVariable>) type, contextClass), clz, null);
} else
return ((TypeVariable>) type).getName();
} else {
throw new RuntimeException("unknown type: " + type);
}
}
private String getParameterizedType(TSClass clz, ParameterizedType pt, Class> contextClass) {
Class> rawType = (Class>) pt.getRawType();
if (Collection.class.isAssignableFrom(rawType)) {
return getClassType(pt.getActualTypeArguments()[0], clz, contextClass) + "[]";
} else if (Map.class.isAssignableFrom(rawType)) {
return String.format("Map<%s, %s>",
getClassType(pt.getActualTypeArguments()[0], clz, contextClass),
getClassType(pt.getActualTypeArguments()[1], clz, contextClass));
} else {
StringBuilder builder = new StringBuilder();
builder.append(getClassType(rawType, clz))
.append("<");
boolean isFirst = true;
for (Type t : pt.getActualTypeArguments()) {
if (!isFirst) builder.append(", ");
builder.append(getClassType(t, clz, contextClass));
isFirst = false;
}
builder.append(">");
return builder.toString();
}
}
private String getClassType(Class> c, TSClass clz) {
if (void.class.equals(c) || Void.class.equals(c)) {
return "void";
} else if (boolean.class.equals(c) || Boolean.class.equals(c)) {
return "boolean";
} else if (Common.inArray(c, NUMBERS) || Number.class.isAssignableFrom(c)) {
return "number";
} else if (char.class.equals(c) || Character.class.equals(c) || CharSequence.class.isAssignableFrom(c)) {
return "string";
} else if (Collection.class.isAssignableFrom(c)) {
return "any[]";
} else if (Map.class.isAssignableFrom(c)) {
return "Map";
} else if (Object.class.equals(c)) {
return "any";
} else {
clz.getImports().add(c);
return getTSPojo(c).getClassName();
}
}
private TSPojo getTSPojo(Class> c) {
// 处理过的不管
Map, TSClass> map = getTSClassMap(c);
if (map.containsKey(c))
return (TSPojo) map.get(c);
TSPojo pojo = new TSPojo(c);
map.put(c, pojo);
if (Object.class.equals(c)) {
return pojo;
}
if (!Object.class.equals(c.getGenericSuperclass()))
pojo.setSuperClass(getClassType(c.getGenericSuperclass(), pojo, null));
for (Field field : c.getDeclaredFields()) {
int mod = field.getModifiers();
if (!Modifier.isStatic(mod) && !Modifier.isTransient(mod)) {
TSField tsField = new TSField();
tsField.setName(field.getName());
tsField.setType(getClassType(field.getGenericType(), pojo, null));
pojo.getFields().add(tsField);
}
}
while (!Object.class.equals(c.getSuperclass())) {
c = c.getSuperclass();
getTSPojo(c);
}
return pojo;
}
protected abstract String getBody(U unit);
}