From 094ba8cfe9d3632823401a0b06c8fe4a4bc7b9de Mon Sep 17 00:00:00 2001 From: godotg Date: Sun, 3 Dec 2023 19:02:45 +0800 Subject: [PATCH] ref[protobuf]: refactor protobuf generate --- .../serializer/protobuf/GeneratePbUtils.java | 142 ++++++++++-------- .../protocol/serializer/protobuf/PbType.java | 6 +- 2 files changed, 79 insertions(+), 69 deletions(-) diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/protobuf/GeneratePbUtils.java b/protocol/src/main/java/com/zfoo/protocol/serializer/protobuf/GeneratePbUtils.java index b29f3747..2fb96342 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/protobuf/GeneratePbUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/protobuf/GeneratePbUtils.java @@ -67,11 +67,6 @@ public abstract class GeneratePbUtils { public static void generate(PbGenerateOperation buildOption, List protos) { - var allProtos = new HashMap(); - for (var proto : protos) { - allProtos.put(proto.getName(), proto); - } - var messageOutputPath = buildOption.getOutputPath() + File.separator; if (StringUtils.isNotEmpty(buildOption.getJavaPackage())) { messageOutputPath = messageOutputPath + buildOption.getJavaPackage().replaceAll(StringUtils.PERIOD_REGEX, "/"); @@ -83,7 +78,7 @@ public abstract class GeneratePbUtils { continue; } for (var pbMessage : pbMessages) { - var code = buildMessage(proto, pbMessage, 1, null); + var code = buildMessage(buildOption, protos, proto, pbMessage); var filePath = StringUtils.format("{}/{}/{}.java", messageOutputPath, proto.getName(), pbMessage.getName()); FileUtils.writeStringToFile(new File(filePath), code, false); } @@ -91,10 +86,10 @@ public abstract class GeneratePbUtils { } // ------------------------------------------------------------------------------------------------------------- - public static String getJavaType(PbField field) { - String type = field.getType(); - if (field instanceof PbMapField) { - var mapField = (PbMapField) field; + public static String getJavaType(PbField pbField) { + String type = pbField.getType(); + if (pbField instanceof PbMapField) { + var mapField = (PbMapField) pbField; type = StringUtils.format("Map<{}, {}>", getBoxJavaType(mapField.getKey().value()), getBoxJavaType(mapField.getValue())); return type; } @@ -110,8 +105,8 @@ public abstract class GeneratePbUtils { return javaType.getTypeString(); } - private static String getBoxJavaType(PbField field) { - return getBoxJavaType(field.getType()); + private static String getBoxJavaType(PbField pbField) { + return getBoxJavaType(pbField.getType()); } private static String getBoxJavaType(String type) { @@ -123,22 +118,55 @@ public abstract class GeneratePbUtils { return javaType.getBoxedType(); } - private static void buildMsgImps(PbMessage msg, List tmp, Set imps) { - var fields = msg.getFields(); - if (CollectionUtils.isNotEmpty(fields)) { - for (var field : fields) { - getJavaType(field); - tmp.add(field); + private static Set buildMessageImports(PbGenerateOperation buildOption, List protos, Proto proto, PbMessage pbMessage) { + var imports = new HashSet(); + var pbFields = pbMessage.getFields(); + if (CollectionUtils.isEmpty(pbFields)) { + return imports; + } + + for (var pbField : pbFields) { + if (pbField instanceof PbMapField) { + imports.add(Map.class.getName()); + continue; + } + + if (pbField.getCardinality() == PbField.Cardinality.REPEATED) { + imports.add(List.class.getName()); + } + + buildImports(buildOption, protos, proto, pbField.getType(), imports); + } + return imports; + } + + private static void buildImports(PbGenerateOperation buildOption, List protos, Proto proto, String fieldType, Set imports) { + // 基本数据类型不需要导入 + var typeProtobuf = PbType.typeOfProtobuf(fieldType); + if (typeProtobuf != null) { + return; + } + + // 属于同一个包不需要导入 + if (proto.getPbMessages().stream().anyMatch(it -> it.getName().equals(fieldType))) { + return; + } + + // 遍历其它的proto找到需要导入的类 + for (var pt : protos) { + for (var msg : pt.getPbMessages()) { + if (msg.getName().equals(fieldType)) { + if (StringUtils.isBlank(buildOption.getJavaPackage())) { + imports.add(StringUtils.format("{}.{}", pt.getName(), fieldType)); + } else { + imports.add(StringUtils.format("{}.{}.{}", buildOption.getJavaPackage(), pt.getName(), fieldType)); + } + return; + } } } - for (int i = 0; i < tmp.size(); i++) { - if (tmp.get(i) instanceof PbMapField) { - imps.add(Map.class.getName()); - } else if (tmp.get(i).getCardinality() == PbField.Cardinality.REPEATED) { - imps.add(List.class.getName()); - } - } + throw new RuntimeException(StringUtils.format("not found type:[{}] in proto:[{}]", fieldType, proto.getName())); } private static void buildDocComment(StringBuilder builder, PbMessage msg) { @@ -157,65 +185,49 @@ public abstract class GeneratePbUtils { pbField.getComments().forEach(it -> builder.append(TAB).append(StringUtils.format("// {}", it)).append(LS)); } - private static String getJavaPackage(Proto proto) { - if (CollectionUtils.isEmpty(proto.getOptions())) { - return StringUtils.EMPTY; - } - for (PbOption option : proto.getOptions()) { - if ("java_package".equalsIgnoreCase(option.getName())) { - return option.getValue(); - } - } - return StringUtils.EMPTY; - } - - public static String buildMessage(Proto proto, PbMessage msg, int indent, Map defineMsgs) { - var tmp = new ArrayList(); - var imports = new HashSet(); + public static String buildMessage(PbGenerateOperation buildOption, List protos, Proto proto, PbMessage pbMessage) { var builder = new StringBuilder(); - buildMsgImps(msg, tmp, imports); - - List fields = new ArrayList<>(); - tmp.stream().sorted(Comparator.comparingInt(PbField::getTag)) - .forEach(fields::add); - - imports.stream().sorted(Comparator.naturalOrder()) + // import other class + var imports = buildMessageImports(buildOption, protos, proto, pbMessage); + imports.stream() + .sorted(Comparator.naturalOrder()) .forEach(it -> builder.append(StringUtils.format("import {};", it)).append(LS)); - buildDocComment(builder, msg); - builder.append(StringUtils.format("public class {} {", msg.getName())).append(LS); + buildDocComment(builder, pbMessage); + builder.append(StringUtils.format("public class {} {", pbMessage.getName())).append(LS); - int size = fields.size(); + var pbFields = pbMessage.getFields() + .stream() + .sorted((a, b) -> a.getTag() - b.getTag()) + .toList(); var builderMethod = new StringBuilder(); - for (int i = 0; i < size; i++) { - PbField f = fields.get(i); - - buildFieldComment(builder, f); - String type = getJavaType(f); - String name = f.getName(); - if (f.getCardinality() == PbField.Cardinality.REPEATED) { - String boxedTypeName = getBoxJavaType(f); + for (var pbField : pbFields) { + buildFieldComment(builder, pbField); + String type = getJavaType(pbField); + String name = pbField.getName(); + if (pbField.getCardinality() == PbField.Cardinality.REPEATED) { + String boxedTypeName = getBoxJavaType(pbField); type = "List<" + boxedTypeName + ">"; } builder.append(TAB).append(StringUtils.format("private {} {};", type, name)).append(LS); String getMethod; - if (!"bool".equalsIgnoreCase(f.getType())) { - getMethod = StringUtils.format("get{}", StringUtils.capitalize(f.getName())); + if (!"bool".equalsIgnoreCase(pbField.getType())) { + getMethod = StringUtils.format("get{}", StringUtils.capitalize(pbField.getName())); } else { - getMethod = StringUtils.format("is{}", StringUtils.capitalize(f.getName())); + getMethod = StringUtils.format("is{}", StringUtils.capitalize(pbField.getName())); } builderMethod.append(TAB).append(StringUtils.format("public {} {}() {", type, getMethod)).append(LS); - builderMethod.append(TAB + TAB).append(StringUtils.format("return {};", f.getName())).append(LS); + builderMethod.append(TAB + TAB).append(StringUtils.format("return {};", pbField.getName())).append(LS); builderMethod.append(TAB).append("}").append(LS); - String setMethod = StringUtils.format("set{}", StringUtils.capitalize(f.getName())); - builderMethod.append(TAB).append(StringUtils.format("public void {}({} {}) {", setMethod, type, f.getName())).append(LS); - builderMethod.append(TAB + TAB).append(StringUtils.format("this.{} = {};", f.getName(), f.getName())).append(LS); + String setMethod = StringUtils.format("set{}", StringUtils.capitalize(pbField.getName())); + builderMethod.append(TAB).append(StringUtils.format("public void {}({} {}) {", setMethod, type, pbField.getName())).append(LS); + builderMethod.append(TAB + TAB).append(StringUtils.format("this.{} = {};", pbField.getName(), pbField.getName())).append(LS); builderMethod.append(TAB).append("}").append(LS); } diff --git a/protocol/src/main/java/com/zfoo/protocol/serializer/protobuf/PbType.java b/protocol/src/main/java/com/zfoo/protocol/serializer/protobuf/PbType.java index 04b33983..02d4b8c4 100644 --- a/protocol/src/main/java/com/zfoo/protocol/serializer/protobuf/PbType.java +++ b/protocol/src/main/java/com/zfoo/protocol/serializer/protobuf/PbType.java @@ -32,10 +32,8 @@ public enum PbType { ENUM("enum", PbTypeJava.ENUM), STRING("string", PbTypeJava.STRING), BYTES("bytes", PbTypeJava.BYTES), - MESSAGE("", PbTypeJava.MESSAGE), - OBJECT("OBJECT", PbTypeJava.OBJECT), - GROUP("group", PbTypeJava.MESSAGE), - MAP("", PbTypeJava.MAP); + MAP("map", PbTypeJava.MAP), + ; private final String value; private final PbTypeJava javaType;