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.marshall.json;
018
019import static org.apache.juneau.commons.utils.CollectionUtils.*;
020
021import java.lang.annotation.*;
022import java.lang.reflect.*;
023
024import org.apache.juneau.commons.*;
025import org.apache.juneau.commons.reflect.*;
026import org.apache.juneau.commons.svl.*;
027import org.apache.juneau.marshall.*;
028
029/**
030 * Utility classes and methods for the {@link JsonApply @JsonApply} annotation.
031 *
032 */
033public class JsonApplyAnnotation {
034
035   /**
036    * Prevents instantiation.
037    */
038   private JsonApplyAnnotation() {}
039
040   /**
041    * Applies targeted {@link JsonApply} annotations to a {@link org.apache.juneau.marshall.Context.Builder Context.Builder}.
042    *
043    * <p>
044    * Passes the {@link JsonApply @JsonApply} annotation through to the builder's annotation list.
045    * The {@link org.apache.juneau.commons.reflect.AnnotationProvider.Builder#addRuntimeAnnotations(java.util.List) AnnotationProvider.Builder#addRuntimeAnnotations(java.util.List)}
046    * method handles unwrapping the nested {@link Json @Json} from {@link JsonApply#value()} and registering it
047    * under the targets specified by {@link JsonApply#on()} and {@link JsonApply#onClass()}.
048    */
049   @SuppressWarnings({
050      "rawtypes" // Raw types required for reflective annotation application.
051   })
052   public static class Applier extends AnnotationApplier<JsonApply,Context.Builder> {
053
054      /**
055       * Constructor.
056       *
057       * @param vr The resolver for resolving values in annotations.
058       *    <br>Must not be <jk>null</jk>.
059       */
060      public Applier(VarResolverSession vr) {
061         super(JsonApply.class, Context.Builder.class, vr);
062      }
063
064      @Override
065      public void apply(AnnotationInfo<JsonApply> ai, Context.Builder b) {
066         JsonApply a = ai.inner();
067         if (isEmptyArray(a.on()) && isEmptyArray(a.onClass()))
068            return;
069         b.annotations(a);
070      }
071   }
072
073   /**
074    * Builder class.
075    *
076    * <h5 class='section'>See Also:</h5><ul>
077    *    <li class='jm'>{@link org.apache.juneau.marshall.MarshallingContext.Builder#annotations(Annotation...) MarshallingContext.Builder#annotations(Annotation...)}
078    * </ul>
079    */
080   public static class Builder extends AppliedAnnotationObject.BuilderTMF {
081
082      Json value = JsonAnnotation.DEFAULT;
083
084      /**
085       * Constructor.
086       */
087      protected Builder() {
088         super(JsonApply.class);
089      }
090
091      /**
092       * Sets the {@link JsonApply#value()} property on this annotation.
093       *
094       * @param value The new value for this property.
095       * @return This object.
096       */
097      public Builder value(Json value) {
098         this.value = value;
099         return this;
100      }
101
102      @Override /* Overridden from AppliedAnnotationObject.Builder */
103      public Builder on(String...value) {
104         super.on(value);
105         return this;
106      }
107
108      @Override /* Overridden from AppliedAnnotationObject.BuilderT */
109      public Builder on(Class<?>...value) {
110         super.on(value);
111         return this;
112      }
113
114      @Override /* Overridden from AppliedOnClassAnnotationObject.Builder */
115      public Builder onClass(Class<?>...value) {
116         super.onClass(value);
117         return this;
118      }
119
120      @Override /* Overridden from AppliedAnnotationObject.BuilderM */
121      public Builder on(Method...value) {
122         super.on(value);
123         return this;
124      }
125
126      @Override /* Overridden from AppliedAnnotationObject.BuilderMF */
127      public Builder on(Field...value) {
128         super.on(value);
129         return this;
130      }
131
132      @Override /* Overridden from AppliedAnnotationObject.BuilderT */
133      public Builder on(ClassInfo...value) {
134         super.on(value);
135         return this;
136      }
137
138      @Override /* Overridden from AppliedAnnotationObject.BuilderT */
139      public Builder onClass(ClassInfo...value) {
140         super.onClass(value);
141         return this;
142      }
143
144      @Override /* Overridden from AppliedAnnotationObject.BuilderTMF */
145      public Builder on(FieldInfo...value) {
146         super.on(value);
147         return this;
148      }
149
150      @Override /* Overridden from AppliedAnnotationObject.BuilderTMF */
151      public Builder on(MethodInfo...value) {
152         super.on(value);
153         return this;
154      }
155
156      /**
157       * Instantiates a new {@link JsonApply @JsonApply} object initialized with this builder.
158       *
159       * @return A new {@link JsonApply} object.
160       */
161      public JsonApply build() {
162         return new Object(this);
163      }
164   }
165
166   @SuppressWarnings({
167      "java:S2160" // equals() inherited from AnnotationObject compares all annotation interface methods; subclass fields are accessed via those methods
168   })
169   private static class Object extends AppliedOnClassAnnotationObject implements JsonApply {
170
171      private final Json value;
172
173      Object(JsonApplyAnnotation.Builder b) {
174         super(b);
175         value = b.value;
176      }
177
178      @Override /* Overridden from JsonApply */
179      public Json value() {
180         return value;
181      }
182   }
183
184   /** Default value */
185   public static final JsonApply DEFAULT = create().build();
186
187   /**
188    * Instantiates a new builder for this class.
189    *
190    * @return A new builder object.
191    */
192   public static Builder create() {
193      return new Builder();
194   }
195
196   /**
197    * Instantiates a new builder for this class.
198    *
199    * @param on The targets this annotation applies to.
200    * @return A new builder object.
201    */
202   public static Builder create(Class<?>...on) {
203      return create().on(on);
204   }
205
206   /**
207    * Instantiates a new builder for this class.
208    *
209    * @param on The targets this annotation applies to.
210    * @return A new builder object.
211    */
212   public static Builder create(String...on) {
213      return create().on(on);
214   }
215
216   /**
217    * Returns <jk>true</jk> if the specified annotation contains all default values.
218    *
219    * @param a The annotation to check.
220    *    <br>Can be <jk>null</jk> (returns <jk>true</jk>).
221    * @return <jk>true</jk> if the specified annotation contains all default values.
222    */
223   public static boolean empty(JsonApply a) {
224      return a == null || DEFAULT.equals(a);
225   }
226}