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;
018
019import static org.apache.juneau.collections.JsonMap.*;
020import static org.apache.juneau.common.utils.ThrowableUtils.*;
021import static org.apache.juneau.common.utils.Utils.*;
022import static org.apache.juneau.internal.ClassUtils.*;
023import static org.apache.juneau.internal.CollectionUtils.*;
024import static org.apache.juneau.internal.ConsumerUtils.*;
025
026import java.lang.annotation.*;
027import java.lang.reflect.*;
028import java.util.*;
029import java.util.concurrent.*;
030import java.util.function.*;
031
032import org.apache.juneau.annotation.*;
033import org.apache.juneau.collections.*;
034import org.apache.juneau.common.utils.*;
035import org.apache.juneau.csv.annotation.*;
036import org.apache.juneau.html.annotation.*;
037import org.apache.juneau.internal.*;
038import org.apache.juneau.json.annotation.*;
039import org.apache.juneau.jsonschema.annotation.*;
040import org.apache.juneau.msgpack.annotation.*;
041import org.apache.juneau.oapi.annotation.*;
042import org.apache.juneau.parser.annotation.*;
043import org.apache.juneau.plaintext.annotation.*;
044import org.apache.juneau.reflect.*;
045import org.apache.juneau.serializer.annotation.*;
046import org.apache.juneau.soap.annotation.*;
047import org.apache.juneau.svl.*;
048import org.apache.juneau.uon.annotation.*;
049import org.apache.juneau.urlencoding.annotation.*;
050import org.apache.juneau.utils.*;
051import org.apache.juneau.xml.annotation.*;
052
053/**
054 * Base class for all Context beans.
055 *
056 * <p>
057 * Context beans follow the convention of havinTg the following parts:
058 * <ul>
059 *    <li>A {@link Builder} class for configuring the context bean.
060 *    <ul>
061 *       <li>This bean is non-thread-safe and meant for one-time use.
062 *    </ul>
063 *    <li>A {@link Context#Context(Builder)} constructor that takes in a builder object.
064 *    <ul>
065 *       <li>This bean is thread-safe and cacheable/reusable.
066 *    </ul>
067 *    <li>A {@link ContextSession} class for doing work.
068 *    <ul>
069 *       <li>This bean is non-thread-safe and meant for one-time use.
070 *    </ul>
071 *
072 * <h5 class='section'>Notes:</h5><ul>
073 *    <li class='note'>This class is thread safe and reusable.
074 * </ul>
075 *
076 * <h5 class='section'>See Also:</h5><ul>
077 * </ul>
078 */
079public abstract class Context implements AnnotationProvider {
080
081   //-----------------------------------------------------------------------------------------------------------------
082   // Static
083   //-----------------------------------------------------------------------------------------------------------------
084
085   private static final Map<Class<?>,MethodInfo> BUILDER_CREATE_METHODS = new ConcurrentHashMap<>();
086
087   /**
088    * Predicate for annotations that themselves are annotated with {@link ContextApply}.
089    */
090   public static final Predicate<AnnotationInfo<?>> CONTEXT_APPLY_FILTER = x -> x.hasAnnotation(ContextApply.class);
091
092   /**
093    * Instantiates a builder of the specified context class.
094    *
095    * <p>
096    * Looks for a public static method called <c>create</c> that returns an object that can be passed into a public
097    * or protected constructor of the class.
098    *
099    * @param type The builder to create.
100    * @return A new builder.
101    */
102   public static Builder createBuilder(Class<? extends Context> type) {
103      try {
104         MethodInfo mi = BUILDER_CREATE_METHODS.get(type);
105         if (mi == null) {
106            ClassInfo c = ClassInfo.of(type);
107            for (ConstructorInfo ci : c.getPublicConstructors()) {
108               if (ci.matches(x -> x.hasNumParams(1) && ! x.getParam(0).getParameterType().is(type))) {
109                  mi = c.getPublicMethod(
110                     x -> x.isStatic()
111                     && x.isNotDeprecated()
112                     && x.hasName("create")
113                     && x.hasReturnType(ci.getParam(0).getParameterType())
114                  );
115                  if (mi != null)
116                     break;
117               }
118            }
119            if (mi == null)
120               throw new BasicRuntimeException("Could not find builder create method on class {0}", type);
121            BUILDER_CREATE_METHODS.put(type, mi);
122         }
123         Builder b = (Builder)mi.invoke(null);
124         b.type(type);
125         return b;
126      } catch (ExecutableException e) {
127         throw asRuntimeException(e);
128      }
129   }
130
131   //-----------------------------------------------------------------------------------------------------------------
132   // Builder
133   //-----------------------------------------------------------------------------------------------------------------
134
135   /**
136    * Builder class.
137    */
138   public abstract static class Builder {
139
140      private static final Map<Class<?>,ConstructorInfo> CONTEXT_CONSTRUCTORS = new ConcurrentHashMap<>();
141
142      boolean debug;
143      Class<? extends Context> type;
144      Context impl;
145      List<Annotation> annotations;
146      Cache<HashKey,? extends Context> cache;
147
148      private final List<Object> builders = Utils.list();
149      private final AnnotationWorkList applied = AnnotationWorkList.create();
150
151      /**
152       * Constructor.
153       * Default settings.
154       */
155      @SuppressWarnings("unchecked")
156      protected Builder() {
157         debug = env("Context.debug", false);
158         annotations = null;
159         registerBuilders(this);
160
161         // By default, the type being created should be the class declaring the builder.
162         Class<?> dc = getClass().getDeclaringClass();
163         if (Context.class.isAssignableFrom(dc))
164            type((Class<? extends Context>)dc);
165      }
166
167      /**
168       * Copy constructor.
169       *
170       * @param copyFrom The bean to copy from.
171       */
172      protected Builder(Context copyFrom) {
173         debug = copyFrom.debug;
174         type = copyFrom.getClass();
175         annotations = listFrom(copyFrom.annotations, true);
176         registerBuilders(this);
177      }
178
179      /**
180       * Copy constructor.
181       *
182       * @param copyFrom The builder to copy from.
183       */
184      protected Builder(Builder copyFrom) {
185         debug = copyFrom.debug;
186         type = copyFrom.type;
187         annotations = listFrom(copyFrom.annotations, true);
188         registerBuilders(this);
189      }
190
191      private Context innerBuild() {
192         if (type == null)
193            throw new BasicRuntimeException("Type not specified for context builder {0}", getClass().getName());
194         if (impl != null && type.isInstance(impl))
195            return type.cast(impl);
196         if (cache != null)
197            return cache.get(hashKey(), ()->getContextConstructor().invoke(this));
198         return getContextConstructor().invoke(this);
199      }
200
201      private ConstructorInfo getContextConstructor() {
202         ConstructorInfo cci = CONTEXT_CONSTRUCTORS.get(type);
203         if (cci == null) {
204            cci = ClassInfo.of(type).getPublicConstructor(
205               x -> x.hasNumParams(1)
206               && x.getParam(0).canAccept(this)
207            );
208            if (cci == null)
209               throw new BasicRuntimeException("Public constructor not found: {0}({1})", className(type), className(this));
210            CONTEXT_CONSTRUCTORS.put(type, cci);
211         }
212         return cci;
213      }
214
215      /**
216       * Copy creator.
217       *
218       * @return A new mutable copy of this builder.
219       */
220      public abstract Builder copy();
221
222      /**
223       * Build the object.
224       *
225       * @return The built object.
226       */
227      public Context build() {
228         return innerBuild();
229      }
230
231      /**
232       * Returns the hashkey of this builder.
233       *
234       * <p>
235       * Used to return previously instantiated context beans that have matching hashkeys.
236       * The {@link HashKey} object is suitable for use as a hashmap key of a map of context beans.
237       * A context bean is considered equivalent if the {@link HashKey#equals(Object)} method is the same.
238       *
239       * @return The hashkey of this builder.
240       */
241      public HashKey hashKey() {
242         return HashKey.of(debug, type, annotations);
243      }
244
245      /**
246       * Specifies a cache to use for hashkey-based caching.
247       *
248       * @param value The cache.
249       * @return This object.
250       */
251      public Builder cache(Cache<HashKey,? extends Context> value) {
252         this.cache = value;
253         return this;
254      }
255
256      /**
257       * Convenience method for calling {@link #build()} while avoiding a cast.
258       *
259       * @param <T> The type to cast the built object to.
260       * @param c The type to cast the built object to.
261       * @return The built context bean.
262       */
263      @SuppressWarnings("unchecked")
264      public final <T extends Context> T build(Class<T> c) {
265         if (type == null || ! c.isAssignableFrom(type))
266            type = c;
267         return (T)innerBuild();
268      }
269
270      /**
271       * Apply a consumer to this builder.
272       *
273       * @param <T> The builder subtype that this consumer can be applied to.
274       * @param subtype The builder subtype that this consumer can be applied to.
275       * @param consumer The consumer.
276       * @return This object.
277       */
278      public <T extends Builder> Builder apply(Class<T> subtype, Consumer<T> consumer) {
279         if (subtype.isInstance(this))
280            consumer.accept(subtype.cast(this));
281         return this;
282      }
283
284      /**
285       * Associates a context class with this builder.
286       *
287       * <p>
288       * This is the type of object that this builder creates when the {@link #build()} method is called.
289       *
290       * <p>
291       * By default, it's the outer class of where the builder class is defined.
292       *
293       * @param value The context class that this builder should create.
294       * @return This object.
295       */
296      public Builder type(Class<? extends Context> value) {
297         this.type = value;
298         return this;
299      }
300
301      /**
302       * Returns the context class that this builder should create.
303       *
304       * @return The context class if it was specified.
305       */
306      public Optional<Class<?>> getType() {
307         return Utils.opt(type);
308      }
309
310      /**
311       * Specifies a pre-instantiated bean for the {@link #build()} method to return.
312       *
313       * @param value The value for this setting.
314       * @return This object.
315       */
316      public Builder impl(Context value) {
317         impl = value;
318         return this;
319      }
320
321      /**
322       * Returns <jk>true</jk> if any of the annotations/appliers can be applied to this builder.
323       *
324       * @param work The work to check.
325       * @return <jk>true</jk> if any of the annotations/appliers can be applied to this builder.
326       */
327      public boolean canApply(AnnotationWorkList work) {
328         Flag f = Flag.create();
329         work.forEach(x -> builders.forEach(b -> f.setIf(x.canApply(b))));
330         return f.isSet();
331      }
332
333      /**
334       * Applies a set of applied to this builder.
335       *
336       * <p>
337       * An {@link AnnotationWork} consists of a single pair of {@link AnnotationInfo} that represents an annotation instance,
338       * and {@link AnnotationApplier} which represents the code used to apply the values in that annotation to a specific builder.
339       *
340       * <h5 class='section'>Example:</h5>
341       * <p class='bjava'>
342       *    <jc>// A class annotated with a config annotation.</jc>
343       *    <ja>@BeanConfig</ja>(sortProperties=<js>"$S{sortProperties,false}"</js>)
344       *    <jk>public class</jk> MyClass {...}
345       *
346       *    <jc>// Find all annotations that themselves are annotated with @ContextPropertiesApply.</jc>
347       *    AnnotationList <jv>annotations</jv> = ClassInfo.<jsm>of</jsm>(MyClass.<jk>class</jk>).getAnnotationList(<jsf>CONTEXT_APPLY_FILTER</jsf>);
348       *    VarResolverSession <jv>vrs</jv> = VarResolver.<jsf>DEFAULT</jsf>.createSession();
349       *    AnnotationWorkList <jv>work</jv> = AnnotationWorkList.of(<jv>vrs</jv>, <jv>annotations</jv>);
350       *
351       *    <jc>// Apply any settings found on the annotations.</jc>
352       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
353       *       .<jsm>create</jsm>()
354       *       .apply(<jv>work</jv>)
355       *       .build();
356       * </p>
357       *
358       * @param work The list of annotations and appliers to apply to this builder.
359       * @return This object.
360       */
361      public Builder apply(AnnotationWorkList work) {
362         applied.addAll(work);
363         work.forEach(x -> builders.forEach(x::apply));
364         return this;
365      }
366
367      /**
368       * Returns all the annotations that have been applied to this builder.
369       *
370       * @return All the annotations that have been applied to this builder.
371       */
372      public AnnotationWorkList getApplied() {
373         return applied;
374      }
375
376      /**
377       * Registers the specified secondary builders with this context builder.
378       *
379       * <p>
380       * When {@link #apply(AnnotationWorkList)} is called, it gets called on all registered builders.
381       *
382       * @param builders The builders to add to the list of builders.
383       */
384      protected void registerBuilders(Object...builders) {
385         for (Object b : builders) {
386            if (b == this)
387               this.builders.add(b);
388            else if (b instanceof Builder b2)
389               this.builders.addAll(b2.builders);
390            else
391               this.builders.add(b);
392         }
393      }
394
395      /**
396       * Applies any of the various <ja>@XConfig</ja> annotations on the specified classes or methods to this context.
397       *
398       * <p>
399       * Any annotations found that themselves are annotated with {@link ContextApply} will be resolved and
400       * applied as properties to this builder.  These annotations include:
401       * <ul class='javatreec'>
402       *    <li class ='ja'>{@link BeanConfig}
403       *    <li class ='ja'>{@link CsvConfig}
404       *    <li class ='ja'>{@link HtmlConfig}
405       *    <li class ='ja'>{@link HtmlDocConfig}
406       *    <li class ='ja'>{@link JsonConfig}
407       *    <li class ='ja'>{@link JsonSchemaConfig}
408       *    <li class ='ja'>{@link MsgPackConfig}
409       *    <li class ='ja'>{@link OpenApiConfig}
410       *    <li class ='ja'>{@link ParserConfig}
411       *    <li class ='ja'>{@link PlainTextConfig}
412       *    <li class ='ja'>{@link SerializerConfig}
413       *    <li class ='ja'>{@link SoapXmlConfig}
414       *    <li class ='ja'>{@link UonConfig}
415       *    <li class ='ja'>{@link UrlEncodingConfig}
416       *    <li class ='ja'>{@link XmlConfig}
417       *    <li class ='ja'><c>RdfConfig</c>
418       * </ul>
419       *
420       * <p>
421       * Annotations on classes are appended in the following order:
422       * <ol>
423       *    <li>On the package of this class.
424       *    <li>On interfaces ordered parent-to-child.
425       *    <li>On parent classes ordered parent-to-child.
426       *    <li>On this class.
427       * </ol>
428       *
429       * <p>
430       * Annotations on methods are appended in the following order:
431       * <ol>
432       *    <li>On the package of the method class.
433       *    <li>On interfaces ordered parent-to-child.
434       *    <li>On parent classes ordered parent-to-child.
435       *    <li>On the method class.
436       *    <li>On this method and matching methods ordered parent-to-child.
437       * </ol>
438       *
439       * <p>
440       * The default var resolver {@link VarResolver#DEFAULT} is used to resolve any variables in annotation field values.
441       *
442       * <h5 class='section'>Example:</h5>
443       * <p class='bjava'>
444       *    <jc>// A class annotated with a config annotation.</jc>
445       *    <ja>@BeanConfig</ja>(sortProperties=<js>"$S{sortProperties,false}"</js>)
446       *    <jk>public class</jk> MyClass {...}
447       *
448       *    <jc>// Apply any settings found on the annotations.</jc>
449       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
450       *       .<jsm>create</jsm>()
451       *       .applyAnnotations(MyClass.<jk>class</jk>)
452       *       .build();
453       *
454       *    <jc>// A method annotated with a config annotation.</jc>
455       *    <jk>public class</jk> MyClass {
456       *       <ja>@BeanConfig</ja>(sortProperties=<js>"$S{sortProperties,false}"</js>)
457       *       <jk>public void</jk> myMethod() {...}
458       *    }
459       *
460       *    <jc>// Apply any settings found on the annotations.</jc>
461       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
462       *       .<jsm>create</jsm>()
463       *       .applyAnnotations(MyClass.<jk>class</jk>.getMethod(<js>"myMethod"</js>))
464       *       .build();
465       * </p>
466       *
467       * @param from The classes or methods on which the annotations are defined.
468       *    Can be any of the following types:
469       *    <ul>
470       *       <li>{@link Class}
471       *       <li>{@link ClassInfo}
472       *       <li>{@link Method}
473       *       <li>{@link MethodInfo}
474       *    <li>A collection/stream/array of anything on this list.
475       * @return This object.
476       */
477      public Builder applyAnnotations(Object...from) {
478         var work = AnnotationWorkList.create();
479         Arrays.stream(from).forEach(x -> traverse(work, x));
480         return apply(work);
481      }
482
483      private AnnotationWorkList traverse(AnnotationWorkList work, Object x) {
484         Utils.traverse(x, y -> {
485            if (x instanceof Class<?> x2)
486               work.add(ClassInfo.of(x2).getAnnotationList(CONTEXT_APPLY_FILTER));
487            else if (x instanceof ClassInfo x2)
488               work.add(x2.getAnnotationList(CONTEXT_APPLY_FILTER));
489            else if (x instanceof Method x2)
490               work.add(MethodInfo.of(x2).getAnnotationList(CONTEXT_APPLY_FILTER));
491            else if (x instanceof MethodInfo x2)
492               work.add(x2.getAnnotationList(CONTEXT_APPLY_FILTER));
493            else
494               throw illegalArg("Invalid type passed to applyAnnotations:  {0}", x.getClass().getName());
495         });
496         return work;
497      }
498
499      /**
500       * Same as {@link #applyAnnotations(Object...)} but explicitly specifies a class varargs to avoid compilation warnings.
501       *
502       * @param from The classes or methods on which the annotations are defined.
503       * @return This object.
504       */
505      public Builder applyAnnotations(Class<?>...from) {
506         return applyAnnotations((Object[])from);
507      }
508
509      //-----------------------------------------------------------------------------------------------------------------
510      // Properties
511      //-----------------------------------------------------------------------------------------------------------------
512
513      /**
514       * Defines annotations to apply to specific classes and methods.
515       *
516       * <p>
517       * Allows you to dynamically apply Juneau annotations typically applied directly to classes and methods.
518       * Useful in cases where you want to use the functionality of the annotation on beans and bean properties but
519       * do not have access to the code to do so.
520       *
521       * <p>
522       * As a rule, any Juneau annotation with an <l>on()</l> method can be used with this setting.
523       *
524       * <p>
525       * The following example shows the equivalent methods for applying the {@link Bean @Bean} annotation:
526       * <p class='bjava'>
527       *    <jc>// Class with explicit annotation.</jc>
528       *    <ja>@Bean</ja>(properties=<js>"street,city,state"</js>)
529       *    <jk>public class</jk> A {...}
530       *
531       *    <jc>// Class with annotation applied via @BeanConfig</jc>
532       *    <jk>public class</jk> B {...}
533       *
534       *    <jc>// Java REST method with @BeanConfig annotation.</jc>
535       *    <ja>@RestGet</ja>(...)
536       *    <ja>@Bean</ja>(on=<js>"B"</js>, properties=<js>"street,city,state"</js>)
537       *    <jk>public void</jk> doFoo() {...}
538       * </p>
539       *
540       * <p>
541       * In general, the underlying framework uses this method when it finds dynamically applied annotations on
542       * config annotations.  However, concrete implementations of annotations are also provided that can be passed
543       * directly into builder classes like so:
544       * <p class='bjava'>
545       *    <jc>// Create a concrete @Bean annotation.</jc>
546       *    <ja>Bean</ja> <jv>annotation</jv> = BeanAnnotation.<jsm>create</jsm>(B.<jk>class</jk>).properties(<js>"street,city,state"</js>).build();
547       *
548       *    <jc>// Apply it to a serializer.</jc>
549       *    WriterSerializer <jv>serializer</jv> = JsonSerializer.<jsm>create</jsm>().annotations(<jv>annotation</jv>).build();
550       *
551       *    <jc>// Serialize a bean with the dynamically applied annotation.</jc>
552       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> B());
553       * </p>
554       *
555       * <p>
556       * The following is the list of annotations builders provided that can be constructed
557       * and passed into the builder class:
558       * <ul class='javatreec'>
559       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanAnnotation}
560       *    <li class='ja'>{@link org.apache.juneau.annotation.BeancAnnotation}
561       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanIgnoreAnnotation}
562       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanpAnnotation}
563       *    <li class='ja'>{@link org.apache.juneau.annotation.ExampleAnnotation}
564       *    <li class='ja'>{@link org.apache.juneau.annotation.NamePropertyAnnotation}
565       *    <li class='ja'>{@link org.apache.juneau.annotation.ParentPropertyAnnotation}
566       *    <li class='ja'>{@link org.apache.juneau.annotation.SwapAnnotation}
567       *    <li class='ja'>{@link org.apache.juneau.annotation.UriAnnotation}
568       *    <li class='ja'>{@link org.apache.juneau.csv.annotation.CsvAnnotation}
569       *    <li class='ja'>{@link org.apache.juneau.html.annotation.HtmlAnnotation}
570       *    <li class='ja'>{@link org.apache.juneau.json.annotation.JsonAnnotation}
571       *    <li class='ja'>{@link org.apache.juneau.annotation.SchemaAnnotation}
572       *    <li class='ja'>{@link org.apache.juneau.msgpack.annotation.MsgPackAnnotation}
573       *    <li class='ja'>{@link org.apache.juneau.oapi.annotation.OpenApiAnnotation}
574       *    <li class='ja'>{@link org.apache.juneau.plaintext.annotation.PlainTextAnnotation}
575       *    <li class='ja'>{@link org.apache.juneau.soap.annotation.SoapXmlAnnotation}
576       *    <li class='ja'>{@link org.apache.juneau.uon.annotation.UonAnnotation}
577       *    <li class='ja'>{@link org.apache.juneau.urlencoding.annotation.UrlEncodingAnnotation}
578       *    <li class='ja'>{@link org.apache.juneau.xml.annotation.XmlAnnotation}
579       * </ul>
580       *
581       * <p>
582       * The syntax for the <l>on()</l> pattern match parameter depends on whether it applies to a class, method, field, or constructor.
583       * The valid pattern matches are:
584       * <ul class='spaced-list'>
585       *  <li>Classes:
586       *       <ul>
587       *          <li>Fully qualified:
588       *             <ul>
589       *                <li><js>"com.foo.MyClass"</js>
590       *             </ul>
591       *          <li>Fully qualified inner class:
592       *             <ul>
593       *                <li><js>"com.foo.MyClass$Inner1$Inner2"</js>
594       *             </ul>
595       *          <li>Simple:
596       *             <ul>
597       *                <li><js>"MyClass"</js>
598       *             </ul>
599       *          <li>Simple inner:
600       *             <ul>
601       *                <li><js>"MyClass$Inner1$Inner2"</js>
602       *                <li><js>"Inner1$Inner2"</js>
603       *                <li><js>"Inner2"</js>
604       *             </ul>
605       *       </ul>
606       *    <li>Methods:
607       *       <ul>
608       *          <li>Fully qualified with args:
609       *             <ul>
610       *                <li><js>"com.foo.MyClass.myMethod(String,int)"</js>
611       *                <li><js>"com.foo.MyClass.myMethod(java.lang.String,int)"</js>
612       *                <li><js>"com.foo.MyClass.myMethod()"</js>
613       *             </ul>
614       *          <li>Fully qualified:
615       *             <ul>
616       *                <li><js>"com.foo.MyClass.myMethod"</js>
617       *             </ul>
618       *          <li>Simple with args:
619       *             <ul>
620       *                <li><js>"MyClass.myMethod(String,int)"</js>
621       *                <li><js>"MyClass.myMethod(java.lang.String,int)"</js>
622       *                <li><js>"MyClass.myMethod()"</js>
623       *             </ul>
624       *          <li>Simple:
625       *             <ul>
626       *                <li><js>"MyClass.myMethod"</js>
627       *             </ul>
628       *          <li>Simple inner class:
629       *             <ul>
630       *                <li><js>"MyClass$Inner1$Inner2.myMethod"</js>
631       *                <li><js>"Inner1$Inner2.myMethod"</js>
632       *                <li><js>"Inner2.myMethod"</js>
633       *             </ul>
634       *       </ul>
635       *    <li>Fields:
636       *       <ul>
637       *          <li>Fully qualified:
638       *             <ul>
639       *                <li><js>"com.foo.MyClass.myField"</js>
640       *             </ul>
641       *          <li>Simple:
642       *             <ul>
643       *                <li><js>"MyClass.myField"</js>
644       *             </ul>
645       *          <li>Simple inner class:
646       *             <ul>
647       *                <li><js>"MyClass$Inner1$Inner2.myField"</js>
648       *                <li><js>"Inner1$Inner2.myField"</js>
649       *                <li><js>"Inner2.myField"</js>
650       *             </ul>
651       *       </ul>
652       *    <li>Constructors:
653       *       <ul>
654       *          <li>Fully qualified with args:
655       *             <ul>
656       *                <li><js>"com.foo.MyClass(String,int)"</js>
657       *                <li><js>"com.foo.MyClass(java.lang.String,int)"</js>
658       *                <li><js>"com.foo.MyClass()"</js>
659       *             </ul>
660       *          <li>Simple with args:
661       *             <ul>
662       *                <li><js>"MyClass(String,int)"</js>
663       *                <li><js>"MyClass(java.lang.String,int)"</js>
664       *                <li><js>"MyClass()"</js>
665       *             </ul>
666       *          <li>Simple inner class:
667       *             <ul>
668       *                <li><js>"MyClass$Inner1$Inner2()"</js>
669       *                <li><js>"Inner1$Inner2()"</js>
670       *                <li><js>"Inner2()"</js>
671       *             </ul>
672       *       </ul>
673       *    <li>A comma-delimited list of anything on this list.
674       * </ul>
675       *
676       * <h5 class='section'>See Also:</h5><ul>
677       *    <li class='ja'>{@link BeanConfig}
678       * </ul>
679       *
680       * @param values
681       *    The annotations to register with the context.
682       * @return This object.
683       */
684      public Builder annotations(Annotation...values) {
685         annotations = addAll(annotations, values);
686         return this;
687      }
688
689      /**
690       * Same as {@link #annotations(Annotation...)} but uses a list as input.
691       *
692       * @param values
693       *    The annotations to register with the context.
694       * @return This object.
695       */
696      public Builder annotations(List<Annotation> values) {
697         annotations = addAll(annotations, values);
698         return this;
699      }
700
701      /**
702       * <i><l>Context</l> configuration property:&emsp;</i>  Debug mode.
703       *
704       * <p>
705       * Enables the following additional information during serialization:
706       * <ul class='spaced-list'>
707       *    <li>
708       *       When bean getters throws exceptions, the exception includes the object stack information
709       *       in order to determine how that method was invoked.
710       *    <li>
711       *       Enables {@link BeanTraverseContext.Builder#detectRecursions()}.
712       * </ul>
713       *
714       * <p>
715       * Enables the following additional information during parsing:
716       * <ul class='spaced-list'>
717       *    <li>
718       *       When bean setters throws exceptions, the exception includes the object stack information
719       *       in order to determine how that method was invoked.
720       * </ul>
721       *
722       * <h5 class='section'>Example:</h5>
723       * <p class='bjava'>
724       *    <jc>// Create a serializer with debug enabled.</jc>
725       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
726       *       .<jsm>create</jsm>()
727       *       .debug()
728       *       .build();
729       *
730       *    <jc>// Create a POJO model with a recursive loop.</jc>
731       *    <jk>public class</jk> MyBean {
732       *       <jk>public</jk> Object <jf>f</jf>;
733       *    }
734       *    MyBean <jv>bean</jv> = <jk>new</jk> MyBean();
735       *    <jv>bean</jv>.<jf>f</jf> = <jv>bean</jv>;
736       *
737       *    <jc>// Throws a SerializeException and not a StackOverflowError</jc>
738       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>bean</jv>);
739       * </p>
740       *
741       * <h5 class='section'>See Also:</h5><ul>
742       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#debug()}
743       *    <li class='jm'>{@link org.apache.juneau.ContextSession.Builder#debug(Boolean)}
744       * </ul>
745       *
746       * @return This object.
747       */
748      public Builder debug() {
749         return debug(true);
750      }
751
752      /**
753       * Same as {@link #debug()} but allows you to explicitly specify the value.
754       *
755       * @param value The value for this setting.
756       * @return This object.
757       */
758      public Builder debug(boolean value) {
759         debug = value;
760         return this;
761      }
762
763      /**
764       * Returns <jk>true</jk> if debug is enabled.
765       *
766       * @return <jk>true</jk> if debug is enabled.
767       */
768      public boolean isDebug() {
769         return debug;
770      }
771   }
772
773   //-----------------------------------------------------------------------------------------------------------------
774   // Instance
775   //-----------------------------------------------------------------------------------------------------------------
776
777   final List<Annotation> annotations;
778   final boolean debug;
779
780   private final ReflectionMap<Annotation> annotationMap;
781   private final TwoKeyConcurrentCache<Class<?>,Class<? extends Annotation>,Annotation[]> classAnnotationCache;
782   private final TwoKeyConcurrentCache<Class<?>,Class<? extends Annotation>,Annotation[]> declaredClassAnnotationCache;
783   private final TwoKeyConcurrentCache<Method,Class<? extends Annotation>,Annotation[]> methodAnnotationCache;
784   private final TwoKeyConcurrentCache<Field,Class<? extends Annotation>,Annotation[]> fieldAnnotationCache;
785   private final TwoKeyConcurrentCache<Constructor<?>,Class<? extends Annotation>,Annotation[]> constructorAnnotationCache;
786
787   /**
788    * Copy constructor.
789    *
790    * @param copyFrom The context to copy from.
791    */
792   protected Context(Context copyFrom) {
793      annotationMap = copyFrom.annotationMap;
794      annotations = copyFrom.annotations;
795      debug = copyFrom.debug;
796      classAnnotationCache = copyFrom.classAnnotationCache;
797      declaredClassAnnotationCache = copyFrom.declaredClassAnnotationCache;
798      methodAnnotationCache = copyFrom.methodAnnotationCache;
799      fieldAnnotationCache = copyFrom.fieldAnnotationCache;
800      constructorAnnotationCache = copyFrom.constructorAnnotationCache;
801   }
802
803   /**
804    * Constructor for this class.
805    *
806    * @param builder The builder for this class.
807    */
808   protected Context(Builder builder) {
809      init(builder);
810      debug = builder.debug;
811      annotations = Utils.opt(builder.annotations).orElseGet(Collections::emptyList);
812
813      ReflectionMap.Builder<Annotation> rmb = ReflectionMap.create(Annotation.class);
814
815      annotations.forEach(a -> {
816         try {
817            ClassInfo ci = ClassInfo.of(a.getClass());
818
819            MethodInfo mi = ci.getPublicMethod(x -> x.hasName("onClass"));
820            if (mi != null) {
821               if (! mi.getReturnType().is(Class[].class))
822                  throw new ConfigException("Invalid annotation @{0} used in BEAN_annotations property.  Annotation must define an onClass() method that returns a Class array.", a.getClass().getSimpleName());
823               for (Class<?> c : (Class<?>[])mi.accessible().invoke(a))
824                  rmb.append(c.getName(), a);
825            }
826
827            mi = ci.getPublicMethod(x -> x.hasName("on"));
828            if (mi != null) {
829               if (! mi.getReturnType().is(String[].class))
830                  throw new ConfigException("Invalid annotation @{0} used in BEAN_annotations property.  Annotation must define an on() method that returns a String array.", a.getClass().getSimpleName());
831               for (String s : (String[])mi.accessible().invoke(a))
832                  rmb.append(s, a);
833            }
834
835         } catch (Exception e) {
836            throw new ConfigException(e, "Invalid annotation @{0} used in BEAN_annotations property.", className(a));
837         }
838      });
839      this.annotationMap = rmb.build();
840      boolean disabled = Boolean.getBoolean("juneau.disableAnnotationCaching");
841      classAnnotationCache = new TwoKeyConcurrentCache<>(disabled, (k1,k2) -> annotationMap.appendAll(k1, k2, k1.getAnnotationsByType(k2)));
842      declaredClassAnnotationCache = new TwoKeyConcurrentCache<>(disabled, (k1,k2) -> annotationMap.appendAll(k1, k2, k1.getDeclaredAnnotationsByType(k2)));
843      methodAnnotationCache = new TwoKeyConcurrentCache<>(disabled, (k1,k2) -> annotationMap.appendAll(k1, k2, k1.getAnnotationsByType(k2)));
844      fieldAnnotationCache = new TwoKeyConcurrentCache<>(disabled, (k1,k2) -> annotationMap.appendAll(k1, k2, k1.getAnnotationsByType(k2)));
845      constructorAnnotationCache = new TwoKeyConcurrentCache<>(disabled, (k1,k2) -> annotationMap.appendAll(k1, k2, k1.getAnnotationsByType(k2)));
846   }
847
848   /**
849    * Perform optional initialization on builder before it is used.
850    *
851    * <p>
852    * Default behavior is a no-op.
853    *
854    * @param builder The builder to initialize.
855    */
856   protected void init(Builder builder) {}
857
858   /**
859    * Creates a builder from this context object.
860    *
861    * <p>
862    * Builders are used to define new contexts (e.g. serializers, parsers) based on existing configurations.
863    *
864    * @return A new Builder object.
865    */
866   public Builder copy() {
867      throw new UnsupportedOperationException("Not implemented.");
868   }
869
870   /**
871    * Create a session builder based on the properties defined on this context.
872    *
873    * <p>
874    * Use this method for creating sessions where you want to override basic settings.
875    * Otherwise, use {@link #getSession()} directly.
876    *
877    * @return A new session builder.
878    */
879   public ContextSession.Builder createSession() {
880      throw new UnsupportedOperationException("Not implemented.");
881   }
882
883   /**
884    * Returns a session to use for this context.
885    *
886    * <p>
887    * Note that subclasses may opt to return a reusable non-modifiable session.
888    *
889    * @return A new session object.
890    */
891   public ContextSession getSession() {
892      return createSession().build();
893   }
894
895   //-----------------------------------------------------------------------------------------------------------------
896   // Properties
897   //-----------------------------------------------------------------------------------------------------------------
898
899   /**
900    * Debug mode.
901    *
902    * @see Context.Builder#debug()
903    * @return
904    *    <jk>true</jk> if debug mode is enabled.
905    */
906   public boolean isDebug() {
907      return debug;
908   }
909
910   //-----------------------------------------------------------------------------------------------------------------
911   // MetaProvider methods
912   //-----------------------------------------------------------------------------------------------------------------
913
914   @Override /* MetaProvider */
915   public <A extends Annotation> void forEachAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter, Consumer<A> action) {
916      if (type != null && onClass != null)
917         for (A a : annotations(type, onClass))
918            consume(filter, action, a);
919   }
920
921   @Override /* MetaProvider */
922   public <A extends Annotation> A firstAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter) {
923      if (type != null && onClass != null)
924         for (A a : annotations(type, onClass))
925            if (test(filter, a))
926               return a;
927      return null;
928   }
929
930   @Override /* MetaProvider */
931   public <A extends Annotation> A lastAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter) {
932      A x = null;
933      if (type != null && onClass != null)
934         for (A a : annotations(type, onClass))
935            if (test(filter, a))
936               x = a;
937      return x;
938   }
939
940   @Override /* MetaProvider */
941   public <A extends Annotation> void forEachDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter, Consumer<A> action) {
942      if (type != null && onClass != null)
943         for (A a : declaredAnnotations(type, onClass))
944            consume(filter, action, a);
945   }
946
947   @Override /* MetaProvider */
948   public <A extends Annotation> A firstDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter) {
949      if (type != null && onClass != null)
950         for (A a : declaredAnnotations(type, onClass))
951            if (test(filter, a))
952               return a;
953      return null;
954   }
955
956   @Override /* MetaProvider */
957   public <A extends Annotation> A lastDeclaredAnnotation(Class<A> type, Class<?> onClass, Predicate<A> filter) {
958      A x = null;
959      if (type != null && onClass != null)
960         for (A a : declaredAnnotations(type, onClass))
961            if (test(filter, a))
962               x = a;
963      return x;
964   }
965
966   @Override /* MetaProvider */
967   public <A extends Annotation> void forEachAnnotation(Class<A> type, Method onMethod, Predicate<A> filter, Consumer<A> action) {
968      if (type != null && onMethod != null)
969         for (A a : annotations(type, onMethod))
970            consume(filter, action, a);
971   }
972
973   @Override /* MetaProvider */
974   public <A extends Annotation> A firstAnnotation(Class<A> type, Method onMethod, Predicate<A> filter) {
975      if (type != null && onMethod != null)
976         for (A a : annotations(type, onMethod))
977            if (test(filter, a))
978               return a;
979      return null;
980   }
981
982   @Override /* MetaProvider */
983   public <A extends Annotation> A lastAnnotation(Class<A> type, Method onMethod, Predicate<A> filter) {
984      A x = null;
985      if (type != null && onMethod != null)
986         for (A a : annotations(type, onMethod))
987            if (test(filter, a))
988               x = a;
989      return x;
990   }
991
992   @Override /* MetaProvider */
993   public <A extends Annotation> void forEachAnnotation(Class<A> type, Field onField, Predicate<A> filter, Consumer<A> action) {
994      if (type != null && onField != null)
995         for (A a : annotations(type, onField))
996            consume(filter, action, a);
997   }
998
999   @Override /* MetaProvider */
1000   public <A extends Annotation> A firstAnnotation(Class<A> type, Field onField, Predicate<A> filter) {
1001      if (type != null && onField != null)
1002         for (A a : annotations(type, onField))
1003            if (test(filter, a))
1004               return a;
1005      return null;
1006   }
1007
1008   @Override /* MetaProvider */
1009   public <A extends Annotation> A lastAnnotation(Class<A> type, Field onField, Predicate<A> filter) {
1010      A x = null;
1011      if (type != null && onField != null)
1012         for (A a : annotations(type, onField))
1013            if (test(filter, a))
1014               x = a;
1015      return x;
1016   }
1017
1018   @Override /* MetaProvider */
1019   public <A extends Annotation> void forEachAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter, Consumer<A> action) {
1020      if (type != null && onConstructor != null)
1021         for (A a : annotations(type, onConstructor))
1022            consume(filter, action, a);
1023   }
1024
1025   @Override /* MetaProvider */
1026   public <A extends Annotation> A firstAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter) {
1027      if (type != null && onConstructor != null)
1028         for (A a : annotations(type, onConstructor))
1029            if (test(filter, a))
1030               return a;
1031      return null;
1032   }
1033
1034   @Override /* MetaProvider */
1035   public <A extends Annotation> A lastAnnotation(Class<A> type, Constructor<?> onConstructor, Predicate<A> filter) {
1036      A x = null;
1037      if (type != null && onConstructor != null)
1038         for (A a : annotations(type, onConstructor))
1039            if (test(filter, a))
1040               x = a;
1041      return x;
1042   }
1043
1044   /**
1045    * Returns <jk>true</jk> if <c>getAnnotation(a,c)</c> returns a non-null value.
1046    *
1047    * @param <A> The annotation being checked for.
1048    * @param type The annotation being checked for.
1049    * @param onClass The class being checked on.
1050    * @return <jk>true</jk> if the annotation exists on the specified class.
1051    */
1052   public <A extends Annotation> boolean hasAnnotation(Class<A> type, Class<?> onClass) {
1053      return annotations(type, onClass).length > 0;
1054   }
1055
1056   /**
1057    * Returns <jk>true</jk> if <c>getAnnotation(a,m)</c> returns a non-null value.
1058    *
1059    * @param <A> The annotation being checked for.
1060    * @param type The annotation being checked for.
1061    * @param onMethod The method being checked on.
1062    * @return <jk>true</jk> if the annotation exists on the specified method.
1063    */
1064   public <A extends Annotation> boolean hasAnnotation(Class<A> type, Method onMethod) {
1065      return annotations(type, onMethod).length > 0;
1066   }
1067
1068   /**
1069    * Returns <jk>true</jk> if <c>getAnnotation(a,f)</c> returns a non-null value.
1070    *
1071    * @param <A> The annotation being checked for.
1072    * @param type The annotation being checked for.
1073    * @param onField The field being checked on.
1074    * @return <jk>true</jk> if the annotation exists on the specified field.
1075    */
1076   public <A extends Annotation> boolean hasAnnotation(Class<A> type, Field onField) {
1077      return annotations(type, onField).length > 0;
1078   }
1079
1080   /**
1081    * Returns <jk>true</jk> if <c>getAnnotation(a,c)</c> returns a non-null value.
1082    *
1083    * @param <A> The annotation being checked for.
1084    * @param type The annotation being checked for.
1085    * @param onConstructor The constructor being checked on.
1086    * @return <jk>true</jk> if the annotation exists on the specified field.
1087    */
1088   public <A extends Annotation> boolean hasAnnotation(Class<A> type, Constructor<?> onConstructor) {
1089      return annotations(type, onConstructor).length > 0;
1090   }
1091
1092   @SuppressWarnings("unchecked")
1093   private <A extends Annotation> A[] annotations(Class<A> type, Class<?> onClass) {
1094      return (A[])classAnnotationCache.get(onClass, type);
1095   }
1096
1097   @SuppressWarnings("unchecked")
1098   private <A extends Annotation> A[] declaredAnnotations(Class<A> type, Class<?> onClass) {
1099      return (A[])declaredClassAnnotationCache.get(onClass, type);
1100   }
1101
1102   @SuppressWarnings("unchecked")
1103   private <A extends Annotation> A[] annotations(Class<A> type, Method onMethod) {
1104      return (A[])methodAnnotationCache.get(onMethod, type);
1105   }
1106
1107   @SuppressWarnings("unchecked")
1108   private <A extends Annotation> A[] annotations(Class<A> type, Field onField) {
1109      return (A[])fieldAnnotationCache.get(onField, type);
1110   }
1111
1112   @SuppressWarnings("unchecked")
1113   private <A extends Annotation> A[] annotations(Class<A> type, Constructor<?> onConstructor) {
1114      return (A[])constructorAnnotationCache.get(onConstructor, type);
1115   }
1116
1117   //-----------------------------------------------------------------------------------------------------------------
1118   // Other methods
1119   //-----------------------------------------------------------------------------------------------------------------
1120
1121   /**
1122    * Returns the properties on this bean as a map for debugging.
1123    *
1124    * @return The properties on this bean as a map for debugging.
1125    */
1126   protected JsonMap properties() {
1127      return filteredMap("annotations", annotations, "debug", debug);
1128   }
1129
1130   @Override /* Object */
1131   public String toString() {
1132      return Utils2.toPropertyMap(this).asReadableString();
1133   }
1134}