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.core;
17
18 import software.amazon.awssdk.annotations.SdkProtectedApi;
19 import software.amazon.awssdk.http.SdkHttpMethod;
20 import software.amazon.awssdk.utils.AttributeMap;
21
22 /**
23  * Static information about an API operation used to marshall it correctly.
24  */

25 @SdkProtectedApi
26 public final class OperationInfo {
27
28     private final String requestUri;
29     private final SdkHttpMethod httpMethod;
30     private final String operationIdentifier;
31     private final String apiVersion;
32     private final boolean hasExplicitPayloadMember;
33     private final boolean hasPayloadMembers;
34     private final boolean hasStreamingInput;
35     private final boolean hasEventStreamingInput;
36     private final boolean hasEvent;
37     private final AttributeMap additionalMetadata;
38
39     private OperationInfo(Builder builder) {
40         this.requestUri = builder.requestUri;
41         this.httpMethod = builder.httpMethod;
42         this.operationIdentifier = builder.operationIdentifier;
43         this.apiVersion = builder.apiVersion;
44         this.hasExplicitPayloadMember = builder.hasExplicitPayloadMember;
45         this.hasPayloadMembers = builder.hasPayloadMembers;
46         this.hasStreamingInput = builder.hasStreamingInput;
47         this.additionalMetadata = builder.additionalMetadata.build();
48         this.hasEventStreamingInput = builder.hasEventStreamingInput;
49         this.hasEvent = builder.hasEvent;
50     }
51
52     /**
53      * @return Request URI for operation (may contain placeholders for members bound to the uri).
54      */

55     public String requestUri() {
56         return requestUri;
57     }
58
59     /**
60      * @return HTTP Method that should be used when sending the request.
61      */

62     public SdkHttpMethod httpMethod() {
63         return httpMethod;
64     }
65
66     /**
67      * @return Identifer for the operation/API being invoked. This is used for RPC based protocols that
68      *     need to identify which action is being taken. For Query/EC2 protocol this is sent as the 'Action' query
69      *     parameter, for JSON RPC this is sent as the 'X-Amz-Target' header.
70      */

71     public String operationIdentifier() {
72         return operationIdentifier;
73     }
74
75     /**
76      * @return Version of the service's API. For Query protocol this is sent as a 'Version' query parameter.
77      */

78     public String apiVersion() {
79         return apiVersion;
80     }
81
82     /**
83      * @return True if the operation has a member that's explicitly marked as the payload. False otherwise. (Applicable only to
84      *     RESTUL protocols).
85      */

86     public boolean hasExplicitPayloadMember() {
87         return hasExplicitPayloadMember;
88     }
89
90     /**
91      * @return True if the operation has members bound to the payload. Some requests (especially GET and DELETE) may not
92      *     have any members bound to the payload. (Applicable only to RESTFUL protocols).
93      */

94     public boolean hasPayloadMembers() {
95         return hasPayloadMembers;
96     }
97
98     /**
99      * @return True if the operation has streaming input.
100      */

101     public boolean hasStreamingInput() {
102         return hasStreamingInput;
103     }
104
105     /**
106      * @return True if the operation has event streaming input.
107      */

108     public boolean hasEventStreamingInput() {
109         return hasEventStreamingInput;
110     }
111
112     /**
113      * @return True if the operation has event.
114      */

115     public boolean hasEvent() {
116         return hasEvent;
117     }
118
119     /**
120      * Gets an unmodeled piece of metadata. Useful for protocol specific options.
121      *
122      * @param key Key the metadata was registered under.
123      * @param <T> Type of metadata being requested.
124      * @return The value of the additional metadata being requested or null if it's not present.
125      */

126     public <T> T addtionalMetadata(OperationMetadataAttribute<T> key) {
127         return additionalMetadata.get(key);
128     }
129
130     /**
131      * @return Builder instance to construct a {@link OperationInfo}.
132      */

133     public static Builder builder() {
134         return new Builder();
135     }
136
137     /**
138      * Builder for a {@link OperationInfo}.
139      */

140     public static final class Builder {
141
142         private String requestUri;
143         private SdkHttpMethod httpMethod;
144         private String operationIdentifier;
145         private String apiVersion;
146         private boolean hasExplicitPayloadMember;
147         private boolean hasPayloadMembers;
148         private boolean hasStreamingInput;
149         private boolean hasEventStreamingInput;
150         private boolean hasEvent;
151         private AttributeMap.Builder additionalMetadata = AttributeMap.builder();
152
153         private Builder() {
154         }
155
156         public Builder requestUri(String requestUri) {
157             this.requestUri = requestUri;
158             return this;
159         }
160
161         public Builder httpMethod(SdkHttpMethod httpMethod) {
162             this.httpMethod = httpMethod;
163             return this;
164         }
165
166         public Builder operationIdentifier(String operationIdentifier) {
167             this.operationIdentifier = operationIdentifier;
168             return this;
169         }
170
171         public Builder apiVersion(String apiVersion) {
172             this.apiVersion = apiVersion;
173             return this;
174         }
175
176         public Builder hasExplicitPayloadMember(boolean hasExplicitPayloadMember) {
177             this.hasExplicitPayloadMember = hasExplicitPayloadMember;
178             return this;
179         }
180
181         public Builder hasPayloadMembers(boolean hasPayloadMembers) {
182             this.hasPayloadMembers = hasPayloadMembers;
183             return this;
184         }
185
186         public Builder hasStreamingInput(boolean hasStreamingInput) {
187             this.hasStreamingInput = hasStreamingInput;
188             return this;
189         }
190
191         public Builder hasEventStreamingInput(boolean hasEventStreamingInput) {
192             this.hasEventStreamingInput = hasEventStreamingInput;
193             return this;
194         }
195
196         public Builder hasEvent(boolean hasEvent) {
197             this.hasEvent = hasEvent;
198             return this;
199         }
200
201         /**
202          * Adds additional unmodeled metadata to the {@link OperationInfo}. Useful for communicating protocol
203          * specific operation metadata.
204          *
205          * @param key Key to register metadata.
206          * @param value Value of metadata.
207          * @param <T> Type of metadata being registered.
208          * @return This builder for method chaining.
209          */

210         public <T> Builder putAdditionalMetadata(OperationMetadataAttribute<T> key, T value) {
211             additionalMetadata.put(key, value);
212             return this;
213         }
214
215         /**
216          * @return An immutable {@link OperationInfo} object.
217          */

218         public OperationInfo build() {
219             return new OperationInfo(this);
220         }
221     }
222 }
223