Skip to content

Commit 5da1a23

Browse files
committed
feat(generator): emit callable getter and convenience method for resumable upload RPCs
- In AbstractServiceStubClassComposer: emit public ResumableUploadCallable<RequestT, ResponseT> [method]Callable() throwing UnsupportedOperationException - In AbstractServiceClientClassComposer: emit public ResumableUploadCallable<RequestT, ResponseT> [method]Callable() delegating to stub - In AbstractServiceClientClassComposer: emit synchronous convenience method [method](RequestT request, InputStream payload) calling ApiExceptions.callAndTranslateApiException - Suppress method variants (flattened methods) for resumable upload RPCs - In ServiceClientCommentComposer: emit Javadoc call context override warning on both callable method and synchronous convenience method - Add unit test ResumableUploadServiceClientComposerTest verifying generated stub and client methods
1 parent 8f9a345 commit 5da1a23

18 files changed

Lines changed: 901 additions & 104 deletions

‎sdk-platform-java/gapic-generator-java/src/main/java/com/google/api/generator/gapic/composer/comment/ServiceClientCommentComposer.java‎

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,19 @@
3333
import java.util.Optional;
3434
import java.util.stream.Collectors;
3535
import org.jspecify.annotations.NullMarked;
36+
import org.jspecify.annotations.Nullable;
3637

