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 * Maps constructor arguments to property names on beans with read-only properties.
024 *
025 * <p>
026 * Can be used in the following locations:
027 * <ul>
028 *    <li>Bean constructors.
029 *    <li><ja>@Rest</ja>-annotated classes and <ja>@RestOp</ja>-annotated methods when an {@link #on()} value is specified.
030 * </ul>
031
032 * <p>
033 * This annotation can be used in the case of beans with properties whose values can only be set by passing them in
034 * through a constructor on the class.
035 * <br>Since method parameter names are lost during compilation, this annotation essentially redefines them so that they
036 * are available at runtime.
037 *
038 * <p>
039 * This annotation can only be applied to constructors and can only be applied to one constructor per class.
040 *
041 * <p>
042 * When present, bean instantiation is delayed until the call to {@link BeanMap#getBean()}.
043 * Until then, bean property values are stored in a local cache until <c>getBean()</c> is called.
044 * Because of this additional caching step, parsing into read-only beans tends to be slower and use more memory than
045 * parsing into beans with writable properties.
046 *
047 * <p>
048 * Attempting to call {@link BeanMap#put(String,Object)} on a read-only property after calling {@link BeanMap#getBean()}
049 * will result in a {@link BeanRuntimeException} being thrown.
050 * Multiple calls to {@link BeanMap#getBean()} will return the same bean instance.
051 *
052 * <h5 class='section'>See Also:</h5><ul>
053 *    <li class='link'><a class="doclink" href="../../../../index.html#jm.BeancAnnotation">@Beanc Annotation</a>
054 * </ul>
055 */
056@Documented
057@Target({METHOD,TYPE,CONSTRUCTOR})
058@Retention(RUNTIME)
059@Inherited
060@Repeatable(BeancAnnotation.Array.class)
061@ContextApply(BeancAnnotation.Applier.class)
062public @interface Beanc {
063
064   /**
065    * Dynamically apply this annotation to the specified constructors.
066    *
067    * <p>
068    * Used in conjunction with {@link org.apache.juneau.BeanContext.Builder#applyAnnotations(Class...)} to dynamically apply an annotation to an existing constructor.
069    * It is ignored when the annotation is applied directly to constructors.
070    *
071    * <p>
072    * The following example shows this annotation in use:
073    * <p class='bjava'>
074    *    <jc>// Our read-only bean.</jc>
075    *    <jk>public class</jk> Person {
076    *       <jk>private final</jk> String <jf>name</jf>;
077    *       <jk>private final int</jk> <jf>age</jf>;
078    *
079    *       <jk>public</jk> Person(String <jv>name</jv>, <jk>int</jk> <jv>age</jv>) {
080    *          <jk>this</jk>.<jf>name</jf> = <jv>name</jv>;
081    *          <jk>this</jk>.<jf>age</jf> = <jv>age</jv>;
082    *       }
083    *
084    *       <jc>// Read only properties.</jc>
085    *       <jc>// Getters, but no setters.</jc>
086    *
087    *       <jk>public</jk> String getName() {
088    *          <jk>return</jk> <jf>name</jf>;
089    *       }
090    *
091    *       <jk>public int</jk> getAge() {
092    *          <jk>return</jk> <jf>age</jf>;
093    *       }
094    *    }
095    *
096    *    <ja>@BeanConfig</ja>
097    *    <ja>@Beanc</ja>(on=<js>"Person(String,int)"</js>, properties=<js>"name,age"</js>))
098    *    <jk>public static class</jk> MyConfig {}
099    * </p>
100    * <p class='bjava'>
101    *    <jc>// Parsing into a read-only bean.</jc>
102    *    String <jv>json</jv> = <js>"{name:'John Smith',age:45}"</js>;
103    *    Person <jv>person</jv> = JsonParser.<jsf>DEFAULT</jsf>.copy().applyAnnotations(MyConfig.<jk>class</jk>).build().parse(<jv>json</jv>);
104    *    String <jv>name</jv> = <jv>person</jv>.getName();  <jc>// "John Smith"</jc>
105    *    <jk>int</jk> <jv>age</jv> = <jv>person</jv>.getAge();   <jc>// 45</jc>
106    * </p>
107    *
108    * <h5 class='section'>Valid patterns:</h5>
109    * <ul class='spaced-list'>
110    *    <li>Constructors:
111    *       <ul>
112    *          <li>Fully qualified with args:
113    *             <ul>
114    *                <li><js>"com.foo.MyClass(String,int)"</js>
115    *                <li><js>"com.foo.MyClass(java.lang.String,int)"</js>
116    *                <li><js>"com.foo.MyClass()"</js>
117    *             </ul>
118    *          <li>Simple with args:
119    *             <ul>
120    *                <li><js>"MyClass(String,int)"</js>
121    *                <li><js>"MyClass(java.lang.String,int)"</js>
122    *                <li><js>"MyClass()"</js>
123    *             </ul>
124    *          <li>Simple inner class:
125    *             <ul>
126    *                <li><js>"MyClass$Inner1$Inner2()"</js>
127    *                <li><js>"Inner1$Inner2()"</js>
128    *                <li><js>"Inner2()"</js>
129    *             </ul>
130    *       </ul>
131    *    <li>A comma-delimited list of anything on this list.
132    * </ul>
133    *
134    * <h5 class='section'>See Also:</h5><ul>
135    *    <li class='link'><a class="doclink" href="../../../../index.html#jm.DynamicallyAppliedAnnotations">Dynamically Applied Annotations</a>
136    * </ul>
137    *
138    * @return The annotation value.
139    */
140   String[] on() default {};
141
142   /**
143    * The names of the properties of the constructor arguments.
144    *
145    * <p>
146    * The {@link org.apache.juneau.annotation.Beanc @Beanc} annotation is used to map constructor arguments to property
147    * names on bean with read-only properties.
148    * <br>Since method parameter names are lost during compilation, this annotation essentially redefines them so that
149    * they are available at runtime.
150    *
151    * <p>
152    * The definition of a read-only bean is a bean with properties with only getters, like shown below:
153    * <p class='bjava'>
154    *    <jc>// Our read-only bean.</jc>
155    *    <jk>public class</jk> Person {
156    *       <jk>private final</jk> String <jf>name</jf>;
157    *       <jk>private final int</jk> <jf>age</jf>;
158    *
159    *       <ja>@Beanc</ja>(properties=<js>"name,age"</js>)
160    *       <jk>public</jk> Person(String <jv>name</jv>, <jk>int</jk> <jv>age</jv>) {
161    *          <jk>this</jk>.<jf>name</jf> = <jv>name</jv>;
162    *          <jk>this</jk>.<jf>age</jf> = <jv>age</jv>;
163    *       }
164    *
165    *       <jc>// Read only properties.</jc>
166    *       <jc>// Getters, but no setters.</jc>
167    *
168    *       <jk>public</jk> String getName() {
169    *          <jk>return</jk> <jf>name</jf>;
170    *       }
171    *
172    *       <jk>public int</jk> getAge() {
173    *          <jk>return</jk> <jf>age</jf>;
174    *       }
175    *    }
176    * </p>
177    * <p class='bjava'>
178    *    <jc>// Parsing into a read-only bean.</jc>
179    *    String <jv>json</jv> = <js>"{name:'John Smith',age:45}"</js>;
180    *    Person <jv>person</jv> = JsonParser.<jsf>DEFAULT</jsf>.parse(<jv>json</jv>);
181    *    String <jv>name</jv> = <jv>person</jv>.getName();  <jc>// "John Smith"</jc>
182    *    <jk>int</jk> <jv>age</jv> = <jv>person</jv>.getAge();   <jc>// 45</jc>
183    * </p>
184    * <p>
185    *    Note that the {@link Name @Name} annotation can also be used to identify bean property names on constructor
186    *    arguments.  If neither this annotation or {@link Name @Name} is used, then we try to get the property names
187    *    from the parameter names if they are available in the bytecode.
188    * </p>
189    *
190    * @return The annotation value.
191    */
192   String properties() default "";
193}