From 8bc63f4e5645dc626e502c3a5d2546dfd0286d61 Mon Sep 17 00:00:00 2001 From: Mira Leung Date: Wed, 2 Dec 2020 13:27:08 -0800 Subject: [PATCH 1/4] fix: fix dep ordering in Bazel dedupe rules --- rules_java_gapic/java_gapic.bzl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rules_java_gapic/java_gapic.bzl b/rules_java_gapic/java_gapic.bzl index 96e482907c..d265f8c676 100644 --- a/rules_java_gapic/java_gapic.bzl +++ b/rules_java_gapic/java_gapic.bzl @@ -189,7 +189,7 @@ def java_gapic_library( ) # General additional deps. - actual_deps = resource_name_deps + [ + actual_deps = deps + resource_name_deps + [ "@com_google_googleapis//google/rpc:rpc_java_proto", "@com_google_googleapis//google/longrunning:longrunning_java_proto", "@com_google_protobuf//:protobuf_java", @@ -207,7 +207,6 @@ def java_gapic_library( "@com_google_http_client_google_http_client//jar", "@javax_annotation_javax_annotation_api//jar", ] - _append_dep_without_duplicates(actual_deps, deps) native.java_library( name = name, From 06d5d4ac6506fa6b019b310a3f1cc252728ade0e Mon Sep 17 00:00:00 2001 From: Mira Leung Date: Tue, 22 Dec 2020 14:53:00 -0800 Subject: [PATCH 2/4] feat: add a basic trie --- BUILD.bazel | 1 + .../java/com/google/api/generator/BUILD.bazel | 1 + .../com/google/api/generator/util/BUILD.bazel | 15 ++++ .../com/google/api/generator/util/Trie.java | 88 +++++++++++++++++++ .../com/google/api/generator/util/BUILD.bazel | 24 +++++ .../google/api/generator/util/TrieTest.java | 65 ++++++++++++++ 6 files changed, 194 insertions(+) create mode 100644 src/main/java/com/google/api/generator/util/BUILD.bazel create mode 100644 src/main/java/com/google/api/generator/util/Trie.java create mode 100644 src/test/java/com/google/api/generator/util/BUILD.bazel create mode 100644 src/test/java/com/google/api/generator/util/TrieTest.java diff --git a/BUILD.bazel b/BUILD.bazel index 5ba8d4f99b..8823250fca 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -16,6 +16,7 @@ JAVA_SRCS = [ TEST_SRCS = [ "//src/test/java/com/google/api/generator/engine:engine_files", "//src/test/java/com/google/api/generator/gapic:gapic_files", + "//src/test/java/com/google/api/generator/util:util_files", "//src/test/java/com/google/api/generator/test/framework:framework_files", ] diff --git a/src/main/java/com/google/api/generator/BUILD.bazel b/src/main/java/com/google/api/generator/BUILD.bazel index 33b265ab7d..de7f95f193 100644 --- a/src/main/java/com/google/api/generator/BUILD.bazel +++ b/src/main/java/com/google/api/generator/BUILD.bazel @@ -37,6 +37,7 @@ java_library( "//src/main/java/com/google/api/generator/engine/ast", "//src/main/java/com/google/api/generator/gapic", "//src/main/java/com/google/api/generator/gapic/model", + "//src/main/java/com/google/api/generator/util", "@com_google_googleapis//google/api:api_java_proto", "@com_google_googleapis//google/longrunning:longrunning_java_proto", "@com_google_guava_guava//jar", diff --git a/src/main/java/com/google/api/generator/util/BUILD.bazel b/src/main/java/com/google/api/generator/util/BUILD.bazel new file mode 100644 index 0000000000..cf765b3a70 --- /dev/null +++ b/src/main/java/com/google/api/generator/util/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_java//java:defs.bzl", "java_library") + +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "util_files", + srcs = glob(["*.java"]), +) + +java_library( + name = "util", + srcs = [ + ":util_files", + ], +) diff --git a/src/main/java/com/google/api/generator/util/Trie.java b/src/main/java/com/google/api/generator/util/Trie.java new file mode 100644 index 0000000000..97038db253 --- /dev/null +++ b/src/main/java/com/google/api/generator/util/Trie.java @@ -0,0 +1,88 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.util; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * A common-prefix trie. T represents the type of each "char" in a word (which is a T-typed list). + */ +public class Trie { + private class Node { + final T chr; + Map children = new HashMap<>(); + boolean isLeaf; + + Node() { + chr = null; + } + + Node(T chr) { + this.chr = chr; + } + } + + private Node root; + + public Trie() { + root = new Node(); + } + + public void insert(List word) { + Map children = root.children; + for (int i = 0; i < word.size(); i++) { + T chr = word.get(i); + Node t; + if (children.containsKey(chr)) { + t = children.get(chr); + } else { + t = new Node(chr); + children.put(chr, t); + } + children = t.children; + if (i == word.size() - 1) { + t.isLeaf = true; + } + } + } + + /** Returns true if the word is in the trie. */ + public boolean search(List word) { + Node node = searchNode(word); + return node != null && node.isLeaf; + } + + /** Returns true if some word in the trie begins with the given prefix. */ + public boolean hasPrefix(List prefix) { + return searchNode(prefix) != null; + } + + private Node searchNode(List word) { + Map children = root.children; + Node t = null; + for (int i = 0; i < word.size(); i++) { + T chr = word.get(i); + if (children.containsKey(chr)) { + t = children.get(chr); + children = t.children; + } else { + return null; + } + } + return t; + } +} diff --git a/src/test/java/com/google/api/generator/util/BUILD.bazel b/src/test/java/com/google/api/generator/util/BUILD.bazel new file mode 100644 index 0000000000..2a934e83b4 --- /dev/null +++ b/src/test/java/com/google/api/generator/util/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_java//java:defs.bzl", "java_test") + +package(default_visibility = ["//visibility:public"]) + +TESTS = [ + "TrieTest", +] + +filegroup( + name = "util_files", + srcs = ["{0}.java".format(f) for f in TESTS], +) + +[java_test( + name = test_name, + srcs = ["{0}.java".format(test_name)], + test_class = "com.google.api.generator.util.{0}".format(test_name), + deps = [ + "//src/main/java/com/google/api/generator/util", + "@com_google_guava_guava//jar", + "@com_google_truth_truth//jar", + "@junit_junit//jar", + ], +) for test_name in TESTS] diff --git a/src/test/java/com/google/api/generator/util/TrieTest.java b/src/test/java/com/google/api/generator/util/TrieTest.java new file mode 100644 index 0000000000..41fdb999f9 --- /dev/null +++ b/src/test/java/com/google/api/generator/util/TrieTest.java @@ -0,0 +1,65 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.util; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; +import org.junit.Test; + +public class TrieTest { + @Test + public void stringTrie() { + Trie trie = new Trie<>(); + + Function> wordToCharListFn = w -> Arrays.asList(w.split("(?!^)")); + List wordCat = wordToCharListFn.apply("cat"); + assertFalse(trie.search(wordCat)); + + trie.insert(wordCat); + assertTrue(trie.search(wordCat)); + assertFalse(trie.search(wordToCharListFn.apply("car"))); + assertTrue(trie.hasPrefix(wordToCharListFn.apply("ca"))); + + trie.insert(wordToCharListFn.apply("car")); + trie.insert(wordToCharListFn.apply("dog")); + assertTrue(trie.search(wordToCharListFn.apply("car"))); + assertTrue(trie.search(wordToCharListFn.apply("dog"))); + } + + @Test + public void multiStringTrie() { + Trie trie = new Trie<>(); + assertFalse(trie.search(Arrays.asList("user", "identity", "name"))); + + trie.insert(Arrays.asList("user", "identity", "name")); + trie.insert(Arrays.asList("user", "identity", "age")); + trie.insert(Arrays.asList("user", "contact", "email")); + + assertTrue(trie.search(Arrays.asList("user", "identity", "name"))); + assertTrue(trie.search(Arrays.asList("user", "identity", "age"))); + assertFalse(trie.search(Arrays.asList("user", "identity", "eyeColor"))); + assertTrue(trie.search(Arrays.asList("user", "contact", "email"))); + assertTrue(trie.hasPrefix(Arrays.asList("user", "identity"))); + assertTrue(trie.hasPrefix(Arrays.asList("user", "contact"))); + assertTrue(trie.hasPrefix(Arrays.asList("user"))); + + assertFalse(trie.hasPrefix(Arrays.asList("identity"))); + assertFalse(trie.hasPrefix(Arrays.asList("contact"))); + } +} From 90391ce906c968eb7ca6b47d1a2abdd9c069113b Mon Sep 17 00:00:00 2001 From: Mira Leung Date: Tue, 22 Dec 2020 15:22:20 -0800 Subject: [PATCH 3/4] fix: add hashCode() and equals() to Field --- .../api/generator/gapic/model/Field.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/main/java/com/google/api/generator/gapic/model/Field.java b/src/main/java/com/google/api/generator/gapic/model/Field.java index 6613caf4bd..e178e417e6 100644 --- a/src/main/java/com/google/api/generator/gapic/model/Field.java +++ b/src/main/java/com/google/api/generator/gapic/model/Field.java @@ -16,6 +16,7 @@ import com.google.api.generator.engine.ast.TypeNode; import com.google.auto.value.AutoValue; +import java.util.Objects; import javax.annotation.Nullable; @AutoValue @@ -48,6 +49,37 @@ public boolean hasResourceReference() { return type().equals(TypeNode.STRING) && resourceReference() != null; } + @Override + public boolean equals(Object o) { + if (!(o instanceof Field)) { + return false; + } + + Field other = (Field) o; + return name().equals(other.name()) + && type().equals(other.type()) + && isMessage() == other.isMessage() + && isEnum() == other.isEnum() + && isRepeated() == other.isRepeated() + && isMap() == other.isMap() + && isContainedInOneof() == other.isContainedInOneof() + && Objects.equals(resourceReference(), other.resourceReference()) + && Objects.equals(description(), other.description()); + } + + @Override + public int hashCode() { + return 17 * name().hashCode() + + 19 * type().hashCode() + + (isMessage() ? 1 : 0) * 23 + + (isEnum() ? 1 : 0) * 29 + + (isRepeated() ? 1 : 0) * 31 + + (isMap() ? 1 : 0) * 37 + + (isContainedInOneof() ? 1 : 0) * 41 + + (resourceReference() == null ? 0 : resourceReference().hashCode()) + + (description() == null ? 0 : description().hashCode()); + } + public abstract Builder toBuilder(); public static Builder builder() { From 3308c20827e8be7f00e5e2cd486c3f64a3366dbc Mon Sep 17 00:00:00 2001 From: Mira Leung Date: Wed, 23 Dec 2020 19:16:31 -0800 Subject: [PATCH 4/4] fix: add equals() and hashCode() for MethodArgument --- .../generator/gapic/model/MethodArgument.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/com/google/api/generator/gapic/model/MethodArgument.java b/src/main/java/com/google/api/generator/gapic/model/MethodArgument.java index f5776aa730..e13deda713 100644 --- a/src/main/java/com/google/api/generator/gapic/model/MethodArgument.java +++ b/src/main/java/com/google/api/generator/gapic/model/MethodArgument.java @@ -46,6 +46,28 @@ public int compareTo(MethodArgument other) { return compareVal; } + @Override + public boolean equals(Object o) { + if (!(o instanceof MethodArgument)) { + return false; + } + + MethodArgument other = (MethodArgument) o; + return name().equals(other.name()) + && type().equals(other.type()) + && field().equals(other.field()) & nestedFields().equals(other.nestedFields()) + && isResourceNameHelper() == other.isResourceNameHelper(); + } + + @Override + public int hashCode() { + return 17 * name().hashCode() + + 19 * type().hashCode() + + 23 * field().hashCode() + + 29 * nestedFields().hashCode() + + (isResourceNameHelper() ? 1 : 0) * 31; + } + public static Builder builder() { return new AutoValue_MethodArgument.Builder() .setNestedFields(ImmutableList.of())