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