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.annotation; 014 015import static java.lang.annotation.ElementType.*; 016import static java.lang.annotation.RetentionPolicy.*; 017import static org.apache.juneau.internal.ArrayUtils.*; 018 019import java.lang.annotation.*; 020 021import org.apache.juneau.*; 022import org.apache.juneau.reflect.*; 023import org.apache.juneau.svl.*; 024import org.apache.juneau.swap.*; 025 026/** 027 * Utility classes and methods for the {@link Bean @Bean} annotation. 028 * 029 * <h5 class='section'>See Also:</h5><ul> 030 * </ul> 031 */ 032public class BeanAnnotation { 033 034 //----------------------------------------------------------------------------------------------------------------- 035 // Static 036 //----------------------------------------------------------------------------------------------------------------- 037 038 /** Default value */ 039 public static final Bean DEFAULT = create().build(); 040 041 /** 042 * Instantiates a new builder for this class. 043 * 044 * @return A new builder object. 045 */ 046 public static Builder create() { 047 return new Builder(); 048 } 049 050 /** 051 * Instantiates a new builder for this class. 052 * 053 * @param on The targets this annotation applies to. 054 * @return A new builder object. 055 */ 056 public static Builder create(Class<?>...on) { 057 return create().on(on); 058 } 059 060 /** 061 * Instantiates a new builder for this class. 062 * 063 * @param on The targets this annotation applies to. 064 * @return A new builder object. 065 */ 066 public static Builder create(String...on) { 067 return create().on(on); 068 } 069 070 /** 071 * Creates a copy of the specified annotation. 072 * 073 * @param a The annotation to copy. 074 * @param r The var resolver for resolving any variables. 075 * @return A copy of the specified annotation. 076 */ 077 public static Bean copy(Bean a, VarResolverSession r) { 078 return 079 create() 080 .dictionary(a.dictionary()) 081 .example(r.resolve(a.example())) 082 .excludeProperties(r.resolve(a.excludeProperties())) 083 .findFluentSetters(a.findFluentSetters()) 084 .implClass(a.implClass()) 085 .interceptor(a.interceptor()) 086 .interfaceClass(a.interfaceClass()) 087 .on(r.resolve(a.on())) 088 .onClass(a.onClass()) 089 .p(r.resolve(a.p())) 090 .properties(r.resolve(a.properties())) 091 .propertyNamer(a.propertyNamer()) 092 .readOnlyProperties(r.resolve(a.readOnlyProperties())) 093 .ro(r.resolve(a.ro())) 094 .sort(a.sort()) 095 .stopClass(a.stopClass()) 096 .typeName(r.resolve(a.typeName())) 097 .typePropertyName(r.resolve(a.typePropertyName())) 098 .wo(r.resolve(a.wo())) 099 .writeOnlyProperties(r.resolve(a.writeOnlyProperties())) 100 .xp(r.resolve(a.xp())) 101 .build(); 102 } 103 104 //----------------------------------------------------------------------------------------------------------------- 105 // Builder 106 //----------------------------------------------------------------------------------------------------------------- 107 108 /** 109 * Builder class. 110 * 111 * <h5 class='section'>See Also:</h5><ul> 112 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#annotations(Annotation...)} 113 * </ul> 114 */ 115 public static class Builder extends TargetedAnnotationTBuilder { 116 117 Class<?>[] dictionary = new Class[0]; 118 Class<?> implClass=void.class, interfaceClass=void.class, stopClass=void.class; 119 Class<? extends BeanInterceptor<?>> interceptor=BeanInterceptor.Void.class; 120 Class<? extends PropertyNamer> propertyNamer=BasicPropertyNamer.class; 121 String example="", excludeProperties="", p="", properties="", readOnlyProperties="", ro="", typeName="", typePropertyName="", wo="", writeOnlyProperties="", xp=""; 122 boolean findFluentSetters, sort; 123 124 /** 125 * Constructor. 126 */ 127 protected Builder() { 128 super(Bean.class); 129 } 130 131 /** 132 * Instantiates a new {@link Bean @Bean} object initialized with this builder. 133 * 134 * @return A new {@link Bean @Bean} object. 135 */ 136 public Bean build() { 137 return new Impl(this); 138 } 139 140 /** 141 * Sets the {@link Bean#dictionary()} property on this annotation. 142 * 143 * @param value The new value for this property. 144 * @return This object. 145 */ 146 public Builder dictionary(Class<?>...value) { 147 this.dictionary = value; 148 return this; 149 } 150 151 /** 152 * Sets the {@link Bean#example()} property on this annotation. 153 * 154 * @param value The new value for this property. 155 * @return This object. 156 */ 157 public Builder example(String value) { 158 this.example = value; 159 return this; 160 } 161 162 /** 163 * Sets the {@link Bean#excludeProperties()} property on this annotation. 164 * 165 * @param value The new value for this property. 166 * @return This object. 167 */ 168 public Builder excludeProperties(String value) { 169 this.excludeProperties = value; 170 return this; 171 } 172 173 /** 174 * Sets the {@link Bean#findFluentSetters()} property on this annotation. 175 * 176 * @param value The new value for this property. 177 * @return This object. 178 */ 179 public Builder findFluentSetters(boolean value) { 180 this.findFluentSetters = value; 181 return this; 182 } 183 184 /** 185 * Sets the {@link Bean#implClass()} property on this annotation. 186 * 187 * @param value The new value for this property. 188 * @return This object. 189 */ 190 public Builder implClass(Class<?> value) { 191 this.implClass = value; 192 return this; 193 } 194 195 /** 196 * Sets the {@link Bean#interceptor()} property on this annotation. 197 * 198 * @param value The new value for this property. 199 * @return This object. 200 */ 201 public Builder interceptor(Class<? extends BeanInterceptor<?>> value) { 202 this.interceptor = value; 203 return this; 204 } 205 206 /** 207 * Sets the {@link Bean#interfaceClass()} property on this annotation. 208 * 209 * @param value The new value for this property. 210 * @return This object. 211 */ 212 public Builder interfaceClass(Class<?> value) { 213 this.interfaceClass = value; 214 return this; 215 } 216 217 /** 218 * Sets the {@link Bean#properties()} property on this annotation. 219 * 220 * @param value The new value for this property. 221 * @return This object. 222 */ 223 public Builder properties(String value) { 224 this.properties = value; 225 return this; 226 } 227 228 /** 229 * Sets the {@link Bean#p()} property on this annotation. 230 * 231 * @param value The new value for this property. 232 * @return This object. 233 */ 234 public Builder p(String value) { 235 this.p = value; 236 return this; 237 } 238 239 /** 240 * Sets the {@link Bean#propertyNamer()} property on this annotation. 241 * 242 * @param value The new value for this property. 243 * @return This object. 244 */ 245 public Builder propertyNamer(Class<? extends PropertyNamer> value) { 246 this.propertyNamer = value; 247 return this; 248 } 249 250 /** 251 * Sets the {@link Bean#readOnlyProperties()} property on this annotation. 252 * 253 * @param value The new value for this property. 254 * @return This object. 255 */ 256 public Builder readOnlyProperties(String value) { 257 this.readOnlyProperties = value; 258 return this; 259 } 260 261 /** 262 * Sets the {@link Bean#ro()} property on this annotation. 263 * 264 * @param value The new value for this property. 265 * @return This object. 266 */ 267 public Builder ro(String value) { 268 this.ro = value; 269 return this; 270 } 271 272 /** 273 * Sets the {@link Bean#sort()} property on this annotation. 274 * 275 * @param value The new value for this property. 276 * @return This object. 277 */ 278 public Builder sort(boolean value) { 279 this.sort = value; 280 return this; 281 } 282 283 /** 284 * Sets the {@link Bean#stopClass()} property on this annotation. 285 * 286 * @param value The new value for this property. 287 * @return This object. 288 */ 289 public Builder stopClass(Class<?> value) { 290 this.stopClass = value; 291 return this; 292 } 293 294 /** 295 * Sets the {@link Bean#typeName()} property on this annotation. 296 * 297 * @param value The new value for this property. 298 * @return This object. 299 */ 300 public Builder typeName(String value) { 301 this.typeName = value; 302 return this; 303 } 304 305 /** 306 * Sets the {@link Bean#typePropertyName()} property on this annotation. 307 * 308 * @param value The new value for this property. 309 * @return This object. 310 */ 311 public Builder typePropertyName(String value) { 312 this.typePropertyName = value; 313 return this; 314 } 315 316 /** 317 * Sets the{@link Bean#wo()} property on this annotation. 318 * 319 * @param value The new value for this property. 320 * @return This object. 321 */ 322 public Builder wo(String value) { 323 this.wo = value; 324 return this; 325 } 326 327 /** 328 * Sets the{@link Bean#writeOnlyProperties()} property on this annotation. 329 * 330 * @param value The new value for this property. 331 * @return This object. 332 */ 333 public Builder writeOnlyProperties(String value) { 334 this.writeOnlyProperties = value; 335 return this; 336 } 337 338 /** 339 * Sets the {@link Bean#xp()} property on this annotation. 340 * 341 * @param value The new value for this property. 342 * @return This object. 343 */ 344 public Builder xp(String value) { 345 this.xp = value; 346 return this; 347 } 348 349 // <FluentSetters> 350 351 @Override /* GENERATED - TargetedAnnotationBuilder */ 352 public Builder on(String...values) { 353 super.on(values); 354 return this; 355 } 356 357 @Override /* GENERATED - TargetedAnnotationTBuilder */ 358 public Builder on(java.lang.Class<?>...value) { 359 super.on(value); 360 return this; 361 } 362 363 @Override /* GENERATED - TargetedAnnotationTBuilder */ 364 public Builder onClass(java.lang.Class<?>...value) { 365 super.onClass(value); 366 return this; 367 } 368 369 // </FluentSetters> 370 } 371 372 //----------------------------------------------------------------------------------------------------------------- 373 // Implementation 374 //----------------------------------------------------------------------------------------------------------------- 375 376 private static class Impl extends TargetedAnnotationTImpl implements Bean { 377 378 private final boolean findFluentSetters, sort; 379 private final Class<? extends BeanInterceptor<?>> interceptor; 380 private final Class<? extends PropertyNamer> propertyNamer; 381 private final Class<?> implClass, interfaceClass, stopClass; 382 private final Class<?>[] dictionary; 383 private final String example, excludeProperties, p, properties, readOnlyProperties, ro, typeName, typePropertyName, wo, writeOnlyProperties, xp; 384 385 Impl(Builder b) { 386 super(b); 387 this.dictionary = copyOf(b.dictionary); 388 this.example = b.example; 389 this.excludeProperties = b.excludeProperties; 390 this.findFluentSetters = b.findFluentSetters; 391 this.implClass = b.implClass; 392 this.interceptor = b.interceptor; 393 this.interfaceClass = b.interfaceClass; 394 this.p = b.p; 395 this.properties = b.properties; 396 this.propertyNamer = b.propertyNamer; 397 this.readOnlyProperties = b.readOnlyProperties; 398 this.ro = b.ro; 399 this.sort = b.sort; 400 this.stopClass = b.stopClass; 401 this.typeName = b.typeName; 402 this.typePropertyName = b.typePropertyName; 403 this.wo = b.wo; 404 this.writeOnlyProperties = b.writeOnlyProperties; 405 this.xp = b.xp; 406 postConstruct(); 407 } 408 409 @Override /* Bean */ 410 public Class<?>[] dictionary() { 411 return dictionary; 412 } 413 414 @Override /* Bean */ 415 public String example() { 416 return example; 417 } 418 419 @Override /* Bean */ 420 public String excludeProperties() { 421 return excludeProperties; 422 } 423 424 @Override /* Bean */ 425 public boolean findFluentSetters() { 426 return findFluentSetters; 427 } 428 429 @Override /* Bean */ 430 public Class<?> implClass() { 431 return implClass; 432 } 433 434 @Override /* Bean */ 435 public Class<? extends BeanInterceptor<?>> interceptor() { 436 return interceptor; 437 } 438 439 @Override /* Bean */ 440 public Class<?> interfaceClass() { 441 return interfaceClass; 442 } 443 444 @Override /* Bean */ 445 public String p() { 446 return p; 447 } 448 449 @Override /* Bean */ 450 public String properties() { 451 return properties; 452 } 453 454 @Override /* Bean */ 455 public Class<? extends PropertyNamer> propertyNamer() { 456 return propertyNamer; 457 } 458 459 @Override /* Bean */ 460 public String readOnlyProperties() { 461 return readOnlyProperties; 462 } 463 464 @Override /* Bean */ 465 public String ro() { 466 return ro; 467 } 468 469 @Override /* Bean */ 470 public boolean sort() { 471 return sort; 472 } 473 474 @Override /* Bean */ 475 public Class<?> stopClass() { 476 return stopClass; 477 } 478 479 @Override /* Bean */ 480 public String typeName() { 481 return typeName; 482 } 483 484 @Override /* Bean */ 485 public String typePropertyName() { 486 return typePropertyName; 487 } 488 489 @Override /* Bean */ 490 public String writeOnlyProperties() { 491 return writeOnlyProperties; 492 } 493 494 @Override /* Bean */ 495 public String wo() { 496 return wo; 497 } 498 499 @Override /* Bean */ 500 public String xp() { 501 return xp; 502 } 503 } 504 505 //----------------------------------------------------------------------------------------------------------------- 506 // Appliers 507 //----------------------------------------------------------------------------------------------------------------- 508 509 /** 510 * Applies targeted {@link Bean} annotations to a {@link org.apache.juneau.BeanContext.Builder}. 511 */ 512 public static class Applier extends AnnotationApplier<Bean,BeanContext.Builder> { 513 514 /** 515 * Constructor. 516 * 517 * @param vr The resolver for resolving values in annotations. 518 */ 519 public Applier(VarResolverSession vr) { 520 super(Bean.class, BeanContext.Builder.class, vr); 521 } 522 523 @Override 524 public void apply(AnnotationInfo<Bean> ai, BeanContext.Builder b) { 525 Bean a = ai.inner(); 526 if (isEmptyArray(a.on(), a.onClass())) 527 return; 528 b.annotations(copy(a, vr())); 529 } 530 } 531 532 //----------------------------------------------------------------------------------------------------------------- 533 // Other 534 //----------------------------------------------------------------------------------------------------------------- 535 536 /** 537 * A collection of {@link Bean @Bean annotations}. 538 */ 539 @Documented 540 @Target({METHOD,TYPE}) 541 @Retention(RUNTIME) 542 @Inherited 543 public static @interface Array { 544 545 /** 546 * The child annotations. 547 * 548 * @return The annotation value. 549 */ 550 Bean[] value(); 551 } 552}