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.swap.*;
025
026/**
027 * Associates {@link ObjectSwap} and {@link Surrogate} classes with POJOs and bean properties.
028 *
029 * <p>
030 * Can be used in the following locations:
031 * <ul>
032 *    <li>Classes.
033 *    <li>Bean getters/setters/fields.
034 *    <li><ja>@Rest</ja>-annotated classes and <ja>@RestOp</ja>-annotated methods when an {@link #on()} value is specified.
035 * </ul>
036
037 * <h5 class='section'>See Also:</h5><ul>
038 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SwapAnnotation">@Swap Annotation</a>
039
040 * </ul>
041 */
042@Documented
043@Target({TYPE,ANNOTATION_TYPE,FIELD,METHOD})
044@Retention(RUNTIME)
045@Inherited
046@Repeatable(SwapAnnotation.Array.class)
047@ContextApply(SwapAnnotation.Applier.class)
048public @interface Swap {
049
050    /**
051     * Optional description for the exposed API.
052     *
053     * @return The annotation value.
054     * @since 9.2.0
055     */
056    String[] description() default {};
057
058    /**
059    * The {@link ObjectSwap} and {@link Surrogate} class.
060    *
061    * <p>
062    * A synonym for {@link #value()}.
063    *
064    * @return The annotation value.
065    */
066   Class<?> impl() default void.class;
067
068   /**
069    * Identifies the media types that this swap is applicable for.
070    *
071    * <p>
072    * In the following example, the swap is only invoked by the JSON serializer:
073    *
074    * <p class='bjava'>
075    *    <ja>@Swap</ja>(impl=ToStringSwap.<jk>class</jk>, mediaTypes=<js>"&#42;/json"</js>)
076    *    <jk>public class</jk> MyBean { ... }
077    *
078    *    <jk>public class</jk> ToStringSwap <jk>extends</jk> ObjectSwap&lt;Object,String&gt; {
079    *          <jk>public</jk> String swap(BeanSession <jv>session</jv>, Object <jv>value</jv>) <jk>throws</jk> Exception {
080    *             <jk>return</jk> <jv>value</jv>.toString();
081    *          }
082    *       }
083    * </p>
084    *
085    * <h5 class='section'>See Also:</h5><ul>
086    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/PerMediaTypeSwaps">Per-media-type Swaps</a>
087    * </ul>
088    *
089    * @return The annotation value.
090    */
091   String[] mediaTypes() default {};
092
093   /**
094    * Dynamically apply this annotation to the specified classes/methods/fields.
095    *
096    * <p>
097    * Used in conjunction with {@link org.apache.juneau.BeanContext.Builder#applyAnnotations(Class...)} to dynamically apply an annotation to an existing class.
098    * It is ignored when the annotation is applied directly to classes.
099    *
100    * <h5 class='section'>Valid patterns:</h5>
101    * <ul class='spaced-list'>
102    *  <li>Classes:
103    *       <ul>
104    *          <li>Fully qualified:
105    *             <ul>
106    *                <li><js>"com.foo.MyClass"</js>
107    *             </ul>
108    *          <li>Fully qualified inner class:
109    *             <ul>
110    *                <li><js>"com.foo.MyClass$Inner1$Inner2"</js>
111    *             </ul>
112    *          <li>Simple:
113    *             <ul>
114    *                <li><js>"MyClass"</js>
115    *             </ul>
116    *          <li>Simple inner:
117    *             <ul>
118    *                <li><js>"MyClass$Inner1$Inner2"</js>
119    *                <li><js>"Inner1$Inner2"</js>
120    *                <li><js>"Inner2"</js>
121    *             </ul>
122    *       </ul>
123    *    <li>Methods:
124    *       <ul>
125    *          <li>Fully qualified with args:
126    *             <ul>
127    *                <li><js>"com.foo.MyClass.myMethod(String,int)"</js>
128    *                <li><js>"com.foo.MyClass.myMethod(java.lang.String,int)"</js>
129    *                <li><js>"com.foo.MyClass.myMethod()"</js>
130    *             </ul>
131    *          <li>Fully qualified:
132    *             <ul>
133    *                <li><js>"com.foo.MyClass.myMethod"</js>
134    *             </ul>
135    *          <li>Simple with args:
136    *             <ul>
137    *                <li><js>"MyClass.myMethod(String,int)"</js>
138    *                <li><js>"MyClass.myMethod(java.lang.String,int)"</js>
139    *                <li><js>"MyClass.myMethod()"</js>
140    *             </ul>
141    *          <li>Simple:
142    *             <ul>
143    *                <li><js>"MyClass.myMethod"</js>
144    *             </ul>
145    *          <li>Simple inner class:
146    *             <ul>
147    *                <li><js>"MyClass$Inner1$Inner2.myMethod"</js>
148    *                <li><js>"Inner1$Inner2.myMethod"</js>
149    *                <li><js>"Inner2.myMethod"</js>
150    *             </ul>
151    *       </ul>
152    *    <li>Fields:
153    *       <ul>
154    *          <li>Fully qualified:
155    *             <ul>
156    *                <li><js>"com.foo.MyClass.myField"</js>
157    *             </ul>
158    *          <li>Simple:
159    *             <ul>
160    *                <li><js>"MyClass.myField"</js>
161    *             </ul>
162    *          <li>Simple inner class:
163    *             <ul>
164    *                <li><js>"MyClass$Inner1$Inner2.myField"</js>
165    *                <li><js>"Inner1$Inner2.myField"</js>
166    *                <li><js>"Inner2.myField"</js>
167    *             </ul>
168    *       </ul>
169    *    <li>A comma-delimited list of anything on this list.
170    * </ul>
171    *
172    * <h5 class='section'>See Also:</h5><ul>
173    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/DynamicallyAppliedAnnotations">Dynamically Applied Annotations</a>
174    * </ul>
175    *
176    * @return The annotation value.
177    */
178   String[] on() default {};
179
180   /**
181    * Dynamically apply this annotation to the specified classes.
182    *
183    * <p>
184    * Identical to {@link #on()} except allows you to specify class objects instead of a strings.
185    *
186    * <h5 class='section'>See Also:</h5><ul>
187    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/DynamicallyAppliedAnnotations">Dynamically Applied Annotations</a>
188    * </ul>
189    *
190    * @return The annotation value.
191    */
192   Class<?>[] onClass() default {};
193
194   /**
195    * Identifies a template string along with this swap.
196    *
197    * <p>
198    * Template strings are arbitrary strings associated with swaps that help provide additional context information
199    * for the swap class.
200    * They're called 'templates' because their primary purpose is for providing template names, such as Apache FreeMarker
201    * template names.
202    *
203    * <p>
204    * The following is an example of a templated swap class used to serialize POJOs to HTML using FreeMarker:
205    *
206    * <p class='bjava'>
207    *    <jc>// Our templated swap class.</jc>
208    *    <jk>public class</jk> FreeMarkerSwap <jk>extends</jk> ObjectSwap&lt;Object,Reader&gt; {
209    *
210    *       <jk>public</jk> MediaType[] forMediaTypes() {
211    *          <jk>return</jk> MediaType.<jsm>forStrings</jsm>(<js>"&#42;/html"</js>);
212    *       }
213    *
214    *       <jk>public</jk> Reader swap(BeanSession <jv>session</jv>, Object <jv>value</jv>, String <jv>template</jv>) <jk>throws</jk> Exception {
215    *          <jk>return</jk> <jsm>getFreeMarkerReader</jsm>(<jv>template</jv>, <jv>value</jv>);  <jc>// Some method that creates raw HTML.</jc>
216    *       }
217    *    }
218    * </p>
219    * <p class='bjava'>
220    *    <ja>@Swap</ja>(impl=FreeMarkerSwap.<jk>class</jk>, template=<js>"MyPojo.div.ftl"</js>)
221    *    <jk>public class</jk> MyPojo {}
222    * </p>
223    *
224    * <h5 class='section'>See Also:</h5><ul>
225    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/TemplatedSwaps">Templated Swaps</a>
226    * </ul>
227    *
228    * @return The annotation value.
229    */
230   String template() default "";
231
232   /**
233    * The {@link ObjectSwap} and {@link Surrogate} class.
234    *
235    * <p>
236    * A synonym for {@link #impl()}.
237    *
238    * @return The annotation value.
239    */
240   Class<?> value() default void.class;
241}