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.swagger;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020import static org.apache.juneau.commons.utils.StringUtils.*;
021import static org.apache.juneau.marshall.internal.ConverterUtils.*;
022
023import java.net.*;
024import java.util.*;
025
026import org.apache.juneau.commons.collections.*;
027import org.apache.juneau.marshall.*;
028
029/**
030 * Allows referencing an external resource for extended documentation.
031 *
032 * <p>
033 * The External Documentation Object allows referencing an external resource for extended documentation in Swagger 2.0.
034 * This can be used to provide additional documentation that is not part of the main Swagger specification, such as
035 * detailed guides, tutorials, or API documentation hosted elsewhere.
036 *
037 * <h5 class='section'>Swagger Specification:</h5>
038 * <p>
039 * The External Documentation Object is composed of the following fields:
040 * <ul class='spaced-list'>
041 *    <li><c>description</c> (string) - A short description of the target documentation
042 *    <li><c>url</c> (string, REQUIRED) - The URL for the target documentation
043 * </ul>
044 *
045 * <h5 class='section'>Example:</h5>
046 * <p class='bjava'>
047 *    <jc>// Construct using SwaggerBuilder.</jc>
048 *    ExternalDocumentation <jv>extDoc</jv> = <jsm>externalDocumentation</jsm>(<js>"https://swagger.io"</js>, <js>"Find more info here"</js>);
049 *
050 *    <jc>// Serialize using JsonSerializer.</jc>
051 *    String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>extDoc</jv>);
052 *
053 *    <jc>// Or just use toString() which does the same as above.</jc>
054 *    <jv>json</jv> = <jv>extDoc</jv>.toString();
055 * </p>
056 * <p class='bjson'>
057 *    <jc>// Output</jc>
058 *    {
059 *       <js>"description"</js>: <js>"Find more info here"</js>,
060 *       <js>"url"</js>: <js>"https://swagger.io"</js>
061 *    }
062 * </p>
063 *
064 * <h5 class='section'>See Also:</h5><ul>
065 *    <li class='link'><a class="doclink" href="https://swagger.io/specification/v2/#external-documentation-object">Swagger 2.0 Specification &gt; External Documentation Object</a>
066 *    <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/2-0/external-documentation/">Swagger External Documentation</a>
067 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a>
068 * </ul>
069 */
070@SuppressWarnings({
071   "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants
072})
073public class ExternalDocumentation extends SwaggerElement {
074
075   private String description;
076   private URI url;
077
078   /**
079    * Default constructor.
080    */
081   public ExternalDocumentation() {}
082
083   /**
084    * Copy constructor.
085    *
086    * @param copyFrom The object to copy.
087    */
088   public ExternalDocumentation(ExternalDocumentation copyFrom) {
089      super(copyFrom);
090
091      this.description = copyFrom.description;
092      this.url = copyFrom.url;
093   }
094
095   /**
096    * Make a deep copy of this object.
097    *
098    * @return A deep copy of this object.
099    */
100   public ExternalDocumentation copy() {
101      return new ExternalDocumentation(this);
102   }
103
104   @Override /* Overridden from SwaggerElement */
105   public <T> T get(String property, Class<T> type) {
106      reqnn("property", property);
107      return switch (property) {
108         case "description" -> toType(getDescription(), type);
109         case "url" -> toType(getUrl(), type);
110         default -> super.get(property, type);
111      };
112   }
113
114   /**
115    * Bean property getter:  <property>description</property>.
116    *
117    * <p>
118    * A short description of the target documentation.
119    *
120    * @return The property value, or <jk>null</jk> if it is not set.
121    */
122   public String getDescription() { return description; }
123
124   /**
125    * Bean property getter:  <property>url</property>.
126    *
127    * <p>
128    * The URL for the target documentation.
129    *
130    * @return The property value, or <jk>null</jk> if it is not set.
131    */
132   public URI getUrl() { return url; }
133
134   @Override /* Overridden from SwaggerElement */
135   public Set<String> keySet() {
136      // @formatter:off
137      var s = stb(String.class)
138         .addIf(nn(description), "description")
139         .addIf(nn(url), "url")
140         .build();
141      // @formatter:on
142      return new MultiSet<>(s, super.keySet());
143   }
144
145   @Override /* Overridden from SwaggerElement */
146   public ExternalDocumentation set(String property, Object value) {
147      reqnn("property", property);
148      return switch (property) {
149         case "description" -> setDescription(s(value));
150         case "url" -> setUrl(toUri(value));
151         default -> {
152            super.set(property, value);
153            yield this;
154         }
155      };
156   }
157
158   /**
159    * Bean property setter:  <property>description</property>.
160    *
161    * <p>
162    * A short description of the target documentation.
163    *
164    * @param value
165    *    The new value for this property.
166    *    <br><a class="doclink" href="https://help.github.com/articles/github-flavored-markdown">GFM syntax</a> can be used for rich text representation.
167    *    <br>Can be <jk>null</jk> to unset the property.
168    * @return This object.
169    */
170   public ExternalDocumentation setDescription(String value) {
171      description = value;
172      return this;
173   }
174
175   /**
176    * Bean property setter:  <property>url</property>.
177    *
178    * <p>
179    * The URL for the target documentation.
180    *
181    * @param value
182    *    The new value for this property.
183    *    <br>Property value is required.
184    *    <br>URIs defined by {@link UriResolver} can be used for values.
185    *    <br>Can be <jk>null</jk> to unset the property.
186    * @return This object.
187    */
188   public ExternalDocumentation setUrl(URI value) {
189      url = value;
190      return this;
191   }
192
193   /**
194    * Sets strict mode on this bean.
195    *
196    * @return This object.
197    */
198   @Override
199   public ExternalDocumentation strict() {
200      super.strict();
201      return this;
202   }
203
204   /**
205    * Sets strict mode on this bean.
206    *
207    * @param value
208    *    The new value for this property.
209    *    <br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
210    *    <br>Can be <jk>null</jk> (interpreted as <jk>false</jk>).
211    * @return This object.
212    */
213   @Override
214   public ExternalDocumentation strict(Object value) {
215      super.strict(value);
216      return this;
217   }
218}