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