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.commons.bean;
018
019import static java.lang.annotation.ElementType.*;
020import static java.lang.annotation.RetentionPolicy.*;
021
022import java.lang.annotation.*;
023import java.util.*;
024import java.util.stream.*;
025
026import org.apache.juneau.commons.function.*;
027import org.apache.juneau.commons.inject.*;
028
029/**
030 * Annotation that can be applied to bean fields, getter/setter methods, and constructor parameters
031 * to control bean introspection and property modeling.
032 *
033 * <p>
034 * The bean-modeling sibling of {@code @MarshalledProp}.
035 * Where {@code @MarshalledProp} (in <c>juneau-marshall</c>) carries the marshalling-only attributes
036 * (such as {@code dictionary}, {@code format}, and {@code properties}), this annotation carries the
037 * attributes that describe the bean property itself — its name, accessibility (read/write only),
038 * concrete type, generic type parameters, element type, and the bean factory used to instantiate
039 * its value.
040 *
041 * <p>
042 * Splitting the annotations lets a property participate in the bean model (for example, to declare
043 * its name or read-only semantics) without dragging in any marshalling concerns, and lets the
044 * bean-modeling layer live in <c>juneau-commons</c> independent of <c>juneau-marshall</c>.
045 *
046 * <p>
047 * Can be used in the following locations:
048 * <ul>
049 *    <li>Bean fields, getter methods, and setter methods.
050 *    <li>Constructor parameters.
051 * </ul>
052 *
053 * <h5 class='section'>See Also:</h5><ul>
054 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/BeanPropAnnotation">@BeanProp Annotation</a>
055 * </ul>
056 */
057@Documented
058@Target({ FIELD, METHOD, PARAMETER })
059@Retention(RUNTIME)
060@Inherited
061public @interface BeanProp {
062
063   /**
064    * Optional description for the exposed API.
065    *
066    * @return The annotation value.
067    * @since 9.2.0
068    */
069   String[] description() default {};
070
071   /**
072    * Short, concise summary of the exposed API.
073    *
074    * <p>
075    * Intended as a brief, single-line description suitable for AI/LLM consumption, compact documentation,
076    * or any context where brevity matters. See {@link org.apache.juneau.commons.Schema#summary()}
077    * for the canonical definition; this field is the bean-property-level counterpart.
078    *
079    * @return The annotation value.
080    * @since 10.0.0
081    */
082   String summary() default "";
083
084   /**
085    * Element type for streaming/consuming bean properties.
086    *
087    * <p>
088    * Specifies the element type for properties of type {@link Stream},
089    * {@link BeanSupplier},
090    * {@link BeanConsumer}, or
091    * {@link BeanChannel} when type erasure prevents
092    * the framework from inferring the generic type argument at runtime.
093    *
094    * <p>
095    * This attribute also supports:
096    * <ul>
097    *    <li><b>Narrowing</b> - Specify a more specific subtype than the declared type
098    *    <li><b>Concrete implementation</b> - Specify a concrete class for an abstract/interface element type
099    * </ul>
100    *
101    * <h5 class='section'>Example:</h5>
102    * <p class='bjava'>
103    *    <jk>public class</jk> OrderCollection {
104    *       <jc>// Stream property - element type cannot be inferred at runtime due to erasure</jc>
105    *       <ja>@BeanProp</ja>(elementType=Order.<jk>class</jk>)
106    *       <jk>public</jk> Stream&lt;Order&gt; getOrders() { ... }
107    *
108    *       <jc>// BeanChannel with concrete impl specified instead of abstract element type</jc>
109    *       <ja>@BeanProp</ja>(elementType=ConcreteItem.<jk>class</jk>)
110    *       <jk>public</jk> BeanChannel&lt;AbstractItem&gt; getItems() { ... }
111    *    }
112    * </p>
113    *
114    * <h5 class='section'>See Also:</h5><ul>
115    *    <li class='jc'>{@link BeanSupplier}
116    *    <li class='jc'>{@link BeanConsumer}
117    *    <li class='jc'>{@link BeanChannel}
118    * </ul>
119    *
120    * @return The annotation value.
121    */
122   Class<?> elementType() default void.class;
123
124   /**
125    * Bean factory class for this property's value.
126    *
127    * <p>
128    * Specifies a {@link BeanFactory} class to use when instantiating
129    * the value of this specific bean property, overriding the class-level {@link BeanType#factory()} if present.
130    *
131    * <p>
132    * When a factory class is specified, the framework resolves it in the following order:
133    * <ol>
134    *    <li>Look up the factory class in the configured {@link BeanStore}
135    *    <li>Attempt direct instantiation via no-arg constructor or {@code getInstance()} static method
136    *    <li>Throw {@link IllegalArgumentException} if both fail
137    * </ol>
138    *
139    * <h5 class='section'>Example:</h5>
140    * <p class='bjava'>
141    *    <jk>public class</jk> MyBean {
142    *       <ja>@BeanProp</ja>(factory=ItemChannelFactory.<jk>class</jk>, elementType=Item.<jk>class</jk>)
143    *       <jk>public</jk> BeanChannel&lt;Item&gt; getItems() { ... }
144    *    }
145    * </p>
146    *
147    * <h5 class='section'>See Also:</h5><ul>
148    *    <li class='jc'>{@link BeanFactory}
149    *    <li class='ja'>{@link BeanType#factory()}
150    * </ul>
151    *
152    * @return The annotation value.
153    */
154   @SuppressWarnings({
155      "rawtypes" // Raw BeanFactory type required for annotation attribute declaration
156   })
157   Class<? extends BeanFactory> factory() default BeanFactory.Void.class;
158
159   /**
160    * Identifies the name of the property.
161    *
162    * <p>
163    * Normally, this is automatically inferred from the field name or getter method name of the property.
164    * However, this property can be used to assign a different property name from the automatically inferred value.
165    *
166    * <h5 class='topic'>Dynamic beans</h5>
167    * <p>
168    * On a <strong>field</strong> whose type is not a {@link Map}, <js>"*"</js> does not create a dynamic property:
169    * the property name is the field name (same as omitting {@code name}/{@code value}), while other attributes on
170    * this annotation still apply.
171    * </p>
172    * <p>
173    * The bean property named <js>"*"</js> is the designated "dynamic property" which allows for "extra" bean
174    * properties not otherwise defined.
175    *
176    * <p>
177    * The following examples show how to define dynamic bean properties.
178    * <p class='bjava'>
179    *    <jc>// Option #1 - A simple public Map field.
180    *    // The field name can be anything.</jc>
181    *    <jk>public class</jk> BeanWithDynaField {
182    *
183    *       <ja>@BeanProp</ja>(name=<js>"*"</js>)
184    *       <jk>public</jk> Map&lt;String,Object&gt; <jf>extraStuff</jf> = <jk>new</jk> LinkedHashMap&lt;&gt;();
185    *    }
186    *
187    *    <jc>// Option #2 - Getters and setters.
188    *    // Method names can be anything.
189    *    // Getter must return a Map with String keys.
190    *    // Setter must take in two arguments.</jc>
191    *    <jk>public class</jk> BeanWithDynaMethods {
192    *
193    *       <ja>@BeanProp</ja>(name=<js>"*"</js>)
194    *       <jk>public</jk> Map&lt;String,Object&gt; getMyExtraStuff() {
195    *          ...
196    *       }
197    *
198    *       <ja>@BeanProp</ja>(name=<js>"*"</js>)
199    *       <jk>public void</jk> setAnExtraField(String <jv>name</jv>, Object <jv>value</jv>) {
200    *          ...
201    *       }
202    *    }
203    * </p>
204    *
205    * <div class='info'>
206    *       Note that the {@link Name @Name} annotation can also be used for identifying a property name.
207    * </div>
208    *
209    * @return The annotation value.
210    */
211   String name() default "";
212
213   /**
214    * For bean properties of maps and collections, this annotation can be used to identify the class types of the
215    * contents of the bean property object when the generic parameter types are interfaces or abstract classes.
216    *
217    * <h5 class='section'>Example:</h5>
218    * <p class='bjava'>
219    *    <jk>public class</jk> MyBean {
220    *
221    *       <jc>// Identify concrete map type with String keys and Integer values.</jc>
222    *       <ja>@BeanProp</ja>(type=HashMap.<jk>class</jk>, params={String.<jk>class</jk>,Integer.<jk>class</jk>})
223    *       <jk>public</jk> Map <jf>p1</jf>;
224    *    }
225    * </p>
226    *
227    * @return The annotation value.
228    */
229   Class<?>[] params() default {};
230
231   /**
232    * Marks this property as required on input.
233    *
234    * <p>
235    * When <jk>true</jk>, parsers (and {@code Map}-to-bean conversion) throw a
236    * {@code org.apache.juneau.marshall.parser.MissingRequiredPropertyException} if the input does not contain this
237    * property.  The check runs once per bean, before the bean is constructed, so records and constructor-argument
238    * beans get a clear error instead of a constructor failure.
239    *
240    * <p>
241    * "Present" means the key appears in the input.  An explicit <jk>null</jk> value counts as present; use your own
242    * validation (or a compact record constructor) to reject null values.
243    *
244    * <p>
245    * The flag is OR-merged across the field, getter and setter: annotating any one of them makes the property required.
246    * Wrapping an existing object (for example {@code MarshallingSession.toBeanMap(Object)}) never checks.
247    *
248    * <p>
249    * This attribute is independent of {@code @Schema(required)}, which only affects generated schema documentation and
250    * HTTP part validation.
251    *
252    * <h5 class='section'>Example:</h5>
253    * <p class='bjava'>
254    *    <jk>public record</jk> Person(<ja>@BeanProp</ja>(required=<jk>true</jk>) String <jv>name</jv>, Integer <jv>age</jv>) {}
255    *
256    *    <jc>// Throws MissingRequiredPropertyException:
257    *    //   Missing required properties on bean class 'Person': [name]</jc>
258    *    JsonParser.<jsf>DEFAULT</jsf>.read(<js>"{\"age\":30}"</js>, Person.<jk>class</jk>);
259    *
260    *    <jc>// OK: explicit null counts as present.</jc>
261    *    JsonParser.<jsf>DEFAULT</jsf>.read(<js>"{\"name\":null}"</js>, Person.<jk>class</jk>);
262    * </p>
263    *
264    * <h5 class='section'>Notes:</h5><ul>
265    *    <li class='note'>
266    *       A required property must be writable (a field, setter or constructor argument).  Marking a read-only
267    *       property required fails when the bean metadata is built.
268    *    <li class='note'>
269    *       For builder-based beans, put the annotation on the builder's setter.
270    *    <li class='note'>
271    *       On a non-record bean, put the annotation on the field or getter; it is not read from constructor parameters.
272    *    <li class='note'>
273    *       In REST methods, a missing required property in an {@code @Content} body produces <c>400 Bad Request</c>.
274    * </ul>
275    *
276    * @return <jk>true</jk> if this property must be present in the input.
277    */
278   boolean required() default false;
279
280   /**
281    * Identifies a property as read-only.
282    *
283    * <p>
284    * Serializers will serialize such properties as usual, but parsers will silently ignore them.
285    *
286    * <h5 class='section'>Example:</h5>
287    * <p class='bjava'>
288    *    <jk>public class</jk> MyBean {
289    *       <ja>@BeanProp</ja>(ro=<js>"true"</js>)
290    *       <jk>public float</jk> <jf>price</jf>;
291    *    }
292    * </p>
293    *
294    * <h5 class='section'>Notes:</h5><ul>
295    *    <li class='note'>
296    *       <b>Java Records:</b> Marking record components as read-only is not supported during parsing.
297    *       Because records are immutable, all components must be provided to the canonical constructor.
298    *       Read-only components will be serialized as usual, but the parser will be unable to instantiate the
299    *       record if the read-only component values are missing from the input.
300    * </ul>
301    *
302    * @return The annotation value.
303    */
304   String ro() default "";
305
306   /**
307    * Identifies a specialized class type for the property.
308    *
309    * <p>
310    * Normally this can be inferred through reflection of the field type or getter return type.
311    * However, you'll want to specify this value if you're parsing beans where the bean property class is an interface
312    * or abstract class to identify the bean type to instantiate.
313    * Otherwise, you may cause an {@link InstantiationException} when trying to set these fields.
314    *
315    * <p>
316    * This property must denote a concrete bean class with a no-arg constructor.
317    *
318    * <h5 class='section'>Example:</h5>
319    * <p class='bjava'>
320    *    <jk>public class</jk> MyBean {
321    *
322    *       <jc>// Identify concrete map type.</jc>
323    *       <ja>@BeanProp</ja>(type=HashMap.<jk>class</jk>)
324    *       <jk>public</jk> Map <jf>p1</jf>;
325    *    }
326    * </p>
327    *
328    * @return The annotation value.
329    */
330   Class<?> type() default void.class;
331
332   /**
333    * A synonym for {@link #name()}.
334    *
335    * <p>
336    * The following annotations are equivalent:
337    *
338    * <p class='bjava'>
339    *    <ja>@BeanProp</ja>(name=<js>"foo"</js>)
340    *
341    *    <ja>@BeanProp</ja>(<js>"foo"</js>)
342    * </p>
343    *
344    * @return The annotation value.
345    */
346   String value() default "";
347
348   /**
349    * Identifies a property as write-only.
350    *
351    * <p>
352    * Parsers will parse such properties as usual, but serializers will silently ignore them.
353    *
354    * <h5 class='section'>Example:</h5>
355    * <p class='bjava'>
356    *    <jk>public class</jk> MyBean {
357    *       <ja>@BeanProp</ja>(wo=<js>"true"</js>)
358    *       <jk>public float</jk> <jf>price</jf>;
359    *    }
360    * </p>
361    *
362    * @return The annotation value.
363    */
364   String wo() default "";
365}