Skip to content

Commit 2ebe948

Browse files
committed
refactor: expose parsed api short name and version as fields in Service (#1075)
* Exposes parsed apiShortName and apiVersion as fields in Service.java, since the source fields (defaultHost and protoPakkage) are both defined per-service. * Adds these two fields correspondingly to GapicClass so that it can be composed from Service given these two upstream fields, then replaces withDefaultHost (for building GapicClass) withApiShortName and withApiVersion. (Composers and tests where this is currently used for sample generation are updated) * This change will enable Spring Codegen (when eventually split out from this repo) to reuse this parsing logic in descriptive comments and metadata. It also moves the parsing logic to earlier in the parse-compose process.
1 parent 6774245 commit 2ebe948

12 files changed

+238
-106
lines changed

src/main/java/com/google/api/generator/gapic/composer/Composer.java

+3-34
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737
import com.google.api.generator.gapic.model.Service;
3838
import com.google.api.generator.gapic.model.Transport;
3939
import com.google.common.annotations.VisibleForTesting;
40-
import com.google.common.base.Splitter;
41-
import com.google.common.collect.Iterables;
4240
import java.util.ArrayList;
4341
import java.util.Arrays;
4442
import java.util.List;
@@ -50,8 +48,7 @@ public static List<GapicClass> composeServiceClasses(GapicContext context) {
5048
clazzes.addAll(generateServiceClasses(context));
5149
clazzes.addAll(generateMockClasses(context, context.mixinServices()));
5250
clazzes.addAll(generateResourceNameHelperClasses(context));
53-
return addApacheLicense(
54-
prepareExecutableSamples(clazzes, context.gapicMetadata().getProtoPackage()));
51+
return addApacheLicense(prepareExecutableSamples(clazzes));
5552
}
5653

5754
public static GapicPackageInfo composePackageInfo(GapicContext context) {
@@ -193,16 +190,7 @@ public static List<GapicClass> generateTestClasses(GapicContext context) {
193190
}
194191

195192
@VisibleForTesting
196-
static List<GapicClass> prepareExecutableSamples(List<GapicClass> clazzes, String protoPackage) {
197-
// parse protoPackage for apiVersion
198-
String[] pakkage = protoPackage.split("\\.");
199-
String apiVersion;
200-
// e.g. v1, v2, v1beta1
201-
if (pakkage[pakkage.length - 1].matches("v[0-9].*")) {
202-
apiVersion = pakkage[pakkage.length - 1];
203-
} else {
204-
apiVersion = "";
205-
}
193+
static List<GapicClass> prepareExecutableSamples(List<GapicClass> clazzes) {
206194
// Include license header, apiShortName, and apiVersion
207195
List<GapicClass> clazzesWithSamples = new ArrayList<>();
208196
clazzes.forEach(
@@ -214,31 +202,12 @@ static List<GapicClass> prepareExecutableSamples(List<GapicClass> clazzes, Strin
214202
sample ->
215203
samples.add(
216204
addRegionTagAndHeaderToSample(
217-
sample, parseDefaultHost(gapicClass.defaultHost()), apiVersion)));
205+
sample, gapicClass.apiShortName(), gapicClass.apiVersion())));
218206
clazzesWithSamples.add(gapicClass.withSamples(samples));
219207
});
220208
return clazzesWithSamples;
221209
}
222210

