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