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.http.annotation;
018
019import static java.lang.annotation.ElementType.*;
020import static java.lang.annotation.RetentionPolicy.*;
021
022import java.lang.annotation.*;
023
024import org.apache.juneau.annotation.*;
025import org.apache.juneau.httppart.*;
026import org.apache.juneau.oapi.*;
027
028/**
029 * REST request form-data annotation.
030 *
031 * <p>
032 * Identifies a POJO to be used as a form-data entry on an HTTP request.
033 *
034 * <p>
035 * Can be used in the following locations:
036 * <ul>
037 *    <li>Arguments and argument-types of server-side <ja>@RestOp</ja>-annotated methods.
038 *    <li>Arguments and argument-types of client-side <ja>@RemoteResource</ja>-annotated interfaces.
039 *    <li>Methods and return types of server-side and client-side <ja>@Request</ja>-annotated interfaces.
040 * </ul>
041 *
042 * <h5 class='topic'>Arguments and argument-types of server-side @RestOp-annotated methods</h5>
043 * <p>
044 * Annotation that can be applied to a parameter of a <ja>@RestOp</ja>-annotated method to identify it as a form-data parameter.
045 *
046 * <h5 class='section'>Example:</h5>
047 * <p class='bjava'>
048 *    <ja>@RestPost</ja>
049 *    <jk>public void</jk> doPost(
050 *          <ja>@FormData</ja>(<js>"p1"</js>) <jk>int</jk> <jv>p1</jv>,
051 *          <ja>@FormData</ja>(<js>"p2"</js>) String <jv>p2</jv>,
052 *          <ja>@FormData</ja>(<js>"p3"</js>) UUID <jv>p3</jv>
053 *       ) {...}
054 * </p>
055 *
056 * <p>
057 * This is functionally equivalent to the following code...
058 * <p class='bjava'>
059 *    <ja>@RestPost</ja>
060 *    <jk>public void</jk> doPost(RestRequest <jv>req</jv>) {
061 *       <jk>int</jk> <jv>p1</jv> = <jv>req</jv>.getFormParam(<js>"p1"</js>).as(<jk>int</jk>.<jk>class</jk>).orElse(0);
062 *       String <jv>p2</jv> = <jv>req</jv>.getFormParam(<js>"p2"</js>).asString().orElse(<jk>null</jk>);
063 *       UUID <jv>p3</jv> = <jv>req</jv>.getFormParam(<js>"p3"</js>).as(UUID.<jk>class</jk>).orElse(<jk>null</jk>);
064 *       ...
065 *    }
066 * </p>
067 *
068 * <h5 class='section'>See Also:</h5><ul>
069 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a>
070 *    <li class='extlink'><a class='doclink' href='https://swagger.io/specification/v2#parameterObject'>Swagger Parameter Object</a>
071 * </ul>
072 *
073 * <h5 class='topic'>Important note concerning FORM posts</h5>
074 * <p>
075 * This annotation should not be combined with the {@link Content @Content} annotation or <c>RestRequest.getContent()</c> method
076 * for <c>application/x-www-form-urlencoded POST</c> posts, since it will trigger the underlying servlet
077 * API to parse the body content as key-value pairs resulting in empty content.
078 *
079 * <p>
080 * The {@link Query @Query} annotation can be used to retrieve a URL parameter in the URL string without triggering the
081 * servlet to drain the body content.
082 *
083 * <h5 class='topic'>Arguments and argument-types of client-side @RemoteResource-annotated interfaces</h5>
084 * <p>
085 * Annotation applied to Java method arguments of interface proxies to denote that they are FORM post parameters on the
086 * request.
087 *
088 * <h5 class='section'>See Also:</h5><ul>
089 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/FormData">@FormData</a>
090 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Request">@Request</a>
091 * </ul>
092 *
093 * <h5 class='topic'>Methods and return types of server-side and client-side @Request-annotated interfaces</h5>
094 * <p>
095 * <h5 class='section'>See Also:</h5><ul>
096 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Request">@Request</a>
097 * </ul>
098 *
099 * <div class='warn'>
100 *    This annotation should not be combined with the {@link Content @Content} annotation or <c>RestRequest#getContent()</c> method
101 *    for <c>application/x-www-form-urlencoded POST</c> posts, since it will trigger the underlying servlet
102 *    API to parse the body content as key-value pairs resulting in empty content.
103 *    <br>The {@link Query @Query} annotation can be used to retrieve a URL parameter in the URL string without triggering the
104 *    servlet to drain the body content.
105 * </div>
106 * <div class='warn'>
107 *    If using this annotation on a Spring bean, note that you are likely to encounter issues when using on parameterized
108 *    types such as <code>List&lt;MyBean&gt;</code>.  This is due to the fact that Spring uses CGLIB to recompile classes
109 *    at runtime, and CGLIB was written before generics were introduced into Java and is a virtually-unsupported library.
110 *    Therefore, parameterized types will often be stripped from class definitions and replaced with unparameterized types
111 * (e.g. <code>List</code>).  Under these circumstances, you are likely to get <code>ClassCastExceptions</code>
112 * when trying to access generalized <code>JsonMaps</code> as beans.  The best solution to this issue is to either
113 * specify the parameter as a bean array (e.g. <code>MyBean[]</code>) or declare the method as final so that CGLIB
114 * will not try to recompile it.
115 * </div>
116 *
117 * <h5 class='section'>See Also:</h5><ul>
118
119 * </ul>
120 */
121@Documented
122@Target({PARAMETER,METHOD,TYPE,FIELD})
123@Retention(RUNTIME)
124@Inherited
125@Repeatable(FormDataAnnotation.Array.class)
126@ContextApply(FormDataAnnotation.Applier.class)
127public @interface FormData {
128
129   /**
130    * Default value for this parameter.
131    *
132    * @return The annotation value.
133    */
134   String def() default "";
135
136    /**
137     * Optional description for the exposed API.
138     *
139     * @return The annotation value.
140     * @since 9.2.0
141     */
142    String[] description() default {};
143
144    /**
145    * FORM parameter name.
146    *
147    * <p>
148    * The name of the parameter (required).
149    *
150    * <p>
151    * The value should be either a valid form parameter name, or <js>"*"</js> to represent multiple name/value pairs
152    *
153    * <p>
154    * A blank value (the default) has the following behavior:
155    * <ul class='spaced-list'>
156    *    <li>
157    *       If the data type is <c>NameValuePairs</c>, <c>Map</c>, or a bean,
158    *       then it's the equivalent to <js>"*"</js> which will cause the value to be serialized as name/value pairs.
159    *
160    *       <h5 class='figure'>Examples:</h5>
161    *       <p class='bjava'>
162    *    <jc>// When used on a REST method</jc>
163    *    <ja>@RestPost</ja>(<js>"/addPet"</js>)
164    *    <jk>public void</jk> addPet(<ja>@FormData</ja> JsonMap <jv>allFormDataParameters</jv>) {...}
165    *       </p>
166    *       <p class='bjava'>
167    *    <jc>// When used on a remote method parameter</jc>
168    *    <ja>@RemoteResource</ja>(path=<js>"/myproxy"</js>)
169    *    <jk>public interface</jk> MyProxy {
170    *
171    *       <jc>// Equivalent to @FormData("*")</jc>
172    *       <ja>@RemotePost</ja>(<js>"/mymethod"</js>)
173    *       String myProxyMethod1(<ja>@FormData</ja> Map&lt;String,Object&gt; <jv>allFormDataParameters</jv>);
174    *    }
175    *       </p>
176    *       <p class='bjava'>
177    *    <jc>// When used on a request bean method</jc>
178    *    <jk>public interface</jk> MyRequest {
179    *
180    *       <jc>// Equivalent to @FormData("*")</jc>
181    *       <ja>@FormData</ja>
182    *       Map&lt;String,Object&gt; getFoo();
183    *    }
184    *       </p>
185    *    </li>
186    *    <li>
187    *       If used on a request bean method, uses the bean property name.
188    *
189    *       <h5 class='figure'>Example:</h5>
190    *       <p class='bjava'>
191    *    <jk>public interface</jk> MyRequest {
192    *
193    *       <jc>// Equivalent to @FormData("foo")</jc>
194    *       <ja>@FormData</ja>
195    *       String getFoo();
196    *    }
197    *       </p>
198    *    </li>
199    * </ul>
200    *
201    * <h5 class='section'>Notes:</h5><ul>
202    *    <li class='note'>
203    *       The format is plain-text.
204    * </ul>
205    *
206    * @return The annotation value.
207    */
208   String name() default "";
209
210   /**
211    * Dynamically apply this annotation to the specified classes.
212    *
213    * <h5 class='section'>See Also:</h5><ul>
214    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/DynamicallyAppliedAnnotations">Dynamically Applied Annotations</a>
215    * </ul>
216    *
217    * @return The annotation value.
218    */
219   String[] on() default {};
220
221   /**
222    * Dynamically apply this annotation to the specified classes.
223    *
224    * <p>
225    * Identical to {@link #on()} except allows you to specify class objects instead of a strings.
226    *
227    * <h5 class='section'>See Also:</h5><ul>
228    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/DynamicallyAppliedAnnotations">Dynamically Applied Annotations</a>
229    * </ul>
230    *
231    * @return The annotation value.
232    */
233   Class<?>[] onClass() default {};
234
235   /**
236    * Specifies the {@link HttpPartParser} class used for parsing strings to values.
237    *
238    * <p>
239    * Overrides for this part the part parser defined on the REST resource which by default is {@link OpenApiParser}.
240    *
241    * @return The annotation value.
242    */
243   Class<? extends HttpPartParser> parser() default HttpPartParser.Void.class;
244
245   /**
246    * <mk>schema</mk> field of the <a class='doclink' href='https://swagger.io/specification/v2#parameterObject'>Swagger Parameter Object</a>.
247    *
248    * <p>
249    * The schema defining the type used for parameter.
250    *
251    * <p>
252    * The {@link Schema @Schema} annotation can also be used standalone on the parameter or type.
253    * Values specified on this field override values specified on the type, and values specified on child types override values
254    * specified on parent types.
255    *
256    * <h5 class='section'>Used for:</h5>
257    * <ul class='spaced-list'>
258    *    <li>
259    *       Server-side schema-based parsing and parsing validation.
260    *    <li>
261    *       Server-side generated Swagger documentation.
262    *    <li>
263    *       Client-side schema-based serializing and serializing validation.
264    * </ul>
265    *
266    * @return The annotation value.
267    */
268   Schema schema() default @Schema;
269
270   /**
271    * Specifies the {@link HttpPartSerializer} class used for serializing values to strings.
272    *
273    * <p>
274    * Overrides for this part the part serializer defined on the REST client which by default is {@link OpenApiSerializer}.
275    *
276    * @return The annotation value.
277    */
278   Class<? extends HttpPartSerializer> serializer() default HttpPartSerializer.Void.class;
279
280   /**
281    * A synonym for {@link #name()}.
282    *
283    * <p>
284    * Allows you to use shortened notation if you're only specifying the name.
285    *
286    * <p>
287    * The following are completely equivalent ways of defining a form post entry:
288    * <p class='bjava'>
289    *    <jk>public</jk> Order placeOrder(<ja>@FormData</ja>(name=<js>"petId"</js>) <jk>long</jk> <jv>petId</jv>) {...}
290    * </p>
291    * <p class='bjava'>
292    *    <jk>public</jk> Order placeOrder(<ja>@FormData</ja>(<js>"petId"</js>) <jk>long</jk> <jv>petId</jv>) {...}
293    * </p>
294    *
295    * @return The annotation value.
296    */
297   String value() default "";
298}