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.commons.bean;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020
021import org.apache.juneau.commons.*;
022import org.apache.juneau.commons.function.*;
023
024/**
025 * Utility classes and methods for the {@link BeanProp @BeanProp} annotation.
026 *
027 * <p>
028 * Provides a {@link Builder} that constructs a synthetic {@link BeanProp @BeanProp} annotation instance
029 * programmatically without requiring it to be declared on a program element at compile time.
030 *
031 * <p>
032 * This builder is pure-data: it captures the annotation attribute
033 * values and produces an annotation instance that is functionally equivalent to a declared one, but
034 * does <i>not</i> apply itself to a marshalling context. The application logic remains in
035 * <c>juneau-marshall</c> (see {@code MarshalledPropAnnotation} and {@code BeanPropApplyAnnotation})
036 * until later phases move that machinery down into <c>juneau-commons</c>.
037 *
038 * <h5 class='section'>See Also:</h5><ul>
039 *    <li class='ja'>{@link BeanProp}
040 *    <li class='jc'>{@link AnnotationObject}
041 * </ul>
042 */
043@SuppressWarnings({
044   "rawtypes" // Raw types required for reflective annotation application.
045})
046public class BeanPropAnnotation {
047
048   /**
049    * Prevents instantiation.
050    */
051   private BeanPropAnnotation() {}
052
053   /**
054    * Builder class.
055    */
056   public static class Builder extends AnnotationObject.Builder {
057
058      private String[] description = {};
059      private Class<?> type = void.class;
060      private Class<?> elementType = void.class;
061      private Class<?>[] params = new Class[0];
062      private Class<? extends BeanFactory> factory = BeanFactory.Void.class;
063      private String name = "";
064      private boolean required;
065      private String ro = "";
066      private String summary = "";
067      private String value = "";
068      private String wo = "";
069
070      /**
071       * Constructor.
072       */
073      protected Builder() {
074         super(BeanProp.class);
075      }
076
077      /**
078       * Instantiates a new {@link BeanProp @BeanProp} object initialized with this builder.
079       *
080       * @return A new {@link BeanProp @BeanProp} object.
081       */
082      public BeanProp build() {
083         return new Object(this);
084      }
085
086      /**
087       * Sets the description property on this annotation.
088       *
089       * @param value The new value for this property.  Can be <jk>null</jk> (stored as-is, with no default substitution).
090       * @return This object.
091       */
092      public Builder description(String...value) {
093         description = value;
094         return this;
095      }
096
097      /**
098       * Sets the {@link BeanProp#elementType()} property on this annotation.
099       *
100       * @param value The new value for this property.  Can be <jk>null</jk> (stored as-is, with no default substitution).
101       * @return This object.
102       */
103      public Builder elementType(Class<?> value) {
104         elementType = value;
105         return this;
106      }
107
108      /**
109       * Sets the {@link BeanProp#factory()} property on this annotation.
110       *
111       * @param value The new value for this property.  Can be <jk>null</jk> (stored as-is, with no default substitution).
112       * @return This object.
113       */
114      public Builder factory(Class<? extends BeanFactory> value) {
115         factory = value;
116         return this;
117      }
118
119      /**
120       * Sets the {@link BeanProp#name()} property on this annotation.
121       *
122       * @param value The new value for this property.  Can be <jk>null</jk> (stored as-is, with no default substitution).
123       * @return This object.
124       */
125      public Builder name(String value) {
126         name = value;
127         return this;
128      }
129
130      /**
131       * Sets the {@link BeanProp#params()} property on this annotation.
132       *
133       * @param value The new value for this property.  Can be <jk>null</jk> (stored as-is, with no default substitution).
134       * @return This object.
135       */
136      public Builder params(Class<?>...value) {
137         params = value;
138         return this;
139      }
140
141      /**
142       * Sets the {@link BeanProp#required()} property on this annotation.
143       *
144       * @param value The new value for this property.
145       * @return This object.
146       */
147      public Builder required(boolean value) {
148         required = value;
149         return this;
150      }
151
152      /**
153       * Sets the {@link BeanProp#ro()} property on this annotation.
154       *
155       * @param value The new value for this property.  Can be <jk>null</jk> (stored as-is, with no default substitution).
156       * @return This object.
157       */
158      public Builder ro(String value) {
159         ro = value;
160         return this;
161      }
162
163      /**
164       * Sets the {@link BeanProp#summary()} property on this annotation.
165       *
166       * @param value The new value for this property.  Can be <jk>null</jk> (stored as-is, with no default substitution).
167       * @return This object.
168       * @since 10.0.0
169       */
170      public Builder summary(String value) {
171         summary = value;
172         return this;
173      }
174
175      /**
176       * Sets the {@link BeanProp#type()} property on this annotation.
177       *
178       * @param value The new value for this property.  Can be <jk>null</jk> (stored as-is, with no default substitution).
179       * @return This object.
180       */
181      public Builder type(Class<?> value) {
182         type = value;
183         return this;
184      }
185
186      /**
187       * Sets the {@link BeanProp#value()} property on this annotation.
188       *
189       * @param value The new value for this property.  Can be <jk>null</jk> (stored as-is, with no default substitution).
190       * @return This object.
191       */
192      public Builder value(String value) {
193         this.value = value;
194         return this;
195      }
196
197      /**
198       * Sets the {@link BeanProp#wo()} property on this annotation.
199       *
200       * @param value The new value for this property.  Can be <jk>null</jk> (stored as-is, with no default substitution).
201       * @return This object.
202       */
203      public Builder wo(String value) {
204         wo = value;
205         return this;
206      }
207
208   }
209
210   @SuppressWarnings({
211      "annotationSuperInterface", // Eclipse JDT: intentional concrete implementation of annotation interface for runtime-built annotation instances
212      "java:S2160" // equals() inherited from AnnotationObject compares all annotation interface methods; subclass fields are accessed via those methods
213   })
214   private static class Object extends AnnotationObject implements BeanProp {
215
216      private final String[] description;
217      private final Class<?> type;
218      private final Class<?> elementType;
219      private final Class<?>[] params;
220      private final Class<? extends BeanFactory> factory;
221      private final String name;
222      private final String value;
223      private final boolean required;
224      private final String ro;
225      private final String summary;
226      private final String wo;
227
228      Object(BeanPropAnnotation.Builder b) {
229         super(b);
230         description = cp(b.description);
231         elementType = b.elementType;
232         factory = b.factory;
233         name = b.name;
234         params = cp(b.params);
235         required = b.required;
236         ro = b.ro;
237         summary = b.summary;
238         type = b.type;
239         value = b.value;
240         wo = b.wo;
241      }
242
243      @Override /* Overridden from BeanProp */
244      public String[] description() {
245         return cp(description);
246      }
247
248      @Override /* Overridden from BeanProp */
249      public Class<?> elementType() {
250         return elementType;
251      }
252
253      @Override /* Overridden from BeanProp */
254      public Class<? extends BeanFactory> factory() {
255         return factory;
256      }
257
258      @Override /* Overridden from BeanProp */
259      public String name() {
260         return name;
261      }
262
263      @Override /* Overridden from BeanProp */
264      public Class<?>[] params() {
265         return cp(params);
266      }
267
268      @Override /* Overridden from BeanProp */
269      public boolean required() {
270         return required;
271      }
272
273      @Override /* Overridden from BeanProp */
274      public String ro() {
275         return ro;
276      }
277
278      @Override /* Overridden from BeanProp */
279      public String summary() {
280         return summary;
281      }
282
283      @Override /* Overridden from BeanProp */
284      public Class<?> type() {
285         return type;
286      }
287
288      @Override /* Overridden from BeanProp */
289      public String value() {
290         return value;
291      }
292
293      @Override /* Overridden from BeanProp */
294      public String wo() {
295         return wo;
296      }
297   }
298
299   /** Default value */
300   public static final BeanProp DEFAULT = create().build();
301
302   /**
303    * Instantiates a new builder for this class.
304    *
305    * @return A new builder object.
306    */
307   public static Builder create() {
308      return new Builder();
309   }
310}