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