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