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