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.CollectionUtils.*; 020import static org.apache.juneau.commons.utils.Shorts.*; 021import static org.apache.juneau.commons.utils.StringUtils.*; 022import static org.apache.juneau.marshall.internal.ConverterUtils.*; 023 024import java.net.*; 025import java.util.*; 026 027import org.apache.juneau.commons.collections.*; 028import org.apache.juneau.marshall.*; 029 030/** 031 * An object representing a Server. 032 * 033 * <p> 034 * The Server Object represents a server that provides connectivity information to a target server. This can be used 035 * to specify different servers for different environments (e.g., development, staging, production) or to provide 036 * server-specific configuration such as variables for templating. 037 * 038 * <h5 class='section'>OpenAPI Specification:</h5> 039 * <p> 040 * The Server Object is composed of the following fields: 041 * <ul class='spaced-list'> 042 * <li><c>url</c> (string, REQUIRED) - A URL to the target host. This URL supports Server Variables and may be relative 043 * <li><c>description</c> (string) - An optional string describing the host designated by the URL (CommonMark syntax may be used) 044 * <li><c>variables</c> (map of {@link ServerVariable}) - A map between a variable name and its value 045 * </ul> 046 * 047 * <h5 class='section'>Example:</h5> 048 * <p class='bjava'> 049 * <jc>// Create a server with variables</jc> 050 * Server <jv>server</jv> = <jk>new</jk> Server() 051 * .setUrl(<js>"https://{username}.gigantic-server.com:{port}/{basePath}"</js>) 052 * .setDescription(<js>"The production API server"</js>) 053 * .setVariables( 054 * JsonMap.<jsm>of</jsm>( 055 * <js>"username"</js>, <jk>new</jk> ServerVariable() 056 * .setDefault(<js>"demo"</js>) 057 * .setDescription(<js>"this value is assigned by the service provider"</js>), 058 * <js>"port"</js>, <jk>new</jk> ServerVariable() 059 * .setDefault(<js>"8443"</js>) 060 * .setEnum(<js>"8443"</js>, <js>"443"</js>), 061 * <js>"basePath"</js>, <jk>new</jk> ServerVariable() 062 * .setDefault(<js>"v2"</js>) 063 * ) 064 * ); 065 * </p> 066 * 067 * <h5 class='section'>See Also:</h5><ul> 068 * <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#server-object">OpenAPI Specification > Server Object</a> 069 * <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/api-host-and-base-path/">OpenAPI API Host and Base Path</a> 070 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a> 071 * </ul> 072 */ 073@SuppressWarnings({ 074 "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants 075}) 076public class Server extends OpenApiElement { 077 078 private URI url; 079 private String description; 080 private final Map<String,ServerVariable> variables = map(); 081 082 /** 083 * Default constructor. 084 */ 085 public Server() {} 086 087 /** 088 * Copy constructor. 089 * 090 * @param copyFrom The object to copy. 091 */ 092 public Server(Server copyFrom) { 093 super(copyFrom); 094 095 this.url = copyFrom.url; 096 this.description = copyFrom.description; 097 variables.putAll(cp(copyFrom.variables, ServerVariable::copy)); 098 } 099 100 /** 101 * Adds one or more values to the <property>variables</property> property. 102 * 103 * @param key The mapping key. Must not be <jk>null</jk>, or an {@link IllegalArgumentException} is thrown. 104 * @param value 105 * The values to add to this property. 106 * <br>Must not be <jk>null</jk>, or an {@link IllegalArgumentException} is thrown. 107 * <br>Ignored if <jk>null</jk>. 108 * @return This object 109 */ 110 public Server addVariable(String key, ServerVariable value) { 111 reqnn("key", key); 112 reqnn("value", value); 113 variables.put(key, value); 114 return this; 115 } 116 117 /** 118 * Make a deep copy of this object. 119 * 120 * @return A deep copy of this object. 121 */ 122 public Server copy() { 123 return new Server(this); 124 } 125 126 @Override /* Overridden from OpenApiElement */ 127 public <T> T get(String property, Class<T> type) { 128 reqnn("property", property); 129 return switch (property) { 130 case "url" -> toType(getUrl(), type); 131 case "description" -> toType(getDescription(), type); 132 case "variables" -> toType(getVariables(), type); 133 default -> super.get(property, type); 134 }; 135 } 136 137 /** 138 * Bean property getter: <property>description</property>. 139 * 140 * @return The property value, or <jk>null</jk> if it is not set. 141 */ 142 public String getDescription() { return description; } 143 144 /** 145 * Bean property getter: <property>url</property>. 146 * 147 * <p> 148 * A URL to the target host. 149 * 150 * @return The property value, or <jk>null</jk> if it is not set. 151 */ 152 public URI getUrl() { return url; } 153 154 /** 155 * Bean property getter: <property>variables</property>. 156 * 157 * @return The property value, or <jk>null</jk> if it is not set. 158 */ 159 public Map<String,ServerVariable> getVariables() { return nie(variables); } 160 161 @Override /* Overridden from OpenApiElement */ 162 public Set<String> keySet() { 163 // @formatter:off 164 var s = stb(String.class) 165 .addIf(nn(description), "description") 166 .addIf(nn(url), "url") 167 .addIf(ine(variables), "variables") 168 .build(); 169 // @formatter:on 170 return new MultiSet<>(s, super.keySet()); 171 } 172 173 @Override /* Overridden from OpenApiElement */ 174 public Server set(String property, Object value) { 175 reqnn("property", property); 176 return switch (property) { 177 case "description" -> setDescription(s(value)); 178 case "url" -> setUrl(toUri(value)); 179 case "variables" -> setVariables(toMapBuilder(value, String.class, ServerVariable.class).sparse().build()); 180 default -> { 181 super.set(property, value); 182 yield this; 183 } 184 }; 185 } 186 187 /** 188 * Bean property setter: <property>description</property>. 189 * 190 * @param value 191 * The new value for this property. 192 * <br>Can be <jk>null</jk> to unset the property. 193 * @return This object 194 */ 195 public Server setDescription(String value) { 196 description = value; 197 return this; 198 } 199 200 /** 201 * Bean property setter: <property>url</property>. 202 * 203 * <p> 204 * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}. 205 * <br>Strings must be valid URIs. 206 * 207 * <p> 208 * URIs defined by {@link UriResolver} can be used for values. 209 * 210 * @param value 211 * The new value for this property. 212 * <br>Can be <jk>null</jk> to unset the property. 213 * @return This object 214 */ 215 public Server setUrl(URI value) { 216 url = value; 217 return this; 218 } 219 220 /** 221 * Bean property setter: <property>variables</property>. 222 * 223 * @param value 224 * The new value for this property. 225 * <br>Can be <jk>null</jk> to unset the property. 226 * @return This object 227 */ 228 public Server setVariables(Map<String,ServerVariable> value) { 229 variables.clear(); 230 if (nn(value)) 231 variables.putAll(value); 232 return this; 233 } 234 235 @Override /* Overridden from OpenApiElement */ 236 public Server strict(Object value) { 237 super.strict(value); 238 return this; 239 } 240 241 @Override /* Overridden from OpenApiElement */ 242 protected Server strict() { 243 super.strict(); 244 return this; 245 } 246}