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