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.swagger;
014
015import static org.apache.juneau.internal.BeanPropertyUtils.*;
016import java.util.*;
017
018import org.apache.juneau.annotation.*;
019
020/**
021 * Describes a single response from an API Operation.
022 * 
023 * <h5 class='section'>Example:</h5>
024 * <p class='bcode'>
025 *    <jc>// Construct using SwaggerBuilder.</jc>
026 *    ResponseInfo x = <jsm>responseInfo</jsm>(<js>"A complex object array response"</js>)
027 *       .schema(
028 *          <jsm>schemaInfo</jsm>
029 *             .type(<js>"array"</js>)
030 *             .items(
031 *                <jsm>items<jsm>()
032 *                   .set(<js>"$ref"</js>, <js>"#/definitions/VeryComplexType"</js>)
033 *             )
034 *       );
035 * 
036 *    <jc>// Serialize using JsonSerializer.</jc>
037 *    String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x);
038 * 
039 *    <jc>// Or just use toString() which does the same as above.</jc>
040 *    String json = x.toString();
041 * </p>
042 * <p class='bcode'>
043 *    <jc>// Output</jc>
044 *    {
045 *       <js>"description"</js>: <js>"A complex object array response"</js>,
046 *       <js>"schema"</js>: {
047 *          <js>"type"</js>: <js>"array"</js>,
048 *          <js>"items"</js>: {
049 *             <js>"$ref"</js>: <js>"#/definitions/VeryComplexType"</js>
050 *          }
051 *       }
052 *    }
053 * </p>
054 * 
055 * <h5 class='section'>See Also:</h5>
056 * <ul class='doctree'>
057 *    <li class='link'><a class='doclink' href='../../../../../overview-summary.html#juneau-dto.Swagger'>Overview &gt; juneau-dto &gt; Swagger</a>
058 * </ul>
059 */
060@Bean(properties="description,schema,headers,examples,*")
061public class ResponseInfo extends SwaggerElement {
062
063   private String description;
064   private SchemaInfo schema;
065   private Map<String,HeaderInfo> headers;
066   private Map<String,Object> examples;
067
068   /**
069    * Copies any non-null fields from the specified object to this object.
070    * 
071    * @param r 
072    *    The object to copy fields from.
073    *    <br>Can be <jk>null</jk>.
074    * @return This object (for method chaining).
075    */
076   public ResponseInfo copyFrom(ResponseInfo r) {
077      if (r != null) {
078         if (r.description != null)
079            description = r.description;
080         if (r.schema != null)
081            schema = r.schema;
082         if (r.headers != null)
083            headers = r.headers;
084         if (r.examples != null)
085            examples = r.examples;
086      }
087      return this;
088   }
089   
090   /**
091    * Bean property getter:  <property>description</property>.
092    * 
093    * <p>
094    * A short description of the response.
095    * 
096    * @return The property value, or <jk>null</jk> if it is not set.
097    */
098   public String getDescription() {
099      return description;
100   }
101
102   /**
103    * Bean property setter:  <property>description</property>.
104    * 
105    * <p>
106    * A short description of the response.
107    * 
108    * @param value 
109    *    The new value for this property.
110    *    <br><a class="doclink" href="https://help.github.com/articles/github-flavored-markdown">GFM syntax</a> can be used for rich text representation.
111    *    <br>Property value is required.
112    * @return This object (for method chaining).
113    */
114   public ResponseInfo setDescription(String value) {
115      description = value;
116      return this;
117   }
118
119   /**
120    * Same as {@link #setDescription(String)}.
121    * 
122    * @param value
123    *    The new value for this property.
124    *    <br>Non-String values will be converted to String using <code>toString()</code>.
125    *    <br>Can be <jk>null</jk> to unset the property.
126    * @return This object (for method chaining).
127    */
128   public ResponseInfo description(Object value) {
129      return setDescription(toStringVal(value));
130   }
131
132   /**
133    * Bean property getter:  <property>schema</property>.
134    * 
135    * <p>
136    * A definition of the response structure.
137    * 
138    * <h5 class='section'>Notes:</h5>
139    * <ul class='spaced-list'>
140    *    <li>
141    *       If this field does not exist, it means no content is returned as part of the response.
142    *    <li>
143    *       As an extension to the <a class="doclink" href="http://swagger.io/specification/#schemaObject">Schema Object</a>,
144    *       its root type value may also be <js>"file"</js>.
145    *    <li>
146    *       This SHOULD be accompanied by a relevant produces mime-type.
147    * </ul>
148    * 
149    * @return The property value, or <jk>null</jk> if it is not set.
150    */
151   public SchemaInfo getSchema() {
152      return schema;
153   }
154
155   /**
156    * Bean property setter:  <property>schema</property>.
157    * 
158    * <p>
159    * A definition of the response structure.
160    * 
161    * <h5 class='section'>Notes:</h5>
162    * <ul class='spaced-list'>
163    *    <li>
164    *       If this field does not exist, it means no content is returned as part of the response.
165    *    <li>
166    *       As an extension to the <a class="doclink" href="http://swagger.io/specification/#schemaObject">Schema Object</a>,
167    *       its root type value may also be <js>"file"</js>.
168    *    <li>
169    *       This SHOULD be accompanied by a relevant produces mime-type.
170    * </ul>
171    * 
172    * @param value 
173    *    The new value for this property.
174    *    <br>It can be a primitive, an array or an object.
175    *    <br>Can be <jk>null</jk> to unset the property.
176    * @return This object (for method chaining).
177    */
178   public ResponseInfo setSchema(SchemaInfo value) {
179      schema = value;
180      return this;
181   }
182
183   /**
184    * Same as {@link #setSchema(SchemaInfo)}.
185    * 
186    * @param value 
187    *    The new value for this property.
188    *    <br>Valid types:
189    *    <ul>
190    *       <li>{@link SchemaInfo}
191    *       <li><code>String</code> - JSON object representation of {@link SchemaInfo}
192    *          <h5 class='figure'>Example:</h5>
193    *          <p class='bcode'>
194    *    schema(<js>"{type:'type',description:'description',...}"</js>);
195    *          </p>
196    *    </ul>
197    *    <br>Can be <jk>null</jk> to unset the property.
198    * @return This object (for method chaining).
199    */
200   public ResponseInfo schema(Object value) {
201      return setSchema(toType(value, SchemaInfo.class));
202   }
203
204   /**
205    * Bean property getter:  <property>headers</property>.
206    * 
207    * <p>
208    * A list of headers that are sent with the response.
209    * 
210    * @return The property value, or <jk>null</jk> if it is not set.
211    */
212   public Map<String,HeaderInfo> getHeaders() {
213      return headers;
214   }
215
216   /**
217    * Bean property setter:  <property>headers</property>.
218    * 
219    * <p>
220    * A list of headers that are sent with the response.
221    * 
222    * @param value 
223    *    The new value for this property.
224    *    <br>Can be <jk>null</jk> to unset the property.
225    * @return This object (for method chaining).
226    */
227   public ResponseInfo setHeaders(Map<String,HeaderInfo> value) {
228      headers = newMap(value);
229      return this;
230   }
231
232   /**
233    * Adds one or more values to the <property>headers</property> property.
234    * 
235    * @param values
236    *    The values to add to this property.
237    *    <br>Ignored if <jk>null</jk>.
238    * @return This object (for method chaining).
239    */
240   public ResponseInfo addHeaders(Map<String,HeaderInfo> values) {
241      headers = addToMap(headers, values);
242      return this;
243   }
244
245   /**
246    * Adds a single value to the <property>headers</property> property.
247    * 
248    * @param name The header name.
249    * @param header The header descriptions
250    * @return This object (for method chaining).
251    */
252   public ResponseInfo header(String name, HeaderInfo header) {
253      addHeaders(Collections.singletonMap(name, header));
254      return this;
255   }
256
257   /**
258    * Adds one or more values to the <property>headers</property> property.
259    * 
260    * @param values
261    *    The values to add to this property.
262    *    <br>Valid types:
263    *    <ul>
264    *       <li><code>Map&lt;String,{@link HeaderInfo}|String&gt;</code>
265    *       <li><code>String</code> - JSON object representation of <code>Map&lt;String,{@link HeaderInfo}&gt;</code>
266    *          <h5 class='figure'>Example:</h5>
267    *          <p class='bcode'>
268    *    headers(<js>"{headerName:{description:'description',...}}"</js>);
269    *          </p>
270    *    </ul>
271    *    <br>Ignored if <jk>null</jk>.
272    * @return This object (for method chaining).
273    */
274   public ResponseInfo headers(Object...values) {
275      headers = addToMap(headers, values, String.class, HeaderInfo.class);
276      return this;
277   }
278
279   /**
280    * Bean property getter:  <property>examples</property>.
281    * 
282    * <p>
283    * An example of the response message.
284    * 
285    * @return The property value, or <jk>null</jk> if it is not set.
286    */
287   public Map<String,Object> getExamples() {
288      return examples;
289   }
290
291   /**
292    * Bean property setter:  <property>examples</property>.
293    * 
294    * <p>
295    * An example of the response message.
296    * 
297    * @param value 
298    *    The new value for this property.
299    *    <br>Keys must be MIME-type strings.
300    *    <br>Can be <jk>null</jk> to unset the property.
301    * @return This object (for method chaining).
302    */
303   public ResponseInfo setExamples(Map<String,Object> value) {
304      examples = newMap(value);
305      return this;
306   }
307
308   /**
309    * Adds one or more values to the <property>examples</property> property.
310    * 
311    * @param values
312    *    The values to add to this property.
313    *    <br>Ignored if <jk>null</jk>.
314    * @return This object (for method chaining).
315    */
316   public ResponseInfo addExamples(Map<String,Object> values) {
317      examples = addToMap(examples, values);
318      return this;
319   }
320
321   /**
322    * Adds a single value to the <property>examples</property> property.
323    * 
324    * @param mimeType The mime-type string.
325    * @param example The example.
326    * @return This object (for method chaining).
327    */
328   public ResponseInfo example(String mimeType, Object example) {
329      examples = addToMap(examples, mimeType, example);
330      return this;
331   }
332
333   /**
334    * Adds one or more values to the <property>examples</property> property.
335    * 
336    * @param values
337    *    The values to add to this property.
338    *    <br>Valid types:
339    *    <ul>
340    *       <li><code>Map&lt;String,Object&gt;</code>
341    *       <li><code>String</code> - JSON object representation of <code>Map&lt;String,Object&gt;</code>
342    *          <h5 class='figure'>Example:</h5>
343    *          <p class='bcode'>
344    *    examples(<js>"{'text/json':{foo:'bar'}}"</js>);
345    *          </p>
346    *    </ul>
347    *    <br>Ignored if <jk>null</jk>.
348    * @return This object (for method chaining).
349    */
350   public ResponseInfo examples(Object...values) {
351      examples = addToMap(examples, values, String.class, Object.class);
352      return this;
353   }
354
355   @Override /* SwaggerElement */
356   public <T> T get(String property, Class<T> type) {
357      if (property == null)
358         return null;
359      switch (property) {
360         case "description": return toType(getDescription(), type);
361         case "schema": return toType(getSchema(), type);
362         case "headers": return toType(getHeaders(), type);
363         case "examples": return toType(getExamples(), type);
364         default: return super.get(property, type);
365      }
366   }
367
368   @Override /* SwaggerElement */
369   public ResponseInfo set(String property, Object value) {
370      if (property == null)
371         return this;
372      switch (property) {
373         case "description": return description(value);
374         case "schema": return schema(value);
375         case "headers": return setHeaders(null).headers(value);
376         case "examples": return setExamples(null).examples(value);
377         default: 
378            super.set(property, value);
379            return this;
380      }
381   }
382}