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.enhanced.dynamodb.internal.operations; 17 18 import java.util.concurrent.CompletableFuture; 19 import java.util.function.Function; 20 import software.amazon.awssdk.annotations.SdkInternalApi; 21 import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncIndex; 22 import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; 23 import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension; 24 import software.amazon.awssdk.enhanced.dynamodb.DynamoDbIndex; 25 import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; 26 import software.amazon.awssdk.enhanced.dynamodb.OperationContext; 27 import software.amazon.awssdk.enhanced.dynamodb.TableSchema; 28 import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; 29 import software.amazon.awssdk.services.dynamodb.DynamoDbClient; 30 31 32 /** 33 * Common interface for a single operation that can be executed in a synchronous or non-blocking asynchronous fashion 34 * against a mapped database table. These operations can be made against either the primary index of a table or a 35 * secondary index, although some implementations of this interface do not support secondary indices and will throw 36 * an exception when executed against one. Conceptually an operation maps 1:1 with an actual DynamoDb call. 37 * <p> 38 * This interface is extended by {@link TableOperation} and {@link IndexOperation} which contain implementations of 39 * the behavior to actually execute the operation in the context of a table or secondary index and are used by 40 * {@link DynamoDbTable} or {@link DynamoDbAsyncTable} and {@link DynamoDbIndex} or {@link DynamoDbAsyncIndex} 41 * respectively. By sharing this common interface operations are able to re-use code regardless of whether they are 42 * executed in the context of a primary or secondary index or whether they are being executed in a synchronous or 43 * non-blocking asynchronous fashion. 44 * 45 * @param <ItemT> The modelled object that this table maps records to. 46 * @param <RequestT> The type of the request object for the DynamoDb call in the low level {@link DynamoDbClient} or 47 * {@link DynamoDbAsyncClient}. 48 * @param <ResponseT> The type of the response object for the DynamoDb call in the low level {@link DynamoDbClient} 49 * or {@link DynamoDbAsyncClient}. 50 * @param <ResultT> The type of the mapped result object that will be returned by the execution of this operation. 51 */ 52 @SdkInternalApi 53 public interface CommonOperation<ItemT, RequestT, ResponseT, ResultT> { 54 /** 55 * This method generates the request that needs to be sent to a low level {@link DynamoDbClient}. 56 * @param tableSchema A {@link TableSchema} that maps the table to a modelled object. 57 * @param context An object containing the context, or target, of the command execution. 58 * @param extension A {@link DynamoDbEnhancedClientExtension} that may modify the request of this operation. A null 59 * value here will result in no modifications. 60 * @return A request that can be used as an argument to a {@link DynamoDbClient} call to perform the operation. 61 */ generateRequest(TableSchema<ItemT> tableSchema, OperationContext context, DynamoDbEnhancedClientExtension extension)62 RequestT generateRequest(TableSchema<ItemT> tableSchema, OperationContext context, 63 DynamoDbEnhancedClientExtension extension); 64 65 /** 66 * Provides a function for making the low level synchronous SDK call to DynamoDb. 67 * @param dynamoDbClient A low level {@link DynamoDbClient} to make the call against. 68 * @return A function that calls DynamoDb with a provided request object and returns the response object. 69 */ serviceCall(DynamoDbClient dynamoDbClient)70 Function<RequestT, ResponseT> serviceCall(DynamoDbClient dynamoDbClient); 71 72 /** 73 * Provides a function for making the low level non-blocking asynchronous SDK call to DynamoDb. 74 * @param dynamoDbAsyncClient A low level {@link DynamoDbAsyncClient} to make the call against. 75 * @return A function that calls DynamoDb with a provided request object and returns the response object. 76 */ asyncServiceCall(DynamoDbAsyncClient dynamoDbAsyncClient)77 Function<RequestT, CompletableFuture<ResponseT>> asyncServiceCall(DynamoDbAsyncClient dynamoDbAsyncClient); 78 79 /** 80 * Takes the response object returned by the actual DynamoDb call and maps it into a higher level abstracted 81 * result object. 82 * @param response The response object returned by the DynamoDb call for this operation. 83 * @param tableSchema A {@link TableSchema} that maps the table to a modelled object. 84 * @param context An object containing the context, or target, of the command execution. 85 * @param extension A {@link DynamoDbEnhancedClientExtension} that may modify the result of this operation. A null 86 * value here will result in no modifications. 87 * @return A high level result object as specified by the implementation of this operation. 88 */ transformResponse(ResponseT response, TableSchema<ItemT> tableSchema, OperationContext context, DynamoDbEnhancedClientExtension extension)89 ResultT transformResponse(ResponseT response, 90 TableSchema<ItemT> tableSchema, 91 OperationContext context, 92 DynamoDbEnhancedClientExtension extension); 93 94 /** 95 * Default implementation of a complete synchronous execution of this operation against either the primary or a 96 * secondary index. 97 * It performs three steps: 98 * 1) Call generateRequest() to get the request object. 99 * 2) Call getServiceCall() and call it using the request object generated in the previous step. 100 * 3) Call transformResponse() to convert the response object returned in the previous step to a high level result. 101 * 102 * @param tableSchema A {@link TableSchema} that maps the table to a modelled object. 103 * @param context An object containing the context, or target, of the command execution. 104 * @param dynamoDbClient A {@link DynamoDbClient} to make the call against. 105 * @param extension A {@link DynamoDbEnhancedClientExtension} that may modify the request or result of this 106 * operation. A null value here will result in no modifications. 107 * @return A high level result object as specified by the implementation of this operation. 108 */ execute(TableSchema<ItemT> tableSchema, OperationContext context, DynamoDbEnhancedClientExtension extension, DynamoDbClient dynamoDbClient)109 default ResultT execute(TableSchema<ItemT> tableSchema, 110 OperationContext context, 111 DynamoDbEnhancedClientExtension extension, 112 DynamoDbClient dynamoDbClient) { 113 RequestT request = generateRequest(tableSchema, context, extension); 114 ResponseT response = serviceCall(dynamoDbClient).apply(request); 115 return transformResponse(response, tableSchema, context, extension); 116 } 117 118 /** 119 * Default implementation of a complete non-blocking asynchronous execution of this operation against either the 120 * primary or a secondary index. 121 * It performs three steps: 122 * 1) Call generateRequest() to get the request object. 123 * 2) Call getServiceCall() and call it using the request object generated in the previous step. 124 * 3) Wraps the {@link CompletableFuture} returned by the SDK in a new one that calls transformResponse() to 125 * convert the response object returned in the previous step to a high level result. 126 * 127 * @param tableSchema A {@link TableSchema} that maps the table to a modelled object. 128 * @param context An object containing the context, or target, of the command execution. 129 * @param dynamoDbAsyncClient A {@link DynamoDbAsyncClient} to make the call against. 130 * @param extension A {@link DynamoDbEnhancedClientExtension} that may modify the request or result of this 131 * operation. A null value here will result in no modifications. 132 * @return A {@link CompletableFuture} of the high level result object as specified by the implementation of this 133 * operation. 134 */ executeAsync(TableSchema<ItemT> tableSchema, OperationContext context, DynamoDbEnhancedClientExtension extension, DynamoDbAsyncClient dynamoDbAsyncClient)135 default CompletableFuture<ResultT> executeAsync(TableSchema<ItemT> tableSchema, 136 OperationContext context, 137 DynamoDbEnhancedClientExtension extension, 138 DynamoDbAsyncClient dynamoDbAsyncClient) { 139 RequestT request = generateRequest(tableSchema, context, extension); 140 CompletableFuture<ResponseT> response = asyncServiceCall(dynamoDbAsyncClient).apply(request); 141 return response.thenApply(r -> transformResponse(r, tableSchema, context, extension)); 142 } 143 144 /** 145 * The type, or name, of the operation. 146 */ operationName()147 OperationName operationName(); 148 } 149