From fcfa1919b09101a176cf6ead451fb6a4e60ce324 Mon Sep 17 00:00:00 2001 From: Dmitrii Duzhinskii Date: Tue, 5 Sep 2023 11:05:09 +0300 Subject: [PATCH] Comparator reference --- .../generator/message/MessageGenerator.java | 23 +++++++++++++++---- .../org/sudu/protogen/protobuf/Message.java | 2 ++ .../sudu/protogen/protoc/adaptor/Message.java | 5 ++++ .../sudu/protogen/protobuf/MessageMock.java | 5 ++++ options/src/main/proto/protogen/options.proto | 5 ++++ .../ComparatorReferenceTest.java | 20 ++++++++++++++++ .../test/comparatorRef/TestComparators.java | 8 +++++++ tests/src/test/proto/comparatorRef.proto | 16 +++++++++++++ 8 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 tests/src/test/java/org/sudu/protogen/test/comparatorRef/ComparatorReferenceTest.java create mode 100644 tests/src/test/java/org/sudu/protogen/test/comparatorRef/TestComparators.java create mode 100644 tests/src/test/proto/comparatorRef.proto diff --git a/generator/src/main/java/org/sudu/protogen/generator/message/MessageGenerator.java b/generator/src/main/java/org/sudu/protogen/generator/message/MessageGenerator.java index 181d92d..79711a7 100644 --- a/generator/src/main/java/org/sudu/protogen/generator/message/MessageGenerator.java +++ b/generator/src/main/java/org/sudu/protogen/generator/message/MessageGenerator.java @@ -1,9 +1,6 @@ package org.sudu.protogen.generator.message; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.FieldSpec; -import com.squareup.javapoet.ParameterSpec; -import com.squareup.javapoet.TypeSpec; +import com.squareup.javapoet.*; import org.jetbrains.annotations.NotNull; import org.sudu.protogen.generator.GenerationContext; import org.sudu.protogen.generator.field.FieldGenerator; @@ -42,6 +39,9 @@ public TypeSpec generate() { TypeSpec.Builder typeBuilder = getRecordBuilder(fields); boolean annotateNotNull = msgDescriptor.getContainingFile().doUseNullabilityAnnotation(false); + msgDescriptor.getComparatorReference().ifPresent( + comparator -> addComparable(typeBuilder, comparator) + ); return typeBuilder .multiLineRecord(true) @@ -52,6 +52,21 @@ public TypeSpec generate() { .build(); } + private void addComparable(TypeSpec.Builder typeBuilder, String comparator) { + ClassName type = generatedType(); + typeBuilder.addSuperinterface(ParameterizedTypeName.get(ClassName.get(Comparable.class), type)); + ParameterSpec methodParameter = ParameterSpec.builder(type, "rhs").build(); + typeBuilder.addMethod( + MethodSpec.methodBuilder("compareTo") + .addModifiers(Modifier.PUBLIC) + .returns(TypeName.INT) + .addParameter(methodParameter) + .addAnnotation(ClassName.get(Override.class)) + .addStatement("return $L.compare(this, $N)", comparator, methodParameter) + .build() + ); + } + private TypeSpec.Builder getRecordBuilder(List fields) { List parameters = fields.stream() .map(Poem::fieldToParameter) diff --git a/generator/src/main/java/org/sudu/protogen/protobuf/Message.java b/generator/src/main/java/org/sudu/protogen/protobuf/Message.java index c4588f5..739712f 100644 --- a/generator/src/main/java/org/sudu/protogen/protobuf/Message.java +++ b/generator/src/main/java/org/sudu/protogen/protobuf/Message.java @@ -26,5 +26,7 @@ public final boolean isUnfolded() { */ public abstract boolean isMap(); + public abstract Optional getComparatorReference(); + protected abstract Optional getUnfoldOption(); } diff --git a/generator/src/main/java/org/sudu/protogen/protoc/adaptor/Message.java b/generator/src/main/java/org/sudu/protogen/protoc/adaptor/Message.java index f5b9403..6d13eba 100644 --- a/generator/src/main/java/org/sudu/protogen/protoc/adaptor/Message.java +++ b/generator/src/main/java/org/sudu/protogen/protoc/adaptor/Message.java @@ -92,4 +92,9 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(descriptor); } + + @Override + public Optional getComparatorReference() { + return Options.wrapExtension(descriptor.getOptions(), protogen.Options.messageComparator); + } } diff --git a/generator/src/test/java/org/sudu/protogen/protobuf/MessageMock.java b/generator/src/test/java/org/sudu/protogen/protobuf/MessageMock.java index bf07b48..e0aea47 100644 --- a/generator/src/test/java/org/sudu/protogen/protobuf/MessageMock.java +++ b/generator/src/test/java/org/sudu/protogen/protobuf/MessageMock.java @@ -181,6 +181,11 @@ public void setUnfoldOption(Optional unfoldOption) { this.unfoldOption = unfoldOption; } + @Override + public Optional getComparatorReference() { + return Optional.empty(); + } + @Override public String toString() { return "MessageMock{" + diff --git a/options/src/main/proto/protogen/options.proto b/options/src/main/proto/protogen/options.proto index f183dce..4cead5f 100644 --- a/options/src/main/proto/protogen/options.proto +++ b/options/src/main/proto/protogen/options.proto @@ -55,6 +55,11 @@ extend google.protobuf.MessageOptions { * Ex: option (protogen.custom_class) = "org.sudu.api.computeengine.BatchInfo"; */ string custom_class = 5104; + /* + * Allows to implement Comparable using specified comparator. + * Ex: option (protogen.message_comparator) = "org.sudu.api.console.types.ConsoleComparators.INSTANCE_ID"; + */ + string message_comparator = 5105; } extend google.protobuf.EnumOptions { diff --git a/tests/src/test/java/org/sudu/protogen/test/comparatorRef/ComparatorReferenceTest.java b/tests/src/test/java/org/sudu/protogen/test/comparatorRef/ComparatorReferenceTest.java new file mode 100644 index 0000000..b209948 --- /dev/null +++ b/tests/src/test/java/org/sudu/protogen/test/comparatorRef/ComparatorReferenceTest.java @@ -0,0 +1,20 @@ +package org.sudu.protogen.test.comparatorRef; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ComparatorReferenceTest { + + @Test + public void Person_should_compare_correctly() { + Person anton20 = new Person("Anton", 20); + Person anton25 = new Person("Anton", 25); + Person lena20 = new Person("Lena", 20); + + Assertions.assertTrue(anton20.compareTo(anton25) < 0); + Assertions.assertTrue(anton20.compareTo(anton20) == 0); + Assertions.assertTrue(lena20.compareTo(anton25) > 0); + Assertions.assertTrue(lena20.compareTo(anton20) > 0); + Assertions.assertTrue(anton20.compareTo(lena20) < 0); + } +} diff --git a/tests/src/test/java/org/sudu/protogen/test/comparatorRef/TestComparators.java b/tests/src/test/java/org/sudu/protogen/test/comparatorRef/TestComparators.java new file mode 100644 index 0000000..9343206 --- /dev/null +++ b/tests/src/test/java/org/sudu/protogen/test/comparatorRef/TestComparators.java @@ -0,0 +1,8 @@ +package org.sudu.protogen.test.comparatorRef; + +import java.util.Comparator; + +public class TestComparators { + + public static final Comparator PERSON_COMPARATOR = Comparator.comparing(Person::name).thenComparing(Person::age); +} diff --git a/tests/src/test/proto/comparatorRef.proto b/tests/src/test/proto/comparatorRef.proto new file mode 100644 index 0000000..c47f24d --- /dev/null +++ b/tests/src/test/proto/comparatorRef.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +package org.sudu.protogen.test.comparatorRef; + +import "google/protobuf/empty.proto"; +import "protogen/options.proto"; + +option java_multiple_files = true; +option (.protogen.enable) = true; + +message GrpcPerson { + string name = 1; + int32 age = 2; + + option (.protogen.message_comparator) = "org.sudu.protogen.test.comparatorRef.TestComparators.PERSON_COMPARATOR"; +} \ No newline at end of file