diff --git a/src/main/java/io/github/lonamiwebs/overgram/generator/Generator.java b/src/main/java/io/github/lonamiwebs/overgram/generator/Generator.java index e16b2d6..4a1cda0 100644 --- a/src/main/java/io/github/lonamiwebs/overgram/generator/Generator.java +++ b/src/main/java/io/github/lonamiwebs/overgram/generator/Generator.java @@ -1,18 +1,19 @@ package io.github.lonamiwebs.overgram.generator; +import io.github.lonamiwebs.overgram.parser.TLArg; import io.github.lonamiwebs.overgram.parser.TLObject; import java.io.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class Generator { public static void generateJava( final List types, final List functions, final File abstractsFile, final File typesFile, final File functionsFile) throws IOException { makeParents(abstractsFile, typesFile, functionsFile); + try (final Writer writer = new BufferedWriter(new FileWriter(abstractsFile))) { + writeAbstract(writer, types); + } try (final Writer writer = new BufferedWriter(new FileWriter(typesFile))) { writeCode(writer, "Types", "TLObject", types); } @@ -21,34 +22,86 @@ public class Generator { } } + private static void writeAbstract(final Writer writer, final List objects) throws IOException { + writer.write("package io.github.lonamiwebs.overgram.tl;\n"); + writer.write("@SuppressWarnings(\"unused\")\n"); + writer.write("public class Abstract {\n"); + for (final Map.Entry> nsNames : stringsByNamespace(uniqueTypes(objects)).entrySet()) { + if (!nsNames.getKey().isEmpty()) { + writer.write("public static class "); + writer.write(nsNames.getKey()); + writer.write(" {\n"); + } + for (final String name : nsNames.getValue()) { + writer.write("public static abstract class "); + writer.write(TLObject.toCamelCase(name)); + writer.write(" extends TLObject {}\n"); + } + if (!nsNames.getKey().isEmpty()) { + writer.write("}\n"); + } + } + writer.write("}\n"); + } + private static void writeCode( final Writer writer, final String className, final String extendsName, final List objects) throws IOException { writer.write("package io.github.lonamiwebs.overgram.tl;\n"); + writer.write("import io.github.lonamiwebs.overgram.utils.BinaryReader;\n"); + writer.write("import io.github.lonamiwebs.overgram.utils.BinaryWriter;\n"); + writer.write("import java.util.List;\n"); + writer.write("@SuppressWarnings(\"unused\")\n"); writer.write("public class "); writer.write(className); writer.write(" {\n"); - for (Map.Entry> nsObjects : byNamespace(objects).entrySet()) { + for (final Map.Entry> nsObjects : byNamespace(objects).entrySet()) { if (!nsObjects.getKey().isEmpty()) { writer.write("public static class "); - writer.write(TLObject.toCamelCase(nsObjects.getKey())); + writer.write(nsObjects.getKey()); writer.write(" {\n"); } - for (TLObject object : nsObjects.getValue()) { + for (final TLObject object : nsObjects.getValue()) { writer.write("public static class "); writer.write(TLObject.toCamelCase(object.name)); writer.write(" extends "); writer.write(extendsName); writer.write(" {\n"); + + int n = 0; + for (TLArg arg : object.args) { + if (arg.flags) { + continue; + } + + writer.write("private "); + writer.write(arg.javaType()); + writer.write(" var" + n); + ++n; + writer.write(";\n"); + } + + writer.write("public "); + writer.write(TLObject.toCamelCase(object.name)); + writer.write("() {}\n"); + + // Use the builder pattern because Java is stupid and has no optional named arguments. + // Objects will be created with nothing set and the arguments set with .argument(value). + // TODO + + writer.write("public void serialize(final BinaryWriter writer) {}\n"); + writer.write("public void deserialize(final BinaryReader reader) {}\n"); + writer.write("}\n"); } if (!nsObjects.getKey().isEmpty()) { writer.write("}\n"); } } + writer.write("}\n"); } - private static Map> byNamespace(final List objects) { + private static Map> byNamespace(final Iterable objects) { final Map> result = new HashMap<>(); for (final TLObject object : objects) { result.computeIfAbsent(object.namespace, k -> new ArrayList<>()).add(object); @@ -56,6 +109,34 @@ public class Generator { return result; } + private static Map> stringsByNamespace(final Iterable strings) { + final Map> result = new HashMap<>(); + + String[] tmp; + String namespace; + String name; + for (final String string : strings) { + tmp = string.split("\\."); + if (tmp.length == 1) { + namespace = ""; + name = tmp[0]; + } else { + namespace = tmp[0]; + name = tmp[1]; + } + result.computeIfAbsent(namespace, k -> new ArrayList<>()).add(name); + } + return result; + } + + private static Set uniqueTypes(final List objects) { + final Set result = new HashSet<>(); + for (final TLObject object : objects) { + result.add(object.type); + } + return result; + } + private static void makeParents(final File... files) throws IOException { for (File file : files) { file = file.getAbsoluteFile().getParentFile(); diff --git a/src/main/java/io/github/lonamiwebs/overgram/parser/TLArg.java b/src/main/java/io/github/lonamiwebs/overgram/parser/TLArg.java index b0c97e8..a21e9dd 100644 --- a/src/main/java/io/github/lonamiwebs/overgram/parser/TLArg.java +++ b/src/main/java/io/github/lonamiwebs/overgram/parser/TLArg.java @@ -43,6 +43,73 @@ public class TLArg { return new TLArg(tmp[0], types, flags, flag); } + public String javaType() { + final StringBuilder builder = new StringBuilder(); + + boolean nested = false; + for (final String type : types) { + switch (type) { + case "vector": + case "Vector": + builder.append("List"); + break; + case "int": + if (flag == null && !nested) { + builder.append("int"); + } else { + builder.append("Integer"); + } + break; + case "long": + // TODO handle int128 and int256 properly + case "int128": + case "int256": + if (flag == null && !nested) { + builder.append("long"); + } else { + builder.append("Long"); + } + break; + case "double": + if (flag == null && !nested) { + builder.append("double"); + } else { + builder.append("Double"); + } + break; + case "Bool": + if (flag == null && !nested) { + builder.append("boolean"); + } else { + builder.append("Boolean"); + } + break; + case "true": + builder.append("boolean"); + break; + case "string": + builder.append("String"); + break; + case "bytes": + builder.append("byte[]"); + break; + default: + builder.append("Abstract."); + builder.append(TLObject.toCamelCase(type)); + break; + } + builder.append('<'); + nested = true; + } + + builder.setLength(builder.length() - 1); + for (int i = 1; i < types.size(); ++i) { + builder.append('>'); + } + + return builder.toString(); + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); diff --git a/src/main/java/io/github/lonamiwebs/overgram/parser/TLObject.java b/src/main/java/io/github/lonamiwebs/overgram/parser/TLObject.java index 65007c2..137600b 100644 --- a/src/main/java/io/github/lonamiwebs/overgram/parser/TLObject.java +++ b/src/main/java/io/github/lonamiwebs/overgram/parser/TLObject.java @@ -29,7 +29,10 @@ public class TLObject { } public static String toCamelCase(final String string) { - return string.substring(0, 1).toUpperCase() + string.substring(1); + final int dot = string.lastIndexOf("."); + return string.substring(0, dot + 1) + + string.substring(dot + 1, dot + 2).toUpperCase() + + string.substring(dot + 2); } public static TLObject fromString(String string) { diff --git a/src/main/java/io/github/lonamiwebs/overgram/tl/TLObject.java b/src/main/java/io/github/lonamiwebs/overgram/tl/TLObject.java index 2b6850c..0843655 100644 --- a/src/main/java/io/github/lonamiwebs/overgram/tl/TLObject.java +++ b/src/main/java/io/github/lonamiwebs/overgram/tl/TLObject.java @@ -1,5 +1,9 @@ package io.github.lonamiwebs.overgram.tl; -public abstract class TLObject { +import io.github.lonamiwebs.overgram.utils.BinaryReader; +import io.github.lonamiwebs.overgram.utils.BinaryWriter; +public abstract class TLObject { + public abstract void serialize(final BinaryWriter writer); + public abstract void deserialize(final BinaryReader reader); } diff --git a/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryReader.java b/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryReader.java new file mode 100644 index 0000000..3e761a0 --- /dev/null +++ b/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryReader.java @@ -0,0 +1,4 @@ +package io.github.lonamiwebs.overgram.utils; + +public class BinaryReader { +} diff --git a/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryWriter.java b/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryWriter.java new file mode 100644 index 0000000..d59b8db --- /dev/null +++ b/src/main/java/io/github/lonamiwebs/overgram/utils/BinaryWriter.java @@ -0,0 +1,5 @@ +package io.github.lonamiwebs.overgram.utils; + + +public class BinaryWriter { +}