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