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.bean.openapi3.OpenApiCopyUtils.*; 021import static org.apache.juneau.commons.utils.Shorts.*; 022import static org.apache.juneau.marshall.internal.ConverterUtils.*; 023 024import java.util.*; 025 026import org.apache.juneau.commons.collections.*; 027 028/** 029 * The Link object represents a possible design-time link for a response. 030 * 031 * <p> 032 * The Link Object represents a possible design-time link for a response. The presence of a link does not guarantee 033 * the caller's ability to successfully invoke it, rather it provides a known relationship and traversal mechanism 034 * between responses and other operations. 035 * 036 * <h5 class='section'>OpenAPI Specification:</h5> 037 * <p> 038 * The Link Object is composed of the following fields: 039 * <ul class='spaced-list'> 040 * <li><c>operationRef</c> (string) - A relative or absolute reference to an OAS operation (mutually exclusive with <c>operationId</c>) 041 * <li><c>operationId</c> (string) - The name of an existing, resolvable OAS operation (mutually exclusive with <c>operationRef</c>) 042 * <li><c>parameters</c> (map of any) - A map representing parameters to pass to an operation as specified with <c>operationId</c> or identified via <c>operationRef</c> 043 * <li><c>requestBody</c> (any) - A literal value or expression to use as a request body when calling the target operation 044 * <li><c>description</c> (string) - A description of the link (CommonMark syntax may be used) 045 * <li><c>server</c> ({@link Server}) - A server object to be used by the target operation 046 * </ul> 047 * 048 * <h5 class='section'>Example:</h5> 049 * <p class='bjava'> 050 * <jc>// Create a link to another operation</jc> 051 * Link <jv>link</jv> = <jk>new</jk> Link() 052 * .setOperationId(<js>"getUserById"</js>) 053 * .setParameters( 054 * JsonMap.<jsm>of</jsm>(<js>"userId"</js>, <js>"$response.body#/id"</js>) 055 * ) 056 * .setDescription(<js>"The id value returned in the response can be used as userId parameter in GET /users/{userId}"</js>); 057 * </p> 058 * 059 * <h5 class='section'>See Also:</h5><ul> 060 * <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#link-object">OpenAPI Specification > Link Object</a> 061 * <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/links/">OpenAPI Links</a> 062 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a> 063 * </ul> 064 */ 065@SuppressWarnings({ 066 "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants 067}) 068public class Link extends OpenApiElement { 069 070 private String operationRef; 071 private String operationId; 072 private String description; 073 private Object requestBody; 074 private Server server; 075 private final Map<String,Object> parameters = map(); 076 077 /** 078 * Default constructor. 079 */ 080 public Link() {} 081 082 /** 083 * Copy constructor. 084 * 085 * @param copyFrom The object to copy. 086 */ 087 public Link(Link copyFrom) { 088 super(copyFrom); 089 090 this.operationRef = copyFrom.operationRef; 091 this.description = copyFrom.description; 092 this.operationId = copyFrom.operationId; 093 this.requestBody = copyFrom.requestBody; 094 this.server = copyOf(copyFrom.server); 095 parameters.putAll(copyFrom.parameters); 096 } 097 098 /** 099 * Adds a single value to the <property>parameters</property> property. 100 * 101 * @param mimeType The parameter name. Must not be <jk>null</jk>, or an {@link IllegalArgumentException} is thrown. 102 * @param parameter The parameter value. Must not be <jk>null</jk>, or an {@link IllegalArgumentException} is thrown. 103 * @return This object 104 */ 105 public Link addParameter(String mimeType, Object parameter) { 106 reqnn("mimeType", mimeType); 107 reqnn("parameter", parameter); 108 parameters.put(mimeType, parameter); 109 return this; 110 } 111 112 /** 113 * Make a deep copy of this object. 114 * 115 * @return A deep copy of this object. 116 */ 117 public Link copy() { 118 return new Link(this); 119 } 120 121 @Override /* Overridden from OpenApiElement */ 122 public <T> T get(String property, Class<T> type) { 123 reqnn("property", property); 124 return switch (property) { 125 case "description" -> toType(getDescription(), type); 126 case "operationRef" -> toType(getOperationRef(), type); 127 case "operationId" -> toType(getOperationId(), type); 128 case "requestBody" -> toType(getRequestBody(), type); 129 case "parameters" -> toType(getParameters(), type); 130 case "server" -> toType(getServer(), type); 131 default -> super.get(property, type); 132 }; 133 } 134 135 /** 136 * Bean property getter: <property>description</property>. 137 * 138 * <p> 139 * A description of the link. 140 * 141 * @return The property value, or <jk>null</jk> if it is not set. 142 */ 143 public String getDescription() { return description; } 144 145 /** 146 * Bean property getter: <property>operationId</property>. 147 * 148 * <p> 149 * The name of an existing, resolvable OAS operation. 150 * 151 * @return The property value, or <jk>null</jk> if it is not set. 152 */ 153 public String getOperationId() { return operationId; } 154 155 /** 156 * Bean property getter: <property>operationRef</property>. 157 * 158 * <p> 159 * A relative or absolute reference to an OAS operation. 160 * 161 * @return The property value, or <jk>null</jk> if it is not set. 162 */ 163 public String getOperationRef() { return operationRef; } 164 165 /** 166 * Bean property getter: <property>parameters</property>. 167 * 168 * <p> 169 * A map representing parameters to pass to an operation. 170 * 171 * @return The property value, or <jk>null</jk> if it is not set. 172 */ 173 public Map<String,Object> getParameters() { return nie(parameters); } 174 175 /** 176 * Bean property getter: <property>requestBody</property>. 177 * 178 * <p> 179 * A literal value or expression to use as a request body when calling the target operation. 180 * 181 * @return The property value, or <jk>null</jk> if it is not set. 182 */ 183 public Object getRequestBody() { return requestBody; } 184 185 /** 186 * Bean property getter: <property>server</property>. 187 * 188 * @return The property value, or <jk>null</jk> if it is not set. 189 */ 190 public Server getServer() { return server; } 191 192 @Override /* Overridden from OpenApiElement */ 193 public Set<String> keySet() { 194 // @formatter:off 195 var s = stb(String.class) 196 .addIf(nn(description), "description") 197 .addIf(nn(operationId), "operationId") 198 .addIf(nn(operationRef), "operationRef") 199 .addIf(ine(parameters), "parameters") 200 .addIf(nn(requestBody), "requestBody") 201 .addIf(nn(server), "server") 202 .build(); 203 // @formatter:on 204 return new MultiSet<>(s, super.keySet()); 205 } 206 207 @Override /* Overridden from OpenApiElement */ 208 public Link set(String property, Object value) { 209 reqnn("property", property); 210 return switch (property) { 211 case "description" -> setDescription(s(value)); 212 case "operationId" -> setOperationId(s(value)); 213 case "operationRef" -> setOperationRef(s(value)); 214 case "parameters" -> setParameters(toMapBuilder(value, String.class, Object.class).sparse().build()); 215 case "requestBody" -> setRequestBody(value); 216 case "server" -> setServer(toType(value, Server.class)); 217 default -> { 218 super.set(property, value); 219 yield this; 220 } 221 }; 222 } 223 224 /** 225 * Bean property setter: <property>description</property>. 226 * @param value 227 * The new value for this property. 228 * <br>Can be <jk>null</jk> to unset the property. 229 * @return This object 230 */ 231 public Link setDescription(String value) { 232 description = value; 233 return this; 234 } 235 236 /** 237 * Bean property setter: <property>operationId</property>. 238 * 239 * <p> 240 * The name of an existing, resolvable OAS operation. 241 * 242 * @param value 243 * The new value for this property. 244 * <br>Can be <jk>null</jk> to unset the property. 245 * @return This object 246 */ 247 public Link setOperationId(String value) { 248 operationId = value; 249 return this; 250 } 251 252 /** 253 * Bean property setter: <property>operationRef</property>. 254 * 255 * <p> 256 * A relative or absolute reference to an OAS operation. 257 * 258 * @param value 259 * The new value for this property. 260 * <br>Can be <jk>null</jk> to unset the property. 261 * @return This object 262 */ 263 public Link setOperationRef(String value) { 264 operationRef = value; 265 return this; 266 } 267 268 /** 269 * Bean property setter: <property>parameters</property>. 270 * 271 * <p> 272 * A map representing parameters to pass to an operation. 273 * 274 * @param value 275 * The new value for this property. 276 * <br>Can be <jk>null</jk> to unset the property. 277 * @return This object 278 */ 279 public Link setParameters(Map<String,Object> value) { 280 parameters.clear(); 281 if (nn(value)) 282 parameters.putAll(value); 283 return this; 284 } 285 286 /** 287 * Bean property setter: <property>requestBody</property>. 288 * 289 * <p> 290 * A literal value or expression to use as a request body when calling the target operation. 291 * 292 * @param val The new value for this property. 293 * <br>Can be <jk>null</jk> to unset the property. 294 * @return This object 295 */ 296 public Link setRequestBody(Object val) { 297 requestBody = val; 298 return this; 299 } 300 301 /** 302 * Bean property setter: <property>server</property>. 303 * 304 * @param value 305 * The new value for this property. 306 * <br>Can be <jk>null</jk> to unset the property. 307 * @return This object 308 */ 309 public Link setServer(Server value) { 310 server = value; 311 return this; 312 } 313 314 @Override /* Overridden from OpenApiElement */ 315 public Link strict() { 316 super.strict(); 317 return this; 318 } 319 320 @Override /* Overridden from OpenApiElement */ 321 public Link strict(Object value) { 322 super.strict(value); 323 return this; 324 } 325}