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.*;
029
030/**
031 * Utility classes and methods for the {@link Marshalled @Marshalled} annotation.
032 *
033 */
034public class MarshalledAnnotation {
035   /**
036    * Applies targeted {@link Marshalled} annotations to a {@link org.apache.juneau.BeanContext.Builder}.
037    */
038   public static class Applier extends AnnotationApplier<Marshalled,BeanContext.Builder> {
039
040      /**
041       * Constructor.
042       *
043       * @param vr The resolver for resolving values in annotations.
044       */
045      public Applier(VarResolverSession vr) {
046         super(Marshalled.class, BeanContext.Builder.class, vr);
047      }
048
049      @Override
050      public void apply(AnnotationInfo<Marshalled> ai, BeanContext.Builder b) {
051         Marshalled a = ai.inner();
052         if (isEmptyArray(a.on()) && isEmptyArray(a.onClass()))
053            return;
054         b.annotations(copy(a, vr()));
055      }
056   }
057
058   /**
059    * A collection of {@link Marshalled @Marshalled annotations}.
060    */
061   @Documented
062   @Target({ METHOD, TYPE })
063   @Retention(RUNTIME)
064   @Inherited
065   public static @interface Array {
066
067      /**
068       * The child annotations.
069       *
070       * @return The annotation value.
071       */
072      Marshalled[] value();
073   }
074
075   /**
076    * Builder class.
077    *
078    * <h5 class='section'>See Also:</h5><ul>
079    *    <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#annotations(Annotation...)}
080    * </ul>
081    */
082   public static class Builder extends AppliedAnnotationObject.BuilderT {
083
084      private String[] description = {};
085      private Class<?> implClass = void.class;
086      private String example = "";
087
088      /**
089       * Constructor.
090       */
091      protected Builder() {
092         super(Marshalled.class);
093      }
094
095      /**
096       * Instantiates a new {@link Marshalled @Marshalled} object initialized with this builder.
097       *
098       * @return A new {@link Marshalled @Marshalled} object.
099       */
100      public Marshalled build() {
101         return new Object(this);
102      }
103
104      /**
105       * Sets the description property on this annotation.
106       *
107       * @param value The new value for this property.
108       * @return This object.
109       */
110      public Builder description(String...value) {
111         description = value;
112         return this;
113      }
114
115      /**
116       * Sets the {@link Marshalled#example()} property on this annotation.
117       *
118       * @param value The new value for this property.
119       * @return This object.
120       */
121      public Builder example(String value) {
122         example = value;
123         return this;
124      }
125
126      /**
127       * Sets the {@link Marshalled#implClass()} property on this annotation.
128       *
129       * @param value The new value for this property.
130       * @return This object.
131       */
132      public Builder implClass(Class<?> value) {
133         implClass = value;
134         return this;
135      }
136
137      @Override /* Overridden from AppliedAnnotationObject.Builder */
138      public Builder on(String...value) {
139         super.on(value);
140         return this;
141      }
142
143      @Override /* Overridden from AppliedAnnotationObject.BuilderT */
144      public Builder on(Class<?>...value) {
145         super.on(value);
146         return this;
147      }
148
149      @Override /* Overridden from AppliedOnClassAnnotationObject.Builder */
150      public Builder onClass(Class<?>...value) {
151         super.onClass(value);
152         return this;
153      }
154
155      @Override /* Overridden from AppliedAnnotationObject.BuilderT */
156      public Builder on(ClassInfo...value) {
157         super.on(value);
158         return this;
159      }
160
161      @Override /* Overridden from AppliedAnnotationObject.BuilderT */
162      public Builder onClass(ClassInfo...value) {
163         super.onClass(value);
164         return this;
165      }
166
167   }
168
169   private static class Object extends AppliedOnClassAnnotationObject implements Marshalled {
170
171      private final String[] description;
172      private final Class<?> implClass;
173      private final String example;
174
175      Object(MarshalledAnnotation.Builder b) {
176         super(b);
177         description = copyOf(b.description);
178         example = b.example;
179         implClass = b.implClass;
180      }
181
182      @Override /* Overridden from Marshalled */
183      public String example() {
184         return example;
185      }
186
187      @Override /* Overridden from Marshalled */
188      public Class<?> implClass() {
189         return implClass;
190      }
191
192      @Override /* Overridden from annotation */
193      public String[] description() {
194         return description;
195      }
196   }
197
198   /** Default value */
199   public static final Marshalled DEFAULT = create().build();
200
201   /**
202    * Creates a copy of the specified annotation.
203    *
204    * @param a The annotation to copy.s
205    * @param r The var resolver for resolving any variables.
206    * @return A copy of the specified annotation.
207    */
208   public static Marshalled copy(Marshalled a, VarResolverSession r) {
209      // @formatter:off
210      return
211         create()
212         .example(r.resolve(a.example()))
213         .implClass(a.implClass())
214         .on(r.resolve(a.on()))
215         .onClass(a.onClass())
216         .build();
217      // @formatter:on
218   }
219
220   /**
221    * Instantiates a new builder for this class.
222    *
223    * @return A new builder object.
224    */
225   public static Builder create() {
226      return new Builder();
227   }
228
229   /**
230    * Instantiates a new builder for this class.
231    *
232    * @param on The targets this annotation applies to.
233    * @return A new builder object.
234    */
235   public static Builder create(Class<?>...on) {
236      return create().on(on);
237   }
238
239   /**
240    * Instantiates a new builder for this class.
241    *
242    * @param on The targets this annotation applies to.
243    * @return A new builder object.
244    */
245   public static Builder create(String...on) {
246      return create().on(on);
247   }
248}