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