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