Skip to content

Commit 4bd876e

Browse files
authored
Codegen the partitions data (#4789)
Instead of embedding the JSON string and parsing it at runtime
1 parent 6d36235 commit 4bd876e

File tree

1 file changed

+136
-40
lines changed

1 file changed

+136
-40
lines changed

codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/DefaultPartitionDataProviderSpec.java

Lines changed: 136 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,49 @@
1919
import com.squareup.javapoet.CodeBlock;
2020
import com.squareup.javapoet.FieldSpec;
2121
import com.squareup.javapoet.MethodSpec;
22-
import com.squareup.javapoet.ParameterizedTypeName;
2322
import com.squareup.javapoet.TypeSpec;
2423
import java.io.IOException;
2524
import java.io.InputStream;
2625
import java.io.UncheckedIOException;
26+
import java.util.Map;
2727
import javax.lang.model.element.Modifier;
2828
import software.amazon.awssdk.annotations.SdkInternalApi;
2929
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
3030
import software.amazon.awssdk.codegen.poet.ClassSpec;
3131
import software.amazon.awssdk.codegen.poet.PoetUtils;
3232
import software.amazon.awssdk.protocols.jsoncore.JsonNode;
3333
import software.amazon.awssdk.utils.IoUtils;
34-
import software.amazon.awssdk.utils.Lazy;
3534
import software.amazon.awssdk.utils.Validate;
3635

3736
public class DefaultPartitionDataProviderSpec implements ClassSpec {
37+
// partitions
38+
private static final String VERSION = "version";
39+
private static final String PARTITIONS = "partitions";
40+
// partition
41+
private static final String ID = "id";
42+
private static final String REGION_REGEX = "regionRegex";
43+
private static final String REGIONS = "regions";
44+
private static final String OUTPUTS = "outputs";
45+
// outputs
46+
private static final String DNS_SUFFIX = "dnsSuffix";
47+
private static final String DUAL_STACK_DNS_SUFFIX = "dualStackDnsSuffix";
48+
private static final String SUPPORTS_FIPS = "supportsFIPS";
49+
private static final String SUPPORTS_DUAL_STACK = "supportsDualStack";
50+
3851
private final IntermediateModel model;
3952
private final EndpointRulesSpecUtils endpointRulesSpecUtils;
40-
4153
private final ClassName partitionsClass;
54+
private final ClassName partitionClass;
55+
private final ClassName regionOverrideClass;
56+
private final ClassName outputsClass;
4257

4358
public DefaultPartitionDataProviderSpec(IntermediateModel model) {
4459
this.model = model;
4560
this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(model);
4661
this.partitionsClass = endpointRulesSpecUtils.rulesRuntimeClassName("Partitions");
62+
this.partitionClass = endpointRulesSpecUtils.rulesRuntimeClassName("Partition");
63+
this.regionOverrideClass = endpointRulesSpecUtils.rulesRuntimeClassName("RegionOverride");
64+
this.outputsClass = endpointRulesSpecUtils.rulesRuntimeClassName("Outputs");
4765
}
4866

4967
@Override
@@ -54,10 +72,8 @@ public TypeSpec poetSpec() {
5472
.addSuperinterface(
5573
endpointRulesSpecUtils.rulesRuntimeClassName("PartitionDataProvider"));
5674

57-
builder.addField(partitionDataField());
58-
builder.addField(partitionsLazyField());
75+
builder.addType(lazyPartitionsContainer());
5976
builder.addMethod(loadPartitionsMethod());
60-
builder.addMethod(doLoadPartitionsMethod());
6177
return builder.build();
6278
}
6379

@@ -68,44 +84,24 @@ public ClassName className() {
6884

6985
private MethodSpec loadPartitionsMethod() {
7086
MethodSpec.Builder builder = MethodSpec.methodBuilder("loadPartitions")
71-
.addAnnotation(Override.class)
72-
.addModifiers(Modifier.PUBLIC)
73-
.returns(partitionsClass);
74-
75-
builder.addStatement("return PARTITIONS.getValue()");
76-
77-
return builder.build();
78-
}
79-
80-
private FieldSpec partitionDataField() {
81-
FieldSpec.Builder builder = FieldSpec.builder(String.class, "DEFAULT_PARTITION_DATA", Modifier.PRIVATE,
82-
Modifier.STATIC, Modifier.FINAL);
83-
builder.initializer("$S", readPartitionsJson());
84-
return builder.build();
85-
}
86-
87-
private FieldSpec partitionsLazyField() {
88-
ParameterizedTypeName lazyType = ParameterizedTypeName.get(ClassName.get(Lazy.class),
89-
partitionsClass);
90-
FieldSpec.Builder builder = FieldSpec.builder(lazyType, "PARTITIONS")
91-
.addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL);
92-
CodeBlock init = CodeBlock.builder()
93-
.addStatement("new $T<>($T::doLoadPartitions)", Lazy.class, className())
94-
.build();
95-
96-
builder.initializer(init);
87+
.addAnnotation(Override.class)
88+
.addModifiers(Modifier.PUBLIC)
89+
.returns(partitionsClass);
9790

91+
builder.addStatement("return LazyPartitionsContainer.PARTITIONS");
9892
return builder.build();
9993
}
10094

101-
private MethodSpec doLoadPartitionsMethod() {
102-
MethodSpec.Builder builder = MethodSpec.methodBuilder("doLoadPartitions")
103-
.addModifiers(Modifier.PRIVATE, Modifier.STATIC)
104-
.returns(partitionsClass);
105-
106-
builder.addStatement("return $T.fromNode($T.parser().parse(DEFAULT_PARTITION_DATA))", partitionsClass, JsonNode.class);
107-
108-
return builder.build();
95+
private TypeSpec lazyPartitionsContainer() {
96+
CodeBlock.Builder builder = CodeBlock.builder();
97+
JsonNode node = JsonNode.parser().parse(readPartitionsJson());
98+
codegenPartitions(builder, node);
99+
return TypeSpec.classBuilder("LazyPartitionsContainer")
100+
.addModifiers(Modifier.STATIC)
101+
.addField(FieldSpec.builder(partitionsClass, "PARTITIONS", Modifier.STATIC, Modifier.FINAL)
102+
.initializer(builder.build())
103+
.build())
104+
.build();
109105
}
110106

111107
private String readPartitionsJson() {
@@ -132,4 +128,104 @@ private InputStream loadResource(String name) {
132128
Validate.notNull(resourceAsStream, "Failed to load resource from %s", name);
133129
return resourceAsStream;
134130
}
131+
132+
private void codegenPartitions(CodeBlock.Builder builder, JsonNode node) {
133+
builder.add("$T.builder()", partitionsClass);
134+
Map<String, JsonNode> objNode = node.asObject();
135+
136+
JsonNode version = objNode.get(VERSION);
137+
if (version != null) {
138+
builder.add(".version(");
139+
builder.add("$S", version.asString());
140+
builder.add(")");
141+
}
142+
143+
JsonNode partitions = objNode.get(PARTITIONS);
144+
if (partitions != null) {
145+
partitions.asArray().forEach(partNode -> {
146+
builder.add(".addPartition(");
147+
codegenPartition(builder, partNode);
148+
builder.add(")");
149+
});
150+
}
151+
builder.add(".build()");
152+
}
153+
154+
private void codegenPartition(CodeBlock.Builder builder, JsonNode node) {
155+
builder.add("$T.builder()", partitionClass);
156+
Map<String, JsonNode> objNode = node.asObject();
157+
158+
JsonNode id = objNode.get(ID);
159+
if (id != null) {
160+
builder.add(".id(");
161+
builder.add("$S", id.asString());
162+
builder.add(")");
163+
}
164+
165+
JsonNode regionRegex = objNode.get(REGION_REGEX);
166+
if (regionRegex != null) {
167+
builder.add(".regionRegex(");
168+
builder.add("$S", regionRegex.asString());
169+
builder.add(")");
170+
}
171+
172+
JsonNode regions = objNode.get(REGIONS);
173+
if (regions != null) {
174+
// At the moment `RegionOverride.fromNode` does nothing. We need to fix it here **and** if we keep the
175+
// loading from textual JSON also fix `RegionOverride.fromNode`.
176+
Map<String, JsonNode> regionsObj = regions.asObject();
177+
regionsObj.forEach((k, v) -> {
178+
builder.add(".putRegion($S, ", k);
179+
codegenRegionOverride(builder, v);
180+
builder.add(")");
181+
});
182+
}
183+
184+
JsonNode outputs = objNode.get(OUTPUTS);
185+
if (outputs != null) {
186+
builder.add(".outputs(");
187+
codegenOutputs(builder, outputs);
188+
builder.add(")");
189+
}
190+
builder.add(".build()");
191+
}
192+
193+
private void codegenRegionOverride(CodeBlock.Builder builder, JsonNode node) {
194+
builder.add("$T.builder().build()", regionOverrideClass);
195+
}
196+
197+
private void codegenOutputs(CodeBlock.Builder builder, JsonNode node) {
198+
builder.add("$T.builder()", outputsClass);
199+
Map<String, JsonNode> objNode = node.asObject();
200+
201+
JsonNode dnsSuffix = objNode.get(DNS_SUFFIX);
202+
if (dnsSuffix != null) {
203+
builder.add(".dnsSuffix(");
204+
builder.add("$S", dnsSuffix.asString());
205+
builder.add(")");
206+
}
207+
208+
JsonNode dualStackDnsSuffix = objNode.get(DUAL_STACK_DNS_SUFFIX);
209+
if (dualStackDnsSuffix != null) {
210+
builder.add(".dualStackDnsSuffix(");
211+
builder.add("$S", dualStackDnsSuffix.asString());
212+
builder.add(")");
213+
}
214+
215+
JsonNode supportsFips = objNode.get(SUPPORTS_FIPS);
216+
if (supportsFips != null) {
217+
builder.add(".supportsFips(");
218+
builder.add("$L", supportsFips.asBoolean());
219+
builder.add(")");
220+
}
221+
222+
JsonNode supportsDualStack = objNode.get(SUPPORTS_DUAL_STACK);
223+
if (supportsDualStack != null) {
224+
builder.add(".supportsDualStack(");
225+
builder.add("$L", supportsDualStack.asBoolean());
226+
builder.add(")");
227+
}
228+
builder.add(".build()");
229+
}
135230
}
231+

0 commit comments

Comments
 (0)