Skip to content

Commit a6883c0

Browse files
JsonNode as any, inheritance, improved logging
1 parent c33f435 commit a6883c0

File tree

5 files changed

+88
-30
lines changed

5 files changed

+88
-30
lines changed

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/BeanModel.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,23 @@
77
public class BeanModel {
88

99
private final String name;
10+
private final String parent;
1011
private final List<PropertyModel> properties;
1112

12-
public BeanModel(String name, List<PropertyModel> properties) {
13+
public BeanModel(String name, String parent, List<PropertyModel> properties) {
1314
this.name = name;
15+
this.parent = parent;
1416
this.properties = properties;
1517
}
1618

1719
public String getName() {
1820
return name;
1921
}
2022

23+
public String getParent() {
24+
return parent;
25+
}
26+
2127
public List<PropertyModel> getProperties() {
2228
return properties;
2329
}

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/Emitter.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,9 @@ private Emitter(Logger logger, Settings settings, PrintWriter writer) {
1919
}
2020

2121
public static void emit(Logger logger, Settings settings, File outputFile, Model model) {
22-
try {
23-
final PrintWriter printWriter = new PrintWriter(outputFile);
22+
try (PrintWriter printWriter = new PrintWriter(outputFile)) {
2423
final Emitter emitter = new Emitter(logger, settings, printWriter);
2524
emitter.emitModule(model);
26-
printWriter.close();
2725
} catch (FileNotFoundException e) {
2826
throw new RuntimeException(e);
2927
}
@@ -46,7 +44,8 @@ private void emitModule(Model model) {
4644
private void emitInterfaces(Model model) {
4745
for (BeanModel bean : model.getBeans()) {
4846
writeNewLine();
49-
writeIndentedLine("export interface " + bean.getName() + " {");
47+
final String parent = bean.getParent() != null ? " extends " + bean.getParent() : "";
48+
writeIndentedLine("export interface " + bean.getName() + parent + " {");
5049
indent++;
5150
for (PropertyModel property : bean.getProperties()) {
5251
emitProperty(property);

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/Jackson1Parser.java

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11

22
package cz.habarta.typescript.generator;
33

4+
import java.lang.reflect.Type;
45
import java.util.*;
56
import java.util.logging.Logger;
7+
import org.codehaus.jackson.JsonNode;
8+
import org.codehaus.jackson.annotate.JsonSubTypes;
69
import org.codehaus.jackson.map.*;
710
import org.codehaus.jackson.map.ser.*;
811
import org.codehaus.jackson.type.JavaType;
@@ -17,19 +20,57 @@ public Jackson1Parser(Logger logger, Settings settings) {
1720
}
1821

1922
@Override
20-
protected BeanModel parseBean(Class<?> beanClass) {
23+
protected BeanModel parseBean(ClassWithUsage classWithUsage) {
24+
final BeanHelper beanHelper = getBeanHelper(classWithUsage.beanClass);
25+
final List<PropertyModel> properties = new ArrayList<>();
26+
for (BeanPropertyWriter beanPropertyWriter : beanHelper.getProperties()) {
27+
if (!isParentProperty(beanPropertyWriter.getName(), classWithUsage.beanClass)) {
28+
Type propertyType = beanPropertyWriter.getGenericPropertyType();
29+
if (propertyType.equals(JsonNode.class)) {
30+
propertyType = Object.class;
31+
}
32+
properties.add(processTypeAndCreateProperty(beanPropertyWriter.getName(), propertyType, classWithUsage.beanClass));
33+
}
34+
}
35+
36+
final JsonSubTypes jsonSubTypes = classWithUsage.beanClass.getAnnotation(JsonSubTypes.class);
37+
if (jsonSubTypes != null) {
38+
for (JsonSubTypes.Type type : jsonSubTypes.value()) {
39+
addBeanToQueue(new ClassWithUsage(type.value(), "<subClass>", classWithUsage.beanClass));
40+
}
41+
}
42+
final Class<?> superclass = classWithUsage.beanClass.getSuperclass().equals(Object.class) ? null : classWithUsage.beanClass.getSuperclass();
43+
if (superclass != null) {
44+
addBeanToQueue(new ClassWithUsage(superclass, "<superClass>", classWithUsage.beanClass));
45+
}
46+
return new BeanModel(getMappedName(classWithUsage.beanClass), getMappedName(superclass), properties);
47+
}
48+
49+
private boolean isParentProperty(String property, Class<?> cls) {
50+
if (cls.getSuperclass().equals(Object.class)) {
51+
return false;
52+
} else {
53+
final BeanHelper beanHelper = getBeanHelper(cls.getSuperclass());
54+
for (BeanPropertyWriter beanPropertyWriter : beanHelper.getProperties()) {
55+
if (beanPropertyWriter.getName().equals(property)) {
56+
return true;
57+
}
58+
}
59+
return false;
60+
}
61+
}
62+
63+
private BeanHelper getBeanHelper(Class<?> beanClass) {
2164
try {
2265
final SerializationConfig serializationConfig = objectMapper.getSerializationConfig();
2366
final JavaType simpleType = objectMapper.constructType(beanClass);
24-
2567
final JsonSerializer<?> jsonSerializer = BeanSerializerFactory.instance.createSerializer(serializationConfig, simpleType, null);
26-
final BeanHelper beanHelper = new BeanHelper((BeanSerializer) jsonSerializer);
27-
28-
final List<PropertyModel> properties = new ArrayList<>();
29-
for (BeanPropertyWriter beanPropertyWriter : beanHelper.getProperties()) {
30-
properties.add(processTypeAndCreateProperty(beanPropertyWriter.getName(), beanPropertyWriter.getGenericPropertyType()));
68+
if (jsonSerializer instanceof BeanSerializer) {
69+
return new BeanHelper((BeanSerializer) jsonSerializer);
70+
} else {
71+
final String jsonSerializerName = jsonSerializer != null ? jsonSerializer.getClass().getName() : null;
72+
throw new RuntimeException(String.format("Unknown serializer '%s' for class '%s'", jsonSerializerName, beanClass));
3173
}
32-
return new BeanModel(getMappedName(beanClass), properties);
3374
} catch (JsonMappingException e) {
3475
throw new RuntimeException(e);
3576
}

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/ModelParser.java

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public abstract class ModelParser {
1111

1212
protected final Logger logger;
1313
protected final Settings settings;
14-
private Queue<Class<?>> classQueue;
14+
private final Queue<ClassWithUsage> classQueue = new LinkedList<>();
1515

1616
public ModelParser(Logger logger, Settings settings) {
1717
this.logger = logger;
@@ -23,27 +23,35 @@ public Model parseModel(Class<?> cls) {
2323
}
2424

2525
public Model parseModel(List<? extends Class<?>> classes) {
26-
classQueue = new LinkedList<>(classes);
26+
for (Class<?> cls : classes) {
27+
classQueue.add(new ClassWithUsage(cls, null, null));
28+
}
2729
return parseQueue();
2830
}
2931

3032
private Model parseQueue() {
3133
final LinkedHashMap<Class<?>, BeanModel> parsedClasses = new LinkedHashMap<>();
32-
Class<?> cls;
33-
while ((cls = classQueue.poll()) != null) {
34+
ClassWithUsage classWithUsage;
35+
while ((classWithUsage = classQueue.poll()) != null) {
36+
final Class<?> cls = classWithUsage.beanClass;
3437
if (!parsedClasses.containsKey(cls)) {
35-
logger.info(String.format("Parsing '%s'", cls.getName()));
36-
final BeanModel bean = parseBean(cls);
38+
logger.info("Parsing '" + cls.getName() + "'" +
39+
(classWithUsage.usedInClass != null ? " used in '" + classWithUsage.usedInClass.getSimpleName() + "." + classWithUsage.usedInProperty + "'" : ""));
40+
final BeanModel bean = parseBean(classWithUsage);
3741
parsedClasses.put(cls, bean);
3842
}
3943
}
4044
return new Model(new ArrayList<>(parsedClasses.values()));
4145
}
4246

43-
protected abstract BeanModel parseBean(Class<?> beanClass);
47+
protected abstract BeanModel parseBean(ClassWithUsage classWithUsage);
48+
49+
protected void addBeanToQueue(ClassWithUsage classWithUsage) {
50+
classQueue.add(classWithUsage);
51+
}
4452

45-
protected PropertyModel processTypeAndCreateProperty(String name, Type type) {
46-
final TsType originalType = typeFromJava(type);
53+
protected PropertyModel processTypeAndCreateProperty(String name, Type type, Class<?> usedInClass) {
54+
final TsType originalType = typeFromJava(type, name, usedInClass);
4755
final LinkedHashSet<TsType.EnumType> replacedEnums = new LinkedHashSet<>();
4856
final TsType tsType = TsType.replaceEnumsWithStrings(originalType, replacedEnums);
4957
List<String> comments = null;
@@ -58,6 +66,9 @@ protected PropertyModel processTypeAndCreateProperty(String name, Type type) {
5866
}
5967

6068
protected String getMappedName(Class<?> cls) {
69+
if (cls == null) {
70+
return null;
71+
}
6172
final String name = cls.getSimpleName();
6273
if (settings.removeTypeNameSuffix != null && name.endsWith(settings.removeTypeNameSuffix)) {
6374
return name.substring(0, name.length() - settings.removeTypeNameSuffix.length());
@@ -66,12 +77,12 @@ protected String getMappedName(Class<?> cls) {
6677
}
6778
}
6879

69-
private TsType typeFromJava(Type javaType) {
80+
private TsType typeFromJava(Type javaType, String usedInProperty, Class<?> usedInClass) {
7081
if (KnownTypes.containsKey(javaType)) return KnownTypes.get(javaType);
7182
if (javaType instanceof Class) {
7283
final Class<?> javaClass = (Class<?>) javaType;
7384
if (javaClass.isArray()) {
74-
return new TsType.BasicArrayType(typeFromJava(javaClass.getComponentType()));
85+
return new TsType.BasicArrayType(typeFromJava(javaClass.getComponentType(), usedInProperty, usedInClass));
7586
}
7687
if (javaClass.isEnum()) {
7788
@SuppressWarnings("unchecked")
@@ -89,27 +100,28 @@ private TsType typeFromJava(Type javaType) {
89100
return new TsType.IndexedArrayType(TsType.String, TsType.Any);
90101
}
91102
// consider it structural
92-
classQueue.add(javaClass);
103+
classQueue.add(new ClassWithUsage(javaClass, usedInProperty, usedInClass));
93104
return new TsType.StructuralType(getMappedName(javaClass));
94105
}
95106
if (javaType instanceof ParameterizedType) {
96107
final ParameterizedType parameterizedType = (ParameterizedType) javaType;
97108
if (parameterizedType.getRawType() instanceof Class) {
98109
final Class<?> javaClass = (Class<?>) parameterizedType.getRawType();
99110
if (List.class.isAssignableFrom(javaClass)) {
100-
return new TsType.BasicArrayType(typeFromJava(parameterizedType.getActualTypeArguments()[0]));
111+
return new TsType.BasicArrayType(typeFromJava(parameterizedType.getActualTypeArguments()[0], usedInProperty, usedInClass));
101112
}
102113
if (Map.class.isAssignableFrom(javaClass)) {
103-
return new TsType.IndexedArrayType(TsType.String, typeFromJava(parameterizedType.getActualTypeArguments()[1]));
114+
return new TsType.IndexedArrayType(TsType.String, typeFromJava(parameterizedType.getActualTypeArguments()[1], usedInProperty, usedInClass));
104115
}
105116
}
106117
}
107-
logger.warning(String.format("Unsupported type '%s'", javaType));
118+
logger.warning(String.format("Unsupported type '%s' used in '%s.%s'", javaType, usedInClass.getSimpleName(), usedInProperty));
108119
return TsType.Any;
109120
}
110121

111122
private static Map<Type, TsType> getKnownTypes() {
112123
final Map<Type, TsType> knownTypes = new LinkedHashMap<>();
124+
knownTypes.put(Object.class, TsType.Any);
113125
knownTypes.put(Byte.class, TsType.Number);
114126
knownTypes.put(Byte.TYPE, TsType.Number);
115127
knownTypes.put(Short.class, TsType.Number);

typescript-generator-maven-plugin/src/main/java/cz/habarta/typescript/generator/maven/GenerateMojo.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class GenerateMojo extends AbstractMojo {
3333
private List<String> classes;
3434

3535
/**
36-
* Name of generated module.
36+
* Name of generated TypeScript module.
3737
*/
3838
@Parameter
3939
private String moduleName;
@@ -66,7 +66,7 @@ public void execute() {
6666
for (String element : project.getCompileClasspathElements()) {
6767
urls.add(new File(element).toURI().toURL());
6868
}
69-
URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[0]));
69+
URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[0]), Thread.currentThread().getContextClassLoader());
7070

7171
// classes
7272
final List<Class<?>> classList = new ArrayList<>();

0 commit comments

Comments
 (0)