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.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. This can be
034 * used to provide additional documentation that is not part of the main OpenAPI specification, such as detailed
035 * guides, tutorials, or API documentation hosted elsewhere.
036 *
037 * <h5 class='section'>OpenAPI 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 (CommonMark syntax may be used)
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>// Create external documentation reference</jc>
048 *    ExternalDocumentation <jv>docs</jv> = <jk>new</jk> ExternalDocumentation()
049 *       .setDescription(<js>"Find more info here"</js>)
050 *       .setUrl(<js>"https://example.com"</js>);
051 * </p>
052 *
053 * <h5 class='section'>See Also:</h5><ul>
054 *    <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#external-documentation-object">OpenAPI Specification &gt; External Documentation Object</a>
055 *    <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/external-documentation/">OpenAPI External Documentation</a>
056 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a>
057 * </ul>
058 */
059@SuppressWarnings({
060   "java:S1192" // Duplicated literals (property names) read more clearly inline than as constants
061})
062public class ExternalDocumentation extends OpenApiElement {
063
064   private String description;
065   private URI url;
066
067   /**
068    * Default constructor.
069    */
070   public ExternalDocumentation() {}
071
072   /**
073    * Copy constructor.
074    *
075    * @param copyFrom The object to copy.
076    */
077   public ExternalDocumentation(ExternalDocumentation copyFrom) {
078      super(copyFrom);
079
080      this.description = copyFrom.description;
081      this.url = copyFrom.url;
082   }
083
084   /**
085    * Make a deep copy of this object.
086    *
087    * @return A deep copy of this object.
088    */
089   public ExternalDocumentation copy() {
090      return new ExternalDocumentation(this);
091   }
092
093   @Override /* Overridden from OpenApiElement */
094   public <T> T get(String property, Class<T> type) {
095      reqnn("property", property);
096      return switch (property) {
097         case "description" -> toType(getDescription(), type);
098         case "url" -> toType(getUrl(), type);
099         default -> super.get(property, type);
100      };
101   }
102
103   /**
104    * Bean property getter:  <property>description</property>.
105    *
106    * <p>
107    * A short description of the target documentation.
108    *
109    * @return The property value, or <jk>null</jk> if it is not set.
110    */
111   public String getDescription() { return description; }
112
113   /**
114    * Bean property getter:  <property>url</property>.
115    *
116    * <p>
117    * The URL for the target documentation.
118    *
119    * @return The property value, or <jk>null</jk> if it is not set.
120    */
121   public URI getUrl() { return url; }
122
123   @Override /* Overridden from OpenApiElement */
124   public Set<String> keySet() {
125      // @formatter:off
126      var s = stb(String.class)
127         .addIf(nn(description), "description")
128         .addIf(nn(url), "url")
129         .build();
130      // @formatter:on
131      return new MultiSet<>(s, super.keySet());
132   }
133
134   @Override /* Overridden from OpenApiElement */
135   public ExternalDocumentation set(String property, Object value) {
136      reqnn("property", property);
137      return switch (property) {
138         case "description" -> setDescription(s(value));
139         case "url" -> setUrl(toUri(value));
140         default -> {
141            super.set(property, value);
142            yield this;
143         }
144      };
145   }
146
147   /**
148    * Bean property setter:  <property>description</property>.
149    *
150    * <p>
151    * A short description of the target documentation.
152    *
153    * @param value
154    *    The new value for this property.
155    *    <br>Can be <jk>null</jk> to unset the property.
156    * @return This object
157    */
158   public ExternalDocumentation setDescription(String value) {
159      description = value;
160      return this;
161   }
162
163   /**
164    * Bean property setter:  <property>url</property>.
165    *
166    * <p>
167    * The URL for the target documentation.
168    *
169    * @param value
170    *    The new value for this property.
171    *    <br>Property value is required.
172    *    <br>URIs defined by {@link UriResolver} can be used for values.
173    *    <br>Can be <jk>null</jk> to unset the property.
174    * @return This object
175    */
176   public ExternalDocumentation setUrl(URI value) {
177      url = value;
178      return this;
179   }
180
181   @Override /* Overridden from OpenApiElement */
182   public ExternalDocumentation strict() {
183      super.strict();
184      return this;
185   }
186
187   @Override /* Overridden from OpenApiElement */
188   public ExternalDocumentation strict(Object value) {
189      super.strict(value);
190      return this;
191   }
192}