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