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 3ddd7f7  CollectionUtils refactoring.
3ddd7f7 is described below

commit 3ddd7f7afe256278592d199536c3ea740e890110
Author: JamesBognar <[email protected]>
AuthorDate: Sat Feb 6 11:00:11 2021 -0500

    CollectionUtils refactoring.
---
 .../org/apache/juneau/dto/swagger/HeaderInfo.java  |   4 +-
 .../java/org/apache/juneau/dto/swagger/Items.java  |   4 +-
 .../org/apache/juneau/dto/swagger/Operation.java   |  48 +--
 .../apache/juneau/dto/swagger/ParameterInfo.java   |  12 +-
 .../apache/juneau/dto/swagger/ResponseInfo.java    |  14 +-
 .../org/apache/juneau/dto/swagger/SchemaInfo.java  |  20 +-
 .../apache/juneau/dto/swagger/SecurityScheme.java  |   6 +-
 .../org/apache/juneau/dto/swagger/Swagger.java     |  75 ++--
 .../apache/juneau/internal/CollectionUtils.java    | 465 ++-------------------
 .../org/apache/juneau/internal/ListBuilder.java    | 234 +++++++++++
 .../org/apache/juneau/internal/MapBuilder.java     | 222 ++++++++++
 .../org/apache/juneau/internal/SetBuilder.java     | 237 +++++++++++
 .../java/org/apache/juneau/mstat/ThrownStats.java  |   4 +-
 .../java/org/apache/juneau/reflect/ClassInfo.java  |   7 +-
 .../java/org/apache/juneau/rest/RestContext.java   |  21 +-
 .../apache/juneau/dto/swagger/HeaderInfo_Test.java |   4 +-
 .../apache/juneau/dto/swagger/Swagger_Test.java    |   2 +-
 .../apache/juneau/utils/CollectionUtilsTest.java   |  64 ---
 18 files changed, 857 insertions(+), 586 deletions(-)

diff --git 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/HeaderInfo.java
 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/HeaderInfo.java
index 7076856..a80407c 100644
--- 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/HeaderInfo.java
+++ 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/HeaderInfo.java
@@ -382,7 +382,7 @@ public class HeaderInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public HeaderInfo addEnum(Collection<Object> value) {
-               _enum = addToSet(_enum, value);
+               _enum = setBuilder(_enum).sparse().addAll(value).build();
                return this;
        }
 
@@ -421,7 +421,7 @@ public class HeaderInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public HeaderInfo _enum(Object...value) {
-               setEnum(toSet(value, Object.class));
+               
setEnum(setBuilder(Object.class).sparse().addAny(value).build());
                return this;
        }
 
