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.*;
024
025import org.apache.juneau.*;
026import org.apache.juneau.commons.annotation.*;
027import org.apache.juneau.commons.reflect.*;
028import org.apache.juneau.svl.*;
029import org.apache.juneau.swap.*;
030
031/**
032 * Utility classes and methods for the {@link Bean @Bean} annotation.
033 *
034 */
035public class BeanAnnotation {
036   /**
037    * Applies targeted {@link Bean} annotations to a {@link org.apache.juneau.BeanContext.Builder}.
038    */
039   public static class Applier extends AnnotationApplier<Bean,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(Bean.class, BeanContext.Builder.class, vr);
048      }
049
050      @Override
051      public void apply(AnnotationInfo<Bean> ai, BeanContext.Builder b) {
052         Bean a = ai.inner();
053         if (isEmptyArray(a.on()) && isEmptyArray(a.onClass()))
054            return;
055         b.annotations(copy(a, vr()));
056      }
057   }
058
059   /**
060    * A collection of {@link Bean @Bean 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      Bean[] 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.BuilderT {
084
085      private String[] description = {};
086      private Class<?>[] dictionary = new Class[0];
087      private Class<?> implClass = void.class;
088      private Class<?> interfaceClass = void.class;
089      private Class<?> stopClass = void.class;
090      private Class<? extends BeanInterceptor<?>> interceptor = BeanInterceptor.Void.class;
091      private Class<? extends PropertyNamer> propertyNamer = BasicPropertyNamer.class;
092      private String example = "", excludeProperties = "", p = "", properties = "", readOnlyProperties = "", ro = "", typeName = "", typePropertyName = "", wo = "", writeOnlyProperties = "",
093         xp = "";
094      private boolean findFluentSetters, sort;
095
096      /**
097       * Constructor.
098       */
099      protected Builder() {
100         super(Bean.class);
101      }
102
103      /**
104       * Instantiates a new {@link Bean @Bean} object initialized with this builder.
105       *
106       * @return A new {@link Bean @Bean} object.
107       */
108      public Bean build() {
109         return new Object(this);
110      }
111
112      /**
113       * Sets the description property on this annotation.
114       *
115       * @param value The new value for this property.
116       * @return This object.
117       */
118      public Builder description(String...value) {
119         description = value;
120         return this;
121      }
122
123      /**
124       * Sets the {@link Bean#dictionary()} property on this annotation.
125       *
126       * @param value The new value for this property.
127       * @return This object.
128       */
129      public Builder dictionary(Class<?>...value) {
130         dictionary = value;
131         return this;
132      }
133
134      /**
135       * Sets the {@link Bean#example()} property on this annotation.
136       *
137       * @param value The new value for this property.
138       * @return This object.
139       */
140      public Builder example(String value) {
141         example = value;
142         return this;
143      }
144
145      /**
146       * Sets the {@link Bean#excludeProperties()} property on this annotation.
147       *
148       * @param value The new value for this property.
149       * @return This object.
150       */
151      public Builder excludeProperties(String value) {
152         excludeProperties = value;
153         return this;
154      }
155
156      /**
157       * Sets the {@link Bean#findFluentSetters()} property on this annotation.
158       *
159       * @param value The new value for this property.
160       * @return This object.
161       */
162      public Builder findFluentSetters(boolean value) {
163         findFluentSetters = value;
164         return this;
165      }
166
167      /**
168       * Sets the {@link Bean#implClass()} property on this annotation.
169       *
170       * @param value The new value for this property.
171       * @return This object.
172       */
173      public Builder implClass(Class<?> value) {
174         implClass = value;
175         return this;
176      }
177
178      /**
179       * Sets the {@link Bean#interceptor()} property on this annotation.
180       *
181       * @param value The new value for this property.
182       * @return This object.
183       */
184      public Builder interceptor(Class<? extends BeanInterceptor<?>> value) {
185         interceptor = value;
186         return this;
187      }
188
189      /**
190       * Sets the {@link Bean#interfaceClass()} property on this annotation.
191       *
192       * @param value The new value for this property.
193       * @return This object.
194       */
195      public Builder interfaceClass(Class<?> value) {
196         interfaceClass = value;
197         return this;
198      }
199
200      /**
201       * Sets the {@link Bean#p()} property on this annotation.
202       *
203       * @param value The new value for this property.
204       * @return This object.
205       */
206      public Builder p(String value) {
207         p = value;
208         return this;
209      }
210
211      /**
212       * Sets the {@link Bean#properties()} property on this annotation.
213       *
214       * @param value The new value for this property.
215       * @return This object.
216       */
217      public Builder properties(String value) {
218         properties = value;
219         return this;
220      }
221
222      /**
223       * Sets the {@link Bean#propertyNamer()} property on this annotation.
224       *
225       * @param value The new value for this property.
226       * @return This object.
227       */
228      public Builder propertyNamer(Class<? extends PropertyNamer> value) {
229         propertyNamer = value;
230         return this;
231      }
232
233      /**
234       * Sets the {@link Bean#readOnlyProperties()} property on this annotation.
235       *
236       * @param value The new value for this property.
237       * @return This object.
238       */
239      public Builder readOnlyProperties(String value) {
240         readOnlyProperties = value;
241         return this;
242      }
243
244      /**
245       * Sets the {@link Bean#ro()} property on this annotation.
246       *
247       * @param value The new value for this property.
248       * @return This object.
249       */
250      public Builder ro(String value) {
251         ro = value;
252         return this;
253      }
254
255      /**
256       * Sets the {@link Bean#sort()} property on this annotation.
257       *
258       * @param value The new value for this property.
259       * @return This object.
260       */
261      public Builder sort(boolean value) {
262         sort = value;
263         return this;
264      }
265
266      /**
267       * Sets the {@link Bean#stopClass()} property on this annotation.
268       *
269       * @param value The new value for this property.
270       * @return This object.
271       */
272      public Builder stopClass(Class<?> value) {
273         stopClass = value;
274         return this;
275      }
276
277      /**
278       * Sets the {@link Bean#typeName()} property on this annotation.
279       *
280       * @param value The new value for this property.
281       * @return This object.
282       */
283      public Builder typeName(String value) {
284         typeName = value;
285         return this;
286      }
287
288      /**
289       * Sets the {@link Bean#typePropertyName()} property on this annotation.
290       *
291       * @param value The new value for this property.
292       * @return This object.
293       */
294      public Builder typePropertyName(String value) {
295         typePropertyName = value;
296         return this;
297      }
298
299      /**
300       * Sets the{@link Bean#wo()} property on this annotation.
301       *
302       * @param value The new value for this property.
303       * @return This object.
304       */
305      public Builder wo(String value) {
306         wo = value;
307         return this;
308      }
309
310      /**
311       * Sets the{@link Bean#writeOnlyProperties()} property on this annotation.
312       *
313       * @param value The new value for this property.
314       * @return This object.
315       */
316      public Builder writeOnlyProperties(String value) {
317         writeOnlyProperties = value;
318         return this;
319      }
320
321      /**
322       * Sets the {@link Bean#xp()} property on this annotation.
323       *
324       * @param value The new value for this property.
325       * @return This object.
326       */
327      public Builder xp(String value) {
328         xp = value;
329         return this;
330      }
331
332      @Override /* Overridden from AppliedAnnotationObject.Builder */
333      public Builder on(String...value) {
334         super.on(value);
335         return this;
336      }
337
338      @Override /* Overridden from AppliedAnnotationObject.BuilderT */
339      public Builder on(Class<?>...value) {
340         super.on(value);
341         return this;
342      }
343
344      @Override /* Overridden from AppliedOnClassAnnotationObject.Builder */
345      public Builder onClass(Class<?>...value) {
346         super.onClass(value);
347         return this;
348      }
349
350      @Override /* Overridden from AppliedAnnotationObject.BuilderT */
351      public Builder on(ClassInfo...value) {
352         super.on(value);
353         return this;
354      }
355
356      @Override /* Overridden from AppliedAnnotationObject.BuilderT */
357      public Builder onClass(ClassInfo...value) {
358         super.onClass(value);
359         return this;
360      }
361
362   }
363
364   private static class Object extends AppliedOnClassAnnotationObject implements Bean {
365
366      private final String[] description;
367      private final boolean findFluentSetters, sort;
368      private final Class<? extends BeanInterceptor<?>> interceptor;
369      private final Class<? extends PropertyNamer> propertyNamer;
370      private final Class<?> implClass, interfaceClass, stopClass;
371      private final Class<?>[] dictionary;
372      private final String example, excludeProperties, p, properties, readOnlyProperties, ro, typeName, typePropertyName, wo, writeOnlyProperties, xp;
373
374      Object(BeanAnnotation.Builder b) {
375         super(b);
376         description = copyOf(b.description);
377         dictionary = copyOf(b.dictionary);
378         example = b.example;
379         excludeProperties = b.excludeProperties;
380         findFluentSetters = b.findFluentSetters;
381         implClass = b.implClass;
382         interceptor = b.interceptor;
383         interfaceClass = b.interfaceClass;
384         p = b.p;
385         properties = b.properties;
386         propertyNamer = b.propertyNamer;
387         readOnlyProperties = b.readOnlyProperties;
388         ro = b.ro;
389         sort = b.sort;
390         stopClass = b.stopClass;
391         typeName = b.typeName;
392         typePropertyName = b.typePropertyName;
393         wo = b.wo;
394         writeOnlyProperties = b.writeOnlyProperties;
395         xp = b.xp;
396      }
397
398      @Override /* Overridden from Bean */
399      public Class<?>[] dictionary() {
400         return dictionary;
401      }
402
403      @Override /* Overridden from Bean */
404      public String example() {
405         return example;
406      }
407
408      @Override /* Overridden from Bean */
409      public String excludeProperties() {
410         return excludeProperties;
411      }
412
413      @Override /* Overridden from Bean */
414      public boolean findFluentSetters() {
415         return findFluentSetters;
416      }
417
418      @Override /* Overridden from Bean */
419      public Class<?> implClass() {
420         return implClass;
421      }
422
423      @Override /* Overridden from Bean */
424      public Class<? extends BeanInterceptor<?>> interceptor() {
425         return interceptor;
426      }
427
428      @Override /* Overridden from Bean */
429      public Class<?> interfaceClass() {
430         return interfaceClass;
431      }
432
433      @Override /* Overridden from Bean */
434      public String p() {
435         return p;
436      }
437
438      @Override /* Overridden from Bean */
439      public String properties() {
440         return properties;
441      }
442
443      @Override /* Overridden from Bean */
444      public Class<? extends PropertyNamer> propertyNamer() {
445         return propertyNamer;
446      }
447
448      @Override /* Overridden from Bean */
449      public String readOnlyProperties() {
450         return readOnlyProperties;
451      }
452
453      @Override /* Overridden from Bean */
454      public String ro() {
455         return ro;
456      }
457
458      @Override /* Overridden from Bean */
459      public boolean sort() {
460         return sort;
461      }
462
463      @Override /* Overridden from Bean */
464      public Class<?> stopClass() {
465         return stopClass;
466      }
467
468      @Override /* Overridden from Bean */
469      public String typeName() {
470         return typeName;
471      }
472
473      @Override /* Overridden from Bean */
474      public String typePropertyName() {
475         return typePropertyName;
476      }
477
478      @Override /* Overridden from Bean */
479      public String wo() {
480         return wo;
481      }
482
483      @Override /* Overridden from Bean */
484      public String writeOnlyProperties() {
485         return writeOnlyProperties;
486      }
487
488      @Override /* Overridden from Bean */
489      public String xp() {
490         return xp;
491      }
492
493      @Override /* Overridden from Bean */
494      public String[] description() {
495         return description;
496      }
497   }
498
499   /** Default value */
500   public static final Bean DEFAULT = create().build();
501
502   /**
503    * Creates a copy of the specified annotation.
504    *
505    * @param a The annotation to copy.
506    * @param r The var resolver for resolving any variables.
507    * @return A copy of the specified annotation.
508    */
509   public static Bean copy(Bean a, VarResolverSession r) {
510      // @formatter:off
511      return
512         create()
513         .dictionary(a.dictionary())
514         .example(r.resolve(a.example()))
515         .excludeProperties(r.resolve(a.excludeProperties()))
516         .findFluentSetters(a.findFluentSetters())
517         .implClass(a.implClass())
518         .interceptor(a.interceptor())
519         .interfaceClass(a.interfaceClass())
520         .on(r.resolve(a.on()))
521         .onClass(a.onClass())
522         .p(r.resolve(a.p()))
523         .properties(r.resolve(a.properties()))
524         .propertyNamer(a.propertyNamer())
525         .readOnlyProperties(r.resolve(a.readOnlyProperties()))
526         .ro(r.resolve(a.ro()))
527         .sort(a.sort())
528         .stopClass(a.stopClass())
529         .typeName(r.resolve(a.typeName()))
530         .typePropertyName(r.resolve(a.typePropertyName()))
531         .wo(r.resolve(a.wo()))
532         .writeOnlyProperties(r.resolve(a.writeOnlyProperties()))
533         .xp(r.resolve(a.xp()))
534         .build();
535      // @formatter:on
536   }
537
538   /**
539    * Instantiates a new builder for this class.
540    *
541    * @return A new builder object.
542    */
543   public static Builder create() {
544      return new Builder();
545   }
546
547   /**
548    * Instantiates a new builder for this class.
549    *
550    * @param on The targets this annotation applies to.
551    * @return A new builder object.
552    */
553   public static Builder create(Class<?>...on) {
554      return create().on(on);
555   }
556
557   /**
558    * Instantiates a new builder for this class.
559    *
560    * @param on The targets this annotation applies to.
561    * @return A new builder object.
562    */
563   public static Builder create(String...on) {
564      return create().on(on);
565   }
566}