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 * <div class='warn'> 033 * <b>Deprecated</b> - {@link Beanp}. 034 * </div> 035 */ 036@Documented 037@Target({FIELD,METHOD,PARAMETER}) 038@Retention(RUNTIME) 039@Inherited 040@Deprecated 041public @interface BeanProperty { 042 043 /** 044 * Identifies the name of the property. 045 * 046 * <p> 047 * Normally, this is automatically inferred from the field name or getter method name of the property. 048 * However, this property can be used to assign a different property name from the automatically inferred value. 049 * 050 * <p> 051 * If the {@link BeanContext#BEAN_beanFieldVisibility} setting on the bean context excludes this field (e.g. the 052 * visibility is set to PUBLIC, but the field is PROTECTED), this annotation can be used to force the field to be 053 * identified as a property. 054 * 055 * <h5 class='topic'>Dynamic beans</h5> 056 * <p> 057 * The bean property named <js>"*"</js> is the designated "dynamic property" which allows for "extra" bean 058 * properties not otherwise defined. 059 * This is similar in concept to the Jackson <ja>@JsonGetterAll</ja> and <ja>@JsonSetterAll</ja> annotations. 060 * The primary purpose is for backwards compatibility in parsing newer streams with addition information into older 061 * beans. 062 * 063 * <p> 064 * The following examples show how to define dynamic bean properties. 065 * <p class='bcode w800'> 066 * <jc>// Option #1 - A simple public Map field. 067 * // The field name can be anything.</jc> 068 * <jk>public class</jk> BeanWithDynaField { 069 * 070 * <ja>@BeanProperty</ja>(name=<js>"*"</js>) 071 * <jk>public</jk> Map<String,Object> extraStuff = <jk>new</jk> LinkedHashMap<String,Object>(); 072 * } 073 * 074 * <jc>// Option #2 - Getters and setters. 075 * // Method names can be anything. 076 * // Getter must return a Map with String keys. 077 * // Setter must take in two arguments.</jc> 078 * <jk>public class</jk> BeanWithDynaMethods { 079 * 080 * <ja>@BeanProperty</ja>(name=<js>"*"</js>) 081 * <jk>public</jk> Map<String,Object> getMyExtraStuff() { 082 * ... 083 * } 084 * 085 * <ja>@BeanProperty</ja>(name=<js>"*"</js>) 086 * <jk>public void</jk> setAnExtraField(String name, Object value) { 087 * ... 088 * } 089 * } 090 * 091 * <jc>// Option #3 - Getter only. 092 * // Properties will be added through the getter.</jc> 093 * <jk>public class</jk> BeanWithDynaGetterOnly { 094 * 095 * <ja>@BeanProperty</ja>(name=<js>"*"</js>) 096 * <jk>public</jk> Map<String,Object> getMyExtraStuff() { 097 * ... 098 * } 099 * } 100 * 101 * <jc>// Option #4 - Getter, setter, and extra-keys method . 102 * // Define a method that returns a Collection<String> with currently-set property names.</jc> 103 * <jk>public class</jk> BeanWithDynaExtraKeys { 104 * 105 * <ja>@BeanProperty</ja>(name=<js>"*"</js>) 106 * <jk>public</jk> Object get(String name) { 107 * ... 108 * } 109 * 110 * <ja>@BeanProperty</ja>(name=<js>"*"</js>) 111 * <jk>public void</jk> set(String name, Object value) { 112 * ... 113 * } 114 * 115 * <ja>@BeanProperty</ja>(name=<js>"*"</js>) 116 * <jk>public</jk> Collection<String> extraKeys() { 117 * ... 118 * } 119 * } 120 * </p> 121 * 122 *<p> 123 * Similar rules apply for value types and swaps. 124 * The property values optionally can be any serializable type or use swaps. 125 * <p class='bcode w800'> 126 * <jc>// A serializable type other than Object.</jc> 127 * <jk>public class</jk> BeanWithDynaFieldWithListValues { 128 * 129 * <ja>@BeanProperty</ja>(name=<js>"*"</js>) 130 * <jk>public</jk> Map<String,List<String>> getMyExtraStuff() { 131 * ... 132 * } 133 * } 134 * 135 * <jc>// A swapped value.</jc> 136 * <jk>public class</jk> BeanWithDynaFieldWithSwappedValues { 137 * 138 * <ja>@BeanProperty</ja>(name=<js>"*"</js>, swap=TemporalCalendarSwap.IsoLocalDateTime.<jk>class</jk>) 139 * <jk>public</jk> Map<String,Calendar> getMyExtraStuff() { 140 * ... 141 * } 142 * } 143 * </p> 144 * 145 * <div class='info'> 146 * Note that if you're not interested in these additional properties, you can also use the 147 * {@link BeanContext#BEAN_ignoreUnknownBeanProperties} setting to ignore values that don't fit into existing 148 * properties. 149 * </div> 150 * <div class='info'> 151 * Note that the {@link Name @Name} annotation can also be used for identifying a property name. 152 * </div> 153 */ 154 String name() default ""; 155 156 /** 157 * A synonym for {@link #name()}. 158 * 159 * <p> 160 * The following annotations are equivalent: 161 * 162 * <p class='bcode w800'> 163 * <ja>@BeanProperty</ja>(name=<js>"foo"</js>) 164 * 165 * <ja>@BeanProperty</ja>(<js>"foo"</js>) 166 * </p> 167 */ 168 String value() default ""; 169 170 /** 171 * Identifies a specialized class type for the property. 172 * 173 * <p> 174 * Normally this can be inferred through reflection of the field type or getter return type. 175 * However, you'll want to specify this value if you're parsing beans where the bean property class is an interface 176 * or abstract class to identify the bean type to instantiate. 177 * Otherwise, you may cause an {@link InstantiationException} when trying to set these fields. 178 * 179 * <p> 180 * This property must denote a concrete bean class with a no-arg constructor. 181 * 182 * <h5 class='section'>Example:</h5> 183 * <p class='bcode w800'> 184 * <jk>public class</jk> MyBean { 185 * 186 * <jc>// Identify concrete map type.</jc> 187 * <ja>@BeanProperty</ja>(type=HashMap.<jk>class</jk>) 188 * <jk>public</jk> Map <jf>p1</jf>; 189 * } 190 * </p> 191 * 192 * <p> 193 * This annotation can also be used on private fields of a property like so: 194 * 195 * <h5 class='section'>Example:</h5> 196 * <p class='bcode w800'> 197 * <jk>public class</jk> MyBean { 198 * 199 * <ja>@BeanProperty</ja>(type=HashMap.<jk>class</jk>) 200 * <jk>private</jk> Map <jf>p1</jf>; 201 * 202 * <jk>public</jk> Map getP1() { 203 * <jk>return</jk> <jf>p1</jf>; 204 * } 205 * } 206 * </p> 207 */ 208 Class<?> type() default Object.class; 209 210 /** 211 * For bean properties of maps and collections, this annotation can be used to identify the class types of the 212 * contents of the bean property object when the generic parameter types are interfaces or abstract classes. 213 * 214 * <h5 class='section'>Example:</h5> 215 * <p class='bcode w800'> 216 * <jk>public class</jk> MyBean { 217 * 218 * <jc>// Identify concrete map type with String keys and Integer values.</jc> 219 * <ja>@BeanProperty</ja>(type=HashMap.<jk>class</jk>, params={String.<jk>class</jk>,Integer.<jk>class</jk>}) 220 * <jk>public</jk> Map <jf>p1</jf>; 221 * } 222 * </p> 223 * 224 * <p> 225 * This annotation can also be used on private fields of a property like so: 226 * 227 * <h5 class='section'>Example:</h5> 228 * <p class='bcode w800'> 229 * <jk>public class</jk> MyBean { 230 * 231 * <ja>@BeanProperty</ja>(type=HashMap.<jk>class</jk>, params={String.<jk>class</jk>,Integer.<jk>class</jk>}) 232 * <jk>private</jk> Map <jf>p1</jf>; 233 * 234 * <jk>public</jk> Map getP1() { 235 * <jk>return</jk> <jf>p1</jf>; 236 * } 237 * } 238 * </p> 239 */ 240 Class<?>[] params() default {}; 241 242 /** 243 * Used to limit which child properties are rendered by the serializers. 244 * 245 * <p> 246 * Can be used on any of the following bean property types: 247 * <ul class='spaced-list'> 248 * <li>Beans - Only render the specified properties of the bean. 249 * <li>Maps - Only render the specified entries in the map. 250 * <li>Bean/Map arrays - Same, but applied to each element in the array. 251 * <li>Bean/Map collections - Same, but applied to each element in the collection. 252 * </ul> 253 * 254 * <h5 class='section'>Example:</h5> 255 * <p class='bcode w800'> 256 * <jk>public class</jk> MyClass { 257 * 258 * <jc>// Only render 'f1' when serializing this bean property.</jc> 259 * <ja>@BeanProperty</ja>(bpi=<js>"f1"</js>) 260 * <jk>public</jk> MyChildClass x1 = <jk>new</jk> MyChildClass(); 261 * } 262 * 263 * <jk>public class</jk> MyChildClass { 264 * <jk>public int</jk> f1 = 1; 265 * <jk>public int</jk> f2 = 2; 266 * } 267 * 268 * <jc>// Renders "{x1:{f1:1}}"</jc> 269 * String json = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jk>new</jk> MyClass()); 270 * </p> 271 * 272 * <p> 273 * This annotation can also be used on private fields of a property like so: 274 * 275 * <h5 class='section'>Example:</h5> 276 * <p class='bcode w800'> 277 * <jk>public class</jk> MyBean { 278 * 279 * <ja>@BeanProperty</ja>(properties=<js>"f1"</js>) 280 * <jk>private</jk> MyChildClass <jf>x1</jf>; 281 * 282 * <jk>public</jk> MyChildClass getX1() { 283 * <jk>return</jk> <jf>x1</jf>; 284 * } 285 * } 286 * </p> 287 */ 288 String properties() default ""; 289 290 /** 291 * Bean dictionary. 292 * 293 * <p> 294 * The list of classes that make up the bean dictionary this bean property. 295 * 296 * <ul class='seealso'> 297 * <li class='jf'>{@link BeanContext#BEAN_beanDictionary} 298 * </ul> 299 * 300 * <p> 301 * This annotation can also be used on private fields of a property. 302 */ 303 Class<?>[] beanDictionary() default {}; 304 305 /** 306 * Specifies a String format for converting the bean property value to a formatted string. 307 * 308 * <p> 309 * Note that this is usually a one-way conversion during serialization. 310 * 311 * <p> 312 * During parsing, we will attempt to convert the value to the original form by using the 313 * {@link BeanSession#convertToType(Object, Class)} but there is no guarantee that this will succeed. 314 * 315 * <h5 class='section'>Example:</h5> 316 * <p class='bcode w800'> 317 * <ja>@BeanProperty</ja>(format=<js>"$%.2f"</js>) 318 * <jk>public float</jk> <jf>price</jf>; 319 * </p> 320 * 321 * <p> 322 * This annotation can also be used on private fields of a property like so: 323 * 324 * <h5 class='section'>Example:</h5> 325 * <p class='bcode w800'> 326 * <jk>public class</jk> MyBean { 327 * 328 * <ja>@BeanProperty</ja>(format=<js>"$%.2f"</js>) 329 * <jk>private float</jk> <jf>price</jf>; 330 * 331 * <jk>public float</jk> gePrice() { 332 * <jk>return</jk> <jf>price</jf>; 333 * } 334 * } 335 * </p> 336 */ 337 String format() default ""; 338}