package im.actor.generator.generators; import im.actor.generator.FileGenerator; import im.actor.generator.scheme.*; import java.io.IOException; /** * Created by ex3ndr on 15.11.14. */ public class ProtoBufGenerator { public static void generate(SchemeDefinition definition, String fileName) throws IOException { FileGenerator generator = new FileGenerator(fileName); for (SchemeSection section : definition.getSections()) { generator.appendLn("//////////////////////////////////////////////////////"); generator.appendLn("// " + section.getName()); generator.appendLn("//////////////////////////////////////////////////////"); for (String s : section.getDocs()) { generator.appendLn("//" + s); } generator.appendLn(); for (SchemeRecord record : section.getRecords()) { if (record instanceof SchemeEnum) { SchemeEnum sEnum = (SchemeEnum) record; generator.appendLn("enum " + sEnum.getName() + " {"); generator.increaseDepth(); for (SchemeEnum.Record enrec : sEnum.getRecord()) { generator.appendLn(enrec.getName().toUpperCase() + " = " + enrec.getId() + ";"); } generator.decreaseDepth(); generator.appendLn("}"); generator.appendLn(); } else if (record instanceof SchemeStruct) { SchemeStruct sEnum = (SchemeStruct) record; for (SchemeDoc d : sEnum.getDocs()) { if (d instanceof SchemeDocComment) { generator.appendLn("// " + ((SchemeDocComment) d).getText()); } else if (d instanceof SchemeDocParameter) { generator.appendLn("// " + ((SchemeDocParameter) d).getArgument() + " " + ((SchemeDocParameter) d).getDescription()); } } generator.appendLn("message " + sEnum.getName() + " {"); generator.increaseDepth(); appendContents(definition, sEnum, generator); generator.decreaseDepth(); generator.appendLn("}"); generator.appendLn(); } else if (record instanceof SchemeUpdate) { SchemeUpdate update = (SchemeUpdate) record; generator.appendLn("// API#0x" + toHex(update.getHeader())); for (SchemeDoc d : update.getDocs()) { if (d instanceof SchemeDocComment) { generator.appendLn("// " + ((SchemeDocComment) d).getText()); } else if (d instanceof SchemeDocParameter) { generator.appendLn("// " + ((SchemeDocParameter) d).getArgument() + " " + ((SchemeDocParameter) d).getDescription()); } } generator.appendLn("message Update" + update.getName() + " {"); generator.increaseDepth(); appendContents(definition, update, generator); generator.decreaseDepth(); generator.appendLn("}"); generator.appendLn(); } else if (record instanceof SchemeUpdateBox) { SchemeUpdateBox update = (SchemeUpdateBox) record; generator.appendLn("// API#0x" + toHex(update.getHeader())); for (SchemeDoc d : update.getDocs()) { if (d instanceof SchemeDocComment) { generator.appendLn("// " + ((SchemeDocComment) d).getText()); } else if (d instanceof SchemeDocParameter) { generator.appendLn("// " + ((SchemeDocParameter) d).getArgument() + " " + ((SchemeDocParameter) d).getDescription()); } } generator.appendLn("message Update" + update.getName() + " {"); generator.increaseDepth(); appendContents(definition, update, generator); generator.decreaseDepth(); generator.appendLn("}"); generator.appendLn(); } else if (record instanceof SchemeResponse) { SchemeResponse update = (SchemeResponse) record; generator.appendLn("// API#0x" + toHex(update.getHeader())); for (SchemeDoc d : update.getDocs()) { if (d instanceof SchemeDocComment) { generator.appendLn("// " + ((SchemeDocComment) d).getText()); } else if (d instanceof SchemeDocParameter) { generator.appendLn("// " + ((SchemeDocParameter) d).getArgument() + " " + ((SchemeDocParameter) d).getDescription()); } } generator.appendLn("message Response" + update.getName() + " {"); generator.increaseDepth(); appendContents(definition, update, generator); generator.decreaseDepth(); generator.appendLn("}"); generator.appendLn(); } else if (record instanceof SchemeRpc) { SchemeRpc rpc = (SchemeRpc) record; generator.appendLn("// API#0x" + toHex(rpc.getHeader())); if (rpc.getResponse() instanceof SchemeRpc.RefResponse) { SchemeRpc.RefResponse resp = (SchemeRpc.RefResponse) rpc.getResponse(); generator.appendLn("// Response" + resp.getName()); } else { generator.appendLn("// " + responseName(rpc.getName())); } for (SchemeDoc d : rpc.getDocs()) { if (d instanceof SchemeDocComment) { generator.appendLn("// " + ((SchemeDocComment) d).getText()); } else if (d instanceof SchemeDocParameter) { generator.appendLn("// " + ((SchemeDocParameter) d).getArgument() + " " + ((SchemeDocParameter) d).getDescription()); } } generator.appendLn("message " + requestName(rpc.getName()) + " {"); generator.increaseDepth(); appendContents(definition, rpc, generator); generator.decreaseDepth(); generator.appendLn("}"); generator.appendLn(); if (rpc.getResponse() instanceof SchemeRpc.AnonymousResponse) { SchemeRpc.AnonymousResponse resp = (SchemeRpc.AnonymousResponse) rpc.getResponse(); generator.appendLn("// API#0x" + toHex(resp.getResponse().getHeader())); generator.appendLn("message " + responseName(rpc.getName()) + " {"); generator.increaseDepth(); appendContents(definition, resp.getResponse(), generator); generator.decreaseDepth(); generator.appendLn("}"); generator.appendLn(); } } } } generator.close(); } private static void appendContents(SchemeDefinition definition, SchemeContainer container, FileGenerator generator) throws IOException { for (SchemeAttribute enrec : container.getAttributes()) { generator.appendLn(getType(definition, enrec.getType(), true) + " " + enrec.getName() + " = " + enrec.getId() + ";"); } } private static String getType(SchemeDefinition definition, SchemeType attribute, boolean isFirst) throws IOException { if (attribute instanceof SchemePrimitiveType) { return (isFirst ? "required " : "") + ((SchemePrimitiveType) attribute).getName(); } else if (attribute instanceof SchemeOptionalType) { return "optional " + getType(definition, ((SchemeOptionalType) attribute).getType(), false); } else if (attribute instanceof SchemeListType) { return "repeated " + getType(definition, ((SchemeListType) attribute).getType(), false); } else if (attribute instanceof SchemeStructType) { return (isFirst ? "required " : "") + ((SchemeStructType) attribute).getType(); } else if (attribute instanceof SchemeEnumType) { return (isFirst ? "required " : "") + ((SchemeEnumType) attribute).getName(); } else if (attribute instanceof SchemeAliasType) { return getType(definition, definition.getAliases().get(((SchemeAliasType) attribute).getName()), isFirst); } else if (attribute instanceof SchemeTraitType) { return (isFirst ? "required bytes" : "bytes"); } else { throw new IOException(); } } private static String toHex(int val) { String res = Integer.toHexString(val); if (res.length() < 2) { res = "0" + res; } return res.toUpperCase(); } private static String requestName(String name) { if (name.startsWith("Request")) { return name; } else { return "Request" + name; } } private static String responseName(String name) { if (name.startsWith("Request")) { return "Response" + name.substring("Request".length()); } else { return "Response" + name; } } }