001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.dto.openapi3;
014
015import static org.apache.juneau.internal.ConverterUtils.*;
016
017import org.apache.juneau.*;
018import org.apache.juneau.annotation.Bean;
019import org.apache.juneau.internal.*;
020
021import java.util.*;
022
023import static org.apache.juneau.common.internal.StringUtils.*;
024import static org.apache.juneau.internal.ArrayUtils.contains;
025import static org.apache.juneau.internal.CollectionUtils.*;
026
027/**
028 * Describes a single operation parameter.
029 *
030 * <p>
031 * A unique parameter is defined by a combination of a name and location.
032 *
033 * <p>
034 * There are five possible parameter types.
035 * <ul class='spaced-list'>
036 *    <li><js>"path"</js> - Used together with Path Templating, where the parameter value is actually part of the
037 *       operation's URL.
038 *       This does not include the host or base path of the API.
039 *       For example, in <code>/items/{itemId}</code>, the path parameter is <code>itemId</code>.
040 *    <li><js>"query"</js> - Parameters that are appended to the URL.
041 *       For example, in <code>/items?id=###</code>, the query parameter is <code>id</code>.
042 *    <li><js>"header"</js> - Custom headers that are expected as part of the request.
043 *    <li><js>"body"</js> - The payload that's appended to the HTTP request.
044 *       Since there can only be one payload, there can only be one body parameter.
045 *       The name of the body parameter has no effect on the parameter itself and is used for documentation purposes
046 *       only.
047 *       Since Form parameters are also in the payload, body and form parameters cannot exist together for the same
048 *       operation.
049 *    <li><js>"formData"</js> - Used to describe the payload of an HTTP request when either
050 *       <code>application/x-www-form-urlencoded</code>, <code>multipart/form-data</code> or both are used as the
051 *       content type of the request (in Swagger's definition, the consumes property of an operation).
052 *       This is the only parameter type that can be used to send files, thus supporting the file type.
053 *       Since form parameters are sent in the payload, they cannot be declared together with a body parameter for the
054 *       same operation.
055 *       Form parameters have a different format based on the content-type used (for further details, consult
056 *       <code>http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4</code>):
057 *       <ul>
058 *          <li><js>"application/x-www-form-urlencoded"</js> - Similar to the format of Query parameters but as a
059 *             payload.
060 *             For example, <code>foo=1&amp;bar=swagger</code> - both <code>foo</code> and <code>bar</code> are form
061 *             parameters.
062 *             This is normally used for simple parameters that are being transferred.
063 *          <li><js>"multipart/form-data"</js> - each parameter takes a section in the payload with an internal header.
064 *             For example, for the header <code>Content-Disposition: form-data; name="submit-name"</code> the name of
065 *             the parameter is <code>submit-name</code>.
066 *             This type of form parameters is more commonly used for file transfers.
067 *       </ul>
068 *    </li>
069 * </ul>
070 *
071 * <h5 class='section'>Example:</h5>
072 * <p class='bcode'>
073 *    <jc>// Construct using SwaggerBuilder.</jc>
074 *    ParameterInfo x = <jsm>parameterInfo</jsm>(<js>"query"</js>, <js>"foo"</js>);
075 *
076 *    <jc>// Serialize using JsonSerializer.</jc>
077 *    String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
078 *
079 *    <jc>// Or just use toString() which does the same as above.</jc>
080 *    String json = x.toString();
081 * </p>
082 * <p class='bcode'>
083 *    <jc>// Output</jc>
084 *    {
085 *       <js>"in"</js>: <js>"query"</js>,
086 *       <js>"name"</js>: <js>"foo"</js>
087 *    }
088 * </p>
089 */
090@Bean(properties="in,name,type,description,scheme,bearerFormat,flows,*")
091@FluentSetters
092public class SecuritySchemeInfo extends OpenApiElement {
093
094   private static final String[] VALID_IN = {"query", "header", "cookie"};
095   private static final String[] VALID_TYPES = {"apiKey", "http", "oauth2", "openIdConnect"};
096
097   private String
098      type,
099      description,
100      name,
101      in,
102      scheme,
103      bearerFormat,
104      openIdConnectUrl;
105
106   private OAuthFlow flows;
107
108   /**
109    * Default constructor.
110    */
111   public SecuritySchemeInfo() {}
112
113   /**
114    * Copy constructor.
115    *
116    * @param copyFrom The object to copy.
117    */
118   public SecuritySchemeInfo(SecuritySchemeInfo copyFrom) {
119      super(copyFrom);
120
121      this.name = copyFrom.name;
122      this.in = copyFrom.in;
123      this.description = copyFrom.description;
124      this.type = copyFrom.type;
125      this.scheme = copyFrom.scheme;
126      this.bearerFormat = copyFrom.bearerFormat;
127      this.openIdConnectUrl = copyFrom.openIdConnectUrl;
128      this.flows = copyFrom.flows;
129   }
130
131   /**
132    * Make a deep copy of this object.
133    *
134    * @return A deep copy of this object.
135    */
136   public SecuritySchemeInfo copy() {
137      return new SecuritySchemeInfo(this);
138   }
139
140   @Override /* SwaggerElement */
141   protected SecuritySchemeInfo strict() {
142      super.strict();
143      return this;
144   }
145
146
147   /**
148    * Bean property getter:  <property>name</property>.
149    *
150    * <p>
151    * The name of the parameter.
152    *
153    * <h5 class='section'>Notes:</h5>
154    * <ul class='spaced-list'>
155    *    <li>
156    *       Parameter names are case sensitive.
157    *    <li>
158    *       If <code>in</code> is <js>"path"</js>, the <code>name</code> field MUST correspond to the associated path segment
159    *       from the <code>path</code> field in the paths object.
160    *    <li>
161    *       For all other cases, the name corresponds to the parameter name used based on the <code>in</code> property.
162    * </ul>
163    *
164    * @return The property value, or <jk>null</jk> if it is not set.
165    */
166   public String getName() {
167      return name;
168   }
169
170   /**
171    * Bean property setter:  <property>name</property>.
172    *
173    * <p>
174    * The name of the parameter.
175    *
176    * <h5 class='section'>Notes:</h5>
177    * <ul class='spaced-list'>
178    *    <li>
179    *       Parameter names are case sensitive.
180    *    <li>
181    *       If <code>in</code> is <js>"path"</js>, the <code>name</code> field MUST correspond to the associated path segment
182    *       from the <code>path</code> field in the paths object.
183    *    <li>
184    *       For all other cases, the name corresponds to the parameter name used based on the <code>in</code> property.
185    * </ul>
186    *
187    * @param value
188    *    The new value for this property.
189    *    <br>Property value is required.
190    * @return This object
191    */
192   public SecuritySchemeInfo setName(String value) {
193      name = value;
194      return this;
195   }
196
197   /**
198    * Bean property getter:  <property>in</property>.
199    *
200    * <p>
201    * The location of the parameter.
202    *
203    * @return The property value, or <jk>null</jk> if it is not set.
204    */
205   public String getIn() {
206      return in;
207   }
208
209   /**
210    * Bean property setter:  <property>in</property>.
211    *
212    * <p>
213    * The location of the parameter.
214    *
215    * @param value
216    *    The new value for this property.
217    *    <br>Valid values:
218    *    <ul>
219    *       <li><js>"query"</js>
220    *       <li><js>"header"</js>
221    *       <li><js>"path"</js>
222    *       <li><js>"formData"</js>
223    *       <li><js>"body"</js>
224    *    </ul>
225    *    <br>Property value is required.
226    * @return This object
227    */
228   public SecuritySchemeInfo setIn(String value) {
229      if (isStrict() && ! contains(value, VALID_IN))
230         throw new BasicRuntimeException(
231            "Invalid value passed in to setIn(String).  Value=''{0}'', valid values={1}",
232            value, VALID_IN
233         );
234      in = value;
235      return this;
236   }
237
238   /**
239    * Bean property getter:  <property>description</property>.
240    *
241    * <p>
242    * A brief description of the parameter.
243    * <br>This could contain examples of use.
244    *
245    * @return The property value, or <jk>null</jk> if it is not set.
246    */
247   public String getDescription() {
248      return description;
249   }
250
251   /**
252    * Bean property setter:  <property>description</property>.
253    *
254    * <p>
255    * A brief description of the parameter.
256    * <br>This could contain examples of use.
257    *
258    * @param value
259    *    The new value for this property.
260    *    <br>Can be <jk>null</jk> to unset the property.
261    * @return This object
262    */
263   public SecuritySchemeInfo setDescription(String value) {
264      description = value;
265      return this;
266   }
267
268   /**
269    * Bean property getter:  <property>schema</property>.
270    *
271    * <p>
272    * The schema defining the type used for the body parameter.
273    *
274    * @return The property value, or <jk>null</jk> if it is not set.
275    */
276   public String getScheme() {
277      return scheme;
278   }
279
280   /**
281    * Bean property setter:  <property>schema</property>.
282    *
283    * <p>
284    * The schema defining the type used for the body parameter.
285    *
286    * @param value
287    *    The new value for this property.
288    *    <br>Property value is required.
289    * @return This object
290    */
291   public SecuritySchemeInfo setScheme(String value) {
292      scheme = value;
293      return this;
294   }
295
296   /**
297    * Bean property getter:  <property>type</property>.
298    *
299    * <p>
300    * The type of the parameter.
301    *
302    * @return The property value, or <jk>null</jk> if it is not set.
303    */
304   public String getType() {
305      return type;
306   }
307
308   /**
309    * Bean property setter:  <property>type</property>.
310    *
311    * <p>
312    * The type of the parameter.
313    *
314    * @param value
315    *    The new value for this property.
316    *    <br>Valid values:
317    *    <ul>
318    *       <li><js>"string"</js>
319    *       <li><js>"number"</js>
320    *       <li><js>"integer"</js>
321    *       <li><js>"boolean"</js>
322    *       <li><js>"array"</js>
323    *       <li><js>"file"</js>
324    *    </ul>
325    *    <br>If type is <js>"file"</js>, the <code>consumes</code> MUST be either <js>"multipart/form-data"</js>, <js>"application/x-www-form-urlencoded"</js>
326    *       or both and the parameter MUST be <code>in</code> <js>"formData"</js>.
327    *    <br>Property value is required.
328    * @return This object
329    */
330   public SecuritySchemeInfo setType(String value) {
331      if (isStrict() && ! contains(value, VALID_TYPES))
332         throw new BasicRuntimeException(
333            "Invalid value passed in to setType(String).  Value=''{0}'', valid values={1}",
334            value, VALID_TYPES
335         );
336      type = value;
337      return this;
338   }
339
340   /**
341    * Bean property getter:  <property>format</property>.
342    *
343    * <p>
344    * The extending format for the previously mentioned type.
345    *
346    * @return The property value, or <jk>null</jk> if it is not set.
347    */
348   public String getBearerFormat() {
349      return bearerFormat;
350   }
351
352   /**
353    * Bean property setter:  <property>format</property>.
354    *
355    * <p>
356    * The extending format for the previously mentioned type.
357    *
358    * @param value The new value for this property.
359    * @return This object
360    */
361   public SecuritySchemeInfo setBearerFormat(String value) {
362      bearerFormat = value;
363      return this;
364   }
365
366   /**
367    * Bean property getter:  <property>items</property>.
368    *
369    * <p>
370    * Describes the type of items in the array.
371    *
372    * @return The property value, or <jk>null</jk> if it is not set.
373    */
374   public OAuthFlow getFlows() {
375      return flows;
376   }
377
378   /**
379    * Bean property setter:  <property>items</property>.
380    *
381    * <p>
382    * Describes the type of items in the array.
383    *
384    * @param value
385    *    The new value for this property.
386    *    <br>Property value is required if <code>type</code> is <js>"array"</js>.
387    *    <br>Can be <jk>null</jk> to unset the property.
388    * @return This object
389    */
390   public SecuritySchemeInfo setFlows(OAuthFlow value) {
391      flows = value;
392      return this;
393   }
394
395   /**
396    * Bean property getter:  <property>collectionFormat</property>.
397    *
398    * <p>
399    * Determines the format of the array if type array is used.
400    *
401    * @return The property value, or <jk>null</jk> if it is not set.
402    */
403   public String getOpenIdConnectUrl() {
404      return openIdConnectUrl;
405   }
406
407   /**
408    * Bean property setter:  <property>collectionFormat</property>.
409    *
410    * <p>
411    * Determines the format of the array if type array is used.
412    *
413    * @param value The new value for this property.
414    * @return This object
415    */
416   public SecuritySchemeInfo setOpenIdConnectUrl(String value) {
417      openIdConnectUrl = value;
418      return this;
419   }
420
421   // <FluentSetters>
422
423   // </FluentSetters>
424
425   @Override /* SwaggerElement */
426   public <T> T get(String property, Class<T> type) {
427      if (property == null)
428         return null;
429      switch (property) {
430         case "name": return toType(getName(), type);
431         case "in": return toType(getIn(), type);
432         case "description": return toType(getDescription(), type);
433         case "scheme": return toType(getScheme(), type);
434         case "flows": return toType(getFlows(), type);
435         case "bearerFormat": return toType(getBearerFormat(), type);
436         case "openIdConnectUrl": return toType(getOpenIdConnectUrl(), type);
437         case "type": return toType(getType(), type);
438         default: return super.get(property, type);
439      }
440   }
441
442   @Override /* SwaggerElement */
443   public SecuritySchemeInfo set(String property, Object value) {
444      if (property == null)
445         return this;
446      switch (property) {
447         case "name": return setName(stringify(value));
448         case "in": return setIn(stringify(value));
449         case "description": return setDescription(stringify(value));
450         case "scheme": return setScheme(stringify(value));
451         case "bearerFormat": return setBearerFormat(stringify(value));
452         case "type": return setType(stringify(value));
453         case "flows": return setFlows(toType(value, OAuthFlow.class));
454         case "openIdConnectUrl": return setOpenIdConnectUrl(stringify(value));
455         default:
456            super.set(property, value);
457            return this;
458      }
459   }
460
461   @Override /* SwaggerElement */
462   public Set<String> keySet() {
463      Set<String> s = setBuilder(String.class)
464         .addIf(name != null, "name")
465         .addIf(in != null, "in")
466         .addIf(description != null, "description")
467         .addIf(scheme != null, "scheme")
468         .addIf(bearerFormat != null, "bearerFormat")
469         .addIf(type != null, "type")
470         .addIf(flows != null, "flows")
471         .addIf(openIdConnectUrl != null, "openIdConnectUrl")
472         .build();
473      return new MultiSet<>(s, super.keySet());
474   }
475
476}