From 0dd930dbfcbe0e490f8d36601d8e7ffef36de06d Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Thu, 12 Mar 2026 14:20:22 -0700 Subject: [PATCH 01/16] Include shape name in REQUEST_URI_NOT_FOUND validation error message --- .../amazon/awssdk/codegen/AddShapes.java | 8 ++- .../awssdk/codegen/CodeGeneratorTest.java | 23 ++++++++ .../uri-on-non-input-shape-service.json | 57 +++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 codegen/src/test/resources/software/amazon/awssdk/codegen/uri-on-non-input-shape-service.json diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java index 19600e33210e..55975faf69cd 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java @@ -367,7 +367,13 @@ private String findRequestUri(Shape parentShape, Map allC2jShapes return operation.map(o -> o.getHttp().getRequestUri()) .orElseThrow(() -> { - String detailMsg = "Could not find request URI for input shape for operation: " + operation; + String shapeName = allC2jShapes.entrySet().stream() + .filter(e -> e.getValue().equals(parentShape)) + .map(Map.Entry::getKey) + .findFirst() + .orElse("unknown"); + String detailMsg = "Could not find request URI for input shape '" + shapeName + + "'. No operation was found that references this shape as its input."; ValidationEntry entry = new ValidationEntry().withErrorId(ValidationErrorId.REQUEST_URI_NOT_FOUND) .withDetailMessage(detailMsg) diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java index 05a492ca24c4..0ce91b61b576 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java @@ -48,6 +48,7 @@ import software.amazon.awssdk.codegen.poet.ClientTestModels; import software.amazon.awssdk.codegen.validation.ModelInvalidException; import software.amazon.awssdk.codegen.validation.ModelValidator; +import software.amazon.awssdk.codegen.validation.ValidationEntry; import software.amazon.awssdk.codegen.validation.ValidationErrorId; public class CodeGeneratorTest { @@ -176,6 +177,23 @@ void execute_endpointsTestReferencesUnknownOperationMember_throwsValidationError }); } + @Test + void execute_uriLocationOnNonInputShape_throwsValidationErrorWithShapeName() throws IOException { + C2jModels models = C2jModels.builder() + .customizationConfig(CustomizationConfig.create()) + .serviceModel(getUriOnNonInputShapeServiceModel()) + .build(); + + assertThatThrownBy(() -> generateCodeFromC2jModels(models, outputDir, true, Collections.emptyList())) + .isInstanceOf(ModelInvalidException.class) + .matches(e -> { + ModelInvalidException ex = (ModelInvalidException) e; + ValidationEntry entry = ex.validationEntries().get(0); + return entry.getErrorId() == ValidationErrorId.REQUEST_URI_NOT_FOUND + && entry.getDetailMessage().contains("No operation was found"); + }); + } + @Test void execute_operationHasNoRequestUri_throwsValidationError() throws IOException { C2jModels models = C2jModels.builder() @@ -244,6 +262,11 @@ private ServiceModel getMissingRequestUriServiceModel() throws IOException { return Jackson.load(ServiceModel.class, json); } + private ServiceModel getUriOnNonInputShapeServiceModel() throws IOException { + String json = resourceAsString("uri-on-non-input-shape-service.json"); + return Jackson.load(ServiceModel.class, json); + } + private String resourceAsString(String name) throws IOException { ByteArrayOutputStream baos; try (InputStream resourceAsStream = getClass().getResourceAsStream(name)) { diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/uri-on-non-input-shape-service.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/uri-on-non-input-shape-service.json new file mode 100644 index 000000000000..7462f20501db --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/uri-on-non-input-shape-service.json @@ -0,0 +1,57 @@ +{ + "version": "2.0", + "metadata": { + "apiVersion": "2010-05-08", + "endpointPrefix": "json-service-endpoint", + "globalEndpoint": "json-service.amazonaws.com", + "protocol": "rest-json", + "serviceAbbreviation": "Rest Json Service", + "serviceFullName": "Some Service That Uses Rest-Json Protocol", + "serviceId": "Rest Json Service", + "signingName": "json-service", + "signatureVersion": "v4", + "uid": "json-service-2010-05-08", + "xmlNamespace": "https://json-service.amazonaws.com/doc/2010-05-08/" + }, + "operations": { + "SomeOperation": { + "name": "SomeOperation", + "http": { + "method": "POST", + "requestUri": "/things/{thingId}" + }, + "input": { + "shape": "SomeOperationRequest" + } + } + }, + "shapes": { + "SomeOperationRequest": { + "type": "structure", + "members": { + "thingId": { + "shape": "String", + "location": "uri", + "locationName": "thingId" + }, + "options": { + "shape": "NestedOptions" + } + } + }, + "NestedOptions": { + "type": "structure", + "members": { + "pageSize": { + "shape": "String", + "location": "uri", + "locationName": "pageSize" + } + } + }, + "String": { + "type": "string" + } + }, + "documentation": "A service with a uri-bound member on a non-input shape" +} From 2559160bedec22470e53005bf8a0911233ea16df Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Fri, 13 Mar 2026 11:50:26 -0700 Subject: [PATCH 02/16] Fix codegen logic to allow non input shape uri bound member --- .../amazon/awssdk/codegen/AddShapes.java | 46 ++++++------------- .../awssdk/codegen/CodeGeneratorTest.java | 14 ++---- 2 files changed, 18 insertions(+), 42 deletions(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java index 55975faf69cd..725bf8f38e62 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java @@ -21,7 +21,6 @@ import static software.amazon.awssdk.codegen.internal.Utils.isMapShape; import static software.amazon.awssdk.codegen.internal.Utils.isScalar; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -38,15 +37,10 @@ import software.amazon.awssdk.codegen.model.intermediate.VariableModel; import software.amazon.awssdk.codegen.model.service.Location; import software.amazon.awssdk.codegen.model.service.Member; -import software.amazon.awssdk.codegen.model.service.Operation; import software.amazon.awssdk.codegen.model.service.ServiceModel; import software.amazon.awssdk.codegen.model.service.Shape; import software.amazon.awssdk.codegen.naming.NamingStrategy; import software.amazon.awssdk.codegen.utils.ProtocolUtils; -import software.amazon.awssdk.codegen.validation.ModelInvalidException; -import software.amazon.awssdk.codegen.validation.ValidationEntry; -import software.amazon.awssdk.codegen.validation.ValidationErrorId; -import software.amazon.awssdk.codegen.validation.ValidationErrorSeverity; import software.amazon.awssdk.utils.StringUtils; import software.amazon.awssdk.utils.Validate; @@ -342,9 +336,9 @@ private boolean isRequiredMember(String memberName, Shape memberShape) { */ private boolean isGreedy(Shape parentShape, Map allC2jShapes, ParameterHttpMapping mapping) { if (mapping.getLocation() == Location.URI) { - // If the location is URI we can assume the parent shape is an input shape. - String requestUri = findRequestUri(parentShape, allC2jShapes); - if (requestUri.contains(String.format("{%s+}", mapping.getMarshallLocationName()))) { + Optional requestUri = findRequestUri(parentShape, allC2jShapes); + if (requestUri.isPresent() + && requestUri.get().contains(String.format("{%s+}", mapping.getMarshallLocationName()))) { return true; } } @@ -353,33 +347,19 @@ private boolean isGreedy(Shape parentShape, Map allC2jShapes, Par /** * Given an input shape, finds the Request URI for the operation that input is referenced from. + * Per the Smithy spec, httpLabel on non-input shapes has no meaning and is ignored, + * so this returns Optional.empty() if the shape is not a direct operation input. * - * @param parentShape Input shape to find operation's request URI for. + * @param parentShape Shape to find operation's request URI for. * @param allC2jShapes All shapes in the service model. - * @return Request URI for operation. - * @throws RuntimeException If operation can't be found. + * @return Request URI for operation, or empty if the shape is not a direct operation input. */ - private String findRequestUri(Shape parentShape, Map allC2jShapes) { - Optional operation = builder.getService().getOperations().values().stream() - .filter(o -> o.getInput() != null) - .filter(o -> allC2jShapes.get(o.getInput().getShape()).equals(parentShape)) - .findFirst(); - - return operation.map(o -> o.getHttp().getRequestUri()) - .orElseThrow(() -> { - String shapeName = allC2jShapes.entrySet().stream() - .filter(e -> e.getValue().equals(parentShape)) - .map(Map.Entry::getKey) - .findFirst() - .orElse("unknown"); - String detailMsg = "Could not find request URI for input shape '" + shapeName - + "'. No operation was found that references this shape as its input."; - ValidationEntry entry = - new ValidationEntry().withErrorId(ValidationErrorId.REQUEST_URI_NOT_FOUND) - .withDetailMessage(detailMsg) - .withSeverity(ValidationErrorSeverity.DANGER); - return ModelInvalidException.builder().validationEntries(Collections.singletonList(entry)).build(); - }); + private Optional findRequestUri(Shape parentShape, Map allC2jShapes) { + return builder.getService().getOperations().values().stream() + .filter(o -> o.getInput() != null) + .filter(o -> allC2jShapes.get(o.getInput().getShape()).equals(parentShape)) + .findFirst() + .map(o -> o.getHttp().getRequestUri()); } private String deriveUnmarshallerLocationName(Shape memberShape, String memberName, Member member) { diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java index 0ce91b61b576..1f94a8b3849a 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.codegen; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -178,20 +179,15 @@ void execute_endpointsTestReferencesUnknownOperationMember_throwsValidationError } @Test - void execute_uriLocationOnNonInputShape_throwsValidationErrorWithShapeName() throws IOException { + void execute_uriLocationOnNonInputShape_isIgnored() throws IOException { C2jModels models = C2jModels.builder() .customizationConfig(CustomizationConfig.create()) .serviceModel(getUriOnNonInputShapeServiceModel()) .build(); - assertThatThrownBy(() -> generateCodeFromC2jModels(models, outputDir, true, Collections.emptyList())) - .isInstanceOf(ModelInvalidException.class) - .matches(e -> { - ModelInvalidException ex = (ModelInvalidException) e; - ValidationEntry entry = ex.validationEntries().get(0); - return entry.getErrorId() == ValidationErrorId.REQUEST_URI_NOT_FOUND - && entry.getDetailMessage().contains("No operation was found"); - }); + // Per the Smithy spec, httpLabel on non-input shapes has no meaning and is simply ignored. + assertThatNoException().isThrownBy( + () -> generateCodeFromC2jModels(models, outputDir, true, Collections.emptyList())); } @Test From 58dbf2f7d42dcc5587a9dad5cc985559409214cd Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Fri, 13 Mar 2026 12:29:50 -0700 Subject: [PATCH 03/16] Fix logic to ignore instead of throw --- .../amazon/awssdk/codegen/AddShapes.java | 45 +++++++++++++++---- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java index 725bf8f38e62..5344016041e8 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java @@ -21,6 +21,7 @@ import static software.amazon.awssdk.codegen.internal.Utils.isMapShape; import static software.amazon.awssdk.codegen.internal.Utils.isScalar; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -37,10 +38,15 @@ import software.amazon.awssdk.codegen.model.intermediate.VariableModel; import software.amazon.awssdk.codegen.model.service.Location; import software.amazon.awssdk.codegen.model.service.Member; +import software.amazon.awssdk.codegen.model.service.Operation; import software.amazon.awssdk.codegen.model.service.ServiceModel; import software.amazon.awssdk.codegen.model.service.Shape; import software.amazon.awssdk.codegen.naming.NamingStrategy; import software.amazon.awssdk.codegen.utils.ProtocolUtils; +import software.amazon.awssdk.codegen.validation.ModelInvalidException; +import software.amazon.awssdk.codegen.validation.ValidationEntry; +import software.amazon.awssdk.codegen.validation.ValidationErrorId; +import software.amazon.awssdk.codegen.validation.ValidationErrorSeverity; import software.amazon.awssdk.utils.StringUtils; import software.amazon.awssdk.utils.Validate; @@ -349,17 +355,38 @@ private boolean isGreedy(Shape parentShape, Map allC2jShapes, Par * Given an input shape, finds the Request URI for the operation that input is referenced from. * Per the Smithy spec, httpLabel on non-input shapes has no meaning and is ignored, * so this returns Optional.empty() if the shape is not a direct operation input. - * - * @param parentShape Shape to find operation's request URI for. - * @param allC2jShapes All shapes in the service model. - * @return Request URI for operation, or empty if the shape is not a direct operation input. + * If the shape IS a direct operation input but the operation is missing a requestUri, + * a validation error is thrown. */ private Optional findRequestUri(Shape parentShape, Map allC2jShapes) { - return builder.getService().getOperations().values().stream() - .filter(o -> o.getInput() != null) - .filter(o -> allC2jShapes.get(o.getInput().getShape()).equals(parentShape)) - .findFirst() - .map(o -> o.getHttp().getRequestUri()); + Optional operation = builder.getService().getOperations().values().stream() + .filter(o -> o.getInput() != null) + .filter(o -> allC2jShapes.get(o.getInput().getShape()).equals(parentShape)) + .findFirst(); + + if (!operation.isPresent()) { + // Not a direct operation input shape, should be ignored. + // https://smithy.io/2.0/spec/http-bindings.html#httplabel-is-only-used-on-top-level-input + return Optional.empty(); + } + + String requestUri = operation.get().getHttp().getRequestUri(); + if (requestUri == null) { + String shapeName = allC2jShapes.entrySet().stream() + .filter(e -> e.getValue().equals(parentShape)) + .map(Map.Entry::getKey) + .findFirst() + .get(); + String detailMsg = "Could not find request URI for input shape '" + shapeName + + "'. No operation was found that references this shape as its input."; + ValidationEntry entry = + new ValidationEntry().withErrorId(ValidationErrorId.REQUEST_URI_NOT_FOUND) + .withDetailMessage(detailMsg) + .withSeverity(ValidationErrorSeverity.DANGER); + throw ModelInvalidException.builder().validationEntries(Collections.singletonList(entry)).build(); + } + + return Optional.of(requestUri); } private String deriveUnmarshallerLocationName(Shape memberShape, String memberName, Member member) { From 691d5618f86d84514d768a84082d9f27fae48f3a Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Fri, 13 Mar 2026 12:48:30 -0700 Subject: [PATCH 04/16] Fix javadoc --- .../software/amazon/awssdk/codegen/AddShapes.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java index 5344016041e8..14766b3d46be 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java @@ -352,11 +352,14 @@ private boolean isGreedy(Shape parentShape, Map allC2jShapes, Par } /** - * Given an input shape, finds the Request URI for the operation that input is referenced from. - * Per the Smithy spec, httpLabel on non-input shapes has no meaning and is ignored, - * so this returns Optional.empty() if the shape is not a direct operation input. - * If the shape IS a direct operation input but the operation is missing a requestUri, - * a validation error is thrown. + * Given a shape, finds the Request URI for the operation that references it as input. + * Returns empty if the shape is not a direct operation input. + * Throws if the shape is a direct operation input but the operation is missing a requestUri. + * + * @param parentShape Shape to find operation's request URI for. + * @param allC2jShapes All shapes in the service model. + * @return Request URI for operation, or empty if the shape is not a direct operation input. + * @throws ModelInvalidException If the shape is a direct operation input but requestUri is missing. */ private Optional findRequestUri(Shape parentShape, Map allC2jShapes) { Optional operation = builder.getService().getOperations().values().stream() From 560d15ae63388552125f30587aa08fb408a71cc6 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Mon, 16 Mar 2026 13:53:47 -0700 Subject: [PATCH 05/16] Ignore HTTP binding locations on non-input shapes per Smithy spec --- .../amazon/awssdk/codegen/AddShapes.java | 29 ++- .../amazon/awssdk/codegen/AddShapesTest.java | 2 +- .../awssdk/codegen/CodeGeneratorTest.java | 21 ++ .../codegen/expected-nested-options.java | 201 ++++++++++++++++++ .../model/nestedqueryparameteroperation.java | 4 +- 5 files changed, 251 insertions(+), 6 deletions(-) create mode 100644 codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java index 14766b3d46be..a64e1ad15fdf 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java @@ -311,8 +311,13 @@ private ParameterHttpMapping generateParameterHttpMapping(Shape parentShape, ParameterHttpMapping mapping = new ParameterHttpMapping(); + // https://smithy.io/2.0/spec/http-bindings.html#httplabel-is-only-used-on-top-level-input + Location location = isDirectOperationInputOrOutput(parentShape, allC2jShapes) + ? Location.forValue(member.getLocation()) + : null; + Shape memberShape = allC2jShapes.get(member.getShape()); - mapping.withLocation(Location.forValue(member.getLocation())) + mapping.withLocation(location) .withPayload(member.isPayload()).withStreaming(member.isStreaming()) .withFlattened(isFlattened(member, memberShape)) .withUnmarshallLocationName(deriveUnmarshallerLocationName(memberShape, memberName, member)) @@ -323,6 +328,26 @@ private ParameterHttpMapping generateParameterHttpMapping(Shape parentShape, return mapping; } + private boolean isDirectOperationInputOrOutput(Shape parentShape, Map allC2jShapes) { + for (Operation operation : builder.getService().getOperations().values()) { + if (operation.getInput() != null) { + String inputShapeName = operation.getInput().getShape(); + Shape inputShape = allC2jShapes.get(inputShapeName); + if (parentShape.equals(inputShape)) { + return true; + } + } + if (operation.getOutput() != null) { + String outputShapeName = operation.getOutput().getShape(); + Shape outputShape = allC2jShapes.get(outputShapeName); + if (parentShape.equals(outputShape)) { + return true; + } + } + } + return false; + } + private boolean isFlattened(Member member, Shape memberShape) { return member.isFlattened() || memberShape.isFlattened(); @@ -354,12 +379,10 @@ private boolean isGreedy(Shape parentShape, Map allC2jShapes, Par /** * Given a shape, finds the Request URI for the operation that references it as input. * Returns empty if the shape is not a direct operation input. - * Throws if the shape is a direct operation input but the operation is missing a requestUri. * * @param parentShape Shape to find operation's request URI for. * @param allC2jShapes All shapes in the service model. * @return Request URI for operation, or empty if the shape is not a direct operation input. - * @throws ModelInvalidException If the shape is a direct operation input but requestUri is missing. */ private Optional findRequestUri(Shape parentShape, Map allC2jShapes) { Optional operation = builder.getService().getOperations().values().stream() diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java index dde88dd226e0..5f827cdadd44 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java @@ -84,7 +84,7 @@ void generateShapeModel_memberRequiredByNestedShape_setsMemberModelAsRequired() MemberModel requiredMemberModel = requestShapeModel.findMemberModelByC2jName(queryParamName); assertThat(requestShapeModel.getRequired()).contains(queryParamName); - assertThat(requiredMemberModel.getHttp().getLocation()).isEqualTo(Location.QUERY_STRING); + assertThat(requiredMemberModel.getHttp().getLocation()).isNull(); assertThat(requiredMemberModel.isRequired()).isTrue(); } diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java index 1f94a8b3849a..c4cc96b16691 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java @@ -44,7 +44,10 @@ import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; import software.amazon.awssdk.codegen.model.config.customization.UnderscoresInNameBehavior; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.model.intermediate.MemberModel; +import software.amazon.awssdk.codegen.model.intermediate.ShapeModel; import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel; +import software.amazon.awssdk.codegen.model.service.Location; import software.amazon.awssdk.codegen.model.service.ServiceModel; import software.amazon.awssdk.codegen.poet.ClientTestModels; import software.amazon.awssdk.codegen.validation.ModelInvalidException; @@ -188,6 +191,24 @@ void execute_uriLocationOnNonInputShape_isIgnored() throws IOException { // Per the Smithy spec, httpLabel on non-input shapes has no meaning and is simply ignored. assertThatNoException().isThrownBy( () -> generateCodeFromC2jModels(models, outputDir, true, Collections.emptyList())); + + IntermediateModel intermediateModel = new IntermediateModelBuilder(models).build(); + ShapeModel inputShape = intermediateModel.getShapes().get("SomeOperationRequest"); + MemberModel uriMember = inputShape.findMemberModelByC2jName("thingId"); + assertThat(uriMember.getHttp().getLocation()).isEqualTo(Location.URI); + + ShapeModel nestedShape = intermediateModel.getShapes().get("NestedOptions"); + MemberModel nestedUriMember = nestedShape.findMemberModelByC2jName("pageSize"); + assertThat(nestedUriMember.getHttp().getLocation()).isNull(); + assertThat(nestedUriMember.getHttp().isGreedy()).isFalse(); + + Path generatedNestedOptions = Files.walk(outputDir) + .filter(p -> p.getFileName().toString().equals("NestedOptions.java")) + .findFirst() + .orElseThrow(() -> new AssertionError("NestedOptions.java not found in generated output")); + String actual = new String(Files.readAllBytes(generatedNestedOptions), StandardCharsets.UTF_8); + String expected = resourceAsString("expected-nested-options.java"); + assertThat(actual).isEqualTo(expected); } @Test diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java new file mode 100644 index 000000000000..bb8c7e9e3efc --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java @@ -0,0 +1,201 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with + * the License. A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ + +package software.amazon.awssdk.services.restjson.model; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Function; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.Mutable; +import software.amazon.awssdk.annotations.NotThreadSafe; +import software.amazon.awssdk.core.SdkField; +import software.amazon.awssdk.core.SdkPojo; +import software.amazon.awssdk.core.protocol.MarshallLocation; +import software.amazon.awssdk.core.protocol.MarshallingType; +import software.amazon.awssdk.core.traits.LocationTrait; +import software.amazon.awssdk.utils.ToString; +import software.amazon.awssdk.utils.builder.CopyableBuilder; +import software.amazon.awssdk.utils.builder.ToCopyableBuilder; + +/** + */ +@Generated("software.amazon.awssdk:codegen") +public final class NestedOptions implements SdkPojo, Serializable, ToCopyableBuilder { + private static final SdkField PAGE_SIZE_FIELD = SdkField. builder(MarshallingType.STRING) + .memberName("pageSize").getter(getter(NestedOptions::pageSize)).setter(setter(Builder::pageSize)) + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("pageSize").build()).build(); + + private static final List> SDK_FIELDS = Collections.unmodifiableList(Arrays.asList(PAGE_SIZE_FIELD)); + + private static final Map> SDK_NAME_TO_FIELD = memberNameToFieldInitializer(); + + private static final long serialVersionUID = 1L; + + private final String pageSize; + + private NestedOptions(BuilderImpl builder) { + this.pageSize = builder.pageSize; + } + + /** + * Returns the value of the PageSize property for this object. + * + * @return The value of the PageSize property for this object. + */ + public final String pageSize() { + return pageSize; + } + + @Override + public Builder toBuilder() { + return new BuilderImpl(this); + } + + public static Builder builder() { + return new BuilderImpl(); + } + + public static Class serializableBuilderClass() { + return BuilderImpl.class; + } + + @Override + public final int hashCode() { + int hashCode = 1; + hashCode = 31 * hashCode + Objects.hashCode(pageSize()); + return hashCode; + } + + @Override + public final boolean equals(Object obj) { + return equalsBySdkFields(obj); + } + + @Override + public final boolean equalsBySdkFields(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof NestedOptions)) { + return false; + } + NestedOptions other = (NestedOptions) obj; + return Objects.equals(pageSize(), other.pageSize()); + } + + /** + * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be + * redacted from this string using a placeholder value. + */ + @Override + public final String toString() { + return ToString.builder("NestedOptions").add("PageSize", pageSize()).build(); + } + + public final Optional getValueForField(String fieldName, Class clazz) { + switch (fieldName) { + case "pageSize": + return Optional.ofNullable(clazz.cast(pageSize())); + default: + return Optional.empty(); + } + } + + @Override + public final List> sdkFields() { + return SDK_FIELDS; + } + + @Override + public final Map> sdkFieldNameToField() { + return SDK_NAME_TO_FIELD; + } + + private static Map> memberNameToFieldInitializer() { + Map> map = new HashMap<>(); + map.put("pageSize", PAGE_SIZE_FIELD); + return Collections.unmodifiableMap(map); + } + + private static Function getter(Function g) { + return obj -> g.apply((NestedOptions) obj); + } + + private static BiConsumer setter(BiConsumer s) { + return (obj, val) -> s.accept((Builder) obj, val); + } + + @Mutable + @NotThreadSafe + public interface Builder extends SdkPojo, CopyableBuilder { + /** + * Sets the value of the PageSize property for this object. + * + * @param pageSize + * The new value for the PageSize property for this object. + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder pageSize(String pageSize); + } + + static final class BuilderImpl implements Builder { + private String pageSize; + + private BuilderImpl() { + } + + private BuilderImpl(NestedOptions model) { + pageSize(model.pageSize); + } + + public final String getPageSize() { + return pageSize; + } + + public final void setPageSize(String pageSize) { + this.pageSize = pageSize; + } + + @Override + public final Builder pageSize(String pageSize) { + this.pageSize = pageSize; + return this; + } + + @Override + public NestedOptions build() { + return new NestedOptions(this); + } + + @Override + public List> sdkFields() { + return SDK_FIELDS; + } + + @Override + public Map> sdkFieldNameToField() { + return SDK_NAME_TO_FIELD; + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/nestedqueryparameteroperation.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/nestedqueryparameteroperation.java index c935db9281f0..e743d7c2bea4 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/nestedqueryparameteroperation.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/nestedqueryparameteroperation.java @@ -33,13 +33,13 @@ public final class NestedQueryParameterOperation implements SdkPojo, Serializabl .memberName("QueryParamOne") .getter(getter(NestedQueryParameterOperation::queryParamOne)) .setter(setter(Builder::queryParamOne)) - .traits(LocationTrait.builder().location(MarshallLocation.QUERY_PARAM).locationName("QueryParamOne").build(), + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("QueryParamOne").build(), RequiredTrait.create()).build(); private static final SdkField QUERY_PARAM_TWO_FIELD = SdkField. builder(MarshallingType.STRING) .memberName("QueryParamTwo").getter(getter(NestedQueryParameterOperation::queryParamTwo)) .setter(setter(Builder::queryParamTwo)) - .traits(LocationTrait.builder().location(MarshallLocation.QUERY_PARAM).locationName("QueryParamTwo").build()).build(); + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("QueryParamTwo").build()).build(); private static final List> SDK_FIELDS = Collections.unmodifiableList(Arrays.asList(QUERY_PARAM_ONE_FIELD, QUERY_PARAM_TWO_FIELD)); From d7396273d9ef6b6a3a118149a4f288d874944ecc Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 17 Mar 2026 09:51:00 -0700 Subject: [PATCH 06/16] Account for error shapes as well --- .../software/amazon/awssdk/codegen/AddShapes.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java index a64e1ad15fdf..f628c41d8610 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java @@ -36,6 +36,7 @@ import software.amazon.awssdk.codegen.model.intermediate.ReturnTypeModel; import software.amazon.awssdk.codegen.model.intermediate.ShapeModel; import software.amazon.awssdk.codegen.model.intermediate.VariableModel; +import software.amazon.awssdk.codegen.model.service.ErrorMap; import software.amazon.awssdk.codegen.model.service.Location; import software.amazon.awssdk.codegen.model.service.Member; import software.amazon.awssdk.codegen.model.service.Operation; @@ -344,6 +345,16 @@ private boolean isDirectOperationInputOrOutput(Shape parentShape, Map Date: Tue, 17 Mar 2026 14:33:17 -0700 Subject: [PATCH 07/16] Fix comments --- .../amazon/awssdk/codegen/AddShapes.java | 41 +++---- .../amazon/awssdk/codegen/AddShapesTest.java | 16 ++- .../awssdk/codegen/CodeGeneratorTest.java | 11 +- .../codegen/expected-nested-options.java | 102 +++++++++++++++++- .../uri-on-non-input-shape-service.json | 12 ++- 5 files changed, 148 insertions(+), 34 deletions(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java index f628c41d8610..70d7be7ec3b0 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java @@ -22,9 +22,11 @@ import static software.amazon.awssdk.codegen.internal.Utils.isScalar; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import software.amazon.awssdk.codegen.internal.TypeUtils; import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; import software.amazon.awssdk.codegen.model.intermediate.EnumModel; @@ -55,6 +57,7 @@ abstract class AddShapes { private final IntermediateModelBuilder builder; private final NamingStrategy namingStrategy; + private Set directOperationShapes; AddShapes(IntermediateModelBuilder builder) { this.builder = builder; @@ -313,7 +316,7 @@ private ParameterHttpMapping generateParameterHttpMapping(Shape parentShape, ParameterHttpMapping mapping = new ParameterHttpMapping(); // https://smithy.io/2.0/spec/http-bindings.html#httplabel-is-only-used-on-top-level-input - Location location = isDirectOperationInputOrOutput(parentShape, allC2jShapes) + Location location = isDirectOperationShape(parentShape, allC2jShapes) ? Location.forValue(member.getLocation()) : null; @@ -329,34 +332,24 @@ private ParameterHttpMapping generateParameterHttpMapping(Shape parentShape, return mapping; } - private boolean isDirectOperationInputOrOutput(Shape parentShape, Map allC2jShapes) { - for (Operation operation : builder.getService().getOperations().values()) { - if (operation.getInput() != null) { - String inputShapeName = operation.getInput().getShape(); - Shape inputShape = allC2jShapes.get(inputShapeName); - if (parentShape.equals(inputShape)) { - return true; + private boolean isDirectOperationShape(Shape parentShape, Map allC2jShapes) { + if (directOperationShapes == null) { + directOperationShapes = new HashSet<>(); + for (Operation operation : builder.getService().getOperations().values()) { + if (operation.getInput() != null) { + directOperationShapes.add(allC2jShapes.get(operation.getInput().getShape())); } - } - if (operation.getOutput() != null) { - String outputShapeName = operation.getOutput().getShape(); - Shape outputShape = allC2jShapes.get(outputShapeName); - if (parentShape.equals(outputShape)) { - return true; + if (operation.getOutput() != null) { + directOperationShapes.add(allC2jShapes.get(operation.getOutput().getShape())); } - } - - if (operation.getErrors() != null) { - for (ErrorMap error : operation.getErrors()) { - String errorShapeName = error.getShape(); - Shape outputShape = allC2jShapes.get(errorShapeName); - if (parentShape.equals(outputShape)) { - return true; + if (operation.getErrors() != null) { + for (ErrorMap error : operation.getErrors()) { + directOperationShapes.add(allC2jShapes.get(error.getShape())); } } } } - return false; + return directOperationShapes.contains(parentShape); } private boolean isFlattened(Member member, Shape memberShape) { @@ -413,7 +406,7 @@ private Optional findRequestUri(Shape parentShape, Map al .filter(e -> e.getValue().equals(parentShape)) .map(Map.Entry::getKey) .findFirst() - .get(); + .orElseThrow(() -> new IllegalStateException("Shape not found in model: " + parentShape)); String detailMsg = "Could not find request URI for input shape '" + shapeName + "'. No operation was found that references this shape as its input."; ValidationEntry entry = diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java index 5f827cdadd44..0243c001e90e 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java @@ -84,8 +84,22 @@ void generateShapeModel_memberRequiredByNestedShape_setsMemberModelAsRequired() MemberModel requiredMemberModel = requestShapeModel.findMemberModelByC2jName(queryParamName); assertThat(requestShapeModel.getRequired()).contains(queryParamName); - assertThat(requiredMemberModel.getHttp().getLocation()).isNull(); assertThat(requiredMemberModel.isRequired()).isTrue(); } + @Test + void generateShapeModel_locationOnNestedShape_isIgnored() { + ShapeModel nestedShape = intermediateModel.getShapes().get("NestedQueryParameterOperation"); + MemberModel queryParam = nestedShape.findMemberModelByC2jName("QueryParamOne"); + assertThat(queryParam.getHttp().getLocation()).isNull(); + } + + @Test + void generateShapeModel_locationOnDirectInputShape_isPreserved() { + ShapeModel inputShape = intermediateModel.getShapes().get("QueryParameterOperationRequest"); + assertThat(inputShape.findMemberModelByC2jName("PathParam").getHttp().getLocation()).isEqualTo(Location.URI); + assertThat(inputShape.findMemberModelByC2jName("QueryParamOne").getHttp().getLocation()).isEqualTo(Location.QUERY_STRING); + assertThat(inputShape.findMemberModelByC2jName("StringHeaderMember").getHttp().getLocation()).isEqualTo(Location.HEADER); + } + } diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java index c4cc96b16691..7da5022cbb83 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java @@ -193,14 +193,15 @@ void execute_uriLocationOnNonInputShape_isIgnored() throws IOException { () -> generateCodeFromC2jModels(models, outputDir, true, Collections.emptyList())); IntermediateModel intermediateModel = new IntermediateModelBuilder(models).build(); + ShapeModel inputShape = intermediateModel.getShapes().get("SomeOperationRequest"); - MemberModel uriMember = inputShape.findMemberModelByC2jName("thingId"); - assertThat(uriMember.getHttp().getLocation()).isEqualTo(Location.URI); + assertThat(inputShape.findMemberModelByC2jName("thingId").getHttp().getLocation()).isEqualTo(Location.URI); ShapeModel nestedShape = intermediateModel.getShapes().get("NestedOptions"); - MemberModel nestedUriMember = nestedShape.findMemberModelByC2jName("pageSize"); - assertThat(nestedUriMember.getHttp().getLocation()).isNull(); - assertThat(nestedUriMember.getHttp().isGreedy()).isFalse(); + assertThat(nestedShape.findMemberModelByC2jName("pageSize").getHttp().getLocation()).isNull(); + assertThat(nestedShape.findMemberModelByC2jName("pageSize").getHttp().isGreedy()).isFalse(); + assertThat(nestedShape.findMemberModelByC2jName("headerParam").getHttp().getLocation()).isNull(); + assertThat(nestedShape.findMemberModelByC2jName("queryParam").getHttp().getLocation()).isNull(); Path generatedNestedOptions = Files.walk(outputDir) .filter(p -> p.getFileName().toString().equals("NestedOptions.java")) diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java index bb8c7e9e3efc..8254a9771fa5 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java @@ -43,7 +43,17 @@ public final class NestedOptions implements SdkPojo, Serializable, ToCopyableBui .memberName("pageSize").getter(getter(NestedOptions::pageSize)).setter(setter(Builder::pageSize)) .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("pageSize").build()).build(); - private static final List> SDK_FIELDS = Collections.unmodifiableList(Arrays.asList(PAGE_SIZE_FIELD)); + private static final SdkField HEADER_PARAM_FIELD = SdkField. builder(MarshallingType.STRING) + .memberName("headerParam").getter(getter(NestedOptions::headerParam)).setter(setter(Builder::headerParam)) + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("x-amz-nested-header").build()) + .build(); + + private static final SdkField QUERY_PARAM_FIELD = SdkField. builder(MarshallingType.STRING) + .memberName("queryParam").getter(getter(NestedOptions::queryParam)).setter(setter(Builder::queryParam)) + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("nestedQuery").build()).build(); + + private static final List> SDK_FIELDS = Collections.unmodifiableList(Arrays.asList(PAGE_SIZE_FIELD, + HEADER_PARAM_FIELD, QUERY_PARAM_FIELD)); private static final Map> SDK_NAME_TO_FIELD = memberNameToFieldInitializer(); @@ -51,8 +61,14 @@ public final class NestedOptions implements SdkPojo, Serializable, ToCopyableBui private final String pageSize; + private final String headerParam; + + private final String queryParam; + private NestedOptions(BuilderImpl builder) { this.pageSize = builder.pageSize; + this.headerParam = builder.headerParam; + this.queryParam = builder.queryParam; } /** @@ -64,6 +80,24 @@ public final String pageSize() { return pageSize; } + /** + * Returns the value of the HeaderParam property for this object. + * + * @return The value of the HeaderParam property for this object. + */ + public final String headerParam() { + return headerParam; + } + + /** + * Returns the value of the QueryParam property for this object. + * + * @return The value of the QueryParam property for this object. + */ + public final String queryParam() { + return queryParam; + } + @Override public Builder toBuilder() { return new BuilderImpl(this); @@ -81,6 +115,8 @@ public static Class serializableBuilderClass() { public final int hashCode() { int hashCode = 1; hashCode = 31 * hashCode + Objects.hashCode(pageSize()); + hashCode = 31 * hashCode + Objects.hashCode(headerParam()); + hashCode = 31 * hashCode + Objects.hashCode(queryParam()); return hashCode; } @@ -101,7 +137,8 @@ public final boolean equalsBySdkFields(Object obj) { return false; } NestedOptions other = (NestedOptions) obj; - return Objects.equals(pageSize(), other.pageSize()); + return Objects.equals(pageSize(), other.pageSize()) && Objects.equals(headerParam(), other.headerParam()) + && Objects.equals(queryParam(), other.queryParam()); } /** @@ -110,13 +147,18 @@ public final boolean equalsBySdkFields(Object obj) { */ @Override public final String toString() { - return ToString.builder("NestedOptions").add("PageSize", pageSize()).build(); + return ToString.builder("NestedOptions").add("PageSize", pageSize()).add("HeaderParam", headerParam()) + .add("QueryParam", queryParam()).build(); } public final Optional getValueForField(String fieldName, Class clazz) { switch (fieldName) { case "pageSize": return Optional.ofNullable(clazz.cast(pageSize())); + case "headerParam": + return Optional.ofNullable(clazz.cast(headerParam())); + case "queryParam": + return Optional.ofNullable(clazz.cast(queryParam())); default: return Optional.empty(); } @@ -135,6 +177,8 @@ public final Map> sdkFieldNameToField() { private static Map> memberNameToFieldInitializer() { Map> map = new HashMap<>(); map.put("pageSize", PAGE_SIZE_FIELD); + map.put("x-amz-nested-header", HEADER_PARAM_FIELD); + map.put("nestedQuery", QUERY_PARAM_FIELD); return Collections.unmodifiableMap(map); } @@ -157,16 +201,40 @@ public interface Builder extends SdkPojo, CopyableBuilder Date: Tue, 17 Mar 2026 14:58:05 -0700 Subject: [PATCH 08/16] Fix comments 2 --- .../awssdk/codegen/CodeGeneratorTest.java | 4 + .../codegen/expected-nested-options.java | 88 ++++++++++++++++++- .../uri-on-non-input-shape-service.json | 33 +++++++ 3 files changed, 122 insertions(+), 3 deletions(-) diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java index 7da5022cbb83..194a315537b8 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java @@ -202,6 +202,10 @@ void execute_uriLocationOnNonInputShape_isIgnored() throws IOException { assertThat(nestedShape.findMemberModelByC2jName("pageSize").getHttp().isGreedy()).isFalse(); assertThat(nestedShape.findMemberModelByC2jName("headerParam").getHttp().getLocation()).isNull(); assertThat(nestedShape.findMemberModelByC2jName("queryParam").getHttp().getLocation()).isNull(); + assertThat(nestedShape.findMemberModelByC2jName("prefixHeaders").getHttp().getLocation()).isNull(); + + ShapeModel sharedShape = intermediateModel.getShapes().get("SharedShapeOperationRequest"); + assertThat(sharedShape.findMemberModelByC2jName("sharedId").getHttp().getLocation()).isEqualTo(Location.URI); Path generatedNestedOptions = Files.walk(outputDir) .filter(p -> p.getFileName().toString().equals("NestedOptions.java")) diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java index 8254a9771fa5..4940bbc56a14 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java @@ -31,6 +31,9 @@ import software.amazon.awssdk.core.protocol.MarshallLocation; import software.amazon.awssdk.core.protocol.MarshallingType; import software.amazon.awssdk.core.traits.LocationTrait; +import software.amazon.awssdk.core.traits.MapTrait; +import software.amazon.awssdk.core.util.DefaultSdkAutoConstructMap; +import software.amazon.awssdk.core.util.SdkAutoConstructMap; import software.amazon.awssdk.utils.ToString; import software.amazon.awssdk.utils.builder.CopyableBuilder; import software.amazon.awssdk.utils.builder.ToCopyableBuilder; @@ -52,8 +55,22 @@ public final class NestedOptions implements SdkPojo, Serializable, ToCopyableBui .memberName("queryParam").getter(getter(NestedOptions::queryParam)).setter(setter(Builder::queryParam)) .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("nestedQuery").build()).build(); + private static final SdkField> PREFIX_HEADERS_FIELD = SdkField + .> builder(MarshallingType.MAP) + .memberName("prefixHeaders") + .getter(getter(NestedOptions::prefixHeaders)) + .setter(setter(Builder::prefixHeaders)) + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("x-amz-prefix-").build(), + MapTrait.builder() + .keyLocationName("key") + .valueLocationName("value") + .valueFieldInfo( + SdkField. builder(MarshallingType.STRING) + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD) + .locationName("value").build()).build()).build()).build(); + private static final List> SDK_FIELDS = Collections.unmodifiableList(Arrays.asList(PAGE_SIZE_FIELD, - HEADER_PARAM_FIELD, QUERY_PARAM_FIELD)); + HEADER_PARAM_FIELD, QUERY_PARAM_FIELD, PREFIX_HEADERS_FIELD)); private static final Map> SDK_NAME_TO_FIELD = memberNameToFieldInitializer(); @@ -65,10 +82,13 @@ public final class NestedOptions implements SdkPojo, Serializable, ToCopyableBui private final String queryParam; + private final Map prefixHeaders; + private NestedOptions(BuilderImpl builder) { this.pageSize = builder.pageSize; this.headerParam = builder.headerParam; this.queryParam = builder.queryParam; + this.prefixHeaders = builder.prefixHeaders; } /** @@ -98,6 +118,34 @@ public final String queryParam() { return queryParam; } + /** + * For responses, this returns true if the service returned a value for the PrefixHeaders property. This DOES NOT + * check that the value is non-empty (for which, you should check the {@code isEmpty()} method on the property). + * This is useful because the SDK will never return a null collection or map, but you may need to differentiate + * between the service returning nothing (or null) and the service returning an empty collection or map. For + * requests, this returns true if a value for the property was specified in the request builder, and false if a + * value was not specified. + */ + public final boolean hasPrefixHeaders() { + return prefixHeaders != null && !(prefixHeaders instanceof SdkAutoConstructMap); + } + + /** + * Returns the value of the PrefixHeaders property for this object. + *

+ * Attempts to modify the collection returned by this method will result in an UnsupportedOperationException. + *

+ *

+ * This method will never return null. If you would like to know whether the service returned this field (so that + * you can differentiate between null and empty), you can use the {@link #hasPrefixHeaders} method. + *

+ * + * @return The value of the PrefixHeaders property for this object. + */ + public final Map prefixHeaders() { + return prefixHeaders; + } + @Override public Builder toBuilder() { return new BuilderImpl(this); @@ -117,6 +165,7 @@ public final int hashCode() { hashCode = 31 * hashCode + Objects.hashCode(pageSize()); hashCode = 31 * hashCode + Objects.hashCode(headerParam()); hashCode = 31 * hashCode + Objects.hashCode(queryParam()); + hashCode = 31 * hashCode + Objects.hashCode(hasPrefixHeaders() ? prefixHeaders() : null); return hashCode; } @@ -138,7 +187,8 @@ public final boolean equalsBySdkFields(Object obj) { } NestedOptions other = (NestedOptions) obj; return Objects.equals(pageSize(), other.pageSize()) && Objects.equals(headerParam(), other.headerParam()) - && Objects.equals(queryParam(), other.queryParam()); + && Objects.equals(queryParam(), other.queryParam()) && hasPrefixHeaders() == other.hasPrefixHeaders() + && Objects.equals(prefixHeaders(), other.prefixHeaders()); } /** @@ -148,7 +198,7 @@ public final boolean equalsBySdkFields(Object obj) { @Override public final String toString() { return ToString.builder("NestedOptions").add("PageSize", pageSize()).add("HeaderParam", headerParam()) - .add("QueryParam", queryParam()).build(); + .add("QueryParam", queryParam()).add("PrefixHeaders", hasPrefixHeaders() ? prefixHeaders() : null).build(); } public final Optional getValueForField(String fieldName, Class clazz) { @@ -159,6 +209,8 @@ public final Optional getValueForField(String fieldName, Class clazz) return Optional.ofNullable(clazz.cast(headerParam())); case "queryParam": return Optional.ofNullable(clazz.cast(queryParam())); + case "prefixHeaders": + return Optional.ofNullable(clazz.cast(prefixHeaders())); default: return Optional.empty(); } @@ -179,6 +231,7 @@ private static Map> memberNameToFieldInitializer() { map.put("pageSize", PAGE_SIZE_FIELD); map.put("x-amz-nested-header", HEADER_PARAM_FIELD); map.put("nestedQuery", QUERY_PARAM_FIELD); + map.put("x-amz-prefix-", PREFIX_HEADERS_FIELD); return Collections.unmodifiableMap(map); } @@ -219,6 +272,15 @@ public interface Builder extends SdkPojo, CopyableBuilder prefixHeaders); } static final class BuilderImpl implements Builder { @@ -228,6 +290,8 @@ static final class BuilderImpl implements Builder { private String queryParam; + private Map prefixHeaders = DefaultSdkAutoConstructMap.getInstance(); + private BuilderImpl() { } @@ -235,6 +299,7 @@ private BuilderImpl(NestedOptions model) { pageSize(model.pageSize); headerParam(model.headerParam); queryParam(model.queryParam); + prefixHeaders(model.prefixHeaders); } public final String getPageSize() { @@ -279,6 +344,23 @@ public final Builder queryParam(String queryParam) { return this; } + public final Map getPrefixHeaders() { + if (prefixHeaders instanceof SdkAutoConstructMap) { + return null; + } + return prefixHeaders; + } + + public final void setPrefixHeaders(Map prefixHeaders) { + this.prefixHeaders = MapOfStringsCopier.copy(prefixHeaders); + } + + @Override + public final Builder prefixHeaders(Map prefixHeaders) { + this.prefixHeaders = MapOfStringsCopier.copy(prefixHeaders); + return this; + } + @Override public NestedOptions build() { return new NestedOptions(this); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/uri-on-non-input-shape-service.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/uri-on-non-input-shape-service.json index 08357e6e89b2..f858a11b94ed 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/uri-on-non-input-shape-service.json +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/uri-on-non-input-shape-service.json @@ -23,6 +23,16 @@ "input": { "shape": "SomeOperationRequest" } + }, + "SharedShapeOperation": { + "name": "SharedShapeOperation", + "http": { + "method": "GET", + "requestUri": "/shared/{sharedId}" + }, + "input": { + "shape": "SharedShape" + } } }, "shapes": { @@ -36,6 +46,9 @@ }, "options": { "shape": "NestedOptions" + }, + "shared": { + "shape": "SharedShape" } } }, @@ -56,11 +69,31 @@ "shape": "String", "location": "querystring", "locationName": "nestedQuery" + }, + "prefixHeaders": { + "shape": "MapOfStrings", + "location": "headers", + "locationName": "x-amz-prefix-" + } + } + }, + "SharedShape": { + "type": "structure", + "members": { + "sharedId": { + "shape": "String", + "location": "uri", + "locationName": "sharedId" } } }, "String": { "type": "string" + }, + "MapOfStrings": { + "type": "map", + "key": {"shape": "String"}, + "value": {"shape": "String"} } }, "documentation": "A service with HTTP binding locations on non-input shapes" From 2d77293f0016fd9df45e698da5bae88193447458 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Wed, 18 Mar 2026 11:53:34 -0700 Subject: [PATCH 09/16] Add assertion --- .../src/main/java/software/amazon/awssdk/codegen/AddShapes.java | 2 +- .../test/java/software/amazon/awssdk/codegen/AddShapesTest.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java index 70d7be7ec3b0..a965a12f5f29 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java @@ -315,7 +315,7 @@ private ParameterHttpMapping generateParameterHttpMapping(Shape parentShape, ParameterHttpMapping mapping = new ParameterHttpMapping(); - // https://smithy.io/2.0/spec/http-bindings.html#httplabel-is-only-used-on-top-level-input + // https://smithy.io/2.0/spec/http-bindings.html Location location = isDirectOperationShape(parentShape, allC2jShapes) ? Location.forValue(member.getLocation()) : null; diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java index 0243c001e90e..45185281666c 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java @@ -84,6 +84,7 @@ void generateShapeModel_memberRequiredByNestedShape_setsMemberModelAsRequired() MemberModel requiredMemberModel = requestShapeModel.findMemberModelByC2jName(queryParamName); assertThat(requestShapeModel.getRequired()).contains(queryParamName); + assertThat(requiredMemberModel.getHttp().getLocation()).isNull(); assertThat(requiredMemberModel.isRequired()).isTrue(); } From 65826f0d4b8b48889b1d5b99b9e482f678fd9d3c Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Thu, 19 Mar 2026 14:14:00 -0700 Subject: [PATCH 10/16] Add protocol test --- .../codegen-resources/restjson/service-2.json | 30 ++++++++ .../NestedLocationSerializationTest.java | 76 +++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/NestedLocationSerializationTest.java diff --git a/test/protocol-tests/src/main/resources/codegen-resources/restjson/service-2.json b/test/protocol-tests/src/main/resources/codegen-resources/restjson/service-2.json index c0348f5b1ca6..70e58cf31d0d 100644 --- a/test/protocol-tests/src/main/resources/codegen-resources/restjson/service-2.json +++ b/test/protocol-tests/src/main/resources/codegen-resources/restjson/service-2.json @@ -255,6 +255,14 @@ "requestUri":"/2016-03-11/documentInputOperation" }, "input":{"shape":"StructureWithDocumentMember"} + }, + "NestedLocationOperation":{ + "name":"NestedLocationOperation", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/nestedLocationOperation" + }, + "input":{"shape":"NestedLocationOperationInput"} } }, "shapes":{ @@ -782,6 +790,28 @@ "StringMember":{"shape":"String"} } }, + "NestedLocationOperationInput":{ + "type":"structure", + "members":{ + "TopLevelQueryParam":{ + "shape":"String", + "location":"querystring", + "locationName":"topLevel" + }, + "Nested":{"shape":"NestedShapeWithLocations"} + } + }, + "NestedShapeWithLocations":{ + "type":"structure", + "members":{ + "NestedQueryParam":{ + "shape":"String", + "location":"querystring", + "locationName":"shouldBeIgnored" + }, + "StringMember":{"shape":"String"} + } + }, "StatusCodeInOutputStructure":{ "type":"structure", "members":{ diff --git a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/NestedLocationSerializationTest.java b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/NestedLocationSerializationTest.java new file mode 100644 index 000000000000..da25133f45b2 --- /dev/null +++ b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/NestedLocationSerializationTest.java @@ -0,0 +1,76 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.protocol.tests; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import java.net.URI; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; +import software.amazon.awssdk.services.protocolrestjson.model.NestedLocationOperationRequest; +import software.amazon.awssdk.services.protocolrestjson.model.NestedShapeWithLocations; + +/** + * Verifies that HTTP binding locations on non-input shapes are ignored per the Smithy spec, + * and the members are serialized into the request body instead. + */ +public class NestedLocationSerializationTest { + + @Rule + public WireMockRule wireMock = new WireMockRule(0); + + private ProtocolRestJsonClient client; + + @Before + public void setup() { + client = ProtocolRestJsonClient.builder() + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost:" + wireMock.port())) + .build(); + } + + @Test + public void nestedMemberWithLocation_serializedToBodyNotQueryParam() { + stubFor(post(anyUrl()).willReturn(aResponse().withStatus(200).withBody("{}"))); + + client.nestedLocationOperation(NestedLocationOperationRequest.builder() + .topLevelQueryParam("topValue") + .nested(NestedShapeWithLocations.builder() + .nestedQueryParam("nestedValue") + .stringMember("hello") + .build()) + .build()); + + verify(postRequestedFor(anyUrl()).withQueryParam("topLevel", equalTo("topValue"))); + + verify(postRequestedFor(anyUrl()).withRequestBody( + equalToJson("{\"Nested\":{\"shouldBeIgnored\":\"nestedValue\",\"StringMember\":\"hello\"}}"))); + } +} From c9173e86ce76a52b9ba020deb43ef13c06b8890d Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 24 Mar 2026 16:25:40 -0700 Subject: [PATCH 11/16] Refadctor to remove cache complexity, add coverage --- .../amazon/awssdk/codegen/AddShapes.java | 66 +- .../model/nestedqueryparameteroperation.java | 430 ++++--- .../model/queryparameteroperationrequest.java | 1089 ++++++++--------- .../queryparameteroperationresponse.java | 349 ++++-- .../awssdk/codegen/poet/model/service-2.json | 40 +- 5 files changed, 1159 insertions(+), 815 deletions(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java index a965a12f5f29..9944a6a52931 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java @@ -22,11 +22,9 @@ import static software.amazon.awssdk.codegen.internal.Utils.isScalar; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; import software.amazon.awssdk.codegen.internal.TypeUtils; import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; import software.amazon.awssdk.codegen.model.intermediate.EnumModel; @@ -38,7 +36,6 @@ import software.amazon.awssdk.codegen.model.intermediate.ReturnTypeModel; import software.amazon.awssdk.codegen.model.intermediate.ShapeModel; import software.amazon.awssdk.codegen.model.intermediate.VariableModel; -import software.amazon.awssdk.codegen.model.service.ErrorMap; import software.amazon.awssdk.codegen.model.service.Location; import software.amazon.awssdk.codegen.model.service.Member; import software.amazon.awssdk.codegen.model.service.Operation; @@ -57,7 +54,6 @@ abstract class AddShapes { private final IntermediateModelBuilder builder; private final NamingStrategy namingStrategy; - private Set directOperationShapes; AddShapes(IntermediateModelBuilder builder) { this.builder = builder; @@ -315,10 +311,9 @@ private ParameterHttpMapping generateParameterHttpMapping(Shape parentShape, ParameterHttpMapping mapping = new ParameterHttpMapping(); + // Per the Smithy spec, HTTP binding traits are only honored on specific shape types: // https://smithy.io/2.0/spec/http-bindings.html - Location location = isDirectOperationShape(parentShape, allC2jShapes) - ? Location.forValue(member.getLocation()) - : null; + Location location = resolveLocation(parentShape, member, allC2jShapes); Shape memberShape = allC2jShapes.get(member.getShape()); mapping.withLocation(location) @@ -332,24 +327,43 @@ private ParameterHttpMapping generateParameterHttpMapping(Shape parentShape, return mapping; } - private boolean isDirectOperationShape(Shape parentShape, Map allC2jShapes) { - if (directOperationShapes == null) { - directOperationShapes = new HashSet<>(); - for (Operation operation : builder.getService().getOperations().values()) { - if (operation.getInput() != null) { - directOperationShapes.add(allC2jShapes.get(operation.getInput().getShape())); - } - if (operation.getOutput() != null) { - directOperationShapes.add(allC2jShapes.get(operation.getOutput().getShape())); - } - if (operation.getErrors() != null) { - for (ErrorMap error : operation.getErrors()) { - directOperationShapes.add(allC2jShapes.get(error.getShape())); - } - } - } + private Location resolveLocation(Shape parentShape, Member member, Map allC2jShapes) { + Location location = Location.forValue(member.getLocation()); + if (location == null) { + return null; + } + switch (location) { + case URI: + case QUERY_STRING: + return isDirectInputShape(parentShape, allC2jShapes) ? location : null; + case HEADER: + case HEADERS: + return isDirectOperationShape(parentShape, allC2jShapes) ? location : null; + case STATUS_CODE: + return isDirectOutputShape(parentShape, allC2jShapes) ? location : null; + default: + return location; } - return directOperationShapes.contains(parentShape); + } + + private boolean isDirectInputShape(Shape shape, Map allC2jShapes) { + return builder.getService().getOperations().values().stream() + .filter(o -> o.getInput() != null) + .anyMatch(o -> allC2jShapes.get(o.getInput().getShape()).equals(shape)); + } + + private boolean isDirectOutputShape(Shape shape, Map allC2jShapes) { + return builder.getService().getOperations().values().stream() + .filter(o -> o.getOutput() != null) + .anyMatch(o -> allC2jShapes.get(o.getOutput().getShape()).equals(shape)); + } + + private boolean isDirectOperationShape(Shape shape, Map allC2jShapes) { + return builder.getService().getOperations().values().stream() + .anyMatch(o -> (o.getInput() != null && allC2jShapes.get(o.getInput().getShape()).equals(shape)) + || (o.getOutput() != null && allC2jShapes.get(o.getOutput().getShape()).equals(shape)) + || (o.getErrors() != null && o.getErrors().stream() + .anyMatch(e -> allC2jShapes.get(e.getShape()).equals(shape)))); } private boolean isFlattened(Member member, Shape memberShape) { @@ -407,8 +421,8 @@ private Optional findRequestUri(Shape parentShape, Map al .map(Map.Entry::getKey) .findFirst() .orElseThrow(() -> new IllegalStateException("Shape not found in model: " + parentShape)); - String detailMsg = "Could not find request URI for input shape '" + shapeName - + "'. No operation was found that references this shape as its input."; + String detailMsg = "Operation referencing input shape '" + shapeName + + "' has no requestUri configured in its HTTP binding."; ValidationEntry entry = new ValidationEntry().withErrorId(ValidationErrorId.REQUEST_URI_NOT_FOUND) .withDetailMessage(detailMsg) diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/nestedqueryparameteroperation.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/nestedqueryparameteroperation.java index e743d7c2bea4..611656500dd2 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/nestedqueryparameteroperation.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/nestedqueryparameteroperation.java @@ -26,218 +26,308 @@ /** */ @Generated("software.amazon.awssdk:codegen") -public final class NestedQueryParameterOperation implements SdkPojo, Serializable, - ToCopyableBuilder { - private static final SdkField QUERY_PARAM_ONE_FIELD = SdkField - . builder(MarshallingType.STRING) - .memberName("QueryParamOne") - .getter(getter(NestedQueryParameterOperation::queryParamOne)) - .setter(setter(Builder::queryParamOne)) - .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("QueryParamOne").build(), - RequiredTrait.create()).build(); - - private static final SdkField QUERY_PARAM_TWO_FIELD = SdkField. builder(MarshallingType.STRING) - .memberName("QueryParamTwo").getter(getter(NestedQueryParameterOperation::queryParamTwo)) - .setter(setter(Builder::queryParamTwo)) - .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("QueryParamTwo").build()).build(); - - private static final List> SDK_FIELDS = Collections.unmodifiableList(Arrays.asList(QUERY_PARAM_ONE_FIELD, - QUERY_PARAM_TWO_FIELD)); - - private static final Map> SDK_NAME_TO_FIELD = memberNameToFieldInitializer(); - - private static final long serialVersionUID = 1L; - - private final String queryParamOne; - - private final String queryParamTwo; - - private NestedQueryParameterOperation(BuilderImpl builder) { - this.queryParamOne = builder.queryParamOne; - this.queryParamTwo = builder.queryParamTwo; +public final class NestedQueryParameterOperation implements SdkPojo, Serializable, ToCopyableBuilder { + private static final SdkField QUERY_PARAM_ONE_FIELD = SdkField.builder(MarshallingType.STRING) + .memberName("QueryParamOne") + .getter(getter(NestedQueryParameterOperation::queryParamOne)) + .setter(setter(Builder::queryParamOne)) + .traits(LocationTrait.builder() + .location(MarshallLocation.PAYLOAD) + .locationName("QueryParamOne") + .build(), RequiredTrait.create()).build(); + + private static final SdkField QUERY_PARAM_TWO_FIELD = SdkField.builder(MarshallingType.STRING) + .memberName("QueryParamTwo") + .getter(getter(NestedQueryParameterOperation::queryParamTwo)) + .setter(setter(Builder::queryParamTwo)) + .traits(LocationTrait.builder() + .location(MarshallLocation.PAYLOAD) + .locationName("QueryParamTwo") + .build()).build(); + + private static final SdkField NESTED_HEADER_MEMBER_FIELD = SdkField.builder(MarshallingType.STRING) + .memberName("NestedHeaderMember") + .getter(getter(NestedQueryParameterOperation::nestedHeaderMember)) + .setter(setter(Builder::nestedHeaderMember)) + .traits(LocationTrait.builder() + .location(MarshallLocation.PAYLOAD) + .locationName("x-amz-nested-header") + .build()).build(); + + private static final SdkField NESTED_STATUS_CODE_FIELD = SdkField.builder(MarshallingType.INTEGER) + .memberName("NestedStatusCode") + .getter(getter(NestedQueryParameterOperation::nestedStatusCode)) + .setter(setter(Builder::nestedStatusCode)) + .traits(LocationTrait.builder() + .location(MarshallLocation.PAYLOAD) + .locationName("NestedStatusCode") + .build()).build(); + + private static final List> SDK_FIELDS = Collections.unmodifiableList(Arrays.asList(QUERY_PARAM_ONE_FIELD,QUERY_PARAM_TWO_FIELD,NESTED_HEADER_MEMBER_FIELD,NESTED_STATUS_CODE_FIELD)); + + private static final Map> SDK_NAME_TO_FIELD = memberNameToFieldInitializer(); + + private static final long serialVersionUID = 1L; + + private final String queryParamOne; + + private final String queryParamTwo; + + private final String nestedHeaderMember; + + private final Integer nestedStatusCode; + + private NestedQueryParameterOperation(BuilderImpl builder) { + this.queryParamOne = builder.queryParamOne; + this.queryParamTwo = builder.queryParamTwo; + this.nestedHeaderMember = builder.nestedHeaderMember; + this.nestedStatusCode = builder.nestedStatusCode; + } + + /** + * Returns the value of the QueryParamOne property for this object. + * @return The value of the QueryParamOne property for this object. + */ + public final String queryParamOne() { + return queryParamOne; + } + + /** + * Returns the value of the QueryParamTwo property for this object. + * @return The value of the QueryParamTwo property for this object. + */ + public final String queryParamTwo() { + return queryParamTwo; + } + + /** + * Returns the value of the NestedHeaderMember property for this object. + * @return The value of the NestedHeaderMember property for this object. + */ + public final String nestedHeaderMember() { + return nestedHeaderMember; + } + + /** + * Returns the value of the NestedStatusCode property for this object. + * @return The value of the NestedStatusCode property for this object. + */ + public final Integer nestedStatusCode() { + return nestedStatusCode; + } + + @Override + public Builder toBuilder() { + return new BuilderImpl(this); + } + + public static Builder builder() { + return new BuilderImpl(); + } + + public static Class serializableBuilderClass() { + return BuilderImpl.class; + } + + @Override + public final int hashCode() { + int hashCode = 1; + hashCode = 31 * hashCode + Objects.hashCode(queryParamOne()); + hashCode = 31 * hashCode + Objects.hashCode(queryParamTwo()); + hashCode = 31 * hashCode + Objects.hashCode(nestedHeaderMember()); + hashCode = 31 * hashCode + Objects.hashCode(nestedStatusCode()); + return hashCode; + } + + @Override + public final boolean equals(Object obj) { + return equalsBySdkFields(obj); + } + + @Override + public final boolean equalsBySdkFields(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof NestedQueryParameterOperation)) { + return false; } + NestedQueryParameterOperation other = (NestedQueryParameterOperation) obj; + return Objects.equals(queryParamOne(), other.queryParamOne())&&Objects.equals(queryParamTwo(), other.queryParamTwo())&&Objects.equals(nestedHeaderMember(), other.nestedHeaderMember())&&Objects.equals(nestedStatusCode(), other.nestedStatusCode()); + } + + /** + * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be redacted from this string using a placeholder value. + */ + @Override + public final String toString() { + return ToString.builder("NestedQueryParameterOperation").add("QueryParamOne", queryParamOne()).add("QueryParamTwo", queryParamTwo()).add("NestedHeaderMember", nestedHeaderMember()).add("NestedStatusCode", nestedStatusCode()).build(); + } + + public final Optional getValueForField(String fieldName, Class clazz) { + switch (fieldName) { + case "QueryParamOne":return Optional.ofNullable(clazz.cast(queryParamOne())); + case "QueryParamTwo":return Optional.ofNullable(clazz.cast(queryParamTwo())); + case "NestedHeaderMember":return Optional.ofNullable(clazz.cast(nestedHeaderMember())); + case "NestedStatusCode":return Optional.ofNullable(clazz.cast(nestedStatusCode())); + default:return Optional.empty(); + } + } + + @Override + public final List> sdkFields() { + return SDK_FIELDS; + } + + @Override + public final Map> sdkFieldNameToField() { + return SDK_NAME_TO_FIELD; + } + + private static Map> memberNameToFieldInitializer() { + Map> map = new HashMap<>(); + map.put("QueryParamOne", QUERY_PARAM_ONE_FIELD); + map.put("QueryParamTwo", QUERY_PARAM_TWO_FIELD); + map.put("x-amz-nested-header", NESTED_HEADER_MEMBER_FIELD); + map.put("NestedStatusCode", NESTED_STATUS_CODE_FIELD); + return Collections.unmodifiableMap(map); + } + + private static Function getter(Function g) { + return obj -> g.apply((NestedQueryParameterOperation) obj); + } + + private static BiConsumer setter(BiConsumer s) { + return (obj, val) -> s.accept((Builder) obj, val); + } + + @Mutable + @NotThreadSafe + public interface Builder extends SdkPojo, CopyableBuilder { + /** + * Sets the value of the QueryParamOne property for this object. + * + * @param queryParamOne The new value for the QueryParamOne property for this object. + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder queryParamOne(String queryParamOne); /** - * Returns the value of the QueryParamOne property for this object. + * Sets the value of the QueryParamTwo property for this object. * - * @return The value of the QueryParamOne property for this object. + * @param queryParamTwo The new value for the QueryParamTwo property for this object. + * @return Returns a reference to this object so that method calls can be chained together. */ - public final String queryParamOne() { - return queryParamOne; - } + Builder queryParamTwo(String queryParamTwo); + + /** + * Sets the value of the NestedHeaderMember property for this object. + * + * @param nestedHeaderMember The new value for the NestedHeaderMember property for this object. + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder nestedHeaderMember(String nestedHeaderMember); /** - * Returns the value of the QueryParamTwo property for this object. + * Sets the value of the NestedStatusCode property for this object. * - * @return The value of the QueryParamTwo property for this object. + * @param nestedStatusCode The new value for the NestedStatusCode property for this object. + * @return Returns a reference to this object so that method calls can be chained together. */ - public final String queryParamTwo() { - return queryParamTwo; + Builder nestedStatusCode(Integer nestedStatusCode); + } + + static final class BuilderImpl implements Builder { + private String queryParamOne; + + private String queryParamTwo; + + private String nestedHeaderMember; + + private Integer nestedStatusCode; + + private BuilderImpl() { } - @Override - public Builder toBuilder() { - return new BuilderImpl(this); + private BuilderImpl(NestedQueryParameterOperation model) { + queryParamOne(model.queryParamOne); + queryParamTwo(model.queryParamTwo); + nestedHeaderMember(model.nestedHeaderMember); + nestedStatusCode(model.nestedStatusCode); } - public static Builder builder() { - return new BuilderImpl(); + public final String getQueryParamOne() { + return queryParamOne; } - public static Class serializableBuilderClass() { - return BuilderImpl.class; + public final void setQueryParamOne(String queryParamOne) { + this.queryParamOne = queryParamOne; } @Override - public final int hashCode() { - int hashCode = 1; - hashCode = 31 * hashCode + Objects.hashCode(queryParamOne()); - hashCode = 31 * hashCode + Objects.hashCode(queryParamTwo()); - return hashCode; + public final Builder queryParamOne(String queryParamOne) { + this.queryParamOne = queryParamOne; + return this; } - @Override - public final boolean equals(Object obj) { - return equalsBySdkFields(obj); + public final String getQueryParamTwo() { + return queryParamTwo; } - @Override - public final boolean equalsBySdkFields(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof NestedQueryParameterOperation)) { - return false; - } - NestedQueryParameterOperation other = (NestedQueryParameterOperation) obj; - return Objects.equals(queryParamOne(), other.queryParamOne()) && Objects.equals(queryParamTwo(), other.queryParamTwo()); + public final void setQueryParamTwo(String queryParamTwo) { + this.queryParamTwo = queryParamTwo; } - /** - * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be - * redacted from this string using a placeholder value. - */ @Override - public final String toString() { - return ToString.builder("NestedQueryParameterOperation").add("QueryParamOne", queryParamOne()) - .add("QueryParamTwo", queryParamTwo()).build(); + public final Builder queryParamTwo(String queryParamTwo) { + this.queryParamTwo = queryParamTwo; + return this; } - public final Optional getValueForField(String fieldName, Class clazz) { - switch (fieldName) { - case "QueryParamOne": - return Optional.ofNullable(clazz.cast(queryParamOne())); - case "QueryParamTwo": - return Optional.ofNullable(clazz.cast(queryParamTwo())); - default: - return Optional.empty(); - } + public final String getNestedHeaderMember() { + return nestedHeaderMember; } - @Override - public final List> sdkFields() { - return SDK_FIELDS; + public final void setNestedHeaderMember(String nestedHeaderMember) { + this.nestedHeaderMember = nestedHeaderMember; } @Override - public final Map> sdkFieldNameToField() { - return SDK_NAME_TO_FIELD; + public final Builder nestedHeaderMember(String nestedHeaderMember) { + this.nestedHeaderMember = nestedHeaderMember; + return this; } - private static Map> memberNameToFieldInitializer() { - Map> map = new HashMap<>(); - map.put("QueryParamOne", QUERY_PARAM_ONE_FIELD); - map.put("QueryParamTwo", QUERY_PARAM_TWO_FIELD); - return Collections.unmodifiableMap(map); + public final Integer getNestedStatusCode() { + return nestedStatusCode; } - private static Function getter(Function g) { - return obj -> g.apply((NestedQueryParameterOperation) obj); + public final void setNestedStatusCode(Integer nestedStatusCode) { + this.nestedStatusCode = nestedStatusCode; } - private static BiConsumer setter(BiConsumer s) { - return (obj, val) -> s.accept((Builder) obj, val); + @Override + public final Builder nestedStatusCode(Integer nestedStatusCode) { + this.nestedStatusCode = nestedStatusCode; + return this; } - @Mutable - @NotThreadSafe - public interface Builder extends SdkPojo, CopyableBuilder { - /** - * Sets the value of the QueryParamOne property for this object. - * - * @param queryParamOne - * The new value for the QueryParamOne property for this object. - * @return Returns a reference to this object so that method calls can be chained together. - */ - Builder queryParamOne(String queryParamOne); - - /** - * Sets the value of the QueryParamTwo property for this object. - * - * @param queryParamTwo - * The new value for the QueryParamTwo property for this object. - * @return Returns a reference to this object so that method calls can be chained together. - */ - Builder queryParamTwo(String queryParamTwo); + @Override + public NestedQueryParameterOperation build() { + return new NestedQueryParameterOperation(this); } - static final class BuilderImpl implements Builder { - private String queryParamOne; - - private String queryParamTwo; - - private BuilderImpl() { - } - - private BuilderImpl(NestedQueryParameterOperation model) { - queryParamOne(model.queryParamOne); - queryParamTwo(model.queryParamTwo); - } - - public final String getQueryParamOne() { - return queryParamOne; - } - - public final void setQueryParamOne(String queryParamOne) { - this.queryParamOne = queryParamOne; - } - - @Override - public final Builder queryParamOne(String queryParamOne) { - this.queryParamOne = queryParamOne; - return this; - } - - public final String getQueryParamTwo() { - return queryParamTwo; - } - - public final void setQueryParamTwo(String queryParamTwo) { - this.queryParamTwo = queryParamTwo; - } - - @Override - public final Builder queryParamTwo(String queryParamTwo) { - this.queryParamTwo = queryParamTwo; - return this; - } - - @Override - public NestedQueryParameterOperation build() { - return new NestedQueryParameterOperation(this); - } - - @Override - public List> sdkFields() { - return SDK_FIELDS; - } + @Override + public List> sdkFields() { + return SDK_FIELDS; + } - @Override - public Map> sdkFieldNameToField() { - return SDK_NAME_TO_FIELD; - } + @Override + public Map> sdkFieldNameToField() { + return SDK_NAME_TO_FIELD; } + } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/queryparameteroperationrequest.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/queryparameteroperationrequest.java index 6e5452cb2e58..74c7c9899ac8 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/queryparameteroperationrequest.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/queryparameteroperationrequest.java @@ -32,614 +32,607 @@ /** */ @Generated("software.amazon.awssdk:codegen") -public final class QueryParameterOperationRequest extends JsonProtocolTestsRequest implements - ToCopyableBuilder { - private static final SdkField PATH_PARAM_FIELD = SdkField - . builder(MarshallingType.STRING) - .memberName("PathParam") - .getter(getter(QueryParameterOperationRequest::pathParam)) - .setter(setter(Builder::pathParam)) - .traits(LocationTrait.builder().location(MarshallLocation.PATH).locationName("PathParam").build(), - RequiredTrait.create()).build(); - - private static final SdkField QUERY_PARAM_ONE_FIELD = SdkField - . builder(MarshallingType.STRING) - .memberName("QueryParamOne") - .getter(getter(QueryParameterOperationRequest::queryParamOne)) - .setter(setter(Builder::queryParamOne)) - .traits(LocationTrait.builder().location(MarshallLocation.QUERY_PARAM).locationName("QueryParamOne").build(), - RequiredTrait.create()).build(); - - private static final SdkField QUERY_PARAM_TWO_FIELD = SdkField. builder(MarshallingType.STRING) - .memberName("QueryParamTwo").getter(getter(QueryParameterOperationRequest::queryParamTwo)) - .setter(setter(Builder::queryParamTwo)) - .traits(LocationTrait.builder().location(MarshallLocation.QUERY_PARAM).locationName("QueryParamTwo").build()).build(); - - private static final SdkField STRING_HEADER_MEMBER_FIELD = SdkField - . builder(MarshallingType.STRING) - .memberName("StringHeaderMember") - .getter(getter(QueryParameterOperationRequest::stringHeaderMember)) - .setter(setter(Builder::stringHeaderMember)) - .traits(LocationTrait.builder().location(MarshallLocation.HEADER).locationName("x-amz-header-string").build(), - RequiredTrait.create()).build(); - - private static final SdkField NESTED_QUERY_PARAMETER_OPERATION_FIELD = SdkField - . builder(MarshallingType.SDK_POJO) - .memberName("NestedQueryParameterOperation") - .getter(getter(QueryParameterOperationRequest::nestedQueryParameterOperation)) - .setter(setter(Builder::nestedQueryParameterOperation)) - .constructor(NestedQueryParameterOperation::builder) - .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("NestedQueryParameterOperation") - .build(), PayloadTrait.create()).build(); - - private static final SdkField> REQUIRED_LIST_QUERY_PARAMS_FIELD = SdkField - .> builder(MarshallingType.LIST) - .memberName("RequiredListQueryParams") - .getter(getter(QueryParameterOperationRequest::requiredListQueryParams)) - .setter(setter(Builder::requiredListQueryParams)) - .traits(LocationTrait.builder().location(MarshallLocation.QUERY_PARAM).locationName("RequiredListQueryParams") - .build(), - ListTrait - .builder() - .memberLocationName(null) - .memberFieldInfo( - SdkField. builder(MarshallingType.INTEGER) - .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD) - .locationName("member").build()).build()).build(), RequiredTrait.create()) - .build(); - - private static final SdkField> OPTIONAL_LIST_QUERY_PARAMS_FIELD = SdkField - .> builder(MarshallingType.LIST) - .memberName("OptionalListQueryParams") - .getter(getter(QueryParameterOperationRequest::optionalListQueryParams)) - .setter(setter(Builder::optionalListQueryParams)) - .traits(LocationTrait.builder().location(MarshallLocation.QUERY_PARAM).locationName("OptionalListQueryParams") - .build(), - ListTrait - .builder() - .memberLocationName(null) - .memberFieldInfo( - SdkField. builder(MarshallingType.INTEGER) - .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD) - .locationName("member").build()).build()).build()).build(); - - private static final List> SDK_FIELDS = Collections.unmodifiableList(Arrays.asList(PATH_PARAM_FIELD, - QUERY_PARAM_ONE_FIELD, QUERY_PARAM_TWO_FIELD, STRING_HEADER_MEMBER_FIELD, NESTED_QUERY_PARAMETER_OPERATION_FIELD, - REQUIRED_LIST_QUERY_PARAMS_FIELD, OPTIONAL_LIST_QUERY_PARAMS_FIELD)); - - private static final Map> SDK_NAME_TO_FIELD = memberNameToFieldInitializer(); - - private final String pathParam; - - private final String queryParamOne; - - private final String queryParamTwo; - - private final String stringHeaderMember; - - private final NestedQueryParameterOperation nestedQueryParameterOperation; - - private final List requiredListQueryParams; - - private final List optionalListQueryParams; - - private QueryParameterOperationRequest(BuilderImpl builder) { - super(builder); - this.pathParam = builder.pathParam; - this.queryParamOne = builder.queryParamOne; - this.queryParamTwo = builder.queryParamTwo; - this.stringHeaderMember = builder.stringHeaderMember; - this.nestedQueryParameterOperation = builder.nestedQueryParameterOperation; - this.requiredListQueryParams = builder.requiredListQueryParams; - this.optionalListQueryParams = builder.optionalListQueryParams; +public final class QueryParameterOperationRequest extends JsonProtocolTestsRequest implements ToCopyableBuilder { + private static final SdkField PATH_PARAM_FIELD = SdkField.builder(MarshallingType.STRING) + .memberName("PathParam") + .getter(getter(QueryParameterOperationRequest::pathParam)) + .setter(setter(Builder::pathParam)) + .traits(LocationTrait.builder() + .location(MarshallLocation.PATH) + .locationName("PathParam") + .build(), RequiredTrait.create()).build(); + + private static final SdkField QUERY_PARAM_ONE_FIELD = SdkField.builder(MarshallingType.STRING) + .memberName("QueryParamOne") + .getter(getter(QueryParameterOperationRequest::queryParamOne)) + .setter(setter(Builder::queryParamOne)) + .traits(LocationTrait.builder() + .location(MarshallLocation.QUERY_PARAM) + .locationName("QueryParamOne") + .build(), RequiredTrait.create()).build(); + + private static final SdkField QUERY_PARAM_TWO_FIELD = SdkField.builder(MarshallingType.STRING) + .memberName("QueryParamTwo") + .getter(getter(QueryParameterOperationRequest::queryParamTwo)) + .setter(setter(Builder::queryParamTwo)) + .traits(LocationTrait.builder() + .location(MarshallLocation.QUERY_PARAM) + .locationName("QueryParamTwo") + .build()).build(); + + private static final SdkField STRING_HEADER_MEMBER_FIELD = SdkField.builder(MarshallingType.STRING) + .memberName("StringHeaderMember") + .getter(getter(QueryParameterOperationRequest::stringHeaderMember)) + .setter(setter(Builder::stringHeaderMember)) + .traits(LocationTrait.builder() + .location(MarshallLocation.HEADER) + .locationName("x-amz-header-string") + .build(), RequiredTrait.create()).build(); + + private static final SdkField NESTED_QUERY_PARAMETER_OPERATION_FIELD = SdkField.builder(MarshallingType.SDK_POJO) + .memberName("NestedQueryParameterOperation") + .getter(getter(QueryParameterOperationRequest::nestedQueryParameterOperation)) + .setter(setter(Builder::nestedQueryParameterOperation)) + .constructor(NestedQueryParameterOperation::builder) + .traits(LocationTrait.builder() + .location(MarshallLocation.PAYLOAD) + .locationName("NestedQueryParameterOperation") + .build(), PayloadTrait.create()).build(); + + private static final SdkField> REQUIRED_LIST_QUERY_PARAMS_FIELD = SdkField.>builder(MarshallingType.LIST) + .memberName("RequiredListQueryParams") + .getter(getter(QueryParameterOperationRequest::requiredListQueryParams)) + .setter(setter(Builder::requiredListQueryParams)) + .traits(LocationTrait.builder() + .location(MarshallLocation.QUERY_PARAM) + .locationName("RequiredListQueryParams") + .build(), ListTrait.builder() + .memberLocationName(null) + .memberFieldInfo(SdkField.builder(MarshallingType.INTEGER) + .traits(LocationTrait.builder() + .location(MarshallLocation.PAYLOAD) + .locationName("member") + .build()).build()) + .build(), RequiredTrait.create()).build(); + + private static final SdkField> OPTIONAL_LIST_QUERY_PARAMS_FIELD = SdkField.>builder(MarshallingType.LIST) + .memberName("OptionalListQueryParams") + .getter(getter(QueryParameterOperationRequest::optionalListQueryParams)) + .setter(setter(Builder::optionalListQueryParams)) + .traits(LocationTrait.builder() + .location(MarshallLocation.QUERY_PARAM) + .locationName("OptionalListQueryParams") + .build(), ListTrait.builder() + .memberLocationName(null) + .memberFieldInfo(SdkField.builder(MarshallingType.INTEGER) + .traits(LocationTrait.builder() + .location(MarshallLocation.PAYLOAD) + .locationName("member") + .build()).build()) + .build()).build(); + + private static final SdkField STATUS_CODE_ON_INPUT_FIELD = SdkField.builder(MarshallingType.INTEGER) + .memberName("StatusCodeOnInput") + .getter(getter(QueryParameterOperationRequest::statusCodeOnInput)) + .setter(setter(Builder::statusCodeOnInput)) + .traits(LocationTrait.builder() + .location(MarshallLocation.PAYLOAD) + .locationName("StatusCodeOnInput") + .build()).build(); + + private static final List> SDK_FIELDS = Collections.unmodifiableList(Arrays.asList(PATH_PARAM_FIELD,QUERY_PARAM_ONE_FIELD,QUERY_PARAM_TWO_FIELD,STRING_HEADER_MEMBER_FIELD,NESTED_QUERY_PARAMETER_OPERATION_FIELD,REQUIRED_LIST_QUERY_PARAMS_FIELD,OPTIONAL_LIST_QUERY_PARAMS_FIELD,STATUS_CODE_ON_INPUT_FIELD)); + + private static final Map> SDK_NAME_TO_FIELD = memberNameToFieldInitializer(); + + private final String pathParam; + + private final String queryParamOne; + + private final String queryParamTwo; + + private final String stringHeaderMember; + + private final NestedQueryParameterOperation nestedQueryParameterOperation; + + private final List requiredListQueryParams; + + private final List optionalListQueryParams; + + private final Integer statusCodeOnInput; + + private QueryParameterOperationRequest(BuilderImpl builder) { + super(builder); + this.pathParam = builder.pathParam; + this.queryParamOne = builder.queryParamOne; + this.queryParamTwo = builder.queryParamTwo; + this.stringHeaderMember = builder.stringHeaderMember; + this.nestedQueryParameterOperation = builder.nestedQueryParameterOperation; + this.requiredListQueryParams = builder.requiredListQueryParams; + this.optionalListQueryParams = builder.optionalListQueryParams; + this.statusCodeOnInput = builder.statusCodeOnInput; + } + + /** + * Returns the value of the PathParam property for this object. + * @return The value of the PathParam property for this object. + */ + public final String pathParam() { + return pathParam; + } + + /** + * Returns the value of the QueryParamOne property for this object. + * @return The value of the QueryParamOne property for this object. + */ + public final String queryParamOne() { + return queryParamOne; + } + + /** + * Returns the value of the QueryParamTwo property for this object. + * @return The value of the QueryParamTwo property for this object. + */ + public final String queryParamTwo() { + return queryParamTwo; + } + + /** + * Returns the value of the StringHeaderMember property for this object. + * @return The value of the StringHeaderMember property for this object. + */ + public final String stringHeaderMember() { + return stringHeaderMember; + } + + /** + * Returns the value of the NestedQueryParameterOperation property for this object. + * @return The value of the NestedQueryParameterOperation property for this object. + */ + public final NestedQueryParameterOperation nestedQueryParameterOperation() { + return nestedQueryParameterOperation; + } + + /** + * For responses, this returns true if the service returned a value for the RequiredListQueryParams property. This DOES NOT check that the value is non-empty (for which, you should check the {@code isEmpty()} method on the property). This is useful because the SDK will never return a null collection or map, but you may need to differentiate between the service returning nothing (or null) and the service returning an empty collection or map. For requests, this returns true if a value for the property was specified in the request builder, and false if a value was not specified. + */ + public final boolean hasRequiredListQueryParams() { + return requiredListQueryParams != null && !(requiredListQueryParams instanceof SdkAutoConstructList); + } + + /** + * Returns the value of the RequiredListQueryParams property for this object. + *

+ * Attempts to modify the collection returned by this method will result in an UnsupportedOperationException. + *

+ *

+ * This method will never return null. If you would like to know whether the service returned this field (so that you can differentiate between null and empty), you can use the {@link #hasRequiredListQueryParams} method. + *

+ * @return The value of the RequiredListQueryParams property for this object. + */ + public final List requiredListQueryParams() { + return requiredListQueryParams; + } + + /** + * For responses, this returns true if the service returned a value for the OptionalListQueryParams property. This DOES NOT check that the value is non-empty (for which, you should check the {@code isEmpty()} method on the property). This is useful because the SDK will never return a null collection or map, but you may need to differentiate between the service returning nothing (or null) and the service returning an empty collection or map. For requests, this returns true if a value for the property was specified in the request builder, and false if a value was not specified. + */ + public final boolean hasOptionalListQueryParams() { + return optionalListQueryParams != null && !(optionalListQueryParams instanceof SdkAutoConstructList); + } + + /** + * Returns the value of the OptionalListQueryParams property for this object. + *

+ * Attempts to modify the collection returned by this method will result in an UnsupportedOperationException. + *

+ *

+ * This method will never return null. If you would like to know whether the service returned this field (so that you can differentiate between null and empty), you can use the {@link #hasOptionalListQueryParams} method. + *

+ * @return The value of the OptionalListQueryParams property for this object. + */ + public final List optionalListQueryParams() { + return optionalListQueryParams; + } + + /** + * Returns the value of the StatusCodeOnInput property for this object. + * @return The value of the StatusCodeOnInput property for this object. + */ + public final Integer statusCodeOnInput() { + return statusCodeOnInput; + } + + @Override + public Builder toBuilder() { + return new BuilderImpl(this); + } + + public static Builder builder() { + return new BuilderImpl(); + } + + public static Class serializableBuilderClass() { + return BuilderImpl.class; + } + + @Override + public final int hashCode() { + int hashCode = 1; + hashCode = 31 * hashCode + super.hashCode(); + hashCode = 31 * hashCode + Objects.hashCode(pathParam()); + hashCode = 31 * hashCode + Objects.hashCode(queryParamOne()); + hashCode = 31 * hashCode + Objects.hashCode(queryParamTwo()); + hashCode = 31 * hashCode + Objects.hashCode(stringHeaderMember()); + hashCode = 31 * hashCode + Objects.hashCode(nestedQueryParameterOperation()); + hashCode = 31 * hashCode + Objects.hashCode(hasRequiredListQueryParams() ? requiredListQueryParams() : null); + hashCode = 31 * hashCode + Objects.hashCode(hasOptionalListQueryParams() ? optionalListQueryParams() : null); + hashCode = 31 * hashCode + Objects.hashCode(statusCodeOnInput()); + return hashCode; + } + + @Override + public final boolean equals(Object obj) { + return super.equals(obj) && equalsBySdkFields(obj); + } + + @Override + public final boolean equalsBySdkFields(Object obj) { + if (this == obj) { + return true; } + if (obj == null) { + return false; + } + if (!(obj instanceof QueryParameterOperationRequest)) { + return false; + } + QueryParameterOperationRequest other = (QueryParameterOperationRequest) obj; + return Objects.equals(pathParam(), other.pathParam())&&Objects.equals(queryParamOne(), other.queryParamOne())&&Objects.equals(queryParamTwo(), other.queryParamTwo())&&Objects.equals(stringHeaderMember(), other.stringHeaderMember())&&Objects.equals(nestedQueryParameterOperation(), other.nestedQueryParameterOperation())&&hasRequiredListQueryParams() == other.hasRequiredListQueryParams() && Objects.equals(requiredListQueryParams(), other.requiredListQueryParams())&&hasOptionalListQueryParams() == other.hasOptionalListQueryParams() && Objects.equals(optionalListQueryParams(), other.optionalListQueryParams())&&Objects.equals(statusCodeOnInput(), other.statusCodeOnInput()); + } + + /** + * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be redacted from this string using a placeholder value. + */ + @Override + public final String toString() { + return ToString.builder("QueryParameterOperationRequest").add("PathParam", pathParam()).add("QueryParamOne", queryParamOne()).add("QueryParamTwo", queryParamTwo()).add("StringHeaderMember", stringHeaderMember()).add("NestedQueryParameterOperation", nestedQueryParameterOperation()).add("RequiredListQueryParams", hasRequiredListQueryParams() ? requiredListQueryParams() : null).add("OptionalListQueryParams", hasOptionalListQueryParams() ? optionalListQueryParams() : null).add("StatusCodeOnInput", statusCodeOnInput()).build(); + } + + public final Optional getValueForField(String fieldName, Class clazz) { + switch (fieldName) { + case "PathParam":return Optional.ofNullable(clazz.cast(pathParam())); + case "QueryParamOne":return Optional.ofNullable(clazz.cast(queryParamOne())); + case "QueryParamTwo":return Optional.ofNullable(clazz.cast(queryParamTwo())); + case "StringHeaderMember":return Optional.ofNullable(clazz.cast(stringHeaderMember())); + case "NestedQueryParameterOperation":return Optional.ofNullable(clazz.cast(nestedQueryParameterOperation())); + case "RequiredListQueryParams":return Optional.ofNullable(clazz.cast(requiredListQueryParams())); + case "OptionalListQueryParams":return Optional.ofNullable(clazz.cast(optionalListQueryParams())); + case "StatusCodeOnInput":return Optional.ofNullable(clazz.cast(statusCodeOnInput())); + default:return Optional.empty(); + } + } + + @Override + public final List> sdkFields() { + return SDK_FIELDS; + } + + @Override + public final Map> sdkFieldNameToField() { + return SDK_NAME_TO_FIELD; + } + + private static Map> memberNameToFieldInitializer() { + Map> map = new HashMap<>(); + map.put("PathParam", PATH_PARAM_FIELD); + map.put("QueryParamOne", QUERY_PARAM_ONE_FIELD); + map.put("QueryParamTwo", QUERY_PARAM_TWO_FIELD); + map.put("x-amz-header-string", STRING_HEADER_MEMBER_FIELD); + map.put("NestedQueryParameterOperation", NESTED_QUERY_PARAMETER_OPERATION_FIELD); + map.put("RequiredListQueryParams", REQUIRED_LIST_QUERY_PARAMS_FIELD); + map.put("OptionalListQueryParams", OPTIONAL_LIST_QUERY_PARAMS_FIELD); + map.put("StatusCodeOnInput", STATUS_CODE_ON_INPUT_FIELD); + return Collections.unmodifiableMap(map); + } + + private static Function getter(Function g) { + return obj -> g.apply((QueryParameterOperationRequest) obj); + } + + private static BiConsumer setter(BiConsumer s) { + return (obj, val) -> s.accept((Builder) obj, val); + } + + @Mutable + @NotThreadSafe + public interface Builder extends JsonProtocolTestsRequest.Builder, SdkPojo, CopyableBuilder { + /** + * Sets the value of the PathParam property for this object. + * + * @param pathParam The new value for the PathParam property for this object. + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder pathParam(String pathParam); /** - * Returns the value of the PathParam property for this object. + * Sets the value of the QueryParamOne property for this object. * - * @return The value of the PathParam property for this object. + * @param queryParamOne The new value for the QueryParamOne property for this object. + * @return Returns a reference to this object so that method calls can be chained together. */ - public final String pathParam() { - return pathParam; - } + Builder queryParamOne(String queryParamOne); /** - * Returns the value of the QueryParamOne property for this object. + * Sets the value of the QueryParamTwo property for this object. * - * @return The value of the QueryParamOne property for this object. + * @param queryParamTwo The new value for the QueryParamTwo property for this object. + * @return Returns a reference to this object so that method calls can be chained together. */ - public final String queryParamOne() { - return queryParamOne; - } + Builder queryParamTwo(String queryParamTwo); /** - * Returns the value of the QueryParamTwo property for this object. + * Sets the value of the StringHeaderMember property for this object. * - * @return The value of the QueryParamTwo property for this object. + * @param stringHeaderMember The new value for the StringHeaderMember property for this object. + * @return Returns a reference to this object so that method calls can be chained together. */ - public final String queryParamTwo() { - return queryParamTwo; - } + Builder stringHeaderMember(String stringHeaderMember); /** - * Returns the value of the StringHeaderMember property for this object. + * Sets the value of the NestedQueryParameterOperation property for this object. * - * @return The value of the StringHeaderMember property for this object. + * @param nestedQueryParameterOperation The new value for the NestedQueryParameterOperation property for this object. + * @return Returns a reference to this object so that method calls can be chained together. */ - public final String stringHeaderMember() { - return stringHeaderMember; - } + Builder nestedQueryParameterOperation( + NestedQueryParameterOperation nestedQueryParameterOperation); /** - * Returns the value of the NestedQueryParameterOperation property for this object. + * Sets the value of the NestedQueryParameterOperation property for this object. + * + * This is a convenience method that creates an instance of the {@link NestedQueryParameterOperation.Builder} avoiding the need to create one manually via {@link NestedQueryParameterOperation#builder()}. * - * @return The value of the NestedQueryParameterOperation property for this object. + *

When the {@link Consumer} completes, {@link NestedQueryParameterOperation.Builder#build()} is called immediately and its result is passed to {@link #nestedQueryParameterOperation(NestedQueryParameterOperation)}. + * @param nestedQueryParameterOperation a consumer that will call methods on {@link NestedQueryParameterOperation.Builder} + * @return Returns a reference to this object so that method calls can be chained together. + * @see #nestedQueryParameterOperation(NestedQueryParameterOperation) */ - public final NestedQueryParameterOperation nestedQueryParameterOperation() { - return nestedQueryParameterOperation; + default Builder nestedQueryParameterOperation( + Consumer nestedQueryParameterOperation) { + return nestedQueryParameterOperation(NestedQueryParameterOperation.builder().applyMutation(nestedQueryParameterOperation).build()); } /** - * For responses, this returns true if the service returned a value for the RequiredListQueryParams property. This - * DOES NOT check that the value is non-empty (for which, you should check the {@code isEmpty()} method on the - * property). This is useful because the SDK will never return a null collection or map, but you may need to - * differentiate between the service returning nothing (or null) and the service returning an empty collection or - * map. For requests, this returns true if a value for the property was specified in the request builder, and false - * if a value was not specified. + * Sets the value of the RequiredListQueryParams property for this object. + * + * @param requiredListQueryParams The new value for the RequiredListQueryParams property for this object. + * @return Returns a reference to this object so that method calls can be chained together. */ - public final boolean hasRequiredListQueryParams() { - return requiredListQueryParams != null && !(requiredListQueryParams instanceof SdkAutoConstructList); - } + Builder requiredListQueryParams(Collection requiredListQueryParams); /** - * Returns the value of the RequiredListQueryParams property for this object. - *

- * Attempts to modify the collection returned by this method will result in an UnsupportedOperationException. - *

- *

- * This method will never return null. If you would like to know whether the service returned this field (so that - * you can differentiate between null and empty), you can use the {@link #hasRequiredListQueryParams} method. - *

+ * Sets the value of the RequiredListQueryParams property for this object. * - * @return The value of the RequiredListQueryParams property for this object. + * @param requiredListQueryParams The new value for the RequiredListQueryParams property for this object. + * @return Returns a reference to this object so that method calls can be chained together. */ - public final List requiredListQueryParams() { - return requiredListQueryParams; - } + Builder requiredListQueryParams(Integer... requiredListQueryParams); /** - * For responses, this returns true if the service returned a value for the OptionalListQueryParams property. This - * DOES NOT check that the value is non-empty (for which, you should check the {@code isEmpty()} method on the - * property). This is useful because the SDK will never return a null collection or map, but you may need to - * differentiate between the service returning nothing (or null) and the service returning an empty collection or - * map. For requests, this returns true if a value for the property was specified in the request builder, and false - * if a value was not specified. + * Sets the value of the OptionalListQueryParams property for this object. + * + * @param optionalListQueryParams The new value for the OptionalListQueryParams property for this object. + * @return Returns a reference to this object so that method calls can be chained together. */ - public final boolean hasOptionalListQueryParams() { - return optionalListQueryParams != null && !(optionalListQueryParams instanceof SdkAutoConstructList); - } + Builder optionalListQueryParams(Collection optionalListQueryParams); /** - * Returns the value of the OptionalListQueryParams property for this object. - *

- * Attempts to modify the collection returned by this method will result in an UnsupportedOperationException. - *

- *

- * This method will never return null. If you would like to know whether the service returned this field (so that - * you can differentiate between null and empty), you can use the {@link #hasOptionalListQueryParams} method. - *

+ * Sets the value of the OptionalListQueryParams property for this object. * - * @return The value of the OptionalListQueryParams property for this object. + * @param optionalListQueryParams The new value for the OptionalListQueryParams property for this object. + * @return Returns a reference to this object so that method calls can be chained together. */ - public final List optionalListQueryParams() { - return optionalListQueryParams; + Builder optionalListQueryParams(Integer... optionalListQueryParams); + + /** + * Sets the value of the StatusCodeOnInput property for this object. + * + * @param statusCodeOnInput The new value for the StatusCodeOnInput property for this object. + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder statusCodeOnInput(Integer statusCodeOnInput); + + @Override + Builder overrideConfiguration(AwsRequestOverrideConfiguration overrideConfiguration); + + @Override + Builder overrideConfiguration( + Consumer builderConsumer); + } + + static final class BuilderImpl extends JsonProtocolTestsRequest.BuilderImpl implements Builder { + private String pathParam; + + private String queryParamOne; + + private String queryParamTwo; + + private String stringHeaderMember; + + private NestedQueryParameterOperation nestedQueryParameterOperation; + + private List requiredListQueryParams = DefaultSdkAutoConstructList.getInstance(); + + private List optionalListQueryParams = DefaultSdkAutoConstructList.getInstance(); + + private Integer statusCodeOnInput; + + private BuilderImpl() { + } + + private BuilderImpl(QueryParameterOperationRequest model) { + super(model);pathParam(model.pathParam); + queryParamOne(model.queryParamOne); + queryParamTwo(model.queryParamTwo); + stringHeaderMember(model.stringHeaderMember); + nestedQueryParameterOperation(model.nestedQueryParameterOperation); + requiredListQueryParams(model.requiredListQueryParams); + optionalListQueryParams(model.optionalListQueryParams); + statusCodeOnInput(model.statusCodeOnInput); + } + + public final String getPathParam() { + return pathParam; + } + + public final void setPathParam(String pathParam) { + this.pathParam = pathParam; } @Override - public Builder toBuilder() { - return new BuilderImpl(this); + public final Builder pathParam(String pathParam) { + this.pathParam = pathParam; + return this; } - public static Builder builder() { - return new BuilderImpl(); + public final String getQueryParamOne() { + return queryParamOne; } - public static Class serializableBuilderClass() { - return BuilderImpl.class; + public final void setQueryParamOne(String queryParamOne) { + this.queryParamOne = queryParamOne; } @Override - public final int hashCode() { - int hashCode = 1; - hashCode = 31 * hashCode + super.hashCode(); - hashCode = 31 * hashCode + Objects.hashCode(pathParam()); - hashCode = 31 * hashCode + Objects.hashCode(queryParamOne()); - hashCode = 31 * hashCode + Objects.hashCode(queryParamTwo()); - hashCode = 31 * hashCode + Objects.hashCode(stringHeaderMember()); - hashCode = 31 * hashCode + Objects.hashCode(nestedQueryParameterOperation()); - hashCode = 31 * hashCode + Objects.hashCode(hasRequiredListQueryParams() ? requiredListQueryParams() : null); - hashCode = 31 * hashCode + Objects.hashCode(hasOptionalListQueryParams() ? optionalListQueryParams() : null); - return hashCode; + public final Builder queryParamOne(String queryParamOne) { + this.queryParamOne = queryParamOne; + return this; + } + + public final String getQueryParamTwo() { + return queryParamTwo; + } + + public final void setQueryParamTwo(String queryParamTwo) { + this.queryParamTwo = queryParamTwo; } @Override - public final boolean equals(Object obj) { - return super.equals(obj) && equalsBySdkFields(obj); + public final Builder queryParamTwo(String queryParamTwo) { + this.queryParamTwo = queryParamTwo; + return this; + } + + public final String getStringHeaderMember() { + return stringHeaderMember; + } + + public final void setStringHeaderMember(String stringHeaderMember) { + this.stringHeaderMember = stringHeaderMember; } @Override - public final boolean equalsBySdkFields(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof QueryParameterOperationRequest)) { - return false; - } - QueryParameterOperationRequest other = (QueryParameterOperationRequest) obj; - return Objects.equals(pathParam(), other.pathParam()) && Objects.equals(queryParamOne(), other.queryParamOne()) - && Objects.equals(queryParamTwo(), other.queryParamTwo()) - && Objects.equals(stringHeaderMember(), other.stringHeaderMember()) - && Objects.equals(nestedQueryParameterOperation(), other.nestedQueryParameterOperation()) - && hasRequiredListQueryParams() == other.hasRequiredListQueryParams() - && Objects.equals(requiredListQueryParams(), other.requiredListQueryParams()) - && hasOptionalListQueryParams() == other.hasOptionalListQueryParams() - && Objects.equals(optionalListQueryParams(), other.optionalListQueryParams()); + public final Builder stringHeaderMember(String stringHeaderMember) { + this.stringHeaderMember = stringHeaderMember; + return this; + } + + public final NestedQueryParameterOperation.Builder getNestedQueryParameterOperation() { + return nestedQueryParameterOperation != null ? nestedQueryParameterOperation.toBuilder() : null; + } + + public final void setNestedQueryParameterOperation( + NestedQueryParameterOperation.BuilderImpl nestedQueryParameterOperation) { + this.nestedQueryParameterOperation = nestedQueryParameterOperation != null ? nestedQueryParameterOperation.build() : null; + } + + @Override + public final Builder nestedQueryParameterOperation( + NestedQueryParameterOperation nestedQueryParameterOperation) { + this.nestedQueryParameterOperation = nestedQueryParameterOperation; + return this; + } + + public final Collection getRequiredListQueryParams() { + if (requiredListQueryParams instanceof SdkAutoConstructList) {return null;}return requiredListQueryParams; + } + + public final void setRequiredListQueryParams(Collection requiredListQueryParams) { + this.requiredListQueryParams = ListOfIntegersCopier.copy(requiredListQueryParams); + } + + @Override + public final Builder requiredListQueryParams(Collection requiredListQueryParams) { + this.requiredListQueryParams = ListOfIntegersCopier.copy(requiredListQueryParams); + return this; + } + + @Override + @SafeVarargs + public final Builder requiredListQueryParams(Integer... requiredListQueryParams) { + requiredListQueryParams(Arrays.asList(requiredListQueryParams));return this; + } + + public final Collection getOptionalListQueryParams() { + if (optionalListQueryParams instanceof SdkAutoConstructList) {return null;}return optionalListQueryParams; + } + + public final void setOptionalListQueryParams(Collection optionalListQueryParams) { + this.optionalListQueryParams = ListOfIntegersCopier.copy(optionalListQueryParams); + } + + @Override + public final Builder optionalListQueryParams(Collection optionalListQueryParams) { + this.optionalListQueryParams = ListOfIntegersCopier.copy(optionalListQueryParams); + return this; + } + + @Override + @SafeVarargs + public final Builder optionalListQueryParams(Integer... optionalListQueryParams) { + optionalListQueryParams(Arrays.asList(optionalListQueryParams));return this; + } + + public final Integer getStatusCodeOnInput() { + return statusCodeOnInput; + } + + public final void setStatusCodeOnInput(Integer statusCodeOnInput) { + this.statusCodeOnInput = statusCodeOnInput; + } + + @Override + public final Builder statusCodeOnInput(Integer statusCodeOnInput) { + this.statusCodeOnInput = statusCodeOnInput; + return this; + } + + @Override + public Builder overrideConfiguration(AwsRequestOverrideConfiguration overrideConfiguration) { + super.overrideConfiguration(overrideConfiguration); + return this; + } + + @Override + public Builder overrideConfiguration( + Consumer builderConsumer) { + super.overrideConfiguration(builderConsumer); + return this; } - /** - * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be - * redacted from this string using a placeholder value. - */ @Override - public final String toString() { - return ToString.builder("QueryParameterOperationRequest").add("PathParam", pathParam()) - .add("QueryParamOne", queryParamOne()).add("QueryParamTwo", queryParamTwo()) - .add("StringHeaderMember", stringHeaderMember()) - .add("NestedQueryParameterOperation", nestedQueryParameterOperation()) - .add("RequiredListQueryParams", hasRequiredListQueryParams() ? requiredListQueryParams() : null) - .add("OptionalListQueryParams", hasOptionalListQueryParams() ? optionalListQueryParams() : null).build(); - } - - public final Optional getValueForField(String fieldName, Class clazz) { - switch (fieldName) { - case "PathParam": - return Optional.ofNullable(clazz.cast(pathParam())); - case "QueryParamOne": - return Optional.ofNullable(clazz.cast(queryParamOne())); - case "QueryParamTwo": - return Optional.ofNullable(clazz.cast(queryParamTwo())); - case "StringHeaderMember": - return Optional.ofNullable(clazz.cast(stringHeaderMember())); - case "NestedQueryParameterOperation": - return Optional.ofNullable(clazz.cast(nestedQueryParameterOperation())); - case "RequiredListQueryParams": - return Optional.ofNullable(clazz.cast(requiredListQueryParams())); - case "OptionalListQueryParams": - return Optional.ofNullable(clazz.cast(optionalListQueryParams())); - default: - return Optional.empty(); - } + public QueryParameterOperationRequest build() { + return new QueryParameterOperationRequest(this); } @Override - public final List> sdkFields() { - return SDK_FIELDS; + public List> sdkFields() { + return SDK_FIELDS; } @Override - public final Map> sdkFieldNameToField() { - return SDK_NAME_TO_FIELD; - } - - private static Map> memberNameToFieldInitializer() { - Map> map = new HashMap<>(); - map.put("PathParam", PATH_PARAM_FIELD); - map.put("QueryParamOne", QUERY_PARAM_ONE_FIELD); - map.put("QueryParamTwo", QUERY_PARAM_TWO_FIELD); - map.put("x-amz-header-string", STRING_HEADER_MEMBER_FIELD); - map.put("NestedQueryParameterOperation", NESTED_QUERY_PARAMETER_OPERATION_FIELD); - map.put("RequiredListQueryParams", REQUIRED_LIST_QUERY_PARAMS_FIELD); - map.put("OptionalListQueryParams", OPTIONAL_LIST_QUERY_PARAMS_FIELD); - return Collections.unmodifiableMap(map); - } - - private static Function getter(Function g) { - return obj -> g.apply((QueryParameterOperationRequest) obj); - } - - private static BiConsumer setter(BiConsumer s) { - return (obj, val) -> s.accept((Builder) obj, val); - } - - @Mutable - @NotThreadSafe - public interface Builder extends JsonProtocolTestsRequest.Builder, SdkPojo, - CopyableBuilder { - /** - * Sets the value of the PathParam property for this object. - * - * @param pathParam - * The new value for the PathParam property for this object. - * @return Returns a reference to this object so that method calls can be chained together. - */ - Builder pathParam(String pathParam); - - /** - * Sets the value of the QueryParamOne property for this object. - * - * @param queryParamOne - * The new value for the QueryParamOne property for this object. - * @return Returns a reference to this object so that method calls can be chained together. - */ - Builder queryParamOne(String queryParamOne); - - /** - * Sets the value of the QueryParamTwo property for this object. - * - * @param queryParamTwo - * The new value for the QueryParamTwo property for this object. - * @return Returns a reference to this object so that method calls can be chained together. - */ - Builder queryParamTwo(String queryParamTwo); - - /** - * Sets the value of the StringHeaderMember property for this object. - * - * @param stringHeaderMember - * The new value for the StringHeaderMember property for this object. - * @return Returns a reference to this object so that method calls can be chained together. - */ - Builder stringHeaderMember(String stringHeaderMember); - - /** - * Sets the value of the NestedQueryParameterOperation property for this object. - * - * @param nestedQueryParameterOperation - * The new value for the NestedQueryParameterOperation property for this object. - * @return Returns a reference to this object so that method calls can be chained together. - */ - Builder nestedQueryParameterOperation(NestedQueryParameterOperation nestedQueryParameterOperation); - - /** - * Sets the value of the NestedQueryParameterOperation property for this object. - * - * This is a convenience method that creates an instance of the {@link NestedQueryParameterOperation.Builder} - * avoiding the need to create one manually via {@link NestedQueryParameterOperation#builder()}. - * - *

- * When the {@link Consumer} completes, {@link NestedQueryParameterOperation.Builder#build()} is called - * immediately and its result is passed to {@link #nestedQueryParameterOperation(NestedQueryParameterOperation)}. - * - * @param nestedQueryParameterOperation - * a consumer that will call methods on {@link NestedQueryParameterOperation.Builder} - * @return Returns a reference to this object so that method calls can be chained together. - * @see #nestedQueryParameterOperation(NestedQueryParameterOperation) - */ - default Builder nestedQueryParameterOperation( - Consumer nestedQueryParameterOperation) { - return nestedQueryParameterOperation(NestedQueryParameterOperation.builder() - .applyMutation(nestedQueryParameterOperation).build()); - } - - /** - * Sets the value of the RequiredListQueryParams property for this object. - * - * @param requiredListQueryParams - * The new value for the RequiredListQueryParams property for this object. - * @return Returns a reference to this object so that method calls can be chained together. - */ - Builder requiredListQueryParams(Collection requiredListQueryParams); - - /** - * Sets the value of the RequiredListQueryParams property for this object. - * - * @param requiredListQueryParams - * The new value for the RequiredListQueryParams property for this object. - * @return Returns a reference to this object so that method calls can be chained together. - */ - Builder requiredListQueryParams(Integer... requiredListQueryParams); - - /** - * Sets the value of the OptionalListQueryParams property for this object. - * - * @param optionalListQueryParams - * The new value for the OptionalListQueryParams property for this object. - * @return Returns a reference to this object so that method calls can be chained together. - */ - Builder optionalListQueryParams(Collection optionalListQueryParams); - - /** - * Sets the value of the OptionalListQueryParams property for this object. - * - * @param optionalListQueryParams - * The new value for the OptionalListQueryParams property for this object. - * @return Returns a reference to this object so that method calls can be chained together. - */ - Builder optionalListQueryParams(Integer... optionalListQueryParams); - - @Override - Builder overrideConfiguration(AwsRequestOverrideConfiguration overrideConfiguration); - - @Override - Builder overrideConfiguration(Consumer builderConsumer); - } - - static final class BuilderImpl extends JsonProtocolTestsRequest.BuilderImpl implements Builder { - private String pathParam; - - private String queryParamOne; - - private String queryParamTwo; - - private String stringHeaderMember; - - private NestedQueryParameterOperation nestedQueryParameterOperation; - - private List requiredListQueryParams = DefaultSdkAutoConstructList.getInstance(); - - private List optionalListQueryParams = DefaultSdkAutoConstructList.getInstance(); - - private BuilderImpl() { - } - - private BuilderImpl(QueryParameterOperationRequest model) { - super(model); - pathParam(model.pathParam); - queryParamOne(model.queryParamOne); - queryParamTwo(model.queryParamTwo); - stringHeaderMember(model.stringHeaderMember); - nestedQueryParameterOperation(model.nestedQueryParameterOperation); - requiredListQueryParams(model.requiredListQueryParams); - optionalListQueryParams(model.optionalListQueryParams); - } - - public final String getPathParam() { - return pathParam; - } - - public final void setPathParam(String pathParam) { - this.pathParam = pathParam; - } - - @Override - public final Builder pathParam(String pathParam) { - this.pathParam = pathParam; - return this; - } - - public final String getQueryParamOne() { - return queryParamOne; - } - - public final void setQueryParamOne(String queryParamOne) { - this.queryParamOne = queryParamOne; - } - - @Override - public final Builder queryParamOne(String queryParamOne) { - this.queryParamOne = queryParamOne; - return this; - } - - public final String getQueryParamTwo() { - return queryParamTwo; - } - - public final void setQueryParamTwo(String queryParamTwo) { - this.queryParamTwo = queryParamTwo; - } - - @Override - public final Builder queryParamTwo(String queryParamTwo) { - this.queryParamTwo = queryParamTwo; - return this; - } - - public final String getStringHeaderMember() { - return stringHeaderMember; - } - - public final void setStringHeaderMember(String stringHeaderMember) { - this.stringHeaderMember = stringHeaderMember; - } - - @Override - public final Builder stringHeaderMember(String stringHeaderMember) { - this.stringHeaderMember = stringHeaderMember; - return this; - } - - public final NestedQueryParameterOperation.Builder getNestedQueryParameterOperation() { - return nestedQueryParameterOperation != null ? nestedQueryParameterOperation.toBuilder() : null; - } - - public final void setNestedQueryParameterOperation(NestedQueryParameterOperation.BuilderImpl nestedQueryParameterOperation) { - this.nestedQueryParameterOperation = nestedQueryParameterOperation != null ? nestedQueryParameterOperation.build() - : null; - } - - @Override - public final Builder nestedQueryParameterOperation(NestedQueryParameterOperation nestedQueryParameterOperation) { - this.nestedQueryParameterOperation = nestedQueryParameterOperation; - return this; - } - - public final Collection getRequiredListQueryParams() { - if (requiredListQueryParams instanceof SdkAutoConstructList) { - return null; - } - return requiredListQueryParams; - } - - public final void setRequiredListQueryParams(Collection requiredListQueryParams) { - this.requiredListQueryParams = ListOfIntegersCopier.copy(requiredListQueryParams); - } - - @Override - public final Builder requiredListQueryParams(Collection requiredListQueryParams) { - this.requiredListQueryParams = ListOfIntegersCopier.copy(requiredListQueryParams); - return this; - } - - @Override - @SafeVarargs - public final Builder requiredListQueryParams(Integer... requiredListQueryParams) { - requiredListQueryParams(Arrays.asList(requiredListQueryParams)); - return this; - } - - public final Collection getOptionalListQueryParams() { - if (optionalListQueryParams instanceof SdkAutoConstructList) { - return null; - } - return optionalListQueryParams; - } - - public final void setOptionalListQueryParams(Collection optionalListQueryParams) { - this.optionalListQueryParams = ListOfIntegersCopier.copy(optionalListQueryParams); - } - - @Override - public final Builder optionalListQueryParams(Collection optionalListQueryParams) { - this.optionalListQueryParams = ListOfIntegersCopier.copy(optionalListQueryParams); - return this; - } - - @Override - @SafeVarargs - public final Builder optionalListQueryParams(Integer... optionalListQueryParams) { - optionalListQueryParams(Arrays.asList(optionalListQueryParams)); - return this; - } - - @Override - public Builder overrideConfiguration(AwsRequestOverrideConfiguration overrideConfiguration) { - super.overrideConfiguration(overrideConfiguration); - return this; - } - - @Override - public Builder overrideConfiguration(Consumer builderConsumer) { - super.overrideConfiguration(builderConsumer); - return this; - } - - @Override - public QueryParameterOperationRequest build() { - return new QueryParameterOperationRequest(this); - } - - @Override - public List> sdkFields() { - return SDK_FIELDS; - } - - @Override - public Map> sdkFieldNameToField() { - return SDK_NAME_TO_FIELD; - } + public Map> sdkFieldNameToField() { + return SDK_NAME_TO_FIELD; } + } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/queryparameteroperationresponse.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/queryparameteroperationresponse.java index 14376b1d1c97..e87e085e71de 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/queryparameteroperationresponse.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/queryparameteroperationresponse.java @@ -1,122 +1,331 @@ package software.amazon.awssdk.services.jsonprotocoltests.model; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Function; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.Mutable; import software.amazon.awssdk.annotations.NotThreadSafe; import software.amazon.awssdk.core.SdkField; import software.amazon.awssdk.core.SdkPojo; +import software.amazon.awssdk.core.protocol.MarshallLocation; +import software.amazon.awssdk.core.protocol.MarshallingType; +import software.amazon.awssdk.core.traits.LocationTrait; import software.amazon.awssdk.utils.ToString; import software.amazon.awssdk.utils.builder.CopyableBuilder; import software.amazon.awssdk.utils.builder.ToCopyableBuilder; +/** + */ @Generated("software.amazon.awssdk:codegen") -public final class QueryParameterOperationResponse extends JsonProtocolTestsResponse implements - ToCopyableBuilder { - private static final List> SDK_FIELDS = Collections.emptyList(); +public final class QueryParameterOperationResponse extends JsonProtocolTestsResponse implements ToCopyableBuilder { + private static final SdkField RESPONSE_HEADER_MEMBER_FIELD = SdkField.builder(MarshallingType.STRING) + .memberName("ResponseHeaderMember") + .getter(getter(QueryParameterOperationResponse::responseHeaderMember)) + .setter(setter(Builder::responseHeaderMember)) + .traits(LocationTrait.builder() + .location(MarshallLocation.HEADER) + .locationName("x-amz-response-header") + .build()).build(); - private static final Map> SDK_NAME_TO_FIELD = memberNameToFieldInitializer(); + private static final SdkField RESPONSE_STATUS_CODE_FIELD = SdkField.builder(MarshallingType.INTEGER) + .memberName("ResponseStatusCode") + .getter(getter(QueryParameterOperationResponse::responseStatusCode)) + .setter(setter(Builder::responseStatusCode)) + .traits(LocationTrait.builder() + .location(MarshallLocation.STATUS_CODE) + .locationName("ResponseStatusCode") + .build()).build(); - private QueryParameterOperationResponse(BuilderImpl builder) { - super(builder); + private static final SdkField URI_MEMBER_ON_OUTPUT_FIELD = SdkField.builder(MarshallingType.STRING) + .memberName("UriMemberOnOutput") + .getter(getter(QueryParameterOperationResponse::uriMemberOnOutput)) + .setter(setter(Builder::uriMemberOnOutput)) + .traits(LocationTrait.builder() + .location(MarshallLocation.PAYLOAD) + .locationName("UriMemberOnOutput") + .build()).build(); + + private static final SdkField QUERY_MEMBER_ON_OUTPUT_FIELD = SdkField.builder(MarshallingType.STRING) + .memberName("QueryMemberOnOutput") + .getter(getter(QueryParameterOperationResponse::queryMemberOnOutput)) + .setter(setter(Builder::queryMemberOnOutput)) + .traits(LocationTrait.builder() + .location(MarshallLocation.PAYLOAD) + .locationName("QueryMemberOnOutput") + .build()).build(); + + private static final List> SDK_FIELDS = Collections.unmodifiableList(Arrays.asList(RESPONSE_HEADER_MEMBER_FIELD,RESPONSE_STATUS_CODE_FIELD,URI_MEMBER_ON_OUTPUT_FIELD,QUERY_MEMBER_ON_OUTPUT_FIELD)); + + private static final Map> SDK_NAME_TO_FIELD = memberNameToFieldInitializer(); + + private final String responseHeaderMember; + + private final Integer responseStatusCode; + + private final String uriMemberOnOutput; + + private final String queryMemberOnOutput; + + private QueryParameterOperationResponse(BuilderImpl builder) { + super(builder); + this.responseHeaderMember = builder.responseHeaderMember; + this.responseStatusCode = builder.responseStatusCode; + this.uriMemberOnOutput = builder.uriMemberOnOutput; + this.queryMemberOnOutput = builder.queryMemberOnOutput; + } + + /** + * Returns the value of the ResponseHeaderMember property for this object. + * @return The value of the ResponseHeaderMember property for this object. + */ + public final String responseHeaderMember() { + return responseHeaderMember; + } + + /** + * Returns the value of the ResponseStatusCode property for this object. + * @return The value of the ResponseStatusCode property for this object. + */ + public final Integer responseStatusCode() { + return responseStatusCode; + } + + /** + * Returns the value of the UriMemberOnOutput property for this object. + * @return The value of the UriMemberOnOutput property for this object. + */ + public final String uriMemberOnOutput() { + return uriMemberOnOutput; + } + + /** + * Returns the value of the QueryMemberOnOutput property for this object. + * @return The value of the QueryMemberOnOutput property for this object. + */ + public final String queryMemberOnOutput() { + return queryMemberOnOutput; + } + + @Override + public Builder toBuilder() { + return new BuilderImpl(this); + } + + public static Builder builder() { + return new BuilderImpl(); + } + + public static Class serializableBuilderClass() { + return BuilderImpl.class; + } + + @Override + public final int hashCode() { + int hashCode = 1; + hashCode = 31 * hashCode + super.hashCode(); + hashCode = 31 * hashCode + Objects.hashCode(responseHeaderMember()); + hashCode = 31 * hashCode + Objects.hashCode(responseStatusCode()); + hashCode = 31 * hashCode + Objects.hashCode(uriMemberOnOutput()); + hashCode = 31 * hashCode + Objects.hashCode(queryMemberOnOutput()); + return hashCode; + } + + @Override + public final boolean equals(Object obj) { + return super.equals(obj) && equalsBySdkFields(obj); + } + + @Override + public final boolean equalsBySdkFields(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; } + if (!(obj instanceof QueryParameterOperationResponse)) { + return false; + } + QueryParameterOperationResponse other = (QueryParameterOperationResponse) obj; + return Objects.equals(responseHeaderMember(), other.responseHeaderMember())&&Objects.equals(responseStatusCode(), other.responseStatusCode())&&Objects.equals(uriMemberOnOutput(), other.uriMemberOnOutput())&&Objects.equals(queryMemberOnOutput(), other.queryMemberOnOutput()); + } - @Override - public Builder toBuilder() { - return new BuilderImpl(this); + /** + * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be redacted from this string using a placeholder value. + */ + @Override + public final String toString() { + return ToString.builder("QueryParameterOperationResponse").add("ResponseHeaderMember", responseHeaderMember()).add("ResponseStatusCode", responseStatusCode()).add("UriMemberOnOutput", uriMemberOnOutput()).add("QueryMemberOnOutput", queryMemberOnOutput()).build(); + } + + public final Optional getValueForField(String fieldName, Class clazz) { + switch (fieldName) { + case "ResponseHeaderMember":return Optional.ofNullable(clazz.cast(responseHeaderMember())); + case "ResponseStatusCode":return Optional.ofNullable(clazz.cast(responseStatusCode())); + case "UriMemberOnOutput":return Optional.ofNullable(clazz.cast(uriMemberOnOutput())); + case "QueryMemberOnOutput":return Optional.ofNullable(clazz.cast(queryMemberOnOutput())); + default:return Optional.empty(); + } + } + + @Override + public final List> sdkFields() { + return SDK_FIELDS; + } + + @Override + public final Map> sdkFieldNameToField() { + return SDK_NAME_TO_FIELD; + } + + private static Map> memberNameToFieldInitializer() { + Map> map = new HashMap<>(); + map.put("x-amz-response-header", RESPONSE_HEADER_MEMBER_FIELD); + map.put("ResponseStatusCode", RESPONSE_STATUS_CODE_FIELD); + map.put("UriMemberOnOutput", URI_MEMBER_ON_OUTPUT_FIELD); + map.put("QueryMemberOnOutput", QUERY_MEMBER_ON_OUTPUT_FIELD); + return Collections.unmodifiableMap(map); + } + + private static Function getter(Function g) { + return obj -> g.apply((QueryParameterOperationResponse) obj); + } + + private static BiConsumer setter(BiConsumer s) { + return (obj, val) -> s.accept((Builder) obj, val); + } + + @Mutable + @NotThreadSafe + public interface Builder extends JsonProtocolTestsResponse.Builder, SdkPojo, CopyableBuilder { + /** + * Sets the value of the ResponseHeaderMember property for this object. + * + * @param responseHeaderMember The new value for the ResponseHeaderMember property for this object. + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder responseHeaderMember(String responseHeaderMember); + + /** + * Sets the value of the ResponseStatusCode property for this object. + * + * @param responseStatusCode The new value for the ResponseStatusCode property for this object. + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder responseStatusCode(Integer responseStatusCode); + + /** + * Sets the value of the UriMemberOnOutput property for this object. + * + * @param uriMemberOnOutput The new value for the UriMemberOnOutput property for this object. + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder uriMemberOnOutput(String uriMemberOnOutput); + + /** + * Sets the value of the QueryMemberOnOutput property for this object. + * + * @param queryMemberOnOutput The new value for the QueryMemberOnOutput property for this object. + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder queryMemberOnOutput(String queryMemberOnOutput); + } + + static final class BuilderImpl extends JsonProtocolTestsResponse.BuilderImpl implements Builder { + private String responseHeaderMember; + + private Integer responseStatusCode; + + private String uriMemberOnOutput; + + private String queryMemberOnOutput; + + private BuilderImpl() { } - public static Builder builder() { - return new BuilderImpl(); + private BuilderImpl(QueryParameterOperationResponse model) { + super(model);responseHeaderMember(model.responseHeaderMember); + responseStatusCode(model.responseStatusCode); + uriMemberOnOutput(model.uriMemberOnOutput); + queryMemberOnOutput(model.queryMemberOnOutput); } - public static Class serializableBuilderClass() { - return BuilderImpl.class; + public final String getResponseHeaderMember() { + return responseHeaderMember; } - @Override - public final int hashCode() { - int hashCode = 1; - hashCode = 31 * hashCode + super.hashCode(); - return hashCode; + public final void setResponseHeaderMember(String responseHeaderMember) { + this.responseHeaderMember = responseHeaderMember; } @Override - public final boolean equals(Object obj) { - return super.equals(obj) && equalsBySdkFields(obj); + public final Builder responseHeaderMember(String responseHeaderMember) { + this.responseHeaderMember = responseHeaderMember; + return this; } - @Override - public final boolean equalsBySdkFields(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof QueryParameterOperationResponse)) { - return false; - } - return true; + public final Integer getResponseStatusCode() { + return responseStatusCode; + } + + public final void setResponseStatusCode(Integer responseStatusCode) { + this.responseStatusCode = responseStatusCode; } - /** - * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be - * redacted from this string using a placeholder value. - */ @Override - public final String toString() { - return ToString.builder("QueryParameterOperationResponse").build(); + public final Builder responseStatusCode(Integer responseStatusCode) { + this.responseStatusCode = responseStatusCode; + return this; } - public final Optional getValueForField(String fieldName, Class clazz) { - return Optional.empty(); + public final String getUriMemberOnOutput() { + return uriMemberOnOutput; } - @Override - public final List> sdkFields() { - return SDK_FIELDS; + public final void setUriMemberOnOutput(String uriMemberOnOutput) { + this.uriMemberOnOutput = uriMemberOnOutput; } @Override - public final Map> sdkFieldNameToField() { - return SDK_NAME_TO_FIELD; + public final Builder uriMemberOnOutput(String uriMemberOnOutput) { + this.uriMemberOnOutput = uriMemberOnOutput; + return this; } - private static Map> memberNameToFieldInitializer() { - return Collections.emptyMap(); + public final String getQueryMemberOnOutput() { + return queryMemberOnOutput; } - @Mutable - @NotThreadSafe - public interface Builder extends JsonProtocolTestsResponse.Builder, SdkPojo, - CopyableBuilder { + public final void setQueryMemberOnOutput(String queryMemberOnOutput) { + this.queryMemberOnOutput = queryMemberOnOutput; } - static final class BuilderImpl extends JsonProtocolTestsResponse.BuilderImpl implements Builder { - private BuilderImpl() { - } - - private BuilderImpl(QueryParameterOperationResponse model) { - super(model); - } + @Override + public final Builder queryMemberOnOutput(String queryMemberOnOutput) { + this.queryMemberOnOutput = queryMemberOnOutput; + return this; + } - @Override - public QueryParameterOperationResponse build() { - return new QueryParameterOperationResponse(this); - } + @Override + public QueryParameterOperationResponse build() { + return new QueryParameterOperationResponse(this); + } - @Override - public List> sdkFields() { - return SDK_FIELDS; - } + @Override + public List> sdkFields() { + return SDK_FIELDS; + } - @Override - public Map> sdkFieldNameToField() { - return SDK_NAME_TO_FIELD; - } + @Override + public Map> sdkFieldNameToField() { + return SDK_NAME_TO_FIELD; } + } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/service-2.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/service-2.json index 5b2f1c8ebcaf..88a71b8f470f 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/service-2.json +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/service-2.json @@ -127,7 +127,8 @@ "method":"DELETE", "requestUri":"/2016-03-11/queryParameterOperation/{PathParam}" }, - "input":{"shape":"QueryParameterOperationRequest"} + "input":{"shape":"QueryParameterOperationRequest"}, + "output":{"shape":"QueryParameterOperationResponse"} }, "OperationWithReservedKeywordMember": { "name": "DeprecatedRename", @@ -640,6 +641,15 @@ "shape":"String", "location":"querystring", "locationName":"QueryParamTwo" + }, + "NestedHeaderMember":{ + "shape":"String", + "location":"header", + "locationName":"x-amz-nested-header" + }, + "NestedStatusCode":{ + "shape":"Integer", + "location":"statusCode" } } }, @@ -682,10 +692,38 @@ "OptionalListQueryParams":{ "shape":"ListOfIntegers", "location":"querystring" + }, + "StatusCodeOnInput":{ + "shape":"Integer", + "location":"statusCode" } }, "payload":"NestedQueryParameterOperation" }, + "QueryParameterOperationResponse":{ + "type":"structure", + "members":{ + "ResponseHeaderMember":{ + "shape":"String", + "location":"header", + "locationName":"x-amz-response-header" + }, + "ResponseStatusCode":{ + "shape":"Integer", + "location":"statusCode" + }, + "UriMemberOnOutput":{ + "shape":"String", + "location":"uri", + "locationName":"UriMemberOnOutput" + }, + "QueryMemberOnOutput":{ + "shape":"String", + "location":"querystring", + "locationName":"QueryMemberOnOutput" + } + } + }, "ContainsReservedKeyword": { "type": "structure", "members": { From 2d52a011f23111d86aa797a0f43dc081700a329e Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Thu, 26 Mar 2026 11:52:06 -0700 Subject: [PATCH 12/16] Corrected logic and added test for locationName --- .../amazon/awssdk/codegen/AddShapes.java | 14 ++++++++--- .../amazon/awssdk/codegen/AddShapesTest.java | 6 +++++ .../codegen/expected-nested-options.java | 13 +++++----- .../model/nestedqueryparameteroperation.java | 4 +-- .../codegen-resources/restjson/service-2.json | 25 ++++++++++++++++++- .../NestedLocationSerializationTest.java | 19 +++++++++++++- 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java index 9944a6a52931..98948ba17df0 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java @@ -311,17 +311,23 @@ private ParameterHttpMapping generateParameterHttpMapping(Shape parentShape, ParameterHttpMapping mapping = new ParameterHttpMapping(); - // Per the Smithy spec, HTTP binding traits are only honored on specific shape types: + // Per the Smithy spec, HTTP binding traits are only honored on specific shape types. + // When a trait is ignored, its locationName is also ignored so the member name is used as the wire name. // https://smithy.io/2.0/spec/http-bindings.html Location location = resolveLocation(parentShape, member, allC2jShapes); + boolean locationIgnored = member.getLocation() != null && location == null; Shape memberShape = allC2jShapes.get(member.getShape()); + String marshallLocationName = locationIgnored + ? memberName : deriveMarshallerLocationName(memberShape, memberName, member, protocol); + String unmarshallLocationName = locationIgnored + ? memberName : deriveUnmarshallerLocationName(memberShape, memberName, member); + mapping.withLocation(location) .withPayload(member.isPayload()).withStreaming(member.isStreaming()) .withFlattened(isFlattened(member, memberShape)) - .withUnmarshallLocationName(deriveUnmarshallerLocationName(memberShape, memberName, member)) - .withMarshallLocationName( - deriveMarshallerLocationName(memberShape, memberName, member, protocol)) + .withUnmarshallLocationName(unmarshallLocationName) + .withMarshallLocationName(marshallLocationName) .withIsGreedy(isGreedy(parentShape, allC2jShapes, mapping)); return mapping; diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java index 45185281666c..72a38d948c46 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java @@ -103,4 +103,10 @@ void generateShapeModel_locationOnDirectInputShape_isPreserved() { assertThat(inputShape.findMemberModelByC2jName("StringHeaderMember").getHttp().getLocation()).isEqualTo(Location.HEADER); } + @Test + void generateShapeModel_locationNameOnNestedShape_usesMemberNameForMarshalling() { + ShapeModel inputShape = intermediateModel.getShapes().get("NestedQueryParameterOperation"); + assertThat(inputShape.findMemberModelByC2jName("NestedHeaderMember").getHttp().getMarshallLocationName()).isEqualTo("NestedHeaderMember"); + } + } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java index 4940bbc56a14..b08ba3f6b643 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/expected-nested-options.java @@ -48,19 +48,18 @@ public final class NestedOptions implements SdkPojo, Serializable, ToCopyableBui private static final SdkField HEADER_PARAM_FIELD = SdkField. builder(MarshallingType.STRING) .memberName("headerParam").getter(getter(NestedOptions::headerParam)).setter(setter(Builder::headerParam)) - .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("x-amz-nested-header").build()) - .build(); + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("headerParam").build()).build(); private static final SdkField QUERY_PARAM_FIELD = SdkField. builder(MarshallingType.STRING) .memberName("queryParam").getter(getter(NestedOptions::queryParam)).setter(setter(Builder::queryParam)) - .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("nestedQuery").build()).build(); + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("queryParam").build()).build(); private static final SdkField> PREFIX_HEADERS_FIELD = SdkField .> builder(MarshallingType.MAP) .memberName("prefixHeaders") .getter(getter(NestedOptions::prefixHeaders)) .setter(setter(Builder::prefixHeaders)) - .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("x-amz-prefix-").build(), + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("prefixHeaders").build(), MapTrait.builder() .keyLocationName("key") .valueLocationName("value") @@ -229,9 +228,9 @@ public final Map> sdkFieldNameToField() { private static Map> memberNameToFieldInitializer() { Map> map = new HashMap<>(); map.put("pageSize", PAGE_SIZE_FIELD); - map.put("x-amz-nested-header", HEADER_PARAM_FIELD); - map.put("nestedQuery", QUERY_PARAM_FIELD); - map.put("x-amz-prefix-", PREFIX_HEADERS_FIELD); + map.put("headerParam", HEADER_PARAM_FIELD); + map.put("queryParam", QUERY_PARAM_FIELD); + map.put("prefixHeaders", PREFIX_HEADERS_FIELD); return Collections.unmodifiableMap(map); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/nestedqueryparameteroperation.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/nestedqueryparameteroperation.java index 611656500dd2..7b04d3d9f97d 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/nestedqueryparameteroperation.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/nestedqueryparameteroperation.java @@ -51,7 +51,7 @@ public final class NestedQueryParameterOperation implements SdkPojo, Serializabl .setter(setter(Builder::nestedHeaderMember)) .traits(LocationTrait.builder() .location(MarshallLocation.PAYLOAD) - .locationName("x-amz-nested-header") + .locationName("NestedHeaderMember") .build()).build(); private static final SdkField NESTED_STATUS_CODE_FIELD = SdkField.builder(MarshallingType.INTEGER) @@ -191,7 +191,7 @@ private static Map> memberNameToFieldInitializer() { Map> map = new HashMap<>(); map.put("QueryParamOne", QUERY_PARAM_ONE_FIELD); map.put("QueryParamTwo", QUERY_PARAM_TWO_FIELD); - map.put("x-amz-nested-header", NESTED_HEADER_MEMBER_FIELD); + map.put("NestedHeaderMember", NESTED_HEADER_MEMBER_FIELD); map.put("NestedStatusCode", NESTED_STATUS_CODE_FIELD); return Collections.unmodifiableMap(map); } diff --git a/test/protocol-tests/src/main/resources/codegen-resources/restjson/service-2.json b/test/protocol-tests/src/main/resources/codegen-resources/restjson/service-2.json index 70e58cf31d0d..24d50a060735 100644 --- a/test/protocol-tests/src/main/resources/codegen-resources/restjson/service-2.json +++ b/test/protocol-tests/src/main/resources/codegen-resources/restjson/service-2.json @@ -262,7 +262,8 @@ "method":"POST", "requestUri":"/2016-03-11/nestedLocationOperation" }, - "input":{"shape":"NestedLocationOperationInput"} + "input":{"shape":"NestedLocationOperationInput"}, + "output":{"shape":"NestedLocationOperationOutput"} } }, "shapes":{ @@ -812,6 +813,28 @@ "StringMember":{"shape":"String"} } }, + "NestedLocationOperationOutput":{ + "type":"structure", + "members":{ + "TopLevelHeader":{ + "shape":"String", + "location":"header", + "locationName":"x-amz-top-level" + }, + "NestedResult":{"shape":"NestedResponseData"} + } + }, + "NestedResponseData":{ + "type":"structure", + "members":{ + "NestedHeader":{ + "shape":"String", + "location":"header", + "locationName":"x-amz-should-be-ignored" + }, + "Value":{"shape":"String"} + } + }, "StatusCodeInOutputStructure":{ "type":"structure", "members":{ diff --git a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/NestedLocationSerializationTest.java b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/NestedLocationSerializationTest.java index da25133f45b2..9941c0226d28 100644 --- a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/NestedLocationSerializationTest.java +++ b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/NestedLocationSerializationTest.java @@ -23,6 +23,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static org.assertj.core.api.Assertions.assertThat; import com.github.tomakehurst.wiremock.junit.WireMockRule; import java.net.URI; @@ -34,6 +35,7 @@ import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; import software.amazon.awssdk.services.protocolrestjson.model.NestedLocationOperationRequest; +import software.amazon.awssdk.services.protocolrestjson.model.NestedLocationOperationResponse; import software.amazon.awssdk.services.protocolrestjson.model.NestedShapeWithLocations; /** @@ -71,6 +73,21 @@ public void nestedMemberWithLocation_serializedToBodyNotQueryParam() { verify(postRequestedFor(anyUrl()).withQueryParam("topLevel", equalTo("topValue"))); verify(postRequestedFor(anyUrl()).withRequestBody( - equalToJson("{\"Nested\":{\"shouldBeIgnored\":\"nestedValue\",\"StringMember\":\"hello\"}}"))); + equalToJson("{\"Nested\":{\"NestedQueryParam\":\"nestedValue\",\"StringMember\":\"hello\"}}"))); + } + + @Test + public void nestedMemberWithLocation_deserializedFromBodyNotHeader() { + stubFor(post(anyUrl()).willReturn(aResponse() + .withStatus(200) + .withHeader("x-amz-top-level", "headerValue") + .withBody("{\"NestedResult\":{\"NestedHeader\":\"from-body\",\"Value\":\"hello\"}}"))); + + NestedLocationOperationResponse response = client.nestedLocationOperation( + NestedLocationOperationRequest.builder().build()); + + assertThat(response.topLevelHeader()).isEqualTo("headerValue"); + assertThat(response.nestedResult().nestedHeader()).isEqualTo("from-body"); + assertThat(response.nestedResult().value()).isEqualTo("hello"); } } From 1302754ee5a768795bd2587963db1474c6ba0364 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Thu, 26 Mar 2026 15:00:49 -0700 Subject: [PATCH 13/16] Fix comments --- .../amazon/awssdk/codegen/AddShapes.java | 16 ++++++++-------- .../amazon/awssdk/codegen/AddShapesTest.java | 8 ++++++++ .../awssdk/codegen/poet/model/service-2.json | 4 ++++ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java index 98948ba17df0..e6daed69595e 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java @@ -311,11 +311,11 @@ private ParameterHttpMapping generateParameterHttpMapping(Shape parentShape, ParameterHttpMapping mapping = new ParameterHttpMapping(); - // Per the Smithy spec, HTTP binding traits are only honored on specific shape types. - // When a trait is ignored, its locationName is also ignored so the member name is used as the wire name. - // https://smithy.io/2.0/spec/http-bindings.html - Location location = resolveLocation(parentShape, member, allC2jShapes); - boolean locationIgnored = member.getLocation() != null && location == null; + // Per the Smithy spec, HTTP binding traits are only honored on top-level shapes (direct operation + // input/output/error). When a location trait is ignored, its locationName is also ignored so the member + // name is used as the wire name. https://smithy.io/2.0/spec/http-bindings.html + Location resolvedLocation = resolveLocation(parentShape, member, allC2jShapes); + boolean locationIgnored = member.getLocation() != null && resolvedLocation == null; Shape memberShape = allC2jShapes.get(member.getShape()); String marshallLocationName = locationIgnored @@ -323,7 +323,7 @@ private ParameterHttpMapping generateParameterHttpMapping(Shape parentShape, String unmarshallLocationName = locationIgnored ? memberName : deriveUnmarshallerLocationName(memberShape, memberName, member); - mapping.withLocation(location) + mapping.withLocation(resolvedLocation) .withPayload(member.isPayload()).withStreaming(member.isStreaming()) .withFlattened(isFlattened(member, memberShape)) .withUnmarshallLocationName(unmarshallLocationName) @@ -344,7 +344,7 @@ private Location resolveLocation(Shape parentShape, Member member, Map allC2jShapes .anyMatch(o -> allC2jShapes.get(o.getOutput().getShape()).equals(shape)); } - private boolean isDirectOperationShape(Shape shape, Map allC2jShapes) { + private boolean isTopLevelShape(Shape shape, Map allC2jShapes) { return builder.getService().getOperations().values().stream() .anyMatch(o -> (o.getInput() != null && allC2jShapes.get(o.getInput().getShape()).equals(shape)) || (o.getOutput() != null && allC2jShapes.get(o.getOutput().getShape()).equals(shape)) diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java index 72a38d948c46..992ae5d602e8 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/AddShapesTest.java @@ -109,4 +109,12 @@ void generateShapeModel_locationNameOnNestedShape_usesMemberNameForMarshalling() assertThat(inputShape.findMemberModelByC2jName("NestedHeaderMember").getHttp().getMarshallLocationName()).isEqualTo("NestedHeaderMember"); } + @Test + void generateShapeModel_locationNameOnTopLevelShape_honorsLocationName() { + ShapeModel inputShape = intermediateModel.getShapes().get("QueryParameterOperationRequest"); + MemberModel member = inputShape.findMemberModelByC2jName("PayloadMemberWithCustomName"); + assertThat(member.getHttp().getLocation()).isNull(); + assertThat(member.getHttp().getMarshallLocationName()).isEqualTo("CustomWireName"); + } + } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/service-2.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/service-2.json index 88a71b8f470f..0699c8297a79 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/service-2.json +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/service-2.json @@ -696,6 +696,10 @@ "StatusCodeOnInput":{ "shape":"Integer", "location":"statusCode" + }, + "PayloadMemberWithCustomName":{ + "shape":"String", + "locationName":"CustomWireName" } }, "payload":"NestedQueryParameterOperation" From 16c162bc368328161c1260592ed4c423783e0bad Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Mon, 30 Mar 2026 07:42:06 -0700 Subject: [PATCH 14/16] Update fixture file --- .../model/queryparameteroperationrequest.java | 379 +++++++++++------- 1 file changed, 243 insertions(+), 136 deletions(-) diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/queryparameteroperationrequest.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/queryparameteroperationrequest.java index 74c7c9899ac8..681f3d3f17e5 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/queryparameteroperationrequest.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/model/queryparameteroperationrequest.java @@ -32,95 +32,92 @@ /** */ @Generated("software.amazon.awssdk:codegen") -public final class QueryParameterOperationRequest extends JsonProtocolTestsRequest implements ToCopyableBuilder { - private static final SdkField PATH_PARAM_FIELD = SdkField.builder(MarshallingType.STRING) - .memberName("PathParam") - .getter(getter(QueryParameterOperationRequest::pathParam)) - .setter(setter(Builder::pathParam)) - .traits(LocationTrait.builder() - .location(MarshallLocation.PATH) - .locationName("PathParam") - .build(), RequiredTrait.create()).build(); - - private static final SdkField QUERY_PARAM_ONE_FIELD = SdkField.builder(MarshallingType.STRING) - .memberName("QueryParamOne") - .getter(getter(QueryParameterOperationRequest::queryParamOne)) - .setter(setter(Builder::queryParamOne)) - .traits(LocationTrait.builder() - .location(MarshallLocation.QUERY_PARAM) - .locationName("QueryParamOne") - .build(), RequiredTrait.create()).build(); - - private static final SdkField QUERY_PARAM_TWO_FIELD = SdkField.builder(MarshallingType.STRING) - .memberName("QueryParamTwo") - .getter(getter(QueryParameterOperationRequest::queryParamTwo)) - .setter(setter(Builder::queryParamTwo)) - .traits(LocationTrait.builder() - .location(MarshallLocation.QUERY_PARAM) - .locationName("QueryParamTwo") - .build()).build(); - - private static final SdkField STRING_HEADER_MEMBER_FIELD = SdkField.builder(MarshallingType.STRING) - .memberName("StringHeaderMember") - .getter(getter(QueryParameterOperationRequest::stringHeaderMember)) - .setter(setter(Builder::stringHeaderMember)) - .traits(LocationTrait.builder() - .location(MarshallLocation.HEADER) - .locationName("x-amz-header-string") - .build(), RequiredTrait.create()).build(); - - private static final SdkField NESTED_QUERY_PARAMETER_OPERATION_FIELD = SdkField.builder(MarshallingType.SDK_POJO) - .memberName("NestedQueryParameterOperation") - .getter(getter(QueryParameterOperationRequest::nestedQueryParameterOperation)) - .setter(setter(Builder::nestedQueryParameterOperation)) - .constructor(NestedQueryParameterOperation::builder) - .traits(LocationTrait.builder() - .location(MarshallLocation.PAYLOAD) - .locationName("NestedQueryParameterOperation") - .build(), PayloadTrait.create()).build(); - - private static final SdkField> REQUIRED_LIST_QUERY_PARAMS_FIELD = SdkField.>builder(MarshallingType.LIST) - .memberName("RequiredListQueryParams") - .getter(getter(QueryParameterOperationRequest::requiredListQueryParams)) - .setter(setter(Builder::requiredListQueryParams)) - .traits(LocationTrait.builder() - .location(MarshallLocation.QUERY_PARAM) - .locationName("RequiredListQueryParams") - .build(), ListTrait.builder() - .memberLocationName(null) - .memberFieldInfo(SdkField.builder(MarshallingType.INTEGER) - .traits(LocationTrait.builder() - .location(MarshallLocation.PAYLOAD) - .locationName("member") - .build()).build()) - .build(), RequiredTrait.create()).build(); - - private static final SdkField> OPTIONAL_LIST_QUERY_PARAMS_FIELD = SdkField.>builder(MarshallingType.LIST) - .memberName("OptionalListQueryParams") - .getter(getter(QueryParameterOperationRequest::optionalListQueryParams)) - .setter(setter(Builder::optionalListQueryParams)) - .traits(LocationTrait.builder() - .location(MarshallLocation.QUERY_PARAM) - .locationName("OptionalListQueryParams") - .build(), ListTrait.builder() - .memberLocationName(null) - .memberFieldInfo(SdkField.builder(MarshallingType.INTEGER) - .traits(LocationTrait.builder() - .location(MarshallLocation.PAYLOAD) - .locationName("member") - .build()).build()) - .build()).build(); - - private static final SdkField STATUS_CODE_ON_INPUT_FIELD = SdkField.builder(MarshallingType.INTEGER) - .memberName("StatusCodeOnInput") - .getter(getter(QueryParameterOperationRequest::statusCodeOnInput)) - .setter(setter(Builder::statusCodeOnInput)) - .traits(LocationTrait.builder() - .location(MarshallLocation.PAYLOAD) - .locationName("StatusCodeOnInput") - .build()).build(); - - private static final List> SDK_FIELDS = Collections.unmodifiableList(Arrays.asList(PATH_PARAM_FIELD,QUERY_PARAM_ONE_FIELD,QUERY_PARAM_TWO_FIELD,STRING_HEADER_MEMBER_FIELD,NESTED_QUERY_PARAMETER_OPERATION_FIELD,REQUIRED_LIST_QUERY_PARAMS_FIELD,OPTIONAL_LIST_QUERY_PARAMS_FIELD,STATUS_CODE_ON_INPUT_FIELD)); +public final class QueryParameterOperationRequest extends JsonProtocolTestsRequest implements + ToCopyableBuilder { + private static final SdkField PATH_PARAM_FIELD = SdkField + . builder(MarshallingType.STRING) + .memberName("PathParam") + .getter(getter(QueryParameterOperationRequest::pathParam)) + .setter(setter(Builder::pathParam)) + .traits(LocationTrait.builder().location(MarshallLocation.PATH).locationName("PathParam").build(), + RequiredTrait.create()).build(); + + private static final SdkField QUERY_PARAM_ONE_FIELD = SdkField + . builder(MarshallingType.STRING) + .memberName("QueryParamOne") + .getter(getter(QueryParameterOperationRequest::queryParamOne)) + .setter(setter(Builder::queryParamOne)) + .traits(LocationTrait.builder().location(MarshallLocation.QUERY_PARAM).locationName("QueryParamOne").build(), + RequiredTrait.create()).build(); + + private static final SdkField QUERY_PARAM_TWO_FIELD = SdkField. builder(MarshallingType.STRING) + .memberName("QueryParamTwo").getter(getter(QueryParameterOperationRequest::queryParamTwo)) + .setter(setter(Builder::queryParamTwo)) + .traits(LocationTrait.builder().location(MarshallLocation.QUERY_PARAM).locationName("QueryParamTwo").build()).build(); + + private static final SdkField STRING_HEADER_MEMBER_FIELD = SdkField + . builder(MarshallingType.STRING) + .memberName("StringHeaderMember") + .getter(getter(QueryParameterOperationRequest::stringHeaderMember)) + .setter(setter(Builder::stringHeaderMember)) + .traits(LocationTrait.builder().location(MarshallLocation.HEADER).locationName("x-amz-header-string").build(), + RequiredTrait.create()).build(); + + private static final SdkField NESTED_QUERY_PARAMETER_OPERATION_FIELD = SdkField + . builder(MarshallingType.SDK_POJO) + .memberName("NestedQueryParameterOperation") + .getter(getter(QueryParameterOperationRequest::nestedQueryParameterOperation)) + .setter(setter(Builder::nestedQueryParameterOperation)) + .constructor(NestedQueryParameterOperation::builder) + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("NestedQueryParameterOperation") + .build(), PayloadTrait.create()).build(); + + private static final SdkField> REQUIRED_LIST_QUERY_PARAMS_FIELD = SdkField + .> builder(MarshallingType.LIST) + .memberName("RequiredListQueryParams") + .getter(getter(QueryParameterOperationRequest::requiredListQueryParams)) + .setter(setter(Builder::requiredListQueryParams)) + .traits(LocationTrait.builder().location(MarshallLocation.QUERY_PARAM).locationName("RequiredListQueryParams") + .build(), + ListTrait + .builder() + .memberLocationName(null) + .memberFieldInfo( + SdkField. builder(MarshallingType.INTEGER) + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD) + .locationName("member").build()).build()).build(), RequiredTrait.create()) + .build(); + + private static final SdkField> OPTIONAL_LIST_QUERY_PARAMS_FIELD = SdkField + .> builder(MarshallingType.LIST) + .memberName("OptionalListQueryParams") + .getter(getter(QueryParameterOperationRequest::optionalListQueryParams)) + .setter(setter(Builder::optionalListQueryParams)) + .traits(LocationTrait.builder().location(MarshallLocation.QUERY_PARAM).locationName("OptionalListQueryParams") + .build(), + ListTrait + .builder() + .memberLocationName(null) + .memberFieldInfo( + SdkField. builder(MarshallingType.INTEGER) + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD) + .locationName("member").build()).build()).build()).build(); + + private static final SdkField STATUS_CODE_ON_INPUT_FIELD = SdkField. builder(MarshallingType.INTEGER) + .memberName("StatusCodeOnInput").getter(getter(QueryParameterOperationRequest::statusCodeOnInput)) + .setter(setter(Builder::statusCodeOnInput)) + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("StatusCodeOnInput").build()).build(); + + private static final SdkField PAYLOAD_MEMBER_WITH_CUSTOM_NAME_FIELD = SdkField + . builder(MarshallingType.STRING).memberName("PayloadMemberWithCustomName") + .getter(getter(QueryParameterOperationRequest::payloadMemberWithCustomName)) + .setter(setter(Builder::payloadMemberWithCustomName)) + .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("CustomWireName").build()).build(); + + private static final List> SDK_FIELDS = Collections.unmodifiableList(Arrays.asList(PATH_PARAM_FIELD, + QUERY_PARAM_ONE_FIELD, QUERY_PARAM_TWO_FIELD, STRING_HEADER_MEMBER_FIELD, NESTED_QUERY_PARAMETER_OPERATION_FIELD, + REQUIRED_LIST_QUERY_PARAMS_FIELD, OPTIONAL_LIST_QUERY_PARAMS_FIELD, STATUS_CODE_ON_INPUT_FIELD, + PAYLOAD_MEMBER_WITH_CUSTOM_NAME_FIELD)); private static final Map> SDK_NAME_TO_FIELD = memberNameToFieldInitializer(); @@ -140,6 +137,8 @@ public final class QueryParameterOperationRequest extends JsonProtocolTestsReque private final Integer statusCodeOnInput; + private final String payloadMemberWithCustomName; + private QueryParameterOperationRequest(BuilderImpl builder) { super(builder); this.pathParam = builder.pathParam; @@ -150,10 +149,12 @@ private QueryParameterOperationRequest(BuilderImpl builder) { this.requiredListQueryParams = builder.requiredListQueryParams; this.optionalListQueryParams = builder.optionalListQueryParams; this.statusCodeOnInput = builder.statusCodeOnInput; + this.payloadMemberWithCustomName = builder.payloadMemberWithCustomName; } /** * Returns the value of the PathParam property for this object. + * * @return The value of the PathParam property for this object. */ public final String pathParam() { @@ -162,6 +163,7 @@ public final String pathParam() { /** * Returns the value of the QueryParamOne property for this object. + * * @return The value of the QueryParamOne property for this object. */ public final String queryParamOne() { @@ -170,6 +172,7 @@ public final String queryParamOne() { /** * Returns the value of the QueryParamTwo property for this object. + * * @return The value of the QueryParamTwo property for this object. */ public final String queryParamTwo() { @@ -178,6 +181,7 @@ public final String queryParamTwo() { /** * Returns the value of the StringHeaderMember property for this object. + * * @return The value of the StringHeaderMember property for this object. */ public final String stringHeaderMember() { @@ -186,6 +190,7 @@ public final String stringHeaderMember() { /** * Returns the value of the NestedQueryParameterOperation property for this object. + * * @return The value of the NestedQueryParameterOperation property for this object. */ public final NestedQueryParameterOperation nestedQueryParameterOperation() { @@ -193,7 +198,12 @@ public final NestedQueryParameterOperation nestedQueryParameterOperation() { } /** - * For responses, this returns true if the service returned a value for the RequiredListQueryParams property. This DOES NOT check that the value is non-empty (for which, you should check the {@code isEmpty()} method on the property). This is useful because the SDK will never return a null collection or map, but you may need to differentiate between the service returning nothing (or null) and the service returning an empty collection or map. For requests, this returns true if a value for the property was specified in the request builder, and false if a value was not specified. + * For responses, this returns true if the service returned a value for the RequiredListQueryParams property. This + * DOES NOT check that the value is non-empty (for which, you should check the {@code isEmpty()} method on the + * property). This is useful because the SDK will never return a null collection or map, but you may need to + * differentiate between the service returning nothing (or null) and the service returning an empty collection or + * map. For requests, this returns true if a value for the property was specified in the request builder, and false + * if a value was not specified. */ public final boolean hasRequiredListQueryParams() { return requiredListQueryParams != null && !(requiredListQueryParams instanceof SdkAutoConstructList); @@ -205,8 +215,10 @@ public final boolean hasRequiredListQueryParams() { * Attempts to modify the collection returned by this method will result in an UnsupportedOperationException. *

*

- * This method will never return null. If you would like to know whether the service returned this field (so that you can differentiate between null and empty), you can use the {@link #hasRequiredListQueryParams} method. + * This method will never return null. If you would like to know whether the service returned this field (so that + * you can differentiate between null and empty), you can use the {@link #hasRequiredListQueryParams} method. *

+ * * @return The value of the RequiredListQueryParams property for this object. */ public final List requiredListQueryParams() { @@ -214,7 +226,12 @@ public final List requiredListQueryParams() { } /** - * For responses, this returns true if the service returned a value for the OptionalListQueryParams property. This DOES NOT check that the value is non-empty (for which, you should check the {@code isEmpty()} method on the property). This is useful because the SDK will never return a null collection or map, but you may need to differentiate between the service returning nothing (or null) and the service returning an empty collection or map. For requests, this returns true if a value for the property was specified in the request builder, and false if a value was not specified. + * For responses, this returns true if the service returned a value for the OptionalListQueryParams property. This + * DOES NOT check that the value is non-empty (for which, you should check the {@code isEmpty()} method on the + * property). This is useful because the SDK will never return a null collection or map, but you may need to + * differentiate between the service returning nothing (or null) and the service returning an empty collection or + * map. For requests, this returns true if a value for the property was specified in the request builder, and false + * if a value was not specified. */ public final boolean hasOptionalListQueryParams() { return optionalListQueryParams != null && !(optionalListQueryParams instanceof SdkAutoConstructList); @@ -226,8 +243,10 @@ public final boolean hasOptionalListQueryParams() { * Attempts to modify the collection returned by this method will result in an UnsupportedOperationException. *

*

- * This method will never return null. If you would like to know whether the service returned this field (so that you can differentiate between null and empty), you can use the {@link #hasOptionalListQueryParams} method. + * This method will never return null. If you would like to know whether the service returned this field (so that + * you can differentiate between null and empty), you can use the {@link #hasOptionalListQueryParams} method. *

+ * * @return The value of the OptionalListQueryParams property for this object. */ public final List optionalListQueryParams() { @@ -236,12 +255,22 @@ public final List optionalListQueryParams() { /** * Returns the value of the StatusCodeOnInput property for this object. + * * @return The value of the StatusCodeOnInput property for this object. */ public final Integer statusCodeOnInput() { return statusCodeOnInput; } + /** + * Returns the value of the PayloadMemberWithCustomName property for this object. + * + * @return The value of the PayloadMemberWithCustomName property for this object. + */ + public final String payloadMemberWithCustomName() { + return payloadMemberWithCustomName; + } + @Override public Builder toBuilder() { return new BuilderImpl(this); @@ -267,6 +296,7 @@ public final int hashCode() { hashCode = 31 * hashCode + Objects.hashCode(hasRequiredListQueryParams() ? requiredListQueryParams() : null); hashCode = 31 * hashCode + Objects.hashCode(hasOptionalListQueryParams() ? optionalListQueryParams() : null); hashCode = 31 * hashCode + Objects.hashCode(statusCodeOnInput()); + hashCode = 31 * hashCode + Objects.hashCode(payloadMemberWithCustomName()); return hashCode; } @@ -287,28 +317,56 @@ public final boolean equalsBySdkFields(Object obj) { return false; } QueryParameterOperationRequest other = (QueryParameterOperationRequest) obj; - return Objects.equals(pathParam(), other.pathParam())&&Objects.equals(queryParamOne(), other.queryParamOne())&&Objects.equals(queryParamTwo(), other.queryParamTwo())&&Objects.equals(stringHeaderMember(), other.stringHeaderMember())&&Objects.equals(nestedQueryParameterOperation(), other.nestedQueryParameterOperation())&&hasRequiredListQueryParams() == other.hasRequiredListQueryParams() && Objects.equals(requiredListQueryParams(), other.requiredListQueryParams())&&hasOptionalListQueryParams() == other.hasOptionalListQueryParams() && Objects.equals(optionalListQueryParams(), other.optionalListQueryParams())&&Objects.equals(statusCodeOnInput(), other.statusCodeOnInput()); + return Objects.equals(pathParam(), other.pathParam()) && Objects.equals(queryParamOne(), other.queryParamOne()) + && Objects.equals(queryParamTwo(), other.queryParamTwo()) + && Objects.equals(stringHeaderMember(), other.stringHeaderMember()) + && Objects.equals(nestedQueryParameterOperation(), other.nestedQueryParameterOperation()) + && hasRequiredListQueryParams() == other.hasRequiredListQueryParams() + && Objects.equals(requiredListQueryParams(), other.requiredListQueryParams()) + && hasOptionalListQueryParams() == other.hasOptionalListQueryParams() + && Objects.equals(optionalListQueryParams(), other.optionalListQueryParams()) + && Objects.equals(statusCodeOnInput(), other.statusCodeOnInput()) + && Objects.equals(payloadMemberWithCustomName(), other.payloadMemberWithCustomName()); } /** - * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be redacted from this string using a placeholder value. + * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be + * redacted from this string using a placeholder value. */ @Override public final String toString() { - return ToString.builder("QueryParameterOperationRequest").add("PathParam", pathParam()).add("QueryParamOne", queryParamOne()).add("QueryParamTwo", queryParamTwo()).add("StringHeaderMember", stringHeaderMember()).add("NestedQueryParameterOperation", nestedQueryParameterOperation()).add("RequiredListQueryParams", hasRequiredListQueryParams() ? requiredListQueryParams() : null).add("OptionalListQueryParams", hasOptionalListQueryParams() ? optionalListQueryParams() : null).add("StatusCodeOnInput", statusCodeOnInput()).build(); + return ToString.builder("QueryParameterOperationRequest").add("PathParam", pathParam()) + .add("QueryParamOne", queryParamOne()).add("QueryParamTwo", queryParamTwo()) + .add("StringHeaderMember", stringHeaderMember()) + .add("NestedQueryParameterOperation", nestedQueryParameterOperation()) + .add("RequiredListQueryParams", hasRequiredListQueryParams() ? requiredListQueryParams() : null) + .add("OptionalListQueryParams", hasOptionalListQueryParams() ? optionalListQueryParams() : null) + .add("StatusCodeOnInput", statusCodeOnInput()).add("PayloadMemberWithCustomName", payloadMemberWithCustomName()) + .build(); } public final Optional getValueForField(String fieldName, Class clazz) { switch (fieldName) { - case "PathParam":return Optional.ofNullable(clazz.cast(pathParam())); - case "QueryParamOne":return Optional.ofNullable(clazz.cast(queryParamOne())); - case "QueryParamTwo":return Optional.ofNullable(clazz.cast(queryParamTwo())); - case "StringHeaderMember":return Optional.ofNullable(clazz.cast(stringHeaderMember())); - case "NestedQueryParameterOperation":return Optional.ofNullable(clazz.cast(nestedQueryParameterOperation())); - case "RequiredListQueryParams":return Optional.ofNullable(clazz.cast(requiredListQueryParams())); - case "OptionalListQueryParams":return Optional.ofNullable(clazz.cast(optionalListQueryParams())); - case "StatusCodeOnInput":return Optional.ofNullable(clazz.cast(statusCodeOnInput())); - default:return Optional.empty(); + case "PathParam": + return Optional.ofNullable(clazz.cast(pathParam())); + case "QueryParamOne": + return Optional.ofNullable(clazz.cast(queryParamOne())); + case "QueryParamTwo": + return Optional.ofNullable(clazz.cast(queryParamTwo())); + case "StringHeaderMember": + return Optional.ofNullable(clazz.cast(stringHeaderMember())); + case "NestedQueryParameterOperation": + return Optional.ofNullable(clazz.cast(nestedQueryParameterOperation())); + case "RequiredListQueryParams": + return Optional.ofNullable(clazz.cast(requiredListQueryParams())); + case "OptionalListQueryParams": + return Optional.ofNullable(clazz.cast(optionalListQueryParams())); + case "StatusCodeOnInput": + return Optional.ofNullable(clazz.cast(statusCodeOnInput())); + case "PayloadMemberWithCustomName": + return Optional.ofNullable(clazz.cast(payloadMemberWithCustomName())); + default: + return Optional.empty(); } } @@ -332,6 +390,7 @@ private static Map> memberNameToFieldInitializer() { map.put("RequiredListQueryParams", REQUIRED_LIST_QUERY_PARAMS_FIELD); map.put("OptionalListQueryParams", OPTIONAL_LIST_QUERY_PARAMS_FIELD); map.put("StatusCodeOnInput", STATUS_CODE_ON_INPUT_FIELD); + map.put("CustomWireName", PAYLOAD_MEMBER_WITH_CUSTOM_NAME_FIELD); return Collections.unmodifiableMap(map); } @@ -345,11 +404,13 @@ private static BiConsumer setter(BiConsumer s) { @Mutable @NotThreadSafe - public interface Builder extends JsonProtocolTestsRequest.Builder, SdkPojo, CopyableBuilder { + public interface Builder extends JsonProtocolTestsRequest.Builder, SdkPojo, + CopyableBuilder { /** * Sets the value of the PathParam property for this object. * - * @param pathParam The new value for the PathParam property for this object. + * @param pathParam + * The new value for the PathParam property for this object. * @return Returns a reference to this object so that method calls can be chained together. */ Builder pathParam(String pathParam); @@ -357,7 +418,8 @@ public interface Builder extends JsonProtocolTestsRequest.Builder, SdkPojo, Copy /** * Sets the value of the QueryParamOne property for this object. * - * @param queryParamOne The new value for the QueryParamOne property for this object. + * @param queryParamOne + * The new value for the QueryParamOne property for this object. * @return Returns a reference to this object so that method calls can be chained together. */ Builder queryParamOne(String queryParamOne); @@ -365,7 +427,8 @@ public interface Builder extends JsonProtocolTestsRequest.Builder, SdkPojo, Copy /** * Sets the value of the QueryParamTwo property for this object. * - * @param queryParamTwo The new value for the QueryParamTwo property for this object. + * @param queryParamTwo + * The new value for the QueryParamTwo property for this object. * @return Returns a reference to this object so that method calls can be chained together. */ Builder queryParamTwo(String queryParamTwo); @@ -373,7 +436,8 @@ public interface Builder extends JsonProtocolTestsRequest.Builder, SdkPojo, Copy /** * Sets the value of the StringHeaderMember property for this object. * - * @param stringHeaderMember The new value for the StringHeaderMember property for this object. + * @param stringHeaderMember + * The new value for the StringHeaderMember property for this object. * @return Returns a reference to this object so that method calls can be chained together. */ Builder stringHeaderMember(String stringHeaderMember); @@ -381,31 +445,38 @@ public interface Builder extends JsonProtocolTestsRequest.Builder, SdkPojo, Copy /** * Sets the value of the NestedQueryParameterOperation property for this object. * - * @param nestedQueryParameterOperation The new value for the NestedQueryParameterOperation property for this object. + * @param nestedQueryParameterOperation + * The new value for the NestedQueryParameterOperation property for this object. * @return Returns a reference to this object so that method calls can be chained together. */ - Builder nestedQueryParameterOperation( - NestedQueryParameterOperation nestedQueryParameterOperation); + Builder nestedQueryParameterOperation(NestedQueryParameterOperation nestedQueryParameterOperation); /** * Sets the value of the NestedQueryParameterOperation property for this object. * - * This is a convenience method that creates an instance of the {@link NestedQueryParameterOperation.Builder} avoiding the need to create one manually via {@link NestedQueryParameterOperation#builder()}. + * This is a convenience method that creates an instance of the {@link NestedQueryParameterOperation.Builder} + * avoiding the need to create one manually via {@link NestedQueryParameterOperation#builder()}. + * + *

+ * When the {@link Consumer} completes, {@link NestedQueryParameterOperation.Builder#build()} is called + * immediately and its result is passed to {@link #nestedQueryParameterOperation(NestedQueryParameterOperation)}. * - *

When the {@link Consumer} completes, {@link NestedQueryParameterOperation.Builder#build()} is called immediately and its result is passed to {@link #nestedQueryParameterOperation(NestedQueryParameterOperation)}. - * @param nestedQueryParameterOperation a consumer that will call methods on {@link NestedQueryParameterOperation.Builder} + * @param nestedQueryParameterOperation + * a consumer that will call methods on {@link NestedQueryParameterOperation.Builder} * @return Returns a reference to this object so that method calls can be chained together. * @see #nestedQueryParameterOperation(NestedQueryParameterOperation) */ default Builder nestedQueryParameterOperation( Consumer nestedQueryParameterOperation) { - return nestedQueryParameterOperation(NestedQueryParameterOperation.builder().applyMutation(nestedQueryParameterOperation).build()); + return nestedQueryParameterOperation(NestedQueryParameterOperation.builder() + .applyMutation(nestedQueryParameterOperation).build()); } /** * Sets the value of the RequiredListQueryParams property for this object. * - * @param requiredListQueryParams The new value for the RequiredListQueryParams property for this object. + * @param requiredListQueryParams + * The new value for the RequiredListQueryParams property for this object. * @return Returns a reference to this object so that method calls can be chained together. */ Builder requiredListQueryParams(Collection requiredListQueryParams); @@ -413,7 +484,8 @@ default Builder nestedQueryParameterOperation( /** * Sets the value of the RequiredListQueryParams property for this object. * - * @param requiredListQueryParams The new value for the RequiredListQueryParams property for this object. + * @param requiredListQueryParams + * The new value for the RequiredListQueryParams property for this object. * @return Returns a reference to this object so that method calls can be chained together. */ Builder requiredListQueryParams(Integer... requiredListQueryParams); @@ -421,7 +493,8 @@ default Builder nestedQueryParameterOperation( /** * Sets the value of the OptionalListQueryParams property for this object. * - * @param optionalListQueryParams The new value for the OptionalListQueryParams property for this object. + * @param optionalListQueryParams + * The new value for the OptionalListQueryParams property for this object. * @return Returns a reference to this object so that method calls can be chained together. */ Builder optionalListQueryParams(Collection optionalListQueryParams); @@ -429,7 +502,8 @@ default Builder nestedQueryParameterOperation( /** * Sets the value of the OptionalListQueryParams property for this object. * - * @param optionalListQueryParams The new value for the OptionalListQueryParams property for this object. + * @param optionalListQueryParams + * The new value for the OptionalListQueryParams property for this object. * @return Returns a reference to this object so that method calls can be chained together. */ Builder optionalListQueryParams(Integer... optionalListQueryParams); @@ -437,17 +511,26 @@ default Builder nestedQueryParameterOperation( /** * Sets the value of the StatusCodeOnInput property for this object. * - * @param statusCodeOnInput The new value for the StatusCodeOnInput property for this object. + * @param statusCodeOnInput + * The new value for the StatusCodeOnInput property for this object. * @return Returns a reference to this object so that method calls can be chained together. */ Builder statusCodeOnInput(Integer statusCodeOnInput); + /** + * Sets the value of the PayloadMemberWithCustomName property for this object. + * + * @param payloadMemberWithCustomName + * The new value for the PayloadMemberWithCustomName property for this object. + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder payloadMemberWithCustomName(String payloadMemberWithCustomName); + @Override Builder overrideConfiguration(AwsRequestOverrideConfiguration overrideConfiguration); @Override - Builder overrideConfiguration( - Consumer builderConsumer); + Builder overrideConfiguration(Consumer builderConsumer); } static final class BuilderImpl extends JsonProtocolTestsRequest.BuilderImpl implements Builder { @@ -467,11 +550,14 @@ static final class BuilderImpl extends JsonProtocolTestsRequest.BuilderImpl impl private Integer statusCodeOnInput; + private String payloadMemberWithCustomName; + private BuilderImpl() { } private BuilderImpl(QueryParameterOperationRequest model) { - super(model);pathParam(model.pathParam); + super(model); + pathParam(model.pathParam); queryParamOne(model.queryParamOne); queryParamTwo(model.queryParamTwo); stringHeaderMember(model.stringHeaderMember); @@ -479,6 +565,7 @@ private BuilderImpl(QueryParameterOperationRequest model) { requiredListQueryParams(model.requiredListQueryParams); optionalListQueryParams(model.optionalListQueryParams); statusCodeOnInput(model.statusCodeOnInput); + payloadMemberWithCustomName(model.payloadMemberWithCustomName); } public final String getPathParam() { @@ -541,20 +628,22 @@ public final NestedQueryParameterOperation.Builder getNestedQueryParameterOperat return nestedQueryParameterOperation != null ? nestedQueryParameterOperation.toBuilder() : null; } - public final void setNestedQueryParameterOperation( - NestedQueryParameterOperation.BuilderImpl nestedQueryParameterOperation) { - this.nestedQueryParameterOperation = nestedQueryParameterOperation != null ? nestedQueryParameterOperation.build() : null; + public final void setNestedQueryParameterOperation(NestedQueryParameterOperation.BuilderImpl nestedQueryParameterOperation) { + this.nestedQueryParameterOperation = nestedQueryParameterOperation != null ? nestedQueryParameterOperation.build() + : null; } @Override - public final Builder nestedQueryParameterOperation( - NestedQueryParameterOperation nestedQueryParameterOperation) { + public final Builder nestedQueryParameterOperation(NestedQueryParameterOperation nestedQueryParameterOperation) { this.nestedQueryParameterOperation = nestedQueryParameterOperation; return this; } public final Collection getRequiredListQueryParams() { - if (requiredListQueryParams instanceof SdkAutoConstructList) {return null;}return requiredListQueryParams; + if (requiredListQueryParams instanceof SdkAutoConstructList) { + return null; + } + return requiredListQueryParams; } public final void setRequiredListQueryParams(Collection requiredListQueryParams) { @@ -570,11 +659,15 @@ public final Builder requiredListQueryParams(Collection requiredListQue @Override @SafeVarargs public final Builder requiredListQueryParams(Integer... requiredListQueryParams) { - requiredListQueryParams(Arrays.asList(requiredListQueryParams));return this; + requiredListQueryParams(Arrays.asList(requiredListQueryParams)); + return this; } public final Collection getOptionalListQueryParams() { - if (optionalListQueryParams instanceof SdkAutoConstructList) {return null;}return optionalListQueryParams; + if (optionalListQueryParams instanceof SdkAutoConstructList) { + return null; + } + return optionalListQueryParams; } public final void setOptionalListQueryParams(Collection optionalListQueryParams) { @@ -590,7 +683,8 @@ public final Builder optionalListQueryParams(Collection optionalListQue @Override @SafeVarargs public final Builder optionalListQueryParams(Integer... optionalListQueryParams) { - optionalListQueryParams(Arrays.asList(optionalListQueryParams));return this; + optionalListQueryParams(Arrays.asList(optionalListQueryParams)); + return this; } public final Integer getStatusCodeOnInput() { @@ -607,6 +701,20 @@ public final Builder statusCodeOnInput(Integer statusCodeOnInput) { return this; } + public final String getPayloadMemberWithCustomName() { + return payloadMemberWithCustomName; + } + + public final void setPayloadMemberWithCustomName(String payloadMemberWithCustomName) { + this.payloadMemberWithCustomName = payloadMemberWithCustomName; + } + + @Override + public final Builder payloadMemberWithCustomName(String payloadMemberWithCustomName) { + this.payloadMemberWithCustomName = payloadMemberWithCustomName; + return this; + } + @Override public Builder overrideConfiguration(AwsRequestOverrideConfiguration overrideConfiguration) { super.overrideConfiguration(overrideConfiguration); @@ -614,8 +722,7 @@ public Builder overrideConfiguration(AwsRequestOverrideConfiguration overrideCon } @Override - public Builder overrideConfiguration( - Consumer builderConsumer) { + public Builder overrideConfiguration(Consumer builderConsumer) { super.overrideConfiguration(builderConsumer); return this; } From 68fc9939d92b4153c42f728ba833051cbf92743b Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:36:25 -0700 Subject: [PATCH 15/16] Add test coverage --- .../software/amazon/awssdk/codegen/CodeGeneratorTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java index 194a315537b8..b91c4c90a5bb 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java @@ -44,7 +44,6 @@ import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; import software.amazon.awssdk.codegen.model.config.customization.UnderscoresInNameBehavior; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; -import software.amazon.awssdk.codegen.model.intermediate.MemberModel; import software.amazon.awssdk.codegen.model.intermediate.ShapeModel; import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel; import software.amazon.awssdk.codegen.model.service.Location; @@ -52,7 +51,6 @@ import software.amazon.awssdk.codegen.poet.ClientTestModels; import software.amazon.awssdk.codegen.validation.ModelInvalidException; import software.amazon.awssdk.codegen.validation.ModelValidator; -import software.amazon.awssdk.codegen.validation.ValidationEntry; import software.amazon.awssdk.codegen.validation.ValidationErrorId; public class CodeGeneratorTest { @@ -226,7 +224,9 @@ void execute_operationHasNoRequestUri_throwsValidationError() throws IOException assertThatThrownBy(() -> generateCodeFromC2jModels(models, outputDir, true, Collections.emptyList())) .isInstanceOf(ModelInvalidException.class) .matches(e -> ((ModelInvalidException) e).validationEntries().get(0).getErrorId() - == ValidationErrorId.REQUEST_URI_NOT_FOUND); + == ValidationErrorId.REQUEST_URI_NOT_FOUND) + .matches(e -> ((ModelInvalidException) e).validationEntries().get(0).getDetailMessage() + .contains("OperationWithUriMappedParamRequest")); } private void generateCodeFromC2jModels(C2jModels c2jModels, Path outputDir) { From 792910517d7af7fc83325740e646a79a9fcc3540 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:38:04 -0700 Subject: [PATCH 16/16] Fix assertion --- .../java/software/amazon/awssdk/codegen/CodeGeneratorTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java index b91c4c90a5bb..26b65c66d04e 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java @@ -226,7 +226,8 @@ void execute_operationHasNoRequestUri_throwsValidationError() throws IOException .matches(e -> ((ModelInvalidException) e).validationEntries().get(0).getErrorId() == ValidationErrorId.REQUEST_URI_NOT_FOUND) .matches(e -> ((ModelInvalidException) e).validationEntries().get(0).getDetailMessage() - .contains("OperationWithUriMappedParamRequest")); + .equals("Operation referencing input shape 'OperationWithUriMappedParamRequest'" + + " has no requestUri configured in its HTTP binding.")); } private void generateCodeFromC2jModels(C2jModels c2jModels, Path outputDir) {