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