package io.github.lonamiwebs.overgram.parser; import java.util.ArrayList; import java.util.List; public class TLArg { public final String name; public final List types; public final boolean flags; public final Flag flag; public final boolean genericDefinition; private TLArg(final String name, final List types, final boolean flags, final Flag flag, final boolean genericDefinition) { this.name = name; this.types = types; this.flags = flags; this.flag = flag; this.genericDefinition = genericDefinition; } public static TLArg fromString(String string) { final String[] tmp = string.split(":"); boolean genericDefinition = false; if (tmp[1].equals("Type}")) { tmp[1] = tmp[1].substring(0, tmp[1].length() - 1); tmp[0] = tmp[0].substring(1); genericDefinition = true; } boolean flags = false; if (tmp[1].equals("#")) { tmp[1] = ""; flags = true; } Flag flag = null; final int flagIndex = tmp[1].indexOf('?'); if (flagIndex != -1) { flag = Flag.fromString(tmp[1].substring(0, flagIndex)); tmp[1] = tmp[1].substring(flagIndex + 1); } final List types = new ArrayList<>(2); int angleBracket; while ((angleBracket = tmp[1].indexOf("<")) != -1) { types.add(tmp[1].substring(0, angleBracket)); tmp[1] = tmp[1].substring(angleBracket + 1, tmp[1].length() - 1); } types.add(tmp[1]); return new TLArg(tmp[0], types, flags, flag, genericDefinition); } public String javaType() { final StringBuilder builder = new StringBuilder(); boolean nested = false; for (final String type : types) { if (type.startsWith("!")) { if (nested) { throw new UnsupportedOperationException(); } return "TLObject"; } 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(); } public String javaSetCheck() { return types.size() == 1 && types.get(0).equals("true") ? "" : " != null"; } public static String toCamelCase(final String string) { final StringBuilder result = new StringBuilder(string.length()); result.append(Character.toLowerCase(string.charAt(0))); boolean upperNext = false; for (int i = 1; i < string.length(); ++i) { final char c = string.charAt(i); if (c == '_') { upperNext = true; } else if (upperNext) { upperNext = false; result.append(Character.toUpperCase(c)); } else { result.append(Character.toLowerCase(c)); } } return result.toString(); } public String javaName() { switch (name) { case "lat": return "latitude"; // not reserved but consistent case "long": return "longitude"; case "static": return "isStatic"; case "public": return "isPublic"; case "private": return "isPrivate"; case "final": return "last"; default: return toCamelCase(name); } } @Override public String toString() { final StringBuilder builder = new StringBuilder(); if (genericDefinition) { builder.append('{'); } builder.append(name); builder.append(':'); if (flag != null) { builder.append(flag.toString()); } if (flags) { builder.append('#'); } else { for (final String type : types) { builder.append(type); builder.append('<'); } builder.setLength(builder.length() - 1); for (int i = 1; i < types.size(); ++i) { builder.append('>'); } } if (genericDefinition) { builder.append('}'); } return builder.toString(); } public static final class Flag { public final String flagName; public final int flagIndex; private Flag(final String flagName, final int flagIndex) { this.flagName = flagName; this.flagIndex = flagIndex; } private static Flag fromString(final String string) { final String[] tmp = string.split("\\."); return new Flag(tmp[0], Integer.parseInt(tmp[1])); } @Override public String toString() { return flagName + "." + flagIndex + "?"; } } }