Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,11 @@ public MethodSpec recordAccountIdEndpointModeMethod() {
+ ".ifPresent(m -> executionAttributes.getAttribute($T.BUSINESS_METRICS).addMetric(m))",
BusinessMetricsUtils.class, SdkInternalExecutionAttribute.class);

builder.addStatement("return mode.name().toLowerCase()");
// Use endpointModeValue() rather than name().toLowerCase() so that the returned String is an interned
// compile-time literal. That keeps the reference stable across calls and removes a per-request allocation.
// It also avoids name().toLowerCase()'s dependence on the default locale, which mangles the value under a
// Turkish locale.
builder.addStatement("return mode.endpointModeValue()");

return builder.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,22 @@
import com.fasterxml.jackson.jr.stree.JrsString;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.TypeVariableName;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.lang.model.element.Modifier;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.awscore.AwsExecutionAttribute;
Expand Down Expand Up @@ -119,6 +123,7 @@ public TypeSpec poetSpec() {

b.addMethod(setStaticContextParamsMethod());
addStaticContextParamMethods(b);
addStaticListFields(b);

b.addMethod(authSchemeWithEndpointSignerPropertiesMethod());

Expand Down Expand Up @@ -342,9 +347,8 @@ private MethodSpec addStaticContextParamsMethod(OperationModel opModel) {
b.addStatement("params.$N($L)", setterName, ((JrsBoolean) value).booleanValue());
break;
case START_ARRAY:
JrsArray arrayValue = (JrsArray) value;
CodeBlock arrayCode = endpointRulesSpecUtils.treeNodeToLiteral(arrayValue);
b.addStatement("params.$N($L)", setterName, arrayCode);
String fieldName = staticListFieldName(opModel, n);
b.addStatement("params.$N($N)", setterName, fieldName);
break;
default:
throw new RuntimeException("Don't know how to set parameter of type " + value.asToken());
Expand All @@ -358,6 +362,57 @@ private String staticContextParamsMethodName(OperationModel opModel) {
return opModel.getMethodName() + "StaticContextParams";
}

/**
* Generates the name of the {@code static final List<String>} field holding the static array value of
* {@code paramName} for {@code opModel}.
*
* <p>Format: {@code STATIC_LIST_{OPERATION}_{PARAM}}
*/
private static String staticListFieldName(OperationModel opModel, String paramName) {
return "STATIC_LIST_" + screamCase(opModel.getOperationName()) + "_" + screamCase(paramName);
}

private static String screamCase(String word) {
return Stream.of(CodegenNamingUtils.splitOnWordBoundaries(word))
.map(s -> s.toUpperCase(Locale.US))
.collect(Collectors.joining("_"));
}

/**
* Generates a {@code private static final List<String>} field for every {@code staticContextParams} entry whose
* value is an array, so that {@code setStaticContextParams} hands the same list reference to the endpoint params
* builder on every call rather than constructing a new list each time.
*/
private void addStaticListFields(TypeSpec.Builder classBuilder) {
ParameterizedTypeName listOfString = ParameterizedTypeName.get(List.class, String.class);

model.getOperations().forEach((opName, opModel) -> {
Map<String, StaticContextParam> statics = opModel.getStaticContextParams();
if (CollectionUtils.isNullOrEmpty(statics)) {
return;
}
statics.forEach((paramName, scp) -> {
TreeNode value = scp.getValue();
if (value.asToken() != JsonToken.START_ARRAY) {
return;
}
JrsArray arrayValue = (JrsArray) value;
CodeBlock initializer;
if (arrayValue.size() == 0) {
initializer = CodeBlock.of("$T.emptyList()", Collections.class);
} else {
initializer = CodeBlock.of("$T.unmodifiableList($L)", Collections.class,
endpointRulesSpecUtils.treeNodeToLiteral(arrayValue));
}
FieldSpec field = FieldSpec.builder(listOfString, staticListFieldName(opModel, paramName),
Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
.initializer(initializer)
.build();
classBuilder.addField(field);
});
});
}

private boolean hasStaticContextParams(OperationModel opModel) {
Map<String, StaticContextParam> staticContextParams = opModel.getStaticContextParams();
return staticContextParams != null && !staticContextParams.isEmpty();
Expand Down
Loading
Loading