This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 2caa4ff  Context API refactoring.
2caa4ff is described below

commit 2caa4ff20f906167a4c1adb4aba349465dff3f68
Author: JamesBognar <james.bog...@salesforce.com>
AuthorDate: Thu Sep 30 10:27:35 2021 -0400

    Context API refactoring.
---
 .../juneau/jena/annotation/RdfAnnotation.java      |  5 +--
 .../main/java/org/apache/juneau/BeanContext.java   |  2 +-
 .../java/org/apache/juneau/BeanContextBuilder.java | 31 +++++++++-----
 .../java/org/apache/juneau/BeanContextable.java    |  4 +-
 .../org/apache/juneau/BeanContextableBuilder.java  | 19 ++++++++
 .../src/main/java/org/apache/juneau/Context.java   | 45 ++++++-------------
 .../java/org/apache/juneau/ContextBuilder.java     | 50 ++++++++++++++++++----
 .../juneau/html/HtmlSchemaDocSerializer.java       |  2 +-
 .../juneau/html/HtmlSchemaSerializerBuilder.java   |  6 +++
 .../org/apache/juneau/html/HtmlSerializer.java     |  2 +-
 .../apache/juneau/html/HtmlSerializerBuilder.java  |  6 +++
 .../org/apache/juneau/json/JsonSerializer.java     |  2 +-
 .../apache/juneau/json/JsonSerializerBuilder.java  |  6 +++
 .../juneau/jsonschema/JsonSchemaGenerator.java     |  2 +-
 .../jsonschema/JsonSchemaGeneratorBuilder.java     |  6 +++
 .../main/java/org/apache/juneau/utils/HashKey.java | 24 +++++++++++
 .../org/apache/juneau/rest/client/RestClient.java  |  4 +-
 .../org/apache/juneau/ContextPropertiesTest.java   | 16 +++----
 .../juneau/a/rttests/RoundTripBeanMapsTest.java    |  7 ++-
 .../org/apache/juneau/a/rttests/RoundTripTest.java | 25 ++++++++---
 .../apache/juneau/transforms/ReaderFilterTest.java |  2 +-
 21 files changed, 189 insertions(+), 77 deletions(-)

diff --git 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/annotation/RdfAnnotation.java
 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/annotation/RdfAnnotation.java
index d2205bb..a023f00 100644
--- 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/annotation/RdfAnnotation.java
+++ 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/annotation/RdfAnnotation.java
@@ -14,7 +14,6 @@ package org.apache.juneau.jena.annotation;
 
 import static java.lang.annotation.ElementType.*;
 import static java.lang.annotation.RetentionPolicy.*;
-import static org.apache.juneau.BeanContext.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
@@ -263,7 +262,7 @@ public class RdfAnnotation {
                        if (isEmpty(a.on()) && isEmpty(a.onClass()))
                                return;
 
-                       b.prependTo(CONTEXT_annotations, copy(a, vr()));
+                       b.annotations(copy(a, vr()));
                }
        }
 
@@ -289,7 +288,7 @@ public class RdfAnnotation {
                        if (isEmpty(a.on()) && isEmpty(a.onClass()))
                                return;
 
-                       b.prependTo(CONTEXT_annotations, copy(a, vr()));
+                       b.annotations(copy(a, vr()));
                }
        }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
