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>"*/json"</js>) 076 * <jk>public class</jk> MyBean { ... } 077 * 078 * <jk>public class</jk> ToStringSwap <jk>extends</jk> ObjectSwap<Object,String> { 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<Object,Reader> { 209 * 210 * <jk>public</jk> MediaType[] forMediaTypes() { 211 * <jk>return</jk> MediaType.<jsm>forStrings</jsm>(<js>"*/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}