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 859d899  RestClient tests
859d899 is described below

commit 859d8994b01d7b5c7158ca7270eae39ff6f0d666
Author: JamesBognar <james.bog...@salesforce.com>
AuthorDate: Mon Jun 22 11:59:10 2020 -0400

    RestClient tests
---
 .../org/apache/juneau/http/BasicNameValuePair.java |  38 +++-
 .../org/apache/juneau/http/NameValuePairable.java  |  28 +++
 .../org/apache/juneau/http/SerializedHeader.java   | 113 +---------
 .../juneau/http/SerializedHeaderBuilder.java       | 128 +++++++++++
 .../juneau/http/SerializedNameValuePair.java       | 116 +---------
 .../http/SerializedNameValuePairBuilder.java       | 138 ++++++++++++
 .../org/apache/juneau/http/header/BasicHeader.java |  40 ++++
 .../apache/juneau/rest/client2/RestClientTest.java |   2 +-
 .../org/apache/juneau/rest/client2/RestClient.java |  54 ++---
 .../juneau/rest/client2/RestClientBuilder.java     | 157 +++++++------
 .../apache/juneau/rest/client2/RestRequest.java    | 243 +++++++++++++++------
 11 files changed, 655 insertions(+), 402 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicNameValuePair.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicNameValuePair.java
index 952705e..be5601b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicNameValuePair.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicNameValuePair.java
@@ -14,14 +14,17 @@ package org.apache.juneau.http;
 
 import static org.apache.juneau.internal.StringUtils.*;
 
+import java.util.*;
 import java.util.function.*;
 
 import org.apache.http.*;
+import org.apache.juneau.*;
 import org.apache.juneau.http.header.*;
