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.commons.reflect.ReflectionUtils.*;
020import static org.apache.juneau.commons.utils.AssertionUtils.*;
021import static org.apache.juneau.commons.utils.CollectionUtils.*;
022import static org.apache.juneau.commons.utils.ThrowableUtils.*;
023import static org.apache.juneau.commons.utils.Utils.*;
024
025import java.lang.annotation.*;
026import java.lang.reflect.*;
027import java.util.*;
028import java.util.function.*;
029import org.apache.juneau.annotation.*;
030import org.apache.juneau.commons.collections.*;
031import org.apache.juneau.commons.reflect.*;
032import org.apache.juneau.commons.utils.*;
033import org.apache.juneau.csv.annotation.*;
034import org.apache.juneau.html.annotation.*;
035import org.apache.juneau.json.annotation.*;
036import org.apache.juneau.jsonschema.annotation.*;
037import org.apache.juneau.msgpack.annotation.*;
038import org.apache.juneau.oapi.annotation.*;
039import org.apache.juneau.parser.annotation.*;
040import org.apache.juneau.plaintext.annotation.*;
041import org.apache.juneau.serializer.annotation.*;
042import org.apache.juneau.soap.annotation.*;
043import org.apache.juneau.svl.*;
044import org.apache.juneau.uon.annotation.*;
045import org.apache.juneau.urlencoding.annotation.*;
046import org.apache.juneau.xml.annotation.*;
047
048/**
049 * Base class for all Context beans.
050 *
051 * <p>
052 * Context beans follow the convention of havinTg the following parts:
053 * <ul>
054 *    <li>A {@link Builder} class for configuring the context bean.
055 *    <ul>
056 *       <li>This bean is non-thread-safe and meant for one-time use.
057 *    </ul>
058 *    <li>A {@link Context#Context(Builder)} constructor that takes in a builder object.
059 *    <ul>
060 *       <li>This bean is thread-safe and cacheable/reusable.
061 *    </ul>
062 *    <li>A {@link ContextSession} class for doing work.
063 *    <ul>
064 *       <li>This bean is non-thread-safe and meant for one-time use.
065 *    </ul>
066 *
067 * <h5 class='section'>Notes:</h5><ul>
068 *    <li class='note'>This class is thread safe and reusable.
069 * </ul>
070 *
071 */
072public abstract class Context {
073
074   /**
075    * Builder class.
076    */
077   public abstract static class Builder {
078
079      private boolean debug;
080      private final AnnotationWorkList applied = AnnotationWorkList.create();
081      private Cache<HashKey,? extends Context> cache;
082      private Class<? extends Context> type;
083      private Context impl;
084      private List<Annotation> annotations;
085      private final List<Object> builders = list();
086
087      /**
088       * Constructor.
089       * Default settings.
090       */
091      @SuppressWarnings("unchecked")
092      protected Builder() {
093         debug = env("Context.debug", false);
094         annotations = list();
095         registerBuilders(this);
096
097         // By default, the type being created should be the class declaring the builder.
098         var dc = getClass().getDeclaringClass();
099         if (Context.class.isAssignableFrom(dc))
100            type((Class<? extends Context>)dc);
101      }
102
103      /**
104       * Copy constructor.
105       *
106       * @param copyFrom The builder to copy from.
107       *    <br>Cannot be <jk>null</jk>.
108       */
109      protected Builder(Builder copyFrom) {
110         assertArgNotNull("copyFrom", copyFrom);
111         annotations = copyOf(copyFrom.annotations);
112         debug = copyFrom.debug;
113         type = copyFrom.type;
114         registerBuilders(this);
115      }
116
117      /**
118       * Copy constructor.
119       *
120       * @param copyFrom The bean to copy from.
121       *    <br>Cannot be <jk>null</jk>.
122       */
123      protected Builder(Context copyFrom) {
124         assertArgNotNull("copyFrom", copyFrom);
125         annotations = copyOf(copyFrom.annotations);
126         debug = copyFrom.debug;
127         type = copyFrom.getClass();
128         registerBuilders(this);
129      }
130
131      /**
132       * Defines annotations to apply to specific classes and methods.
133       *
134       * <p>
135       * Allows you to dynamically apply Juneau annotations typically applied directly to classes and methods.
136       * Useful in cases where you want to use the functionality of the annotation on beans and bean properties but
137       * do not have access to the code to do so.
138       *
139       * <p>
140       * As a rule, any Juneau annotation with an <l>on()</l> method can be used with this setting.
141       *
142       * <p>
143       * The following example shows the equivalent methods for applying the {@link Bean @Bean} annotation:
144       * <p class='bjava'>
145       *    <jc>// Class with explicit annotation.</jc>
146       *    <ja>@Bean</ja>(properties=<js>"street,city,state"</js>)
147       *    <jk>public class</jk> A {...}
148       *
149       *    <jc>// Class with annotation applied via @BeanConfig</jc>
150       *    <jk>public class</jk> B {...}
151       *
152       *    <jc>// Java REST method with @BeanConfig annotation.</jc>
153       *    <ja>@RestGet</ja>(...)
154       *    <ja>@Bean</ja>(on=<js>"B"</js>, properties=<js>"street,city,state"</js>)
155       *    <jk>public void</jk> doFoo() {...}
156       * </p>
157       *
158       * <p>
159       * In general, the underlying framework uses this method when it finds dynamically applied annotations on
160       * config annotations.  However, concrete implementations of annotations are also provided that can be passed
161       * directly into builder classes like so:
162       * <p class='bjava'>
163       *    <jc>// Create a concrete @Bean annotation.</jc>
164       *    <ja>Bean</ja> <jv>annotation</jv> = BeanAnnotation.<jsm>create</jsm>(B.<jk>class</jk>).properties(<js>"street,city,state"</js>).build();
165       *
166       *    <jc>// Apply it to a serializer.</jc>
167       *    WriterSerializer <jv>serializer</jv> = JsonSerializer.<jsm>create</jsm>().annotations(<jv>annotation</jv>).build();
168       *
169       *    <jc>// Serialize a bean with the dynamically applied annotation.</jc>
170       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> B());
171       * </p>
172       *
173       * <p>
174       * The following is the list of annotations builders provided that can be constructed
175       * and passed into the builder class:
176       * <ul class='javatreec'>
177       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanAnnotation}
178       *    <li class='ja'>{@link org.apache.juneau.annotation.BeancAnnotation}
179       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanIgnoreAnnotation}
180       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanpAnnotation}
181       *    <li class='ja'>{@link org.apache.juneau.annotation.ExampleAnnotation}
182       *    <li class='ja'>{@link org.apache.juneau.annotation.NamePropertyAnnotation}
183       *    <li class='ja'>{@link org.apache.juneau.annotation.ParentPropertyAnnotation}
184       *    <li class='ja'>{@link org.apache.juneau.annotation.SwapAnnotation}
185       *    <li class='ja'>{@link org.apache.juneau.annotation.UriAnnotation}
186       *    <li class='ja'>{@link org.apache.juneau.csv.annotation.CsvAnnotation}
187       *    <li class='ja'>{@link org.apache.juneau.html.annotation.HtmlAnnotation}
188       *    <li class='ja'>{@link org.apache.juneau.json.annotation.JsonAnnotation}
189       *    <li class='ja'>{@link org.apache.juneau.annotation.SchemaAnnotation}
190       *    <li class='ja'>{@link org.apache.juneau.msgpack.annotation.MsgPackAnnotation}
191       *    <li class='ja'>{@link org.apache.juneau.oapi.annotation.OpenApiAnnotation}
192       *    <li class='ja'>{@link org.apache.juneau.plaintext.annotation.PlainTextAnnotation}
193       *    <li class='ja'>{@link org.apache.juneau.soap.annotation.SoapXmlAnnotation}
194       *    <li class='ja'>{@link org.apache.juneau.uon.annotation.UonAnnotation}
195       *    <li class='ja'>{@link org.apache.juneau.urlencoding.annotation.UrlEncodingAnnotation}
196       *    <li class='ja'>{@link org.apache.juneau.xml.annotation.XmlAnnotation}
197       * </ul>
198       *
199       * <p>
200       * The syntax for the <l>on()</l> pattern match parameter depends on whether it applies to a class, method, field, or constructor.
201       * The valid pattern matches are:
202       * <ul class='spaced-list'>
203       *  <li>Classes:
204       *       <ul>
205       *          <li>Fully qualified:
206       *             <ul>
207       *                <li><js>"com.foo.MyClass"</js>
208       *             </ul>
209       *          <li>Fully qualified inner class:
210       *             <ul>
211       *                <li><js>"com.foo.MyClass$Inner1$Inner2"</js>
212       *             </ul>
213       *          <li>Simple:
214       *             <ul>
215       *                <li><js>"MyClass"</js>
216       *             </ul>
217       *          <li>Simple inner:
218       *             <ul>
219       *                <li><js>"MyClass$Inner1$Inner2"</js>
220       *                <li><js>"Inner1$Inner2"</js>
221       *                <li><js>"Inner2"</js>
222       *             </ul>
223       *       </ul>
224       *    <li>Methods:
225       *       <ul>
226       *          <li>Fully qualified with args:
227       *             <ul>
228       *                <li><js>"com.foo.MyClass.myMethod(String,int)"</js>
229       *                <li><js>"com.foo.MyClass.myMethod(java.lang.String,int)"</js>
230       *                <li><js>"com.foo.MyClass.myMethod()"</js>
231       *             </ul>
232       *          <li>Fully qualified:
233       *             <ul>
234       *                <li><js>"com.foo.MyClass.myMethod"</js>
235       *             </ul>
236       *          <li>Simple with args:
237       *             <ul>
238       *                <li><js>"MyClass.myMethod(String,int)"</js>
239       *                <li><js>"MyClass.myMethod(java.lang.String,int)"</js>
240       *                <li><js>"MyClass.myMethod()"</js>
241       *             </ul>
242       *          <li>Simple:
243       *             <ul>
244       *                <li><js>"MyClass.myMethod"</js>
245       *             </ul>
246       *          <li>Simple inner class:
247       *             <ul>
248       *                <li><js>"MyClass$Inner1$Inner2.myMethod"</js>
249       *                <li><js>"Inner1$Inner2.myMethod"</js>
250       *                <li><js>"Inner2.myMethod"</js>
251       *             </ul>
252       *       </ul>
253       *    <li>Fields:
254       *       <ul>
255       *          <li>Fully qualified:
256       *             <ul>
257       *                <li><js>"com.foo.MyClass.myField"</js>
258       *             </ul>
259       *          <li>Simple:
260       *             <ul>
261       *                <li><js>"MyClass.myField"</js>
262       *             </ul>
263       *          <li>Simple inner class:
264       *             <ul>
265       *                <li><js>"MyClass$Inner1$Inner2.myField"</js>
266       *                <li><js>"Inner1$Inner2.myField"</js>
267       *                <li><js>"Inner2.myField"</js>
268       *             </ul>
269       *       </ul>
270       *    <li>Constructors:
271       *       <ul>
272       *          <li>Fully qualified with args:
273       *             <ul>
274       *                <li><js>"com.foo.MyClass(String,int)"</js>
275       *                <li><js>"com.foo.MyClass(java.lang.String,int)"</js>
276       *                <li><js>"com.foo.MyClass()"</js>
277       *             </ul>
278       *          <li>Simple with args:
279       *             <ul>
280       *                <li><js>"MyClass(String,int)"</js>
281       *                <li><js>"MyClass(java.lang.String,int)"</js>
282       *                <li><js>"MyClass()"</js>
283       *             </ul>
284       *          <li>Simple inner class:
285       *             <ul>
286       *                <li><js>"MyClass$Inner1$Inner2()"</js>
287       *                <li><js>"Inner1$Inner2()"</js>
288       *                <li><js>"Inner2()"</js>
289       *             </ul>
290       *       </ul>
291       *    <li>A comma-delimited list of anything on this list.
292       * </ul>
293       *
294       * <h5 class='section'>See Also:</h5><ul>
295       *    <li class='ja'>{@link BeanConfig}
296       * </ul>
297       *
298       * @param values
299       *    The annotations to register with the context.
300       *    <br>Cannot contain <jk>null</jk> values.
301       * @return This object.
302       */
303      public Builder annotations(Annotation...values) {
304         assertArgNoNulls("values", values);
305         annotations(l(values));
306         return this;
307      }
308
309      /**
310       * Same as {@link #annotations(Annotation...)} but uses a list as input.
311       *
312       * @param values
313       *    The annotations to register with the context.
314       *    <br>Cannot be <jk>null</jk> or contain <jk>null</jk> values.
315       * @return This object.
316       */
317      public Builder annotations(List<Annotation> values) {
318         annotations.addAll(assertArgNoNulls("values", values));
319         return this;
320      }
321
322      /**
323       * Applies a set of applied to this builder.
324       *
325       * <p>
326       * An {@link AnnotationWork} consists of a single pair of {@link AnnotationInfo} that represents an annotation instance,
327       * and {@link AnnotationApplier} which represents the code used to apply the values in that annotation to a specific builder.
328       *
329       * <h5 class='section'>Example:</h5>
330       * <p class='bjava'>
331       *    <jc>// A class annotated with a config annotation.</jc>
332       *    <ja>@BeanConfig</ja>(sortProperties=<js>"$S{sortProperties,false}"</js>)
333       *    <jk>public class</jk> MyClass {...}
334       *
335       *    <jc>// Find all annotations that themselves are annotated with @ContextPropertiesApply.</jc>
336       *    Stream&lt;AnnotationInfo&lt;?&gt;&gt; <jv>annotations</jv> = ClassInfo.<jsm>of</jsm>(MyClass.<jk>class</jk>).getAnnotations().stream().filter(<jsf>CONTEXT_APPLY_FILTER</jsf>);
337       *    VarResolverSession <jv>vrs</jv> = VarResolver.<jsf>DEFAULT</jsf>.createSession();
338       *    AnnotationWorkList <jv>work</jv> = AnnotationWorkList.of(<jv>vrs</jv>, <jv>annotations</jv>);
339       *
340       *    <jc>// Apply any settings found on the annotations.</jc>
341       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
342       *       .<jsm>create</jsm>()
343       *       .apply(<jv>work</jv>)
344       *       .build();
345       * </p>
346       *
347       * @param work The list of annotations and appliers to apply to this builder.
348       *    <br>Cannot be <jk>null</jk>.
349       * @return This object.
350       */
351      public Builder apply(AnnotationWorkList work) {
352         assertArgNotNull("work", work);
353         applied.addAll(work);
354         work.forEach(x -> builders.forEach(x::apply));
355         return this;
356      }
357
358      /**
359       * Same as {@link #applyAnnotations(Object...)} but explicitly specifies a class varargs to avoid compilation warnings.
360       *
361       * @param from The classes or methods on which the annotations are defined.
362       *    <br>Cannot contain <jk>null</jk> values.
363       * @return This object.
364       */
365      public Builder applyAnnotations(Class<?>...from) {
366         assertArgNoNulls("from", from);
367         return applyAnnotations((Object[])from);
368      }
369
370      /**
371       * Applies any of the various <ja>@XConfig</ja> annotations on the specified classes or methods to this context.
372       *
373       * <p>
374       * Any annotations found that themselves are annotated with {@link ContextApply} will be resolved and
375       * applied as properties to this builder.  These annotations include:
376       * <ul class='javatreec'>
377       *    <li class ='ja'>{@link BeanConfig}
378       *    <li class ='ja'>{@link CsvConfig}
379       *    <li class ='ja'>{@link HtmlConfig}
380       *    <li class ='ja'>{@link HtmlDocConfig}
381       *    <li class ='ja'>{@link JsonConfig}
382       *    <li class ='ja'>{@link JsonSchemaConfig}
383       *    <li class ='ja'>{@link MsgPackConfig}
384       *    <li class ='ja'>{@link OpenApiConfig}
385       *    <li class ='ja'>{@link ParserConfig}
386       *    <li class ='ja'>{@link PlainTextConfig}
387       *    <li class ='ja'>{@link SerializerConfig}
388       *    <li class ='ja'>{@link SoapXmlConfig}
389       *    <li class ='ja'>{@link UonConfig}
390       *    <li class ='ja'>{@link UrlEncodingConfig}
391       *    <li class ='ja'>{@link XmlConfig}
392       *    <li class ='ja'><c>RdfConfig</c>
393       * </ul>
394       *
395       * <p>
396       * Annotations on classes are appended in the following order:
397       * <ol>
398       *    <li>On the package of this class.
399       *    <li>On interfaces ordered parent-to-child.
400       *    <li>On parent classes ordered parent-to-child.
401       *    <li>On this class.
402       * </ol>
403       *
404       * <p>
405       * Annotations on methods are appended in the following order:
406       * <ol>
407       *    <li>On the package of the method class.
408       *    <li>On interfaces ordered parent-to-child.
409       *    <li>On parent classes ordered parent-to-child.
410       *    <li>On the method class.
411       *    <li>On this method and matching methods ordered parent-to-child.
412       * </ol>
413       *
414       * <p>
415       * The default var resolver {@link VarResolver#DEFAULT} is used to resolve any variables in annotation field values.
416       *
417       * <h5 class='section'>Example:</h5>
418       * <p class='bjava'>
419       *    <jc>// A class annotated with a config annotation.</jc>
420       *    <ja>@BeanConfig</ja>(sortProperties=<js>"$S{sortProperties,false}"</js>)
421       *    <jk>public class</jk> MyClass {...}
422       *
423       *    <jc>// Apply any settings found on the annotations.</jc>
424       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
425       *       .<jsm>create</jsm>()
426       *       .applyAnnotations(MyClass.<jk>class</jk>)
427       *       .build();
428       *
429       *    <jc>// A method annotated with a config annotation.</jc>
430       *    <jk>public class</jk> MyClass {
431       *       <ja>@BeanConfig</ja>(sortProperties=<js>"$S{sortProperties,false}"</js>)
432       *       <jk>public void</jk> myMethod() {...}
433       *    }
434       *
435       *    <jc>// Apply any settings found on the annotations.</jc>
436       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
437       *       .<jsm>create</jsm>()
438       *       .applyAnnotations(MyClass.<jk>class</jk>.getMethod(<js>"myMethod"</js>))
439       *       .build();
440       * </p>
441       *
442       * @param from The classes or methods on which the annotations are defined.
443       *    Can be any of the following types:
444       *    <ul>
445       *       <li>{@link Class}
446       *       <li>{@link ClassInfo}
447       *       <li>{@link Method}
448       *       <li>{@link MethodInfo}
449       *    <li>A collection/stream/array of anything on this list.
450       *    <br>Cannot contain <jk>null</jk> values.
451       * @return This object.
452       */
453      public Builder applyAnnotations(Object...from) {
454         assertArgNoNulls("from", from);
455         var work = AnnotationWorkList.create();
456         Arrays.stream(from).forEach(x -> traverse(work, x));
457         return apply(work);
458      }
459
460      /**
461       * Returns this builder cast to the specified subtype if it is an instance of that type.
462       *
463       * <p>
464       * This is a type-safe way to check if this builder is an instance of a specific builder subtype
465       * and cast it accordingly. Returns an empty {@link Optional} if this builder is not an instance
466       * of the specified subtype.
467       *
468       * <h5 class='section'>Example:</h5>
469       * <p class='bjava'>
470       *    Builder <jv>b</jv> = JsonSerializer.<jsm>create</jsm>();
471       *    Optional&lt;JsonSerializer.Builder&gt; <jv>jsonBuilder</jv> = <jv>b</jv>.asSubtype(JsonSerializer.Builder.<jk>class</jk>);
472       *    <jk>if</jk> (<jv>jsonBuilder</jv>.isPresent()) {
473       *       <jc>// Use JsonSerializer.Builder-specific methods</jc>
474       *       <jv>jsonBuilder</jv>.get().pretty();
475       *    }
476       * </p>
477       *
478       * @param <T> The builder subtype.
479       * @param subtype The builder subtype class to cast to.
480       *    <br>Cannot be <jk>null</jk>.
481       * @return An {@link Optional} containing this builder cast to the subtype, or empty if not an instance.
482       */
483      public <T extends Builder> Optional<T> asSubtype(Class<T> subtype) {
484         return opt(assertArgNotNull("subtype", subtype).isInstance(this) ? subtype.cast(this) : null);
485      }
486
487      /**
488       * Build the object.
489       *
490       * @return The built object.
491       */
492      public Context build() {
493         return innerBuild();
494      }
495
496      /**
497       * Convenience method for calling {@link #build()} while avoiding a cast.
498       *
499       * @param <T> The type to cast the built object to.
500       * @param c The type to cast the built object to.
501       *    <br>Cannot be <jk>null</jk>.
502       * @return The built context bean.
503       */
504      @SuppressWarnings("unchecked")
505      public final <T extends Context> T build(Class<T> c) {
506         if (type == null || ! assertArgNotNull("c", c).isAssignableFrom(type))
507            type = c;
508         return (T)innerBuild();
509      }
510
511      /**
512       * Specifies a cache to use for hashkey-based caching.
513       *
514       * <p>
515       * When a cache is specified, contexts with the same hash key will be reused from the cache
516       * instead of creating new instances.  This improves performance when building multiple contexts
517       * with identical configurations.
518       *
519       * <p>
520       * If <jk>null</jk> is specified, caching is disabled and each call to {@link #build()} will
521       * create a new context instance.
522       *
523       * @param value The cache.
524       *    <br>Can be <jk>null</jk> (disables caching, each build creates a new instance).
525       * @return This object.
526       */
527      public Builder cache(Cache<HashKey,? extends Context> value) {
528         cache = value;
529         return this;
530      }
531
532      /**
533       * Returns <jk>true</jk> if any of the annotations/appliers can be applied to this builder.
534       *
535       * @param work The work to check.
536       *    <br>Cannot be <jk>null</jk>.
537       * @return <jk>true</jk> if any of the annotations/appliers can be applied to this builder.
538       */
539      public boolean canApply(AnnotationWorkList work) {
540         return assertArgNotNull("work", work).stream().anyMatch(x -> builders.stream().anyMatch(b -> x.canApply(b)));
541      }
542
543      /**
544       * Copy creator.
545       *
546       * @return A new mutable copy of this builder.
547       */
548      public abstract Builder copy();
549
550      /**
551       * <i><l>Context</l> configuration property:&emsp;</i>  Debug mode.
552       *
553       * <p>
554       * Enables the following additional information during serialization:
555       * <ul class='spaced-list'>
556       *    <li>
557       *       When bean getters throws exceptions, the exception includes the object stack information
558       *       in order to determine how that method was invoked.
559       *    <li>
560       *       Enables {@link BeanTraverseContext.Builder#detectRecursions()}.
561       * </ul>
562       *
563       * <p>
564       * Enables the following additional information during parsing:
565       * <ul class='spaced-list'>
566       *    <li>
567       *       When bean setters throws exceptions, the exception includes the object stack information
568       *       in order to determine how that method was invoked.
569       * </ul>
570       *
571       * <h5 class='section'>Example:</h5>
572       * <p class='bjava'>
573       *    <jc>// Create a serializer with debug enabled.</jc>
574       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
575       *       .<jsm>create</jsm>()
576       *       .debug()
577       *       .build();
578       *
579       *    <jc>// Create a POJO model with a recursive loop.</jc>
580       *    <jk>public class</jk> MyBean {
581       *       <jk>public</jk> Object <jf>f</jf>;
582       *    }
583       *    MyBean <jv>bean</jv> = <jk>new</jk> MyBean();
584       *    <jv>bean</jv>.<jf>f</jf> = <jv>bean</jv>;
585       *
586       *    <jc>// Throws a SerializeException and not a StackOverflowError</jc>
587       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>bean</jv>);
588       * </p>
589       *
590       * <h5 class='section'>See Also:</h5><ul>
591       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#debug()}
592       *    <li class='jm'>{@link org.apache.juneau.ContextSession.Builder#debug(Boolean)}
593       * </ul>
594       *
595       * @return This object.
596       */
597      public Builder debug() {
598         return debug(true);
599      }
600
601      /**
602       * Same as {@link #debug()} but allows you to explicitly specify the value.
603       *
604       * @param value The value for this setting.
605       * @return This object.
606       */
607      public Builder debug(boolean value) {
608         debug = value;
609         return this;
610      }
611
612      /**
613       * Returns all the annotations that have been applied to this builder.
614       *
615       * @return All the annotations that have been applied to this builder.
616       */
617      public AnnotationWorkList getApplied() { return applied; }
618
619      /**
620       * Returns the context class that this builder should create.
621       *
622       * @return The context class if it was specified.
623       */
624      public Optional<Class<?>> getType() { return opt(type); }
625
626      /**
627       * Returns the hashkey of this builder.
628       *
629       * <p>
630       * Used to return previously instantiated context beans that have matching hashkeys.
631       * The {@link HashKey} object is suitable for use as a hashmap key of a map of context beans.
632       * A context bean is considered equivalent if the {@link HashKey#equals(Object)} method is the same.
633       *
634       * @return The hashkey of this builder.
635       */
636      public HashKey hashKey() {
637         return HashKey.of(debug, type, annotations);
638      }
639
640      /**
641       * Specifies a pre-instantiated bean for the {@link #build()} method to return.
642       *
643       * <p>
644       * If a non-null value is provided and it's an instance of the context type, {@link #build()} will return
645       * that instance instead of creating a new one.  If <jk>null</jk>, the normal build process continues.
646       *
647       * @param value The value for this setting.
648       *    <br>Can be <jk>null</jk> (normal build process will continue).
649       * @return This object.
650       */
651      public Builder impl(Context value) {
652         impl = value;
653         return this;
654      }
655
656      /**
657       * Returns <jk>true</jk> if debug is enabled.
658       *
659       * @return <jk>true</jk> if debug is enabled.
660       */
661      public boolean isDebug() { return debug; }
662
663      /**
664       * Associates a context class with this builder.
665       *
666       * <p>
667       * This is the type of object that this builder creates when the {@link #build()} method is called.
668       *
669       * <p>
670       * By default, it's the outer class of where the builder class is defined.
671       *
672       * <p>
673       * If <jk>null</jk> is set, {@link #build()} will throw an exception.  The default constructor automatically
674       * sets this to the outer class, so <jk>null</jk> should only be set explicitly if you want to override the default.
675       *
676       * @param value The context class that this builder should create.
677       *    <br>Can be <jk>null</jk> (will cause {@link #build()} to throw an exception).
678       * @return This object.
679       */
680      public Builder type(Class<? extends Context> value) {
681         type = value;
682         return this;
683      }
684
685      /**
686       * Registers the specified secondary builders with this context builder.
687       *
688       * <p>
689       * When {@link #apply(AnnotationWorkList)} is called, it gets called on all registered builders.
690       *
691       * @param values The builders to add to the list of builders.
692       *    <br>Cannot contain <jk>null</jk> values.
693       */
694      protected void registerBuilders(Object...values) {
695         assertArgNoNulls("values", values);
696         for (var b : values) {
697            if (b == this)
698               builders.add(b);
699            else if (b instanceof Builder b2)
700               builders.addAll(b2.builders);
701            else
702               builders.add(b);
703         }
704      }
705
706      private ConstructorInfo getContextConstructor() {
707         return CONTEXT_CONSTRUCTORS.get(type, getClass());
708      }
709
710      private Context innerBuild() {
711         if (type == null)
712            throw rex("Type not specified for context builder {0}", cn(getClass()));
713         if (nn(impl) && type.isInstance(impl))
714            return type.cast(impl);
715         if (nn(cache))
716            return cache.get(hashKey(), () -> getContextConstructor().newInstance(this));
717         return getContextConstructor().newInstance(this);
718      }
719   }
720
721   /*
722    * Cache of static <c>create</c> methods that return builder instances for context classes.
723    *
724    * <p>
725    * This cache stores {@link MethodInfo} objects for public static methods named <c>create</c> that return
726    * builder objects. The methods are discovered by:
727    * <ol>
728    *    <li>Finding public constructors that take a single parameter (the builder type)
729    *    <li>Looking for a matching static <c>create</c> method that returns the builder type
730    *    <li>Caching the result for future lookups
731    * </ol>
732    *
733    * <p>
734    * Used by {@link #createBuilder(Class)} to efficiently locate and invoke builder creation methods.
735    *
736    * @see #createBuilder(Class)
737    */
738   private static final Cache<Class<?>,MethodInfo> BUILDER_CREATE_METHODS = Cache.<Class<?>,MethodInfo>create()
739      .supplier(type -> {
740         var c = info(type);
741         // @formatter:off
742         return c.getPublicConstructors().stream()
743            .filter(ci -> ci.hasNumParameters(1) && ! ci.getParameter(0).getParameterType().is(type))
744            .map(ci -> c.getPublicMethod(
745               x -> x.isStatic()
746               && x.isNotDeprecated()
747               && x.hasName("create")
748               && x.hasReturnType(ci.getParameter(0).getParameterType())
749               ).orElse(null))
750            .filter(Objects::nonNull)
751            .findFirst()
752            .orElseThrow(() -> rex("Could not find builder create method on class {0}", cn(type)));
753         // @formatter:on
754      })
755      .build();
756
757
758   /*
759    * Cache of public constructors on context classes that accept builder instances.
760    *
761    * <p>
762    * This cache stores {@link ConstructorInfo} objects for public constructors on context classes that take
763    * a single parameter of the builder type. The constructor is discovered by:
764    * <ol>
765    *    <li>Finding public constructors on the context type that take exactly one parameter
766    *    <li>Matching constructors where the parameter type is a parent of (or equal to) the builder type
767    *    <li>Caching the result for future lookups
768    * </ol>
769    *
770    * <p>
771    * Used by {@link Builder#getContextConstructor()} to efficiently locate and invoke context constructors
772    * when building context instances from builders.
773    *
774    * @see Builder#getContextConstructor()
775    * @see Builder#innerBuild()
776    */
777   private static final Cache2<Class<? extends Context>,Class<? extends Builder>,ConstructorInfo> CONTEXT_CONSTRUCTORS = Cache2.<Class<? extends Context>,Class<? extends Builder>,ConstructorInfo>create()
778      .supplier((cacheType, builderType) -> {
779         var ct = info(cacheType);
780         var bt = info(builderType);
781         return ct
782            .getPublicConstructor(x -> x.hasNumParameters(1) && x.getParameter(0).getParameterType().isParentOf(builderType))
783            .orElseThrow(() -> rex("Public constructor not found: {0}({1})", ct.getName(), bt.getName()));
784      })
785      .build();
786
787   /*
788    * Default annotation provider instance for finding annotations on classes, methods, fields, and constructors.
789    *
790    * <p>
791    * This is a static reference to {@link AnnotationProvider#INSTANCE}, used by the {@link Builder#traverse(AnnotationWorkList, Object)}
792    * method to discover annotations that can be applied to context builders.
793    *
794    * <p>
795    * The annotation provider supports:
796    * <ul>
797    *    <li>Finding annotations on classes, methods, fields, and constructors
798    *    <li>Traversing class hierarchies (parent-to-child or child-to-parent order)
799    *    <li>Supporting runtime annotations (annotations added programmatically)
800    *    <li>Caching results for performance
801    * </ul>
802    *
803    * @see AnnotationProvider
804    * @see Builder#traverse(AnnotationWorkList, Object)
805    */
806   private static final AnnotationProvider AP = AnnotationProvider.INSTANCE;
807
808   /**
809    * Predicate for annotations that themselves are annotated with {@link ContextApply}.
810    */
811   public static final Predicate<AnnotationInfo<?>> CONTEXT_APPLY_FILTER = x -> x.hasAnnotation(ContextApply.class);
812
813   /**
814    * Instantiates a builder of the specified context class.
815    *
816    * <p>
817    * Looks for a public static method called <c>create</c> that returns an object that can be passed into a public
818    * or protected constructor of the class.
819    *
820    * @param type The builder to create.
821    * @return A new builder.
822    */
823   public static Builder createBuilder(Class<? extends Context> type) {
824      assertArgNotNull("type", type);
825      try {
826         return ((Builder)BUILDER_CREATE_METHODS.get(type).invoke(null)).type(type);
827      } catch (ExecutableException e) {
828         throw toRex(e);
829      }
830   }
831
832   private static AnnotationWorkList traverse(AnnotationWorkList work, Object x) {
833      var ap = AP;
834      CollectionUtils.traverse(x, y -> {
835         if (x instanceof Class<?> x2)
836            work.add(rstream(ap.find(info(x2))).filter(CONTEXT_APPLY_FILTER));
837         else if (x instanceof ClassInfo x2)
838            work.add(rstream(ap.find(x2)).filter(CONTEXT_APPLY_FILTER));
839         else if (x instanceof Method x2)
840            work.add(rstream(ap.find(info(x2))).filter(CONTEXT_APPLY_FILTER));
841         else if (x instanceof MethodInfo x2)
842            work.add(rstream(ap.find(x2)).filter(CONTEXT_APPLY_FILTER));
843         else
844            illegalArg("Invalid type passed to applyAnnotations:  {0}", cn(x));
845      });
846      return work;
847   }
848
849   private final AnnotationProvider annotationProvider;
850   private final boolean debug;
851   private final List<Annotation> annotations;
852
853   /**
854    * Constructor for this class.
855    *
856    * @param builder The builder for this class.
857    *    <br>Cannot be <jk>null</jk>.
858    */
859   protected Context(Builder builder) {
860      assertArgNotNull("builder", builder);
861      init(builder);
862      annotations = copyOf(builder.annotations);
863      annotationProvider = AnnotationProvider.create().addRuntimeAnnotations(annotations).build();
864      debug = builder.debug;
865   }
866
867   /**
868    * Copy constructor.
869    *
870    * @param copyFrom The context to copy from.
871    */
872   protected Context(Context copyFrom) {
873      annotationProvider = copyFrom.annotationProvider;
874      annotations = copyOf(copyFrom.annotations);
875      debug = copyFrom.debug;
876   }
877
878   /**
879    * Creates a builder from this context object.
880    *
881    * <p>
882    * Builders are used to define new contexts (e.g. serializers, parsers) based on existing configurations.
883    *
884    * @return A new Builder object.
885    */
886   public Builder copy() {
887      throw unsupportedOp();
888   }
889
890   /**
891    * Create a session builder based on the properties defined on this context.
892    *
893    * <p>
894    * Use this method for creating sessions where you want to override basic settings.
895    * Otherwise, use {@link #getSession()} directly.
896    *
897    * @return A new session builder.
898    */
899   public ContextSession.Builder createSession() {
900      throw unsupportedOp();
901   }
902
903   /**
904    * Returns the annotation provider for this context.
905    *
906    * @return The annotation provider for this context.
907    */
908   public AnnotationProvider getAnnotationProvider() { return annotationProvider; }
909
910   /**
911    * Returns a session to use for this context.
912    *
913    * <p>
914    * Note that subclasses may opt to return a reusable non-modifiable session.
915    *
916    * @return A new session object.
917    */
918   public ContextSession getSession() { return createSession().build(); }
919
920   /**
921    * Debug mode.
922    *
923    * @see Context.Builder#debug()
924    * @return
925    *    <jk>true</jk> if debug mode is enabled.
926    */
927   public boolean isDebug() { return debug; }
928
929   @Override /* Overridden from Object */
930   public String toString() {
931      return r(properties());
932   }
933
934   /**
935    * Perform optional initialization on builder before it is used.
936    *
937    * <p>
938    * Default behavior is a no-op.
939    *
940    * @param builder The builder to initialize.
941    */
942   protected void init(Builder builder) {}
943
944   /**
945    * Returns the properties on this bean as a map for debugging.
946    *
947    * @return The properties on this bean as a map for debugging.
948    */
949   protected FluentMap<String,Object> properties() {
950      return filteredBeanPropertyMap()
951         .a("annotations", annotations)
952         .a("debug", debug);
953   }
954}