View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau;
18  
19  import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
20  import static org.apache.juneau.commons.utils.AssertionUtils.*;
21  import static org.apache.juneau.commons.utils.CollectionUtils.*;
22  import static org.apache.juneau.commons.utils.ThrowableUtils.*;
23  import static org.apache.juneau.commons.utils.Utils.*;
24  
25  import java.lang.annotation.*;
26  import java.lang.reflect.*;
27  import java.util.*;
28  import java.util.function.*;
29  import org.apache.juneau.annotation.*;
30  import org.apache.juneau.commons.collections.*;
31  import org.apache.juneau.commons.reflect.*;
32  import org.apache.juneau.commons.utils.*;
33  import org.apache.juneau.csv.annotation.*;
34  import org.apache.juneau.html.annotation.*;
35  import org.apache.juneau.json.annotation.*;
36  import org.apache.juneau.jsonschema.annotation.*;
37  import org.apache.juneau.msgpack.annotation.*;
38  import org.apache.juneau.oapi.annotation.*;
39  import org.apache.juneau.parser.annotation.*;
40  import org.apache.juneau.plaintext.annotation.*;
41  import org.apache.juneau.serializer.annotation.*;
42  import org.apache.juneau.soap.annotation.*;
43  import org.apache.juneau.svl.*;
44  import org.apache.juneau.uon.annotation.*;
45  import org.apache.juneau.urlencoding.annotation.*;
46  import org.apache.juneau.xml.annotation.*;
47  
48  /**
49   * Base class for all Context beans.
50   *
51   * <p>
52   * Context beans follow the convention of havinTg the following parts:
53   * <ul>
54   * 	<li>A {@link Builder} class for configuring the context bean.
55   * 	<ul>
56   * 		<li>This bean is non-thread-safe and meant for one-time use.
57   * 	</ul>
58   * 	<li>A {@link Context#Context(Builder)} constructor that takes in a builder object.
59   * 	<ul>
60   * 		<li>This bean is thread-safe and cacheable/reusable.
61   * 	</ul>
62   * 	<li>A {@link ContextSession} class for doing work.
63   * 	<ul>
64   * 		<li>This bean is non-thread-safe and meant for one-time use.
65   * 	</ul>
66   *
67   * <h5 class='section'>Notes:</h5><ul>
68   * 	<li class='note'>This class is thread safe and reusable.
69   * </ul>
70   *
71   */
72  public abstract class Context {
73  
74  	/**
75  	 * Builder class.
76  	 */
77  	public abstract static class Builder {
78  
79  		private boolean debug;
80  		private final AnnotationWorkList applied = AnnotationWorkList.create();
81  		private Cache<HashKey,? extends Context> cache;
82  		private Class<? extends Context> type;
83  		private Context impl;
84  		private List<Annotation> annotations;
85  		private final List<Object> builders = list();
86  
87  		/**
88  		 * Constructor.
89  		 * Default settings.
90  		 */
91  		@SuppressWarnings("unchecked")
92  		protected Builder() {
93  			debug = env("Context.debug", false);
94  			annotations = list();
95  			registerBuilders(this);
96  
97  			// By default, the type being created should be the class declaring the builder.
98  			var dc = getClass().getDeclaringClass();
99  			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 }