001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.http.annotation;
014
015import static org.apache.juneau.common.internal.StringUtils.*;
016import static org.apache.juneau.internal.ArrayUtils.*;
017import static java.lang.annotation.ElementType.*;
018import static java.lang.annotation.RetentionPolicy.*;
019import java.lang.annotation.*;
020import java.lang.reflect.*;
021import org.apache.juneau.*;
022import org.apache.juneau.annotation.*;
023import org.apache.juneau.httppart.*;
024import org.apache.juneau.reflect.*;
025import org.apache.juneau.svl.*;
026
027/**
028 * Utility classes and methods for the {@link FormData @FormData} annotation.
029 *
030 * <h5 class='section'>See Also:</h5><ul>
031 * </ul>
032 */
033public class FormDataAnnotation {
034
035   //-----------------------------------------------------------------------------------------------------------------
036   // Static
037   //-----------------------------------------------------------------------------------------------------------------
038
039   /** Default value */
040   public static final FormData DEFAULT = create().build();
041
042   /**
043    * Instantiates a new builder for this class.
044    *
045    * @return A new builder object.
046    */
047   public static Builder create() {
048      return new Builder();
049   }
050
051   /**
052    * Instantiates a new builder for this class.
053    *
054    * @param on The targets this annotation applies to.
055    * @return A new builder object.
056    */
057   public static Builder create(Class<?>...on) {
058      return create().on(on);
059   }
060
061   /**
062    * Instantiates a new builder for this class.
063    *
064    * @param on The targets this annotation applies to.
065    * @return A new builder object.
066    */
067   public static Builder create(String...on) {
068      return create().on(on);
069   }
070
071   /**
072    * Returns <jk>true</jk> if the specified annotation contains all default values.
073    *
074    * @param a The annotation to check.
075    * @return <jk>true</jk> if the specified annotation contains all default values.
076    */
077   public static boolean empty(FormData a) {
078      return a == null || DEFAULT.equals(a);
079   }
080
081   /**
082    * Finds the name from the specified lists of annotations.
083    *
084    * <p>
085    * The last matching name found is returned.
086    *
087    * @param pi The parameter.
088    * @return The last matching name, or {@link Value#empty()} if not found.
089    */
090   public static Value<String> findName(ParamInfo pi) {
091      Value<String> n = Value.empty();
092      pi.forEachAnnotation(FormData.class, x -> isNotEmpty(x.value()), x -> n.set(x.value()));
093      pi.forEachAnnotation(FormData.class, x -> isNotEmpty(x.name()), x -> n.set(x.name()));
094      return n;
095   }
096
097   /**
098    * Finds the default value from the specified list of annotations.
099    *
100    * @param pi The parameter.
101    * @return The last matching default value, or {@link Value#empty()} if not found.
102    */
103   public static Value<String> findDef(ParamInfo pi) {
104      Value<String> n = Value.empty();
105      pi.forEachAnnotation(FormData.class, x -> isNotEmpty(x.def()), x -> n.set(x.def()));
106      return n;
107   }
108
109   //-----------------------------------------------------------------------------------------------------------------
110   // Builder
111   //-----------------------------------------------------------------------------------------------------------------
112
113   /**
114    * Builder class.
115    *
116    * <h5 class='section'>See Also:</h5><ul>
117    *    <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#annotations(Annotation...)}
118    * </ul>
119    */
120   public static class Builder extends TargetedAnnotationTMFBuilder {
121
122      Class<? extends HttpPartParser> parser = HttpPartParser.Void.class;
123      Class<? extends HttpPartSerializer> serializer = HttpPartSerializer.Void.class;
124      Schema schema = SchemaAnnotation.DEFAULT;
125      String def="", name="", value="";
126
127      /**
128       * Constructor.
129       */
130      protected Builder() {
131         super(FormData.class);
132      }
133
134      /**
135       * Instantiates a new {@link FormData @FormData} object initialized with this builder.
136       *
137       * @return A new {@link FormData @FormData} object.
138       */
139      public FormData build() {
140         return new Impl(this);
141      }
142
143      /**
144       * Sets the {@link FormData#def} property on this annotation.
145       *
146       * @param value The new value for this property.
147       * @return This object.
148       */
149      public Builder def(String value) {
150         this.def = value;
151         return this;
152      }
153
154      /**
155       * Sets the {@link FormData#name} property on this annotation.
156       *
157       * @param value The new value for this property.
158       * @return This object.
159       */
160      public Builder name(String value) {
161         this.name = value;
162         return this;
163      }
164
165      /**
166       * Sets the {@link FormData#parser} property on this annotation.
167       *
168       * @param value The new value for this property.
169       * @return This object.
170       */
171      public Builder parser(Class<? extends HttpPartParser> value) {
172         this.parser = value;
173         return this;
174      }
175
176      /**
177       * Sets the {@link FormData#schema} property on this annotation.
178       *
179       * @param value The new value for this property.
180       * @return This object.
181       */
182      public Builder schema(Schema value) {
183         this.schema = value;
184         return this;
185      }
186
187      /**
188       * Sets the {@link FormData#serializer} property on this annotation.
189       *
190       * @param value The new value for this property.
191       * @return This object.
192       */
193      public Builder serializer(Class<? extends HttpPartSerializer> value) {
194         this.serializer = value;
195         return this;
196      }
197
198      /**
199       * Sets the {@link FormData#value} property on this annotation.
200       *
201       * @param value The new value for this property.
202       * @return This object.
203       */
204      public Builder value(String value) {
205         this.value = value;
206         return this;
207      }
208
209      // <FluentSetters>
210
211      @Override /* GENERATED - TargetedAnnotationBuilder */
212      public Builder on(String...values) {
213         super.on(values);
214         return this;
215      }
216
217      @Override /* GENERATED - TargetedAnnotationTBuilder */
218      public Builder on(java.lang.Class<?>...value) {
219         super.on(value);
220         return this;
221      }
222
223      @Override /* GENERATED - TargetedAnnotationTBuilder */
224      public Builder onClass(java.lang.Class<?>...value) {
225         super.onClass(value);
226         return this;
227      }
228
229      @Override /* GENERATED - TargetedAnnotationTMFBuilder */
230      public Builder on(Field...value) {
231         super.on(value);
232         return this;
233      }
234
235      @Override /* GENERATED - TargetedAnnotationTMFBuilder */
236      public Builder on(Method...value) {
237         super.on(value);
238         return this;
239      }
240
241      // </FluentSetters>
242   }
243
244   //-----------------------------------------------------------------------------------------------------------------
245   // Implementation
246   //-----------------------------------------------------------------------------------------------------------------
247
248   private static class Impl extends TargetedAnnotationTImpl implements FormData {
249
250      private final Class<? extends HttpPartParser> parser;
251      private final Class<? extends HttpPartSerializer> serializer;
252      private final String name, value, def;
253      private final Schema schema;
254
255      Impl(Builder b) {
256         super(b);
257         this.def = b.def;
258         this.name = b.name;
259         this.parser = b.parser;
260         this.schema = b.schema;
261         this.serializer = b.serializer;
262         this.value = b.value;
263         postConstruct();
264      }
265
266      @Override /* FormData */
267      public String def() {
268         return def;
269      }
270
271      @Override /* FormData */
272      public String name() {
273         return name;
274      }
275
276      @Override /* FormData */
277      public Class<? extends HttpPartParser> parser() {
278         return parser;
279      }
280
281      @Override /* FormData */
282      public Schema schema() {
283         return schema;
284      }
285
286      @Override /* FormData */
287      public Class<? extends HttpPartSerializer> serializer() {
288         return serializer;
289      }
290
291      @Override
292      public String value() {
293         return value;
294      }
295   }
296
297   //-----------------------------------------------------------------------------------------------------------------
298   // Appliers
299   //-----------------------------------------------------------------------------------------------------------------
300
301   /**
302    * Applies targeted {@link FormData} annotations to a {@link org.apache.juneau.BeanContext.Builder}.
303    */
304   public static class Applier extends AnnotationApplier<FormData,BeanContext.Builder> {
305
306      /**
307       * Constructor.
308       *
309       * @param vr The resolver for resolving values in annotations.
310       */
311      public Applier(VarResolverSession vr) {
312         super(FormData.class, BeanContext.Builder.class, vr);
313      }
314
315      @Override
316      public void apply(AnnotationInfo<FormData> ai, BeanContext.Builder b) {
317         FormData a = ai.inner();
318         if (isEmptyArray(a.on(), a.onClass()))
319            return;
320         b.annotations(a);
321      }
322   }
323
324   //-----------------------------------------------------------------------------------------------------------------
325   // Other
326   //-----------------------------------------------------------------------------------------------------------------
327
328   /**
329    * A collection of {@link FormData @FormData annotations}.
330    */
331   @Documented
332   @Target({METHOD,TYPE})
333   @Retention(RUNTIME)
334   @Inherited
335   public static @interface Array {
336
337      /**
338       * The child annotations.
339       *
340       * @return The annotation value.
341       */
342      FormData[] value();
343   }
344}