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