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