com.seeq.utilities.SeeqNamesGenerator Maven / Gradle / Ivy
The newest version!
package com.seeq.utilities;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.annotations.Nullable;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import lombok.RequiredArgsConstructor;
/**
* Converts the strings in the SeeqNames interface into a JSON file.
*
* Note: The resulting file is used to codegen the same strings into various programming languages
*/
@SuppressWarnings("unchecked") // JSONSimple objects extend raw typed HashMap and ArrayList
final class SeeqNamesGenerator {
private static final String SEEQ_NAMES_CANONICAL = "com.seeq.utilities.SeeqNames";
private static final String OUTPUT_FILE_NAME = "SeeqNames.json";
private SeeqNamesGenerator() {}
@RequiredArgsConstructor
private static class Field {
private final String key;
private final T value;
private final SeeqNamesGeneratorOptions options;
}
private static class GroupedStrings {
private static final String JSON_FIELDS = "fields";
private static final String JSON_FIELD_KEY = "key";
private static final String JSON_FIELD_VALUE = "value";
private static final String JSON_INTERFACE_NAME = "interfaceName";
private static final String JSON_SUB_INTERFACES = "subInterfaces";
private static final String JSON_OPTIONS = "options";
private static final String JSON_OPTION_DEPRECATED = "deprecatedWithMessage";
private static final String JSON_OPTION_DEPRECATED_MESSAGE = "Deprecated. See SeeqNames.java for more info";
private static final String JSON_OPTION_SKIP = "skipLanguages";
private static final String JSON_OPTION_SKIP_CSHARP = "csharp";
private static final String JSON_OPTION_SKIP_JAVA = "java";
private static final String JSON_OPTION_SKIP_JAVASCRIPT = "javascript";
private static final String JSON_OPTION_SKIP_PYTHON = "python";
private static final String JSON_OPTION_SKIP_TYPESCRIPT = "typescript";
private final String name;
private final List> fields = new ArrayList<>();
private final List subGroups = new ArrayList<>();
public GroupedStrings(String name) {
this.name = name;
}
public void addField(Field field) {
this.fields.add(field);
}
public void addGroup(GroupedStrings group) {
this.subGroups.add(group);
}
public JSONArray toJson() {
JSONArray jsonGroups = new JSONArray();
for (GroupedStrings group : this.subGroups) {
jsonGroups.add(this.toJson(group, new JSONObject()));
}
return jsonGroups;
}
private JSONObject toJson(GroupedStrings group, JSONObject jsonGroup) {
jsonGroup.put(JSON_INTERFACE_NAME, group.name);
JSONArray jsonFields = new JSONArray();
for (Field field : group.fields) {
JSONObject jsonField = new JSONObject();
jsonField.put(JSON_FIELD_KEY, field.key);
jsonField.put(JSON_FIELD_VALUE, field.value);
JSONObject jsonOptions = new JSONObject();
if (field.options != null) {
// Check for skipped languages
JSONArray jsonSkipLanguages = new JSONArray();
if (field.options.noJava()) {jsonSkipLanguages.add(JSON_OPTION_SKIP_JAVA);}
if (field.options.noCSharp()) {jsonSkipLanguages.add(JSON_OPTION_SKIP_CSHARP);}
if (field.options.noJavascript()) {jsonSkipLanguages.add(JSON_OPTION_SKIP_JAVASCRIPT);}
if (field.options.noPython()) {jsonSkipLanguages.add(JSON_OPTION_SKIP_PYTHON);}
if (field.options.noTypescript()) {jsonSkipLanguages.add(JSON_OPTION_SKIP_TYPESCRIPT);}
if (!jsonSkipLanguages.isEmpty()) {jsonOptions.put(JSON_OPTION_SKIP, jsonSkipLanguages);}
if (field.options.deprecated()) {
jsonOptions.put(JSON_OPTION_DEPRECATED, JSON_OPTION_DEPRECATED_MESSAGE);
}
}
if (!jsonOptions.isEmpty()) {jsonField.put(JSON_OPTIONS, jsonOptions);}
jsonFields.add(jsonField);
}
jsonGroup.put(JSON_FIELDS, jsonFields);
JSONArray jsonSubInterfaces = new JSONArray();
for (GroupedStrings subGroup : group.subGroups) {
JSONObject jsonSubGroup = new JSONObject();
jsonSubInterfaces.add(this.toJson(subGroup, jsonSubGroup));
}
if (!jsonSubInterfaces.isEmpty()) {
jsonGroup.put(JSON_SUB_INTERFACES, jsonSubInterfaces);
}
return jsonGroup;
}
}
private static void parseInterface(Class> rootClass, GroupedStrings parentInterface) {
java.lang.reflect.Field[] fields = rootClass.getDeclaredFields();
for (java.lang.reflect.Field field : fields) {
try {
String key = field.getName();
// TODO CRAB-18691 If needed, expand to generate shared list of string constants from SeeqNames.java
if (!(field.get(null) instanceof String)) {continue;}
String value = (String) field.get(null);
SeeqNamesGeneratorOptions options = getSeeqNamesGeneratorOptions(field);
parentInterface.addField(new Field<>(key, value, options));
} catch (IllegalAccessException e) {
System.err.println("Could not get value for field: " + field.getName());
}
}
Class>[] subClasses = rootClass.getClasses();
for (Class> subClass : subClasses) {
GroupedStrings subGroup = new GroupedStrings(subClass.getSimpleName());
parseInterface(subClass, subGroup);
parentInterface.addGroup(subGroup);
}
}
@Nullable
private static SeeqNamesGeneratorOptions getSeeqNamesGeneratorOptions(java.lang.reflect.Field field) {
boolean isDeprecated = false;
SeeqNamesGeneratorOptions options = null;
Annotation[] annotations = field.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof SeeqNamesGeneratorOptions) {
options = (SeeqNamesGeneratorOptions) annotation;
}
}
return options;
}
public static void main(String[] args) {
final Path BASE_PATH =
new File(SeeqNamesGenerator.class.getProtectionDomain().getCodeSource().getLocation().getFile())
.toPath() // seeq-utilities/target/classes/java/main
.getParent() // seeq-utilities/target/classes/java
.getParent() // seeq-utilities/target/classes
.getParent(); // seeq-utilities/target
System.out.println("SeeqNamesGenerator running in " + BASE_PATH.toString());
try {
Class> c = Class.forName(SEEQ_NAMES_CANONICAL);
GroupedStrings root = new GroupedStrings(c.getSimpleName());
parseInterface(c, root);
JSONArray groups = root.toJson();
Path outputPath = BASE_PATH.resolve(OUTPUT_FILE_NAME);
try (FileWriter file = new FileWriter(outputPath.toString())) {
file.write(groups.toJSONString());
System.out.println("SeeqNamesGenerator done, wrote to " + outputPath.toString());
} catch (IOException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}