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 * An object representing a Server. 033 * 034 * <p> 035 * The Server Object represents a server that provides connectivity information to a target server. This can be used 036 * to specify different servers for different environments (e.g., development, staging, production) or to provide 037 * server-specific configuration such as variables for templating. 038 * 039 * <h5 class='section'>OpenAPI Specification:</h5> 040 * <p> 041 * The Server Object is composed of the following fields: 042 * <ul class='spaced-list'> 043 * <li><c>url</c> (string, REQUIRED) - A URL to the target host. This URL supports Server Variables and may be relative 044 * <li><c>description</c> (string) - An optional string describing the host designated by the URL (CommonMark syntax may be used) 045 * <li><c>variables</c> (map of {@link ServerVariable}) - A map between a variable name and its value 046 * </ul> 047 * 048 * <h5 class='section'>Example:</h5> 049 * <p class='bjava'> 050 * <jc>// Create a server with variables</jc> 051 * Server <jv>server</jv> = <jk>new</jk> Server() 052 * .setUrl(<js>"https://{username}.gigantic-server.com:{port}/{basePath}"</js>) 053 * .setDescription(<js>"The production API server"</js>) 054 * .setVariables( 055 * JsonMap.<jsm>of</jsm>( 056 * <js>"username"</js>, <jk>new</jk> ServerVariable() 057 * .setDefault(<js>"demo"</js>) 058 * .setDescription(<js>"this value is assigned by the service provider"</js>), 059 * <js>"port"</js>, <jk>new</jk> ServerVariable() 060 * .setDefault(<js>"8443"</js>) 061 * .setEnum(<js>"8443"</js>, <js>"443"</js>), 062 * <js>"basePath"</js>, <jk>new</jk> ServerVariable() 063 * .setDefault(<js>"v2"</js>) 064 * ) 065 * ); 066 * </p> 067 * 068 * <h5 class='section'>See Also:</h5><ul> 069 * <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#server-object">OpenAPI Specification > Server Object</a> 070 * <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/api-host-and-base-path/">OpenAPI API Host and Base Path</a> 071 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a> 072 * </ul> 073 */ 074public class Server extends OpenApiElement { 075 private URI url; 076 private String description; 077 private Map<String,ServerVariable> variables = map(); 078 079 /** 080 * Default constructor. 081 */ 082 public Server() {} 083 084 /** 085 * Copy constructor. 086 * 087 * @param copyFrom The object to copy. 088 */ 089 public Server(Server copyFrom) { 090 super(copyFrom); 091 092 this.url = copyFrom.url; 093 this.description = copyFrom.description; 094 if (nn(copyFrom.variables)) 095 variables.putAll(copyOf(copyFrom.variables, ServerVariable::copy)); 096 } 097 098 /** 099 * 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}