diff --git 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Items.java 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Items.java
index f71d92d..a1e29c5 100644
--- 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Items.java
+++ 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Items.java
@@ -326,7 +326,7 @@ public class Items extends SwaggerElement {
         *      <br>Can be <jk>null</jk> to unset the property.
         */
        public void addEnum(Collection<Object> value) {
-               _enum = addToSet(_enum, value);
+               _enum = setBuilder(_enum).sparse().addAll(value).build();
        }
 
        /**
@@ -359,7 +359,7 @@ public class Items extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Items _enum(Object...value) {
-               setEnum(toSet(value, Object.class));
+               
setEnum(setBuilder(Object.class).sparse().addAny(value).build());
                return this;
        }
 
diff --git 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Operation.java
 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Operation.java
index 7b9f85b..b7addf5 100644
--- 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Operation.java
+++ 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Operation.java
@@ -251,7 +251,7 @@ public class Operation extends SwaggerElement {
         *      <br>Can be <jk>null</jk> to unset the property.
         */
        public void addConsumes(Collection<MediaType> value) {
-               consumes = addToSet(consumes, value);
+               consumes = setBuilder(consumes).sparse().addAll(value).build();
        }
 
        /**
@@ -277,7 +277,7 @@ public class Operation extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Operation consumes(MediaType...value) {
-               setConsumes(toSet(value, MediaType.class));
+               
setConsumes(setBuilder(MediaType.class).sparse().add(value).build());
                return this;
        }
 
@@ -308,7 +308,7 @@ public class Operation extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Operation consumes(String...value) {
-               setConsumes(toSet(value, MediaType.class));
+               
setConsumes(setBuilder(MediaType.class).sparse().addJson(value).build());
                return this;
        }
 
@@ -682,7 +682,7 @@ public class Operation extends SwaggerElement {
         *      <br>Ignored if <jk>null</jk>.
         */
        public void addParameters(Collection<ParameterInfo> value) {
-               parameters = addToList(parameters, value);
+               parameters = 
listBuilder(parameters).sparse().addAll(value).build();
        }
 
        /**
@@ -708,7 +708,7 @@ public class Operation extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Operation parameters(ParameterInfo...value) {
-               setParameters(toList(value, ParameterInfo.class));
+               
setParameters(listBuilder(ParameterInfo.class).sparse().add(value).build());
                return this;
        }
 
@@ -739,7 +739,7 @@ public class Operation extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Operation parameters(String...value) {
-               setParameters(toList(value, ParameterInfo.class));
+               
setParameters(listBuilder(ParameterInfo.class).sparse().addJson(value).build());
                return this;
        }
 
@@ -785,7 +785,7 @@ public class Operation extends SwaggerElement {
         *      <br>Value MUST be as described under {@doc ExtSwaggerMimeTypes}.
         */
        public void addProduces(Collection<MediaType> value) {
-               produces = addToSet(produces, value);
+               produces = setBuilder(produces).sparse().addAll(value).build();
        }
 
        /**
@@ -811,7 +811,7 @@ public class Operation extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Operation produces(MediaType...value) {
-               setProduces(toSet(value, MediaType.class));
+               
setProduces(setBuilder(MediaType.class).sparse().add(value).build());
                return this;
        }
 
@@ -842,7 +842,7 @@ public class Operation extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Operation produces(String...value) {
-               setProduces(toSet(value, MediaType.class));
+               
setProduces(setBuilder(MediaType.class).sparse().addJson(value).build());
                return this;
        }
 
@@ -919,7 +919,7 @@ public class Operation extends SwaggerElement {
         *      <br>Ignored if <jk>null</jk>.
         */
        public void addResponses(Map<String,ResponseInfo> values) {
-               responses = addToMap(responses, values);
+               responses = 
mapBuilder(responses).sparse().addAll(values).build();
        }
 
        /**
@@ -977,7 +977,7 @@ public class Operation extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Operation responses(String json) {
-               setResponses(toMap(json, String.class, ResponseInfo.class));
+               
setResponses(mapBuilder(String.class,ResponseInfo.class).sparse().addJson(json).build());
                return this;
        }
 
@@ -1029,7 +1029,7 @@ public class Operation extends SwaggerElement {
         *      <br>Ignored if <jk>null</jk>.
         */
        public void addSchemes(Collection<String> value) {
-               schemes = addToSet(schemes, value);
+               schemes = setBuilder(schemes).sparse().addAll(value).build();
        }
 
        /**
@@ -1056,7 +1056,7 @@ public class Operation extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Operation schemes(String...value) {
-               setSchemes(toSet(value, String.class));
+               
setSchemes(setBuilder(String.class).sparse().addJson(value).build());
                return this;
        }
 
@@ -1118,7 +1118,7 @@ public class Operation extends SwaggerElement {
         * The new value for this property.
         */
        public void addSecurity(Collection<Map<String,List<String>>> values) {
-               security = addToList(security, values);
+               security = 
listBuilder(security).sparse().addAll(values).build();
        }
 
        /**
@@ -1185,7 +1185,7 @@ public class Operation extends SwaggerElement {
         */
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public Operation security(String value) {
-               setSecurity((Collection)toList(value, Map.class, String.class, 
List.class, String.class));
+               
setSecurity((Collection)listBuilder(Map.class,String.class,List.class,String.class).sparse().addJson(value).build());
                return this;
        }
 
@@ -1290,7 +1290,7 @@ public class Operation extends SwaggerElement {
         *      The values to add to this property.
         */
        public void addTags(Collection<String> value) {
-               tags = addToSet(tags, value);
+               tags = setBuilder(tags).sparse().addAll(value).build();
        }
 
        /**
@@ -1341,7 +1341,7 @@ public class Operation extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Operation tags(String...value) {
-               setTags(toSet(value, String.class));
+               
setTags(setBuilder(String.class).sparse().addJson(value).build());
                return this;
        }
 
@@ -1373,18 +1373,18 @@ public class Operation extends SwaggerElement {
                if (property == null)
                        return this;
                switch (property) {
-                       case "consumes": return consumes(toList(value, 
MediaType.class));
+                       case "consumes": return 
consumes(listBuilder(MediaType.class).sparse().addAny(value).build());
                        case "deprecated": return deprecated(toBoolean(value));
                        case "description": return 
description(stringify(value));
                        case "externalDocs": return externalDocs(toType(value, 
ExternalDocumentation.class));
                        case "operationId": return 
operationId(stringify(value));
-                       case "parameters": return parameters(toList(value, 
ParameterInfo.class));
-                       case "produces": return produces(toList(value, 
MediaType.class));
-                       case "responses": return responses(toMap(value, 
String.class, ResponseInfo.class));
-                       case "schemes": return schemes(toList(value, 
String.class));
-                       case "security": return security((List)toList(value, 
Map.class, String.class, List.class, String.class));
+                       case "parameters": return 
parameters(listBuilder(ParameterInfo.class).sparse().addAny(value).build());
+                       case "produces": return 
produces(listBuilder(MediaType.class).sparse().addAny(value).build());
+                       case "responses": return 
responses(mapBuilder(String.class,ResponseInfo.class).sparse().addAny(value).build());
+                       case "schemes": return 
schemes(listBuilder(String.class).sparse().addAny(value).build());
+                       case "security": return 
security((List)listBuilder(Map.class,String.class,List.class,String.class).sparse().addAny(value).build());
                        case "summary": return summary(stringify(value));
-                       case "tags": return tags(toList(value, String.class));
+                       case "tags": return 
tags(listBuilder(String.class).sparse().addAny(value).build());
                        default:
                                super.set(property, value);
                                return this;
diff --git 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java
 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java
index 3f4b501..94e683a 100644
--- 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java
+++ 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ParameterInfo.java
@@ -575,7 +575,7 @@ public class ParameterInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public ParameterInfo addEnum(Collection<Object> value) {
-               _enum = addToSet(_enum, value);
+               _enum = setBuilder(_enum).sparse().addAll(value).build();
                return this;
        }
 
@@ -609,7 +609,7 @@ public class ParameterInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public ParameterInfo _enum(Object...value) {
-               setEnum(toSet(value, Object.class));
+               
setEnum(setBuilder(Object.class).sparse().addAny(value).build());
                return this;
        }
 
@@ -690,7 +690,7 @@ public class ParameterInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public ParameterInfo addExamples(Map<String,String> values) {
-               examples = addToMap(examples, values);
+               examples = mapBuilder(examples).sparse().addAll(values).build();
                return this;
        }
 
@@ -705,7 +705,7 @@ public class ParameterInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public ParameterInfo example(String name, String value) {
-               examples = addToMap(examples, name, value);
+               examples = mapBuilder(examples).sparse().add(name, 
value).build();
                return this;
        }
 
@@ -738,7 +738,7 @@ public class ParameterInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public ParameterInfo examples(String json) {
-               setExamples(toMap(json, String.class, String.class));
+               
setExamples(mapBuilder(String.class,String.class).sparse().addJson(json).build());
                return this;
        }
 
@@ -1939,7 +1939,7 @@ public class ParameterInfo extends SwaggerElement {
                        case "description": return 
description(stringify(value));
                        case "enum": return _enum(value);
                        case "example": return example(stringify(value));
-                       case "examples": return examples(toMap(value, 
String.class, String.class));
+                       case "examples": return 
examples(mapBuilder(String.class,String.class).sparse().addAny(value).build());
                        case "exclusiveMaximum": return 
exclusiveMaximum(toBoolean(value));
                        case "exclusiveMinimum": return 
exclusiveMinimum(toBoolean(value));
                        case "format": return format(stringify(value));
diff --git 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java
 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java
index c0cfad0..b3ac618 100644
--- 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java
+++ 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ResponseInfo.java
@@ -277,7 +277,7 @@ public class ResponseInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public ResponseInfo addExamples(Map<String,Object> values) {
-               examples = addToMap(examples, values);
+               examples = mapBuilder(examples).sparse().addAll(values).build();
                return this;
        }
 
@@ -292,7 +292,7 @@ public class ResponseInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public ResponseInfo example(String mimeType, Object example) {
-               examples = addToMap(examples, mimeType, example);
+               examples =  mapBuilder(examples).sparse().add(mimeType, 
example).build();
                return this;
        }
 
@@ -330,7 +330,7 @@ public class ResponseInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public ResponseInfo examples(String value) {
-               setExamples(toMap(value, String.class, Object.class));
+               
setExamples(mapBuilder(String.class,Object.class).sparse().addJson(value).build());
                return this;
        }
 
@@ -373,7 +373,7 @@ public class ResponseInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public ResponseInfo addHeaders(Map<String,HeaderInfo> values) {
-               headers = addToMap(headers, values);
+               headers = mapBuilder(headers).sparse().addAll(values).build();
                return this;
        }
 
@@ -432,7 +432,7 @@ public class ResponseInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public ResponseInfo headers(String json) {
-               setHeaders(toMap(json, String.class, HeaderInfo.class));
+               
setHeaders(mapBuilder(String.class,HeaderInfo.class).sparse().addJson(json).build());
                return this;
        }
 
@@ -558,8 +558,8 @@ public class ResponseInfo extends SwaggerElement {
                switch (property) {
                        case "description": return 
description(stringify(value));
                        case "example": return example(value);
-                       case "examples": return examples(toMap(value, 
String.class, Object.class));
-                       case "headers": return headers(toMap(value, 
String.class, HeaderInfo.class));
+                       case "examples": return 
examples(mapBuilder(String.class,Object.class).sparse().addAny(value).build());
+                       case "headers": return 
headers(mapBuilder(String.class,HeaderInfo.class).sparse().addAny(value).build());
                        case "schema": return schema(stringify(value));
                        default:
                                super.set(property, value);
diff --git 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SchemaInfo.java
 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SchemaInfo.java
index 2125e50..bb5a448 100644
--- 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SchemaInfo.java
+++ 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SchemaInfo.java
@@ -253,7 +253,7 @@ public class SchemaInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public SchemaInfo addAllOf(Collection<Object> values) {
-               allOf = addToSet(allOf, values);
+               allOf = setBuilder(allOf).sparse().addAll(values).build();
                return this;
        }
 
@@ -288,7 +288,7 @@ public class SchemaInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public SchemaInfo allOf(Object...value) {
-               setAllOf(toSet(value, Object.class));
+               
setAllOf(setBuilder(Object.class).sparse().addAny(value).build());
                return this;
        }
 
@@ -474,7 +474,7 @@ public class SchemaInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public SchemaInfo addEnum(Collection<Object> value) {
-               _enum = addToSet(_enum, value);
+               _enum = setBuilder(_enum).sparse().addAll(value).build();
                return this;
        }
 
@@ -496,7 +496,7 @@ public class SchemaInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public SchemaInfo _enum(Object...value) {
-               setEnum(toSet(value, Object.class));
+               
setEnum(setBuilder(Object.class).sparse().addAny(value).build());
                return this;
        }
 
@@ -1485,7 +1485,7 @@ public class SchemaInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public SchemaInfo addProperties(Map<String,SchemaInfo> values) {
-               properties = addToMap(properties, values);
+               properties = 
mapBuilder(properties).sparse().addAll(values).build();
                return this;
        }
 
@@ -1518,7 +1518,7 @@ public class SchemaInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public SchemaInfo properties(String json) {
-               setProperties(toMap(json, String.class, SchemaInfo.class));
+               
setProperties(mapBuilder(String.class,SchemaInfo.class).sparse().addJson(json).build());
                return this;
        }
 
@@ -1678,7 +1678,7 @@ public class SchemaInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public SchemaInfo addRequired(Collection<String> value) {
-               required = addToSet(required, value);
+               required = setBuilder(required).sparse().addAny(value).build();
                return this;
        }
 
@@ -1711,7 +1711,7 @@ public class SchemaInfo extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public SchemaInfo required(String...value) {
-               setRequired(toSet(value, String.class));
+               
setRequired(setBuilder(String.class).sparse().addJson(value).build());
                return this;
        }
 
@@ -2017,10 +2017,10 @@ public class SchemaInfo extends SwaggerElement {
                        case "minProperties": return 
minProperties(toInteger(value));
                        case "multipleOf": return multipleOf(toNumber(value));
                        case "pattern": return pattern(stringify(value));
-                       case "properties": return 
properties(toMap(value,String.class,SchemaInfo.class));
+                       case "properties": return 
properties(mapBuilder(String.class,SchemaInfo.class).sparse().addAny(value).build());
                        case "readOnly": return readOnly(toBoolean(value));
                        case "$ref": return ref(stringify(value));
-                       case "required": return 
required(toList(value,String.class));
+                       case "required": return 
required(listBuilder(String.class).sparse().addAny(value).build());
                        case "title": return title(stringify(value));
                        case "type": return type(stringify(value));
                        case "uniqueItems": return 
uniqueItems(toBoolean(value));
diff --git 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SecurityScheme.java
 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SecurityScheme.java
index de3b670..5e522fc 100644
--- 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SecurityScheme.java
+++ 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SecurityScheme.java
@@ -473,7 +473,7 @@ public class SecurityScheme extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public SecurityScheme addScopes(Map<String,String> values) {
-               scopes = addToMap(scopes, values);
+               scopes = mapBuilder(scopes).sparse().addAll(values).build();
                return this;
        }
 
@@ -515,7 +515,7 @@ public class SecurityScheme extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public SecurityScheme scopes(String json) {
-               setScopes(toMap(json, String.class, String.class));
+               
setScopes(mapBuilder(String.class,String.class).sparse().addJson(json).build());
                return this;
        }
 
@@ -683,7 +683,7 @@ public class SecurityScheme extends SwaggerElement {
                        case "flow": return flow(stringify(value));
                        case "in": return in(stringify(value));
                        case "name": return name(stringify(value));
-                       case "scopes": return scopes(toMap(value, String.class, 
String.class));
+                       case "scopes": return 
scopes(mapBuilder(String.class,String.class).sparse().addAny(value).build());
                        case "tokenUrl": return tokenUrl(stringify(value));
                        case "type": return type(stringify(value));
                        default:
diff --git 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
index e028260..f55884b 100644
--- 
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
+++ 
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
@@ -269,7 +269,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger addConsumes(Collection<MediaType> values) {
-               consumes = addToSet(consumes, values);
+               consumes = setBuilder(consumes).sparse().addAll(values).build();
                return this;
        }
 
@@ -311,7 +311,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger consumes(MediaType...value) {
-               setConsumes(toSet(value, MediaType.class));
+               
setConsumes(setBuilder(MediaType.class).sparse().add(value).build());
                return this;
        }
 
@@ -327,7 +327,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger consumes(String...value) {
-               setConsumes(toSet(value, MediaType.class));
+               
setConsumes(setBuilder(MediaType.class).sparse().addJson(value).build());
                return this;
        }
 
@@ -373,7 +373,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger addDefinitions(Map<String,OMap> values) {
-               definitions = addToMap(definitions, values);
+               definitions = 
mapBuilder(definitions).sparse().addAll(values).build();
                return this;
        }
 
@@ -388,7 +388,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger definition(String name, OMap schema) {
-               definitions = addToMap(definitions, name, schema);
+               definitions = mapBuilder(definitions).sparse().add(name, 
schema).build();
                return this;
        }
 
@@ -430,7 +430,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger definitions(String json) {
-               setDefinitions(toMap(json, String.class, OMap.class));
+               
setDefinitions(mapBuilder(String.class,OMap.class).sparse().addJson(json).build());
                return this;
        }
 
@@ -698,7 +698,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger addParameters(Map<String,ParameterInfo> values) {
-               parameters = addToMap(parameters, values);
+               parameters = 
mapBuilder(parameters).sparse().addAll(values).build();
                return this;
        }
 
@@ -713,7 +713,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger parameter(String name, ParameterInfo parameter) {
-               parameters = addToMap(parameters, name, parameter);
+               parameters = mapBuilder(parameters).sparse().add(name, 
parameter).build();
                return this;
        }
 
@@ -752,7 +752,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger parameters(String json) {
-               setParameters(toMap(json, String.class, ParameterInfo.class));
+               
setParameters(mapBuilder(String.class,ParameterInfo.class).sparse().addJson(json).build());
                return this;
        }
 
@@ -783,7 +783,7 @@ public class Swagger extends SwaggerElement {
         *      <br>Property value is required.
         */
        public void setPaths(Map<String,OperationMap> value) {
-               paths = newSortedMap(value, PATH_COMPARATOR);
+               paths = 
mapBuilder(String.class,OperationMap.class).sparse().sorted(PATH_COMPARATOR).addAll(value).build();
        }
 
        /**
@@ -798,7 +798,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger addPaths(Map<String,OperationMap> values) {
-               paths = addToSortedMap(paths, values, PATH_COMPARATOR);
+               paths = 
mapBuilder(paths).sparse().sorted(PATH_COMPARATOR).addAll(values).build();
                return this;
        }
 
@@ -862,9 +862,8 @@ public class Swagger extends SwaggerElement {
         *      The values to set on this property as JSON.
         * @return This object (for method chaining).
         */
-       @SuppressWarnings({ "unchecked", "rawtypes" })
        public Swagger paths(String json) {
-               setPaths(addToMap(new TreeMap(PATH_COMPARATOR), new 
Object[]{json}, String.class, Map.class, String.class, Operation.class));
+               
setPaths(mapBuilder(String.class,OperationMap.class).sparse().sorted(PATH_COMPARATOR).addJson(json).build());
                return this;
        }
 
@@ -912,7 +911,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger addProduces(Collection<MediaType> values) {
-               produces = addToSet(produces, values);
+               produces = setBuilder(produces).sparse().addAll(values).build();
                return this;
        }
 
@@ -954,7 +953,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger produces(MediaType...value) {
-               setProduces(toSet(value, MediaType.class));
+               
setProduces(setBuilder(MediaType.class).sparse().add(value).build());
                return this;
        }
 
@@ -970,7 +969,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger produces(String...value) {
-               setProduces(toSet(value, MediaType.class));
+               
setProduces(setBuilder(MediaType.class).sparse().addJson(value).build());
                return this;
        }
 
@@ -1016,7 +1015,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger addResponses(Map<String,ResponseInfo> values) {
-               responses = addToMap(responses, values);
+               responses = 
mapBuilder(responses).sparse().addAll(values).build();
                return this;
        }
 
@@ -1031,7 +1030,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger response(String name, ResponseInfo response) {
-               responses = addToMap(responses, name, response);
+               responses = mapBuilder(responses).sparse().add(name, 
response).build();
                return this;
        }
 
@@ -1073,7 +1072,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger responses(String json) {
-               setResponses(toMap(json, String.class, ResponseInfo.class));
+               
setResponses(mapBuilder(String.class,ResponseInfo.class).sparse().addJson(json).build());
                return this;
        }
 
@@ -1133,7 +1132,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger addSchemes(Collection<String> values) {
-               schemes = addToSet(schemes, values);
+               schemes = setBuilder(schemes).sparse().addAll(values).build();
                return this;
        }
 
@@ -1176,7 +1175,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger schemes(String...value) {
-               setSchemes(toSet(value, String.class));
+               
setSchemes(setBuilder(String.class).sparse().addJson(value).build());
                return this;
        }
 
@@ -1222,7 +1221,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger addSecurity(Collection<Map<String,List<String>>> values) 
{
-               security = addToList(security, values);
+               security = 
listBuilder(security).sparse().addAll(values).build();
                return this;
        }
 
@@ -1282,7 +1281,7 @@ public class Swagger extends SwaggerElement {
         */
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public Swagger security(String json) {
-               setSecurity((List)toList(json, Map.class, String.class, 
List.class, String.class));
+               
setSecurity((List)listBuilder(Map.class,String.class,List.class,String.class).sparse().addJson(json).build());
                return this;
        }
 
@@ -1328,7 +1327,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger addSecurityDefinitions(Map<String,SecurityScheme> 
values) {
-               securityDefinitions = addToMap(securityDefinitions, values);
+               securityDefinitions = 
mapBuilder(securityDefinitions).sparse().addAll(values).build();
                return this;
        }
 
@@ -1343,7 +1342,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger securityDefinition(String name, SecurityScheme 
securityScheme) {
-               securityDefinitions = addToMap(securityDefinitions, name, 
securityScheme);
+               securityDefinitions = 
mapBuilder(securityDefinitions).sparse().add(name, securityScheme).build();
                return this;
        }
 
@@ -1385,7 +1384,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger securityDefinitions(String json) {
-               setSecurityDefinitions(toMap(json, String.class, 
SecurityScheme.class));
+               
setSecurityDefinitions(mapBuilder(String.class,SecurityScheme.class).sparse().addJson(json).build());
                return this;
        }
 
@@ -1497,7 +1496,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger addTags(Collection<Tag> values) {
-               tags = addToSet(tags, values);
+               tags = setBuilder(tags).sparse().addAll(values).build();
                return this;
        }
 
@@ -1539,7 +1538,7 @@ public class Swagger extends SwaggerElement {
         * @return This object (for method chaining).
         */
        public Swagger tags(String json) {
-               setTags(toSet(json, Tag.class));
+               setTags(setBuilder(Tag.class).sparse().addJson(json).build());
                return this;
        }
 
@@ -1700,20 +1699,20 @@ public class Swagger extends SwaggerElement {
                        return this;
                switch (property) {
                        case "basePath": return basePath(stringify(value));
-                       case "consumes": return consumes(toList(value, 
MediaType.class));
-                       case "definitions": return definitions(toMap(value, 
String.class, OMap.class));
+                       case "consumes": return 
consumes(listBuilder(MediaType.class).sparse().addAny(value).build());
+                       case "definitions": return 
definitions(mapBuilder(String.class,OMap.class).sparse().addAny(value).build());
                        case "externalDocs": return externalDocs(toType(value, 
ExternalDocumentation.class));
                        case "host": return host(stringify(value));
                        case "info": return info(toType(value, Info.class));
-                       case "parameters": return parameters(toMap(value, 
String.class, ParameterInfo.class));
-                       case "paths": return paths(toMap(value, String.class, 
OperationMap.class));
-                       case "produces": return produces(toList(value, 
MediaType.class));
-                       case "responses": return responses(toMap(value, 
String.class, ResponseInfo.class));
-                       case "schemes": return schemes(toList(value, 
String.class));
-                       case "security": return security((List)toList(value, 
Map.class, String.class, List.class, String.class));
-                       case "securityDefinitions": return 
securityDefinitions(toMap(value, String.class, SecurityScheme.class));
+                       case "parameters": return 
parameters(mapBuilder(String.class,ParameterInfo.class).sparse().addAny(value).build());
+                       case "paths": return 
paths(mapBuilder(String.class,OperationMap.class).sparse().addAny(value).build());
+                       case "produces": return 
produces(listBuilder(MediaType.class).sparse().addAny(value).build());
+                       case "responses": return 
responses(mapBuilder(String.class,ResponseInfo.class).sparse().addAny(value).build());
+                       case "schemes": return 
schemes(listBuilder(String.class).sparse().addAny(value).build());
+                       case "security": return 
security((List)listBuilder(Map.class,String.class,List.class,String.class).sparse().addAny(value).build());
+                       case "securityDefinitions": return 
securityDefinitions(mapBuilder(String.class,SecurityScheme.class).sparse().addAny(value).build());
                        case "swagger": return swagger(stringify(value));
-                       case "tags": return tags(toList(value, Tag.class));
+                       case "tags": return 
tags(listBuilder(Tag.class).sparse().addAny(value).build());
                        default:
                                super.set(property, value);
                                return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/CollectionUtils.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/CollectionUtils.java
index d952730..25892ed 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/CollectionUtils.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/CollectionUtils.java
@@ -12,35 +12,15 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.internal;
 
-import static org.apache.juneau.internal.StringUtils.*;
-import static org.apache.juneau.internal.ConverterUtils.*;
-
 import java.lang.reflect.*;
 import java.util.*;
 
-import org.apache.juneau.*;
-import org.apache.juneau.collections.*;
-import org.apache.juneau.parser.*;
-
 /**
  * Utility methods for collections.
  */
 public final class CollectionUtils {
 
        /**
-        * Add a value to a list if the value is not null.
-        *
-        * @param l The list to add to.
-        * @param o The element to add.
-        * @return The same list.
-        */
-       public static <T> List<T> addIfNotNull(List<T> l, T o) {
-               if (o != null)
-                       l.add(o);
-               return l;
-       }
-
-       /**
         * Returns an iterable over the specified enumeration.
         *
         * @param e The collection to iterate over.
@@ -107,238 +87,23 @@ public final class CollectionUtils {
        }
 
        /**
-        * Adds a set of values to an existing list.
-        *
-        * @param appendTo
-        *      The list to append to.
-        *      <br>If <jk>null</jk>, a new {@link ArrayList} will be created.
-        * @param values The values to add.
-        * @param type The data type of the elements.
-        * @param args The generic type arguments of the data type.
-        * @return The converted value, or <jk>null</jk> if the input was null.
-        */
-       public static <T> List<T> addToList(List<T> appendTo, Object[] values, 
Class<T> type, Type...args) {
-               if (values == null)
-                       return appendTo;
-               try {
-                       List<T> l = appendTo;
-                       if (appendTo == null)
-                               l = new ArrayList<>();
-                       for (Object o : values) {
-                               if (o != null) {
-                                       if (isJsonArray(o, false)) {
-                                               for (Object o2 : new 
OList(o.toString()))
-                                                       l.add(toType(o2, type, 
args));
-                                       } else if (o instanceof Collection) {
-                                               for (Object o2 : 
(Collection<?>)o)
-                                                       l.add(toType(o2, type, 
args));
-                                       } else if (o.getClass().isArray()) {
-                                               for (int i = 0; i < 
Array.getLength(o); i++)
-                                                       
l.add(toType(Array.get(o, i), type, args));
-                                       } else {
-                                               l.add(toType(o, type, args));
-                                       }
-                               }
-                       }
-                       return l;
-               } catch (ParseException e) {
-                       throw new RuntimeException(e);
-               }
-       }
-
-       /**
-        * Adds a set of values to an existing set.
-        *
-        * @param appendTo
-        *      The set to append to.
-        *      <br>If <jk>null</jk>, a new {@link LinkedHashSet} will be 
created.
-        * @param values The values to add.
-        * @param type The data type of the elements.
-        * @param args The generic type arguments of the data type.
-        * @return The converted value, or <jk>null</jk> if the input was null.
-        */
-       public static <T> Set<T> addToSet(Set<T> appendTo, Object[] values, 
Class<T> type, Type...args) {
-               if (values == null)
-                       return appendTo;
-               try {
-                       Set<T> l = appendTo;
-                       if (appendTo == null)
-                               l = new LinkedHashSet<>();
-                       for (Object o : values) {
-                               if (o != null) {
-                                       if (isJsonArray(o, false)) {
-                                               for (Object o2 : new 
OList(o.toString()))
-                                                       l.add(toType(o2, type, 
args));
-                                       } else if (o instanceof Collection) {
-                                               for (Object o2 : 
(Collection<?>)o)
-                                                       l.add(toType(o2, type, 
args));
-                                       } else if (o.getClass().isArray()) {
-                                               for (int i = 0; i < 
Array.getLength(o); i++)
-                                                       
l.add(toType(Array.get(o, i), type, args));
-                                       } else {
-                                               l.add(toType(o, type, args));
-                                       }
-                               }
-                       }
-                       return l;
-               } catch (ParseException e) {
-                       throw new RuntimeException(e);
-               }
-       }
-
-       /**
-        * Creates a new list from the specified values.
-        *
-        * @param values The values to add.
-        * @param type The data type of the elements.
-        * @param args The generic type arguments of the data type.
-        * @return The converted value, or <jk>null</jk> if the input was null.
-        */
-       public static <T> List<T> toList(Object[] values, Class<T> type, 
Type...args) {
-               return addToList(new ArrayList<T>(), values, type, args);
-       }
-
-       /**
-        * Creates a new list from the specified values.
-        *
-        * @param value The value to add.
-        * @param type The data type of the elements.
-        * @param args The generic type arguments of the data type.
-        * @return The converted value, or <jk>null</jk> if the input was null.
-        */
-       public static <T> List<T> toList(Object value, Class<T> type, 
Type...args) {
-               return addToList(new ArrayList<T>(), new Object[]{value}, type, 
args);
-       }
-
-       /**
-        * Creates a new set from the specified values.
-        *
-        * @param values The values to add.
-        * @param type The data type of the elements.
-        * @param args The generic type arguments of the data type.
-        * @return The converted value, or <jk>null</jk> if the input was null.
-        */
-       public static <T> Set<T> toSet(Object[] values, Class<T> type, 
Type...args) {
-               return addToSet(new LinkedHashSet<T>(), values, type, args);
-       }
-
-       /**
-        * Creates a new set from the specified value.
-        *
-        * @param value The value to add.
-        * @param type The data type of the elements.
-        * @param args The generic type arguments of the data type.
-        * @return The converted value, or <jk>null</jk> if the input was null.
-        */
-       public static <T> Set<T> toSet(Object value, Class<T> type, 
Type...args) {
-               return addToSet(new LinkedHashSet<T>(), new Object[]{value}, 
type, args);
-       }
-
-       /**
-        * Adds a set of values to an existing map.
-        *
-        * @param appendTo
-        *      The map to append to.
-        *      <br>If <jk>null</jk>, a new {@link LinkedHashMap} will be 
created.
-        * @param values The values to add.
-        * @param keyType The data type of the keys.
-        * @param valueType The data type of the values.
-        * @param valueTypeArgs The generic type arguments of the data type of 
the values.
-        * @return The converted value, or <jk>null</jk> if the input was null.
-        */
-       @SuppressWarnings("unchecked")
-       public static <K,V> Map<K,V> addToMap(Map<K,V> appendTo, Object[] 
values, Class<K> keyType, Class<V> valueType, Type...valueTypeArgs) {
-               if (values == null)
-                       return appendTo;
-               try {
-                       Map<K,V> m = appendTo;
-                       if (m == null)
-                               m = new LinkedHashMap<>();
-                       for (Object o : values) {
-                               if (o != null) {
-                                       if (isJsonObject(o, false)) {
-                                               for (Map.Entry<String,Object> e 
: OMap.ofJson(o.toString()).entrySet())
-                                                       
m.put(toType(e.getKey(), keyType), toType(e.getValue(), valueType, 
valueTypeArgs));
-                                       } else if (o instanceof Map) {
-                                               for (Map.Entry<Object,Object> e 
: ((Map<Object,Object>)o).entrySet())
-                                                       
m.put(toType(e.getKey(), keyType), toType(e.getValue(), valueType, 
valueTypeArgs));
-                                       } else {
-                                               throw new 
BasicRuntimeException("Invalid object type {0} passed to addToMap()", 
o.getClass().getName());
-                                       }
-                               }
-                       }
-                       return m.isEmpty() ? null : m;
-               } catch (ParseException e) {
-                       throw new RuntimeException(e);
-               }
-       }
-
-       /**
-        * Creates a new map from the specified values.
-        *
-        * @param values The values to add.
-        * @param keyType The data type of the keys.
-        * @param valueType The data type of the values.
-        * @param valueTypeArgs The generic type arguments of the data type of 
the values.
-        * @return The converted value, or <jk>null</jk> if the input was null.
-        */
-       public static <K,V> Map<K,V> toMap(Object[] values, Class<K> keyType, 
Class<V> valueType, Type...valueTypeArgs) {
-               return addToMap(new LinkedHashMap<>(), values, keyType, 
valueType, valueTypeArgs);
-       }
-
-       /**
-        * Creates a new map from the specified value.
-        *
-        * @param values The values to add.
-        * @param keyType The data type of the keys.
-        * @param valueType The data type of the values.
-        * @param valueTypeArgs The generic type arguments of the data type of 
the values.
-        * @return The converted value, or <jk>null</jk> if the input was null.
-        */
-       public static <K,V> Map<K,V> toMap(Object values, Class<K> keyType, 
Class<V> valueType, Type...valueTypeArgs) {
-               return addToMap(new LinkedHashMap<>(), new Object[]{values}, 
keyType, valueType, valueTypeArgs);
-       }
-
-       /**
         * Creates a new list from the specified collection.
         *
         * @param val The value to copy from.
         * @return A new {@link ArrayList}, or <jk>null</jk> if the input was 
null.
         */
-       public static <T> AList<T> newList(Collection<T> val) {
-               return AList.nullable(val);
+       public static <T> List<T> newList(Collection<T> val) {
+               return val == null ? null : new ArrayList<>(val);
        }
 
        /**
-        * Creates a new list from the specified array.
-        *
-        * @param val The value to copy from.
-        * @return A new {@link ArrayList}, or <jk>null</jk> if the input was 
null.
-        */
-       @SafeVarargs
-       public static <T> AList<T> newList(T...val) {
-               return AList.of(val);
-       }
-
-       /**
-        * Creates a new unmodifiable list from the specified collection.
-        *
-        * @param val The value to copy from.
-        * @return A new {@link ArrayList}, or <jk>null</jk> if the input was 
null.
-        */
-       public static <T> List<T> newUnmodifiableList(Collection<T> val) {
-               return Collections.unmodifiableList(newList(val));
-       }
-
-       /**
-        * Creates a new unmodifiable list from the specified array.
+        * Creates a new list from the specified collection.
         *
         * @param val The value to copy from.
         * @return A new {@link ArrayList}, or <jk>null</jk> if the input was 
null.
         */
-       @SafeVarargs
-       public static <T> List<T> newUnmodifiableList(T...val) {
-               return Collections.unmodifiableList(newList(val));
+       public static <T> List<T> newList(List<T> val) {
+               return val == null ? null : new ArrayList<>(val);
        }
 
        /**
@@ -347,78 +112,18 @@ public final class CollectionUtils {
         * @param val The value to copy from.
         * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input 
was null.
         */
-       public static <T> ASet<T> newSet(Collection<T> val) {
-               return ASet.nullable(val);
+       public static <T> Set<T> newSet(Collection<T> val) {
+               return val == null ? null : new LinkedHashSet<>(val);
        }
 
        /**
-        * Creates a new set from the specified array.
-        *
-        * @param val The value to copy from.
-        * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input 
was null.
-        */
-       @SafeVarargs
-       public static <T> ASet<T> newSet(T...val) {
-               return ASet.of(val);
-       }
-
-       /**
-        * Creates a new unmodifiable set from the specified collection.
-        *
-        * @param val The value to copy from.
-        * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input 
was null.
-        */
-       public static <T> Set<T> newUnmodifiableSet(Collection<T> val) {
-               return Collections.unmodifiableSet(newSet(val));
-       }
-
-       /**
-        * Creates a new unmodifiable set from the specified array.
+        * Creates a new set from the specified collection.
         *
         * @param val The value to copy from.
         * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input 
was null.
         */
-       @SafeVarargs
-       public static <T> Set<T> newUnmodifiableSet(T...val) {
-               return Collections.unmodifiableSet(newSet(val));
-       }
-
-       /**
-        * Copies the specified values into an existing list.
-        *
-        * @param l
-        *      The list to add to.
-        *      <br>If <jk>null</jk>, a new {@link ArrayList} will be created.
-        * @param val The values to add.
-        * @return The list with values copied into it.
-        */
-       public static <T> List<T> addToList(List<T> l, Collection<T> val) {
-               if (val != null) {
-                       if (l == null)
-                               l = new ArrayList<>(val);
-                       else
-                               l.addAll(val);
-               }
-               return l;
-       }
-
-       /**
-        * Copies the specified values into an existing list.
-        *
-        * @param l
-        *      The list to add to.
-        *      <br>If <jk>null</jk>, a new {@link ArrayList} will be created.
-        * @param val The values to add.
-        * @return The list with values copied into it.
-        */
-       public static <T> Set<T> addToSet(Set<T> l, Collection<T> val) {
-               if (val != null) {
-                       if (l == null)
-                               l = new LinkedHashSet<>(val);
-                       else
-                               l.addAll(val);
-               }
-               return l;
+       public static <T> Set<T> newSet(Set<T> val) {
+               return val == null ? null : new LinkedHashSet<>(val);
        }
 
        /**
@@ -428,153 +133,73 @@ public final class CollectionUtils {
         * @return A new {@link LinkedHashMap}, or <jk>null</jk> if the input 
was null.
         */
        public static <K,V> Map<K,V> newMap(Map<K,V> val) {
-               if (val == null)
-                       return null;
-               return new LinkedHashMap<>(val);
-       }
-
-       /**
-        * Creates a new unmodifiable map from the specified map.
-        *
-        * @param val The value to copy from.
-        * @return A new {@link LinkedHashMap}, or <jk>null</jk> if the input 
was null.
-        */
-       public static <K,V> Map<K,V> newUnmodifiableMap(Map<K,V> val) {
-               return Collections.unmodifiableMap(newMap(val));
-       }
-
-       /**
-        * Copies the specified values into an existing map.
-        *
-        * @param m
-        *      The map to add to.
-        *      <br>If <jk>null</jk>, a new {@link LinkedHashMap} will be 
created.
-        * @param val The values to add.
-        * @return The list with values copied into it.
-        */
-       public static <K,V> Map<K,V> addToMap(Map<K,V> m, Map<K,V> val) {
-               if (val != null) {
-                       if (m == null)
-                               m = new LinkedHashMap<>(val);
-                       else
-                               m.putAll(val);
-               }
-               return m;
+               return val == null ? null : new LinkedHashMap<>(val);
        }
 
        /**
-        * Adds a single entry into an existing map.
+        * Instantiates a new builder on top of the specified map.
         *
-        * @param m
-        *      The map to add to.
-        *      <br>If <jk>null</jk>, a new {@link LinkedHashMap} will be 
created.
-        * @param key The entry key.
-        * @param value The entry value.
-        * @return The list with values copied into it.
+        * @param addTo The map to add to.
+        * @return A new builder on top of the specified map.
         */
-       public static <K,V> Map<K,V> addToMap(Map<K,V> m, K key, V value) {
-               if (m == null)
-                       m = new LinkedHashMap<>();
-               m.put(key, value);
-               return m;
+       public static <K,V> MapBuilder<K,V> mapBuilder(Map<K,V> addTo) {
+               return new MapBuilder<>(addTo);
        }
 
        /**
-        * Creates a new map from the specified map.
+        * Instantiates a new builder of the specified map type.
         *
-        * @param val The value to copy from.
-        * @param comparator The key comparator to use, or <jk>null</jk> to use 
natural ordering.
-        * @return A new {@link LinkedHashMap}, or <jk>null</jk> if the input 
was null.
+        * @param keyType The key type.
+        * @param valueType The value type.
+        * @param valueTypeArgs The value type args.
+        * @return A new builder on top of the specified map.
         */
-       public static <K,V> Map<K,V> newSortedMap(Map<K,V> val, Comparator<K> 
comparator) {
-               if (val == null)
-                       return null;
-               Map<K,V> m = new TreeMap<>(comparator);
-               m.putAll(val);
-               return m;
+       public static <K,V> MapBuilder<K,V> mapBuilder(Class<K> keyType, 
Class<V> valueType, Type...valueTypeArgs) {
+               return new MapBuilder<>(keyType, valueType, valueTypeArgs);
        }
 
        /**
-        * Creates a case-insensitive ordered set out of the specified string 
values.
+        * Instantiates a new builder on top of the specified list.
         *
-        * @param values The values to populate the set with.
-        * @return A new ordered set.
+        * @param addTo The list to add to.
+        * @return A new builder on top of the specified list.
         */
-       public static Set<String> newSortedCaseInsensitiveSet(String...values) {
-               Set<String> s = new 
TreeSet<String>(String.CASE_INSENSITIVE_ORDER) {
-                       private static final long serialVersionUID = 1L;
-                       @Override
-                       public boolean contains(Object v) {
-                               return v == null ? false : super.contains(v);
-                       }
-               };
-               for (String v : values)
-                       if (v != null)
-                               s.add(v);
-               return s;
+       public static <E> ListBuilder<E> listBuilder(List<E> addTo) {
+               return new ListBuilder<>(addTo);
        }
 
        /**
-        * Creates a case-insensitive ordered set out of the specified string 
values.
+        * Instantiates a new builder of the specified list type.
         *
-        * @param values
-        *      A comma-delimited list of the values to populate the set with.
-        * @return A new ordered set.
+        * @param elementType The element type.
+        * @param elementTypeArgs The element type args.
+        * @return A new builder on top of the specified list.
         */
-       public static Set<String> newSortedCaseInsensitiveSet(String values) {
-               return 
newSortedCaseInsensitiveSet(StringUtils.split(StringUtils.emptyIfNull(values)));
+       public static <E> ListBuilder<E> listBuilder(Class<E> elementType, 
Type...elementTypeArgs) {
+               return new ListBuilder<>(elementType, elementTypeArgs);
        }
 
        /**
-        * Same as {@link #newSortedCaseInsensitiveSet(String)} but makes the 
set unmodifiable.
+        * Instantiates a new builder on top of the specified set.
         *
-        * @param values
-        *      A comma-delimited list of the values to populate the set with.
-        * @return A new ordered set.
+        * @param addTo The set to add to.
+        * @return A new builder on top of the specified set.
         */
-       public static Set<String> 
newUnmodifiableSortedCaseInsensitiveSet(String values) {
-               return 
Collections.unmodifiableSet(newSortedCaseInsensitiveSet(StringUtils.split(StringUtils.emptyIfNull(values))));
+       public static <E> SetBuilder<E> setBuilder(Set<E> addTo) {
+               return new SetBuilder<>(addTo);
        }
 
        /**
-        * Copies the specified values into an existing map.
+        * Instantiates a new builder of the specified set.
         *
-        * @param m
-        *      The map to add to.
-        *      <br>If <jk>null</jk>, a new {@link LinkedHashMap} will be 
created.
-        * @param val The values to add.
-        * @param comparator The key comparator to use, or <jk>null</jk> to use 
natural ordering.
-        * @return The list with values copied into it.
+        * @param elementType The element type.
+        * @param elementTypeArgs The element type args.
+        * @return A new builder on top of the specified set.
         */
-       public static <K,V> Map<K,V> addToSortedMap(Map<K,V> m, Map<K,V> val, 
Comparator<K> comparator) {
-               if (val != null) {
-                       if (m == null) {
-                               m = new TreeMap<>(comparator);
-                               m.putAll(val);
-                       } else {
-                               m.putAll(val);
-                       }
-               }
-               return m;
+       public static <E> SetBuilder<E> setBuilder(Class<E> elementType, 
Type...elementTypeArgs) {
+               return new SetBuilder<>(elementType, elementTypeArgs);
        }
 
-       /**
-        * Adds a single entry into an existing map.
-        *
-        * @param m
-        *      The map to add to.
-        *      <br>If <jk>null</jk>, a new {@link LinkedHashMap} will be 
created.
-        * @param key The entry key.
-        * @param value The entry value.
-        * @param comparator The key comparator to use, or <jk>null</jk> to use 
natural ordering.
-        * @return The list with values copied into it.
-        */
-       public static <K,V> Map<K,V> addToSortedMap(Map<K,V> m, K key, V value, 
Comparator<K> comparator) {
-               if (m == null)
-                       m = new TreeMap<>(comparator);
-               m.put(key, value);
-               return m;
-       }
 
        /**
         * Simple passthrough to {@link Collections#emptySet()}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ListBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ListBuilder.java
new file mode 100644
index 0000000..1cb5791
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ListBuilder.java
@@ -0,0 +1,234 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.internal;
+
+import static org.apache.juneau.internal.ConverterUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.parser.*;
+
+/**
+ * Builder for lists.
+ *
+ * @param <E> Element type.
+ */
+public class ListBuilder<E> {
+
+       private List<E> list;
+       private boolean unmodifiable = false, sparse = false;
+       private Comparator<E> comparator;
+
+       private Class<E> elementType;
+       private Type[] elementTypeArgs;
+
+       /**
+        * Constructor.
+        *
+        * @param elementType The element type.
+        * @param elementTypeArgs The element type generic arguments if there 
are any.
+        */
+       public ListBuilder(Class<E> elementType, Type...elementTypeArgs) {
+               this.elementType = elementType;
+               this.elementTypeArgs = elementTypeArgs;
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param addTo The list to add to.
+        */
+       public ListBuilder(List<E> addTo) {
+               this.list = addTo;
+       }
+
+       /**
+        * Builds the list.
+        *
+        * @return A list conforming to the settings on this builder.
+        */
+       public List<E> build() {
+               if (sparse) {
+                       if (list != null && list.isEmpty())
+                               list = null;
+               } else {
+                       if (list == null)
+                               list = new ArrayList<>(0);
+               }
+               if (list != null) {
+                       if (comparator != null)
+                               Collections.sort(list, comparator);
+                       if (unmodifiable)
+                               list = Collections.unmodifiableList(list);
+               }
+               return list;
+       }
+
+       /**
+        * When specified, the {@link #build()} method will return 
<jk>null</jk> if the list is empty.
+        *
+        * <p>
+        * Otherwise {@link #build()} will never return <jk>null</jk>.
+        *
+        * @return This object (for method chaining).
+        */
+       public ListBuilder<E> sparse() {
+               this.sparse = true;
+               return this;
+       }
+
+       /**
+        * When specified, {@link #build()} will return an unmodifiable list.
+        *
+        * @return This object (for method chaining).
+        */
+       public ListBuilder<E> unmodifiable() {
+               this.unmodifiable = true;
+               return this;
+       }
+
+       /**
+        * Forces the existing list to be copied instead of appended to.
+        *
+        * @return This object (for method chaining).
+        */
+       public ListBuilder<E> copy() {
+               if (list != null)
+                       list = new ArrayList<>(list);
+               return this;
+       }
+
+       /**
+        * Sorts the contents of the list.
+        *
+        * @return This object (for method chaining).
+        */
+       @SuppressWarnings("unchecked")
+       public ListBuilder<E> sorted() {
+               return sorted((Comparator<E>)Comparator.naturalOrder());
+       }
+
+       /**
+        * Sorts the contents of the list using the specified comparator.
+        *
+        * @param comparator The comparator to use for sorting.
+        * @return This object (for method chaining).
+        */
+       public ListBuilder<E> sorted(Comparator<E> comparator) {
+               this.comparator = comparator;
+               return this;
+       }
+
+       /**
+        * Appends the contents of the specified collection into this list.
+        *
+        * <p>
+        * This is a no-op if the value is <jk>null</jk>.
+        *
+        * @param value The collection to add to this list.
+        * @return This object (for method chaining).
+        */
+       public ListBuilder<E> addAll(Collection<E> value) {
+               if (value != null) {
+                       if (list == null)
+                               list = new LinkedList<>(value);
+                       else
+                               list.addAll(value);
+               }
+               return this;
+       }
+
+       /**
+        * Adds a single value to this list.
+        *
+        * @param value The value to add to this list.
+        * @return This object (for method chaining).
+        */
+       public ListBuilder<E> add(E value) {
+               if (list == null)
+                       list = new ArrayList<>();
+               list.add(value);
+               return this;
+       }
+
+       /**
+        * Adds multiple values to this list.
+        *
+        * @param values The values to add to this list.
+        * @return This object (for method chaining).
+        */
+       @SuppressWarnings("unchecked")
+       public ListBuilder<E> add(E...values) {
+               for (E v : values)
+                       add(v);
+               return this;
+       }
+
+       /**
+        * Adds entries to this list via JSON array strings.
+        *
+        * @param values The JSON array strings to parse and add to this list.
+        * @return This object (for method chaining).
+        */
+       public ListBuilder<E> addJson(String...values) {
+               return addAny((Object[])values);
+       }
+
+       /**
+        * Adds arbitrary values to this list.
+        *
+        * <p>
+        * Objects can be any of the following:
+        * <ul>
+        *      <li>The same type or convertible to the element type of this 
list.
+        *      <li>Collections or arrays of anything on this list.
+        *      <li>JSON array strings parsed and convertible to the element 
type of this list.
+        * </ul>
+        *
+        * @param values The values to add.
+        * @return This object (for method chaining).
+        */
+       @SuppressWarnings("unchecked")
+       public ListBuilder<E> addAny(Object...values) {
+               if (elementType == null)
+                       throw new RuntimeException("Unknown element type.  
Cannot use this method.");
+               try {
+                       if (values != null) {
+                               for (Object o : values) {
+                                       if (o != null) {
+                                               if (o instanceof Collection) {
+                                                       for (Object o2 : 
(Collection<?>)o)
+                                                               addAny(o2);
+                                               } else if 
(o.getClass().isArray()) {
+                                                       for (int i = 0; i < 
Array.getLength(o); i++)
+                                                               
addAny(Array.get(o, i));
+                                               } else if (isJsonArray(o, 
false)) {
+                                                       for (Object o2 : new 
OList(o.toString()))
+                                                               addAny(o2);
+                                               } else if 
(elementType.isInstance(o)) {
+                                                       add((E)o);
+                                               } else {
+                                                       add(toType(o, 
elementType, elementTypeArgs));
+                                               }
+                                       }
+                               }
+                       }
+               } catch (ParseException e) {
+                       throw new RuntimeException(e);
+               }
+               return this;
+       }
+}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/MapBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/MapBuilder.java
new file mode 100644
index 0000000..d27ddb4
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/MapBuilder.java
@@ -0,0 +1,222 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.internal;
+
+import static org.apache.juneau.internal.ConverterUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.collections.*;
+import org.apache.juneau.parser.*;
+
+/**
+ * Builder for maps.
+ *
+ * @param <K> Key type.
+ * @param <V> Value type.
+ */
+public class MapBuilder<K,V> {
+
+       private Map<K,V> map;
+       private boolean unmodifiable = false, sparse = false;
+       private Comparator<K> comparator = null;
+
+       private Class<K> keyType;
+       private Class<V> valueType;
+       private Type[] valueTypeArgs;
+
+       /**
+        * Constructor.
+        *
+        * @param keyType The key type.
+        * @param valueType The value type.
+        * @param valueTypeArgs The value type generic arguments if there are 
any.
+        */
+       public MapBuilder(Class<K> keyType, Class<V> valueType, 
Type...valueTypeArgs) {
+               this.keyType = keyType;
+               this.valueType = valueType;
+               this.valueTypeArgs = valueTypeArgs;
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param addTo The map to add to.
+        */
+       public MapBuilder(Map<K,V> addTo) {
+               this.map = addTo;
+       }
+
+       /**
+        * Builds the map.
+        *
+        * @return A map conforming to the settings on this builder.
+        */
+       public Map<K,V> build() {
+               if (sparse) {
+                       if (map != null && map.isEmpty())
+                               map = null;
+               } else {
+                       if (map == null)
+                               map = new LinkedHashMap<>();
+               }
+               if (map != null) {
+                       if (comparator != null) {
+                               Map<K,V> m2 = new TreeMap<>(comparator);
+                               m2.putAll(map);
+                               map = m2;
+                       }
+                       if (unmodifiable)
+                               map = Collections.unmodifiableMap(map);
+               }
+               return map;
+       }
+
+       /**
+        * When specified, the {@link #build()} method will return 
<jk>null</jk> if the map is empty.
+        *
+        * <p>
+        * Otherwise {@link #build()} will never return <jk>null</jk>.
+        *
+        * @return This object (for method chaining).
+        */
+       public MapBuilder<K,V> sparse() {
+               this.sparse = true;
+               return this;
+       }
+
+       /**
+        * When specified, {@link #build()} will return an unmodifiable map.
+        *
+        * @return This object (for method chaining).
+        */
+       public MapBuilder<K,V> unmodifiable() {
+               this.unmodifiable = true;
+               return this;
+       }
+
+       /**
+        * Forces the existing set to be copied instead of appended to.
+        *
+        * @return This object (for method chaining).
+        */
+       public MapBuilder<K,V> copy() {
+               if (map != null)
+                       map = new LinkedHashMap<>(map);
+               return this;
+       }
+
+       /**
+        * Converts the set into a {@link SortedMap}.
+        *
+        * @return This object (for method chaining).
+        */
+       @SuppressWarnings("unchecked")
+       public MapBuilder<K,V> sorted() {
+               return sorted((Comparator<K>)Comparator.naturalOrder());
+       }
+
+       /**
+        * Converts the set into a {@link SortedMap} using the specified 
comparator.
+        *
+        * @param comparator The comparator to use for sorting.
+        * @return This object (for method chaining).
+        */
+       public MapBuilder<K,V> sorted(Comparator<K> comparator) {
+               this.comparator = comparator;
+               return this;
+       }
+
+       /**
+        * Appends the contents of the specified map into this map.
+        *
+        * <p>
+        * This is a no-op if the value is <jk>null</jk>.
+        *
+        * @param value The map to add to this map.
+        * @return This object (for method chaining).
+        */
+       public MapBuilder<K,V> addAll(Map<K,V> value) {
+               if (value != null) {
+                       if (map == null)
+                               map = new LinkedHashMap<>(value);
+                       else
+                               map.putAll(value);
+               }
+               return this;
+       }
+
+       /**
+        * Adds a single entry to this map.
+        *
+        * @param key The map key.
+        * @param value The map value.
+        * @return This object (for method chaining).
+        */
+       public MapBuilder<K,V> add(K key, V value) {
+               if (map == null)
+                       map = new LinkedHashMap<>();
+               map.put(key, value);
+               return this;
+       }
+
+       /**
+        * Adds entries to this list via JSON object strings.
+        *
+        * @param values The JSON object strings to parse and add to this list.
+        * @return This object (for method chaining).
+        */
+       public MapBuilder<K,V> addJson(String...values) {
+               return addAny((Object[])values);
+       }
+
+       /**
+        * Adds arbitrary values to this list.
+        *
+        * <p>
+        * Objects can be any of the following:
+        * <ul>
+        *      <li>Maps of key/value types convertible to the key/value types 
of this map.
+        *      <li>JSON object strings parsed and convertible to the key/value 
types of this map.
+        * </ul>
+        *
+        * @param values The values to add.
+        * @return This object (for method chaining).
+        */
+       @SuppressWarnings("unchecked")
+       public MapBuilder<K,V> addAny(Object...values) {
+               if (keyType == null || valueType == null)
+                       throw new RuntimeException("Unknown key and value 
types.  Cannot use this method.");
+               try {
+                       for (Object o : values) {
+                               if (o != null) {
+                                       if (o instanceof Map) {
+                                               for (Map.Entry<Object,Object> e 
: ((Map<Object,Object>)o).entrySet())
+                                                       add(toType(e.getKey(), 
keyType), toType(e.getValue(), valueType, valueTypeArgs));
+                                       } else if (isJsonObject(o, false)) {
+                                               for (Map.Entry<String,Object> e 
: OMap.ofJson(o.toString()).entrySet())
+                                                       add(toType(e.getKey(), 
keyType), toType(e.getValue(), valueType, valueTypeArgs));
+                                       } else {
+                                               throw new 
BasicRuntimeException("Invalid object type {0} passed to addAny()", 
o.getClass().getName());
+                                       }
+                               }
+                       }
+               } catch (ParseException e) {
+                       throw new RuntimeException(e);
+               }
+               return this;
+       }
+}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/SetBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/SetBuilder.java
new file mode 100644
index 0000000..add89ca
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/SetBuilder.java
@@ -0,0 +1,237 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.internal;
+
+import static org.apache.juneau.internal.ConverterUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.parser.*;
+
+/**
+ * Builder for sets.
+ *
+ * @param <E> Element type.
+ */
+public class SetBuilder<E> {
+
+       private Set<E> set;
+       private boolean unmodifiable, sparse;
+       private Comparator<E> comparator;
+
+       private Class<E> elementType;
+       private Type[] elementTypeArgs;
+
+       /**
+        * Constructor.
+        *
+        * @param elementType The element type.
+        * @param elementTypeArgs The element type generic arguments if there 
are any.
+        */
+       public SetBuilder(Class<E> elementType, Type...elementTypeArgs) {
+               this.elementType = elementType;
+               this.elementTypeArgs = elementTypeArgs;
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param addTo The set to add to.
+        */
+       public SetBuilder(Set<E> addTo) {
+               this.set = addTo;
+       }
+
+       /**
+        * Builds the set.
+        *
+        * @return A set conforming to the settings on this builder.
+        */
+       public Set<E> build() {
+               if (sparse) {
+                       if (set != null && set.isEmpty())
+                               set = null;
+               } else {
+                       if (set == null)
+                               set = new LinkedHashSet<>(0);
+               }
+               if (set != null) {
+                       if (comparator != null) {
+                               Set<E> s = new TreeSet<>(comparator);
+                               s.addAll(set);
+                               set = s;
+                       }
+                       if (unmodifiable)
+                               set = Collections.unmodifiableSet(set);
+               }
+               return set;
+       }
+
+       /**
+        * When specified, the {@link #build()} method will return 
<jk>null</jk> if the set is empty.
+        *
+        * <p>
+        * Otherwise {@link #build()} will never return <jk>null</jk>.
+        *
+        * @return This object (for method chaining).
+        */
+       public SetBuilder<E> sparse() {
+               this.sparse = true;
+               return this;
+       }
+
+       /**
+        * When specified, {@link #build()} will return an unmodifiable set.
+        *
+        * @return This object (for method chaining).
+        */
+       public SetBuilder<E> unmodifiable() {
+               this.unmodifiable = true;
+               return this;
+       }
+
+       /**
+        * Forces the existing set to be copied instead of appended to.
+        *
+        * @return This object (for method chaining).
+        */
+       public SetBuilder<E> copy() {
+               if (set != null)
+                       set = new LinkedHashSet<>(set);
+               return this;
+       }
+
+       /**
+        * Converts the set into a {@link SortedSet}.
+        *
+        * @return This object (for method chaining).
+        */
+       @SuppressWarnings("unchecked")
+       public SetBuilder<E> sorted() {
+               return sorted((Comparator<E>)Comparator.naturalOrder());
+       }
+
+       /**
+        * Converts the set into a {@link SortedSet} using the specified 
comparator.
+        *
+        * @param comparator The comparator to use for sorting.
+        * @return This object (for method chaining).
+        */
+       public SetBuilder<E> sorted(Comparator<E> comparator) {
+               this.comparator = comparator;
+               return this;
+       }
+
+       /**
+        * Appends the contents of the specified collection into this set.
+        *
+        * <p>
+        * This is a no-op if the value is <jk>null</jk>.
+        *
+        * @param value The collection to add to this set.
+        * @return This object (for method chaining).
+        */
+       public SetBuilder<E> addAll(Collection<E> value) {
+               if (value != null) {
+                       if (set == null)
+                               set = new LinkedHashSet<>(value);
+                       else
+                               set.addAll(value);
+               }
+               return this;
+       }
+
+       /**
+        * Adds a single value to this set.
+        *
+        * @param value The value to add to this set.
+        * @return This object (for method chaining).
+        */
+       public SetBuilder<E> add(E value) {
+               if (set == null)
+                       set = new LinkedHashSet<>();
+               set.add(value);
+               return this;
+       }
+
+       /**
+        * Adds multiple values to this set.
+        *
+        * @param values The values to add to this set.
+        * @return This object (for method chaining).
+        */
+       @SuppressWarnings("unchecked")
+       public SetBuilder<E> add(E...values) {
+               for (E v : values)
+                       add(v);
+               return this;
+       }
+
+       /**
+        * Adds entries to this set via JSON array strings.
+        *
+        * @param values The JSON array strings to parse and add to this set.
+        * @return This object (for method chaining).
+        */
+       public SetBuilder<E> addJson(String...values) {
+               return addAny((Object[])values);
+       }
+
+       /**
+        * Adds arbitrary values to this set.
+        *
+        * <p>
+        * Objects can be any of the following:
+        * <ul>
+        *      <li>The same type or convertible to the element type of this 
set.
+        *      <li>Collections or arrays of anything on this set.
+        *      <li>JSON array strings parsed and convertible to the element 
type of this set.
+        * </ul>
+        *
+        * @param values The values to add.
+        * @return This object (for method chaining).
+        */
+       @SuppressWarnings("unchecked")
+       public SetBuilder<E> addAny(Object...values) {
+               if (elementType == null)
+                       throw new RuntimeException("Unknown element type.  
Cannot use this method.");
+               try {
+                       if (values != null) {
+                               for (Object o : values) {
+                                       if (o != null) {
+                                               if (o instanceof Collection) {
+                                                       for (Object o2 : 
(Collection<?>)o)
+                                                               addAny(o2);
+                                               } else if 
(o.getClass().isArray()) {
+                                                       for (int i = 0; i < 
Array.getLength(o); i++)
+                                                               
addAny(Array.get(o, i));
+                                               } else if (isJsonArray(o, 
false)) {
+                                                       for (Object o2 : new 
OList(o.toString()))
+                                                               addAny(o2);
+                                               } else if 
(elementType.isInstance(o)) {
+                                                       add((E)o);
+                                               } else {
+                                                       add(toType(o, 
elementType, elementTypeArgs));
+                                               }
+                                       }
+                               }
+                       }
+               } catch (ParseException e) {
+                       throw new RuntimeException(e);
+               }
+               return this;
+       }
+}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/ThrownStats.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/ThrownStats.java
index 2d54151..eb224e4 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/ThrownStats.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/ThrownStats.java
@@ -53,7 +53,7 @@ public class ThrownStats implements Cloneable {
                this.guid = new Random().nextLong();
                this.thrownClass = builder.throwable.getClass();
                this.firstMessage = builder.throwable.getMessage();
-               this.stackTrace = newUnmodifiableList(builder.stackTrace);
+               this.stackTrace = 
listBuilder(builder.stackTrace).copy().unmodifiable().build();
                this.causedBy = ofNullable(builder.causedBy);
                this.hash = builder.hash;
                this.count = new AtomicInteger(0);
@@ -69,7 +69,7 @@ public class ThrownStats implements Cloneable {
                this.guid = x.guid;
                this.thrownClass = x.thrownClass;
                this.firstMessage = x.firstMessage;
-               this.stackTrace = newUnmodifiableList(x.stackTrace);
+               this.stackTrace = 
listBuilder(x.stackTrace).copy().unmodifiable().build();
                this.causedBy = Optional.ofNullable(x.causedBy.isPresent() ? 
x.causedBy.get().clone() : null);
                this.hash = x.hash;
                this.count = new AtomicInteger(x.count.get());
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
index d5d4a8b..862ba2f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
@@ -14,7 +14,6 @@ package org.apache.juneau.reflect;
 
 import static org.apache.juneau.internal.StringUtils.*;
 import static org.apache.juneau.reflect.ReflectFlags.*;
-import static org.apache.juneau.internal.CollectionUtils.*;
 import static org.apache.juneau.internal.ObjectUtils.*;
 
 import java.lang.annotation.*;
@@ -2479,6 +2478,12 @@ public final class ClassInfo {
                }
        }
 
+       private static <T> List<T> addIfNotNull(List<T> l, T o) {
+               if (o != null)
+                       l.add(o);
+               return l;
+       }
+
        
//-----------------------------------------------------------------------------------------------------------------
        // Other
        
//-----------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index e5ec8ff..4887238 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -13,7 +13,6 @@
 package org.apache.juneau.rest;
 
 import static javax.servlet.http.HttpServletResponse.*;
-import static org.apache.juneau.internal.CollectionUtils.*;
 import static org.apache.juneau.internal.ObjectUtils.*;
 import static org.apache.juneau.internal.IOUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
@@ -51,6 +50,7 @@ import org.apache.juneau.http.*;
 import org.apache.juneau.http.annotation.Response;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.httppart.bean.*;
+import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
 import org.apache.juneau.marshall.*;
@@ -3526,9 +3526,9 @@ public class RestContext extends BeanContext {
                        uriRelativity = getProperty(REST_uriRelativity, 
UriRelativity.class, UriRelativity.RESOURCE);
 
                        allowBodyParam = ! 
getBooleanProperty(REST_disableAllowBodyParam);
-                       allowedHeaderParams = 
newUnmodifiableSortedCaseInsensitiveSet(getStringPropertyWithNone(REST_allowedHeaderParams,
 "Accept,Content-Type"));
-                       allowedMethodParams = 
newUnmodifiableSortedCaseInsensitiveSet(getStringPropertyWithNone(REST_allowedMethodParams,
 "HEAD,OPTIONS"));
-                       allowedMethodHeaders = 
newUnmodifiableSortedCaseInsensitiveSet(getStringPropertyWithNone(REST_allowedMethodHeaders,
 ""));
+                       allowedHeaderParams = 
newCaseInsensitiveSet(getStringPropertyWithNone(REST_allowedHeaderParams, 
"Accept,Content-Type"));
+                       allowedMethodParams = 
newCaseInsensitiveSet(getStringPropertyWithNone(REST_allowedMethodParams, 
"HEAD,OPTIONS"));
+                       allowedMethodHeaders = 
newCaseInsensitiveSet(getStringPropertyWithNone(REST_allowedMethodHeaders, ""));
                        renderResponseStackTraces = 
getBooleanProperty(REST_renderResponseStackTraces);
                        clientVersionHeader = 
getStringProperty(REST_clientVersionHeader, "X-Client-Version");
 
@@ -3580,6 +3580,19 @@ public class RestContext extends BeanContext {
                return new RestOperationInvoker(m, findHookMethodParams(m, 
getBeanFactory()), getMethodExecStats(m));
        }
 
+       private Set<String> newCaseInsensitiveSet(String value) {
+               Set<String> s = new 
TreeSet<String>(String.CASE_INSENSITIVE_ORDER) {
+                       private static final long serialVersionUID = 1L;
+                       @Override
+                       public boolean contains(Object v) {
+                               return v == null ? false : super.contains(v);
+                       }
+               };
+               for (String v : StringUtils.split(value))
+                       s.add(v);
+               return Collections.unmodifiableSet(s);
+       }
+
        /**
         * Instantiates the bean factory for this REST resource.
         *
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/dto/swagger/HeaderInfo_Test.java 
b/juneau-utest/src/test/java/org/apache/juneau/dto/swagger/HeaderInfo_Test.java
index 0fa39f4..0066e23 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/dto/swagger/HeaderInfo_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/dto/swagger/HeaderInfo_Test.java
@@ -308,7 +308,7 @@ public class HeaderInfo_Test {
                
assertObject(t._enum()).isType(Set.class).asJson().is("['foo','bar']");
 
                t._enum(new Object[0]);
-               assertObject(t._enum()).isType(Set.class).asJson().is("[]");
+               assertObject(t._enum()).isNull();
 
                t._enum((Collection<Object>)null);
                assertObject(t._enum()).isNull();
@@ -458,7 +458,7 @@ public class HeaderInfo_Test {
                
assertObject(t).asJson().is("{description:'d',type:'j',format:'g',items:{type:'h'},collectionFormat:'c','default':'a',maximum:123.0,exclusiveMaximum:true,minimum:123.0,exclusiveMinimum:true,maxLength:123,minLength:123,pattern:'i',maxItems:123,minItems:123,uniqueItems:true,'enum':['b'],multipleOf:123.0,'$ref':'ref',example:'e'}");
 
                assertObject(t.get("default", 
Object.class)).isType(StringBuilder.class).asString().is("a");
-               assertObject(t.get("enum", 
Object.class)).isType(Set.class).asString().is("['b']");
+               assertObject(t.get("enum", 
Object.class)).isType(Set.class).asJson().is("['b']");
                assertObject(t.get("collectionFormat", 
Object.class)).isType(String.class).is("c");
                assertObject(t.get("description", 
Object.class)).isType(String.class).is("d");
                assertObject(t.get("example", 
Object.class)).isType(StringBuilder.class).asString().is("e");
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/dto/swagger/Swagger_Test.java 
b/juneau-utest/src/test/java/org/apache/juneau/dto/swagger/Swagger_Test.java
index 4de8d32..96e8381 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/dto/swagger/Swagger_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/dto/swagger/Swagger_Test.java
@@ -178,7 +178,7 @@ public class Swagger_Test {
                
assertObject(t.paths()).isType(Map.class).asJson().is("{foo:{bar:{summary:'baz'}}}");
 
                t.paths(AMap.create());
-               assertObject(t.paths()).isType(Map.class).asJson().is("{}");
+               assertObject(t.paths()).isNull();
 
                t.paths((Map<String,OperationMap>)null);
                assertObject(t.paths()).isNull();
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java 
b/juneau-utest/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
deleted file mode 100755
index c9ac26e..0000000
--- 
a/juneau-utest/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-// 
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                
                                              *
-// *                                                                           
                                              *
-// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
-// *                                                                           
                                              *
-// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the 
License.                                              *
-// 
***************************************************************************************************************************
-package org.apache.juneau.utils;
-
-import static org.apache.juneau.internal.CollectionUtils.*;
-import static org.junit.Assert.*;
-import static org.junit.runners.MethodSorters.*;
-
-import java.util.*;
-
-import org.apache.commons.lang3.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class CollectionUtilsTest {
-
-       private String[] strings(String s) {
-               return StringUtils.split(s, ',');
-       }
-
-       @Test
-       public void testSortedCaseInsensitiveSet() {
-               Set<String> s = newSortedCaseInsensitiveSet("foo,Bar,BAZ");
-               for (String ss : strings("foo,Foo,FOO,bar,Bar,BAR,baz,Baz,BAZ"))
-                       assertTrue(s.contains(ss));
-               for (String ss : strings("qux"))
-                       assertFalse(s.contains(ss));
-       }
-
-       @Test
-       public void testSortedCaseInsensitiveSet_empty() {
-               Set<String> s = newSortedCaseInsensitiveSet("");
-               assertFalse(s.contains("foo"));
-               assertFalse(s.contains(""));
-               assertFalse(s.contains(null));
-       }
-
-       @Test
-       public void testSortedCaseInsensitiveSet_null() {
-               String ss = null;
-               Set<String> s = newSortedCaseInsensitiveSet(ss);
-               assertFalse(s.contains("foo"));
-               assertFalse(s.contains(""));
-               assertFalse(s.contains(null));
-       }
-
-       @Test
-       public void testSortedCaseInsensitiveSet_containsNull() {
-               Set<String> s = newSortedCaseInsensitiveSet(null, "foo");
-               assertTrue(s.contains("foo"));
-               assertFalse(s.contains(""));
-               assertFalse(s.contains(null));
-       }
-}

Reply via email to