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 * <h5 class='section'>See Also:</h5>
029 * <ul>
030 *    <li class='link'><a class="doclink" href="../../../../overview-summary.html#juneau-marshall.BeanPropertyAnnotation">Overview &gt; juneau-marshall &gt; @BeanProperty Annotation</a>
031 * </ul>
032 */
033@Documented
034@Target({FIELD,METHOD})
035@Retention(RUNTIME)
036@Inherited
037public @interface BeanProperty {
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'>
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>@BeanProperty</ja>(name=<js>"*"</js>)
067    *       <jk>public</jk> Map&lt;String,Object&gt; extraStuff = <jk>new</jk> LinkedHashMap&lt;String,Object&gt;();
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>@BeanProperty</ja>(name=<js>"*"</js>)
077    *       <jk>public</jk> Map&lt;String,Object&gt; getMyExtraStuff() {
078    *          ...
079    *       }
080    * 
081    *       <ja>@BeanProperty</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>@BeanProperty</ja>(name=<js>"*"</js>)
092    *       <jk>public</jk> Map&lt;String,Object&gt; getMyExtraStuff() {
093    *          ...
094    *       }
095    *    }
096    * </p>
097    * 
098    *<p>
099    * Similar rules apply for value types and swaps.
100    * The property values optionally can be any serializable type or use swaps.
101    * <p class='bcode'>
102    *    <jc>// A serializable type other than Object.</jc>
103    *    <jk>public class</jk> BeanWithDynaFieldWithListValues {
104    * 
105    *       <ja>@BeanProperty</ja>(name=<js>"*"</js>)
106    *       <jk>public</jk> Map&lt;String,List&lt;String&gt;&gt; getMyExtraStuff() {
107    *          ...
108    *       }
109    *    }
110    * 
111    *    <jc>// A swapped value.</jc>
112    *    <jk>public class</jk> BeanWithDynaFieldWithSwappedValues {
113    * 
114    *       <ja>@BeanProperty</ja>(name=<js>"*"</js>, swap=CalendarSwap.<jsf>ISO8601DTZ</jsf>.<jk>class</jk>)
115    *       <jk>public</jk> Map&lt;String,Calendar&gt; getMyExtraStuff() {
116    *          ...
117    *       }
118    *    }
119    * </p>
120    * 
121    * <ul class='doctree'>
122    *    <li class='info'>
123    *       Note that if you're not interested in these additional properties, you can also use the
124    *       {@link BeanContext#BEAN_ignoreUnknownBeanProperties} setting to ignore values that don't fit into existing
125    *       properties.
126    * </ul>
127    */
128   String name() default "";
129
130   /**
131    * A synonym for {@link #name()}.
132    * 
133    * <p>
134    * The following annotations are equivalent:
135    * 
136    * <p class='bcode'>
137    *    <ja>@BeanProperty</ja>(name=<js>"foo"</js>)
138    * 
139    *    <ja>@BeanProperty</ja>(<js>"foo"</js>)
140    * </p>
141    */
142   String value() default "";
143
144   /**
145    * Identifies a specialized class type for the property.
146    * 
147    * <p>
148    * Normally this can be inferred through reflection of the field type or getter return type.
149    * However, you'll want to specify this value if you're parsing beans where the bean property class is an interface
150    * or abstract class to identify the bean type to instantiate.
151    * Otherwise, you may cause an {@link InstantiationException} when trying to set these fields.
152    * 
153    * <p>
154    * This property must denote a concrete bean class with a no-arg constructor.
155    * 
156    * <h5 class='section'>Example:</h5>
157    * <p class='bcode'>
158    *    <jk>public class</jk> MyBean {
159    * 
160    *       <jc>// Identify concrete map type.</jc>
161    *       <ja>@BeanProperty</ja>(type=HashMap.<jk>class</jk>)
162    *       <jk>public</jk> Map <jf>p1</jf>;
163    *    }
164    * </p>
165    */
166   Class<?> type() default Object.class;
167
168   /**
169    * For bean properties of maps and collections, this annotation can be used to identify the class types of the
170    * contents of the bean property object when the generic parameter types are interfaces or abstract classes.
171    * 
172    * <h5 class='section'>Example:</h5>
173    * <p class='bcode'>
174    *    <jk>public class</jk> MyBean {
175    * 
176    *       <jc>// Identify concrete map type with String keys and Integer values.</jc>
177    *       <ja>@BeanProperty</ja>(type=HashMap.<jk>class</jk>, params={String.<jk>class</jk>,Integer.<jk>class</jk>})
178    *       <jk>public</jk> Map <jf>p1</jf>;
179    *    }
180    * </p>
181    */
182   Class<?>[] params() default {};
183
184   /**
185    * Used to limit which child properties are rendered by the serializers.
186    * 
187    * <p>
188    * Can be used on any of the following bean property types:
189    * <ul class='spaced-list'>
190    *    <li>Beans - Only render the specified properties of the bean.
191    *    <li>Maps - Only render the specified entries in the map.
192    *    <li>Bean/Map arrays - Same, but applied to each element in the array.
193    *    <li>Bean/Map collections - Same, but applied to each element in the collection.
194    * </ul>
195    * 
196    * <h5 class='section'>Example:</h5>
197    * <p class='bcode'>
198    *    <jk>public class</jk> MyClass {
199    * 
200    *       <jc>// Only render 'f1' when serializing this bean property.</jc>
201    *       <ja>@BeanProperty</ja>(properties=<js>"f1"</js>)
202    *       <jk>public</jk> MyChildClass x1 = <jk>new</jk> MyChildClass();
203    *    }
204    * 
205    *    <jk>public class</jk> MyChildClass {
206    *       <jk>public int</jk> f1 = 1;
207    *       <jk>public int</jk> f2 = 2;
208    *    }
209    * 
210    *    <jc>// Renders "{x1:{f1:1}}"</jc>
211    *    String json = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jk>new</jk> MyClass());
212    * </p>
213    */
214   String properties() default "";
215
216   /**
217    * Bean dictionary.
218    * 
219    * <p>
220    * The list of classes that make up the bean dictionary this bean property.
221    * 
222    * <h5 class='section'>See Also:</h5>
223    * <ul>
224    *    <li class='jf'>{@link BeanContext#BEAN_beanDictionary}
225    * </ul>
226    */
227   Class<?>[] beanDictionary() default {};
228
229   /**
230    * Specifies a String format for converting the bean property value to a formatted string.
231    * 
232    * <p>
233    * Note that this is usually a one-way conversion during serialization.
234    * 
235    * <p>
236    * During parsing, we will attempt to convert the value to the original form by using the
237    * {@link BeanSession#convertToType(Object, Class)} but there is no guarantee that this will succeed.
238    * 
239    * <h5 class='section'>Example:</h5>
240    * <p class='bcode'>
241    *    <ja>@BeanProperty</ja>(format=<js>"$%.2f"</js>)
242    *    <jk>public float</jk> <jf>price</jf>;
243    * </p>
244    */
245   String format() default "";
246}