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.StringUtils.*;
22  import static org.apache.juneau.commons.utils.Utils.*;
23  import static org.apache.juneau.internal.ConverterUtils.*;
24  
25  import java.net.*;
26  import java.util.*;
27  
28  import org.apache.juneau.*;
29  import org.apache.juneau.commons.collections.*;
30  
31  /**
32   * An object representing a Server.
33   *
34   * <p>
35   * The Server Object represents a server that provides connectivity information to a target server. This can be used
36   * to specify different servers for different environments (e.g., development, staging, production) or to provide
37   * server-specific configuration such as variables for templating.
38   *
39   * <h5 class='section'>OpenAPI Specification:</h5>
40   * <p>
41   * The Server Object is composed of the following fields:
42   * <ul class='spaced-list'>
43   * 	<li><c>url</c> (string, REQUIRED) - A URL to the target host. This URL supports Server Variables and may be relative
44   * 	<li><c>description</c> (string) - An optional string describing the host designated by the URL (CommonMark syntax may be used)
45   * 	<li><c>variables</c> (map of {@link ServerVariable}) - A map between a variable name and its value
46   * </ul>
47   *
48   * <h5 class='section'>Example:</h5>
49   * <p class='bjava'>
50   * 	<jc>// Create a server with variables</jc>
51   * 	Server <jv>server</jv> = <jk>new</jk> Server()
52   * 		.setUrl(<js>"https://{username}.gigantic-server.com:{port}/{basePath}"</js>)
53   * 		.setDescription(<js>"The production API server"</js>)
54   * 		.setVariables(
55   * 			JsonMap.<jsm>of</jsm>(
56   * 				<js>"username"</js>, <jk>new</jk> ServerVariable()
57   * 					.setDefault(<js>"demo"</js>)
58   * 					.setDescription(<js>"this value is assigned by the service provider"</js>),
59   * 				<js>"port"</js>, <jk>new</jk> ServerVariable()
60   * 					.setDefault(<js>"8443"</js>)
61   * 					.setEnum(<js>"8443"</js>, <js>"443"</js>),
62   * 				<js>"basePath"</js>, <jk>new</jk> ServerVariable()
63   * 					.setDefault(<js>"v2"</js>)
64   * 			)
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-object">OpenAPI Specification &gt; Server 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 Server extends OpenApiElement {
75  	private URI url;
76  	private String description;
77  	private Map<String,ServerVariable> variables = map();
78  
79  	/**
80  	 * Default constructor.
81  	 */
82  	public Server() {}
83  
84  	/**
85  	 * Copy constructor.
86  	 *
87  	 * @param copyFrom The object to copy.
88  	 */
89  	public Server(Server copyFrom) {
90  		super(copyFrom);
91  
92  		this.url = copyFrom.url;
93  		this.description = copyFrom.description;
94  		if (nn(copyFrom.variables))
95  			variables.putAll(copyOf(copyFrom.variables, ServerVariable::copy));
96  	}
97  
98  	/**
99  	 * Adds one or more values to the <property>variables</property> property.
100 	 *
101 	 * @param key The mapping key.  Must not be <jk>null</jk>.
102 	 * @param value
103 	 * 	The values to add to this property.
104 	 * 	<br>Must not be <jk>null</jk>.
105 	 * 	<br>Ignored if <jk>null</jk>.
106 	 * @return This object
107 	 */
108 	public Server addVariable(String key, ServerVariable value) {
109 		assertArgNotNull("key", key);
110 		assertArgNotNull("value", value);
111 		variables.put(key, value);
112 		return this;
113 	}
114 
115 	/**
116 	 * Make a deep copy of this object.
117 	 *
118 	 * @return A deep copy of this object.
119 	 */
120 	public Server copy() {
121 		return new Server(this);
122 	}
123 
124 	@Override /* Overridden from OpenApiElement */
125 	public <T> T get(String property, Class<T> type) {
126 		assertArgNotNull("property", property);
127 		return switch (property) {
128 			case "url" -> toType(getUrl(), type);
129 			case "description" -> toType(getDescription(), type);
130 			case "variables" -> toType(getVariables(), type);
131 			default -> super.get(property, type);
132 		};
133 	}
134 
135 	/**
136 	 * Bean property getter:  <property>description</property>.
137 	 *
138 	 * @return The property value, or <jk>null</jk> if it is not set.
139 	 */
140 	public String getDescription() { return description; }
141 
142 	/**
143 	 * Bean property getter:  <property>url</property>.
144 	 *
145 	 * <p>
146 	 * The URL pointing to the contact information.
147 	 *
148 	 * @return The property value, or <jk>null</jk> if it is not set.
149 	 */
150 	public URI getUrl() { return url; }
151 
152 	/**
153 	 * Bean property getter:  <property>variables</property>.
154 	 *
155 	 * @return The property value, or <jk>null</jk> if it is not set.
156 	 */
157 	public Map<String,ServerVariable> getVariables() { return nullIfEmpty(variables); }
158 
159 	@Override /* Overridden from OpenApiElement */
160 	public Set<String> keySet() {
161 		// @formatter:off
162 		var s = setb(String.class)
163 			.addIf(nn(description), "description")
164 			.addIf(nn(url), "url")
165 			.addIf(ne(variables), "variables")
166 			.build();
167 		// @formatter:on
168 		return new MultiSet<>(s, super.keySet());
169 	}
170 
171 	@Override /* Overridden from OpenApiElement */
172 	public Server set(String property, Object value) {
173 		assertArgNotNull("property", property);
174 		return switch (property) {
175 			case "description" -> setDescription(s(value));
176 			case "url" -> setUrl(toUri(value));
177 			case "variables" -> setVariables(toMapBuilder(value, String.class, ServerVariable.class).sparse().build());
178 			default -> {
179 				super.set(property, value);
180 				yield this;
181 			}
182 		};
183 	}
184 
185 	/**
186 	 * Bean property setter:  <property>description</property>.
187 	 *
188 	 * @param value
189 	 * 	The new value for this property.
190 	 * 	<br>Can be <jk>null</jk> to unset the property.
191 	 * @return This object
192 	 */
193 	public Server setDescription(String value) {
194 		description = value;
195 		return this;
196 	}
197 
198 	/**
199 	 * Bean property setter:  <property>url</property>.
200 	 *
201 	 * <p>
202 	 * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}.
203 	 * <br>Strings must be valid URIs.
204 	 *
205 	 * <p>
206 	 * URIs defined by {@link UriResolver} can be used for values.
207 	 *
208 	 * @param value
209 	 * 	The new value for this property.
210 	 * 	<br>Can be <jk>null</jk> to unset the property.
211 	 * @return This object
212 	 */
213 	public Server setUrl(URI value) {
214 		url = value;
215 		return this;
216 	}
217 
218 	/**
219 	 * Bean property setter:  <property>variables</property>.
220 	 *
221 	 * @param value
222 	 * 	The new value for this property.
223 	 * 	<br>Can be <jk>null</jk> to unset the property.
224 	 * @return This object
225 	 */
226 	public Server setVariables(Map<String,ServerVariable> value) {
227 		variables.clear();
228 		if (nn(value))
229 			variables.putAll(value);
230 		return this;
231 	}
232 
233 	@Override /* Overridden from OpenApiElement */
234 	public Server strict(Object value) {
235 		super.strict(value);
236 		return this;
237 	}
238 
239 	@Override /* Overridden from OpenApiElement */
240 	protected Server strict() {
241 		super.strict();
242 		return this;
243 	}
244 }