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