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 * 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 title, description, termsOfService, version;
104   private Contact contact;
105   private License license;
106
107   /**
108    * Default constructor.
109    */
110   public Info() {}
111
112   /**
113    * Copy constructor.
114    *
115    * @param copyFrom The object to copy.
116    */
117   public Info(Info copyFrom) {
118      super(copyFrom);
119
120      this.title = copyFrom.title;
121      this.description = copyFrom.description;
122      this.termsOfService = copyFrom.termsOfService;
123      this.version = copyFrom.version;
124      this.contact = copyFrom.contact == null ? null : copyFrom.contact.copy();
125      this.license = copyFrom.license == null ? null : copyFrom.license.copy();
126   }
127
128   /**
129    * Make a deep copy of this object.
130    *
131    * @return A deep copy of this object.
132    */
133   public Info copy() {
134      return new Info(this);
135   }
136
137   @Override /* Overridden from OpenApiElement */
138   public <T> T get(String property, Class<T> type) {
139      assertArgNotNull("property", property);
140      return switch (property) {
141         case "title" -> toType(getTitle(), type);
142         case "description" -> toType(getDescription(), type);
143         case "termsOfService" -> toType(getTermsOfService(), type);
144         case "contact" -> toType(getContact(), type);
145         case "license" -> toType(getLicense(), type);
146         case "version" -> toType(getVersion(), type);
147         default -> super.get(property, type);
148      };
149   }
150
151   /**
152    * Bean property getter:  <property>contact</property>.
153    *
154    * <p>
155    * The contact information for the exposed API.
156    *
157    * @return The property value, or <jk>null</jk> if it is not set.
158    */
159   public Contact getContact() { return contact; }
160
161   /**
162    * Bean property getter:  <property>description</property>.
163    *
164    * <p>
165    * A short description of the application.
166    *
167    * @return The property value, or <jk>null</jk> if it is not set.
168    */
169   public String getDescription() { return description; }
170
171   /**
172    * Bean property getter:  <property>license</property>.
173    *
174    * <p>
175    * The license information for the exposed API.
176    *
177    * @return The property value, or <jk>null</jk> if it is not set.
178    */
179   public License getLicense() { return license; }
180
181   /**
182    * Bean property getter:  <property>termsOfService</property>.
183    *
184    * <p>
185    * The Terms of Service for the API.
186    *
187    * @return The property value, or <jk>null</jk> if it is not set.
188    */
189   public String getTermsOfService() { return termsOfService; }
190
191   /**
192    * Bean property getter:  <property>title</property>.
193    *
194    * <p>
195    * The title of the application.
196    *
197    * @return The property value, or <jk>null</jk> if it is not set.
198    */
199   public String getTitle() { return title; }
200
201   /**
202    * Bean property getter:  <property>version</property>.
203    *
204    * <p>
205    * Provides the version of the application API (not to be confused with the specification version).
206    *
207    * @return The property value, or <jk>null</jk> if it is not set.
208    */
209   public String getVersion() { return version; }
210
211   @Override /* Overridden from OpenApiElement */
212   public Set<String> keySet() {
213      // @formatter:off
214      var s = setb(String.class)
215         .addIf(nn(contact), "contact")
216         .addIf(nn(description), "description")
217         .addIf(nn(license), "license")
218         .addIf(nn(termsOfService), "termsOfService")
219         .addIf(nn(title), "title")
220         .addIf(nn(version), "version")
221         .build();
222      // @formatter:on
223      return new MultiSet<>(s, super.keySet());
224   }
225
226   @Override /* Overridden from OpenApiElement */
227   public Info set(String property, Object value) {
228      assertArgNotNull("property", property);
229      return switch (property) {
230         case "contact" -> setContact(toType(value, Contact.class));
231         case "description" -> setDescription(s(value));
232         case "license" -> setLicense(toType(value, License.class));
233         case "termsOfService" -> setTermsOfService(s(value));
234         case "title" -> setTitle(s(value));
235         case "version" -> setVersion(s(value));
236         default -> {
237            super.set(property, value);
238            yield this;
239         }
240      };
241   }
242
243   /**
244    * Bean property setter:  <property>contact</property>.
245    *
246    * <p>
247    * The contact information for the exposed API.
248    *
249    * @param value
250    *    The new value for this property.
251    *    <br>Can be <jk>null</jk> to unset the property.
252    * @return This object
253    */
254   public Info setContact(Contact value) {
255      contact = value;
256      return this;
257   }
258
259   /**
260    * Bean property setter:  <property>description</property>.
261    *
262    * <p>
263    * A short description of the application.
264    *
265    * @param value
266    *    The new value for this property.
267    *    <br>Can be <jk>null</jk> to unset the property.
268    * @return This object
269    */
270   public Info setDescription(String value) {
271      description = value;
272      return this;
273   }
274
275   /**
276    * Bean property setter:  <property>license</property>.
277    *
278    * <p>
279    * The license information for the exposed API.
280    *
281    * @param value
282    *    The new value for this property.
283    *    <br>Can be <jk>null</jk> to unset the property.
284    * @return This object
285    */
286   public Info setLicense(License value) {
287      license = value;
288      return this;
289   }
290
291   /**
292    * Bean property setter:  <property>termsOfService</property>.
293    *
294    * <p>
295    * The Terms of Service for the API.
296    *
297    * @param value
298    *    The new value for this property.
299    *    <br>Can be <jk>null</jk> to unset the property.
300    * @return This object
301    */
302   public Info setTermsOfService(String value) {
303      termsOfService = value;
304      return this;
305   }
306
307   /**
308    * Bean property setter:  <property>title</property>.
309    *
310    * <p>
311    * The title of the application.
312    *
313    * @param value
314    *    The new value for this property.
315    *    <br>Property value is required.
316    *    <br>Can be <jk>null</jk> to unset the property.
317    * @return This object
318    */
319   public Info setTitle(String value) {
320      title = value;
321      return this;
322   }
323
324   /**
325    * Bean property setter:  <property>version</property>.
326    *
327    * <p>
328    * Provides the version of the application API (not to be confused with the specification version).
329    *
330    * @param value
331    *    The new value for this property.
332    *    <br>Property value is required.
333    *    <br>Can be <jk>null</jk> to unset the property.
334    * @return This object
335    */
336   public Info setVersion(String value) {
337      version = value;
338      return this;
339   }
340
341   @Override /* Overridden from OpenApiElement */
342   public Info strict() {
343      super.strict();
344      return this;
345   }
346
347   @Override /* Overridden from OpenApiElement */
348   public Info strict(Object value) {
349      super.strict(value);
350      return this;
351   }
352}