1 /* 2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"). 5 * You may not use this file except in compliance with the License. 6 * A copy of the License is located at 7 * 8 * http://aws.amazon.com/apache2.0 9 * 10 * or in the "license" file accompanying this file. This file is distributed 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 * express or implied. See the License for the specific language governing 13 * permissions and limitations under the License. 14 */ 15 16 package software.amazon.awssdk.protocols.query.internal.marshall; 17 18 import java.util.List; 19 import software.amazon.awssdk.annotations.SdkInternalApi; 20 import software.amazon.awssdk.core.SdkField; 21 import software.amazon.awssdk.core.traits.ListTrait; 22 import software.amazon.awssdk.core.util.SdkAutoConstructList; 23 24 /** 25 * Marshaller for list types. 26 */ 27 @SdkInternalApi 28 public class ListQueryMarshaller implements QueryMarshaller<List<?>> { 29 30 private final PathResolver pathResolver; 31 ListQueryMarshaller(PathResolver pathResolver)32 private ListQueryMarshaller(PathResolver pathResolver) { 33 this.pathResolver = pathResolver; 34 } 35 36 @Override marshall(QueryMarshallerContext context, String path, List<?> val, SdkField<List<?>> sdkField)37 public void marshall(QueryMarshallerContext context, String path, List<?> val, SdkField<List<?>> sdkField) { 38 // Explicitly empty lists are marshalled as a query param with empty value in AWS/Query 39 if (val.isEmpty() && !(val instanceof SdkAutoConstructList)) { 40 context.request().putRawQueryParameter(path, ""); 41 return; 42 } 43 for (int i = 0; i < val.size(); i++) { 44 ListTrait listTrait = sdkField.getTrait(ListTrait.class); 45 String listPath = pathResolver.resolve(path, i, listTrait); 46 QueryMarshaller<Object> marshaller = context.marshallerRegistry().getMarshaller( 47 ((SdkField<?>) listTrait.memberFieldInfo()).marshallingType(), val); 48 marshaller.marshall(context, listPath, val.get(i), listTrait.memberFieldInfo()); 49 } 50 } 51 52 @FunctionalInterface 53 private interface PathResolver { 54 resolve(String path, int i, ListTrait listTrait)55 String resolve(String path, int i, ListTrait listTrait); 56 } 57 58 /** 59 * Wires up the {@link ListQueryMarshaller} with a {@link PathResolver} that respects the flattened trait. 60 * 61 * @return ListQueryMarshaller. 62 */ awsQuery()63 public static ListQueryMarshaller awsQuery() { 64 return new ListQueryMarshaller((path, i, listTrait) -> 65 listTrait.isFlattened() ? 66 String.format("%s.%d", path, i + 1) : 67 String.format("%s.%s.%d", path, listTrait.memberFieldInfo().locationName(), i + 1)); 68 } 69 70 /** 71 * Wires up the {@link ListQueryMarshaller} with a {@link PathResolver} that always flattens lists. The EC2 protocol 72 * always flattens lists for inputs even when the 'flattened' trait is not present. 73 * 74 * @return ListQueryMarshaller. 75 */ ec2Query()76 public static ListQueryMarshaller ec2Query() { 77 return new ListQueryMarshaller((path, i, listTrait) -> String.format("%s.%d", path, i + 1)); 78 } 79 } 80