001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.bean.openapi3;
018
019import static org.apache.juneau.bean.openapi3.OpenApiCopyUtils.*;
020import static org.apache.juneau.commons.utils.Shorts.*;
021import static org.apache.juneau.marshall.internal.ConverterUtils.*;
022
023import java.util.*;
024
025import org.apache.juneau.commons.collections.*;
026
027/**
028 * Describes the operations available on a single path.
029 *
030 * <p>
031 * The PathItem Object describes the operations available on a single path. A Path Item may be empty, due to ACL
032 * constraints. The path itself is still exposed to the documentation viewer but they will not know which operations
033 * and parameters are available.
034 *
035 * <h5 class='section'>OpenAPI Specification:</h5>
036 * <p>
037 * The PathItem Object is composed of the following fields:
038 * <ul class='spaced-list'>
039 *    <li><c>summary</c> (string) - An optional, string summary, intended to apply to all operations in this path
040 *    <li><c>description</c> (string) - An optional, string description, intended to apply to all operations in this path
041 *    <li><c>get</c> ({@link Operation}) - A definition of a GET operation on this path
042 *    <li><c>put</c> ({@link Operation}) - A definition of a PUT operation on this path
043 *    <li><c>post</c> ({@link Operation}) - A definition of a POST operation on this path
044 *    <li><c>delete</c> ({@link Operation}) - A definition of a DELETE operation on this path
045 *    <li><c>options</c> ({@link Operation}) - A definition of an OPTIONS operation on this path
046 *    <li><c>head</c> ({@link Operation}) - A definition of a HEAD operation on this path
047 *    <li><c>patch</c> ({@link Operation}) - A definition of a PATCH operation on this path
048 *    <li><c>trace</c> ({@link Operation}) - A definition of a TRACE operation on this path
049 *    <li><c>servers</c> (array of {@link Server}) - An alternative server array to service all operations in this path
050 *    <li><c>parameters</c> (array of {@link Parameter}) - A list of parameters that are applicable for all the operations described under this path
051 * </ul>
052 *
053 * <h5 class='section'>Example:</h5>
054 * <p class='bcode'>
055 *    <jc>// Construct using SwaggerBuilder.</jc>
056 *    PathItem <jv>x</jv> = <jsm>pathItem</jsm>()
057 *       .setSummary(<js>"User management"</js>)
058 *       .setGet(<jsm>operation</jsm>().setSummary(<js>"Get users"</js>))
059 *       .setPost(<jsm>operation</jsm>().setSummary(<js>"Create user"</js>));
060 *
061 *    <jc>// Serialize using JsonSerializer.</jc>
062 *    String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>x</jv>);
063 *
064 *    <jc>// Or just use toString() which does the same as above.</jc>
065 *    <jv>json</jv> = <jv>x</jv>.toString();
066 * </p>
067 * <p class='bcode'>
068 *    <jc>// Output</jc>
069 *    {
070 *       <js>"summary"</js>: <js>"User management"</js>,
071 *       <js>"get"</js>: { <js>"summary"</js>: <js>"Get users"</js> },
072 *       <js>"post"</js>: { <js>"summary"</js>: <js>"Create user"</js> }
073 *    }
074 * </p>
075 *
076 * <h5 class='section'>See Also:</h5><ul>
077 *    <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#path-item-object">OpenAPI Specification &gt; Path Item Object</a>
078 *    <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/paths-and-operations/">OpenAPI Paths and Operations</a>
079 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a>
080 * </ul>
081 */
082@SuppressWarnings({
083   "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants
084})
085public class PathItem extends OpenApiElement {
086
087   private String summary;
088   private String description;
089   private Operation get;
090   private Operation put;
091   private Operation post;
092   private Operation delete;
093   private Operation options;
094   private Operation head;
095   private Operation patch;
096   private Operation trace;
097   private List<Server> servers;
098   private List<Parameter> parameters;
099
100   /**
101    * Default constructor.
102    */
103   public PathItem() {}
104
105   /**
106    * Copy constructor.
107    *
108    * @param copyFrom The object to copy.
109    */
110   public PathItem(PathItem copyFrom) {
111      super(copyFrom);
112      this.summary = copyFrom.summary;
113      this.description = copyFrom.description;
114      this.get = copyOf(copyFrom.get);
115      this.put = copyOf(copyFrom.put);
116      this.post = copyOf(copyFrom.post);
117      this.delete = copyOf(copyFrom.delete);
118      this.options = copyOf(copyFrom.options);
119      this.head = copyOf(copyFrom.head);
120      this.patch = copyOf(copyFrom.patch);
121      this.trace = copyOf(copyFrom.trace);
122      this.servers = copyOf(copyFrom.servers, Server::copy);
123      this.parameters = copyOf(copyFrom.parameters, Parameter::copy);
124   }
125
126   /**
127    * Creates a copy of this object.
128    *
129    * @return A copy of this object.
130    */
131   public PathItem copy() {
132      return new PathItem(this);
133   }
134
135   @Override /* Overridden from OpenApiElement */
136   public <T> T get(String property, Class<T> type) {
137      reqnn("property", property);
138      return switch (property) {
139         case "summary" -> toType(getSummary(), type);
140         case "description" -> toType(getDescription(), type);
141         case "get" -> toType(getGet(), type);
142         case "put" -> toType(getPut(), type);
143         case "post" -> toType(getPost(), type);
144         case "delete" -> toType(getDelete(), type);
145         case "options" -> toType(getOptions(), type);
146         case "head" -> toType(getHead(), type);
147         case "patch" -> toType(getPatch(), type);
148         case "trace" -> toType(getTrace(), type);
149         case "servers" -> toType(getServers(), type);
150         case "parameters" -> toType(getParameters(), type);
151         default -> super.get(property, type);
152      };
153   }
154
155   /**
156    * Returns the DELETE operation.
157    *
158    * @return The DELETE operation, or <jk>null</jk> if not set.
159    */
160   public Operation getDelete() { return delete; }
161
162   /**
163    * Returns the description.
164    *
165    * @return The description, or <jk>null</jk> if not set.
166    */
167   public String getDescription() { return description; }
168
169   /**
170    * Returns the GET operation.
171    *
172    * @return The GET operation, or <jk>null</jk> if not set.
173    */
174   public Operation getGet() { return get; }
175
176   /**
177    * Returns the HEAD operation.
178    *
179    * @return The HEAD operation, or <jk>null</jk> if not set.
180    */
181   public Operation getHead() { return head; }
182
183   /**
184    * Returns the OPTIONS operation.
185    *
186    * @return The OPTIONS operation, or <jk>null</jk> if not set.
187    */
188   public Operation getOptions() { return options; }
189
190   /**
191    * Returns the parameters list.
192    *
193    * @return The parameters list, or <jk>null</jk> if not set.
194    */
195   public List<Parameter> getParameters() { return u(parameters); }
196
197   /**
198    * Returns the PATCH operation.
199    *
200    * @return The PATCH operation, or <jk>null</jk> if not set.
201    */
202   public Operation getPatch() { return patch; }
203
204   /**
205    * Returns the POST operation.
206    *
207    * @return The POST operation, or <jk>null</jk> if not set.
208    */
209   public Operation getPost() { return post; }
210
211   /**
212    * Returns the PUT operation.
213    *
214    * @return The PUT operation, or <jk>null</jk> if not set.
215    */
216   public Operation getPut() { return put; }
217
218   /**
219    * Returns the servers list.
220    *
221    * @return The servers list, or <jk>null</jk> if not set.
222    */
223   public List<Server> getServers() { return u(servers); }
224
225   /**
226    * Returns the summary.
227    *
228    * @return The summary, or <jk>null</jk> if not set.
229    */
230   public String getSummary() { return summary; }
231
232   /**
233    * Returns the TRACE operation.
234    *
235    * @return The TRACE operation, or <jk>null</jk> if not set.
236    */
237   public Operation getTrace() { return trace; }
238
239   @Override /* Overridden from OpenApiElement */
240   public Set<String> keySet() {
241      // @formatter:off
242      var s = stb(String.class)
243         .addIf(nn(delete), "delete")
244         .addIf(nn(description), "description")
245         .addIf(nn(get), "get")
246         .addIf(nn(head), "head")
247         .addIf(nn(options), "options")
248         .addIf(nn(parameters), "parameters")
249         .addIf(nn(patch), "patch")
250         .addIf(nn(post), "post")
251         .addIf(nn(put), "put")
252         .addIf(nn(servers), "servers")
253         .addIf(nn(summary), "summary")
254         .addIf(nn(trace), "trace")
255         .build();
256      // @formatter:on
257      return new MultiSet<>(s, super.keySet());
258   }
259
260   @Override /* Overridden from OpenApiElement */
261   public PathItem set(String property, Object value) {
262      reqnn("property", property);
263      return switch (property) {
264         case "delete" -> setDelete(toType(value, Operation.class));
265         case "description" -> setDescription(s(value));
266         case "get" -> setGet(toType(value, Operation.class));
267         case "head" -> setHead(toType(value, Operation.class));
268         case "options" -> setOptions(toType(value, Operation.class));
269         case "patch" -> setPatch(toType(value, Operation.class));
270         case "parameters" -> setParameters(lb(Parameter.class).addAny(value).sparse().build());
271         case "post" -> setPost(toType(value, Operation.class));
272         case "put" -> setPut(toType(value, Operation.class));
273         case "servers" -> setServers(lb(Server.class).addAny(value).sparse().build());
274         case "summary" -> setSummary(s(value));
275         case "trace" -> setTrace(toType(value, Operation.class));
276         default -> {
277            super.set(property, value);
278            yield this;
279         }
280      };
281   }
282
283   /**
284    * Sets the DELETE operation.
285    *
286    * @param value The new value for this property.
287    * @return This object.
288    */
289   public PathItem setDelete(Operation value) {
290      delete = value;
291      return this;
292   }
293
294   /**
295    * Sets the description.
296    *
297    * @param value The new value for this property.
298    * @return This object.
299    */
300   public PathItem setDescription(String value) {
301      description = value;
302      return this;
303   }
304
305   /**
306    * Sets the GET operation.
307    *
308    * @param value The new value for this property.
309    * @return This object.
310    */
311   public PathItem setGet(Operation value) {
312      get = value;
313      return this;
314   }
315
316   /**
317    * Sets the HEAD operation.
318    *
319    * @param value The new value for this property.
320    * @return This object.
321    */
322   public PathItem setHead(Operation value) {
323      head = value;
324      return this;
325   }
326
327   /**
328    * Sets the OPTIONS operation.
329    *
330    * @param value The new value for this property.
331    * @return This object.
332    */
333   public PathItem setOptions(Operation value) {
334      options = value;
335      return this;
336   }
337
338   /**
339    * Sets the parameters list.
340    *
341    * @param value The new value for this property.
342    * @return This object.
343    */
344   public PathItem setParameters(List<Parameter> value) {
345      parameters = value;
346      return this;
347   }
348
349   /**
350    * Sets the PATCH operation.
351    *
352    * @param value The new value for this property.
353    * @return This object.
354    */
355   public PathItem setPatch(Operation value) {
356      patch = value;
357      return this;
358   }
359
360   /**
361    * Sets the POST operation.
362    *
363    * @param value The new value for this property.
364    * @return This object.
365    */
366   public PathItem setPost(Operation value) {
367      post = value;
368      return this;
369   }
370
371   /**
372    * Sets the PUT operation.
373    *
374    * @param value The new value for this property.
375    * @return This object.
376    */
377   public PathItem setPut(Operation value) {
378      put = value;
379      return this;
380   }
381
382   /**
383    * Sets the servers list.
384    *
385    * @param value The new value for this property.
386    * @return This object.
387    */
388   public PathItem setServers(List<Server> value) {
389      servers = value;
390      return this;
391   }
392
393   /**
394    * Sets the summary.
395    *
396    * @param value The new value for this property.
397    * @return This object.
398    */
399   public PathItem setSummary(String value) {
400      summary = value;
401      return this;
402   }
403
404   /**
405    * Sets the TRACE operation.
406    *
407    * @param value The new value for this property.
408    * @return This object.
409    */
410   public PathItem setTrace(Operation value) {
411      trace = value;
412      return this;
413   }
414
415   @Override /* Overridden from OpenApiElement */
416   public PathItem strict() {
417      super.strict();
418      return this;
419   }
420
421   @Override /* Overridden from OpenApiElement */
422   public PathItem strict(Object value) {
423      super.strict(value);
424      return this;
425   }
426}