3738
@NullMarked
3839
public class ServiceClientCommentComposer {
3940
// Tokens.
4041
private static final String EMPTY_STRING = "";
4142
private static final String API_EXCEPTION_TYPE_NAME = "com.google.api.gax.rpc.ApiException";
4243
private static final String EXCEPTION_CONDITION = "if the remote call fails";
44+
private static final String REQUEST_PARAM_NAME = "request";
45+
private static final String REQUEST_PARAM_DESCRIPTION =
46+
"The request object containing all of the parameters for the API call.";
47+
private static final String PAYLOAD_PARAM_NAME = "payload";
48+
private static final String PAYLOAD_PARAM_DESCRIPTION = "The payload data stream to upload.";
4349

4450
// Constants.
4551
private static final String SERVICE_DESCRIPTION_INTRO_STRING =
@@ -93,6 +99,11 @@ public class ServiceClientCommentComposer {
9399
+ " that it is easy to make a subclass, but otherwise, the static factory methods"
94100
+ " should be preferred.";
95101

102+
private static final String RESUMABLE_UPLOAD_CALL_CONTEXT_WARNING =
103+
"Call context overrides (such as withTimeout, withRetrySettings, or credentials) apply"
104+
+ " strictly to the start request (session initiation). Per-chunk PUT calls rely on"
105+
+ " the configured timeout and retry settings from ResumableUploadCallSettings.";
106+
96107
// Comments.
97108
public static final CommentStatement GET_OPERATIONS_CLIENT_METHOD_COMMENT =
98109
toSimpleComment(
@@ -105,9 +116,9 @@ public static List<CommentStatement> createClassHeaderComments(
105116
String classMethodSampleCode,
106117
String credentialsSampleCode,
107118
String endpointSampleCode,
108-
String transportSampleCode,
109-
String primaryTransport,
110-
String secondaryTransport) {
119+
@Nullable String transportSampleCode,
120+
@Nullable String primaryTransport,
121+
@Nullable String secondaryTransport) {
111122
JavaDocComment.Builder classHeaderJavadocBuilder = JavaDocComment.builder();
112123
if (service.hasDescription()) {
113124
String descriptionComment =
@@ -187,14 +198,17 @@ public static List<CommentStatement> createRpcMethodHeaderComment(
187198
methodJavadocBuilder = methodJavadocBuilder.addUnescapedComment(descriptionComment);
188199
}
189200

190-
if (sampleCodeOpt.isPresent()) {
201+
if (method.isResumableUpload()) {
202+
methodJavadocBuilder.addParagraph(RESUMABLE_UPLOAD_CALL_CONTEXT_WARNING);
203+
}
204+
205+
if (sampleCodeOpt.isPresent() && !method.isResumableUpload()) {
191206
methodJavadocBuilder.addParagraph(METHOD_DESCRIPTION_SAMPLE_CODE_SUMMARY_STRING);
192207
methodJavadocBuilder.addSampleCode(sampleCodeOpt.get());
193208
}
194209

195210
if (methodArguments.isEmpty()) {
196-
methodJavadocBuilder.addParam(
197-
"request", "The request object containing all of the parameters for the API call.");
211+
methodJavadocBuilder.addParam(REQUEST_PARAM_NAME, REQUEST_PARAM_DESCRIPTION);
198212
} else {
199213
for (MethodArgument argument : methodArguments) {
200214
// TODO(miraleung): Remove the newline replacement when we support CommonMark.
@@ -204,6 +218,10 @@ public static List<CommentStatement> createRpcMethodHeaderComment(
204218
}
205219
}
206220

221+
if (method.isResumableUpload()) {
222+
methodJavadocBuilder.addParam(PAYLOAD_PARAM_NAME, PAYLOAD_PARAM_DESCRIPTION);
223+
}
224+
207225
methodJavadocBuilder.setThrows(API_EXCEPTION_TYPE_NAME, EXCEPTION_CONDITION);
208226

209227
if (method.isDeprecated()) {
@@ -233,13 +251,17 @@ private static MethodAndVariants createMethodAndVariants(
233251

234252
private static String createTableOfMethods(List<MethodAndVariants> methodAndVariantsList) {
235253
String FLATTENED_METHODS =
236-
"<p>\"Flattened\" method variants have converted the fields of the request object into function parameters to enable multiple ways to call the same method.</p>\n";
254+
"<p>\"Flattened\" method variants have converted the fields of the request object into"
255+
+ " function parameters to enable multiple ways to call the same method.</p>\n";
237256
String REQUEST_OBJECT_METHODS =
238-
"<p>Request object method variants only take one parameter, a request object, which must be constructed before the call.</p>\n";
257+
"<p>Request object method variants only take one parameter, a request object, which must be"
258+
+ " constructed before the call.</p>\n";
239259
String CALLABLE_METHODS =
240-
"<p>Callable method variants take no parameters and return an immutable API callable object, which can be used to initiate calls to the service.</p>\n";
260+
"<p>Callable method variants take no parameters and return an immutable API callable"
261+
+ " object, which can be used to initiate calls to the service.</p>\n";
241262
String ASYNC_METHODS =
242-
"<p>Methods that return long-running operations have \"Async\" method variants that return `OperationFuture`, which is used to track polling of the service.</p>\n";
263+
"<p>Methods that return long-running operations have \"Async\" method variants that return"
264+
+ " `OperationFuture`, which is used to track polling of the service.</p>\n";
243265

244266
StringBuilder tableBuilder = new StringBuilder();
245267
tableBuilder
@@ -348,8 +370,12 @@ public static List<CommentStatement> createRpcCallableMethodHeaderComment(
348370
methodJavadocBuilder = methodJavadocBuilder.addUnescapedComment(descriptionComment);
349371
}
350372

351-
methodJavadocBuilder.addParagraph(METHOD_DESCRIPTION_SAMPLE_CODE_SUMMARY_STRING);
352-
if (sampleCodeOpt.isPresent()) {
373+
if (method.isResumableUpload()) {
374+
methodJavadocBuilder.addParagraph(RESUMABLE_UPLOAD_CALL_CONTEXT_WARNING);
375+
}
376+
377+
if (sampleCodeOpt.isPresent() && !method.isResumableUpload()) {
378+
methodJavadocBuilder.addParagraph(METHOD_DESCRIPTION_SAMPLE_CODE_SUMMARY_STRING);
353379
methodJavadocBuilder.addSampleCode(sampleCodeOpt.get());
354380
}
355381

‎sdk-platform-java/gapic-generator-java/src/main/java/com/google/api/generator/gapic/composer/comment/SettingsCommentComposer.java‎

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -136,21 +136,14 @@ public static CommentStatement createCallSettingsGetterComment(
136136
isMethodInternal);
137137
}
138138

139+
private static final String RESUMABLE_UPLOAD_CALL_SETTINGS_DOC_NOTE =
140+
"Note that custom retry settings and headers configured via ApiCallContext"
141+
+ " apply strictly to the initial session initiation request.";
142+
139143
public static CommentStatement createResumableUploadCallSettingsGetterComment(
140144
String javaMethodName, boolean isMethodDeprecated, boolean isMethodInternal) {
141-
JavaDocComment.Builder docBuilder =
142-
JavaDocComment.builder()
143-
.addComment(String.format(CALL_SETTINGS_METHOD_DOC_PATTERN, javaMethodName))
144-
.addParagraph(
145-
"Note that custom retry settings and headers configured via ApiCallContext"
146-
+ " apply strictly to the initial session initiation request.");
147-
if (isMethodDeprecated) {
148-
docBuilder.setDeprecated(CommentComposer.DEPRECATED_METHOD_STRING);
149-
}
150-
if (isMethodInternal) {
151-
docBuilder.setInternalOnly(CommentComposer.INTERNAL_ONLY_METHOD_STRING);
152-
}
153-
return CommentStatement.withComment(docBuilder.build());
145+
return createResumableUploadCallSettingsComment(
146+
CALL_SETTINGS_METHOD_DOC_PATTERN, javaMethodName, isMethodDeprecated, isMethodInternal);
154147
}
155148

156149
public static CommentStatement createBuilderClassComment(String outerClassName) {
@@ -165,12 +158,19 @@ public static CommentStatement createCallSettingsBuilderGetterComment(
165158

166159
public static CommentStatement createResumableUploadCallSettingsBuilderGetterComment(
167160
String javaMethodName, boolean isMethodDeprecated, boolean isMethodInternal) {
161+
return createResumableUploadCallSettingsComment(
162+
CALL_SETTINGS_BUILDER_METHOD_DOC_PATTERN,
163+
javaMethodName,
164+
isMethodDeprecated,
165+
isMethodInternal);
166+
}
167+
168+
private static CommentStatement createResumableUploadCallSettingsComment(
169+
String pattern, String javaMethodName, boolean isMethodDeprecated, boolean isMethodInternal) {
168170
JavaDocComment.Builder docBuilder =
169171
JavaDocComment.builder()
170-
.addComment(String.format(CALL_SETTINGS_BUILDER_METHOD_DOC_PATTERN, javaMethodName))
171-
.addParagraph(
172-
"Note that custom retry settings and headers configured via ApiCallContext"
173-
+ " apply strictly to the initial session initiation request.");
172+
.addComment(String.format(pattern, javaMethodName))
173+
.addParagraph(RESUMABLE_UPLOAD_CALL_SETTINGS_DOC_NOTE);
174174
if (isMethodDeprecated) {
175175
docBuilder.setDeprecated(CommentComposer.DEPRECATED_METHOD_STRING);
176176
}

0 commit comments

Comments
 (0)