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