View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.bean.openapi3;
18  
19  import static org.apache.juneau.commons.utils.AssertionUtils.*;
20  import static org.apache.juneau.commons.utils.CollectionUtils.*;
21  import static org.apache.juneau.commons.utils.Utils.*;
22  import static org.apache.juneau.internal.ConverterUtils.*;
23  
24  import java.util.*;
25  
26  import org.apache.juneau.commons.collections.*;
27  
28  /**
29   * TODO
30   *
31   * <p>
32   * The ServerVariable Object represents a server variable for server URL template substitution. Server variables can be
33   * used to define different server environments (e.g., development, staging, production) with different base URLs,
34   * ports, or other variable parts of the server URL.
35   *
36   * <h5 class='section'>OpenAPI Specification:</h5>
37   * <p>
38   * The ServerVariable Object is composed of the following fields:
39   * <ul class='spaced-list'>
40   * 	<li><c>enum</c> (array of any) - An enumeration of string values to be used if the substitution options are from a limited set
41   * 	<li><c>default</c> (string, REQUIRED) - The default value to use for substitution, which SHALL be sent if an alternate value is not supplied
42   * 	<li><c>description</c> (string) - An optional description for the server variable. CommonMark syntax MAY be used for rich text representation
43   * </ul>
44   *
45   * <h5 class='section'>Example:</h5>
46   * <p class='bcode'>
47   * 	<jc>// Construct using SwaggerBuilder.</jc>
48   * 	ServerVariable <jv>x</jv> = <jsm>serverVariable</jsm>()
49   * 		.setDefault(<js>"api"</js>)
50   * 		.setEnum(<js>"api"</js>, <js>"staging"</js>, <js>"dev"</js>)
51   * 		.setDescription(<js>"Environment to use"</js>);
52   *
53   * 	<jc>// Serialize using JsonSerializer.</jc>
54   * 	String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>x</jv>);
55   *
56   * 	<jc>// Or just use toString() which does the same as above.</jc>
57   * 	<jv>json</jv> = <jv>x</jv>.toString();
58   * </p>
59   * <p class='bcode'>
60   * 	<jc>// Output</jc>
61   * 	{
62   * 		<js>"default"</js>: <js>"api"</js>,
63   * 		<js>"enum"</js>: [<js>"api"</js>, <js>"staging"</js>, <js>"dev"</js>],
64   * 		<js>"description"</js>: <js>"Environment to use"</js>
65   * 	}
66   * </p>
67   *
68   * <h5 class='section'>See Also:</h5><ul>
69   * 	<li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#server-variable-object">OpenAPI Specification &gt; Server Variable Object</a>
70   * 	<li class='link'><a class="doclink" href="https://swagger.io/docs/specification/api-host-and-base-path/">OpenAPI API Host and Base Path</a>
71   * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a>
72   * </ul>
73   */
74  public class ServerVariable extends OpenApiElement {
75  
76  	private List<Object> enum_ = list();
77  	private String default_;
78  	private String description;
79  
80  	/**
81  	 * Default constructor.
82  	 */
83  	public ServerVariable() {}
84  
85  	/**
86  	 * Copy constructor.
87  	 *
88  	 * @param copyFrom The object to copy.
89  	 */
90  	public ServerVariable(ServerVariable copyFrom) {
91  		super(copyFrom);
92  
93  		if (nn(copyFrom.enum_))
94  			this.enum_.addAll(copyOf(copyFrom.enum_));
95  		this.default_ = copyFrom.default_;
96  		this.description = copyFrom.description;
97  	}
98  
99  	/**
100 	 * Adds one or more values to the <property>enum</property> property.
101 	 *
102 	 * @param values
103 	 * 	The values to add to this property.
104 	 * 	<br>Valid types:
105 	 * 	<ul>
106 	 * 		<li><code>Object</code>
107 	 * 		<li><code>Collection&lt;Object&gt;</code>
108 	 * 		<li><code>String</code> - JSON array representation of <code>Collection&lt;Object&gt;</code>
109 	 * 			<h5 class='figure'>Example:</h5>
110 	 * 			<p class='bcode'>
111 	 * 	enum_(<js>"['foo','bar']"</js>);
112 	 * 			</p>
113 	 * 		<li><code>String</code> - Individual values
114 	 * 			<h5 class='figure'>Example:</h5>
115 	 * 			<p class='bcode'>
116 	 * 	enum_(<js>"foo"</js>, <js>"bar"</js>);
117 	 * 			</p>
118 	 * 	</ul>
119 	 * 	<br>Ignored if <jk>null</jk>.
120 	 * @return This object
121 	 */
122 	public ServerVariable addEnum(Object...values) {
123 		if (nn(values))
124 			for (var v : values)
125 				if (nn(v))
126 					enum_.add(v);
127 		return this;
128 	}
129 
130 	/**
131 	 * Make a deep copy of this object.
132 	 * @return A deep copy of this object.
133 	 */
134 	public ServerVariable copy() {
135 		return new ServerVariable(this);
136 	}
137 
138 	@Override /* Overridden from OpenApiElement */
139 	public <T> T get(String property, Class<T> type) {
140 		assertArgNotNull("property", property);
141 		return switch (property) {
142 			case "enum" -> toType(getEnum(), type);
143 			case "default" -> toType(getDefault(), type);
144 			case "description" -> toType(getDescription(), type);
145 			default -> super.get(property, type);
146 		};
147 	}
148 
149 	/**
150 	 * Bean property getter:  <property>default</property>.
151 	 *
152 	 * <p>
153 	 * Declares the value of the item that the server will use if none is provided.
154 	 *
155 	 * <h5 class='section'>Notes:</h5>
156 	 * <ul class='spaced-list'>
157 	 * 	<li>
158 	 * 		<js>"default"</js> has no meaning for required items.
159 	 * 	<li>
160 	 * 		Unlike JSON Schema this value MUST conform to the defined <code>type</code> for the data type.
161 	 * </ul>
162 	 *
163 	 * @return The property value, or <jk>null</jk> if it is not set.
164 	 */
165 	public String getDefault() { return default_; }
166 
167 	/**
168 	 * Bean property getter:  <property>description</property>.
169 	 *
170 	 * <p>
171 	 * Declares the value of the item that the server will use if none is provided.
172 	 *
173 	 * <h5 class='section'>Notes:</h5>
174 	 * <ul class='spaced-list'>
175 	 * 	<li>
176 	 * 		<js>"description"</js> has no meaning for required items.
177 	 * 	<li>
178 	 * 		Unlike JSON Schema this value MUST conform to the defined <code>type</code> for the data type.
179 	 * </ul>
180 	 *
181 	 * @return The property value, or <jk>null</jk> if it is not set.
182 	 */
183 	public String getDescription() { return description; }
184 
185 	/**
186 	 * Bean property getter:  <property>enum</property>.
187 	 *
188 	 * @return The property value, or <jk>null</jk> if it is not set.
189 	 */
190 	public List<Object> getEnum() { return nullIfEmpty(enum_); }
191 
192 	@Override /* Overridden from OpenApiElement */
193 	public Set<String> keySet() {
194 		// @formatter:off
195 		var s = setb(String.class)
196 			.addIf(nn(default_),"default" )
197 			.addIf(nn(description), "description")
198 			.addIf(ne(enum_), "enum")
199 			.build();
200 		// @formatter:on
201 		return new MultiSet<>(s, super.keySet());
202 	}
203 
204 	@Override /* Overridden from OpenApiElement */
205 	public ServerVariable set(String property, Object value) {
206 		assertArgNotNull("property", property);
207 		return switch (property) {
208 			case "default" -> setDefault(s(value));
209 			case "description" -> setDescription(s(value));
210 			case "enum" -> setEnum(listb(Object.class).addAny(value).sparse().build());
211 			default -> {
212 				super.set(property, value);
213 				yield this;
214 			}
215 		};
216 	}
217 
218 	/**
219 	 * Bean property setter:  <property>default</property>.
220 	 *
221 	 * <p>
222 	 * Declares the value of the item that the server will use if none is provided.
223 	 *
224 	 * <h5 class='section'>Notes:</h5>
225 	 * <ul class='spaced-list'>
226 	 * 	<li>
227 	 * 		<js>"default"</js> has no meaning for required items.
228 	 * 	<li>
229 	 * 		Unlike JSON Schema this value MUST conform to the defined <code>type</code> for the data type.
230 	 * </ul>
231 	 *
232 	 * @param value
233 	 * 	The new value for this property.
234 	 * 	<br>Can be <jk>null</jk> to unset the property.
235 	 * @return This object
236 	 */
237 	public ServerVariable setDefault(String value) {
238 		default_ = value;
239 		return this;
240 	}
241 
242 	/**
243 	 * Bean property setter:  <property>description</property>.
244 	 *
245 	 * <p>
246 	 * Declares the value of the item that the server will use if none is provided.
247 	 *
248 	 * <h5 class='section'>Notes:</h5>
249 	 * <ul class='spaced-list'>
250 	 * 	<li>
251 	 * 		<js>"description"</js> has no meaning for required items.
252 	 * 	<li>
253 	 * 		Unlike JSON Schema this value MUST conform to the defined <code>type</code> for the data type.
254 	 * </ul>
255 	 *
256 	 * @param value
257 	 * 	The new value for this property.
258 	 * 	<br>Can be <jk>null</jk> to unset the property.
259 	 * @return This object
260 	 */
261 	public ServerVariable setDescription(String value) {
262 		description = value;
263 		return this;
264 	}
265 
266 	/**
267 	 * Bean property setter:  <property>enum</property>.
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 ServerVariable setEnum(Collection<Object> value) {
275 		enum_.clear();
276 		if (nn(value))
277 			enum_.addAll(value);
278 		return this;
279 	}
280 
281 	@Override /* Overridden from OpenApiElement */
282 	public ServerVariable strict(Object value) {
283 		super.strict(value);
284 		return this;
285 	}
286 
287 	@Override /* Overridden from OpenApiElement */
288 	protected ServerVariable strict() {
289 		super.strict();
290 		return this;
291 	}
292 }