Skip to content
Closed
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@

public interface ClassComposer {
GapicClass generate(
// TODO(miraleung): clean up the hierarchy to avoid pass another parameter (resourceNames is
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As already mentioned here, please remove resourceNames from this interface and have the class(es) that need it not inherit from ClassComposer. The TODO on me should go into those classes, not this one.

// only used for composing sample code).
Service service, Map<String, Message> messageTypes, Map<String, ResourceName> resourceNames);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

import com.google.api.generator.engine.ast.AssignmentExpr;
import com.google.api.generator.engine.ast.CommentStatement;
import com.google.api.generator.engine.ast.Expr;
import com.google.api.generator.engine.ast.ExprStatement;
import com.google.api.generator.engine.ast.LineComment;
import com.google.api.generator.engine.ast.MethodInvocationExpr;
import com.google.api.generator.engine.ast.TryCatchStatement;
Expand All @@ -26,17 +28,26 @@
import com.google.api.generator.gapic.model.MethodArgument;
import com.google.api.generator.gapic.model.ResourceName;
import com.google.api.generator.gapic.utils.JavaStyle;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public final class SampleCodeHelperComposer {
private static String RESPONSE = "response";

public static TryCatchStatement composeRpcMethodSampleCode(
Method method,
List<MethodArgument> arguments,
TypeNode clientType,
Map<String, ResourceName> resourceNames) {
Preconditions.checkState(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@miraleung could you give me feedback here. I am not sure. Do we need to check if the arguments pass in is empty?
Any possible for a methodSignatures contain an empty list List<List<MethodArgument>> ?

!arguments.isEmpty(),
"If method %s's arguments is none, it should pass %s as argument.",
method.name(),
method.inputType().reference().name());
// Paged Unary RPC method.
if (method.isPaged()) {
return composePagedUnaryRpcMethodSampleCode(method, arguments, clientType, resourceNames);
Expand Down Expand Up @@ -71,14 +82,45 @@ private static TryCatchStatement composeUnaryRpcMethodSampleCode(
List<MethodArgument> arguments,
TypeNode clientType,
Map<String, ResourceName> resourceNames) {
// TODO(summerji): compose sample code for unary rpc method.
VariableExpr clientVarExpr = createVariableExpr(getClientName(clientType), clientType);
// Assign each method arguments with its default value.
Map<String, VariableExpr> methodArgVarExprMap = mapMethodArgumentsToVariableExprs(arguments);
List<Expr> methodArgumentsAssignmentExpr =
assignMethodArgumentsWithDefaultValues(arguments, methodArgVarExprMap, resourceNames);
List<Expr> methodVarExprs =
arguments.stream()
.map(arg -> methodArgVarExprMap.get(arg.name()))
.collect(Collectors.toList());
Comment on lines +87 to +93
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding to create variable expr once issue, for method arguments, what I did here is to create a Map<String, VariableExpr> for method arguments, where key is argument's name and value is its variable expr.
Then I fetch the values from map to make a List<Expr> and reused in the below session.
What do you think of this approach. Welcome any suggestion. Thanks.

// Invoke current method based on return type.
// e.g. if return void, echoClient.echo(..); or,
// e.g. if return other type, EchoResponse response = echoClient.echo(...);
boolean returnsVoid = isProtoEmptyType(method.outputType());
Expr responseExpr = null;
if (returnsVoid) {
responseExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(clientVarExpr)
.setMethodName(JavaStyle.toLowerCamelCase(method.name()))
.setArguments(methodVarExprs)
.setReturnType(clientType)
.build();
} else {
responseExpr =
createAssignExprForVariableWithClientMethod(
createVariableExpr(RESPONSE, method.outputType()),
clientVarExpr,
JavaStyle.toLowerCamelCase(method.name()),
methodVarExprs);
}

List<Expr> bodyExpr = new ArrayList<>();
bodyExpr.addAll(methodArgumentsAssignmentExpr);
bodyExpr.add(responseExpr);

return TryCatchStatement.builder()
.setTryResourceExpr(assignClientVariableWithCreateMethodExpr(clientVarExpr))
.setTryBody(
Arrays.asList(
createLineCommentStatement(
"Note: Not implemented yet, placeholder for pure unary rpc method sample code.")))
bodyExpr.stream().map(e -> ExprStatement.withExpr(e)).collect(Collectors.toList()))
.setIsSampleCode(true)
.build();
}
Expand All @@ -89,6 +131,7 @@ private static TryCatchStatement composeLroUnaryRpcMethodSampleCode(
TypeNode clientType,
Map<String, ResourceName> resourceNames) {
// TODO(summerji): compose sample code for unary lro rpc method.
// TODO(summerji): Add unit tests.
VariableExpr clientVarExpr = createVariableExpr(getClientName(clientType), clientType);
return TryCatchStatement.builder()
.setTryResourceExpr(assignClientVariableWithCreateMethodExpr(clientVarExpr))
Expand All @@ -106,6 +149,7 @@ private static TryCatchStatement composePagedUnaryRpcMethodSampleCode(
TypeNode clientType,
Map<String, ResourceName> resourceNames) {
// TODO(summerji): compose sample code for unary paged rpc method.
// TODO(summerji): Add unit tests.
VariableExpr clientVarExpr = createVariableExpr(getClientName(clientType), clientType);
return TryCatchStatement.builder()
.setTryResourceExpr(assignClientVariableWithCreateMethodExpr(clientVarExpr))
Expand All @@ -116,7 +160,6 @@ private static TryCatchStatement composePagedUnaryRpcMethodSampleCode(
.setIsSampleCode(true)
.build();
}

// ==================================Helpers===================================================//

// Assign client variable expr with create client.
Expand All @@ -134,6 +177,55 @@ private static AssignmentExpr assignClientVariableWithCreateMethodExpr(
.build();
}

private static List<Expr> assignMethodArgumentsWithDefaultValues(
List<MethodArgument> arguments,
Map<String, VariableExpr> argVarExprs,
Map<String, ResourceName> resourceNames) {
return arguments.stream()
.map(
arg ->
createAssignmentExpr(
argVarExprs.get(arg.name()),
DefaultValueComposer.createDefaultValue(arg, resourceNames)))
.collect(Collectors.toList());
}

private static AssignmentExpr createAssignmentExpr(VariableExpr variableExpr, Expr valueExpr) {
return AssignmentExpr.builder()
.setVariableExpr(variableExpr.toBuilder().setIsDecl(true).build())
.setValueExpr(valueExpr)
.build();
}

private static Expr createAssignExprForVariableWithClientMethod(
VariableExpr variableExpr,
VariableExpr clientVarExpr,
String methodName,
List<Expr> argumentsVarExprs) {
MethodInvocationExpr clientMethodInvocationExpr =
MethodInvocationExpr.builder()
.setExprReferenceExpr(clientVarExpr)
.setMethodName(JavaStyle.toLowerCamelCase(methodName))
.setArguments(argumentsVarExprs)
.setReturnType(variableExpr.variable().type())
.build();
return AssignmentExpr.builder()
.setVariableExpr(variableExpr.toBuilder().setIsDecl(true).build())
.setValueExpr(clientMethodInvocationExpr)
.build();
}

private static Map<String, VariableExpr> mapMethodArgumentsToVariableExprs(
List<MethodArgument> arguments) {
return arguments.stream()
.collect(
Collectors.toMap(
methodArg -> methodArg.name(),
methodArg ->
createVariableExpr(
JavaStyle.toLowerCamelCase(methodArg.name()), methodArg.type())));
}

private static String getClientName(TypeNode clientType) {
return JavaStyle.toLowerCamelCase(clientType.reference().name());
}
Expand All @@ -157,4 +249,9 @@ private static VariableExpr createVariableExpr(
.setIsDecl(isDecl)
.build();
}

private static boolean isProtoEmptyType(TypeNode type) {
return type.reference().pakkage().equals("com.google.protobuf")
&& type.reference().name().equals("Empty");
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");\
// 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
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ TESTS = UPDATE_GOLDENS_TESTS + [
"DefaultValueComposerTest",
"ResourceNameTokenizerTest",
"RetrySettingsComposerTest",
"SampleCodeHelperComposerTest"
]

TEST_DEPS = [
Expand All @@ -38,6 +39,7 @@ TEST_DEPS = [
"//src/main/java/com/google/api/generator/gapic/protoparser",
"//src/test/java/com/google/api/generator/gapic/testdata:showcase_java_proto",
"//src/test/java/com/google/api/generator/gapic/testdata:testgapic_java_proto",
"@com_google_api_api_common//jar",
"@com_google_api_gax_java//gax",
"@com_google_googleapis//google/logging/v2:logging_java_proto",
"@com_google_googleapis//google/pubsub/v1:pubsub_java_proto",
Expand Down
Loading