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.common.utils.Utils.*;
020import static org.apache.juneau.internal.CollectionUtils.*;
021import static org.apache.juneau.internal.ConverterUtils.*;
022
023import java.util.*;
024
025import org.apache.juneau.common.utils.*;
026import org.apache.juneau.internal.*;
027
028/**
029 * Provides metadata about the API.
030 *
031 * <p>
032 * The Info Object contains required and optional metadata about the API, including the title, version, description, 
033 * terms of service, contact information, and license. This metadata can be used by client tooling and is typically 
034 * displayed in API documentation interfaces.
035 *
036 * <h5 class='section'>OpenAPI Specification:</h5>
037 * <p>
038 * The Info Object is composed of the following fields:
039 * <ul class='spaced-list'>
040 *    <li><c>title</c> (string, REQUIRED) - The title of the API
041 *    <li><c>version</c> (string, REQUIRED) - The version of the OpenAPI document (not the API itself)
042 *    <li><c>description</c> (string) - A short description of the API (CommonMark syntax may be used)
043 *    <li><c>termsOfService</c> (string) - A URL to the Terms of Service for the API
044 *    <li><c>contact</c> ({@link Contact}) - Contact information for the exposed API
045 *    <li><c>license</c> ({@link License}) - License information for the exposed API
046 * </ul>
047 *
048 * <h5 class='section'>Example:</h5>
049 * <p class='bjava'>
050 *    <jc>// Create an Info object</jc>
051 *    Info <jv>info</jv> = <jk>new</jk> Info()
052 *       .setTitle(<js>"Pet Store API"</js>)
053 *       .setVersion(<js>"1.0.0"</js>)
054 *       .setDescription(<js>"This is a sample Pet Store Server based on the OpenAPI 3.0 specification."</js>)
055 *       .setTermsOfService(<js>"http://example.com/terms/"</js>)
056 *       .setContact(
057 *          <jk>new</jk> Contact()
058 *             .setName(<js>"API Support"</js>)
059 *             .setUrl(URI.<jsm>create</jsm>(<js>"http://www.example.com/support"</js>))
060 *             .setEmail(<js>"support@example.com"</js>)
061 *       )
062 *       .setLicense(
063 *          <jk>new</jk> License()
064 *             .setName(<js>"Apache 2.0"</js>)
065 *             .setUrl(URI.<jsm>create</jsm>(<js>"http://www.apache.org/licenses/LICENSE-2.0.html"</js>))
066 *       );
067 * </p>
068 * <p class='bjava'>
069 *    <jc>// Serialize to JSON</jc>
070 *    String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>info</jv>);
071 *
072 *    <jc>// Or just use toString() which does the same as above.</jc>
073 *    <jv>json</jv> = <jv>info</jv>.toString();
074 * </p>
075 * <p class='bcode'>
076 *    <jc>// Output</jc>
077 *    {
078 *       <js>"title"</js>: <js>"Pet Store API"</js>,
079 *       <js>"version"</js>: <js>"1.0.0"</js>,
080 *       <js>"description"</js>: <js>"This is a sample Pet Store Server based on the OpenAPI 3.0 specification."</js>,
081 *       <js>"termsOfService"</js>: <js>"http://example.com/terms/"</js>,
082 *       <js>"contact"</js>: {
083 *          <js>"name"</js>: <js>"API Support"</js>,
084 *          <js>"url"</js>: <js>"http://www.example.com/support"</js>,
085 *          <js>"email"</js>: <js>"support@example.com"</js>
086 *       },
087 *       <js>"license"</js>: {
088 *          <js>"name"</js>: <js>"Apache 2.0"</js>,
089 *          <js>"url"</js>: <js>"http://www.apache.org/licenses/LICENSE-2.0.html"</js>
090 *       },
091 *       <js>"version"</js>: <js>"1.0.1"</js>
092 *    }
093 * </p>
094 *
095 * <h5 class='section'>See Also:</h5><ul>
096 *    <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#info-object">OpenAPI Specification &gt; Info Object</a>
097 *    <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/api-general-info/">OpenAPI API General Info</a>
098 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a>
099 * </ul>
100 */
101public class Info extends OpenApiElement {
102
103   private String
104      title,
105      description,
106      termsOfService,
107      version;
108   private Contact contact;
109   private License license;
110
111   /**
112    * Default constructor.
113    */
114   public Info() {}
115
116   /**
117    * Copy constructor.
118    *
119    * @param copyFrom The object to copy.
120    */
121   public Info(Info copyFrom) {
122      super(copyFrom);
123
124      this.title = copyFrom.title;
125      this.description = copyFrom.description;
126      this.termsOfService = copyFrom.termsOfService;
127      this.version = copyFrom.version;
128      this.contact = copyFrom.contact == null ? null : copyFrom.contact.copy();
129      this.license = copyFrom.license == null ? null : copyFrom.license.copy();
130   }
131
132   /**
133    * Make a deep copy of this object.
134    *
135    * @return A deep copy of this object.
136    */
137   public Info copy() {
138      return new Info(this);
139   }
140
141   /**
142    * Bean property getter:  <property>title</property>.
143    *
144    * <p>
145    * The title of the application.
146    *
147    * @return The property value, or <jk>null</jk> if it is not set.
148    */
149   public String getTitle() {
150      return title;
151   }
152
153   /**
154    * Bean property setter:  <property>title</property>.
155    *
156    * <p>
157    * The title of the application.
158    *
159    * @param value
160    *    The new value for this property.
161    *    <br>Property value is required.
162    *    <br>Can be <jk>null</jk> to unset the property.
163    * @return This object
164    */
165   public Info setTitle(String value) {
166      title = value;
167      return this;
168   }
169
170   /**
171    * Bean property getter:  <property>description</property>.
172    *
173    * <p>
174    * A short description of the application.
175    *
176    * @return The property value, or <jk>null</jk> if it is not set.
177    */
178   public String getDescription() {
179      return description;
180   }
181
182   /**
183    * Bean property setter:  <property>description</property>.
184    *
185    * <p>
186    * A short description of the application.
187    *
188    * @param value
189    *    The new value for this property.
190    *    <br>Can be <jk>null</jk> to unset the property.
191    * @return This object
192    */
193   public Info setDescription(String value) {
194      description = value;
195      return this;
196   }
197
198   /**
199    * Bean property getter:  <property>termsOfService</property>.
200    *
201    * <p>
202    * The Terms of Service for the API.
203    *
204    * @return The property value, or <jk>null</jk> if it is not set.
205    */
206   public String getTermsOfService() {
207      return termsOfService;
208   }
209
210   /**
211    * Bean property setter:  <property>termsOfService</property>.
212    *
213    * <p>
214    * The Terms of Service for the API.
215    *
216    * @param value
217    *    The new value for this property.
218    *    <br>Can be <jk>null</jk> to unset the property.
219    * @return This object
220    */
221   public Info setTermsOfService(String value) {
222      termsOfService = value;
223      return this;
224   }
225
226   /**
227    * Bean property getter:  <property>contact</property>.
228    *
229    * <p>
230    * The contact information for the exposed API.
231    *
232    * @return The property value, or <jk>null</jk> if it is not set.
233    */
234   public Contact getContact() {
235      return contact;
236   }
237
238   /**
239    * Bean property setter:  <property>contact</property>.
240    *
241    * <p>
242    * The contact information for the exposed API.
243    *
244    * @param value
245    *    The new value for this property.
246    *    <br>Can be <jk>null</jk> to unset the property.
247    * @return This object
248    */
249   public Info setContact(Contact value) {
250      contact = value;
251      return this;
252   }
253
254   /**
255    * Bean property getter:  <property>license</property>.
256    *
257    * <p>
258    * The license information for the exposed API.
259    *
260    * @return The property value, or <jk>null</jk> if it is not set.
261    */
262   public License getLicense() {
263      return license;
264   }
265
266   /**
267    * Bean property setter:  <property>license</property>.
268    *
269    * <p>
270    * The license information for the exposed API.
271    *
272    * @param value
273    *    The new value for this property.
274    *    <br>Can be <jk>null</jk> to unset the property.
275    * @return This object
276    */
277   public Info setLicense(License value) {
278      license = value;
279      return this;
280   }
281
282   /**
283    * Bean property getter:  <property>version</property>.
284    *
285    * <p>
286    * Provides the version of the application API (not to be confused with the specification version).
287    *
288    * @return The property value, or <jk>null</jk> if it is not set.
289    */
290   public String getVersion() {
291      return version;
292   }
293
294   /**
295    * Bean property setter:  <property>version</property>.
296    *
297    * <p>
298    * Provides the version of the application API (not to be confused with the specification version).
299    *
300    * @param value
301    *    The new value for this property.
302    *    <br>Property value is required.
303    *    <br>Can be <jk>null</jk> to unset the property.
304    * @return This object
305    */
306   public Info setVersion(String value) {
307      version = value;
308      return this;
309   }
310
311   @Override /* Overridden from OpenApiElement */
312   public <T> T get(String property, Class<T> type) {
313      assertArgNotNull("property", property);
314      return switch (property) {
315         case "title" -> toType(getTitle(), type);
316         case "description" -> toType(getDescription(), type);
317         case "termsOfService" -> toType(getTermsOfService(), type);
318         case "contact" -> toType(getContact(), type);
319         case "license" -> toType(getLicense(), type);
320         case "version" -> toType(getVersion(), type);
321         default -> super.get(property, type);
322      };
323   }
324
325   @Override /* Overridden from OpenApiElement */
326   public Info set(String property, Object value) {
327      assertArgNotNull("property", property);
328      return switch (property) {
329         case "contact" -> setContact(toType(value, Contact.class));
330         case "description" -> setDescription(Utils.s(value));
331         case "license" -> setLicense(toType(value, License.class));
332         case "termsOfService" -> setTermsOfService(Utils.s(value));
333         case "title" -> setTitle(Utils.s(value));
334         case "version" -> setVersion(Utils.s(value));
335         default -> {
336            super.set(property, value);
337            yield this;
338         }
339      };
340   }
341
342   @Override /* Overridden from OpenApiElement */
343   public Set<String> keySet() {
344      var s = setBuilder(String.class)
345         .addIf(contact != null, "contact")
346         .addIf(description != null, "description")
347         .addIf(license != null, "license")
348         .addIf(termsOfService != null, "termsOfService")
349         .addIf(title != null, "title")
350         .addIf(version != null, "version")
351         .build();
352      return new MultiSet<>(s, super.keySet());
353   }
354
355   @Override /* Overridden from OpenApiElement */
356   public Info strict() {
357      super.strict();
358      return this;
359   }
360
361   @Override /* Overridden from OpenApiElement */
362   public Info strict(Object value) {
363      super.strict(value);
364      return this;
365   }
366
367}