Skip to content

Commit bcb29c0

Browse files
authored
[Endpoints BDD 1/5] BDD endpoint model and infrastructure (#7302)
Add the foundational infrastructure for BDD (Binary Decision Diagram) endpoint resolution without the code generation visitors themselves: Model loading: - EndpointBddModel: parse BDD JSON (endpoint-bdd-1.json) with node graph, conditions, results, and parameters - C2jModels/IntermediateModel: wire EndpointBddModel into the codegen model pipeline - GenerationMojo: discover endpoint-bdd-1.json in codegen-resources Expression/type extensions: - ExpressionParser: support parseExpressionFrom for BDD result templates, negative indexed access, direct negative index syntax - Tokenizer: add directNegativeIndexedAccess and consumeDirectNegative support for BDD template expressions - RuleRuntimeTypeMirror: add LIST_OF_STRING, coalesce return type - EndpointUrlCodeEmitter: add urlFromExpression for BDD url emission - StringConcatExpression: add needsParenthesization flag Runtime additions (RulesFunctions.java.resource): - coalesce(T... args) / coalesce(String... args) - split(value, delimiter, limit) - ite(condition, ifTrue, ifFalse) - listAccess: support negative indices Supporting: - EndpointRulesSpecUtils: simplify rulesEngineFilesFromDirectory - EndpointProviderTestSpec: BDD test case loading support - EndpointProviderTestCase: add bddEndpointProvider field
1 parent 858c1dc commit bcb29c0

13 files changed

Lines changed: 366 additions & 24 deletions

File tree

codegen-maven-plugin/src/main/java/software/amazon/awssdk/codegen/maven/plugin/GenerationMojo.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig;
4343
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
4444
import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel;
45+
import software.amazon.awssdk.codegen.model.service.EndpointBddModel;
4546
import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel;
4647
import software.amazon.awssdk.codegen.model.service.Paginators;
4748
import software.amazon.awssdk.codegen.model.service.ServiceModel;
@@ -62,6 +63,7 @@ public class GenerationMojo extends AbstractMojo {
6263
private static final String PAGINATORS_FILE = "paginators-1.json";
6364
private static final String ENDPOINT_RULE_SET_FILE = "endpoint-rule-set.json";
6465
private static final String ENDPOINT_TESTS_FILE = "endpoint-tests.json";
66+
private static final String ENDPOINT_BDD_FILE = "endpoint-bdd-1.json";
6567

6668

6769
@Parameter(property = "codeGenResources", defaultValue = "${basedir}/src/main/resources/codegen-resources/")
@@ -144,6 +146,7 @@ private List<GenerationParams> initGenerationParams() throws MojoExecutionExcept
144146
.waitersModel(loadWaiterModel(modelRootPath))
145147
.paginatorsModel(loadPaginatorModel(modelRootPath))
146148
.endpointRuleSetModel(loadEndpointRuleSetModel(modelRootPath))
149+
.endpointBddModel(loadEndpointBddModel(modelRootPath))
147150
.endpointTestSuiteModel(loadEndpointTestSuiteModel(modelRootPath))
148151
.build();
149152
String intermediateModelFileNamePrefix = intermediateModelFileNamePrefix(c2jModels);
@@ -218,6 +221,10 @@ private EndpointTestSuiteModel loadEndpointTestSuiteModel(Path root) {
218221
return loadOptionalModel(EndpointTestSuiteModel.class, root.resolve(ENDPOINT_TESTS_FILE)).orElse(null);
219222
}
220223

224+
private EndpointBddModel loadEndpointBddModel(Path root) {
225+
return loadOptionalModel(EndpointBddModel.class, root.resolve(ENDPOINT_BDD_FILE)).orElse(null);
226+
}
227+
221228
/**
222229
* Load required model from the project resources.
223230
*/

codegen/src/main/java/software/amazon/awssdk/codegen/C2jModels.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig;
1919
import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel;
20+
import software.amazon.awssdk.codegen.model.service.EndpointBddModel;
2021
import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel;
2122
import software.amazon.awssdk.codegen.model.service.Paginators;
2223
import software.amazon.awssdk.codegen.model.service.ServiceModel;
@@ -32,19 +33,22 @@ public class C2jModels {
3233
private final Waiters waitersModel;
3334
private final EndpointRuleSetModel endpointRuleSetModel;
3435
private final EndpointTestSuiteModel endpointTestSuiteModel;
36+
private final EndpointBddModel endpointBddModel;
3537
private final CustomizationConfig customizationConfig;
3638
private final Paginators paginatorsModel;
3739

3840
private C2jModels(ServiceModel serviceModel,
3941
Waiters waitersModel,
4042
EndpointRuleSetModel endpointRuleSetModel,
4143
EndpointTestSuiteModel endpointTestSuiteModel,
44+
EndpointBddModel endpointBddModel,
4245
CustomizationConfig customizationConfig,
4346
Paginators paginatorsModel) {
4447
this.serviceModel = serviceModel;
4548
this.waitersModel = waitersModel;
4649
this.endpointRuleSetModel = endpointRuleSetModel;
4750
this.endpointTestSuiteModel = endpointTestSuiteModel;
51+
this.endpointBddModel = endpointBddModel;
4852
this.customizationConfig = customizationConfig;
4953
this.paginatorsModel = paginatorsModel;
5054
}
@@ -77,12 +81,17 @@ public EndpointTestSuiteModel endpointTestSuiteModel() {
7781
return endpointTestSuiteModel;
7882
}
7983

84+
public EndpointBddModel endpointBddModel() {
85+
return endpointBddModel;
86+
}
87+
8088
public static class Builder implements SdkBuilder<Builder, C2jModels> {
8189

8290
private ServiceModel serviceModel;
8391
private Waiters waitersModel;
8492
private EndpointRuleSetModel endpointRuleSetModel;
8593
private EndpointTestSuiteModel endpointTestSuiteModel;
94+
private EndpointBddModel endpointBddModel;
8695
private CustomizationConfig customizationConfig;
8796
private Paginators paginatorsModel;
8897

@@ -119,12 +128,17 @@ public Builder endpointTestSuiteModel(EndpointTestSuiteModel endpointTestSuiteMo
119128
return this;
120129
}
121130

131+
public Builder endpointBddModel(EndpointBddModel endpointBddModel) {
132+
this.endpointBddModel = endpointBddModel;
133+
return this;
134+
}
135+
122136
@Override
123137
public C2jModels build() {
124138
Waiters waiters = waitersModel != null ? waitersModel : Waiters.none();
125139
Paginators paginators = paginatorsModel != null ? paginatorsModel : Paginators.none();
126-
return new C2jModels(serviceModel, waiters, endpointRuleSetModel, endpointTestSuiteModel, customizationConfig,
127-
paginators);
140+
return new C2jModels(serviceModel, waiters, endpointRuleSetModel, endpointTestSuiteModel, endpointBddModel,
141+
customizationConfig, paginators);
128142
}
129143
}
130144
}

codegen/src/main/java/software/amazon/awssdk/codegen/IntermediateModelBuilder.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel;
4040
import software.amazon.awssdk.codegen.model.service.AuthType;
4141
import software.amazon.awssdk.codegen.model.service.CustomOperationContextParam;
42+
import software.amazon.awssdk.codegen.model.service.EndpointBddModel;
4243
import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel;
4344
import software.amazon.awssdk.codegen.model.service.Operation;
4445
import software.amazon.awssdk.codegen.model.service.Paginators;
@@ -65,6 +66,7 @@ public class IntermediateModelBuilder {
6566
private final Waiters waiters;
6667
private final EndpointRuleSetModel endpointRuleSet;
6768
private final EndpointTestSuiteModel endpointTestSuiteModel;
69+
private final EndpointBddModel endpointBddModel;
6870

6971
public IntermediateModelBuilder(C2jModels models) {
7072
this.customConfig = models.customizationConfig();
@@ -76,6 +78,7 @@ public IntermediateModelBuilder(C2jModels models) {
7678
this.waiters = models.waitersModel();
7779
this.endpointRuleSet = models.endpointRuleSetModel();
7880
this.endpointTestSuiteModel = models.endpointTestSuiteModel();
81+
this.endpointBddModel = models.endpointBddModel();
7982
}
8083

8184

@@ -138,7 +141,8 @@ public IntermediateModel build() {
138141
IntermediateModel fullModel = new IntermediateModel(
139142
constructMetadata(service, customConfig), operations, shapes,
140143
customConfig, endpointOperation, paginators.getPagination(), namingStrategy,
141-
waiters.getWaiters(), endpointRuleSet, endpointTestSuiteModel, service.getClientContextParams());
144+
waiters.getWaiters(), endpointRuleSet, endpointTestSuiteModel, endpointBddModel,
145+
service.getClientContextParams());
142146

143147
customization.postprocess(fullModel);
144148

@@ -160,6 +164,7 @@ public IntermediateModel build() {
160164
fullModel.getWaiters(),
161165
fullModel.getEndpointRuleSetModel(),
162166
endpointTestSuiteModel,
167+
fullModel.getEndpointBddModel(),
163168
service.getClientContextParams());
164169

165170
linkMembersToShapes(trimmedModel);

codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/IntermediateModel.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig;
2929
import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel;
3030
import software.amazon.awssdk.codegen.model.service.ClientContextParam;
31+
import software.amazon.awssdk.codegen.model.service.EndpointBddModel;
3132
import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel;
3233
import software.amazon.awssdk.codegen.model.service.PaginatorDefinition;
3334
import software.amazon.awssdk.codegen.model.service.WaiterDefinition;
@@ -60,6 +61,9 @@ public final class IntermediateModel {
6061
@JsonIgnore
6162
private NamingStrategy namingStrategy;
6263

64+
@JsonIgnore
65+
private EndpointBddModel endpointBddModel;
66+
6367
private Map<String, ClientContextParam> clientContextParams;
6468

6569
static {
@@ -80,7 +84,7 @@ public IntermediateModel(Metadata metadata,
8084
Map<String, ShapeModel> shapes,
8185
CustomizationConfig customizationConfig) {
8286
this(metadata, operations, shapes, customizationConfig, null,
83-
Collections.emptyMap(), null, Collections.emptyMap(), null, null, null);
87+
Collections.emptyMap(), null, Collections.emptyMap(), null, null, null, null);
8488
}
8589

8690
public IntermediateModel(
@@ -94,6 +98,7 @@ public IntermediateModel(
9498
Map<String, WaiterDefinition> waiters,
9599
EndpointRuleSetModel endpointRuleSetModel,
96100
EndpointTestSuiteModel endpointTestSuiteModel,
101+
EndpointBddModel endpointBddModel,
97102
Map<String, ClientContextParam> clientContextParams) {
98103
this.metadata = metadata;
99104
this.operations = operations;
@@ -105,6 +110,7 @@ public IntermediateModel(
105110
this.waiters = waiters;
106111
this.endpointRuleSetModel = endpointRuleSetModel;
107112
this.endpointTestSuiteModel = endpointTestSuiteModel;
113+
this.endpointBddModel = endpointBddModel;
108114
this.clientContextParams = clientContextParams;
109115
}
110116

@@ -183,6 +189,10 @@ public EndpointTestSuiteModel getEndpointTestSuiteModel() {
183189
return endpointTestSuiteModel;
184190
}
185191

192+
public EndpointBddModel getEndpointBddModel() {
193+
return endpointBddModel;
194+
}
195+
186196
public Map<String, ClientContextParam> getClientContextParams() {
187197
return clientContextParams;
188198
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.codegen.model.service;
17+
18+
import java.nio.ByteBuffer;
19+
import java.util.ArrayList;
20+
import java.util.Base64;
21+
import java.util.List;
22+
import java.util.Map;
23+
import software.amazon.awssdk.codegen.model.rules.endpoints.ConditionModel;
24+
import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel;
25+
import software.amazon.awssdk.codegen.model.rules.endpoints.RuleModel;
26+
27+
public class EndpointBddModel {
28+
private String serviceId;
29+
private String version;
30+
private Map<String, ParameterModel> parameters;
31+
private List<ConditionModel> conditions;
32+
private List<RuleModel> results;
33+
private int root;
34+
private int nodeCount;
35+
private String nodes; // Base64-encoded binary representation of BDD nodes.
36+
37+
public String getServiceId() {
38+
return serviceId;
39+
}
40+
41+
public void setServiceId(String serviceId) {
42+
this.serviceId = serviceId;
43+
}
44+
45+
public String getVersion() {
46+
return version;
47+
}
48+
49+
public void setVersion(String version) {
50+
this.version = version;
51+
}
52+
53+
public Map<String, ParameterModel> getParameters() {
54+
return parameters;
55+
}
56+
57+
public void setParameters(Map<String, ParameterModel> parameters) {
58+
this.parameters = parameters;
59+
}
60+
61+
public List<ConditionModel> getConditions() {
62+
return conditions;
63+
}
64+
65+
public void setConditions(List<ConditionModel> conditions) {
66+
this.conditions = conditions;
67+
}
68+
69+
public List<RuleModel> getResults() {
70+
return results;
71+
}
72+
73+
public void setResults(List<RuleModel> results) {
74+
this.results = results;
75+
}
76+
77+
public String getNodes() {
78+
return nodes;
79+
}
80+
81+
public int getRoot() {
82+
return root;
83+
}
84+
85+
public void setRoot(int root) {
86+
this.root = root;
87+
}
88+
89+
public int getNodeCount() {
90+
return nodeCount;
91+
}
92+
93+
public void setNodeCount(int nodeCount) {
94+
this.nodeCount = nodeCount;
95+
}
96+
97+
public void setNodes(String nodes) {
98+
this.nodes = nodes;
99+
}
100+
101+
public List<BddNode> getDecodedNodes() {
102+
List<BddNode> out = new ArrayList<>(nodeCount);
103+
byte[] data = Base64.getDecoder().decode(nodes);
104+
ByteBuffer buf = ByteBuffer.wrap(data); // big-endian by default
105+
while (buf.remaining() >= 12) {
106+
int conditionIndex = buf.getInt();
107+
int highRef = buf.getInt();
108+
int lowRef = buf.getInt();
109+
out.add(new BddNode(conditionIndex, highRef, lowRef));
110+
}
111+
return out;
112+
}
113+
114+
public static class BddNode {
115+
int conditionIndex;
116+
int highRef;
117+
int lowRef;
118+
119+
public BddNode(int conditionIndex, int highRef, int lowRef) {
120+
this.conditionIndex = conditionIndex;
121+
this.highRef = highRef;
122+
this.lowRef = lowRef;
123+
}
124+
125+
public int getConditionIndex() {
126+
return conditionIndex;
127+
}
128+
129+
public int getHighRef() {
130+
return highRef;
131+
}
132+
133+
public int getLowRef() {
134+
return lowRef;
135+
}
136+
137+
@Override
138+
public String toString() {
139+
return "[C" + conditionIndex + ", " + highRef + ", " + lowRef + "]";
140+
}
141+
}
142+
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,9 @@ private MethodSpec testsCasesMethod() {
8787

8888
CustomizationConfig customizationConfig = model.getCustomizationConfig();
8989
model.getEndpointTestSuiteModel().getTestCases().forEach(test -> {
90-
b.addStatement("testCases.add(new $T($L, $L))",
90+
b.addStatement("testCases.add(new $T($S, $L, $L))",
9191
EndpointProviderTestCase.class,
92+
test.getDocumentation(),
9293
createTestCase(test),
9394
TestGeneratorUtils.createExpect(customizationConfig, test.getExpect(), null, null));
9495
});

0 commit comments

Comments
 (0)