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