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