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.lang.annotation.*; 023import java.util.*; 024 025import org.apache.juneau.*; 026 027/** 028 * Used tailor how bean properties get interpreted by the framework. 029 * 030 * <p> 031 * Can be used in the following locations: 032 * <ul> 033 * <li>Methods/Fields - Bean getters/setters and properties. 034 * <li><ja>@Rest</ja>-annotated classes and <ja>@RestOp</ja>-annotated methods when an {@link #on()} value is specified. 035 * </ul> 036 * <p> 037 * This annotation is applied to public fields and public getter/setter methods of beans. 038 * 039 * <h5 class='section'>See Also:</h5><ul> 040 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/BeanpAnnotation">@Beanp Annotation</a> 041 042 * </ul> 043 */ 044@Documented 045@Target({FIELD,METHOD,PARAMETER,TYPE}) 046@Retention(RUNTIME) 047@Inherited 048@Repeatable(BeanpAnnotation.Array.class) 049@ContextApply(BeanpAnnotation.Applier.class) 050public @interface Beanp { 051 052 /** 053 * Optional description for the exposed API. 054 * 055 * @return The annotation value. 056 * @since 9.2.0 057 */ 058 String[] description() default {}; 059 060 /** 061 * Bean dictionary. 062 * 063 * <p> 064 * The list of classes that make up the bean dictionary this bean property. 065 * 066 * <h5 class='section'>See Also:</h5><ul> 067 * <li class='ja'>{@link org.apache.juneau.annotation.Bean#dictionary()} 068 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#dictionary()} 069 * <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#dictionary_replace()} 070 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanDictionary(Class...)} 071 * </ul> 072 * 073 * <p> 074 * This annotation can also be used on private fields of a property. 075 * 076 * @return The annotation value. 077 */ 078 Class<?>[] dictionary() default {}; 079 080 /** 081 * Specifies a String format for converting the bean property value to a formatted string. 082 * 083 * <p> 084 * Note that this is usually a one-way conversion during serialization. 085 * 086 * <p> 087 * During parsing, we will attempt to convert the value to the original form by using the 088 * {@link BeanSession#convertToType(Object, Class)} but there is no guarantee that this will succeed. 089 * 090 * <h5 class='section'>Example:</h5> 091 * <p class='bjava'> 092 * <ja>@Beanp</ja>(format=<js>"$%.2f"</js>) 093 * <jk>public float</jk> <jf>price</jf>; 094 * </p> 095 * 096 * <p> 097 * This annotation can also be used on private fields of a property like so: 098 * 099 * <h5 class='section'>Example:</h5> 100 * <p class='bjava'> 101 * <jk>public class</jk> MyBean { 102 * 103 * <ja>@Beanp</ja>(format=<js>"$%.2f"</js>) 104 * <jk>private float</jk> <jf>price</jf>; 105 * 106 * <jk>public float</jk> getPrice() { 107 * <jk>return</jk> <jf>price</jf>; 108 * } 109 * } 110 * </p> 111 * 112 * @return The annotation value. 113 */ 114 String format() default ""; 115 116 /** 117 * Identifies the name of the property. 118 * 119 * <p> 120 * Normally, this is automatically inferred from the field name or getter method name of the property. 121 * However, this property can be used to assign a different property name from the automatically inferred value. 122 * 123 * <p> 124 * If the {@link org.apache.juneau.BeanContext.Builder#beanFieldVisibility(Visibility)} setting on the bean context excludes this field (e.g. the 125 * visibility is set to PUBLIC, but the field is PROTECTED), this annotation can be used to force the field to be 126 * identified as a property. 127 * 128 * <h5 class='topic'>Dynamic beans</h5> 129 * <p> 130 * The bean property named <js>"*"</js> is the designated "dynamic property" which allows for "extra" bean 131 * properties not otherwise defined. 132 * This is similar in concept to the Jackson <ja>@JsonGetterAll</ja> and <ja>@JsonSetterAll</ja> annotations. 133 * The primary purpose is for backwards compatibility in parsing newer streams with addition information into older 134 * beans. 135 * 136 * <p> 137 * The following examples show how to define dynamic bean properties. 138 * <p class='bjava'> 139 * <jc>// Option #1 - A simple public Map field. 140 * // The field name can be anything.</jc> 141 * <jk>public class</jk> BeanWithDynaField { 142 * 143 * <ja>@Beanp</ja>(name=<js>"*"</js>) 144 * <jk>public</jk> Map<String,Object> <jf>extraStuff</jf> = <jk>new</jk> LinkedHashMap<>(); 145 * } 146 * 147 * <jc>// Option #2 - Getters and setters. 148 * // Method names can be anything. 149 * // Getter must return a Map with String keys. 150 * // Setter must take in two arguments.</jc> 151 * <jk>public class</jk> BeanWithDynaMethods { 152 * 153 * <ja>@Beanp</ja>(name=<js>"*"</js>) 154 * <jk>public</jk> Map<String,Object> getMyExtraStuff() { 155 * ... 156 * } 157 * 158 * <ja>@Beanp</ja>(name=<js>"*"</js>) 159 * <jk>public void</jk> setAnExtraField(String <jv>name</jv>, Object <jv>value</jv>) { 160 * ... 161 * } 162 * } 163 * 164 * <jc>// Option #3 - Getter only. 165 * // Properties will be added through the getter.</jc> 166 * <jk>public class</jk> BeanWithDynaGetterOnly { 167 * 168 * <ja>@Beanp</ja>(name=<js>"*"</js>) 169 * <jk>public</jk> Map<String,Object> getMyExtraStuff() { 170 * ... 171 * } 172 * } 173 * 174 * <jc>// Option #4 - Getter, setter, and extra-keys method . 175 * // Define a method that returns a Collection<String> with currently-set property names.</jc> 176 * <jk>public class</jk> BeanWithDynaExtraKeys { 177 * 178 * <ja>@Beanp</ja>(name=<js>"*"</js>) 179 * <jk>public</jk> Object get(String <jv>name</jv>) { 180 * ... 181 * } 182 * 183 * <ja>@Beanp</ja>(name=<js>"*"</js>) 184 * <jk>public void</jk> set(String <jv>name</jv>, Object <jv>value</jv>) { 185 * ... 186 * } 187 * 188 * <ja>@Beanp</ja>(name=<js>"*"</js>) 189 * <jk>public</jk> Collection<String> extraKeys() { 190 * ... 191 * } 192 * } 193 * </p> 194 * 195 *<p> 196 * Similar rules apply for value types and swaps. 197 * The property values optionally can be any serializable type or use swaps. 198 * <p class='bjava'> 199 * <jc>// A serializable type other than Object.</jc> 200 * <jk>public class</jk> BeanWithDynaFieldWithListValues { 201 * 202 * <ja>@Beanp</ja>(name=<js>"*"</js>) 203 * <jk>public</jk> Map<String,List<String>> getMyExtraStuff() { 204 * ... 205 * } 206 * } 207 * 208 * <jc>// A swapped value.</jc> 209 * <jk>public class</jk> BeanWithDynaFieldWithSwappedValues { 210 * 211 * <ja>@Beanp</ja>(name=<js>"*"</js>, swap=TemporalCalendarSwap.IsoLocalDateTime.<jk>class</jk>) 212 * <jk>public</jk> Map<String,Calendar> getMyExtraStuff() { 213 * ... 214 * } 215 * } 216 * </p> 217 * 218 * <div class='info'> 219 * Note that if you're not interested in these additional properties, you can also use the 220 * {@link org.apache.juneau.BeanContext.Builder#ignoreUnknownBeanProperties()} setting to ignore values that don't fit into existing 221 * properties. 222 * </div> 223 * <div class='info'> 224 * Note that the {@link Name @Name} annotation can also be used for identifying a property name. 225 * </div> 226 * 227 * @return The annotation value. 228 */ 229 String name() default ""; 230 231 /** 232 * Dynamically apply this annotation to the specified fields/methods. 233 * 234 * <p> 235 * Used in conjunction with {@link org.apache.juneau.BeanContext.Builder#applyAnnotations(Class...)} to dynamically apply an annotation to an existing field/method. 236 * It is ignored when the annotation is applied directly to fields/methods. 237 * 238 * <h5 class='section'>Valid patterns:</h5> 239 * <ul class='spaced-list'> 240 * <li>Methods: 241 * <ul> 242 * <li>Fully qualified with args: 243 * <ul> 244 * <li><js>"com.foo.MyClass.myMethod(String,int)"</js> 245 * <li><js>"com.foo.MyClass.myMethod(java.lang.String,int)"</js> 246 * <li><js>"com.foo.MyClass.myMethod()"</js> 247 * </ul> 248 * <li>Fully qualified: 249 * <ul> 250 * <li><js>"com.foo.MyClass.myMethod"</js> 251 * </ul> 252 * <li>Simple with args: 253 * <ul> 254 * <li><js>"MyClass.myMethod(String,int)"</js> 255 * <li><js>"MyClass.myMethod(java.lang.String,int)"</js> 256 * <li><js>"MyClass.myMethod()"</js> 257 * </ul> 258 * <li>Simple: 259 * <ul> 260 * <li><js>"MyClass.myMethod"</js> 261 * </ul> 262 * <li>Simple inner class: 263 * <ul> 264 * <li><js>"MyClass$Inner1$Inner2.myMethod"</js> 265 * <li><js>"Inner1$Inner2.myMethod"</js> 266 * <li><js>"Inner2.myMethod"</js> 267 * </ul> 268 * </ul> 269 * <li>Fields: 270 * <ul> 271 * <li>Fully qualified: 272 * <ul> 273 * <li><js>"com.foo.MyClass.myField"</js> 274 * </ul> 275 * <li>Simple: 276 * <ul> 277 * <li><js>"MyClass.myField"</js> 278 * </ul> 279 * <li>Simple inner class: 280 * <ul> 281 * <li><js>"MyClass$Inner1$Inner2.myField"</js> 282 * <li><js>"Inner1$Inner2.myField"</js> 283 * <li><js>"Inner2.myField"</js> 284 * </ul> 285 * </ul> 286 * <li>A comma-delimited list of anything on this list. 287 * </ul> 288 * 289 * <h5 class='section'>See Also:</h5><ul> 290 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/DynamicallyAppliedAnnotations">Dynamically Applied Annotations</a> 291 * </ul> 292 * 293 * @return The annotation value. 294 */ 295 String[] on() default {}; 296 297 /** 298 * For bean properties of maps and collections, this annotation can be used to identify the class types of the 299 * contents of the bean property object when the generic parameter types are interfaces or abstract classes. 300 * 301 * <h5 class='section'>Example:</h5> 302 * <p class='bjava'> 303 * <jk>public class</jk> MyBean { 304 * 305 * <jc>// Identify concrete map type with String keys and Integer values.</jc> 306 * <ja>@Beanp</ja>(type=HashMap.<jk>class</jk>, params={String.<jk>class</jk>,Integer.<jk>class</jk>}) 307 * <jk>public</jk> Map <jf>p1</jf>; 308 * } 309 * </p> 310 * 311 * <p> 312 * This annotation can also be used on private fields of a property like so: 313 * 314 * <h5 class='section'>Example:</h5> 315 * <p class='bjava'> 316 * <jk>public class</jk> MyBean { 317 * 318 * <ja>@Beanp</ja>(type=HashMap.<jk>class</jk>, params={String.<jk>class</jk>,Integer.<jk>class</jk>}) 319 * <jk>private</jk> Map <jf>p1</jf>; 320 * 321 * <jk>public</jk> Map getP1() { 322 * <jk>return</jk> <jf>p1</jf>; 323 * } 324 * } 325 * </p> 326 * 327 * @return The annotation value. 328 */ 329 Class<?>[] params() default {}; 330 331 /** 332 * Used to limit which child properties are rendered by the serializers. 333 * 334 * <p> 335 * Can be used on any of the following bean property types: 336 * <ul class='spaced-list'> 337 * <li>Beans - Only render the specified properties of the bean. 338 * <li>Maps - Only render the specified entries in the map. 339 * <li>Bean/Map arrays - Same, but applied to each element in the array. 340 * <li>Bean/Map collections - Same, but applied to each element in the collection. 341 * </ul> 342 * 343 * <h5 class='section'>Example:</h5> 344 * <p class='bjava'> 345 * <jk>public class</jk> MyClass { 346 * 347 * <jc>// Only render 'f1' when serializing this bean property.</jc> 348 * <ja>@Beanp</ja>(properties=<js>"f1"</js>) 349 * <jk>public</jk> MyChildClass <jf>x1</jf> = <jk>new</jk> MyChildClass(); 350 * } 351 * 352 * <jk>public class</jk> MyChildClass { 353 * <jk>public int</jk> <jf>f1</jf> = 1; 354 * <jk>public int</jk> <jf>f2</jf> = 2; 355 * } 356 * 357 * <jc>// Renders "{x1:{f1:1}}"</jc> 358 * String <jv>json</jv> = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jk>new</jk> MyClass()); 359 * </p> 360 * 361 * <p> 362 * This annotation can also be used on private fields of a property like so: 363 * 364 * <h5 class='section'>Example:</h5> 365 * <p class='bjava'> 366 * <jk>public class</jk> MyBean { 367 * 368 * <ja>@Beanp</ja>(properties=<js>"f1"</js>) 369 * <jk>private</jk> MyChildClass <jf>x1</jf>; 370 * 371 * <jk>public</jk> MyChildClass getX1() { 372 * <jk>return</jk> <jf>x1</jf>; 373 * } 374 * } 375 * </p> 376 * 377 * @return The annotation value. 378 */ 379 String properties() default ""; 380 381 /** 382 * Identifies a property as read-only. 383 * 384 * <p> 385 * Serializers will serialize such properties as usual, but parsers will silently ignore them. 386 * 387 * <h5 class='section'>Example:</h5> 388 * <p class='bjava'> 389 * <jk>public class</jk> MyBean { 390 * <ja>@Beanp</ja>(ro=<js>"true"</js>) 391 * <jk>public float</jk> <jf>price</jf>; 392 * } 393 * </p> 394 * 395 * <h5 class='section'>See Also:</h5><ul> 396 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesReadOnly(Class, String)} 397 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesReadOnly(String, String)} 398 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesReadOnly(Map)} 399 * </ul> 400 * 401 * @return The annotation value. 402 */ 403 String ro() default ""; 404 405 /** 406 * Identifies a specialized class type for the property. 407 * 408 * <p> 409 * Normally this can be inferred through reflection of the field type or getter return type. 410 * However, you'll want to specify this value if you're parsing beans where the bean property class is an interface 411 * or abstract class to identify the bean type to instantiate. 412 * Otherwise, you may cause an {@link InstantiationException} when trying to set these fields. 413 * 414 * <p> 415 * This property must denote a concrete bean class with a no-arg constructor. 416 * 417 * <h5 class='section'>Example:</h5> 418 * <p class='bjava'> 419 * <jk>public class</jk> MyBean { 420 * 421 * <jc>// Identify concrete map type.</jc> 422 * <ja>@Beanp</ja>(type=HashMap.<jk>class</jk>) 423 * <jk>public</jk> Map <jf>p1</jf>; 424 * } 425 * </p> 426 * 427 * <p> 428 * This annotation can also be used on private fields of a property like so: 429 * 430 * <h5 class='section'>Example:</h5> 431 * <p class='bjava'> 432 * <jk>public class</jk> MyBean { 433 * 434 * <ja>@Beanp</ja>(type=HashMap.<jk>class</jk>) 435 * <jk>private</jk> Map <jf>p1</jf>; 436 * 437 * <jk>public</jk> Map getP1() { 438 * <jk>return</jk> <jf>p1</jf>; 439 * } 440 * } 441 * </p> 442 * 443 * @return The annotation value. 444 */ 445 Class<?> type() default void.class; 446 447 /** 448 * A synonym for {@link #name()}. 449 * 450 * <p> 451 * The following annotations are equivalent: 452 * 453 * <p class='bjava'> 454 * <ja>@Beanp</ja>(name=<js>"foo"</js>) 455 * 456 * <ja>@Beanp</ja>(<js>"foo"</js>) 457 * </p> 458 * 459 * @return The annotation value. 460 */ 461 String value() default ""; 462 463 /** 464 * Identifies a property as write-only. 465 * 466 * <p> 467 * Parsers will parse such properties as usual, but serializers will silently ignore them. 468 * 469 * <h5 class='section'>Example:</h5> 470 * <p class='bjava'> 471 * <jk>public class</jk> MyBean { 472 * <ja>@Beanp</ja>(wo=<js>"true"</js>) 473 * <jk>public float</jk> <jf>price</jf>; 474 * } 475 * </p> 476 * 477 * <h5 class='section'>See Also:</h5><ul> 478 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesWriteOnly(Class, String)} 479 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesWriteOnly(String, String)} 480 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanPropertiesWriteOnly(Map)} 481 * </ul> 482 * 483 * @return The annotation value. 484 */ 485 String wo() default ""; 486}