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.Utils.*; 022import static org.apache.juneau.internal.ConverterUtils.*; 023 024import java.util.*; 025 026import org.apache.juneau.commons.collections.*; 027 028/** 029 * TODO 030 * 031 * <p> 032 * The ServerVariable Object represents a server variable for server URL template substitution. Server variables can be 033 * used to define different server environments (e.g., development, staging, production) with different base URLs, 034 * ports, or other variable parts of the server URL. 035 * 036 * <h5 class='section'>OpenAPI Specification:</h5> 037 * <p> 038 * The ServerVariable Object is composed of the following fields: 039 * <ul class='spaced-list'> 040 * <li><c>enum</c> (array of any) - An enumeration of string values to be used if the substitution options are from a limited set 041 * <li><c>default</c> (string, REQUIRED) - The default value to use for substitution, which SHALL be sent if an alternate value is not supplied 042 * <li><c>description</c> (string) - An optional description for the server variable. CommonMark syntax MAY be used for rich text representation 043 * </ul> 044 * 045 * <h5 class='section'>Example:</h5> 046 * <p class='bcode'> 047 * <jc>// Construct using SwaggerBuilder.</jc> 048 * ServerVariable <jv>x</jv> = <jsm>serverVariable</jsm>() 049 * .setDefault(<js>"api"</js>) 050 * .setEnum(<js>"api"</js>, <js>"staging"</js>, <js>"dev"</js>) 051 * .setDescription(<js>"Environment to use"</js>); 052 * 053 * <jc>// Serialize using JsonSerializer.</jc> 054 * String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>x</jv>); 055 * 056 * <jc>// Or just use toString() which does the same as above.</jc> 057 * <jv>json</jv> = <jv>x</jv>.toString(); 058 * </p> 059 * <p class='bcode'> 060 * <jc>// Output</jc> 061 * { 062 * <js>"default"</js>: <js>"api"</js>, 063 * <js>"enum"</js>: [<js>"api"</js>, <js>"staging"</js>, <js>"dev"</js>], 064 * <js>"description"</js>: <js>"Environment to use"</js> 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-variable-object">OpenAPI Specification > Server Variable 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 ServerVariable extends OpenApiElement { 075 076 private List<Object> enum_ = list(); 077 private String default_; 078 private String description; 079 080 /** 081 * Default constructor. 082 */ 083 public ServerVariable() {} 084 085 /** 086 * Copy constructor. 087 * 088 * @param copyFrom The object to copy. 089 */ 090 public ServerVariable(ServerVariable copyFrom) { 091 super(copyFrom); 092 093 if (nn(copyFrom.enum_)) 094 this.enum_.addAll(copyOf(copyFrom.enum_)); 095 this.default_ = copyFrom.default_; 096 this.description = copyFrom.description; 097 } 098 099 /** 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<Object></code> 108 * <li><code>String</code> - JSON array representation of <code>Collection<Object></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}