Skip to content

Commit 65d1968

Browse files
committed
Fix codegen logic to allow non input shape uri bound member
1 parent ff912a7 commit 65d1968

File tree

2 files changed

+18
-42
lines changed

2 files changed

+18
-42
lines changed

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

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import static software.amazon.awssdk.codegen.internal.Utils.isMapShape;
2222
import static software.amazon.awssdk.codegen.internal.Utils.isScalar;
2323

24-
import java.util.Collections;
2524
import java.util.List;
2625
import java.util.Map;
2726
import java.util.Optional;
@@ -38,15 +37,10 @@
3837
import software.amazon.awssdk.codegen.model.intermediate.VariableModel;
3938
import software.amazon.awssdk.codegen.model.service.Location;
4039
import software.amazon.awssdk.codegen.model.service.Member;
41-
import software.amazon.awssdk.codegen.model.service.Operation;
4240
import software.amazon.awssdk.codegen.model.service.ServiceModel;
4341
import software.amazon.awssdk.codegen.model.service.Shape;
4442
import software.amazon.awssdk.codegen.naming.NamingStrategy;
4543
import software.amazon.awssdk.codegen.utils.ProtocolUtils;
46-
import software.amazon.awssdk.codegen.validation.ModelInvalidException;
47-
import software.amazon.awssdk.codegen.validation.ValidationEntry;
48-
import software.amazon.awssdk.codegen.validation.ValidationErrorId;
49-
import software.amazon.awssdk.codegen.validation.ValidationErrorSeverity;
5044
import software.amazon.awssdk.utils.StringUtils;
5145
import software.amazon.awssdk.utils.Validate;
5246

@@ -342,9 +336,9 @@ private boolean isRequiredMember(String memberName, Shape memberShape) {
342336
*/
343337
private boolean isGreedy(Shape parentShape, Map<String, Shape> allC2jShapes, ParameterHttpMapping mapping) {
344338
if (mapping.getLocation() == Location.URI) {
345-
// If the location is URI we can assume the parent shape is an input shape.
346-
String requestUri = findRequestUri(parentShape, allC2jShapes);
347-
if (requestUri.contains(String.format("{%s+}", mapping.getMarshallLocationName()))) {
339+
Optional<String> requestUri = findRequestUri(parentShape, allC2jShapes);
340+
if (requestUri.isPresent()
341+
&& requestUri.get().contains(String.format("{%s+}", mapping.getMarshallLocationName()))) {
348342
return true;
349343
}
350344
}
@@ -353,33 +347,19 @@ private boolean isGreedy(Shape parentShape, Map<String, Shape> allC2jShapes, Par
353347

354348
/**
355349
* Given an input shape, finds the Request URI for the operation that input is referenced from.
350+
* Per the Smithy spec, httpLabel on non-input shapes has no meaning and is ignored,
351+
* so this returns Optional.empty() if the shape is not a direct operation input.
356352
*
357-
* @param parentShape Input shape to find operation's request URI for.
353+
* @param parentShape Shape to find operation's request URI for.
358354
* @param allC2jShapes All shapes in the service model.
359-
* @return Request URI for operation.
360-
* @throws RuntimeException If operation can't be found.
355+
* @return Request URI for operation, or empty if the shape is not a direct operation input.
361356
*/
362-
private String findRequestUri(Shape parentShape, Map<String, Shape> allC2jShapes) {
363-
Optional<Operation> operation = builder.getService().getOperations().values().stream()
364-
.filter(o -> o.getInput() != null)
365-
.filter(o -> allC2jShapes.get(o.getInput().getShape()).equals(parentShape))
366-
.findFirst();
367-
368-
return operation.map(o -> o.getHttp().getRequestUri())
369-
.orElseThrow(() -> {
370-
String shapeName = allC2jShapes.entrySet().stream()
371-
.filter(e -> e.getValue().equals(parentShape))
372-
.map(Map.Entry::getKey)
373-
.findFirst()
374-
.orElse("unknown");
375-
String detailMsg = "Could not find request URI for input shape '" + shapeName
376-
+ "'. No operation was found that references this shape as its input.";
377-
ValidationEntry entry =
378-
new ValidationEntry().withErrorId(ValidationErrorId.REQUEST_URI_NOT_FOUND)
379-
.withDetailMessage(detailMsg)
380-
.withSeverity(ValidationErrorSeverity.DANGER);
381-
return ModelInvalidException.builder().validationEntries(Collections.singletonList(entry)).build();
382-
});
357+
private Optional<String> findRequestUri(Shape parentShape, Map<String, Shape> allC2jShapes) {
358+
return builder.getService().getOperations().values().stream()
359+
.filter(o -> o.getInput() != null)
360+
.filter(o -> allC2jShapes.get(o.getInput().getShape()).equals(parentShape))
361+
.findFirst()
362+
.map(o -> o.getHttp().getRequestUri());
383363
}
384364

385365
private String deriveUnmarshallerLocationName(Shape memberShape, String memberName, Member member) {

codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package software.amazon.awssdk.codegen;
1717

1818
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.assertj.core.api.Assertions.assertThatNoException;
1920
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2021
import static org.mockito.ArgumentMatchers.any;
2122
import static org.mockito.Mockito.mock;
@@ -178,20 +179,15 @@ void execute_endpointsTestReferencesUnknownOperationMember_throwsValidationError
178179
}
179180

180181
@Test
181-
void execute_uriLocationOnNonInputShape_throwsValidationErrorWithShapeName() throws IOException {
182+
void execute_uriLocationOnNonInputShape_isIgnored() throws IOException {
182183
C2jModels models = C2jModels.builder()
183184
.customizationConfig(CustomizationConfig.create())
184185
.serviceModel(getUriOnNonInputShapeServiceModel())
185186
.build();
186187

187-
assertThatThrownBy(() -> generateCodeFromC2jModels(models, outputDir, true, Collections.emptyList()))
188-
.isInstanceOf(ModelInvalidException.class)
189-
.matches(e -> {
190-
ModelInvalidException ex = (ModelInvalidException) e;
191-
ValidationEntry entry = ex.validationEntries().get(0);
192-
return entry.getErrorId() == ValidationErrorId.REQUEST_URI_NOT_FOUND
193-
&& entry.getDetailMessage().contains("No operation was found");
194-
});
188+
// Per the Smithy spec, httpLabel on non-input shapes has no meaning and is simply ignored.
189+
assertThatNoException().isThrownBy(
190+
() -> generateCodeFromC2jModels(models, outputDir, true, Collections.emptyList()));
195191
}
196192

197193
@Test

0 commit comments

Comments
 (0)