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.*;
021import static org.apache.juneau.commons.utils.CollectionUtils.*;
022
023import java.lang.annotation.*;
024import java.lang.reflect.*;
025
026import org.apache.juneau.*;
027import org.apache.juneau.annotation.*;
028import org.apache.juneau.httppart.*;
029import org.apache.juneau.commons.annotation.*;
030import org.apache.juneau.commons.reflect.*;
031import org.apache.juneau.svl.*;
032
033/**
034 * Utility classes and methods for the {@link Response @Response} annotation.
035 *
036 */
037public class ResponseAnnotation {
038   /**
039    * Applies targeted {@link Response} annotations to a {@link org.apache.juneau.BeanContext.Builder}.
040    */
041   public static class Applier extends AnnotationApplier<Response,BeanContext.Builder> {
042
043      /**
044       * Constructor.
045       *
046       * @param vr The resolver for resolving values in annotations.
047       */
048      public Applier(VarResolverSession vr) {
049         super(Response.class, BeanContext.Builder.class, vr);
050      }
051
052      @Override
053      public void apply(AnnotationInfo<Response> ai, BeanContext.Builder b) {
054         Response a = ai.inner();
055         if (isEmptyArray(a.on()) && isEmptyArray(a.onClass()))
056            return;
057         b.annotations(a);
058      }
059   }
060
061   /**
062    * A collection of {@link Response @Response annotations}.
063    */
064   @Documented
065   @Target({ METHOD, TYPE })
066   @Retention(RUNTIME)
067   @Inherited
068   public static @interface Array {
069
070      /**
071       * The child annotations.
072       *
073       * @return The annotation value.
074       */
075      Response[] value();
076   }
077
078   /**
079    * Builder class.
080    *
081    * <h5 class='section'>See Also:</h5><ul>
082    *    <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#annotations(Annotation...)}
083    * </ul>
084    */
085   public static class Builder extends AppliedAnnotationObject.BuilderTM {
086
087      private String[] description = {};
088      private Class<? extends HttpPartParser> parser = HttpPartParser.Void.class;
089      private Class<? extends HttpPartSerializer> serializer = HttpPartSerializer.Void.class;
090      private Header[] headers = {};
091      private Schema schema = SchemaAnnotation.DEFAULT;
092      private String[] examples = {};
093
094      /**
095       * Constructor.
096       */
097      protected Builder() {
098         super(Response.class);
099      }
100
101      /**
102       * Instantiates a new {@link Response @Response} object initialized with this builder.
103       *
104       * @return A new {@link Response @Response} object.
105       */
106      public Response build() {
107         return new Object(this);
108      }
109
110      /**
111       * Sets the description property on this annotation.
112       *
113       * @param value The new value for this property.
114       * @return This object.
115       */
116      public Builder description(String...value) {
117         description = value;
118         return this;
119      }
120
121      /**
122       * Sets the {@link Response#examples} property on this annotation.
123       *
124       * @param value The new value for this property.
125       * @return This object.
126       */
127      public Builder examples(String...value) {
128         examples = value;
129         return this;
130      }
131
132      /**
133       * Sets the {@link Response#headers} property on this annotation.
134       *
135       * @param value The new value for this property.
136       * @return This object.
137       */
138      public Builder headers(Header...value) {
139         headers = value;
140         return this;
141      }
142
143      /**
144       * Sets the {@link Response#parser} property on this annotation.
145       *
146       * @param value The new value for this property.
147       * @return This object.
148       */
149      public Builder parser(Class<? extends HttpPartParser> value) {
150         parser = value;
151         return this;
152      }
153
154      /**
155       * Sets the {@link Response#schema} property on this annotation.
156       *
157       * @param value The new value for this property.
158       * @return This object.
159       */
160      public Builder schema(Schema value) {
161         schema = value;
162         return this;
163      }
164
165      /**
166       * Sets the {@link Response#serializer} property on this annotation.
167       *
168       * @param value The new value for this property.
169       * @return This object.
170       */
171      public Builder serializer(Class<? extends HttpPartSerializer> value) {
172         serializer = value;
173         return this;
174      }
175
176      @Override /* Overridden from AppliedAnnotationObject.Builder */
177      public Builder on(String...value) {
178         super.on(value);
179         return this;
180      }
181
182      @Override /* Overridden from AppliedAnnotationObject.BuilderT */
183      public Builder on(Class<?>...value) {
184         super.on(value);
185         return this;
186      }
187
188      @Override /* Overridden from AppliedOnClassAnnotationObject.Builder */
189      public Builder onClass(Class<?>...value) {
190         super.onClass(value);
191         return this;
192      }
193
194      @Override /* Overridden from AppliedAnnotationObject.BuilderM */
195      public Builder on(Method...value) {
196         super.on(value);
197         return this;
198      }
199
200      @Override /* Overridden from AppliedAnnotationObject.BuilderT */
201      public Builder on(ClassInfo...value) {
202         super.on(value);
203         return this;
204      }
205
206      @Override /* Overridden from AppliedAnnotationObject.BuilderT */
207      public Builder onClass(ClassInfo...value) {
208         super.onClass(value);
209         return this;
210      }
211
212      @Override /* Overridden from AppliedAnnotationObject.BuilderTM */
213      public Builder on(MethodInfo...value) {
214         super.on(value);
215         return this;
216      }
217
218   }
219
220   private static class Object extends AppliedOnClassAnnotationObject implements Response {
221
222      private final String[] description;
223      private final Class<? extends HttpPartParser> parser;
224      private final Class<? extends HttpPartSerializer> serializer;
225      private final Header[] headers;
226      private final Schema schema;
227      private final String[] examples;
228
229      Object(ResponseAnnotation.Builder b) {
230         super(b);
231         description = copyOf(b.description);
232         examples = copyOf(b.examples);
233         headers = copyOf(b.headers);
234         parser = b.parser;
235         schema = b.schema;
236         serializer = b.serializer;
237      }
238
239      @Override /* Overridden from Response */
240      public String[] examples() {
241         return examples;
242      }
243
244      @Override /* Overridden from Response */
245      public Header[] headers() {
246         return headers;
247      }
248
249      @Override /* Overridden from Response */
250      public Class<? extends HttpPartParser> parser() {
251         return parser;
252      }
253
254      @Override /* Overridden from Response */
255      public Schema schema() {
256         return schema;
257      }
258
259      @Override /* Overridden from Response */
260      public Class<? extends HttpPartSerializer> serializer() {
261         return serializer;
262      }
263
264      @Override /* Overridden from annotation */
265      public String[] description() {
266         return description;
267      }
268   }
269
270   /** Default value */
271   public static final Response DEFAULT = create().build();
272
273   /**
274    * Instantiates a new builder for this class.
275    *
276    * @return A new builder object.
277    */
278   public static Builder create() {
279      return new Builder();
280   }
281
282   /**
283    * Instantiates a new builder for this class.
284    *
285    * @param on The targets this annotation applies to.
286    * @return A new builder object.
287    */
288   public static Builder create(Class<?>...on) {
289      return create().on(on);
290   }
291
292   /**
293    * Instantiates a new builder for this class.
294    *
295    * @param on The targets this annotation applies to.
296    * @return A new builder object.
297    */
298   public static Builder create(String...on) {
299      return create().on(on);
300   }
301
302   /**
303    * Returns <jk>true</jk> if the specified annotation contains all default values.
304    *
305    * @param a The annotation to check.
306    * @return <jk>true</jk> if the specified annotation contains all default values.
307    */
308   public static boolean empty(Response a) {
309      return a == null || DEFAULT.equals(a);
310   }
311}