
software.amazon.awssdk.codegen.poet.client.DelegatingSyncClientClass Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of codegen Show documentation
Show all versions of codegen Show documentation
The AWS SDK for Java - Code Generator module holds the classes and templates required to generate the
AWS Java SDK clients for AWS services.
The newest version!
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.codegen.poet.client;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static javax.lang.model.element.Modifier.ABSTRACT;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PROTECTED;
import static javax.lang.model.element.Modifier.PUBLIC;
import static software.amazon.awssdk.codegen.poet.client.AsyncClientInterface.STREAMING_TYPE_VARIABLE;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.TypeVariableName;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.codegen.docs.SimpleMethodOverload;
import software.amazon.awssdk.codegen.model.config.customization.UtilitiesMethod;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.model.intermediate.OperationModel;
import software.amazon.awssdk.codegen.poet.PoetExtension;
import software.amazon.awssdk.codegen.poet.PoetUtils;
import software.amazon.awssdk.core.SdkClient;
import software.amazon.awssdk.utils.Validate;
public class DelegatingSyncClientClass extends SyncClientInterface {
private final IntermediateModel model;
private final ClassName className;
private final PoetExtension poetExtensions;
public DelegatingSyncClientClass(IntermediateModel model) {
super(model);
this.model = model;
this.className = ClassName.get(model.getMetadata().getFullClientPackageName(),
"Delegating" + model.getMetadata().getSyncInterface());
this.poetExtensions = new PoetExtension(model);
}
@Override
protected void addInterfaceClass(TypeSpec.Builder type) {
ClassName interfaceClass = poetExtensions.getClientClass(model.getMetadata().getSyncInterface());
type.addSuperinterface(interfaceClass)
.addMethod(constructor(interfaceClass));
}
@Override
protected TypeSpec.Builder createTypeSpec() {
return PoetUtils.createClassBuilder(className);
}
@Override
protected void addAnnotations(TypeSpec.Builder type) {
type.addAnnotation(SdkPublicApi.class);
}
@Override
protected void addModifiers(TypeSpec.Builder type) {
type.addModifiers(ABSTRACT, PUBLIC);
}
@Override
protected void addFields(TypeSpec.Builder type) {
ClassName interfaceClass = poetExtensions.getClientClass(model.getMetadata().getSyncInterface());
type.addField(FieldSpec.builder(interfaceClass, "delegate")
.addModifiers(PRIVATE, FINAL)
.build());
}
@Override
protected void addConsumerMethod(List specs, MethodSpec spec, SimpleMethodOverload overload,
OperationModel opModel) {
}
@Override
protected void addAdditionalMethods(TypeSpec.Builder type) {
type.addMethod(nameMethod())
.addMethod(delegateMethod())
.addMethod(invokeMethod());
}
@Override
protected void addCloseMethod(TypeSpec.Builder type) {
MethodSpec method = MethodSpec.methodBuilder("close")
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addStatement("delegate.close()")
.build();
type.addMethod(method);
}
@Override
protected List operations() {
return model.getOperations().values().stream()
// TODO Sync not supported for event streaming yet. Revisit after sync/async merge
.filter(o -> !o.hasEventStreamInput())
.filter(o -> !o.hasEventStreamOutput())
.flatMap(this::operations)
.sorted(Comparator.comparing(m -> m.name))
.collect(toList());
}
private Stream operations(OperationModel opModel) {
List methods = new ArrayList<>();
methods.add(traditionalMethod(opModel));
return methods.stream();
}
@Override
public ClassName className() {
return className;
}
@Override
protected MethodSpec.Builder simpleMethodModifier(MethodSpec.Builder builder) {
return builder.addAnnotation(Override.class);
}
protected MethodSpec traditionalMethod(OperationModel opModel) {
MethodSpec.Builder builder = operationMethodSignature(model, opModel);
return operationBody(builder, opModel).build();
}
@Override
protected MethodSpec.Builder operationBody(MethodSpec.Builder builder, OperationModel opModel) {
builder.addModifiers(PUBLIC)
.addAnnotation(Override.class);
if (builder.parameters.isEmpty()) {
throw new IllegalStateException("All client methods must have an argument");
}
List operationParameters = new ArrayList<>(builder.parameters);
String requestParameter = operationParameters.remove(0).name;
String additionalParameters = String.format(", %s", operationParameters.stream().map(p -> p.name).collect(joining(", ")));
builder.addStatement("return invokeOperation($N, request -> delegate.$N(request$N))",
requestParameter,
opModel.getMethodName(),
operationParameters.isEmpty() ? "" : additionalParameters);
return builder;
}
@Override
protected MethodSpec.Builder utilitiesOperationBody(MethodSpec.Builder builder) {
return builder.addAnnotation(Override.class).addStatement("return delegate.$N()", UtilitiesMethod.METHOD_NAME);
}
@Override
protected MethodSpec.Builder waiterOperationBody(MethodSpec.Builder builder) {
return builder.addAnnotation(Override.class).addStatement("return delegate.waiter()");
}
private MethodSpec constructor(ClassName interfaceClass) {
return MethodSpec.constructorBuilder()
.addModifiers(PUBLIC)
.addParameter(interfaceClass, "delegate")
.addStatement("$T.paramNotNull(delegate, \"delegate\")", Validate.class)
.addStatement("this.delegate = delegate")
.build();
}
private MethodSpec nameMethod() {
return MethodSpec.methodBuilder("serviceName")
.addAnnotation(Override.class)
.addModifiers(PUBLIC, FINAL)
.returns(String.class)
.addStatement("return delegate.serviceName()")
.build();
}
private MethodSpec delegateMethod() {
return MethodSpec.methodBuilder("delegate")
.addModifiers(PUBLIC)
.addStatement("return this.delegate")
.returns(SdkClient.class)
.build();
}
private MethodSpec invokeMethod() {
TypeVariableName requestTypeVariableName =
TypeVariableName.get("T", poetExtensions.getModelClass(model.getSdkRequestBaseClassName()));
TypeVariableName responseTypeVariableName = STREAMING_TYPE_VARIABLE;
ParameterizedTypeName functionTypeName = ParameterizedTypeName
.get(ClassName.get(Function.class), requestTypeVariableName, responseTypeVariableName);
return MethodSpec.methodBuilder("invokeOperation")
.addModifiers(PROTECTED)
.addParameter(requestTypeVariableName, "request")
.addParameter(functionTypeName, "operation")
.addTypeVariable(requestTypeVariableName)
.addTypeVariable(responseTypeVariableName)
.returns(responseTypeVariableName)
.addStatement("return operation.apply(request)")
.build();
}
@Override
protected MethodSpec serviceClientConfigMethod() {
return MethodSpec.methodBuilder("serviceClientConfiguration")
.addAnnotation(Override.class)
.addModifiers(PUBLIC, FINAL)
.returns(new PoetExtension(model).getServiceConfigClass())
.addStatement("return delegate.serviceClientConfiguration()")
.build();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy