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.common.utils.Utils.*; 020import static org.apache.juneau.internal.CollectionUtils.*; 021import static org.apache.juneau.internal.ConverterUtils.*; 022 023import java.util.*; 024 025import org.apache.juneau.internal.*; 026 027/** 028 * Holds a set of reusable objects for different aspects of the OpenAPI Specification. 029 * 030 * <p> 031 * The Components Object holds a set of reusable objects that can be referenced from other parts of the API specification. 032 * This promotes reusability and reduces duplication by allowing common schemas, responses, parameters, and other objects 033 * to be defined once and referenced multiple times using the <c>$ref</c> syntax. 034 * 035 * <h5 class='section'>OpenAPI Specification:</h5> 036 * <p> 037 * The Components Object is composed of the following fields: 038 * <ul class='spaced-list'> 039 * <li><c>schemas</c> (map of {@link SchemaInfo}) - Reusable schema definitions 040 * <li><c>responses</c> (map of {@link Response}) - Reusable response definitions 041 * <li><c>parameters</c> (map of {@link Parameter}) - Reusable parameter definitions 042 * <li><c>examples</c> (map of {@link Example}) - Reusable example definitions 043 * <li><c>requestBodies</c> (map of {@link RequestBodyInfo}) - Reusable request body definitions 044 * <li><c>headers</c> (map of {@link HeaderInfo}) - Reusable header definitions 045 * <li><c>securitySchemes</c> (map of {@link SecuritySchemeInfo}) - Reusable security scheme definitions 046 * <li><c>links</c> (map of {@link Link}) - Reusable link definitions 047 * <li><c>callbacks</c> (map of {@link Callback}) - Reusable callback definitions 048 * </ul> 049 * 050 * <h5 class='section'>Example:</h5> 051 * <p class='bjava'> 052 * <jc>// Create a Components object with reusable schemas</jc> 053 * Components <jv>components</jv> = <jk>new</jk> Components() 054 * .setSchemas( 055 * JsonMap.<jsm>of</jsm>( 056 * <js>"Pet"</js>, <jk>new</jk> SchemaInfo() 057 * .setType(<js>"object"</js>) 058 * .setRequired(<js>"id"</js>, <js>"name"</js>) 059 * .setProperties( 060 * JsonMap.<jsm>of</jsm>( 061 * <js>"id"</js>, <jk>new</jk> SchemaInfo().setType(<js>"integer"</js>), 062 * <js>"name"</js>, <jk>new</jk> SchemaInfo().setType(<js>"string"</js>) 063 * ) 064 * ), 065 * <js>"Error"</js>, <jk>new</jk> SchemaInfo() 066 * .setType(<js>"object"</js>) 067 * .setProperties( 068 * JsonMap.<jsm>of</jsm>( 069 * <js>"code"</js>, <jk>new</jk> SchemaInfo().setType(<js>"integer"</js>), 070 * <js>"message"</js>, <jk>new</jk> SchemaInfo().setType(<js>"string"</js>) 071 * ) 072 * ) 073 * ) 074 * ); 075 * <jc>// These schemas can then be referenced: "#/components/schemas/Pet"</jc> 076 * </p> 077 * 078 * <h5 class='section'>See Also:</h5><ul> 079 * <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#components-object">OpenAPI Specification > Components Object</a> 080 * <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/components/">OpenAPI Components</a> 081 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a> 082 * </ul> 083 */ 084public class Components extends OpenApiElement { 085 086 private Map<String,SchemaInfo> schemas; 087 private Map<String,Response> responses; 088 private Map<String,Parameter> parameters; 089 private Map<String,Example> examples; 090 private Map<String,RequestBodyInfo> requestBodies; 091 private Map<String,HeaderInfo> headers; 092 private Map<String,SecuritySchemeInfo> securitySchemes; 093 private Map<String,Link> links; 094 private Map<String,Callback> callbacks; 095 096 /** 097 * Default constructor. 098 */ 099 public Components() {} 100 101 /** 102 * Copy constructor. 103 * 104 * @param copyFrom The object to copy. 105 */ 106 public Components(Components copyFrom) { 107 super(copyFrom); 108 this.schemas = copyOf(copyFrom.schemas); 109 this.responses = copyOf(copyFrom.responses); 110 this.parameters = copyOf(copyFrom.parameters); 111 this.examples = copyOf(copyFrom.examples); 112 this.requestBodies = copyOf(copyFrom.requestBodies); 113 this.headers = copyOf(copyFrom.headers); 114 this.securitySchemes = copyOf(copyFrom.securitySchemes); 115 this.links = copyOf(copyFrom.links); 116 this.callbacks = copyOf(copyFrom.callbacks); 117 } 118 119 /** 120 * Returns the schemas map. 121 * 122 * @return The schemas map. 123 */ 124 public Map<String,SchemaInfo> getSchemas() { 125 return schemas; 126 } 127 128 /** 129 * Sets the schemas map. 130 * 131 * @param value The new value for this property. 132 * @return This object. 133 */ 134 public Components setSchemas(Map<String,SchemaInfo> value) { 135 this.schemas = value; 136 return this; 137 } 138 139 /** 140 * Returns the responses map. 141 * 142 * @return The responses map. 143 */ 144 public Map<String,Response> getResponses() { 145 return responses; 146 } 147 148 /** 149 * Sets the responses map. 150 * 151 * @param value The new value for this property. 152 * @return This object. 153 */ 154 public Components setResponses(Map<String,Response> value) { 155 this.responses = value; 156 return this; 157 } 158 159 /** 160 * Returns the parameters map. 161 * 162 * @return The parameters map. 163 */ 164 public Map<String,Parameter> getParameters() { 165 return parameters; 166 } 167 168 /** 169 * Sets the parameters map. 170 * 171 * @param value The new value for this property. 172 * @return This object. 173 */ 174 public Components setParameters(Map<String,Parameter> value) { 175 this.parameters = value; 176 return this; 177 } 178 179 /** 180 * Returns the examples map. 181 * 182 * @return The examples map. 183 */ 184 public Map<String,Example> getExamples() { 185 return examples; 186 } 187 188 /** 189 * Sets the examples map. 190 * 191 * @param value The new value for this property. 192 * @return This object. 193 */ 194 public Components setExamples(Map<String,Example> value) { 195 this.examples = value; 196 return this; 197 } 198 199 /** 200 * Returns the request bodies map. 201 * 202 * @return The request bodies map. 203 */ 204 public Map<String,RequestBodyInfo> getRequestBodies() { 205 return requestBodies; 206 } 207 208 /** 209 * Sets the request bodies map. 210 * 211 * @param value The new value for this property. 212 * @return This object. 213 */ 214 public Components setRequestBodies(Map<String,RequestBodyInfo> value) { 215 this.requestBodies = value; 216 return this; 217 } 218 219 /** 220 * Returns the headers map. 221 * 222 * @return The headers map. 223 */ 224 public Map<String,HeaderInfo> getHeaders() { 225 return headers; 226 } 227 228 /** 229 * Sets the headers map. 230 * 231 * @param value The new value for this property. 232 * @return This object. 233 */ 234 public Components setHeaders(Map<String,HeaderInfo> value) { 235 this.headers = value; 236 return this; 237 } 238 239 /** 240 * Returns the security schemes map. 241 * 242 * @return The security schemes map. 243 */ 244 public Map<String,SecuritySchemeInfo> getSecuritySchemes() { 245 return securitySchemes; 246 } 247 248 /** 249 * Sets the security schemes map. 250 * 251 * @param value The new value for this property. 252 * @return This object. 253 */ 254 public Components setSecuritySchemes(Map<String,SecuritySchemeInfo> value) { 255 this.securitySchemes = value; 256 return this; 257 } 258 259 /** 260 * Returns the links map. 261 * 262 * @return The links map. 263 */ 264 public Map<String,Link> getLinks() { 265 return links; 266 } 267 268 /** 269 * Sets the links map. 270 * 271 * @param value The new value for this property. 272 * @return This object. 273 */ 274 public Components setLinks(Map<String,Link> value) { 275 this.links = value; 276 return this; 277 } 278 279 /** 280 * Returns the callbacks map. 281 * 282 * @return The callbacks map. 283 */ 284 public Map<String,Callback> getCallbacks() { 285 return callbacks; 286 } 287 288 /** 289 * Sets the callbacks map. 290 * 291 * @param value The new value for this property. 292 * @return This object. 293 */ 294 public Components setCallbacks(Map<String,Callback> value) { 295 this.callbacks = value; 296 return this; 297 } 298 299 /** 300 * Creates a copy of this object. 301 * 302 * @return A copy of this object. 303 */ 304 public Components copy() { 305 return new Components(this); 306 } 307 308 @Override /* Overridden from OpenApiElement */ 309 public <T> T get(String property, Class<T> type) { 310 assertArgNotNull("property", property); 311 return switch (property) { 312 case "schemas" -> toType(getSchemas(), type); 313 case "responses" -> toType(getResponses(), type); 314 case "parameters" -> toType(getParameters(), type); 315 case "examples" -> toType(getExamples(), type); 316 case "requestBodies" -> toType(getRequestBodies(), type); 317 case "headers" -> toType(getHeaders(), type); 318 case "securitySchemes" -> toType(getSecuritySchemes(), type); 319 case "links" -> toType(getLinks(), type); 320 case "callbacks" -> toType(getCallbacks(), type); 321 default -> super.get(property, type); 322 }; 323 } 324 325 @Override /* Overridden from OpenApiElement */ 326 public Components set(String property, Object value) { 327 assertArgNotNull("property", property); 328 return switch (property) { 329 case "callbacks" -> setCallbacks(mapBuilder(String.class, Callback.class).sparse().addAny(value).build()); 330 case "examples" -> setExamples(mapBuilder(String.class, Example.class).sparse().addAny(value).build()); 331 case "headers" -> setHeaders(mapBuilder(String.class, HeaderInfo.class).sparse().addAny(value).build()); 332 case "links" -> setLinks(mapBuilder(String.class, Link.class).sparse().addAny(value).build()); 333 case "parameters" -> setParameters(mapBuilder(String.class, Parameter.class).sparse().addAny(value).build()); 334 case "requestBodies" -> setRequestBodies(mapBuilder(String.class, RequestBodyInfo.class).sparse().addAny(value).build()); 335 case "responses" -> setResponses(mapBuilder(String.class, Response.class).sparse().addAny(value).build()); 336 case "schemas" -> setSchemas(mapBuilder(String.class, SchemaInfo.class).sparse().addAny(value).build()); 337 case "securitySchemes" -> setSecuritySchemes(mapBuilder(String.class, SecuritySchemeInfo.class).sparse().addAny(value).build()); 338 default -> { 339 super.set(property, value); 340 yield this; 341 } 342 }; 343 } 344 345 @Override /* Overridden from OpenApiElement */ 346 public Set<String> keySet() { 347 var s = setBuilder(String.class) 348 .addIf(callbacks != null, "callbacks") 349 .addIf(examples != null, "examples") 350 .addIf(headers != null, "headers") 351 .addIf(links != null, "links") 352 .addIf(parameters != null, "parameters") 353 .addIf(requestBodies != null, "requestBodies") 354 .addIf(responses != null, "responses") 355 .addIf(schemas != null, "schemas") 356 .addIf(securitySchemes != null, "securitySchemes") 357 .build(); 358 return new MultiSet<>(s, super.keySet()); 359 } 360 361 @Override /* Overridden from OpenApiElement */ 362 public Components strict() { 363 super.strict(); 364 return this; 365 } 366 367 @Override /* Overridden from OpenApiElement */ 368 public Components strict(Object value) { 369 super.strict(value); 370 return this; 371 } 372}