|
21 | 21 | import static software.amazon.awssdk.codegen.internal.Utils.isMapShape; |
22 | 22 | import static software.amazon.awssdk.codegen.internal.Utils.isScalar; |
23 | 23 |
|
| 24 | +import java.util.Collections; |
24 | 25 | import java.util.List; |
25 | 26 | import java.util.Map; |
26 | 27 | import java.util.Optional; |
|
37 | 38 | import software.amazon.awssdk.codegen.model.intermediate.VariableModel; |
38 | 39 | import software.amazon.awssdk.codegen.model.service.Location; |
39 | 40 | import software.amazon.awssdk.codegen.model.service.Member; |
| 41 | +import software.amazon.awssdk.codegen.model.service.Operation; |
40 | 42 | import software.amazon.awssdk.codegen.model.service.ServiceModel; |
41 | 43 | import software.amazon.awssdk.codegen.model.service.Shape; |
42 | 44 | import software.amazon.awssdk.codegen.naming.NamingStrategy; |
43 | 45 | 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; |
44 | 50 | import software.amazon.awssdk.utils.StringUtils; |
45 | 51 | import software.amazon.awssdk.utils.Validate; |
46 | 52 |
|
@@ -349,17 +355,38 @@ private boolean isGreedy(Shape parentShape, Map<String, Shape> allC2jShapes, Par |
349 | 355 | * Given an input shape, finds the Request URI for the operation that input is referenced from. |
350 | 356 | * Per the Smithy spec, httpLabel on non-input shapes has no meaning and is ignored, |
351 | 357 | * so this returns Optional.empty() if the shape is not a direct operation input. |
352 | | - * |
353 | | - * @param parentShape Shape to find operation's request URI for. |
354 | | - * @param allC2jShapes All shapes in the service model. |
355 | | - * @return Request URI for operation, or empty if the shape is not a direct operation input. |
| 358 | + * If the shape IS a direct operation input but the operation is missing a requestUri, |
| 359 | + * a validation error is thrown. |
356 | 360 | */ |
357 | 361 | 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()); |
| 362 | + Optional<Operation> operation = builder.getService().getOperations().values().stream() |
| 363 | + .filter(o -> o.getInput() != null) |
| 364 | + .filter(o -> allC2jShapes.get(o.getInput().getShape()).equals(parentShape)) |
| 365 | + .findFirst(); |
| 366 | + |
| 367 | + if (!operation.isPresent()) { |
| 368 | + // Not a direct operation input shape, should be ignored. |
| 369 | + // https://smithy.io/2.0/spec/http-bindings.html#httplabel-is-only-used-on-top-level-input |
| 370 | + return Optional.empty(); |
| 371 | + } |
| 372 | + |
| 373 | + String requestUri = operation.get().getHttp().getRequestUri(); |
| 374 | + if (requestUri == null) { |
| 375 | + String shapeName = allC2jShapes.entrySet().stream() |
| 376 | + .filter(e -> e.getValue().equals(parentShape)) |
| 377 | + .map(Map.Entry::getKey) |
| 378 | + .findFirst() |
| 379 | + .get(); |
| 380 | + String detailMsg = "Could not find request URI for input shape '" + shapeName |
| 381 | + + "'. No operation was found that references this shape as its input."; |
| 382 | + ValidationEntry entry = |
| 383 | + new ValidationEntry().withErrorId(ValidationErrorId.REQUEST_URI_NOT_FOUND) |
| 384 | + .withDetailMessage(detailMsg) |
| 385 | + .withSeverity(ValidationErrorSeverity.DANGER); |
| 386 | + throw ModelInvalidException.builder().validationEntries(Collections.singletonList(entry)).build(); |
| 387 | + } |
| 388 | + |
| 389 | + return Optional.of(requestUri); |
363 | 390 | } |
364 | 391 |
|
365 | 392 | private String deriveUnmarshallerLocationName(Shape memberShape, String memberName, Member member) { |
|
0 commit comments