diff --git a/api-generator/pom.xml b/api-spec-generator/pom.xml similarity index 72% rename from api-generator/pom.xml rename to api-spec-generator/pom.xml index 88a8f65..e632ed3 100644 --- a/api-generator/pom.xml +++ b/api-spec-generator/pom.xml @@ -9,7 +9,7 @@ 1.0.0.0 - api-generator + api-spec-generator @@ -27,13 +27,18 @@ 3.1.0 - generate-js-client - generate-sources + generate-spec + compile java - ru.kirillius.XCP.ApiGenerator.JavascriptClientGenerator + ru.kirillius.XCP.ApiGenerator.SpecGenerator + + rpc/src/main/java + ru.kirillius.XCP.RPC.Services + target/generated-sources/api.spec.json + diff --git a/api-spec-generator/src/main/java/ru/kirillius/XCP/ApiGenerator/SpecGenerator.java b/api-spec-generator/src/main/java/ru/kirillius/XCP/ApiGenerator/SpecGenerator.java new file mode 100644 index 0000000..07d6340 --- /dev/null +++ b/api-spec-generator/src/main/java/ru/kirillius/XCP/ApiGenerator/SpecGenerator.java @@ -0,0 +1,125 @@ +package ru.kirillius.XCP.ApiGenerator; + +import lombok.SneakyThrows; +import ru.kirillius.XCP.RPC.JSONRPC.JsonRpcMethod; +import ru.kirillius.XCP.RPC.JSONRPC.JsonRpcService; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.node.ArrayNode; +import tools.jackson.databind.node.JsonNodeFactory; +import tools.jackson.databind.node.ObjectNode; + +import java.io.*; +import java.util.Collection; +import java.util.Objects; +import java.util.regex.Pattern; + +public class SpecGenerator { + /** + * Args: + * 1 - path to find classes + * 2 - search in package + * 3 - output spec file path + * + * @param args + * @throws IOException + */ + public static void main(String[] args) throws IOException { + var generator = new SpecGenerator( + new File(args[0]), + args[1], + new File(args[2]) + ); + + generator.generate(); + generator.writeSpecs(); + } + + private final File scanDir; + private final String packageName; + private final File outputFile; + + public SpecGenerator(File scanDir, String packageName, File outputFile) { + this.scanDir = scanDir; + this.packageName = packageName; + this.outputFile = outputFile; + } + + private final ObjectNode specs = JsonNodeFactory.instance.objectNode(); + + @SneakyThrows + public void generate() { + specs.removeAll(); + var scanPath = new File(scanDir, packageName.replaceAll(Pattern.quote("."), "/")); + for (var file : Objects.requireNonNull(scanPath.listFiles())) { + if (!file.getName().endsWith(".java") || file.getName().contains("$")) { + continue; + } + var className = packageName + '.' + file.getName(); + className = className.substring(0, className.length() - ".java".length()); + + var cls = Class.forName(className); + + if (!JsonRpcService.class.isAssignableFrom(cls)) { + continue; + } + + var classSpecs = specs.putObject(cls.getSimpleName()); + classSpecs.put("name", cls.getSimpleName()); + var methods = classSpecs.putArray("methods"); + + for (var method : cls.getDeclaredMethods()) { + var descriptor = method.getAnnotation(JsonRpcMethod.class); + if (descriptor == null) { + continue; + } + var methodSpecs = methods.addObject(); + methodSpecs.put("name", method.getName()); + methodSpecs.put("description", descriptor.description()); + methodSpecs.put("return", getTypeName(descriptor.returnType())); + methodSpecs.put("accessLevel", descriptor.accessLevel().name()); + + var params = methodSpecs.putArray("params"); + + for (var parameter : descriptor.parameters()) { + var paramSpecs = params.addObject(); + paramSpecs.put("name", parameter.name()); + paramSpecs.put("type", getTypeName(parameter.type())); + paramSpecs.put("description", parameter.description()); + paramSpecs.put("optional", parameter.optional()); + } + + methodSpecs.put("return", getTypeName(descriptor.returnType())); + + } + + } + + } + + public void writeSpecs() throws IOException { + outputFile.getParentFile().mkdirs(); + try (var stream = new FileOutputStream(outputFile)) { + var mapper = new ObjectMapper(); + mapper.writerWithDefaultPrettyPrinter().writeValue(stream, specs); + } + } + + private static String getTypeName(Class type) { + if (type == null) return "unknown"; + if (type == boolean.class) return "boolean"; + if (type == int.class || type == long.class) return "number"; + if (type == String.class) return "string"; + if (type == void.class || type == Void.class) return "void"; + + if (type.isArray() || Collection.class.isAssignableFrom(type) || type == ArrayNode.class) { + return "Array"; + } + + if (JsonNode.class.isAssignableFrom(type)) { + return "Object"; + } + + return type.getSimpleName(); + } +} diff --git a/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/GroupRepositoryImpl.java b/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/GroupRepositoryImpl.java index b87620f..77a9ca0 100644 --- a/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/GroupRepositoryImpl.java +++ b/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/GroupRepositoryImpl.java @@ -8,7 +8,7 @@ import org.hibernate.annotations.UuidGenerator; import ru.kirillius.XCP.Commons.StreamHandler; import ru.kirillius.XCP.Persistence.Entities.Group; import ru.kirillius.XCP.Persistence.*; -import ru.kirillius.XCP.Serialization.SerializationUtils; +import tools.jackson.databind.node.JsonNodeFactory; import tools.jackson.databind.node.ObjectNode; import java.io.IOException; @@ -157,7 +157,7 @@ public class GroupRepositoryImpl extends AbstractNodeRepository implement @JsonProperty @Getter @Setter - private ObjectNode properties = SerializationUtils.EmptyObject(); + private ObjectNode properties = JsonNodeFactory.instance.objectNode(); @JsonIgnore @ManyToMany(fetch = FetchType.EAGER) diff --git a/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/InputRepositoryImpl.java b/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/InputRepositoryImpl.java index 2d77e49..cc6546d 100644 --- a/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/InputRepositoryImpl.java +++ b/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/InputRepositoryImpl.java @@ -11,9 +11,9 @@ import ru.kirillius.XCP.Persistence.Entities.Group; import ru.kirillius.XCP.Persistence.Entities.Input; import ru.kirillius.XCP.Persistence.*; import ru.kirillius.XCP.Serialization.PollSettingsConverter; -import ru.kirillius.XCP.Serialization.SerializationUtils; import ru.kirillius.XCP.Serialization.ValueTransformationChainConverter; import tools.jackson.databind.annotation.JsonDeserialize; +import tools.jackson.databind.node.JsonNodeFactory; import tools.jackson.databind.node.ObjectNode; import java.util.HashSet; @@ -110,7 +110,7 @@ public class InputRepositoryImpl extends AbstractNodeRepository implement @JsonProperty @Getter @Setter - private ObjectNode properties = SerializationUtils.EmptyObject(); + private ObjectNode properties = JsonNodeFactory.instance.objectNode(); @JsonIgnore @ManyToMany(fetch = FetchType.EAGER) diff --git a/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/OutputRepositoryImpl.java b/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/OutputRepositoryImpl.java index aa85291..a73c67f 100644 --- a/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/OutputRepositoryImpl.java +++ b/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/OutputRepositoryImpl.java @@ -9,8 +9,8 @@ import ru.kirillius.XCP.Data.ValueTransformationChain; import ru.kirillius.XCP.Persistence.Entities.Group; import ru.kirillius.XCP.Persistence.Entities.Output; import ru.kirillius.XCP.Persistence.*; -import ru.kirillius.XCP.Serialization.SerializationUtils; import ru.kirillius.XCP.Serialization.ValueTransformationChainConverter; +import tools.jackson.databind.node.JsonNodeFactory; import tools.jackson.databind.node.ObjectNode; import java.util.HashSet; @@ -106,7 +106,7 @@ public class OutputRepositoryImpl extends AbstractNodeRepository impleme @JsonProperty @Getter @Setter - private ObjectNode properties = SerializationUtils.EmptyObject(); + private ObjectNode properties = JsonNodeFactory.instance.objectNode(); @JsonIgnore @ManyToMany(fetch = FetchType.EAGER) diff --git a/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/UserRepositoryImpl.java b/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/UserRepositoryImpl.java index e6fc0da..76b79b7 100644 --- a/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/UserRepositoryImpl.java +++ b/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/UserRepositoryImpl.java @@ -12,7 +12,7 @@ import ru.kirillius.XCP.Persistence.Entities.User; import ru.kirillius.XCP.Persistence.EntityImplementation; import ru.kirillius.XCP.Persistence.RepositoryServiceImpl; import ru.kirillius.XCP.Security.UserRole; -import ru.kirillius.XCP.Serialization.SerializationUtils; +import tools.jackson.databind.node.JsonNodeFactory; import tools.jackson.databind.node.ObjectNode; import java.io.IOException; @@ -80,7 +80,7 @@ public class UserRepositoryImpl extends AbstractRepository implements User @Getter @Setter @JsonProperty - private ObjectNode values = SerializationUtils.EmptyObject(); + private ObjectNode values = JsonNodeFactory.instance.objectNode(); @Override public void setPassword(String password) { diff --git a/pom.xml b/pom.xml index 08da4ad..35e7c07 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ pom api - api-generator + api-spec-generator database core rpc