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 */
118@Documented
119@Target({ PARAMETER, METHOD, TYPE, FIELD })
120@Retention(RUNTIME)
121@Inherited
122@Repeatable(FormDataAnnotation.Array.class)
123@ContextApply(FormDataAnnotation.Applier.class)
124public @interface FormData {
125
126   /**
127    * Default value for this parameter.
128    *
129    * @return The annotation value.
130    */
131   String def() default "";
132
133   /**
134    * Optional description for the exposed API.
135    *
136    * @return The annotation value.
137    * @since 9.2.0
138    */
139   String[] description() default {};
140
141   /**
142    * FORM parameter name.
143    *
144    * <p>
145    * The name of the parameter (required).
146    *
147    * <p>
148    * The value should be either a valid form parameter name, or <js>"*"</js> to represent multiple name/value pairs
149    *
150    * <p>
151    * A blank value (the default) has the following behavior:
152    * <ul class='spaced-list'>
153    *    <li>
154    *       If the data type is <c>NameValuePairs</c>, <c>Map</c>, or a bean,
155    *       then it's the equivalent to <js>"*"</js> which will cause the value to be serialized as name/value pairs.
156    *
157    *       <h5 class='figure'>Examples:</h5>
158    *       <p class='bjava'>
159    *    <jc>// When used on a REST method</jc>
160    *    <ja>@RestPost</ja>(<js>"/addPet"</js>)
161    *    <jk>public void</jk> addPet(<ja>@FormData</ja> JsonMap <jv>allFormDataParameters</jv>) {...}
162    *       </p>
163    *       <p class='bjava'>
164    *    <jc>// When used on a remote method parameter</jc>
165    *    <ja>@RemoteResource</ja>(path=<js>"/myproxy"</js>)
166    *    <jk>public interface</jk> MyProxy {
167    *
168    *       <jc>// Equivalent to @FormData("*")</jc>
169    *       <ja>@RemotePost</ja>(<js>"/mymethod"</js>)
170    *       String myProxyMethod1(<ja>@FormData</ja> Map&lt;String,Object&gt; <jv>allFormDataParameters</jv>);
171    *    }
172    *       </p>
173    *       <p class='bjava'>
174    *    <jc>// When used on a request bean method</jc>
175    *    <jk>public interface</jk> MyRequest {
176    *
177    *       <jc>// Equivalent to @FormData("*")</jc>
178    *       <ja>@FormData</ja>
179    *       Map&lt;String,Object&gt; getFoo();
180    *    }
181    *       </p>
182    *    </li>
183    *    <li>
184    *       If used on a request bean method, uses the bean property name.
185    *
186    *       <h5 class='figure'>Example:</h5>
187    *       <p class='bjava'>
188    *    <jk>public interface</jk> MyRequest {
189    *
190    *       <jc>// Equivalent to @FormData("foo")</jc>
191    *       <ja>@FormData</ja>
192    *       String getFoo();
193    *    }
194    *       </p>
195    *    </li>
196    * </ul>
197    *
198    * <h5 class='section'>Notes:</h5><ul>
199    *    <li class='note'>
200    *       The format is plain-text.
201    * </ul>
202    *
203    * @return The annotation value.
204    */
205   String name() default "";
206
207   /**
208    * Dynamically apply this annotation to the specified classes.
209    *
210    * <h5 class='section'>See Also:</h5><ul>
211    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/DynamicallyAppliedAnnotations">Dynamically Applied Annotations</a>
212    * </ul>
213    *
214    * @return The annotation value.
215    */
216   String[] on() default {};
217
218   /**
219    * Dynamically apply this annotation to the specified classes.
220    *
221    * <p>
222    * Identical to {@link #on()} except allows you to specify class objects instead of a strings.
223    *
224    * <h5 class='section'>See Also:</h5><ul>
225    *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/DynamicallyAppliedAnnotations">Dynamically Applied Annotations</a>
226    * </ul>
227    *
228    * @return The annotation value.
229    */
230   Class<?>[] onClass() default {};
231
232   /**
233    * Specifies the {@link HttpPartParser} class used for parsing strings to values.
234    *
235    * <p>
236    * Overrides for this part the part parser defined on the REST resource which by default is {@link OpenApiParser}.
237    *
238    * @return The annotation value.
239    */
240   Class<? extends HttpPartParser> parser() default HttpPartParser.Void.class;
241
242   /**
243    * <mk>schema</mk> field of the <a class='doclink' href='https://swagger.io/specification/v2#parameterObject'>Swagger Parameter Object</a>.
244    *
245    * <p>
246    * The schema defining the type used for parameter.
247    *
248    * <p>
249    * The {@link Schema @Schema} annotation can also be used standalone on the parameter or type.
250    * Values specified on this field override values specified on the type, and values specified on child types override values
251    * specified on parent types.
252    *
253    * <h5 class='section'>Used for:</h5>
254    * <ul class='spaced-list'>
255    *    <li>
256    *       Server-side schema-based parsing and parsing validation.
257    *    <li>
258    *       Server-side generated Swagger documentation.
259    *    <li>
260    *       Client-side schema-based serializing and serializing validation.
261    * </ul>
262    *
263    * @return The annotation value.
264    */
265   Schema schema() default @Schema;
266
267   /**
268    * Specifies the {@link HttpPartSerializer} class used for serializing values to strings.
269    *
270    * <p>
271    * Overrides for this part the part serializer defined on the REST client which by default is {@link OpenApiSerializer}.
272    *
273    * @return The annotation value.
274    */
275   Class<? extends HttpPartSerializer> serializer() default HttpPartSerializer.Void.class;
276
277   /**
278    * A synonym for {@link #name()}.
279    *
280    * <p>
281    * Allows you to use shortened notation if you're only specifying the name.
282    *
283    * <p>
284    * The following are completely equivalent ways of defining a form post entry:
285    * <p class='bjava'>
286    *    <jk>public</jk> Order placeOrder(<ja>@FormData</ja>(name=<js>"petId"</js>) <jk>long</jk> <jv>petId</jv>) {...}
287    * </p>
288    * <p class='bjava'>
289    *    <jk>public</jk> Order placeOrder(<ja>@FormData</ja>(<js>"petId"</js>) <jk>long</jk> <jv>petId</jv>) {...}
290    * </p>
291    *
292    * @return The annotation value.
293    */
294   String value() default "";
295}