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