index 0a9413c..4d13612 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
@@ -1270,7 +1270,7 @@ public class BeanContext extends Context {
                if (beanToStringSerializer == null) {
                        if (JsonSerializer.DEFAULT == null)
                                return null;
-                       this.beanToStringSerializer = 
JsonSerializer.create().apply(getContextProperties()).sq().simpleMode().build();
+                       this.beanToStringSerializer = 
JsonSerializer.create().beanContext(this).sq().simpleMode().build();
                }
                return beanToStringSerializer;
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
index c94c9519..bda8e75 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
@@ -205,10 +205,26 @@ public class BeanContextBuilder extends ContextBuilder {
 
        @Override /* ContextBuilder */
        public BeanContext build() {
-               ContextProperties cp = getContextProperties();
-               cp = cp.subset(new String[]{"Context","BeanContext"});
-               HashKey key = HashKey.of(
-                       cp,
+
+               BeanContext impl = impl(BeanContext.class);
+               if (impl != null)
+                       return impl;
+
+               HashKey key = hashKey();
+               BeanContext bc = CACHE.get(key);
+               if (bc == null) {
+                       bc = new BeanContext(this);
+                       CACHE.putIfAbsent(key, bc);
+               } else {
+                       CACHE_HITS.incrementAndGet();
+               }
+               return bc;
+       }
+
+       @Override
+       public HashKey hashKey() {
+               return HashKey.of(
+                       super.hashKey(),
                        beanClassVisibility,
                        beanConstructorVisibility,
                        beanMethodVisibility,
@@ -241,13 +257,6 @@ public class BeanContextBuilder extends ContextBuilder {
                        locale,
                        propertyNamer
                );
-               CACHE_HITS.incrementAndGet();
-               BeanContext bc = CACHE.get(key);
-               if (bc == null) {
-                       bc = new BeanContext(this);
-                       CACHE.putIfAbsent(key, bc);
-               }
-               return bc;
        }
 
        private int integer(boolean...values) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextable.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextable.java
index da67df6..55a1834 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextable.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextable.java
@@ -12,6 +12,8 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau;
 
+import static java.util.Optional.*;
+
 import org.apache.juneau.collections.*;
 
 /**
@@ -28,7 +30,7 @@ public abstract class BeanContextable extends Context {
         */
        protected BeanContextable(BeanContextableBuilder b) {
                super(b);
-               beanContext = b.bcBuilder.build();
+               beanContext = ofNullable(b.bc).orElse(b.bcBuilder.build());
        }
 
        @Override
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextableBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextableBuilder.java
index 7ce6dac..63ebde5 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextableBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextableBuilder.java
@@ -52,6 +52,7 @@ import org.apache.juneau.transform.*;
 public abstract class BeanContextableBuilder extends ContextBuilder {
 
        BeanContextBuilder bcBuilder;
+       BeanContext bc;
 
        /**
         * Constructor.
@@ -83,6 +84,7 @@ public abstract class BeanContextableBuilder extends 
ContextBuilder {
        protected BeanContextableBuilder(BeanContextableBuilder copyFrom) {
                super(copyFrom);
                this.bcBuilder = copyFrom.bcBuilder.copy();
+               this.bc = copyFrom.bc;
                registerBuilders(bcBuilder);
        }
 
@@ -136,6 +138,23 @@ public abstract class BeanContextableBuilder extends 
ContextBuilder {
        }
 
        /**
+        * Specifies an already-instantiated bean context to use.
+        * 
+        * <p>
+        * Provides an optimization for cases where serializers and parsers can 
use an existing
+        * bean context without having to go through 
<c><jv>beanContext</jv>.copy().build()</c>.
+        * An example is {@link BeanContext#getBeanToStringSerializer()}.
+        *
+        * @param value The bean context to use.
+        * @return This object.
+        */
+       @FluentSetter
+       public BeanContextableBuilder beanContext(BeanContext value) {
+               this.bc = value;
+               return this;
+       }
+
+       /**
         * Minimum bean class visibility.
         *
         * <p>
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
index be45593..e23cef0 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
@@ -14,6 +14,7 @@ package org.apache.juneau;
 
 import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.CollectionUtils.*;
+import static java.util.Optional.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
@@ -80,34 +81,13 @@ public abstract class Context implements MetaProvider {
                }
        }
 
-       static final String PREFIX = "Context";
-
-       /**
-        * Configuration property:  Annotations.
-        *
-        * <p>
-        * Defines annotations to apply to specific classes and methods.
-        *
-        * <h5 class='section'>Property:</h5>
-        * <ul class='spaced-list'>
-        *      <li><b>ID:</b>  {@link 
org.apache.juneau.Context#CONTEXT_annotations CONTEXT_annotations}
-        *      <li><b>Name:</b>  <js>"BeanContext.annotations.lo"</js>
-        *      <li><b>Description:</b>
-        *      <li><b>Data type:</b>  <c>List&lt;{@link 
java.lang.annotation.Annotation}&gt;</c>
-        *      <li><b>Default:</b>  Empty list.
-        *      <li><b>Methods:</b>
-        *              <ul>
-        *                      <li class='jm'>{@link 
org.apache.juneau.ContextBuilder#annotations(Annotation...)}
-        *              </ul>
-        * </ul>
-        */
-       public static final String CONTEXT_annotations = PREFIX + 
".annotations.lo";
-
        final ContextProperties properties;
+       final List<Annotation> annotations;
        private final int identityCode;
-       private final ReflectionMap<Annotation> annotations;
        final boolean debug;
 
+       private final ReflectionMap<Annotation> annotationMap;
+
        /**
         * Copy constructor.
         *
@@ -115,6 +95,7 @@ public abstract class Context implements MetaProvider {
         */
        protected Context(Context copyFrom) {
                identityCode = copyFrom.identityCode;
+               annotationMap = copyFrom.annotationMap;
                annotations = copyFrom.annotations;
                debug = copyFrom.debug;
                properties = copyFrom.properties;
@@ -129,9 +110,11 @@ public abstract class Context implements MetaProvider {
                debug = builder.debug;
                identityCode = System.identityHashCode(this);
                properties = builder.getContextProperties();
+               annotations = 
ofNullable(builder.annotations).orElse(emptyList());
 
                ReflectionMap.Builder<Annotation> rmb = 
ReflectionMap.create(Annotation.class);
-               for (Annotation a : 
builder.getContextProperties().getList(CONTEXT_annotations, 
Annotation.class).orElse(emptyList())) {
+
+               for (Annotation a : annotations) {
                        try {
                                ClassInfo ci = ClassInfo.of(a.getClass());
 
@@ -155,7 +138,7 @@ public abstract class Context implements MetaProvider {
                                throw new ConfigException(e, "Invalid 
annotation @{0} used in BEAN_annotations property.", className(a));
                        }
                }
-               this.annotations = rmb.build();
+               this.annotationMap = rmb.build();
        }
 
        /**
@@ -289,7 +272,7 @@ public abstract class Context implements MetaProvider {
                if (aa == null) {
                        A[] x = c.getAnnotationsByType(a);
                        AList<Annotation> l = new AList<>(Arrays.asList(x));
-                       annotations.appendAll(c, a, l);
+                       annotationMap.appendAll(c, a, l);
                        aa = l.unmodifiable();
                        classAnnotationCache.put(c, a, aa);
                }
@@ -313,7 +296,7 @@ public abstract class Context implements MetaProvider {
                if (aa == null) {
                        A[] x = c.getDeclaredAnnotationsByType(a);
                        AList<Annotation> l = new AList<>(Arrays.asList(x));
-                       annotations.appendAll(c, a, l);
+                       annotationMap.appendAll(c, a, l);
                        aa = l.unmodifiable();
                        declaredClassAnnotationCache.put(c, a, aa);
                }
@@ -337,7 +320,7 @@ public abstract class Context implements MetaProvider {
                if (aa == null) {
                        A[] x = m.getAnnotationsByType(a);
                        AList<Annotation> l = new AList<>(Arrays.asList(x));
-                       annotations.appendAll(m, a, l);
+                       annotationMap.appendAll(m, a, l);
                        aa = l.unmodifiable();
                        methodAnnotationCache.put(m, a, aa);
                }
@@ -397,7 +380,7 @@ public abstract class Context implements MetaProvider {
                if (aa == null) {
                        A[] x = f.getAnnotationsByType(a);
                        AList<Annotation> l = new AList<>(Arrays.asList(x));
-                       annotations.appendAll(f, a, l);
+                       annotationMap.appendAll(f, a, l);
                        aa = l.unmodifiable();
                        fieldAnnotationCache.put(f, a, aa);
                }
@@ -433,7 +416,7 @@ public abstract class Context implements MetaProvider {
                if (aa == null) {
                        A[] x = c.getAnnotationsByType(a);
                        AList<Annotation> l = new AList<>(Arrays.asList(x));
-                       annotations.appendAll(c, a, l);
+                       annotationMap.appendAll(c, a, l);
                        aa = l.unmodifiable();
                        constructorAnnotationCache.put(c, a, l);
                }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextBuilder.java
index 7d7ab27..5666740 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextBuilder.java
@@ -12,7 +12,6 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau;
 
-import static org.apache.juneau.Context.*;
 import static org.apache.juneau.internal.ExceptionUtils.*;
 import static org.apache.juneau.reflect.ReflectionFilters.*;
 import static org.apache.juneau.Visibility.*;
@@ -44,6 +43,7 @@ import org.apache.juneau.soap.annotation.*;
 import org.apache.juneau.svl.*;
 import org.apache.juneau.uon.annotation.*;
 import org.apache.juneau.urlencoding.annotation.*;
+import org.apache.juneau.utils.*;
 import org.apache.juneau.xml.annotation.*;
 
 /**
@@ -59,6 +59,7 @@ public abstract class ContextBuilder {
        boolean debug;
        Class<?> type;
        Context impl;
+       List<Annotation> annotations;
 
        private final List<Object> builders = new ArrayList<>();
        private final AnnotationWorkList applied = new AnnotationWorkList();
@@ -70,6 +71,7 @@ public abstract class ContextBuilder {
        protected ContextBuilder() {
                cpb = ContextProperties.create();
                debug = env("Context.debug", false);
+               annotations = null;
                registerBuilders(this, cpb);
        }
 
@@ -79,9 +81,10 @@ public abstract class ContextBuilder {
         * @param copyFrom The bean to copy from.
         */
        protected ContextBuilder(Context copyFrom) {
-               this.cpb = copyFrom.properties.copy();
-               this.debug = copyFrom.debug;
-               this.type = copyFrom.getClass();
+               cpb = copyFrom.properties.copy();
+               debug = copyFrom.debug;
+               type = copyFrom.getClass();
+               annotations = copyFrom.annotations.isEmpty() ? null : new 
ArrayList<>(copyFrom.annotations);
                registerBuilders(this, cpb);
        }
 
@@ -91,9 +94,10 @@ public abstract class ContextBuilder {
         * @param copyFrom The builder to copy from.
         */
        protected ContextBuilder(ContextBuilder copyFrom) {
-               this.cpb =  new ContextPropertiesBuilder(copyFrom.cpb);
-               this.debug = copyFrom.debug;
-               this.type = copyFrom.type;
+               cpb =  new ContextPropertiesBuilder(copyFrom.cpb);
+               debug = copyFrom.debug;
+               type = copyFrom.type;
+               annotations = copyFrom.annotations == null ? null : new 
ArrayList<>(copyFrom.annotations);
                registerBuilders(this, cpb);
        }
 
@@ -105,6 +109,32 @@ public abstract class ContextBuilder {
        public abstract ContextBuilder copy();
 
        /**
+        * Returns the hashkey of this builder.
+        *
+        * <p>
+        * Used to return previously instantiated context beans that have 
matching hashkeys.
+        * The {@link HashKey} object is suitable for use as a hashmap key of a 
map of context beans.
+        * A context bean is considered equivalent if the {@link 
HashKey#equals(Object)} method is the same.
+        *
+        * @return The hashkey of this builder.
+        */
+       public HashKey hashKey() {
+               return HashKey.of(debug, type, annotations);
+       }
+
+       /**
+        * Returns the {@link #impl(Context)} bean if it's the specified type.
+        *
+        * @param c The expected bean type.
+        * @return The impl bean, or <jk>null</jk> if an impl bean wasn't 
specified.
+        */
+       protected <T extends Context> T impl(Class<T> c) {
+               if (impl != null && c.isInstance(impl))
+                       return c.cast(impl);
+               return null;
+       }
+
+       /**
         * Build the object.
         *
         * @return
@@ -611,7 +641,6 @@ public abstract class ContextBuilder {
         *
         * <ul class='seealso'>
         *      <li class='ja'>{@link BeanConfig}
-        *      <li class='jf'>{@link BeanContext#CONTEXT_annotations}
         * </ul>
         *
         * @param values
@@ -620,7 +649,10 @@ public abstract class ContextBuilder {
         */
        @FluentSetter
        public ContextBuilder annotations(Annotation...values) {
-               return prependTo(CONTEXT_annotations, values);
+               if (annotations == null)
+                       annotations = new ArrayList<>();
+               Collections.addAll(annotations, values);
+               return this;
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
index 8507167..1fc905b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
@@ -53,7 +53,7 @@ public final class HtmlSchemaDocSerializer extends 
HtmlDocSerializer {
        protected HtmlSchemaDocSerializer(HtmlDocSerializerBuilder builder) {
                super(builder.detectRecursions().ignoreRecursions());
 
-               generator = 
JsonSchemaGenerator.create().apply(getContextProperties()).build();
+               generator = 
JsonSchemaGenerator.create().beanContext(getBeanContext()).build();
        }
 
        @Override /* Serializer */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializerBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializerBuilder.java
index ad190f2..1d4f58f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializerBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializerBuilder.java
@@ -238,6 +238,12 @@ public class HtmlSchemaSerializerBuilder extends 
HtmlSerializerBuilder {
        // <FluentSetters>
 
        @Override /* GENERATED - ContextBuilder */
+       public HtmlSchemaSerializerBuilder beanContext(BeanContext value) {
+               super.beanContext(value);
+               return this;
+       }
+
+       @Override /* GENERATED - ContextBuilder */
        public HtmlSchemaSerializerBuilder add(Map<String,Object> properties) {
                super.add(properties);
                return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
index 1e568f0..8942674 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
@@ -243,7 +243,7 @@ public class HtmlSerializer extends XmlSerializer 
implements HtmlMetaProvider {
         */
        public HtmlSerializer getSchemaSerializer() {
                if (schemaSerializer == null)
-                       schemaSerializer = 
HtmlSchemaSerializer.create().apply(getContextProperties()).build();
+                       schemaSerializer = 
HtmlSchemaSerializer.create().beanContext(getBeanContext()).build();
                return schemaSerializer;
        }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
index 68133b9..54e1eca 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
@@ -528,6 +528,12 @@ public class HtmlSerializerBuilder extends 
XmlSerializerBuilder {
 
        // <FluentSetters>
 
+       @Override /* GENERATED - ContextBuilder */
+       public HtmlSerializerBuilder beanContext(BeanContext value) {
+               super.beanContext(value);
+               return this;
+       }
+
        @Override
        public HtmlSerializerBuilder produces(String value) {
                super.produces(value);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
index 16c5630..4305127 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
@@ -190,7 +190,7 @@ public class JsonSerializer extends WriterSerializer 
implements JsonMetaProvider
         */
        public JsonSchemaSerializer getSchemaSerializer() {
                if (schemaSerializer == null)
-                       schemaSerializer = 
JsonSchemaSerializer.create().apply(getContextProperties()).build();
+                       schemaSerializer = (JsonSchemaSerializer) 
JsonSchemaSerializer.create().beanContext(getBeanContext()).build();
                return schemaSerializer;
        }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
index aebd0ab..a0e04fc 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
@@ -267,6 +267,12 @@ public class JsonSerializerBuilder extends 
WriterSerializerBuilder {
        }
 
        @Override
+       public JsonSerializerBuilder beanContext(BeanContext value) {
+               super.beanContext(value);
+               return this;
+       }
+
+       @Override
        public JsonSerializerBuilder produces(String value) {
                super.produces(value);
                return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGenerator.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGenerator.java
index f1a20a9..0684f2a 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGenerator.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGenerator.java
@@ -84,7 +84,7 @@ public class JsonSchemaGenerator extends BeanTraverseContext 
implements JsonSche
                }
 
                jsonSerializer = builder.jsonSerializerBuilder.build();
-               jsonParser = 
builder.jsonParserBuilder.apply(getBeanContext().getContextProperties()).build();
+               jsonParser = (JsonParser) 
builder.jsonParserBuilder.beanContext(getBeanContext()).build();
        }
 
        @Override /* Context */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorBuilder.java
index 58a4742..4cfc867 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGeneratorBuilder.java
@@ -364,6 +364,12 @@ public class JsonSchemaGeneratorBuilder extends 
BeanTraverseBuilder {
        }
 
        @Override /* GENERATED - ContextBuilder */
+       public JsonSchemaGeneratorBuilder beanContext(BeanContext value) {
+               super.beanContext(value);
+               return this;
+       }
+
+       @Override /* GENERATED - ContextBuilder */
        public JsonSchemaGeneratorBuilder add(Map<String,Object> properties) {
                super.add(properties);
                return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/HashKey.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/HashKey.java
index 49e678b..daeed3e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/HashKey.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/HashKey.java
@@ -14,6 +14,9 @@ package org.apache.juneau.utils;
 
 import java.util.*;
 
+import org.apache.juneau.collections.*;
+import org.apache.juneau.marshall.*;
+
 /**
  * Represents a list of objects used to compare objects for equality.
  */
@@ -60,4 +63,25 @@ public class HashKey {
                                return false;
                return true;
        }
+
+       /**
+        * Returns the properties defined on this bean as a simple map for 
debugging purposes.
+        *
+        * <p>
+        * Use <c>SimpleJson.<jsf>DEFAULT</jsf>.println(<jv>thisBean</jv>)</c> 
to dump the contents of this bean to the console.
+        *
+        * @return A new map containing this bean's properties.
+        */
+       public OMap toMap() {
+               return OMap
+                       .create()
+                       .filtered()
+                       .a("hashCode", hashCode())
+                       .a("array", array);
+       }
+       
+       @Override /* Object */
+       public String toString() {
+               return SimpleJson.DEFAULT.toString(this);
+       }
 }
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index e1e3a99..96da96f 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -2903,9 +2903,9 @@ public class RestClient extends BeanContextable 
implements HttpClient, Closeable
                Context o = requestContexts.get(c);
                if (o == null) {
                        if (Serializer.class.isAssignableFrom(c)) {
-                               o = Serializer.createSerializerBuilder((Class<? 
extends Serializer>)c).apply(getContextProperties()).build();
+                               o = Serializer.createSerializerBuilder((Class<? 
extends Serializer>)c).beanContext(getBeanContext()).build();
                        } else if (Parser.class.isAssignableFrom(c)) {
-                               o = Parser.createParserBuilder((Class<? extends 
Parser>)c).apply(getContextProperties()).build();
+                               o = Parser.createParserBuilder((Class<? extends 
Parser>)c).beanContext(getBeanContext()).build();
                        } else {
                                o = ContextCache.INSTANCE.create(c, 
getContextProperties());
                        }
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/ContextPropertiesTest.java 
b/juneau-utest/src/test/java/org/apache/juneau/ContextPropertiesTest.java
index e22fba7..34e3d1d 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/ContextPropertiesTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/ContextPropertiesTest.java
@@ -1792,14 +1792,14 @@ public class ContextPropertiesTest {
 
        @Test
        public void testEqualsWithAnnotations() {
-               HtmlSerializer
-                       s1 = HtmlSerializer.create().build(),
-                       s2 = 
HtmlSerializer.create().applyAnnotations(B1Config.class).build(),
-                       s3 = 
HtmlSerializer.create().applyAnnotations(B1Config.class).build(),
-                       s4 = 
HtmlSerializer.create().applyAnnotations(B2Config.class).build();
-               
assertFalse(s1.getContextProperties().equals(s2.getContextProperties()));
-               
assertFalse(s1.getContextProperties().equals(s4.getContextProperties()));
-               
assertTrue(s2.getContextProperties().equals(s3.getContextProperties()));
+               HtmlSerializerBuilder
+                       s1 = HtmlSerializer.create(),
+                       s2 = 
HtmlSerializer.create().applyAnnotations(B1Config.class),
+                       s3 = 
HtmlSerializer.create().applyAnnotations(B1Config.class),
+                       s4 = 
HtmlSerializer.create().applyAnnotations(B2Config.class);
+               assertFalse(s1.hashKey().equals(s2.hashKey()));
+               assertFalse(s1.hashKey().equals(s4.hashKey()));
+               assertTrue(s2.hashKey().equals(s3.hashKey()));
        }
 
        @Html(on="B1", format=HtmlFormat.XML)
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
 
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
index 39d07b1..c49912f 100755
--- 
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
@@ -42,7 +42,7 @@ public class RoundTripBeanMapsTest extends RoundTripTest {
        static Class<?>[] ANNOTATED_CLASSES={L2Config.class, M2Config.class};
 
        public RoundTripBeanMapsTest(String label, SerializerBuilder s, 
ParserBuilder p, int flags) throws Exception {
-               super(label, s.applyAnnotations(ANNOTATED_CLASSES), p == null ? 
null : p.applyAnnotations(ANNOTATED_CLASSES), flags);
+               super(label, s, p, flags);
        }
 
        @Override /* RoundTripTest */
@@ -52,6 +52,11 @@ public class RoundTripBeanMapsTest extends RoundTripTest {
                return m;
        }
 
+       @Override /* RoundTripTest */
+       public Class<?>[] getAnnotatedClasses() {
+               return ANNOTATED_CLASSES;
+       }
+
        
//====================================================================================================
        // IBean/ABean/Bean
        
//====================================================================================================
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/RoundTripTest.java 
b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/RoundTripTest.java
index 90f6c1a..45e1785 100755
--- a/juneau-utest/src/test/java/org/apache/juneau/a/rttests/RoundTripTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/a/rttests/RoundTripTest.java
@@ -13,6 +13,7 @@
 package org.apache.juneau.a.rttests;
 
 import static org.apache.juneau.a.rttests.RoundTripTest.Flags.*;
+import static java.util.Collections.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -190,17 +191,27 @@ public abstract class RoundTripTest {
 
        public RoundTripTest(String label, SerializerBuilder s, ParserBuilder 
p, int flags) throws Exception {
                this.label = label;
-
                Map<Class<Object>, Class<? extends Object>> m = 
getImplClasses();
-               if (m != null) {
+               OMap properties = getProperties();
+               Class<?>[] pojoSwaps = getPojoSwaps();
+               Class<?>[] dictionary = getDictionary();
+               Class<?>[] annotatedClasses = getAnnotatedClasses();
+
+               if (! (m.isEmpty() && properties.isEmpty() && pojoSwaps.length 
== 0 && dictionary.length == 0 && annotatedClasses.length == 0)) {
+                       s = s.copy();
+                       p = p == null ? null : p.copy();
                        for (Entry<Class<Object>, Class<? extends Object>> e : 
m.entrySet()) {
                                s.implClass(e.getKey(), e.getValue());
                                if (p != null)
                                        p.implClass(e.getKey(), e.getValue());
                        }
+                       
s.swaps(pojoSwaps).beanDictionary(dictionary).add(properties).applyAnnotations(annotatedClasses);
+                       if (p != null)
+                               
p.swaps(pojoSwaps).beanDictionary(dictionary).add(properties).applyAnnotations(annotatedClasses);
                }
-               this.s = 
s.swaps(getPojoSwaps()).beanDictionary(getDictionary()).add(getProperties()).build();
-               this.p = p == null ? null : 
p.swaps(getPojoSwaps()).beanDictionary(getDictionary()).add(getProperties()).build();
+
+               this.s = s.build();
+               this.p = p == null ? null : p.build();
                this.validateXmlWhitespace = (flags & CHECK_XML_WHITESPACE) > 0;
                this.validateXml = (flags & VALIDATE_XML) > 0;
                this.returnOriginalObject = (flags & RETURN_ORIGINAL_OBJECT) > 
0;
@@ -219,12 +230,16 @@ public abstract class RoundTripTest {
                return new Class<?>[0];
        }
 
+       public Class<?>[] getAnnotatedClasses() {
+               return new Class<?>[0];
+       }
+
        public OMap getProperties() {
                return OMap.EMPTY_MAP;
        }
 
        public <T> Map<Class<T>,Class<? extends T>> getImplClasses() {
-               return null;
+               return emptyMap();
        }
 
        public <T> T roundTrip(T object, Type c, Type...args) throws Exception {
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/transforms/ReaderFilterTest.java 
b/juneau-utest/src/test/java/org/apache/juneau/transforms/ReaderFilterTest.java
index 6bddf05..26559d0 100755
--- 
a/juneau-utest/src/test/java/org/apache/juneau/transforms/ReaderFilterTest.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/transforms/ReaderFilterTest.java
@@ -91,7 +91,7 @@ public class ReaderFilterTest {
                r = reader("{foo:'bar',baz:'quz'}");
                m = new HashMap<>();
                m.put("X", r);
-               assertEquals("{X:{foo:'bar',baz:'quz'}}", s.serialize(m));
+               assertEquals("{X:'{foo:\\'bar\\',baz:\\'quz\\'}'}", 
s.serialize(m));
        }
 
        
//====================================================================================================

Reply via email to