+import org.apache.juneau.reflect.*;
 
 /**
  * Subclass of {@link NameValuePair} for serializing POJOs as URL-encoded form 
post entries.
- * 
+ *
  * <p>
  * The value is serialized using {@link Object#toString()} at the point of 
reading.  This allows the value to be modified
  * periodically by overriding the method to return different values.
@@ -56,6 +59,39 @@ public class BasicNameValuePair implements NameValuePair, 
Headerable {
        }
 
        /**
+        * Utility method for converting an arbitrary object to a {@link 
NameValuePair}.
+        *
+        * @param o
+        *      The object to cast or convert to a {@link NameValuePair}.
+        * @return Either the same object cast as a {@link NameValuePair} or 
converted to a {@link NameValuePair}.
+        */
+       @SuppressWarnings("rawtypes")
+       public static NameValuePair cast(Object o) {
+               if (o instanceof NameValuePair)
+                       return (NameValuePair)o;
+               if (o instanceof NameValuePairable)
+                       return ((NameValuePairable)o).asNameValuePair();
+               if (o instanceof Headerable)
+                       return ((Headerable)o).asHeader();
+               if (o instanceof Map.Entry) {
+                       Map.Entry e = (Map.Entry)o;
+                       return BasicNameValuePair.of(stringify(e.getKey()), 
e.getValue());
+               }
+               throw new BasicRuntimeException("Object of type {0} could not 
be converted to a NameValuePair.", o == null ? null : o.getClass().getName());
+       }
+
+       /**
+        * Returns <jk>true</jk> if the {@link #cast(Object)} method can be 
used on the specified object.
+        *
+        * @param o The object to check.
+        * @return <jk>true</jk> if the {@link #cast(Object)} method can be 
used on the specified object.
+        */
+       public static boolean canCast(Object o) {
+               ClassInfo ci = ClassInfo.of(o);
+               return ci != null && ci.isChildOfAny(Headerable.class, 
NameValuePair.class, NameValuePairable.class, Map.Entry.class);
+       }
+
+       /**
         * Constructor.
         *
         * @param name The parameter name.
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/NameValuePairable.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/NameValuePairable.java
new file mode 100644
index 0000000..6c39b11
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/NameValuePairable.java
@@ -0,0 +1,28 @@
+// 
***************************************************************************************************************************
+// * 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.http;
+
+import org.apache.http.*;
+
+/**
+ * Identifies a class that can be converted to a {@link NameValuePair} object.
+ */
+public interface NameValuePairable {
+
+       /**
+        * Convert the object to a {@link NameValuePair}.
+        *
+        * @return The object converted to a {@link NameValuePair}.
+        */
+       NameValuePair asNameValuePair();
+}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHeader.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHeader.java
index 032b184..ac68273 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHeader.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHeader.java
@@ -36,7 +36,7 @@ import org.apache.juneau.urlencoding.*;
  *     request.setEntity(<jk>new</jk> UrlEncodedFormEntity(params));
  * </p>
  */
-public class SerializedHeader extends BasicStringHeader {
+public class SerializedHeader extends BasicStringHeader implements 
NameValuePairable {
        private static final long serialVersionUID = 1L;
 
        private Object value;
@@ -49,8 +49,8 @@ public class SerializedHeader extends BasicStringHeader {
         *
         * @return A new builder for this object.
         */
-       public static Builder create() {
-               return new Builder();
+       public static SerializedHeaderBuilder create() {
+               return new SerializedHeaderBuilder();
        }
 
        /**
@@ -76,113 +76,13 @@ public class SerializedHeader extends BasicStringHeader {
                this.skipIfEmpty = skipIfEmpty;
        }
 
-       SerializedHeader(Builder b) {
+       SerializedHeader(SerializedHeaderBuilder b) {
                super(b.name, null);
                this.value = b.value;
                this.serializer = b.serializer;
                this.schema = b.schema == null ? HttpPartSchema.DEFAULT : 
b.schema;
        }
 
-       /**
-        * Builder for {@link SerializedHeader} objects.
-        */
-       public static class Builder {
-               String name;
-               Object value;
-               HttpPartSerializerSession serializer;
-               HttpPartSchema schema;
-
-               /**
-                * Sets the parameter name.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder name(String value) {
-                       this.name = value;
-                       return this;
-               }
-
-               /**
-                * Sets the POJO to serialize to the parameter value.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder value(Object value) {
-                       this.value = value;
-                       return this;
-               }
-
-               /**
-                * Sets the POJO supplier to serialize to the parameter value.
-                * <p>
-                * Value is re-evaluated on each call to {@link #getValue()}.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder value(Supplier<?> value) {
-                       this.value = value;
-                       return this;
-               }
-
-               /**
-                * Sets the serializer to use for serializing the value to a 
string value.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder serializer(HttpPartSerializer value) {
-                       if (value != null)
-                               return 
serializer(value.createPartSession(null));
-                       return this;
-               }
-
-               /**
-                * Sets the serializer to use for serializing the value to a 
string value.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder serializer(HttpPartSerializerSession value) {
-                       return serializer(value, true);
-               }
-
-               /**
-                * Sets the serializer to use for serializing the value to a 
string value.
-                *
-                * @param value The new value for this property.
-                * @param overwrite If <jk>true</jk>, overwrites the existing 
value if the old value is <jk>null</jk>.
-                * @return This object (for method chaining).
-                */
-               public Builder serializer(HttpPartSerializerSession value, 
boolean overwrite) {
-                       if (overwrite || serializer == null)
-                               this.serializer = value;
-                       return this;
-               }
-
-               /**
-                * Sets the schema object that defines the format of the output.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder schema(HttpPartSchema value) {
-                       this.schema = value;
-                       return this;
-               }
-
-               /**
-                * Creates the new {@link SerializedHeader}
-                *
-                * @return The new {@link SerializedHeader}
-                */
-               public SerializedHeader build() {
-                       return new SerializedHeader(this);
-               }
-       }
-
        @Override /* NameValuePair */
        public String getValue() {
                try {
@@ -202,4 +102,9 @@ public class SerializedHeader extends BasicStringHeader {
                        throw new BasicRuntimeException(e, "Serialization error 
on request {0} parameter ''{1}''", HttpPartType.HEADER, getName());
                }
        }
+
+       @Override /* NameValuePairable */
+       public NameValuePair asNameValuePair() {
+               return new SerializedNameValuePair(getName(), value, 
HttpPartType.HEADER, serializer, schema, skipIfEmpty);
+       }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHeaderBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHeaderBuilder.java
new file mode 100644
index 0000000..473ed9a
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHeaderBuilder.java
@@ -0,0 +1,128 @@
+// 
***************************************************************************************************************************
+// * 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.http;
+
+import java.util.function.*;
+
+import org.apache.http.*;
+import org.apache.juneau.httppart.*;
+
+/**
+ * Builder for {@link SerializedHeader} objects.
+ */
+public class SerializedHeaderBuilder implements Headerable, NameValuePairable {
+       String name;
+       Object value;
+       HttpPartSerializerSession serializer;
+       HttpPartSchema schema;
+
+       /**
+        * Sets the parameter name.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedHeaderBuilder name(String value) {
+               this.name = value;
+               return this;
+       }
+
+       /**
+        * Sets the POJO to serialize to the parameter value.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedHeaderBuilder value(Object value) {
+               this.value = value;
+               return this;
+       }
+
+       /**
+        * Sets the POJO supplier to serialize to the parameter value.
+        * <p>
+        * Value is re-evaluated on each call to {@link Header#getValue()}.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedHeaderBuilder value(Supplier<?> value) {
+               this.value = value;
+               return this;
+       }
+
+       /**
+        * Sets the serializer to use for serializing the value to a string 
value.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedHeaderBuilder serializer(HttpPartSerializer value) {
+               if (value != null)
+                       return serializer(value.createPartSession(null));
+               return this;
+       }
+
+       /**
+        * Sets the serializer to use for serializing the value to a string 
value.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedHeaderBuilder serializer(HttpPartSerializerSession 
value) {
+               return serializer(value, true);
+       }
+
+       /**
+        * Sets the serializer to use for serializing the value to a string 
value.
+        *
+        * @param value The new value for this property.
+        * @param overwrite If <jk>true</jk>, overwrites the existing value if 
the old value is <jk>null</jk>.
+        * @return This object (for method chaining).
+        */
+       public SerializedHeaderBuilder serializer(HttpPartSerializerSession 
value, boolean overwrite) {
+               if (overwrite || serializer == null)
+                       this.serializer = value;
+               return this;
+       }
+
+       /**
+        * Sets the schema object that defines the format of the output.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedHeaderBuilder schema(HttpPartSchema value) {
+               this.schema = value;
+               return this;
+       }
+
+       /**
+        * Creates the new {@link SerializedHeader}
+        *
+        * @return The new {@link SerializedHeader}
+        */
+       public SerializedHeader build() {
+               return new SerializedHeader(this);
+       }
+
+       @Override /* Headerable */
+       public Header asHeader() {
+               return build();
+       }
+
+       @Override /* Headerable */
+       public Header asNameValuePair() {
+               return build();
+       }
+}
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedNameValuePair.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedNameValuePair.java
index 519471e..71da93f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedNameValuePair.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedNameValuePair.java
@@ -48,8 +48,8 @@ public class SerializedNameValuePair implements 
NameValuePair, Headerable {
         *
         * @return A new builder for this object.
         */
-       public static Builder create() {
-               return new Builder();
+       public static SerializedNameValuePairBuilder create() {
+               return new SerializedNameValuePairBuilder();
        }
 
        /**
@@ -81,7 +81,7 @@ public class SerializedNameValuePair implements 
NameValuePair, Headerable {
                return new SerializedHeader(name, value, serializer, schema, 
skipIfEmpty);
        }
 
-       SerializedNameValuePair(Builder b) {
+       SerializedNameValuePair(SerializedNameValuePairBuilder b) {
                this.name = b.name;
                this.value = b.value;
                this.type = b.type;
@@ -89,116 +89,6 @@ public class SerializedNameValuePair implements 
NameValuePair, Headerable {
                this.schema = b.schema == null ? HttpPartSchema.DEFAULT : 
b.schema;
        }
 
-       /**
-        * Builder for {@link SerializedNameValuePair} objects.
-        */
-       public static class Builder {
-               String name;
-               Object value;
-               HttpPartType type;
-               HttpPartSerializerSession serializer;
-               HttpPartSchema schema;
-
-               /**
-                * Sets the parameter name.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder name(String value) {
-                       this.name = value;
-                       return this;
-               }
-
-               /**
-                * Sets the POJO to serialize to the parameter value.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder value(Object value) {
-                       this.value = value;
-                       return this;
-               }
-
-               /**
-                * Sets the POJO to serialize to the parameter value.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder value(Supplier<Object> value) {
-                       this.value = value;
-                       return this;
-               }
-
-               /**
-                * Sets the HTTP part type.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder type(HttpPartType value) {
-                       this.type = value;
-                       return this;
-               }
-
-               /**
-                * Sets the serializer to use for serializing the value to a 
string value.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder serializer(HttpPartSerializer value) {
-                       if (value != null)
-                               return 
serializer(value.createPartSession(null));
-                       return this;
-               }
-
-               /**
-                * Sets the serializer to use for serializing the value to a 
string value.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder serializer(HttpPartSerializerSession value) {
-                       return serializer(value, true);
-               }
-
-               /**
-                * Sets the serializer to use for serializing the value to a 
string value.
-                *
-                * @param value The new value for this property.
-                * @param overwrite If <jk>true</jk>, overwrites the existing 
value if the old value is <jk>null</jk>.
-                * @return This object (for method chaining).
-                */
-               public Builder serializer(HttpPartSerializerSession value, 
boolean overwrite) {
-                       if (overwrite || serializer == null)
-                               this.serializer = value;
-                       return this;
-               }
-
-               /**
-                * Sets the schema object that defines the format of the output.
-                *
-                * @param value The new value for this property.
-                * @return This object (for method chaining).
-                */
-               public Builder schema(HttpPartSchema value) {
-                       this.schema = value;
-                       return this;
-               }
-
-               /**
-                * Creates the new {@link SerializedNameValuePair}
-                *
-                * @return The new {@link SerializedNameValuePair}
-                */
-               public SerializedNameValuePair build() {
-                       return new SerializedNameValuePair(this);
-               }
-       }
-
        @Override /* NameValuePair */
        public String getName() {
                return name;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedNameValuePairBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedNameValuePairBuilder.java
new file mode 100644
index 0000000..f51a5da
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedNameValuePairBuilder.java
@@ -0,0 +1,138 @@
+// 
***************************************************************************************************************************
+// * 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.http;
+
+import java.util.function.*;
+
+import org.apache.http.*;
+import org.apache.juneau.httppart.*;
+
+/**
+ * Builder for {@link SerializedNameValuePair} objects.
+ */
+public class SerializedNameValuePairBuilder implements NameValuePairable, 
Headerable {
+       String name;
+       Object value;
+       HttpPartType type;
+       HttpPartSerializerSession serializer;
+       HttpPartSchema schema;
+
+       /**
+        * Sets the parameter name.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedNameValuePairBuilder name(String value) {
+               this.name = value;
+               return this;
+       }
+
+       /**
+        * Sets the POJO to serialize to the parameter value.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedNameValuePairBuilder value(Object value) {
+               this.value = value;
+               return this;
+       }
+
+       /**
+        * Sets the POJO to serialize to the parameter value.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedNameValuePairBuilder value(Supplier<Object> value) {
+               this.value = value;
+               return this;
+       }
+
+       /**
+        * Sets the HTTP part type.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedNameValuePairBuilder type(HttpPartType value) {
+               this.type = value;
+               return this;
+       }
+
+       /**
+        * Sets the serializer to use for serializing the value to a string 
value.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedNameValuePairBuilder serializer(HttpPartSerializer 
value) {
+               if (value != null)
+                       return serializer(value.createPartSession(null));
+               return this;
+       }
+
+       /**
+        * Sets the serializer to use for serializing the value to a string 
value.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedNameValuePairBuilder 
serializer(HttpPartSerializerSession value) {
+               return serializer(value, true);
+       }
+
+       /**
+        * Sets the serializer to use for serializing the value to a string 
value.
+        *
+        * @param value The new value for this property.
+        * @param overwrite If <jk>true</jk>, overwrites the existing value if 
the old value is <jk>null</jk>.
+        * @return This object (for method chaining).
+        */
+       public SerializedNameValuePairBuilder 
serializer(HttpPartSerializerSession value, boolean overwrite) {
+               if (overwrite || serializer == null)
+                       this.serializer = value;
+               return this;
+       }
+
+       /**
+        * Sets the schema object that defines the format of the output.
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        */
+       public SerializedNameValuePairBuilder schema(HttpPartSchema value) {
+               this.schema = value;
+               return this;
+       }
+
+       /**
+        * Creates the new {@link SerializedNameValuePair}
+        *
+        * @return The new {@link SerializedNameValuePair}
+        */
+       public SerializedNameValuePair build() {
+               return new SerializedNameValuePair(this);
+       }
+
+       @Override /* NameValuePairable */
+       public NameValuePair asNameValuePair() {
+               return build();
+       }
+
+       @Override /* Headerable */
+       public Header asHeader() {
+               return build().asHeader();
+       }
+}
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicHeader.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicHeader.java
index cbc1674..f5fb62f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicHeader.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/BasicHeader.java
@@ -15,11 +15,16 @@ package org.apache.juneau.http.header;
 import static org.apache.juneau.internal.StringUtils.*;
 
 import java.io.*;
+import java.util.*;
 import java.util.function.*;
 
 import org.apache.http.*;
 import org.apache.http.message.*;
+import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.header.BasicHeader;
+import org.apache.juneau.reflect.*;
 
 /**
  * Superclass of all headers defined in this package.
@@ -75,6 +80,41 @@ public class BasicHeader implements Header, Cloneable, 
Serializable {
        }
 
        /**
+        * Utility method for converting an arbitrary object to a {@link 
Header}.
+        *
+        * @param o
+        *      The object to cast or convert to a {@link Header}.
+        * @return Either the same object cast as a {@link Header} or converted 
to a {@link Header}.
+        */
+       @SuppressWarnings("rawtypes")
+       public static Header cast(Object o) {
+               if (o instanceof Header)
+                       return (Header)o;
+               if (o instanceof Headerable)
+                       return ((Headerable)o).asHeader();
+               if (o instanceof NameValuePair)
+                       return BasicHeader.of((NameValuePair)o);
+               if (o instanceof NameValuePairable)
+                       return 
BasicHeader.of(((NameValuePairable)o).asNameValuePair());
+               if (o instanceof Map.Entry) {
+                       Map.Entry e = (Map.Entry)o;
+                       return BasicHeader.of(stringify(e.getKey()), 
e.getValue());
+               }
+               throw new BasicRuntimeException("Object of type {0} could not 
be converted to a Header.", o == null ? null : o.getClass().getName());
+       }
+
+       /**
+        * Returns <jk>true</jk> if the {@link #cast(Object)} method can be 
used on the specified object.
+        *
+        * @param o The object to check.
+        * @return <jk>true</jk> if the {@link #cast(Object)} method can be 
used on the specified object.
+        */
+       public static boolean canCast(Object o) {
+               ClassInfo ci = ClassInfo.of(o);
+               return ci != null && ci.isChildOfAny(Header.class, 
Headerable.class, NameValuePair.class, NameValuePairable.class, 
Map.Entry.class);
+       }
+
+       /**
         * Constructor.
         *
         * @param name The parameter name.
diff --git 
a/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RestClientTest.java
 
b/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RestClientTest.java
index e1e17b4..a02e0bd 100644
--- 
a/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RestClientTest.java
+++ 
b/juneau-rest/juneau-rest-client-utest/src/test/java/org/apache/juneau/rest/client2/RestClientTest.java
@@ -6597,7 +6597,7 @@ public class RestClientTest {
                        ;
                        fail();
                } catch (RestCallException e) {
-                       assertEquals("Invalid type passed to path(): 
java.lang.String", e.getMessage());
+                       assertEquals("Invalid type passed to paths(): 
java.lang.String", e.getMessage());
                }
                try {
                        MockRestClient
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClient.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClient.java
index 1a76f8b..0b0a81f 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClient.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClient.java
@@ -55,8 +55,7 @@ import org.apache.juneau.assertions.*;
 import org.apache.juneau.collections.*;
 import org.apache.juneau.http.remote.RemoteReturn;
 import org.apache.juneau.http.*;
-import org.apache.juneau.http.BasicNameValuePair;
-import org.apache.juneau.http.header.BasicHeader;
+import org.apache.juneau.http.header.*;
 import org.apache.juneau.http.remote.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.httppart.bean.*;
@@ -1983,35 +1982,46 @@ public class RestClient extends BeanContext implements 
HttpClient, Closeable, Re
 
                HttpPartSerializerSession partSerializerSession = 
partSerializer.createPartSession(null);
 
-               Function<Object,Object> f = new Function<Object,Object>() {
+               Function<Object,Object> headerFunction = new 
Function<Object,Object>() {
                        @Override
                        public Object apply(Object x) {
-                               if (x instanceof 
SerializedNameValuePair.Builder)
-                                       return 
((SerializedNameValuePair.Builder)x).serializer(partSerializerSession, 
false).build();
-                               if (x instanceof SerializedHeader.Builder)
-                                       return 
((SerializedHeader.Builder)x).serializer(partSerializerSession, false).build();
-                               return x;
+                               if (x instanceof SerializedHeaderBuilder)
+                                       x = 
((SerializedHeaderBuilder)x).serializer(partSerializerSession, false).build();
+                               else if (x instanceof 
SerializedNameValuePairBuilder)
+                                       x = 
((SerializedNameValuePairBuilder)x).serializer(partSerializerSession, 
false).build();
+                               return BasicHeader.cast(x);
+                       }
+               };
+
+               Function<Object,Object> nameValuePairFunction = new 
Function<Object,Object>() {
+                       @Override
+                       public Object apply(Object x) {
+                               if (x instanceof SerializedNameValuePairBuilder)
+                                       x = 
((SerializedNameValuePairBuilder)x).serializer(partSerializerSession, 
false).build();
+                               if (x instanceof SerializedHeaderBuilder)
+                                       x = 
((SerializedHeaderBuilder)x).serializer(partSerializerSession, false).build();
+                               return BasicNameValuePair.cast(x);
                        }
                };
 
                this.headers = Collections.unmodifiableList(
                        getListProperty(RESTCLIENT_headers, Object.class)
                                .stream()
-                               .map(f)
+                               .map(headerFunction)
                                .collect(Collectors.toList())
                );
 
                this.query = Collections.unmodifiableList(
                        getListProperty(RESTCLIENT_query, Object.class)
                                .stream()
-                               .map(f)
+                               .map(nameValuePairFunction)
                                .collect(Collectors.toList())
                );
 
                this.formData = Collections.unmodifiableList(
                        getListProperty(RESTCLIENT_formData, Object.class)
                                .stream()
-                               .map(f)
+                               .map(nameValuePairFunction)
                                .collect(Collectors.toList())
                );
 
@@ -2849,13 +2859,13 @@ public class RestClient extends BeanContext implements 
HttpClient, Closeable, Re
                RestRequest req = createRequest(toURI(url, rootUrl), 
method.toUpperCase(Locale.ENGLISH), hasBody);
 
                for (Object o : headers)
-                       req.header(toHeader(o));
+                       req.header(BasicHeader.cast(o));
 
                for (Object o : query)
-                       req.query(toNameValuePair(o));
+                       req.query(BasicNameValuePair.cast(o));
 
                for (Object o : formData)
-                       req.formData(toNameValuePair(o));
+                       req.formData(BasicNameValuePair.cast(o));
 
                onInit(req);
 
@@ -3701,22 +3711,6 @@ public class RestClient extends BeanContext implements 
HttpClient, Closeable, Re
                return (T)o;
        }
 
-       private static Header toHeader(Object o) {
-               if (o instanceof Header)
-                       return (Header)o;
-               if (o instanceof Headerable)
-                       return ((Headerable)o).asHeader();
-               if (o instanceof NameValuePair)
-                       return BasicHeader.of((NameValuePair)o);
-               return null;
-       }
-
-       private static NameValuePair toNameValuePair(Object o) {
-               if (o instanceof NameValuePair)
-                       return (NameValuePair)o;
-               return null;
-       }
-
        @Override /* Context */
        public OMap toMap() {
                return super.toMap()
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClientBuilder.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClientBuilder.java
index f9effa6..6c55d2a 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClientBuilder.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestClientBuilder.java
@@ -48,11 +48,9 @@ import org.apache.http.conn.util.*;
 import org.apache.http.cookie.*;
 import org.apache.http.impl.client.*;
 import org.apache.http.impl.conn.*;
-import org.apache.juneau.http.header.BasicHeader;
 import org.apache.http.protocol.*;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.collections.*;
 import org.apache.juneau.html.*;
 import org.apache.juneau.http.*;
 import org.apache.juneau.http.header.*;
@@ -1298,47 +1296,42 @@ public class RestClientBuilder extends 
BeanContextBuilder {
         *              .build();
         * </p>
         *
-        * <p>
-        * Can be any of the following singleton types:
-        * <ul>
-        *      <li>{@link Header} (including any subclasses such as {@link 
Accept})
-        *      <li>{@link NameValuePair}
-        * </ul>
-        *
-        * <p>
-        * Can also be any of the following collection types:
-        * <ul>
-        *      <li>{@link Map} / {@link OMap}
+        * @param headers 
+        *      The header to set.
+        *      <br>Can be any of the following types:
         *      <ul>
-        *              <li>Values can be any POJO.
-        *              <li>Values converted to a string using the configured 
part serializer.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
+        *              <li>{@link Header} (including any subclasses such as 
{@link Accept})
+        *              <li>{@link NameValuePair}
+        *              <li>{@link Headerable}
+        *              <li>{@link NameValuePairable}
+        *              <li>{@link java.util.Map.Entry}  
+        *              <li>{@link NameValuePairs}
+        *              <li>{@link Map}
+        *              <ul>
+        *                      <li>Values can be any POJO.
+        *                      <li>Values converted to a string using the 
configured part serializer.
+        *                      <li>Values are converted to strings at runtime 
to allow them to be modified externally.
+        *              </ul>
+        *              <li>A collection or array of anything on this list.
         *      </ul>
-        *      <li>{@link NameValuePairs}
-        * </ul>
-        *
-        * @param headers The header to set.
         * @return This object (for method chaining).
         */
-       @SuppressWarnings("rawtypes")
        @FluentSetter
        public RestClientBuilder headers(Object...headers) {
                for (Object h : headers) {
-                       if (h instanceof Header || h instanceof 
SerializedHeader.Builder || h instanceof SerializedNameValuePair.Builder)
+                       if (BasicHeader.canCast(h)) {
                                appendTo(RESTCLIENT_headers, h);
-                       else if (h instanceof Headerable)
-                               appendTo(RESTCLIENT_headers, 
((Headerable)h).asHeader());
-                       else if (h instanceof NameValuePair) {
-                               NameValuePair p = (NameValuePair)h;
-                               appendTo(RESTCLIENT_headers, new 
BasicHeader(p.getName(), p.getValue()));
                        } else if (h instanceof Map) {
-                               for (Map.Entry e : toMap(h).entrySet())
+                               for (Map.Entry<Object,Object> e : 
toMap(h).entrySet())
                                        appendTo(RESTCLIENT_headers, 
serializedHeader(e.getKey(), e.getValue(), null, null));
-                       } else if (h instanceof NameValuePairs) {
-                               for (NameValuePair p : (NameValuePairs)h)
-                                       headers(p);
+                       } else if (h instanceof Collection) {
+                               for (Object o : (Collection<?>)h)
+                                       headers(o);
+                       } else if (h != null && h.getClass().isArray()) {
+                               for (int i = 0; i < Array.getLength(h); i++)
+                                       headers(Array.get(h, i));
                        } else if (h != null) {
-                               throw new RuntimeException("Invalid type passed 
to headers():  " + h.getClass().getName());
+                               throw new RuntimeException("Invalid type passed 
to headers():  " + className(h));
                        }
                }
                return this;
@@ -2053,42 +2046,41 @@ public class RestClientBuilder extends 
BeanContextBuilder {
         *              
.queries(BasicNameValuePair.<jsm>of</jsm>(<js>"foo"</js>, <js>"bar"</js>))
         *              .build();
         * </p>
-        *
-        * <p>
-        * Can be any of the following singleton types:
-        * <ul>
-        *      <li>{@link NameValuePair}
-        * </ul>
-        *
-        * <p>
-        * Can be any of the following collection types:
-        * <ul>
-        *      <li>{@link Map} / {@link OMap}
+        * 
+        * @param params 
+        *      The query parameters.
+        *      <br>Can be any of the following types:
         *      <ul>
-        *              <li>Values can be any POJO.
-        *              <li>Values converted to a string using the configured 
part serializer.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
+        *              <li>{@link NameValuePair}
+        *              <li>{@link NameValuePairable}
+        *              <li>{@link java.util.Map.Entry}  
+        *              <li>{@link NameValuePairs}
+        *              <li>{@link Map}
+        *              <ul>
+        *                      <li>Values can be any POJO.
+        *                      <li>Values converted to a string using the 
configured part serializer.
+        *                      <li>Values are converted to strings at runtime 
to allow them to be modified externally.
+        *              </ul>
+        *              <li>A collection or array of anything on this list.
         *      </ul>
-        *      <li>{@link NameValuePairs}
-        * </ul>
-
-        * @param params The query parameters.
         * @return This object (for method chaining).
         */
-       @SuppressWarnings("rawtypes")
        @FluentSetter
        public RestClientBuilder queries(Object...params) {
                for (Object p : params) {
-                       if (p instanceof NameValuePair || p instanceof 
SerializedNameValuePair.Builder) {
+                       if (BasicNameValuePair.canCast(p)) {
                                appendTo(RESTCLIENT_query, p);
                        } else if (p instanceof Map) {
-                               for (Map.Entry e : toMap(p).entrySet())
+                               for (Map.Entry<Object,Object> e : 
toMap(p).entrySet())
                                        appendTo(RESTCLIENT_query, 
serializedNameValuePair(e.getKey(), e.getValue(), QUERY, null, null));
-                       } else if (p instanceof NameValuePairs) {
-                               for (NameValuePair nvp : (NameValuePairs)p)
-                                       appendTo(RESTCLIENT_query, nvp);
+                       } else if (p instanceof Collection) {
+                               for (Object o : (Collection<?>)p)
+                                       queries(o);
+                       } else if (p != null && p.getClass().isArray()) {
+                               for (int i = 0; i < Array.getLength(p); i++)
+                                       queries(Array.get(p, i));
                        } else if (p != null) {
-                               throw new RuntimeException("Invalid type passed 
to query():  " + p.getClass().getName());
+                               throw new RuntimeException("Invalid type passed 
to query():  " + className(p));
                        }
                }
                return this;
@@ -2342,40 +2334,40 @@ public class RestClientBuilder extends 
BeanContextBuilder {
         *              .build();
         * </p>
         *
-        * <p>
-        * Can be any of the following singleton types:
-        * <ul>
-        *      <li>{@link NameValuePair}
-        * </ul>
-        *
-        * <p>
-        * Can be any of the following collection types:
-        * <ul>
-        *      <li>{@link Map} / {@link OMap}
+        * @param params 
+        *      The form-data parameters.
+        *      <br>Can be any of the following types:
         *      <ul>
-        *              <li>Values can be any POJO.
-        *              <li>Values converted to a string using the configured 
part serializer.
-        *              <li>Values are converted to strings at runtime to allow 
them to be modified externally.
+        *              <li>{@link NameValuePair}
+        *              <li>{@link NameValuePairable}
+        *              <li>{@link java.util.Map.Entry}  
+        *              <li>{@link NameValuePairs}
+        *              <li>{@link Map}
+        *              <ul>
+        *                      <li>Values can be any POJO.
+        *                      <li>Values converted to a string using the 
configured part serializer.
+        *                      <li>Values are converted to strings at runtime 
to allow them to be modified externally.
+        *              </ul>
+        *              <li>A collection or array of anything on this list.
         *      </ul>
-        *      <li>{@link NameValuePairs}
-        * </ul>
-        *
-        * @param params The form-data parameter.
         * @return This object (for method chaining).
         */
        @FluentSetter
        public RestClientBuilder formDatas(Object...params) {
                for (Object p : params) {
-                       if (p instanceof NameValuePair || p instanceof 
SerializedNameValuePair.Builder) {
+                       if (BasicNameValuePair.canCast(p)) {
                                appendTo(RESTCLIENT_formData, p);
                        } else if (p instanceof Map) {
                                for (Map.Entry<Object,Object> e : 
toMap(p).entrySet())
                                        appendTo(RESTCLIENT_formData, 
serializedNameValuePair(e.getKey(), e.getValue(), FORMDATA, null, null));
-                       } else if (p instanceof NameValuePairs) {
-                               for (NameValuePair nvp : (NameValuePairs)p)
-                                       appendTo(RESTCLIENT_formData, nvp);
+                       } else if (p instanceof Collection) {
+                               for (Object o : (Collection<?>)p)
+                                       formDatas(o);
+                       } else if (p != null && p.getClass().isArray()) {
+                               for (int i = 0; i < Array.getLength(p); i++)
+                                       formDatas(Array.get(p, i));
                        } else if (p != null) {
-                               throw new RuntimeException("Invalid type passed 
to formData():  " + p.getClass().getName());
+                               throw new RuntimeException("Invalid type passed 
to formData():  " + className(p));
                        }
                }
                return this;
@@ -5818,11 +5810,14 @@ public class RestClientBuilder extends 
BeanContextBuilder {
                return (Map<Object,Object>)o;
        }
 
-       private static SerializedNameValuePair.Builder 
serializedNameValuePair(Object key, Object value, HttpPartType type, 
HttpPartSerializer serializer, HttpPartSchema schema) {
+       private static SerializedNameValuePairBuilder 
serializedNameValuePair(Object key, Object value, HttpPartType type, 
HttpPartSerializer serializer, HttpPartSchema schema) {
                return 
SerializedNameValuePair.create().name(stringify(key)).value(value).type(type).serializer(serializer).schema(schema);
        }
 
-       private static SerializedHeader.Builder serializedHeader(Object key, 
Object value, HttpPartSerializer serializer, HttpPartSchema schema) {
+       private static SerializedHeaderBuilder serializedHeader(Object key, 
Object value, HttpPartSerializer serializer, HttpPartSchema schema) {
                return 
SerializedHeader.create().name(stringify(key)).value(value).serializer(serializer).schema(schema);
        }
+       private static String className(Object value) {
+               return value == null ? null : value.getClass().getName();
+       }
 }
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestRequest.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestRequest.java
index 08380bc..7db63b2 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestRequest.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestRequest.java
@@ -17,6 +17,7 @@ import static org.apache.juneau.AddFlag.*;
 import static org.apache.juneau.httppart.HttpPartType.*;
 
 import java.io.*;
+import java.lang.reflect.*;
 import java.net.*;
 import java.text.*;
 import java.util.*;
@@ -32,13 +33,13 @@ import org.apache.http.client.utils.*;
 import org.apache.http.concurrent.*;
 import org.apache.http.entity.*;
 import org.apache.http.entity.ContentType;
-import org.apache.juneau.http.header.BasicHeader;
 import org.apache.http.params.*;
 import org.apache.http.protocol.*;
 import org.apache.juneau.*;
 import org.apache.juneau.collections.*;
 import org.apache.juneau.html.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.http.header.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
@@ -945,23 +946,36 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         *              .run();
         * </p>
         *
-        * @param params The path parameters to set.
+        * @param params
+        *      The path parameters to set.
         *      <br>Can be any of the following types:
         *      <ul>
-        *              <li>{@link Map} / {@link OMap} / bean - Converted to 
key/value pairs using part serializer.
-        *              <li>{@link NameValuePair} / {@link NameValuePairs} - 
Converted to key/value pairs directly.
-        *      </ul>
+        *              <li>{@link NameValuePair}
+        *              <li>{@link NameValuePairable}
+        *              <li>{@link java.util.Map.Entry}
+        *              <li>{@link NameValuePairs}
+        *              <li>{@link Map}
+        *              <ul>
+        *                      <li>Values can be any POJO.
+        *                      <li>Values converted to a string using the 
configured part serializer.
+        *                      <li>Values are converted to strings at runtime 
to allow them to be modified externally.
+        *              </ul>
+        *              <li>A collection or array of anything on this list.
+        * </ul>
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
        @SuppressWarnings("rawtypes")
        public RestRequest paths(Object...params) throws RestCallException {
                for (Object o : params) {
-                       if (o instanceof NameValuePair) {
-                               innerPath((NameValuePair)o);
-                       } else if (o instanceof NameValuePairs) {
-                               for (NameValuePair p : (NameValuePairs)o)
-                                       innerPath(p);
+                       if (BasicNameValuePair.canCast(o)) {
+                               innerPath(BasicNameValuePair.cast(o));
+                       } else if (o instanceof Collection) {
+                               for (Object o2 : (Collection<?>)o)
+                                       innerPath(BasicNameValuePair.cast(o2));
+                       } else if (o != null && o.getClass().isArray()) {
+                               for (int i = 0; i < Array.getLength(o); i++)
+                                       
innerPath(BasicNameValuePair.cast(Array.get(o, i)));
                        } else if (o instanceof Map) {
                                for (Map.Entry e : toMap(o).entrySet())
                                        
innerPath(serializedNameValuePair(e.getKey(), e.getValue(), PATH, 
partSerializer, null, null));
@@ -969,7 +983,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                                for (Map.Entry<String,Object> e : 
toBeanMap(o).entrySet())
                                        
innerPath(serializedNameValuePair(e.getKey(), e.getValue(), PATH, 
partSerializer, null, null));
                        } else {
-                               throw new RestCallException("Invalid type 
passed to path(): " + o.getClass().getName());
+                               throw new RestCallException("Invalid type 
passed to paths(): " + className(o));
                        }
                }
                return this;
@@ -1013,9 +1027,14 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                if (! isMulti)
                        return innerPath(serializedNameValuePair(name, value, 
PATH, serializer, schema, null));
 
-               if (value instanceof NameValuePairs) {
-                       for (NameValuePair p : (NameValuePairs)value)
-                               innerPath(p);
+               if (BasicNameValuePair.canCast(value)) {
+                       innerPath(BasicNameValuePair.cast(value));
+               } else if (value instanceof Collection) {
+                       for (Object o : (Collection<?>)value)
+                               innerPath(BasicNameValuePair.cast(o));
+               } else if (value != null && value.getClass().isArray()) {
+                       for (int i = 0; i < Array.getLength(value); i++)
+                               
innerPath(BasicNameValuePair.cast(Array.get(value, i)));
                } else if (value instanceof Map) {
                        for (Map.Entry<Object,Object> p : 
toMap(value).entrySet())
                                innerPath(serializedNameValuePair(p.getKey(), 
p.getValue(), PATH, serializer, schema, null));
@@ -1215,12 +1234,22 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         *              .run();
         * </p>
         *
-        * @param params The parameters to set.
+        * @param params
+        *      The parameters to set.
         *      <br>Can be any of the following types:
         *      <ul>
-        *              <li>{@link Map} / {@link OMap} / bean - Converted to 
key/value pairs using part serializer.
-        *              <li>{@link NameValuePair} / {@link NameValuePairs} - 
Converted to key/value pairs directly.
-        *      </ul>
+        *              <li>{@link NameValuePair}
+        *              <li>{@link NameValuePairable}
+        *              <li>{@link java.util.Map.Entry}
+        *              <li>{@link NameValuePairs}
+        *              <li>{@link Map}
+        *              <ul>
+        *                      <li>Values can be any POJO.
+        *                      <li>Values converted to a string using the 
configured part serializer.
+        *                      <li>Values are converted to strings at runtime 
to allow them to be modified externally.
+        *              </ul>
+        *              <li>A collection or array of anything on this list.
+        * </ul>
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
@@ -1251,22 +1280,36 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         *              <li>{@link AddFlag#REPLACE REPLACE} - Delete any 
existing with same name and append to end.
         *              <li>{@link AddFlag#SKIP_IF_EMPTY} - Don't add if value 
is an empty string.
         *      </ul>
-        * @param params The parameters to set.
+        * @param params
+        *      The parameters to set.
         *      <br>Can be any of the following types:
         *      <ul>
-        *              <li>{@link Map} / {@link OMap} / bean - Converted to 
key/value pairs using part serializer.
-        *              <li>{@link NameValuePair} / {@link NameValuePairs} - 
Converted to key/value pairs directly.
-        *      </ul>
+        *              <li>{@link NameValuePair}
+        *              <li>{@link NameValuePairable}
+        *              <li>{@link java.util.Map.Entry}
+        *              <li>{@link NameValuePairs}
+        *              <li>{@link Map}
+        *              <ul>
+        *                      <li>Values can be any POJO.
+        *                      <li>Values converted to a string using the 
configured part serializer.
+        *                      <li>Values are converted to strings at runtime 
to allow them to be modified externally.
+        *              </ul>
+        *              <li>A collection or array of anything on this list.
+        * </ul>
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
        public RestRequest queries(EnumSet<AddFlag> flags, Object...params) 
throws RestCallException {
                List<NameValuePair> l = new ArrayList<>();
                for (Object o : params) {
-                       if (o instanceof NameValuePair) {
-                               l.add((NameValuePair)o);
-                       } else if (o instanceof NameValuePairs) {
-                               l.addAll((NameValuePairs)o);
+                       if (BasicNameValuePair.canCast(o)) {
+                               l.add(BasicNameValuePair.cast(o));
+                       } else if (o instanceof Collection) {
+                               for (Object o2 : (Collection<?>)o)
+                                       l.add(BasicNameValuePair.cast(o2));
+                       } else if (o != null && o.getClass().isArray()) {
+                               for (int i = 0; i < Array.getLength(o); i++)
+                                       
l.add(BasicNameValuePair.cast(Array.get(o, i)));
                        } else if (o instanceof Map) {
                                for (Map.Entry<Object,Object> e : 
toMap(o).entrySet())
                                        
l.add(serializedNameValuePair(e.getKey(), e.getValue(), QUERY, partSerializer, 
null, null));
@@ -1274,7 +1317,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                                for (Map.Entry<String,Object> e : 
toBeanMap(o).entrySet())
                                        
l.add(serializedNameValuePair(e.getKey(), e.getValue(), QUERY, partSerializer, 
null, null));
                        } else {
-                               throw new RestCallException("Invalid type 
passed to queries(): " + o.getClass().getName());
+                               throw new RestCallException("Invalid type 
passed to queries(): " + className(o));
                        }
                }
                return innerQuery(flags, l);
@@ -1361,8 +1404,14 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
 
                List<NameValuePair> l = AList.of();
 
-               if (value instanceof NameValuePairs) {
-                       l.addAll((NameValuePairs)value);
+               if (BasicNameValuePair.canCast(value)) {
+                       l.add(BasicNameValuePair.cast(value));
+               } else if (value instanceof Collection) {
+                       for (Object o : (Collection<?>)value)
+                               l.add(BasicNameValuePair.cast(o));
+               } else if (value != null && value.getClass().isArray()) {
+                       for (int i = 0; i < Array.getLength(value); i++)
+                               l.add(BasicNameValuePair.cast(Array.get(value, 
i)));
                } else if (value instanceof Map) {
                        for (Map.Entry<Object,Object> e : 
toMap(value).entrySet())
                                l.add(serializedNameValuePair(e.getKey(), 
e.getValue(), QUERY, serializer, schema, flags));
@@ -1577,12 +1626,22 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         *              .run();
         * </p>
         *
-        * @param params The parameters to set.
+        * @param params
+        *      The parameters to set.
         *      <br>Can be any of the following types:
         *      <ul>
-        *              <li>{@link Map} / {@link OMap} / bean - Converted to 
key/value pairs using part serializer.
-        *              <li>{@link NameValuePair} / {@link NameValuePairs} - 
Converted to key/value pairs directly.
-        *      </ul>
+        *              <li>{@link NameValuePair}
+        *              <li>{@link NameValuePairable}
+        *              <li>{@link java.util.Map.Entry}
+        *              <li>{@link NameValuePairs}
+        *              <li>{@link Map}
+        *              <ul>
+        *                      <li>Values can be any POJO.
+        *                      <li>Values converted to a string using the 
configured part serializer.
+        *                      <li>Values are converted to strings at runtime 
to allow them to be modified externally.
+        *              </ul>
+        *              <li>A collection or array of anything on this list.
+        * </ul>
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
@@ -1613,22 +1672,36 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         *              <li>{@link AddFlag#REPLACE REPLACE} - Delete any 
existing with same name and append to end.
         *              <li>{@link AddFlag#SKIP_IF_EMPTY} - Don't add if value 
is an empty string.
         *      </ul>
-        * @param params The parameters to set.
+        * @param params
+        *      The parameters to set.
         *      <br>Can be any of the following types:
         *      <ul>
-        *              <li>{@link Map} / {@link OMap} / bean - Converted to 
key/value pairs using part serializer.
-        *              <li>{@link NameValuePair} / {@link NameValuePairs} - 
Converted to key/value pairs directly.
-        *      </ul>
+        *              <li>{@link NameValuePair}
+        *              <li>{@link NameValuePairable}
+        *              <li>{@link java.util.Map.Entry}
+        *              <li>{@link NameValuePairs}
+        *              <li>{@link Map}
+        *              <ul>
+        *                      <li>Values can be any POJO.
+        *                      <li>Values converted to a string using the 
configured part serializer.
+        *                      <li>Values are converted to strings at runtime 
to allow them to be modified externally.
+        *              </ul>
+        *              <li>A collection or array of anything on this list.
+        * </ul>
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
        public RestRequest formDatas(EnumSet<AddFlag> flags, Object...params) 
throws RestCallException {
                List<NameValuePair> l = new ArrayList<>();
                for (Object o : params) {
-                       if (o instanceof NameValuePair) {
-                               l.add((NameValuePair)o);
-                       } else if (o instanceof NameValuePairs) {
-                               l.addAll((NameValuePairs)o);
+                       if (BasicNameValuePair.canCast(o)) {
+                               l.add(BasicNameValuePair.cast(o));
+                       } else if (o instanceof Collection) {
+                               for (Object o2 : (Collection<?>)o)
+                                       l.add(BasicNameValuePair.cast(o2));
+                       } else if (o != null && o.getClass().isArray()) {
+                               for (int i = 0; i < Array.getLength(o); i++)
+                                       
l.add(BasicNameValuePair.cast(Array.get(o, i)));
                        } else if (o instanceof Map) {
                                for (Map.Entry<Object,Object> e : 
toMap(o).entrySet())
                                        
l.add(serializedNameValuePair(e.getKey(), e.getValue(), FORMDATA, 
partSerializer, null, flags));
@@ -1636,7 +1709,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                                for (Map.Entry<String,Object> e : 
toBeanMap(o).entrySet())
                                        
l.add(serializedNameValuePair(e.getKey(), e.getValue(), FORMDATA, 
partSerializer, null, flags));
                        } else {
-                               throw new RestCallException("Invalid type 
passed to formDatas(): " + o.getClass().getName());
+                               throw new RestCallException("Invalid type 
passed to formDatas(): " + className(o));
                        }
                }
                return innerFormData(flags, l);
@@ -1734,8 +1807,14 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
 
                List<NameValuePair> l = AList.of();
 
-               if (value instanceof NameValuePairs) {
-                       l.addAll((NameValuePairs)value);
+               if (BasicNameValuePair.canCast(value)) {
+                       l.add(BasicNameValuePair.cast(value));
+               } else if (value instanceof Collection) {
+                       for (Object o : (Collection<?>)value)
+                               l.add(BasicNameValuePair.cast(o));
+               } else if (value != null && value.getClass().isArray()) {
+                       for (int i = 0; i < Array.getLength(value); i++)
+                               l.add(BasicNameValuePair.cast(Array.get(value, 
i)));
                } else if (value instanceof Map) {
                        for (Map.Entry<Object,Object> e : 
toMap(value).entrySet())
                                l.add(serializedNameValuePair(e.getKey(), 
e.getValue(), FORMDATA, serializer, schema, flags));
@@ -2077,12 +2156,24 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         *              .run();
         * </p>
         *
-        * @param headers The headers to set.
+        * @param headers
+        *      The headers to set.
         *      <br>Can be any of the following types:
         *      <ul>
-        *              <li>{@link Map} / {@link OMap} / bean - Converted to 
key/value pairs using part serializer.
-        *              <li>{@link Header} / {@link NameValuePair} / {@link 
NameValuePairs} - Converted to key/value pairs directly.
-        *      </ul>
+        *              <li>{@link Header} (including any subclasses such as 
{@link Accept})
+        *              <li>{@link NameValuePair}
+        *              <li>{@link Headerable}
+        *              <li>{@link NameValuePairable}
+        *              <li>{@link java.util.Map.Entry}
+        *              <li>{@link NameValuePairs}
+        *              <li>{@link Map}
+        *              <ul>
+        *                      <li>Values can be any POJO.
+        *                      <li>Values converted to a string using the 
configured part serializer.
+        *                      <li>Values are converted to strings at runtime 
to allow them to be modified externally.
+        *              </ul>
+        *              <li>A collection or array of anything on this list.
+        * </ul>
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
@@ -2113,23 +2204,38 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         *              <li>{@link AddFlag#REPLACE REPLACE} - Delete any 
existing with same name and append to end.
         *              <li>{@link AddFlag#SKIP_IF_EMPTY} - Don't add if value 
is an empty string.
         *      </ul>
-        * @param headers The headers to set.
+        * @param headers
+        *      The headers to set.
         *      <br>Can be any of the following types:
         *      <ul>
-        *              <li>{@link Map} / {@link OMap} / bean - Converted to 
key/value pairs using part serializer.
-        *              <li>{@link Header} / {@link NameValuePair} / {@link 
NameValuePairs} - Converted to key/value pairs directly.
-        *      </ul>
+        *              <li>{@link Header} (including any subclasses such as 
{@link Accept})
+        *              <li>{@link NameValuePair}
+        *              <li>{@link Headerable}
+        *              <li>{@link NameValuePairable}
+        *              <li>{@link java.util.Map.Entry}
+        *              <li>{@link NameValuePairs}
+        *              <li>{@link Map}
+        *              <ul>
+        *                      <li>Values can be any POJO.
+        *                      <li>Values converted to a string using the 
configured part serializer.
+        *                      <li>Values are converted to strings at runtime 
to allow them to be modified externally.
+        *              </ul>
+        *              <li>A collection or array of anything on this list.
+        * </ul>
         * @return This object (for method chaining).
         * @throws RestCallException Invalid input.
         */
        public RestRequest headers(EnumSet<AddFlag> flags, Object...headers) 
throws RestCallException {
                List<Header> l = new ArrayList<>();
                for (Object o : headers) {
-                       if (o instanceof Header || o instanceof NameValuePair) {
-                               l.add(toHeader(o));
-                       } else if (o instanceof NameValuePairs) {
-                               for (NameValuePair p : (NameValuePairs)o)
-                                       l.add(toHeader(p));
+                       if (BasicHeader.canCast(o)) {
+                               l.add(BasicHeader.cast(o));
+                       } else if (o instanceof Collection) {
+                               for (Object o2 : (Collection<?>)o)
+                                       l.add(BasicHeader.cast(o2));
+                       } else if (o != null && o.getClass().isArray()) {
+                               for (int i = 0; i < Array.getLength(o); i++)
+                                       l.add(BasicHeader.cast(Array.get(o, 
i)));
                        } else if (o instanceof Map) {
                                for (Map.Entry<Object,Object> e : 
toMap(o).entrySet())
                                        l.add(serializedHeader(e.getKey(), 
e.getValue(), partSerializer, null, flags));
@@ -2183,11 +2289,14 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
 
                List<Header> l = AList.of();
 
-               if (value instanceof Headerable) {
-                       l.add(((Headerable)value).asHeader());
-               } else if (value instanceof NameValuePairs) {
-                       for (NameValuePair p : (NameValuePairs)value)
-                               l.add(toHeader(p));
+               if (BasicHeader.canCast(value)) {
+                       l.add(BasicHeader.cast(value));
+               } else if (value instanceof Collection) {
+                       for (Object o : (Collection<?>)value)
+                               l.add(BasicHeader.cast(o));
+               } else if (value != null && value.getClass().isArray()) {
+                       for (int i = 0; i < Array.getLength(value); i++)
+                               l.add(BasicHeader.cast(Array.get(value, i)));
                } else if (value instanceof Map) {
                        for (Map.Entry<Object,Object> e : 
toMap(value).entrySet())
                                l.add(serializedHeader(e.getKey(), 
e.getValue(), serializer, schema, flags));
@@ -3323,16 +3432,6 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                return new SerializedHeader(stringify(key), value, serializer, 
schema, flags == null ? false : flags.contains(SKIP_IF_EMPTY));
        }
 
-       private static Header toHeader(Object o) {
-               if (o instanceof Header)
-                       return (Header)o;
-               if (o instanceof Headerable)
-                       return ((Headerable)o).asHeader();
-               if (o instanceof NameValuePair)
-                       return BasicHeader.of((NameValuePair)o);
-               throw new BasicRuntimeException("Object cannot be converted to 
a header: {0}", o == null ? null : o.getClass().getName());
-       }
-
        private static String className(Object value) {
                return value == null ? null : value.getClass().getName();
        }

Reply via email to