223-
// Parse defaultHost for apiShortName for the RegionTag. Need to account for regional default
224-
// endpoints like
225-
// "us-east1-pubsub.googleapis.com".
226-
@VisibleForTesting
227-
protected static String parseDefaultHost(String defaultHost) {
228-
// If the defaultHost is of the format "**.googleapis.com", take the name before the first
229-
// period.
230-
String apiShortName = Iterables.getFirst(Splitter.on(".").split(defaultHost), defaultHost);
231-
// If the defaultHost is of the format "**-**-**.googleapis.com", take the section before the
232-
// first period and after the last dash to follow CSharp's implementation here:
233-
// https://github.com/googleapis/gapic-generator-csharp/blob/main/Google.Api.Generator/Generation/ServiceDetails.cs#L70
234-
apiShortName = Iterables.getLast(Splitter.on("-").split(apiShortName), defaultHost);
235-
// `iam-meta-api` service is an exceptional case and is handled as a one-off
236-
if (defaultHost.contains("iam-meta-api")) {
237-
apiShortName = "iam";
238-
}
239-
return apiShortName;
240-
}
241-
242211
@VisibleForTesting
243212
protected static Sample addRegionTagAndHeaderToSample(
244213
Sample sample, String apiShortName, String apiVersion) {

src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceClientClassComposer.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ public GapicClass generate(GapicContext context, Service service) {
164164

165165
updateGapicMetadata(context, service, className, grpcRpcsToJavaMethodNames);
166166
return GapicClass.create(kind, classDef, SampleComposerUtil.handleDuplicateSamples(samples))
167-
.withDefaultHost(service.defaultHost());
167+
.withApiShortName(service.apiShortName())
168+
.withApiVersion(service.apiVersion());
168169
}
169170

170171
private static List<AnnotationNode> createClassAnnotations(Service service, TypeStore typeStore) {

src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceSettingsClassComposer.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ public GapicClass generate(GapicContext context, Service service) {
127127
.setNestedClasses(Arrays.asList(createNestedBuilderClass(service, typeStore)))
128128
.build();
129129
return GapicClass.create(kind, classDef, SampleComposerUtil.handleDuplicateSamples(samples))
130-
.withDefaultHost(service.defaultHost());
130+
.withApiShortName(service.apiShortName())
131+
.withApiVersion(service.apiVersion());
131132
}
132133

133134
private static List<CommentStatement> createClassHeaderComments(

src/main/java/com/google/api/generator/gapic/composer/common/AbstractServiceStubSettingsClassComposer.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ public GapicClass generate(GapicContext context, Service service) {
202202
.build();
203203
return GapicClass.create(
204204
GapicClass.Kind.STUB, classDef, SampleComposerUtil.handleDuplicateSamples(samples))
205-
.withDefaultHost(service.defaultHost());
205+
.withApiShortName(service.apiShortName())
206+
.withApiVersion(service.apiVersion());
206207
}
207208

208209
protected MethodDefinition createDefaultCredentialsProviderBuilderMethod() {

src/main/java/com/google/api/generator/gapic/model/GapicClass.java

+16-7
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ public enum Kind {
3535

3636
public abstract List<Sample> samples();
3737

38-
// Represents the host URL for the service. May or may not contain a regional endpoint. Only used
39-
// for generating the region tag for samples; therefore only used in select Composers.
40-
public abstract String defaultHost();
38+
// Only used for generating the region tag for samples; therefore only used in select Composers.
39+
public abstract String apiShortName();
40+
41+
// Only used for generating the region tag for samples; therefore only used in select Composers.
42+
public abstract String apiVersion();
4143

4244
public static GapicClass create(Kind kind, ClassDefinition classDefinition) {
4345
return builder().setKind(kind).setClassDefinition(classDefinition).build();
@@ -51,7 +53,8 @@ public static GapicClass create(
5153
static Builder builder() {
5254
return new AutoValue_GapicClass.Builder()
5355
.setSamples(Collections.emptyList())
54-
.setDefaultHost("");
56+
.setApiShortName("")
57+
.setApiVersion("");
5558
}
5659

5760
abstract Builder toBuilder();
@@ -60,8 +63,12 @@ public final GapicClass withSamples(List<Sample> samples) {
6063
return toBuilder().setSamples(samples).build();
6164
}
6265

63-
public final GapicClass withDefaultHost(String defaultHost) {
64-
return toBuilder().setDefaultHost(defaultHost).build();
66+
public final GapicClass withApiShortName(String apiShortName) {
67+
return toBuilder().setApiShortName(apiShortName).build();
68+
}
69+
70+
public final GapicClass withApiVersion(String apiVersion) {
71+
return toBuilder().setApiVersion(apiVersion).build();
6572
}
6673

6774
@AutoValue.Builder
@@ -72,7 +79,9 @@ abstract static class Builder {
7279

7380
abstract Builder setSamples(List<Sample> samples);
7481

75-
abstract Builder setDefaultHost(String defaultHost);
82+
abstract Builder setApiShortName(String apiShortName);
83+
84+
abstract Builder setApiVersion(String apiVersion);
7685

7786
abstract GapicClass build();
7887
}

src/main/java/com/google/api/generator/gapic/model/Service.java

+47
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616

1717
import com.google.api.generator.engine.ast.TypeNode;
1818
import com.google.auto.value.AutoValue;
19+
import com.google.common.base.Splitter;
1920
import com.google.common.base.Strings;
2021
import com.google.common.collect.ImmutableList;
22+
import com.google.common.collect.Iterables;
2123
import java.util.List;
2224
import javax.annotation.Nullable;
2325

@@ -50,6 +52,20 @@ public boolean hasDescription() {
5052
return !Strings.isNullOrEmpty(description());
5153
}
5254

55+
public String apiShortName() {
56+
if (!Strings.isNullOrEmpty(defaultHost())) {
57+
return parseApiShortName(defaultHost());
58+
}
59+
return "";
60+
}
61+
62+
public String apiVersion() {
63+
if (!Strings.isNullOrEmpty(protoPakkage())) {
64+
return parseApiVersion(protoPakkage());
65+
}
66+
return "";
67+
}
68+
5369
public Method operationPollingMethod() {
5470
for (Method method : methods()) {
5571
if (method.isOperationPollingMethod()) {
@@ -127,4 +143,35 @@ public abstract static class Builder {
127143

128144
public abstract Service build();
129145
}
146+
147+
private static String parseApiVersion(String protoPackage) {
148+
// parse protoPackage for apiVersion
149+
String[] pakkage = protoPackage.split("\\.");
150+
String apiVersion;
151+
// e.g. v1, v2, v1beta1
152+
if (pakkage[pakkage.length - 1].matches("v[0-9].*")) {
153+
apiVersion = pakkage[pakkage.length - 1];
154+
} else {
155+
apiVersion = "";
156+
}
157+
return apiVersion;
158+
}
159+
160+
// Parse defaultHost for apiShortName for the RegionTag. Need to account for regional default
161+
// endpoints like
162+
// "us-east1-pubsub.googleapis.com".
163+
private static String parseApiShortName(String defaultHost) {
164+
// If the defaultHost is of the format "**.googleapis.com", take the name before the first
165+
// period.
166+
String apiShortName = Iterables.getFirst(Splitter.on(".").split(defaultHost), defaultHost);
167+
// If the defaultHost is of the format "**-**-**.googleapis.com", take the section before the
168+
// first period and after the last dash to follow CSharp's implementation here:
169+
// https://github.com/googleapis/gapic-generator-csharp/blob/main/Google.Api.Generator/Generation/ServiceDetails.cs#L70
170+
apiShortName = Iterables.getLast(Splitter.on("-").split(apiShortName), defaultHost);
171+
// `iam-meta-api` service is an exceptional case and is handled as a one-off
172+
if (defaultHost.contains("iam-meta-api")) {
173+
apiShortName = "iam";
174+
}
175+
return apiShortName;
176+
}
130177
}

src/test/java/com/google/api/generator/gapic/composer/ComposerTest.java

+33-41
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,16 @@ public class ComposerTest {
4242
private final Service echoProtoService = context.services().get(0);
4343
private final List<GapicClass> clazzes =
4444
Arrays.asList(
45-
GrpcServiceCallableFactoryClassComposer.instance().generate(context, echoProtoService));
45+
GrpcServiceCallableFactoryClassComposer.instance()
46+
.generate(context, echoProtoService)
47+
.withApiShortName(echoProtoService.apiShortName())
48+
.withApiVersion(echoProtoService.apiVersion()));
4649
private final Sample sample =
4750
Sample.builder()
4851
.setRegionTag(
4952
RegionTag.builder().setServiceName("serviceName").setRpcName("rpcName").build())
5053
.build();
5154
private List<Sample> ListofSamples = Arrays.asList(new Sample[] {sample});
52-
private final String protoPackage = echoProtoService.protoPakkage();
5355

5456
@Test
5557
public void gapicClass_addApacheLicense() {
@@ -75,47 +77,22 @@ public void composeSamples_showcase() {
7577
List<GapicClass> testClassList = Arrays.asList(new GapicClass[] {testClass});
7678

7779
List<Sample> composedSamples =
78-
Composer.prepareExecutableSamples(testClassList, protoPackage).get(0).samples();
80+
Composer.prepareExecutableSamples(testClassList).get(0).samples();
7981

8082
assertFalse(composedSamples.isEmpty());
8183
for (Sample sample : composedSamples) {
8284
assertEquals(
8385
"File header should be APACHE",
8486
Arrays.asList(CommentComposer.APACHE_LICENSE_COMMENT),
8587
sample.fileHeader());
86-
assertEquals("ApiShortName should be empty", "", sample.regionTag().apiShortName());
87-
assertEquals("ApiVersion should be V1beta1", "V1Beta1", sample.regionTag().apiVersion());
88+
assertEquals(
89+
"ApiShortName should be Localhost7469",
90+
"Localhost7469",
91+
sample.regionTag().apiShortName());
92+
assertEquals("ApiVersion should be V1Beta1", "V1Beta1", sample.regionTag().apiVersion());
8893
}
8994
}
9095

91-
@Test
92-
public void parseDefaultHost_shouldReturnApiShortNameIfHostContainsRegionalEndpoint() {
93-
String defaultHost = "us-east1-pubsub.googleapis.com";
94-
String apiShortName = Composer.parseDefaultHost(defaultHost);
95-
assertEquals("pubsub", apiShortName);
96-
}
97-
98-
@Test
99-
public void parseDefaultHost_shouldReturnApiShortName() {
100-
String defaultHost = "logging.googleapis.com";
101-
String apiShortName = Composer.parseDefaultHost(defaultHost);
102-
assertEquals("logging", apiShortName);
103-
}
104-
105-
@Test
106-
public void parseDefaultHost_shouldReturnApiShortNameForIam() {
107-
String defaultHost = "iam-meta-api.googleapis.com";
108-
String apiShortName = Composer.parseDefaultHost(defaultHost);
109-
assertEquals("iam", apiShortName);
110-
}
111-
112-
@Test
113-
public void parseDefaultHost_shouldReturnHostIfNoPeriods() {
114-
String defaultHost = "logging:7469";
115-
String apiShortName = Composer.parseDefaultHost(defaultHost);
116-
assertEquals("logging:7469", apiShortName);
117-
}
118-
11996
@Test
12097
public void gapicClass_addRegionTagAndHeaderToSample() {
12198
Sample testSample;
@@ -129,12 +106,12 @@ public void gapicClass_addRegionTagAndHeaderToSample() {
129106
public void composeSamples_parseProtoPackage() {
130107

131108
String defaultHost = "accessapproval.googleapis.com:443";
132-
GapicClass testClass = clazzes.get(0).withSamples(ListofSamples).withDefaultHost(defaultHost);
133-
List<GapicClass> testClassList = Arrays.asList(new GapicClass[] {testClass});
134109
String protoPack = "google.cloud.accessapproval.v1";
135-
110+
Service testService =
111+
echoProtoService.toBuilder().setDefaultHost(defaultHost).setProtoPakkage(protoPack).build();
112+
List<GapicClass> testClassList = getTestClassListFromService(testService);
136113
List<Sample> composedSamples =
137-
Composer.prepareExecutableSamples(testClassList, protoPack).get(0).samples();
114+
Composer.prepareExecutableSamples(testClassList).get(0).samples();
138115

139116
// If samples is empty, the test automatically passes without checking.
140117
assertFalse(composedSamples.isEmpty());
@@ -149,9 +126,10 @@ public void composeSamples_parseProtoPackage() {
149126

150127
protoPack = "google.cloud.vision.v1p1beta1";
151128
defaultHost = "vision.googleapis.com";
152-
testClass = clazzes.get(0).withSamples(ListofSamples).withDefaultHost(defaultHost);
153-
testClassList = Arrays.asList(new GapicClass[] {testClass});
154-
composedSamples = Composer.prepareExecutableSamples(testClassList, protoPack).get(0).samples();
129+
testService =
130+
testService.toBuilder().setDefaultHost(defaultHost).setProtoPakkage(protoPack).build();
131+
testClassList = getTestClassListFromService(testService);
132+
composedSamples = Composer.prepareExecutableSamples(testClassList).get(0).samples();
155133
// If samples is empty, the test automatically passes without checking.
156134
assertFalse(composedSamples.isEmpty());
157135

@@ -161,7 +139,10 @@ public void composeSamples_parseProtoPackage() {
161139
}
162140

163141
protoPack = "google.cloud.vision";
164-
composedSamples = Composer.prepareExecutableSamples(testClassList, protoPack).get(0).samples();
142+
testService =
143+
testService.toBuilder().setDefaultHost(defaultHost).setProtoPakkage(protoPack).build();
144+
testClassList = getTestClassListFromService(testService);
145+
composedSamples = Composer.prepareExecutableSamples(testClassList).get(0).samples();
165146
// If samples is empty, the test automatically passes without checking.
166147
assertFalse(composedSamples.isEmpty());
167148

@@ -170,4 +151,15 @@ public void composeSamples_parseProtoPackage() {
170151
assertEquals("ApiVersion should be empty", sample.regionTag().apiVersion(), "");
171152
}
172153
}
154+
155+
private List<GapicClass> getTestClassListFromService(Service testService) {
156+
GapicClass testClass =
157+
GrpcServiceCallableFactoryClassComposer.instance()
158+
.generate(context, testService)
159+
.withSamples(ListofSamples)
160+
.withApiShortName(testService.apiShortName())
161+
.withApiVersion(testService.apiVersion());
162+
List<GapicClass> testClassList = Arrays.asList(new GapicClass[] {testClass});
163+
return testClassList;
164+
}
173165
}

0 commit comments

Comments
 (0)