Skip to content

Commit

Permalink
feat: ExecutableSampleComposer
Browse files Browse the repository at this point in the history
  • Loading branch information
eaball35 committed Dec 15, 2021
1 parent 6af0e18 commit 3dce467
Show file tree
Hide file tree
Showing 5 changed files with 439 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2021 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.gapic.composer.samplecode;

import com.google.api.generator.engine.ast.AssignmentExpr;
import com.google.api.generator.engine.ast.Statement;
import java.util.List;

public class ExecutableSample {
private final String samplePackage;
private final String sampleName;
private final List<AssignmentExpr> sampleVariableAssignments;
private final List<Statement> sampleBody;

public ExecutableSample(
String samplePackage,
String sampleName,
List<AssignmentExpr> sampleVariableAssignments,
List<Statement> sampleBody) {
this.samplePackage = samplePackage;
this.sampleName = sampleName;
this.sampleVariableAssignments = sampleVariableAssignments;
this.sampleBody = sampleBody;
}

public String getSamplePackage() {
return samplePackage;
}

public String getSampleName() {
return sampleName;
}

public List<AssignmentExpr> getSampleVariableAssignments() {
return sampleVariableAssignments;
}

public List<Statement> getSampleBody() {
return sampleBody;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright 2021 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.gapic.composer.samplecode;

import com.google.api.generator.engine.ast.AssignmentExpr;
import com.google.api.generator.engine.ast.ClassDefinition;
import com.google.api.generator.engine.ast.Expr;
import com.google.api.generator.engine.ast.ExprStatement;
import com.google.api.generator.engine.ast.MethodDefinition;
import com.google.api.generator.engine.ast.MethodInvocationExpr;
import com.google.api.generator.engine.ast.ScopeNode;
import com.google.api.generator.engine.ast.Statement;
import com.google.api.generator.engine.ast.TypeNode;
import com.google.api.generator.engine.ast.Variable;
import com.google.api.generator.engine.ast.VariableExpr;
import com.google.api.generator.gapic.utils.JavaStyle;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class ExecutableSampleComposer {
public static String createExecutableSample(ExecutableSample executableSample) {
Preconditions.checkNotNull(executableSample);
String sampleMethodName = JavaStyle.toLowerCamelCase(executableSample.getSampleName());
return SampleCodeWriter.write(
composeExecutableSample(
executableSample.getSamplePackage(),
sampleMethodName,
executableSample.getSampleVariableAssignments(),
executableSample.getSampleBody()));
}

private static ClassDefinition composeExecutableSample(
String packageName,
String sampleMethodName,
List<AssignmentExpr> sampleVariableAssignments,
List<Statement> sampleBody) {
String sampleClassName = JavaStyle.toUpperCamelCase(sampleMethodName);
List<VariableExpr> sampleMethodArgs = composeSampleMethodArgs(sampleVariableAssignments);
MethodDefinition mainMethod =
composeMainMethod(
composeMainBody(
sampleVariableAssignments,
composeInvokeMethodStatement(sampleMethodName, sampleMethodArgs)));
MethodDefinition sampleMethod =
composeSampleMethod(sampleMethodName, sampleMethodArgs, sampleBody);
return composeSampleClass(packageName, sampleClassName, mainMethod, sampleMethod);
}

private static List<VariableExpr> composeSampleMethodArgs(
List<AssignmentExpr> sampleVariableAssignments) {
return sampleVariableAssignments.stream()
.map(v -> v.variableExpr().toBuilder().setIsDecl(true).build())
.collect(Collectors.toList());
}

private static Statement composeInvokeMethodStatement(
String sampleMethodName, List<VariableExpr> sampleMethodArgs) {
List<Expr> invokeArgs =
sampleMethodArgs.stream()
.map(arg -> arg.toBuilder().setIsDecl(false).build())
.collect(Collectors.toList());
return ExprStatement.withExpr(
MethodInvocationExpr.builder()
.setMethodName(sampleMethodName)
.setArguments(invokeArgs)
.build());
}

private static List<Statement> composeMainBody(
List<AssignmentExpr> sampleVariableAssignments, Statement invokeMethod) {
List<ExprStatement> setVariables =
sampleVariableAssignments.stream()
.map(var -> ExprStatement.withExpr(var))
.collect(Collectors.toList());
List<Statement> body = new ArrayList<>(setVariables);
body.add(invokeMethod);
return body;
}

private static ClassDefinition composeSampleClass(
String packageName,
String sampleClassName,
MethodDefinition mainMethod,
MethodDefinition sampleMethod) {
return ClassDefinition.builder()
.setScope(ScopeNode.PUBLIC)
.setPackageString(packageName)
.setName(sampleClassName)
.setMethods(ImmutableList.of(mainMethod, sampleMethod))
.build();
}

private static MethodDefinition composeMainMethod(List<Statement> mainBody) {
return MethodDefinition.builder()
.setScope(ScopeNode.PUBLIC)
.setIsStatic(true)
.setReturnType(TypeNode.VOID)
.setName("main")
.setArguments(
VariableExpr.builder()
.setVariable(
Variable.builder().setType(TypeNode.STRING_ARRAY).setName("args").build())
.setIsDecl(true)
.build())
.setThrowsExceptions(Arrays.asList(TypeNode.withExceptionClazz(Exception.class)))
.setBody(mainBody)
.build();
}

private static MethodDefinition composeSampleMethod(
String sampleMethodName,
List<VariableExpr> sampleMethodArgs,
List<Statement> sampleMethodBody) {
return MethodDefinition.builder()
.setScope(ScopeNode.PUBLIC)
.setIsStatic(true)
.setReturnType(TypeNode.VOID)
.setName(sampleMethodName)
.setArguments(sampleMethodArgs)
.setThrowsExceptions(Arrays.asList(TypeNode.withExceptionClazz(Exception.class)))
.setBody(sampleMethodBody)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package com.google.api.generator.gapic.composer.samplecode;

import com.google.api.generator.engine.ast.ClassDefinition;
import com.google.api.generator.engine.ast.Statement;
import com.google.api.generator.engine.writer.JavaWriterVisitor;
import java.util.Arrays;
Expand All @@ -34,4 +35,10 @@ public static String write(List<Statement> statements) {
// Escape character "@" in the markdown code block <pre>{@code...} tags.
return formattedSampleCode.replaceAll("@", "{@literal @}");
}

public static String write(ClassDefinition classDefinition) {
JavaWriterVisitor visitor = new JavaWriterVisitor();
classDefinition.accept(visitor);
return visitor.write();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ TESTS = [
"SampleCodeWriterTest",
"ServiceClientSampleCodeComposerTest",
"SettingsSampleCodeComposerTest",
"ExecutableSampleComposerTest"
]

filegroup(
Expand Down
Loading

0 comments on commit 3dce467

Please sign in to comment.