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.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.commons.annotation.*;
028import org.apache.juneau.commons.reflect.*;
029import org.apache.juneau.svl.*;
030
031/**
032 * Utility classes and methods for the {@link Beanp @Beanp} annotation.
033 *
034 */
035public class BeanpAnnotation {
036   /**
037    * Applies targeted {@link Beanp} annotations to a {@link org.apache.juneau.BeanContext.Builder}.
038    */
039   public static class Applier extends AnnotationApplier<Beanp,BeanContext.Builder> {
040
041      /**
042       * Constructor.
043       *
044       * @param vr The resolver for resolving values in annotations.
045       */
046      public Applier(VarResolverSession vr) {
047         super(Beanp.class, BeanContext.Builder.class, vr);
048      }
049
050      @Override
051      public void apply(AnnotationInfo<Beanp> ai, BeanContext.Builder b) {
052         Beanp a = ai.inner();
053         if (isEmptyArray(a.on()))
054            return;
055         b.annotations(copy(a, vr()));
056      }
057   }
058
059   /**
060    * A collection of {@link Beanp @Beanp annotations}.
061    */
062   @Documented
063   @Target({ METHOD, TYPE })
064   @Retention(RUNTIME)
065   @Inherited
066   public static @interface Array {
067
068      /**
069       * The child annotations.
070       *
071       * @return The annotation value.
072       */
073      Beanp[] value();
074   }
075
076   /**
077    * Builder class.
078    *
079    * <h5 class='section'>See Also:</h5><ul>
080    *    <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#annotations(Annotation...)}
081    * </ul>
082    */
083   public static class Builder extends AppliedAnnotationObject.BuilderMF {
084
085      private String[] description = {};
086      private Class<?> type = void.class;
087      private Class<?>[] dictionary = new Class[0], params = new Class[0];
088      private String format = "", name = "", properties = "", ro = "", value = "", wo = "";
089
090      /**
091       * Constructor.
092       */
093      protected Builder() {
094         super(Beanp.class);
095      }
096
097      /**
098       * Instantiates a new {@link Beanp @Beanp} object initialized with this builder.
099       *
100       * @return A new {@link Beanp @Beanp} object.
101       */
102      public Beanp build() {
103         return new Object(this);
104      }
105
106      /**
107       * Sets the description property on this annotation.
108       *
109       * @param value The new value for this property.
110       * @return This object.
111       */
112      public Builder description(String...value) {
113         description = value;
114         return this;
115      }
116
117      /**
118       * Sets the {@link Beanp#dictionary()} property on this annotation.
119       *
120       * @param value The new value for this property.
121       * @return This object.
122       */
123      public Builder dictionary(Class<?>...value) {
124         dictionary = value;
125         return this;
126      }
127
128      /**
129       * Sets the {@link Beanp#format()} property on this annotation.
130       *
131       * @param value The new value for this property.
132       * @return This object.
133       */
134      public Builder format(String value) {
135         format = value;
136         return this;
137      }
138
139      /**
140       * Sets the {@link Beanp#name()} property on this annotation.
141       *
142       * @param value The new value for this property.
143       * @return This object.
144       */
145      public Builder name(String value) {
146         name = value;
147         return this;
148      }
149
150      /**
151       * Sets the {@link Beanp#params()} property on this annotation.
152       *
153       * @param value The new value for this property.
154       * @return This object.
155       */
156      public Builder params(Class<?>...value) {
157         params = value;
158         return this;
159      }
160
161      /**
162       * Sets the {@link Beanp#properties()} property on this annotation.
163       *
164       * @param value The new value for this property.
165       * @return This object.
166       */
167      public Builder properties(String value) {
168         properties = value;
169         return this;
170      }
171
172      /**
173       * Sets the {@link Beanp#ro()} property on this annotation.
174       *
175       * @param value The new value for this property.
176       * @return This object.
177       */
178      public Builder ro(String value) {
179         ro = value;
180         return this;
181      }
182
183      /**
184       * Sets the {@link Beanp#type()} property on this annotation.
185       *
186       * @param value The new value for this property.
187       * @return This object.
188       */
189      public Builder type(Class<?> value) {
190         type = value;
191         return this;
192      }
193
194      /**
195       * Sets the {@link Beanp#value()} property on this annotation.
196       *
197       * @param value The new value for this property.
198       * @return This object.
199       */
200      public Builder value(String value) {
201         this.value = value;
202         return this;
203      }
204
205      /**
206       * Sets the {@link Beanp#wo()} property on this annotation.
207       *
208       * @param value The new value for this property.
209       * @return This object.
210       */
211      public Builder wo(String value) {
212         wo = value;
213         return this;
214      }
215
216      @Override /* Overridden from AppliedAnnotationObject.Builder */
217      public Builder on(String...value) {
218         super.on(value);
219         return this;
220      }
221
222      @Override /* Overridden from AppliedAnnotationObject.BuilderM */
223      public Builder on(Method...value) {
224         super.on(value);
225         return this;
226      }
227
228      @Override /* Overridden from AppliedAnnotationObject.BuilderMF */
229      public Builder on(Field...value) {
230         super.on(value);
231         return this;
232      }
233
234      @Override /* Overridden from AppliedAnnotationObject.BuilderMF */
235      public Builder on(FieldInfo...value) {
236         super.on(value);
237         return this;
238      }
239
240      @Override /* Overridden from AppliedAnnotationObject.BuilderMF */
241      public Builder on(MethodInfo...value) {
242         super.on(value);
243         return this;
244      }
245
246   }
247
248   private static class Object extends AppliedAnnotationObject implements Beanp {
249
250      private final String[] description;
251      private final Class<?> type;
252      private final Class<?>[] params, dictionary;
253      private final String name, value, properties, format, ro, wo;
254
255      Object(BeanpAnnotation.Builder b) {
256         super(b);
257         description = copyOf(b.description);
258         dictionary = copyOf(b.dictionary);
259         format = b.format;
260         name = b.name;
261         params = copyOf(b.params);
262         properties = b.properties;
263         ro = b.ro;
264         type = b.type;
265         value = b.value;
266         wo = b.wo;
267      }
268
269      @Override /* Overridden from Beanp */
270      public Class<?>[] dictionary() {
271         return dictionary;
272      }
273
274      @Override /* Overridden from Beanp */
275      public String format() {
276         return format;
277      }
278
279      @Override /* Overridden from Beanp */
280      public String name() {
281         return name;
282      }
283
284      @Override /* Overridden from Beanp */
285      public Class<?>[] params() {
286         return params;
287      }
288
289      @Override /* Overridden from Beanp */
290      public String properties() {
291         return properties;
292      }
293
294      @Override /* Overridden from Beanp */
295      public String ro() {
296         return ro;
297      }
298
299      @Override /* Overridden from Beanp */
300      public Class<?> type() {
301         return type;
302      }
303
304      @Override /* Overridden from Beanp */
305      public String value() {
306         return value;
307      }
308
309      @Override /* Overridden from Beanp */
310      public String wo() {
311         return wo;
312      }
313
314      @Override /* Overridden from annotation */
315      public String[] description() {
316         return description;
317      }
318   }
319
320   /** Default value */
321   public static final Beanp DEFAULT = create().build();
322
323   /**
324    * Creates a copy of the specified annotation.
325    *
326    * @param a The annotation to copy.s
327    * @param r The var resolver for resolving any variables.
328    * @return A copy of the specified annotation.
329    */
330   public static Beanp copy(Beanp a, VarResolverSession r) {
331      // @formatter:off
332      return
333         create()
334         .dictionary(a.dictionary())
335         .format(r.resolve(a.format()))
336         .name(r.resolve(a.name()))
337         .on(r.resolve(a.on()))
338         .params(a.params())
339         .properties(r.resolve(a.properties()))
340         .ro(r.resolve(a.ro()))
341         .type(a.type())
342         .value(r.resolve(a.value()))
343         .wo(r.resolve(a.wo()))
344         .build();
345      // @formatter:on
346   }
347
348   /**
349    * Instantiates a new builder for this class.
350    *
351    * @return A new builder object.
352    */
353   public static Builder create() {
354      return new Builder();
355   }
356
357   /**
358    * Instantiates a new builder for this class.
359    *
360    * @param on The targets this annotation applies to.
361    * @return A new builder object.
362    */
363   public static Builder create(String...on) {
364      return create().on(on);
365   }
366}