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.*; 021 022import java.beans.*; 023import java.lang.annotation.*; 024import java.util.*; 025 026import org.apache.juneau.*; 027import org.apache.juneau.swap.*; 028 029/** 030 * Used to tailor how beans get interpreted by the framework. 031 * 032 * <p> 033 * Can be used in the following locations: 034 * <ul> 035 * <li>Bean classes and parent interfaces. 036 * <li><ja>@Rest</ja>-annotated classes and <ja>@RestOp</ja>-annotated methods when an {@link #on()} value is specified. 037 * </ul> 038 * 039 * <h5 class='section'>See Also:</h5><ul> 040 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/BeanAnnotation">@Bean Annotation</a> 041 * </ul> 042 */ 043@Documented 044@Target({METHOD,TYPE}) 045@Retention(RUNTIME) 046@Inherited 047@Repeatable(BeanAnnotation.Array.class) 048@ContextApply(BeanAnnotation.Applier.class) 049public @interface Bean { 050 051 /** 052 * Optional description for the exposed API. 053 * 054 * @return The annotation value. 055 * @since 9.2.0 056 */ 057 String[] description() default {}; 058 059 /** 060 * Bean dictionary. 061 * 062 * <p> 063 * The list of classes that make up the bean dictionary for all properties in this class and all subclasses. 064 * 065 * <h5 class='section'>See Also:</h5><ul> 066 * <li class='ja'>{@link Beanp#dictionary()} 067 * <li class='ja'>{@link BeanConfig#dictionary()} 068 * <li class='ja'>{@link BeanConfig#dictionary_replace()} 069 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanDictionary(Class...)} 070 * </ul> 071 * 072 * @return The annotation value. 073 */ 074 Class<?>[] dictionary() default {}; 075 076 /** 077 * POJO example. 078 * 079 * <p> 080 * Specifies an example of the specified class in Simplified JSON format. 081 * 082 * <p> 083 * Examples are used in cases such as POJO examples in Swagger documents. 084 * 085 * <h5 class='section'>Example:</h5> 086 * <p class='bjava'> 087 * <ja>@Bean</ja>(example=<js>"{foo:'bar'}"</js>) 088 * <jk>public class</jk> MyClass {...} 089 * </p> 090 * 091 * <h5 class='section'>Notes:</h5><ul> 092 * <li class='note'> 093 * Setting applies to specified class and all subclasses. 094 * <li class='note'> 095 * Keys are the class of the example. 096 * <br>Values are JSON 5 representation of that class. 097 * <li class='note'> 098 * POJO examples can also be defined on classes via the following: 099 * <ul class='spaced-list'> 100 * <li>A static field annotated with {@link Example @Example}. 101 * <li>A static method annotated with {@link Example @Example} with zero arguments or one {@link BeanSession} argument. 102 * <li>A static method with name <c>example</c> with no arguments or one {@link BeanSession} argument. 103 * </ul> 104 * <li class='note'> 105 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> (e.g. <js>"$C{myConfigVar}"</js>). 106 * </ul> 107 * 108 * <h5 class='section'>See Also:</h5><ul> 109 * <li class='ja'>{@link Example} 110 * </ul> 111 * 112 * @return The annotation value. 113 */ 114 String example() default ""; 115 116 /** 117 * Bean property excludes. 118 * 119 * <p> 120 * Specifies a list of properties that should be excluded from {@link BeanMap#entrySet()}. 121 * 122 * <h5 class='section'>Example:</h5> 123 * <p class='bjava'> 124 * <jc>// Exclude the 'city' and 'state' properties from the Address class.</jc> 125 * <ja>@Bean</ja>(excludeProperties=<js>"city,state"</js>}) 126 * <jk>public class</jk> Address {...} 127 * </p> 128 * 129 * <h5 class='section'>Notes:</h5><ul> 130 * <li class='note'> 131 * {@link #xp()} is a shortened synonym for this value. 132 * </ul> 133 * 134 * <h5 class='section'>See Also:</h5><ul> 135 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesExcludes(Class, String)} 136 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesExcludes(String, String)} 137 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesExcludes(Map)} 138 * </ul> 139 * 140 * @return The annotation value. 141 */ 142 String excludeProperties() default ""; 143 144 /** 145 * Find fluent setters. 146 * 147 * <p> 148 * When <jk>true</jk>, fluent setters will be detected on beans. 149 * 150 * <h5 class='section'>Example:</h5> 151 * <p class='bjava'> 152 * <ja>@Bean</ja>(findFluentSetters=<jk>true</jk>) 153 * <jk>public class</jk> MyBean { 154 * <jk>public int</jk> getId() {...} 155 * <jk>public</jk> MyBean id(<jk>int</jk> <jv>id</jv>) {...} 156 * } 157 * </p> 158 * 159 * <p> 160 * Fluent setters must have the following attributes: 161 * <ul> 162 * <li>Public. 163 * <li>Not static. 164 * <li>Take in one parameter. 165 * <li>Return the bean itself. 166 * </ul> 167 * 168 * <h5 class='section'>See Also:</h5><ul> 169 * <li class='ja'>{@link BeanConfig#findFluentSetters()} 170 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#findFluentSetters()} 171 * </ul> 172 * 173 * @return The annotation value. 174 */ 175 boolean findFluentSetters() default false; 176 177 /** 178 * Implementation class. 179 * 180 * <p> 181 * For interfaces and abstract classes this method can be used to specify an implementation class for the 182 * interface/abstract class so that instances of the implementation class are used when instantiated (e.g. during a 183 * parse). 184 * 185 * <h5 class='section'>Example:</h5> 186 * <p class='bjava'> 187 * <ja>@Bean</ja>(implClass=MyInterfaceImpl.<jk>class</jk>) 188 * <jk>public class</jk> MyInterface {...} 189 * <p> 190 * 191 * @return The annotation value. 192 */ 193 Class<?> implClass() default void.class; 194 195 /** 196 * Bean property interceptor. 197 * 198 * <p> 199 * Bean interceptors can be used to intercept calls to getters and setters and alter their values in transit. 200 * 201 * <h5 class='section'>See Also:</h5><ul> 202 * <li class='jc'>{@link BeanInterceptor} 203 * </ul> 204 * 205 * @return The annotation value. 206 */ 207 Class<? extends BeanInterceptor<?>> interceptor() default BeanInterceptor.Void.class; 208 209 /** 210 * Identifies a class to be used as the interface class for this and all subclasses. 211 * 212 * <p> 213 * When specified, only the list of properties defined on the interface class will be used during serialization. 214 * Additional properties on subclasses will be ignored. 215 * 216 * <p class='bjava'> 217 * <jc>// Parent class</jc> 218 * <ja>@Bean</ja>(interfaceClass=A.<jk>class</jk>) 219 * <jk>public abstract class</jk> A { 220 * <jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>; 221 * } 222 * 223 * <jc>// Sub class</jc> 224 * <jk>public class</jk> A1 <jk>extends</jk> A { 225 * <jk>public</jk> String <jf>f1</jf> = <js>"f1"</js>; 226 * } 227 * 228 * <jc>// Produces "{f0:'f0'}"</jc> 229 * String <jv>json</jv> = Json5Serializer.<jsf>DEFAULT</jsf>.serialize(<jk>new</jk> A1()); 230 * </p> 231 * 232 * <p> 233 * Note that this annotation can be used on the parent class so that it filters to all child classes, 234 * or can be set individually on the child classes. 235 * 236 * @return The annotation value. 237 */ 238 Class<?> interfaceClass() default void.class; 239 240 /** 241 * Dynamically apply this annotation to the specified classes. 242 * 243 * <p> 244 * Used in conjunction with {@link org.apache.juneau.BeanContext.Builder#applyAnnotations(Class...)} to dynamically apply an annotation to an existing class. 245 * It is ignored when the annotation is applied directly to classes. 246 * 247 * <h5 class='section'>Valid patterns:</h5> 248 * <ul class='spaced-list'> 249 * <li>Classes: 250 * <ul> 251 * <li>Fully qualified: 252 * <ul> 253 * <li><js>"com.foo.MyClass"</js> 254 * </ul> 255 * <li>Fully qualified inner class: 256 * <ul> 257 * <li><js>"com.foo.MyClass$Inner1$Inner2"</js> 258 * </ul> 259 * <li>Simple: 260 * <ul> 261 * <li><js>"MyClass"</js> 262 * </ul> 263 * <li>Simple inner: 264 * <ul> 265 * <li><js>"MyClass$Inner1$Inner2"</js> 266 * <li><js>"Inner1$Inner2"</js> 267 * <li><js>"Inner2"</js> 268 * </ul> 269 * </ul> 270 * <li>A comma-delimited list of anything on this list. 271 * </ul> 272 * 273 * <h5 class='section'>See Also:</h5><ul> 274 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/DynamicallyAppliedAnnotations">Dynamically Applied Annotations</a> 275 * </ul> 276 * 277 * @return The annotation value. 278 */ 279 String[] on() default {}; 280 281 /** 282 * Dynamically apply this annotation to the specified classes. 283 * 284 * <p> 285 * Identical to {@link #on()} except allows you to specify class objects instead of a strings. 286 * 287 * <h5 class='section'>See Also:</h5><ul> 288 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/DynamicallyAppliedAnnotations">Dynamically Applied Annotations</a> 289 * </ul> 290 * 291 * @return The annotation value. 292 */ 293 Class<?>[] onClass() default {}; 294 295 /** 296 * Synonym for {@link #properties()}. 297 * 298 * @return The annotation value. 299 */ 300 String p() default ""; 301 302 /** 303 * Bean property includes. 304 * 305 * <p> 306 * The set and order of names of properties associated with a bean class. 307 * 308 * <p> 309 * The order specified is the same order that the entries will be returned by the {@link BeanMap#entrySet()} and 310 * related methods. 311 * 312 * <p> 313 * This value is entirely optional if you simply want to expose all the getters and public fields on 314 * a class as bean properties. 315 * <br>However, it's useful if you want certain getters to be ignored or you want the properties to be 316 * serialized in a particular order. 317 * <br>Note that on IBM JREs, the property order is the same as the order in the source code, 318 * whereas on Oracle JREs, the order is entirely random. 319 * 320 * <h5 class='section'>Example:</h5> 321 * <p class='bjava'> 322 * <jc>// Address class with only street/city/state properties (in that order).</jc> 323 * <ja>@Bean</ja>(properties=<js>"street,city,state"</js>) 324 * <jk>public class</jk> Address {...} 325 * </p> 326 * 327 * <h5 class='section'>Notes:</h5><ul> 328 * <li class='note'> 329 * {@link #p()} is a shortened synonym for this value. 330 * </ul> 331 * 332 * <h5 class='section'>See Also:</h5><ul> 333 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanProperties(Class, String)} 334 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanProperties(String, String)} 335 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanProperties(Map)} 336 * </ul> 337 * 338 * @return The annotation value. 339 */ 340 String properties() default ""; 341 342 /** 343 * Associates a {@link PropertyNamer} with this bean to tailor the names of the bean properties. 344 * 345 * <p> 346 * Property namers are used to transform bean property names from standard form to some other form. 347 * 348 * <h5 class='section'>Example:</h5> 349 * <p class='bjava'> 350 * <jc>// Define a class with dashed-lowercase property names.</jc> 351 * <ja>@Bean</ja>(propertyNamer=PropertyNamerDashedLC.<jk>class</jk>) 352 * <jk>public class</jk> MyBean {...} 353 * </p> 354 * 355 * <h5 class='section'>See Also:</h5><ul> 356 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#propertyNamer(Class)} 357 * </ul> 358 * 359 * @return The annotation value. 360 */ 361 Class<? extends PropertyNamer> propertyNamer() default PropertyNamer.Void.class; 362 363 /** 364 * Read-only bean properties. 365 * 366 * <p> 367 * Specifies one or more properties on a bean that are read-only despite having valid getters. 368 * Serializers will serialize such properties as usual, but parsers will silently ignore them. 369 * 370 * <h5 class='section'>Example:</h5> 371 * <p class='bjava'> 372 * <jc>// Exclude the 'city' and 'state' properties from being parsed, but not serialized.</jc> 373 * <ja>@Bean</ja>(readOnlyProperties=<js>"city,state"</js>}) 374 * <jk>public class</jk> Address {...} 375 * </p> 376 * 377 * <h5 class='section'>Notes:</h5><ul> 378 * <li class='note'> 379 * {@link #ro()} is a shortened synonym for this value. 380 * </ul> 381 * 382 * <h5 class='section'>See Also:</h5><ul> 383 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesReadOnly(Class, String)} 384 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesReadOnly(String, String)} 385 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesReadOnly(Map)} 386 * </ul> 387 * 388 * @return The annotation value. 389 */ 390 String readOnlyProperties() default ""; 391 392 /** 393 * Synonym for {@link #readOnlyProperties()}. 394 * 395 * @return The annotation value. 396 */ 397 String ro() default ""; 398 399 /** 400 * Sort bean properties in alphabetical order. 401 * 402 * <p> 403 * When <jk>true</jk>, all bean properties will be serialized and access in alphabetical order. 404 * <br>Otherwise, the natural order of the bean properties is used which is dependent on the JVM vendor. 405 * 406 * <h5 class='section'>Example:</h5> 407 * <p class='bjava'> 408 * <jc>// Sort bean properties alphabetically during serialization.</jc> 409 * <ja>@Bean</ja>(sort=<jk>true</jk>) 410 * <jk>public class</jk> MyBean {...} 411 * </p> 412 * 413 * <h5 class='section'>See Also:</h5><ul> 414 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#sortProperties()} 415 * </ul> 416 * 417 * @return The annotation value. 418 */ 419 boolean sort() default false; 420 421 /** 422 * Identifies a stop class for the annotated class. 423 * 424 * <p> 425 * Identical in purpose to the stop class specified by {@link Introspector#getBeanInfo(Class, Class)}. 426 * Any properties in the stop class or in its base classes will be ignored during analysis. 427 * 428 * <p> 429 * For example, in the following class hierarchy, instances of <c>C3</c> will include property <c>p3</c>, 430 * but not <c>p1</c> or <c>p2</c>. 431 * <p class='bjava'> 432 * <jk>public class</jk> C1 { 433 * <jk>public int</jk> getP1(); 434 * } 435 * 436 * <jk>public class</jk> C2 <jk>extends</jk> C1 { 437 * <jk>public int</jk> getP2(); 438 * } 439 * 440 * <ja>@Bean</ja>(stopClass=C2.<jk>class</jk>) 441 * <jk>public class</jk> C3 <jk>extends</jk> C2 { 442 * <jk>public int</jk> getP3(); 443 * } 444 * </p> 445 * 446 * @return The annotation value. 447 */ 448 Class<?> stopClass() default void.class; 449 450 /** 451 * An identifying name for this class. 452 * 453 * <p> 454 * The name is used to identify the class type during parsing when it cannot be inferred through reflection. 455 * <br>For example, if a bean property is of type <c>Object</c>, then the serializer will add the name to the 456 * output so that the class can be determined during parsing. 457 * 458 * <p> 459 * It is also used to specify element names in XML. 460 * 461 * <h5 class='section'>Example:</h5> 462 * <p class='bjava'> 463 * <jc>// Use _type='mybean' to identify this bean.</jc> 464 * <ja>@Bean</ja>(typeName=<js>"mybean"</js>) 465 * <jk>public class</jk> MyBean {...} 466 * </p> 467 * 468 * <h5 class='section'>See Also:</h5><ul> 469 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanDictionary(Class...)} 470 * </ul> 471 * 472 * @return The annotation value. 473 */ 474 String typeName() default ""; 475 476 /** 477 * The property name to use for representing the type name. 478 * 479 * <p> 480 * This can be used to override the name used for the <js>"_type"</js> property used by the {@link #typeName()} setting. 481 * 482 * <p> 483 * The default value if not specified is <js>"_type"</js> . 484 * 485 * <h5 class='section'>Example:</h5> 486 * <p class='bjava'> 487 * <jc>// Use 'type' instead of '_type' for bean names.</jc> 488 * <ja>@Bean</ja>(typePropertyName=<js>"type"</js>) 489 * <jk>public class</jk> MyBean {...} 490 * </p> 491 * 492 * <h5 class='section'>See Also:</h5><ul> 493 * <li class='ja'>{@link BeanConfig#typePropertyName()} 494 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#typePropertyName(String)} 495 * </ul> 496 * 497 * @return The annotation value. 498 */ 499 String typePropertyName() default ""; 500 501 /** 502 * Synonym for {@link #writeOnlyProperties()}. 503 * 504 * @return The annotation value. 505 */ 506 String wo() default ""; 507 508 /** 509 * Write-only bean properties. 510 * 511 * <p> 512 * Specifies one or more properties on a bean that are write-only despite having valid setters. 513 * Parsers will parse such properties as usual, but serializers will silently ignore them. 514 * 515 * <h5 class='section'>Example:</h5> 516 * <p class='bjava'> 517 * <jc>// Exclude the 'city' and 'state' properties from being serialized, but not parsed.</jc> 518 * <ja>@Bean</ja>(writeOnlyProperties=<js>"city,state"</js>}) 519 * <jk>public class</jk> Address {...} 520 * </p> 521 * 522 * <h5 class='section'>Notes:</h5><ul> 523 * <li class='note'> 524 * {@link #wo()} is a shortened synonym for this value. 525 * </ul> 526 * 527 * <h5 class='section'>See Also:</h5><ul> 528 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesWriteOnly(Class, String)} 529 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesWriteOnly(String, String)} 530 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesWriteOnly(Map)} 531 * </ul> 532 * 533 * @return The annotation value. 534 */ 535 String writeOnlyProperties() default ""; 536 537 /** 538 * Synonym for {@link #excludeProperties()}. 539 * 540 * @return The annotation value. 541 */ 542 String xp() default ""; 543}