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.rest.annotation; 018 019import static org.apache.juneau.internal.ArrayUtils.*; 020 021import java.lang.annotation.*; 022import java.nio.charset.*; 023 024import org.apache.juneau.*; 025import org.apache.juneau.annotation.*; 026import org.apache.juneau.encoders.*; 027import org.apache.juneau.http.*; 028import org.apache.juneau.reflect.*; 029import org.apache.juneau.rest.*; 030import org.apache.juneau.rest.converter.*; 031import org.apache.juneau.rest.guard.*; 032import org.apache.juneau.rest.httppart.*; 033import org.apache.juneau.rest.matcher.*; 034import org.apache.juneau.serializer.*; 035import org.apache.juneau.svl.*; 036 037/** 038 * Utility classes and methods for the {@link RestOptions @RestOptions} annotation. 039 * 040 * <h5 class='section'>See Also:</h5><ul> 041 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestOpAnnotatedMethodBasics">@RestOp-Annotated Method Basics</a> 042 * </ul> 043 */ 044public class RestOptionsAnnotation { 045 046 //----------------------------------------------------------------------------------------------------------------- 047 // Static 048 //----------------------------------------------------------------------------------------------------------------- 049 050 /** Default value */ 051 public static final RestOptions DEFAULT = create().build(); 052 053 /** 054 * Instantiates a new builder for this class. 055 * 056 * @return A new builder object. 057 */ 058 public static Builder create() { 059 return new Builder(); 060 } 061 062 //----------------------------------------------------------------------------------------------------------------- 063 // Builder 064 //----------------------------------------------------------------------------------------------------------------- 065 066 /** 067 * Builder class. 068 * 069 * <h5 class='section'>See Also:</h5><ul> 070 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#annotations(Annotation...)} 071 * </ul> 072 */ 073 @SuppressWarnings("unchecked") 074 public static class Builder extends TargetedAnnotationMBuilder<Builder> { 075 076 Class<? extends RestConverter>[] converters = new Class[0]; 077 Class<? extends RestGuard>[] guards = new Class[0]; 078 Class<? extends RestMatcher>[] matchers = new Class[0]; 079 Class<? extends Encoder>[] encoders = new Class[0]; 080 Class<? extends Serializer>[] serializers = new Class[0]; 081 OpSwagger swagger = OpSwaggerAnnotation.DEFAULT; 082 String clientVersion="", debug="", defaultAccept="", defaultCharset="", rolesDeclared="", roleGuard="", summary="", value=""; 083 String[] defaultRequestQueryData={}, defaultRequestAttributes={}, defaultRequestHeaders={}, defaultResponseHeaders={}, path={}, produces={}; 084 085 /** 086 * Constructor. 087 */ 088 protected Builder() { 089 super(RestOptions.class); 090 } 091 092 /** 093 * Instantiates a new {@link RestOptions @RestOptions} object initialized with this builder. 094 * 095 * @return A new {@link RestOptions @RestOptions} object. 096 */ 097 public RestOptions build() { 098 return new Impl(this); 099 } 100 101 /** 102 * Sets the {@link RestOptions#clientVersion()} property on this annotation. 103 * 104 * @param value The new value for this property. 105 * @return This object. 106 */ 107 public Builder clientVersion(String value) { 108 this.clientVersion = value; 109 return this; 110 } 111 112 /** 113 * Sets the {@link RestOptions#converters()} property on this annotation. 114 * 115 * @param value The new value for this property. 116 * @return This object. 117 */ 118 @SafeVarargs 119 public final Builder converters(Class<? extends RestConverter>...value) { 120 this.converters = value; 121 return this; 122 } 123 124 /** 125 * Sets the {@link RestOptions#debug()} property on this annotation. 126 * 127 * @param value The new value for this property. 128 * @return This object. 129 */ 130 public Builder debug(String value) { 131 this.debug = value; 132 return this; 133 } 134 135 /** 136 * Sets the {@link RestOptions#defaultAccept()} property on this annotation. 137 * 138 * @param value The new value for this property. 139 * @return This object. 140 */ 141 public Builder defaultAccept(String value) { 142 this.defaultAccept = value; 143 return this; 144 } 145 146 /** 147 * Sets the {@link RestOptions#defaultCharset()} property on this annotation. 148 * 149 * @param value The new value for this property. 150 * @return This object. 151 */ 152 public Builder defaultCharset(String value) { 153 this.defaultCharset = value; 154 return this; 155 } 156 157 /** 158 * Sets the {@link RestOptions#defaultRequestQueryData()} property on this annotation. 159 * 160 * @param value The new value for this property. 161 * @return This object. 162 */ 163 public Builder defaultRequestQueryData(String...value) { 164 this.defaultRequestQueryData = value; 165 return this; 166 } 167 168 /** 169 * Sets the {@link RestOptions#defaultRequestAttributes()} property on this annotation. 170 * 171 * @param value The new value for this property. 172 * @return This object. 173 */ 174 public Builder defaultRequestAttributes(String...value) { 175 this.defaultRequestAttributes = value; 176 return this; 177 } 178 179 /** 180 * Sets the {@link RestOptions#defaultRequestHeaders()} property on this annotation. 181 * 182 * @param value The new value for this property. 183 * @return This object. 184 */ 185 public Builder defaultRequestHeaders(String...value) { 186 this.defaultRequestHeaders = value; 187 return this; 188 } 189 190 /** 191 * Sets the {@link RestOptions#defaultResponseHeaders()} property on this annotation. 192 * 193 * @param value The new value for this property. 194 * @return This object. 195 */ 196 public Builder defaultResponseHeaders(String...value) { 197 this.defaultResponseHeaders = value; 198 return this; 199 } 200 201 /** 202 * Sets the {@link RestOptions#encoders()} property on this annotation. 203 * 204 * @param value The new value for this property. 205 * @return This object. 206 */ 207 @SafeVarargs 208 public final Builder encoders(Class<? extends Encoder>...value) { 209 this.encoders = value; 210 return this; 211 } 212 213 /** 214 * Sets the {@link RestOptions#guards()} property on this annotation. 215 * 216 * @param value The new value for this property. 217 * @return This object. 218 */ 219 @SafeVarargs 220 public final Builder guards(Class<? extends RestGuard>...value) { 221 this.guards = value; 222 return this; 223 } 224 225 /** 226 * Sets the {@link RestOptions#matchers()} property on this annotation. 227 * 228 * @param value The new value for this property. 229 * @return This object. 230 */ 231 @SafeVarargs 232 public final Builder matchers(Class<? extends RestMatcher>...value) { 233 this.matchers = value; 234 return this; 235 } 236 237 /** 238 * Sets the {@link RestOptions#path()} property on this annotation. 239 * 240 * @param value The new value for this property. 241 * @return This object. 242 */ 243 public Builder path(String...value) { 244 this.path = value; 245 return this; 246 } 247 248 /** 249 * Sets the {@link RestOptions#produces()} property on this annotation. 250 * 251 * @param value The new value for this property. 252 * @return This object. 253 */ 254 public Builder produces(String...value) { 255 this.produces = value; 256 return this; 257 } 258 259 /** 260 * Sets the {@link RestOptions#roleGuard()} property on this annotation. 261 * 262 * @param value The new value for this property. 263 * @return This object. 264 */ 265 public Builder roleGuard(String value) { 266 this.roleGuard = value; 267 return this; 268 } 269 270 /** 271 * Sets the {@link RestOptions#rolesDeclared()} property on this annotation. 272 * 273 * @param value The new value for this property. 274 * @return This object. 275 */ 276 public Builder rolesDeclared(String value) { 277 this.rolesDeclared = value; 278 return this; 279 } 280 281 /** 282 * Sets the {@link RestOptions#serializers()} property on this annotation. 283 * 284 * @param value The new value for this property. 285 * @return This object. 286 */ 287 @SafeVarargs 288 public final Builder serializers(Class<? extends Serializer>...value) { 289 this.serializers = value; 290 return this; 291 } 292 293 /** 294 * Sets the {@link RestOptions#summary()} property on this annotation. 295 * 296 * @param value The new value for this property. 297 * @return This object. 298 */ 299 public Builder summary(String value) { 300 this.summary = value; 301 return this; 302 } 303 304 /** 305 * Sets the {@link RestOptions#swagger()} property on this annotation. 306 * 307 * @param value The new value for this property. 308 * @return This object. 309 */ 310 public Builder swagger(OpSwagger value) { 311 this.swagger = value; 312 return this; 313 } 314 315 /** 316 * Sets the {@link RestOptions#value()} property on this annotation. 317 * 318 * @param value The new value for this property. 319 * @return This object. 320 */ 321 public Builder value(String value) { 322 this.value = value; 323 return this; 324 } 325 326 } 327 328 //----------------------------------------------------------------------------------------------------------------- 329 // Implementation 330 //----------------------------------------------------------------------------------------------------------------- 331 332 private static class Impl extends TargetedAnnotationImpl implements RestOptions { 333 334 private final Class<? extends RestConverter>[] converters; 335 private final Class<? extends RestGuard>[] guards; 336 private final Class<? extends RestMatcher>[] matchers; 337 private final Class<? extends Encoder>[] encoders; 338 private final Class<? extends Serializer>[] serializers; 339 private final OpSwagger swagger; 340 private final String clientVersion, debug, defaultAccept, defaultCharset, rolesDeclared, roleGuard, summary, value; 341 private final String[] defaultRequestQueryData, defaultRequestAttributes, defaultRequestHeaders, defaultResponseHeaders, path, produces; 342 343 Impl(Builder b) { 344 super(b); 345 this.clientVersion = b.clientVersion; 346 this.converters = copyOf(b.converters); 347 this.debug = b.debug; 348 this.defaultAccept = b.defaultAccept; 349 this.defaultCharset = b.defaultCharset; 350 this.defaultRequestQueryData = copyOf(b.defaultRequestQueryData); 351 this.defaultRequestAttributes = copyOf(b.defaultRequestAttributes); 352 this.defaultRequestHeaders = copyOf(b.defaultRequestHeaders); 353 this.defaultResponseHeaders = copyOf(b.defaultResponseHeaders); 354 this.encoders = copyOf(b.encoders); 355 this.guards = copyOf(b.guards); 356 this.matchers = copyOf(b.matchers); 357 this.path = copyOf(b.path); 358 this.produces = copyOf(b.produces); 359 this.roleGuard = b.roleGuard; 360 this.rolesDeclared = b.rolesDeclared; 361 this.serializers = copyOf(b.serializers); 362 this.summary = b.summary; 363 this.swagger = b.swagger; 364 this.value = b.value; 365 postConstruct(); 366 } 367 368 @Override /* RestOptions */ 369 public String clientVersion() { 370 return clientVersion; 371 } 372 373 @Override /* RestOptions */ 374 public Class<? extends RestConverter>[] converters() { 375 return converters; 376 } 377 378 @Override /* RestOptions */ 379 public String debug() { 380 return debug; 381 } 382 383 @Override /* RestOptions */ 384 public String defaultAccept() { 385 return defaultAccept; 386 } 387 388 @Override /* RestOptions */ 389 public String defaultCharset() { 390 return defaultCharset; 391 } 392 393 @Override /* RestOptions */ 394 public String[] defaultRequestQueryData() { 395 return defaultRequestQueryData; 396 } 397 398 @Override /* RestOptions */ 399 public String[] defaultRequestAttributes() { 400 return defaultRequestAttributes; 401 } 402 403 @Override /* RestOptions */ 404 public String[] defaultRequestHeaders() { 405 return defaultRequestHeaders; 406 } 407 408 @Override /* RestOptions */ 409 public String[] defaultResponseHeaders() { 410 return defaultResponseHeaders; 411 } 412 413 @Override /* RestOptions */ 414 public Class<? extends Encoder>[] encoders() { 415 return encoders; 416 } 417 418 @Override /* RestOptions */ 419 public Class<? extends RestGuard>[] guards() { 420 return guards; 421 } 422 423 @Override /* RestOptions */ 424 public Class<? extends RestMatcher>[] matchers() { 425 return matchers; 426 } 427 428 @Override /* RestOptions */ 429 public String[] path() { 430 return path; 431 } 432 433 @Override /* RestOptions */ 434 public String[] produces() { 435 return produces; 436 } 437 438 @Override /* RestOptions */ 439 public String roleGuard() { 440 return roleGuard; 441 } 442 443 @Override /* RestOptions */ 444 public String rolesDeclared() { 445 return rolesDeclared; 446 } 447 448 @Override /* RestOptions */ 449 public Class<? extends Serializer>[] serializers() { 450 return serializers; 451 } 452 453 @Override /* RestOptions */ 454 public String summary() { 455 return summary; 456 } 457 458 @Override /* RestOptions */ 459 public OpSwagger swagger() { 460 return swagger; 461 } 462 463 @Override /* RestOptions */ 464 public String value() { 465 return value; 466 } 467 } 468 469 //----------------------------------------------------------------------------------------------------------------- 470 // Appliers 471 //----------------------------------------------------------------------------------------------------------------- 472 473 /** 474 * Applies {@link RestOptions} annotations to a {@link org.apache.juneau.rest.RestOpContext.Builder}. 475 */ 476 public static class RestOpContextApply extends AnnotationApplier<RestOptions,RestOpContext.Builder> { 477 478 /** 479 * Constructor. 480 * 481 * @param vr The resolver for resolving values in annotations. 482 */ 483 public RestOpContextApply(VarResolverSession vr) { 484 super(RestOptions.class, RestOpContext.Builder.class, vr); 485 } 486 487 @Override 488 public void apply(AnnotationInfo<RestOptions> ai, RestOpContext.Builder b) { 489 RestOptions a = ai.inner(); 490 491 b.httpMethod("options"); 492 493 classes(a.serializers()).ifPresent(x -> b.serializers().set(x)); 494 classes(a.encoders()).ifPresent(x -> b.encoders().set(x)); 495 stream(a.produces()).map(MediaType::of).forEach(x -> b.produces(x)); 496 stream(a.defaultRequestHeaders()).map(HttpHeaders::stringHeader).forEach(x -> b.defaultRequestHeaders().setDefault(x)); 497 stream(a.defaultResponseHeaders()).map(HttpHeaders::stringHeader).forEach(x -> b.defaultResponseHeaders().setDefault(x)); 498 stream(a.defaultRequestAttributes()).map(BasicNamedAttribute::ofPair).forEach(x -> b.defaultRequestAttributes().add(x)); 499 stream(a.defaultRequestQueryData()).map(HttpParts::basicPart).forEach(x -> b.defaultRequestQueryData().setDefault(x)); 500 string(a.defaultAccept()).map(HttpHeaders::accept).ifPresent(x -> b.defaultRequestHeaders().setDefault(x)); 501 b.converters().append(a.converters()); 502 b.guards().append(a.guards()); 503 b.matchers().append(a.matchers()); 504 string(a.clientVersion()).ifPresent(x -> b.clientVersion(x)); 505 string(a.defaultCharset()).map(Charset::forName).ifPresent(x -> b.defaultCharset(x)); 506 stream(a.path()).forEach(x -> b.path(x)); 507 string(a.value()).ifPresent(x -> b.path(x)); 508 cdl(a.rolesDeclared()).forEach(x -> b.rolesDeclared(x)); 509 string(a.roleGuard()).ifPresent(x -> b.roleGuard(x)); 510 string(a.debug()).map(Enablement::fromString).ifPresent(x -> b.debug(x)); 511 } 512 } 513}