New Accept/AcceptEncoding/ContentType classes.

Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/c3609d05
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/c3609d05
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/c3609d05

Branch: refs/heads/master
Commit: c3609d0518c07d1e96b62dee42eda40050a9fe02
Parents: 2ebf5ca
Author: JamesBognar <[email protected]>
Authored: Mon May 1 21:11:38 2017 -0400
Committer: JamesBognar <[email protected]>
Committed: Mon May 1 21:11:38 2017 -0400

----------------------------------------------------------------------
 .../java/org/apache/juneau/jena/RdfParser.java  |   1 +
 .../apache/juneau/jena/RdfParserBuilder.java    |   1 +
 .../apache/juneau/jena/RdfParserSession.java    |   1 +
 .../org/apache/juneau/jena/RdfSerializer.java   |   1 +
 .../juneau/jena/RdfSerializerBuilder.java       |   1 +
 .../juneau/jena/RdfSerializerSession.java       |   1 +
 .../java/org/apache/juneau/MediaRangeTest.java  |  65 ----
 .../test/java/org/apache/juneau/TestUtils.java  |  24 +-
 .../juneau/encoders/EncoderGroupTest.java       | 116 +++++++
 .../juneau/https/AcceptExtensionsTest.java      | 118 +++++++
 .../org/apache/juneau/https/AcceptTest.java     | 128 ++++++++
 .../org/apache/juneau/https/MediaRangeTest.java |  66 ++++
 .../apache/juneau/parser/ParserGroupTest.java   | 125 ++++++++
 .../juneau/serializer/SerializerGroupTest.java  | 166 ++++++++++
 .../juneau/utils/CollectionUtilsTest.java       |   4 +-
 .../apache/juneau/utils/StringUtilsTest.java    |  17 +
 .../java/org/apache/juneau/BeanContext.java     |   1 +
 .../java/org/apache/juneau/BeanSession.java     |   1 +
 .../org/apache/juneau/CoreObjectBuilder.java    |   1 +
 .../main/java/org/apache/juneau/MediaRange.java | 321 -------------------
 .../main/java/org/apache/juneau/MediaType.java  | 158 ---------
 .../main/java/org/apache/juneau/Streamable.java |   2 +
 .../main/java/org/apache/juneau/Writable.java   |   2 +
 .../org/apache/juneau/csv/CsvParserBuilder.java |   1 +
 .../org/apache/juneau/csv/CsvParserSession.java |   1 +
 .../apache/juneau/csv/CsvSerializerBuilder.java |   1 +
 .../apache/juneau/csv/CsvSerializerSession.java |   1 +
 .../apache/juneau/dto/swagger/Operation.java    |   2 +-
 .../org/apache/juneau/dto/swagger/Swagger.java  |   2 +-
 .../apache/juneau/encoders/EncoderGroup.java    |  82 ++---
 .../juneau/encoders/EncoderGroupBuilder.java    |  16 +-
 .../apache/juneau/encoders/EncoderMatch.java    |  10 +-
 .../apache/juneau/html/HtmlDocSerializer.java   |   1 +
 .../juneau/html/HtmlDocSerializerSession.java   |   1 +
 .../java/org/apache/juneau/html/HtmlParser.java |   1 +
 .../apache/juneau/html/HtmlParserBuilder.java   |   1 +
 .../apache/juneau/html/HtmlParserSession.java   |   1 +
 .../juneau/html/HtmlSchemaDocSerializer.java    |   1 +
 .../org/apache/juneau/html/HtmlSerializer.java  |   1 +
 .../juneau/html/HtmlSerializerBuilder.java      |   1 +
 .../juneau/html/HtmlSerializerSession.java      |   1 +
 .../java/org/apache/juneau/http/Accept.java     | 231 +++++++++++++
 .../org/apache/juneau/http/AcceptEncoding.java  | 147 +++++++++
 .../org/apache/juneau/http/ContentType.java     |  90 ++++++
 .../java/org/apache/juneau/http/MediaType.java  | 277 ++++++++++++++++
 .../org/apache/juneau/http/MediaTypeRange.java  | 270 ++++++++++++++++
 .../java/org/apache/juneau/http/TypeRange.java  | 276 ++++++++++++++++
 .../apache/juneau/ini/ConfigFileWritable.java   |   1 +
 .../org/apache/juneau/internal/ArrayUtils.java  |  33 ++
 .../apache/juneau/internal/CollectionUtils.java |  32 ++
 .../org/apache/juneau/internal/StringUtils.java |  79 +++++
 .../org/apache/juneau/jso/JsoParserBuilder.java |   1 +
 .../apache/juneau/jso/JsoSerializerBuilder.java |   1 +
 .../java/org/apache/juneau/json/JsonParser.java |   1 +
 .../apache/juneau/json/JsonParserBuilder.java   |   1 +
 .../apache/juneau/json/JsonParserSession.java   |   1 +
 .../juneau/json/JsonSchemaSerializer.java       |   1 +
 .../json/JsonSchemaSerializerBuilder.java       |   1 +
 .../org/apache/juneau/json/JsonSerializer.java  |   1 +
 .../juneau/json/JsonSerializerBuilder.java      |   1 +
 .../juneau/json/JsonSerializerSession.java      |   1 +
 .../apache/juneau/msgpack/MsgPackParser.java    |   1 +
 .../juneau/msgpack/MsgPackParserBuilder.java    |   1 +
 .../juneau/msgpack/MsgPackParserSession.java    |   1 +
 .../juneau/msgpack/MsgPackSerializer.java       |   1 +
 .../msgpack/MsgPackSerializerBuilder.java       |   1 +
 .../msgpack/MsgPackSerializerSession.java       |   1 +
 .../java/org/apache/juneau/parser/Parser.java   |   1 +
 .../org/apache/juneau/parser/ParserBuilder.java |   1 +
 .../org/apache/juneau/parser/ParserGroup.java   |  68 ++--
 .../juneau/parser/ParserGroupBuilder.java       |  12 +-
 .../org/apache/juneau/parser/ParserMatch.java   |   2 +-
 .../org/apache/juneau/parser/ParserSession.java |   1 +
 .../juneau/plaintext/PlainTextParser.java       |   2 +-
 .../plaintext/PlainTextParserBuilder.java       |   1 +
 .../juneau/plaintext/PlainTextSerializer.java   |   2 +-
 .../plaintext/PlainTextSerializerBuilder.java   |   1 +
 .../apache/juneau/serializer/Serializer.java    |   1 +
 .../juneau/serializer/SerializerBuilder.java    |   1 +
 .../juneau/serializer/SerializerGroup.java      |  68 ++--
 .../serializer/SerializerGroupBuilder.java      |  12 +-
 .../juneau/serializer/SerializerMatch.java      |   2 +-
 .../juneau/serializer/SerializerSession.java    |   1 +
 .../juneau/serializer/WriterSerializer.java     |   1 +
 .../juneau/soap/SoapXmlSerializerBuilder.java   |   1 +
 .../java/org/apache/juneau/uon/UonParser.java   |   1 +
 .../org/apache/juneau/uon/UonParserBuilder.java |   1 +
 .../org/apache/juneau/uon/UonParserSession.java |   1 +
 .../org/apache/juneau/uon/UonSerializer.java    |   1 +
 .../apache/juneau/uon/UonSerializerBuilder.java |   1 +
 .../apache/juneau/uon/UonSerializerSession.java |   1 +
 .../juneau/urlencoding/UrlEncodingParser.java   |   1 +
 .../urlencoding/UrlEncodingParserBuilder.java   |   1 +
 .../urlencoding/UrlEncodingParserSession.java   |   1 +
 .../urlencoding/UrlEncodingSerializer.java      |   1 +
 .../UrlEncodingSerializerBuilder.java           |   1 +
 .../UrlEncodingSerializerSession.java           |   1 +
 .../org/apache/juneau/utils/StringMessage.java  |   1 +
 .../org/apache/juneau/utils/StringObject.java   |   1 +
 .../java/org/apache/juneau/xml/XmlParser.java   |   1 +
 .../org/apache/juneau/xml/XmlParserBuilder.java |   1 +
 .../org/apache/juneau/xml/XmlParserSession.java |   1 +
 .../apache/juneau/xml/XmlSchemaSerializer.java  |   1 +
 .../juneau/xml/XmlSchemaSerializerBuilder.java  |   1 +
 .../org/apache/juneau/xml/XmlSerializer.java    |   1 +
 .../apache/juneau/xml/XmlSerializerBuilder.java |   1 +
 .../apache/juneau/xml/XmlSerializerSession.java |   1 +
 juneau-core/src/main/javadoc/overview.html      |  47 ++-
 .../juneau/rest/client/RestClientBuilder.java   |   1 +
 .../apache/juneau/rest/jaxrs/BaseProvider.java  |   3 +-
 .../juneau/rest/test/HeadersResource.java       |  74 +++++
 .../java/org/apache/juneau/rest/test/Root.java  |   1 +
 .../org/apache/juneau/rest/test/GzipTest.java   |   4 -
 .../apache/juneau/rest/test/HeadersTest.java    |  56 ++++
 .../apache/juneau/rest/test/ParsersTest.java    |   2 +-
 .../java/org/apache/juneau/rest/CallMethod.java |  17 +-
 .../org/apache/juneau/rest/ReaderResource.java  |   1 +
 .../java/org/apache/juneau/rest/RestConfig.java |   7 +-
 .../org/apache/juneau/rest/RestContext.java     |   1 +
 .../apache/juneau/rest/RestInfoProvider.java    |   2 +-
 .../org/apache/juneau/rest/RestRequest.java     |  54 ++--
 .../org/apache/juneau/rest/RestResponse.java    |   3 +-
 .../org/apache/juneau/rest/StreamResource.java  |   1 +
 .../java/org/apache/juneau/rest/package.html    |  52 ++-
 .../rest/remoteable/RemoteableServlet.java      |   2 +-
 .../juneau/rest/response/DefaultHandler.java    |   1 +
 .../juneau/rest/response/StreamableHandler.java |   1 +
 .../juneau/rest/response/WritableHandler.java   |   1 +
 128 files changed, 2673 insertions(+), 756 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java 
b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
index 9bc336e..ffe2453 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
@@ -21,6 +21,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.transform.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java 
b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
index 1a71a2b..03dbc48 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
@@ -18,6 +18,7 @@ import static org.apache.juneau.jena.RdfParserContext.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.jena.annotation.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.xml.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java 
b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
index db1cbdc..f699443 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
@@ -20,6 +20,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.xml.*;
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java 
b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
index 9b254a9..ecbc618 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
@@ -20,6 +20,7 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
 
b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
index 6b8e5bb..da3b59a 100644
--- 
a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
+++ 
b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
@@ -18,6 +18,7 @@ import static org.apache.juneau.jena.RdfSerializerContext.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.jena.annotation.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.xml.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
 
b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
index df13cea..199f144 100644
--- 
a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
+++ 
b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
@@ -20,6 +20,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.msgpack.*;
 import org.apache.juneau.serializer.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/MediaRangeTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/MediaRangeTest.java 
b/juneau-core-test/src/test/java/org/apache/juneau/MediaRangeTest.java
deleted file mode 100644
index 882ca6a..0000000
--- a/juneau-core-test/src/test/java/org/apache/juneau/MediaRangeTest.java
+++ /dev/null
@@ -1,65 +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;
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.apache.juneau.json.*;
-import org.junit.*;
-import org.junit.runner.*;
-import org.junit.runners.*;
-
-/**
- * Verifies that the MediaRange and MediaType classes parse and sort Accept 
headers correctly.
- */
-@RunWith(Parameterized.class)
-public class MediaRangeTest {
-       @Parameterized.Parameters
-       public static Collection<Object[]> getParameters() {
-               return Arrays.asList(new Object[][] {
-                       { "0", "text/json", "['text/json']" },
-                       { "1", "text/json,text/*", "['text/json','text/*']" },
-                       { "2", "text/*,text/json", "['text/json','text/*']" },
-                       { "3", "text/*,text/*", "['text/*']" },
-                       { "4", "*/text,text/*", "['text/*','*/text']" },
-                       { "5", "text/*,*/text", "['text/*','*/text']" },
-                       { "6", "A;q=0.9,B;q=0.1", "['a;q=0.9','b;q=0.1']" },
-                       { "7", "B;q=0.9,A;q=0.1", "['b;q=0.9','a;q=0.1']" },
-                       { "8", "A,B;q=0.9,C;q=0.1,D;q=0", 
"['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
-                       { "9", "D;q=0,C;q=0.1,B;q=0.9,A", 
"['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
-                       { "10", "A;q=1,B;q=0.9,C;q=0.1,D;q=0", 
"['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
-                       { "11", "D;q=0,C;q=0.1,B;q=0.9,A;q=1", 
"['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
-                       { "12", "A;q=0,B;q=0.1,C;q=0.9,D;q=1", 
"['d','c;q=0.9','b;q=0.1','a;q=0.0']" },
-                       { "13", "*", "['*']" },
-                       { "14", "", "['*/*']" },
-                       { "15", null, "['*/*']" },
-                       { "16", "foo/bar/baz", "['foo/bar/baz']" },
-               });
-       }
-       
-       private String label, mediaRange, expected;
-       
-       public MediaRangeTest(String label, String mediaRange, String expected) 
{
-               this.label = label;
-               this.mediaRange = mediaRange;
-               this.expected = expected;
-       }
-       
-       @Test
-       public void test() {
-               MediaRange[] r = MediaRange.parse(mediaRange);
-               assertEquals(label + " failed", expected, 
JsonSerializer.DEFAULT_LAX.toString(r));
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/TestUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/TestUtils.java 
b/juneau-core-test/src/test/java/org/apache/juneau/TestUtils.java
index eaeb4e7..4405efd 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/TestUtils.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/TestUtils.java
@@ -437,14 +437,13 @@ public class TestUtils {
         * If it's a byte[], convert it to a UTF-8 encoded String.
         */
        public static String toString(Object o) {
+               if (o == null)
+                       return null;
                if (o instanceof String)
                        return (String)o;
-               try {
-                       return new String((byte[])o, "UTF-8");
-               } catch (UnsupportedEncodingException e) {
-                       e.printStackTrace();
-               }
-               return null;
+               if (o instanceof byte[])
+                       return new String((byte[])o, IOUtils.UTF8);
+               return o.toString();
        }
 
        private static ThreadLocal<TimeZone> systemTimeZone = new 
ThreadLocal<TimeZone>();
@@ -497,9 +496,9 @@ public class TestUtils {
        /**
         * Same as {@link Assert#assertEquals(String,String,String) except 
takes in a MessageFormat-style message.
         */
-       public static void assertEquals(String expected, String actual, String 
msg, Object...args) {
-               if (! StringUtils.isEquals(expected, actual))
-                       throw new ComparisonFailure(MessageFormat.format(msg, 
args), expected, actual);                 
+       public static void assertEquals(Object expected, Object actual, String 
msg, Object...args) {
+               if (! isEquals(expected, actual))
+                       throw new ComparisonFailure(MessageFormat.format(msg, 
args), toString(expected), toString(actual));                     
        }
        
        /**
@@ -518,4 +517,11 @@ public class TestUtils {
                throw new AssertionError(new StringMessage("Expected type {0} 
but was {1}", type, (o == null ? null : o.getClass())));
        }
        
+       private static boolean isEquals(Object o1, Object o2) {
+               if (o1 == null)
+                       return o2 == null;
+               if (o2 == null)
+                       return false;
+               return o1.equals(o2);
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/encoders/EncoderGroupTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/encoders/EncoderGroupTest.java
 
b/juneau-core-test/src/test/java/org/apache/juneau/encoders/EncoderGroupTest.java
new file mode 100755
index 0000000..e6e2ec1
--- /dev/null
+++ 
b/juneau-core-test/src/test/java/org/apache/juneau/encoders/EncoderGroupTest.java
@@ -0,0 +1,116 @@
+// 
***************************************************************************************************************************
+// * 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.encoders;
+
+import static org.apache.juneau.TestUtils.*;
+
+import org.junit.*;
+
+@SuppressWarnings({"javadoc"})
+public class EncoderGroupTest {
+
+       
//====================================================================================================
+       // Test matching
+       
//====================================================================================================
+       @Test
+       public void testEncoderGroupMatching() throws Exception {
+               
+               EncoderGroup g = new 
EncoderGroupBuilder().append(Encoder1.class, Encoder2.class, 
Encoder3.class).build();
+               assertType(Encoder1.class, g.getEncoder("gzip1"));
+               assertType(Encoder2.class, g.getEncoder("gzip2"));
+               assertType(Encoder2.class, g.getEncoder("gzip2a"));
+               assertType(Encoder3.class, g.getEncoder("gzip3"));
+               assertType(Encoder3.class, g.getEncoder("gzip3a"));
+               assertType(Encoder3.class, g.getEncoder("gzip3,gzip2,gzip1"));
+               assertType(Encoder1.class, 
g.getEncoder("gzip3;q=0.9,gzip2;q=0.1,gzip1"));
+               assertType(Encoder3.class, 
g.getEncoder("gzip2;q=0.9,gzip1;q=0.1,gzip3"));
+               assertType(Encoder2.class, 
g.getEncoder("gzip1;q=0.9,gzip3;q=0.1,gzip2"));
+       }
+       
+       public static class Encoder1 extends GzipEncoder {
+               @Override /* Encoder */
+               public String[] getCodings() {
+                       return new String[]{"gzip1"};
+               }
+       }
+       
+       public static class Encoder2 extends GzipEncoder {
+               @Override /* Encoder */
+               public String[] getCodings() {
+                       return new String[]{"gzip2","gzip2a"};
+               }
+       }
+
+       public static class Encoder3 extends GzipEncoder {
+               @Override /* Encoder */
+               public String[] getCodings() {
+                       return new String[]{"gzip3","gzip3a"};
+               }
+       }
+       
+       
//====================================================================================================
+       // Test inheritence
+       
//====================================================================================================
+       @Test
+       public void testInheritence() throws Exception {
+               EncoderGroupBuilder gb = null;
+               EncoderGroup g = null;
+               
+               gb = new EncoderGroupBuilder().append(E1.class, E2.class);
+               g = gb.build();
+               assertObjectEquals("['E1','E2','E2a']", 
g.getSupportedEncodings());
+               
+               gb = new EncoderGroupBuilder(g).append(E3.class, E4.class);
+               g = gb.build();
+               assertObjectEquals("['E3','E4','E4a','E1','E2','E2a']", 
g.getSupportedEncodings());
+
+               gb = new EncoderGroupBuilder(g).append(E5.class);
+               g = gb.build();
+               assertObjectEquals("['E5','E3','E4','E4a','E1','E2','E2a']", 
g.getSupportedEncodings());
+       }
+       
+       public static class E1 extends GzipEncoder {
+               @Override /* Encoder */
+               public String[] getCodings() {
+                       return new String[]{"E1"};
+               }
+       }
+       
+       public static class E2 extends GzipEncoder {
+               @Override /* Encoder */
+               public String[] getCodings() {
+                       return new String[]{"E2","E2a"};
+               }
+       }
+
+       public static class E3 extends GzipEncoder {
+               @Override /* Encoder */
+               public String[] getCodings() {
+                       return new String[]{"E3"};
+               }
+       }
+       
+       public static class E4 extends GzipEncoder {
+               @Override /* Encoder */
+               public String[] getCodings() {
+                       return new String[]{"E4","E4a"};
+               }
+       }
+       
+       public static class E5 extends GzipEncoder {
+               @Override /* Encoder */
+               public String[] getCodings() {
+                       return new String[]{"E5"};
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptExtensionsTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptExtensionsTest.java
 
b/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptExtensionsTest.java
new file mode 100644
index 0000000..be8b0f0
--- /dev/null
+++ 
b/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptExtensionsTest.java
@@ -0,0 +1,118 @@
+// 
***************************************************************************************************************************
+// * 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.https;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.junit.Assert.*;
+
+import org.apache.juneau.http.*;
+import org.junit.*;
+
+/**
+ * Verifies that the Accept class handles parameters and extensions correctly.
+ */
+public class AcceptExtensionsTest {
+
+       
//--------------------------------------------------------------------------------
+       // Verifies that media type parameters are distinguished from media 
range extensions.
+       
//--------------------------------------------------------------------------------
+       @Test
+       public void testExtensions() throws Exception {
+               Accept accept;
+               MediaTypeRange mr;
+               
+               accept = Accept.forString("text/json");
+               mr = accept.getMediaRanges().get(0);
+               assertTextEquals("text/json", mr);
+               assertTextEquals("text/json", mr.getMediaType());
+               assertObjectEquals("{}", mr.getMediaType().getParameters());
+               assertTextEquals("1.0", mr.getQValue());
+               assertObjectEquals("{}", mr.getExtensions());
+
+               accept = Accept.forString("foo,bar");
+               mr = accept.getMediaRanges().get(0);
+               assertTextEquals("foo", mr);
+               assertTextEquals("foo", mr.getMediaType());
+               assertObjectEquals("{}", mr.getMediaType().getParameters());
+               assertTextEquals("1.0", mr.getQValue());
+               assertObjectEquals("{}", mr.getExtensions());
+
+               accept = Accept.forString(" foo , bar ");
+               mr = accept.getMediaRanges().get(0);
+               assertTextEquals("foo", mr);
+               assertTextEquals("foo", mr.getMediaType());
+               assertObjectEquals("{}", mr.getMediaType().getParameters());
+               assertTextEquals("1.0", mr.getQValue());
+               assertObjectEquals("{}", mr.getExtensions());
+
+               accept = Accept.forString("text/json;a=1;q=0.9;b=2");
+               mr = accept.getMediaRanges().get(0);
+               assertTextEquals("text/json;a=1;q=0.9;b=2", mr);
+               assertTextEquals("text/json;a=1", mr.getMediaType());
+               assertObjectEquals("{a:['1']}", 
mr.getMediaType().getParameters());
+               assertTextEquals("0.9", mr.getQValue());
+               assertObjectEquals("{b:['2']}", mr.getExtensions());
+               
+               accept = Accept.forString("text/json;a=1;a=2;q=0.9;b=3;b=4");
+               mr = accept.getMediaRanges().get(0);
+               assertTextEquals("text/json;a=1;a=2;q=0.9;b=3;b=4", mr);
+               assertTextEquals("text/json;a=1;a=2", mr.getMediaType());
+               assertObjectEquals("{a:['1','2']}", 
mr.getMediaType().getParameters());
+               assertTextEquals("0.9", mr.getQValue());
+               assertObjectEquals("{b:['3','4']}", mr.getExtensions());
+
+               accept = Accept.forString("text/json;a=1");
+               mr = accept.getMediaRanges().get(0);
+               assertTextEquals("text/json;a=1", mr);
+               assertTextEquals("text/json;a=1", mr.getMediaType());
+               assertObjectEquals("{a:['1']}", 
mr.getMediaType().getParameters());
+               assertTextEquals("1.0", mr.getQValue());
+               assertObjectEquals("{}", mr.getExtensions());
+
+               accept = Accept.forString("text/json;a=1;");
+               mr = accept.getMediaRanges().get(0);
+               assertTextEquals("text/json;a=1", mr);
+               assertTextEquals("text/json;a=1", mr.getMediaType());
+               assertObjectEquals("{a:['1']}", 
mr.getMediaType().getParameters());
+               assertTextEquals("1.0", mr.getQValue());
+               assertObjectEquals("{}", mr.getExtensions());
+               
+               accept = Accept.forString("text/json;q=0.9");
+               mr = accept.getMediaRanges().get(0);
+               assertTextEquals("text/json;q=0.9", mr);
+               assertTextEquals("text/json", mr.getMediaType());
+               assertObjectEquals("{}", mr.getMediaType().getParameters());
+               assertTextEquals("0.9", mr.getQValue());
+               assertObjectEquals("{}", mr.getExtensions());
+
+               accept = Accept.forString("text/json;q=0.9;");
+               mr = accept.getMediaRanges().get(0);
+               assertTextEquals("text/json;q=0.9", mr);
+               assertTextEquals("text/json", mr.getMediaType());
+               assertObjectEquals("{}", mr.getMediaType().getParameters());
+               assertTextEquals("0.9", mr.getQValue());
+               assertObjectEquals("{}", mr.getExtensions());
+       }
+       
+       
//--------------------------------------------------------------------------------
+       // Tests the Accept.hasSubtypePart() method.
+       
//--------------------------------------------------------------------------------
+       @Test
+       public void testHasSubtypePart() {
+               Accept accept = 
Accept.forString("text/json+x,text/foo+y;q=0.0");
+               assertTrue(accept.hasSubtypePart("json"));
+               assertTrue(accept.hasSubtypePart("x"));
+               assertFalse(accept.hasSubtypePart("foo"));
+               assertFalse(accept.hasSubtypePart("y"));
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.java 
b/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.java
new file mode 100644
index 0000000..dd905a6
--- /dev/null
+++ b/juneau-core-test/src/test/java/org/apache/juneau/https/AcceptTest.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.https;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+import org.junit.runner.*;
+import org.junit.runners.*;
+
+/**
+ * Verifies that the Accept class handles matching correctly.
+ */
+@RunWith(Parameterized.class)
+public class AcceptTest {
+       @Parameterized.Parameters
+       public static Collection<Object[]> getParameters() {
+               return Arrays.asList(new Object[][] {
+                       
+                       // label, accept-header, media-types, expected-index
+                       
+                       // Simple matches
+                       { "SimpleMatch-1", "text/json", "['text/json']", 0 },
+                       { "SimpleMatch-2", "text/json", 
"['text/json','text/foo']", 0 },
+                       { "SimpleMatch-3", "text/json", 
"['text/foo','text/json']", 1 },
+                       
+                       // Simple no-matches
+                       { "SimpleNoMatch-1", "text/jsonx", "['text/json']", -1 
},
+                       { "SimpleNoMatch-2", "text/jso", "['text/json']", -1 },
+                       { "SimpleNoMatch-3", "text/json", 
"['application/json']", -1 },
+                       { "SimpleNoMatch-4", "text/json", "[]", -1 },
+                       { "SimpleNoMatch-5", null, "['text/json']", -1 },
+                       
+                       // Meta-character matches
+                       { "MetaMatch-1", "text/*", 
"['text/a','text/b+c','text/b+d+e']", 2 },
+                       { "MetaMatch-2", "text/b+*", 
"['text/a','text/b+c','text/b+d+e']", 2 },
+                       { "MetaMatch-3", "text/c+*", 
"['text/a','text/b+c','text/b+d+e']", 1 },
+                       { "MetaMatch-4", "text/b+d+e", 
"['text/a','text/b+c','text/b+d']", 2 },
+                       { "MetaMatch-5", "text/b+*", 
"['text/a','text/b+c','text/b+d']", 1 },
+                       { "MetaMatch-6", "text/d+e+*", 
"['text/a','text/b+c','text/b+d+e']", 2 },
+
+                       { "MetaMatch-7", "*/a", "['text/a','application/a']", 0 
},
+                       { "MetaMatch-8", "*/*", "['text/a','text/b+c']", 1 },
+                       { "MetaMatch-9", "*/*", "['text/b+c','text/a']", 0 },
+
+                       // Reverse meta-character matches
+                       { "RevMetaMatch-1", "text/a", "['text/*']", 0 },
+                       { "RevMetaMatch-3", "text/a", "['*/a']", 0 },
+                       { "RevMetaMatch-3", "text/a", "['*/*']", 0 },
+                       
+                       // Meta-character mixture matches
+                       { "MixedMetaMatch-1", "text/*", 
"['text/*','text/a','text/a+b','text/b+c','text/d+*']", 0 },
+                       { "MixedMetaMatch-2", "*/a", 
"['text/*','text/a','text/a+b','text/b+c','text/d+*']", 1 },
+                       { "MixedMetaMatch-3", "*/*", 
"['text/*','text/a','text/a+b','text/b+c','text/d+*']", 0 },
+                       { "MixedMetaMatch-4", "text/a+*", 
"['text/*','text/a','text/a+b','text/b+c','text/d+*']", 2 },
+                       { "MixedMetaMatch-5", "text/c+*", 
"['text/*','text/a','text/a+b','text/b+c','text/d+*']", 3 },
+                       { "MixedMetaMatch-6", "text/d+*", 
"['text/*','text/a','text/a+b','text/b+c','text/d+*']", 4 },
+
+                       // Fuzzy matches
+                       { "Fuzzy-1", "text/1+2", "['text/1+2']", 0 },
+                       // Order of subtype parts shouldn't matter.
+                       { "Fuzzy-2", "text/2+1", "['text/1+2']", 0 },
+                       // Should match if Accept has 'extra' subtypes.
+                       // For example, "Accept: text/json+activity" should 
match against the "text/json" serializer.
+                       { "Fuzzy-3", "text/1+2", "['text/1']", 0 },
+                       // Shouldn't match because the accept media type must 
be at least a subset of the real media type
+                       // For example, "Accept: text/json" should not match 
against the "text/json+lax" serializer.
+                       { "Fuzzy-4", "text/1", "['text/1+2']", -1 },
+                       { "Fuzzy-5", "text/1+2", "['text/1','text/1+3']", 0 },
+                       // "text/1+2" should be a better match than just 
"text/1"
+                       { "Fuzzy-6", "text/1+2", 
"['text/1','text/1+2','text/1+2+3']", 1 },
+                       // Same as last, but mix up the order a bit.
+                       { "Fuzzy-7", "text/1+2", 
"['text/1+2+3','text/1','text/1+2']", 2 },
+                       // Same as last, but mix up the order of the subtypes 
as well.
+                       { "Fuzzy-8", "text/1+2", 
"['text/3+2+1','text/1','text/2+1']", 2 },
+                       { "Fuzzy-9", "text/1+2+3+4", 
"['text/1+2','text/1+2+3']", 1 },
+                       { "Fuzzy-10", "text/1+2+3+4", 
"['text/1+2+3','text/1+2']", 0 },
+                       { "Fuzzy-11", "text/4+2+3+1", 
"['text/1+2+3','text/1+2']", 0 },
+                       { "Fuzzy-12", "text/4+2+3+1", 
"['text/1+2','text/1+2+3']", 1 },
+                       
+                       // Q metrics
+                       { "Q-1", "text/A;q=0.9,text/B;q=0.1", 
"['text/A','text/B']", 0 },
+                       { "Q-2", "text/A;q=0.9,text/B;q=0.1", 
"['text/B','text/A']", 1 },
+                       { "Q-3", "text/A+1;q=0.9,text/B;q=0.1", 
"['text/A','text/B']", 0 },
+                       { "Q-4", "text/A;q=0.9,text/B+1;q=0.1", 
"['text/A','text/B+1']", 0 },
+                       { "Q-5", "text/A;q=0.9,text/A+1;q=0.1", 
"['text/A+1','text/A']", 1 },
+
+                       // Test q=0
+                       { "Q0-1", "text/A;q=0,text/B;q=0.1", 
"['text/A','text/B']", 1 },
+                       { "Q0-2", "text/A;q=0,text/B;q=0.1", 
"['text/A','text/A+1']", -1 },
+                       
+                       // Test media types with parameters
+                       { "Parms-1", "text/A", "['text/A;foo=bar','text/B']", 0 
},
+                       { "Parms-2", "text/A;foo=bar", "['text/A','text/B']", 0 
},
+               });
+       }
+       
+       private String label, accept, mediaTypes;
+       private int expected;
+       
+       public AcceptTest(String label, String accept, String mediaTypes, int 
expected) {
+               this.label = label;
+               this.accept = accept;
+               this.mediaTypes = mediaTypes;
+               this.expected = expected;
+       }
+       
+       @Test
+       public void test() throws Exception {
+               Accept accept = Accept.forString(this.accept);
+               MediaType[] mt = JsonParser.DEFAULT.parse(mediaTypes, 
MediaType[].class);
+               int r = accept.findMatch(mt);
+               TestUtils.assertEquals(expected, r, "{0} failed", label);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/https/MediaRangeTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/https/MediaRangeTest.java 
b/juneau-core-test/src/test/java/org/apache/juneau/https/MediaRangeTest.java
new file mode 100644
index 0000000..afeb782
--- /dev/null
+++ b/juneau-core-test/src/test/java/org/apache/juneau/https/MediaRangeTest.java
@@ -0,0 +1,66 @@
+// 
***************************************************************************************************************************
+// * 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.https;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.http.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+import org.junit.runner.*;
+import org.junit.runners.*;
+
+/**
+ * Verifies that the MediaRange and MediaType classes parse and sort Accept 
headers correctly.
+ */
+@RunWith(Parameterized.class)
+public class MediaRangeTest {
+       @Parameterized.Parameters
+       public static Collection<Object[]> getParameters() {
+               return Arrays.asList(new Object[][] {
+                       { "0", "text/json", "['text/json']" },
+                       { "1", "text/json,text/*", "['text/json','text/*']" },
+                       { "2", "text/*,text/json", "['text/json','text/*']" },
+                       { "3", "text/*,text/*", "['text/*']" },
+                       { "4", "*/text,text/*", "['text/*','*/text']" },
+                       { "5", "text/*,*/text", "['text/*','*/text']" },
+                       { "6", "a;q=0.9,b;q=0.1", "['a;q=0.9','b;q=0.1']" },
+                       { "7", "b;q=0.9,a;q=0.1", "['b;q=0.9','a;q=0.1']" },
+                       { "8", "a,b;q=0.9,c;q=0.1,d;q=0", 
"['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
+                       { "9", "d;q=0,c;q=0.1,b;q=0.9,a", 
"['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
+                       { "10", "a;q=1,b;q=0.9,c;q=0.1,d;q=0", 
"['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
+                       { "11", "d;q=0,c;q=0.1,b;q=0.9,a;q=1", 
"['a','b;q=0.9','c;q=0.1','d;q=0.0']" },
+                       { "12", "a;q=0,b;q=0.1,c;q=0.9,d;q=1", 
"['d','c;q=0.9','b;q=0.1','a;q=0.0']" },
+                       { "13", "*", "['*']" },
+                       { "14", "", "['*/*']" },
+                       { "15", null, "['*/*']" },
+                       { "16", "foo/bar/baz", "['foo/bar/baz']" },
+               });
+       }
+       
+       private String label, mediaRange, expected;
+       
+       public MediaRangeTest(String label, String mediaRange, String expected) 
{
+               this.label = label;
+               this.mediaRange = mediaRange;
+               this.expected = expected;
+       }
+       
+       @Test
+       public void test() {
+               MediaTypeRange[] r = MediaTypeRange.parse(mediaRange);
+               assertEquals(label + " failed", expected, 
JsonSerializer.DEFAULT_LAX.toString(r));
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/parser/ParserGroupTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/parser/ParserGroupTest.java 
b/juneau-core-test/src/test/java/org/apache/juneau/parser/ParserGroupTest.java
new file mode 100755
index 0000000..79d3b11
--- /dev/null
+++ 
b/juneau-core-test/src/test/java/org/apache/juneau/parser/ParserGroupTest.java
@@ -0,0 +1,125 @@
+// 
***************************************************************************************************************************
+// * 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.parser;
+
+import static org.apache.juneau.TestUtils.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+
+@SuppressWarnings({"javadoc"})
+public class ParserGroupTest {
+
+       
//====================================================================================================
+       // Test parser group matching
+       
//====================================================================================================
+       @Test
+       public void testParserGroupMatching() throws Exception {
+               
+               ParserGroup g = new ParserGroupBuilder().append(Parser1.class, 
Parser2.class, Parser3.class).build();
+               assertType(Parser1.class, g.getParser("text/foo"));
+               assertType(Parser1.class, g.getParser("text/foo_a"));
+               assertType(Parser1.class, g.getParser("text/foo_a+xxx"));
+               assertType(Parser1.class, g.getParser("text/xxx+foo_a"));
+               assertType(Parser2.class, g.getParser("text/foo+bar"));
+               assertType(Parser2.class, g.getParser("text/foo+bar_a"));
+               assertType(Parser2.class, g.getParser("text/bar+foo"));
+               assertType(Parser2.class, g.getParser("text/bar+foo+xxx"));
+               assertType(Parser3.class, g.getParser("text/baz"));
+               assertType(Parser3.class, g.getParser("text/baz_a"));
+               assertType(Parser3.class, g.getParser("text/baz+yyy"));
+               assertType(Parser3.class, g.getParser("text/baz_a+yyy"));
+               assertType(Parser3.class, g.getParser("text/yyy+baz"));
+               assertType(Parser3.class, g.getParser("text/yyy+baz_a"));
+       }
+       
+       
+       @Consumes("text/foo,text/foo_a")
+       public static class Parser1 extends JsonParser {
+               public Parser1(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+       
+       @Consumes("text/foo+bar,text/foo+bar_a")
+       public static class Parser2 extends JsonParser {
+               public Parser2(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+
+       @Consumes("text/baz,text/baz_a")
+       public static class Parser3 extends JsonParser {
+               public Parser3(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+       
+       
//====================================================================================================
+       // Test inheritence
+       
//====================================================================================================
+       @Test
+       public void testInheritence() throws Exception {
+               ParserGroupBuilder gb = null;
+               ParserGroup g = null;
+               
+               gb = new ParserGroupBuilder().append(P1.class, P2.class);
+               g = gb.build();
+               assertObjectEquals("['text/1','text/2','text/2a']", 
g.getSupportedMediaTypes());
+               
+               gb = new ParserGroupBuilder(g).append(P3.class, P4.class);
+               g = gb.build();
+               
assertObjectEquals("['text/3','text/4','text/4a','text/1','text/2','text/2a']", 
g.getSupportedMediaTypes());
+
+               gb = new ParserGroupBuilder(g).append(P5.class);
+               g = gb.build();
+               
assertObjectEquals("['text/5','text/3','text/4','text/4a','text/1','text/2','text/2a']",
 g.getSupportedMediaTypes());
+       }
+       
+       @Consumes("text/1")
+       public static class P1 extends JsonParser {
+               public P1(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+       
+       @Consumes("text/2,text/2a")
+       public static class P2 extends JsonParser {
+               public P2(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+
+       @Consumes("text/3")
+       public static class P3 extends JsonParser {
+               public P3(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+       
+       @Consumes("text/4,text/4a")
+       public static class P4 extends JsonParser {
+               public P4(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+       
+       @Consumes("text/5")
+       public static class P5 extends JsonParser {
+               public P5(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java
 
b/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java
new file mode 100755
index 0000000..2bcf413
--- /dev/null
+++ 
b/juneau-core-test/src/test/java/org/apache/juneau/serializer/SerializerGroupTest.java
@@ -0,0 +1,166 @@
+// 
***************************************************************************************************************************
+// * 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.serializer;
+
+import static org.apache.juneau.TestUtils.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+
+@SuppressWarnings({"javadoc"})
+public class SerializerGroupTest {
+
+       
//====================================================================================================
+       // Trim nulls from beans
+       
//====================================================================================================
+       @Test
+       public void testSerializerGroupMatching() throws Exception {
+               
+               SerializerGroup sg = new 
SerializerGroupBuilder().append(SA1.class, SA2.class, SA3.class).build();
+               assertType(SA1.class, sg.getSerializer("text/foo"));
+               assertType(SA1.class, sg.getSerializer("text/foo_a"));
+               assertType(SA1.class, sg.getSerializer("text/xxx+foo_a"));
+               assertType(SA1.class, sg.getSerializer("text/foo_a+xxx"));
+               assertType(SA2.class, sg.getSerializer("text/foo+bar"));
+               assertType(SA2.class, sg.getSerializer("text/foo+bar_a"));
+               assertType(SA2.class, sg.getSerializer("text/bar+foo"));
+               assertType(SA2.class, sg.getSerializer("text/bar_a+foo"));
+               assertType(SA2.class, sg.getSerializer("text/bar+foo+xxx"));
+               assertType(SA2.class, sg.getSerializer("text/bar_a+foo+xxx"));
+               assertType(SA3.class, sg.getSerializer("text/baz"));
+               assertType(SA3.class, sg.getSerializer("text/baz_a"));
+               assertType(SA3.class, sg.getSerializer("text/baz+yyy"));
+               assertType(SA3.class, sg.getSerializer("text/baz_a+yyy"));
+               assertType(SA3.class, sg.getSerializer("text/yyy+baz"));
+               assertType(SA3.class, sg.getSerializer("text/yyy+baz_a"));
+               
+               assertType(SA1.class, 
sg.getSerializer("text/foo;q=0.9,text/foo+bar;q=0.8"));
+               assertType(SA2.class, 
sg.getSerializer("text/foo;q=0.8,text/foo+bar;q=0.9"));
+       }
+       
+       
+       @Produces("text/foo,text/foo_a")
+       public static class SA1 extends JsonSerializer {
+               public SA1(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+       
+       @Produces("text/foo+bar,text/foo+bar_a")
+       public static class SA2 extends JsonSerializer {
+               public SA2(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+
+       @Produces("text/baz,text/baz_a")
+       public static class SA3 extends JsonSerializer {
+               public SA3(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+
+       
//====================================================================================================
+       // Test inheritence
+       
//====================================================================================================
+       @Test
+       public void testInheritence() throws Exception {
+               SerializerGroupBuilder gb = null;
+               SerializerGroup g = null;
+               
+               gb = new SerializerGroupBuilder().append(SB1.class, SB2.class);
+               g = gb.build();
+               assertObjectEquals("['text/1','text/2','text/2a']", 
g.getSupportedMediaTypes());
+               
+               gb = new SerializerGroupBuilder(g).append(SB3.class, SB4.class);
+               g = gb.build();
+               
assertObjectEquals("['text/3','text/4','text/4a','text/1','text/2','text/2a']", 
g.getSupportedMediaTypes());
+
+               gb = new SerializerGroupBuilder(g).append(SB5.class);
+               g = gb.build();
+               
assertObjectEquals("['text/5','text/3','text/4','text/4a','text/1','text/2','text/2a']",
 g.getSupportedMediaTypes());
+       }
+       
+       @Produces("text/1")
+       public static class SB1 extends JsonSerializer {
+               public SB1(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+       
+       @Produces("text/2,text/2a")
+       public static class SB2 extends JsonSerializer {
+               public SB2(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+
+       @Produces("text/3")
+       public static class SB3 extends JsonSerializer {
+               public SB3(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+       
+       @Produces("text/4,text/4a")
+       public static class SB4 extends JsonSerializer {
+               public SB4(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+       
+       @Produces("text/5")
+       public static class SB5 extends JsonSerializer {
+               public SB5(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+       
+       
//====================================================================================================
+       // Test media type with meta-characters
+       
//====================================================================================================
+       @Test
+       public void testMediaTypesWithMetaCharacters() throws Exception {
+               SerializerGroupBuilder gb = null;
+               SerializerGroup g = null;
+               
+               gb = new SerializerGroupBuilder().append(SC1.class, SC2.class, 
SC3.class);
+               g = gb.build();
+               assertType(SC1.class, g.getSerializer("text/foo"));
+               assertType(SC2.class, g.getSerializer("foo/json"));
+               assertType(SC3.class, g.getSerializer("foo/foo"));
+       }
+       
+       @Produces("text/*")
+       public static class SC1 extends JsonSerializer {
+               public SC1(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+       
+       @Produces("*/json")
+       public static class SC2 extends JsonSerializer {
+               public SC2(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+       
+       @Produces("*/*")
+       public static class SC3 extends JsonSerializer {
+               public SC3(PropertyStore propertyStore) {
+                       super(propertyStore);
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
 
b/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
index bc4b94e..7bd042e 100755
--- 
a/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
+++ 
b/juneau-core-test/src/test/java/org/apache/juneau/utils/CollectionUtilsTest.java
@@ -16,6 +16,8 @@ import static org.apache.juneau.TestUtils.*;
 import static org.apache.juneau.internal.CollectionUtils.*;
 import static org.junit.Assert.*;
 
+import java.util.*;
+
 import org.apache.juneau.*;
 import org.junit.*;
 
@@ -27,7 +29,7 @@ public class CollectionUtilsTest {
        
//====================================================================================================
        @Test
        public void testReverse() throws Exception {
-               assertNull(reverse(null));
+               assertNull(reverse((Map<?,?>)null));
 
                assertObjectEquals("{b:2,a:1}", reverse(new 
ObjectMap("{a:1,b:2}")));
                assertObjectEquals("{}", reverse(new ObjectMap("{}")));

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java 
b/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
index 95c340b..f74d75e 100755
--- 
a/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
+++ 
b/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
@@ -700,4 +700,21 @@ public class StringUtilsTest {
                in = null;
                assertEquals("", getField(0, in, ','));
        }
+
+       
//====================================================================================================
+       // parseMap(String,char,char,boolean)
+       
//====================================================================================================
+       @Test
+       public void testSplitMap() {
+               assertObjectEquals("{a:'1'}", splitMap("a=1", ',', '=', true));
+               assertObjectEquals("{a:'1',b:'2'}", splitMap("a=1,b=2", ',', 
'=', true));
+               assertObjectEquals("{a:'1',b:'2'}", splitMap(" a = 1 , b = 2 ", 
',', '=', true));
+               assertObjectEquals("{' a ':' 1 ',' b ':' 2 '}", splitMap(" a = 
1 , b = 2 ", ',', '=', false));
+               assertObjectEquals("{a:''}", splitMap("a", ',', '=', true));
+               assertObjectEquals("{a:'',b:''}", splitMap("a,b", ',', '=', 
true));
+               assertObjectEquals("{a:'1',b:''}", splitMap("a=1,b", ',', '=', 
true));
+               assertObjectEquals("{a:'',b:'1'}", splitMap("a,b=1", ',', '=', 
true));
+               assertObjectEquals("{'a=':'1'}", splitMap("a\\==1", ',', '=', 
true));
+               assertObjectEquals("{'a\\\\':'1'}", splitMap("a\\\\=1", ',', 
'=', true));
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java 
b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
index 0977ba0..c5df1d1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
@@ -23,6 +23,7 @@ import java.util.*;
 import java.util.concurrent.*;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.serializer.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanSession.java 
b/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
index ad1cee6..525f0e3 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
@@ -20,6 +20,7 @@ import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.atomic.*;
 
+import org.apache.juneau.http.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java 
b/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
index 2f01917..f566a92 100644
--- a/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/CoreObjectBuilder.java
@@ -20,6 +20,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/MediaRange.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/MediaRange.java 
b/juneau-core/src/main/java/org/apache/juneau/MediaRange.java
deleted file mode 100644
index 5a21882..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/MediaRange.java
+++ /dev/null
@@ -1,321 +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;
-
-import java.util.*;
-import java.util.Map.*;
-
-import org.apache.juneau.annotation.*;
-import org.apache.juneau.internal.*;
-
-/**
- * Describes a single type used in content negotiation between an HTTP client 
and server, as described in
- * Section 14.1 and 14.7 of RFC2616 (the HTTP/1.1 specification).
- */
-@BeanIgnore
-public final class MediaRange implements Comparable<MediaRange>  {
-
-       private static final MediaRange[] DEFAULT = new MediaRange[]{new 
MediaRange("*/*")};
-
-       private final MediaType mediaType;
-       private final Float qValue;
-       private final Map<String,Set<String>> parameters, extensions;
-
-       /**
-        * Parses a media range fragement of an <code>Accept</code> header 
value into a single media range object..
-        * <p>
-        * The syntax expected to be found in the referenced <code>value</code> 
complies with the syntax described in RFC2616, Section 14.1, as described below:
-        * <p class='bcode'>
-        *      media-range    = ( "*\/*"
-        *                        | ( type "/" "*" )
-        *                        | ( type "/" subtype )
-        *                        ) *( ";" parameter )
-        *      accept-params  = ";" "q" "=" qvalue *( accept-extension )
-        *      accept-extension = ";" token [ "=" ( token | quoted-string ) ]
-        * </p>
-        * @param mediaRangeFragment The media range fragement string.
-        */
-       private MediaRange(String mediaRangeFragment) {
-
-               String r = mediaRangeFragment;
-               Float _qValue = 1f;
-               MediaType _mediaType = null;
-               Map<String,Set<String>> _parameters = null;
-               Map<String,Set<String>> _extensions = null;
-
-               r = r.trim();
-
-               int i = r.indexOf(';');
-
-               if (i == -1) {
-                       _mediaType = MediaType.forString(r);
-
-               } else {
-
-                       _mediaType = MediaType.forString(r.substring(0, i));
-
-                       String[] tokens = r.substring(i+1).split(";");
-
-                       // Only the type of the range is specified
-                       if (tokens.length > 0) {
-
-                               boolean isInExtensions = false;
-                               for (int j = 0; j < tokens.length; j++) {
-                                       String[] parm = tokens[j].split("=");
-                                       if (parm.length == 2) {
-                                               String k = parm[0], v = parm[1];
-                                               if (isInExtensions) {
-                                                       if (_extensions == null)
-                                                               _extensions = 
new TreeMap<String,Set<String>>();
-                                                       if (! 
_extensions.containsKey(parm[0]))
-                                                               
_extensions.put(parm[0], new TreeSet<String>());
-                                                       
_extensions.get(parm[0]).add(parm[1]);
-                                               } else if (k.equals("q")) {
-                                                       _qValue = new Float(v);
-                                                       isInExtensions = true;
-                                               } else /*(! isInExtensions)*/ {
-                                                       if (_parameters == null)
-                                                               _parameters = 
new TreeMap<String,Set<String>>();
-                                                       if (! 
_parameters.containsKey(parm[0]))
-                                                               
_parameters.put(parm[0], new TreeSet<String>());
-                                                       
_parameters.get(parm[0]).add(parm[1]);
-                                               }
-                                       }
-                               }
-                       }
-               }
-               if (_parameters == null)
-                       _parameters = Collections.emptyMap();
-               if (_extensions == null)
-                       _extensions = Collections.emptyMap();
-
-               this.mediaType = _mediaType;
-               this.parameters = _parameters;
-               this.qValue = _qValue;
-               this.extensions = _extensions;
-       }
-
-       /**
-        * Returns the media type enclosed by this media range.
-        *
-        * <h5 class='section'>Examples:</h5>
-        * <ul>
-        *      <li><js>"text/html"</js>
-        *      <li><js>"text/*"</js>
-        *      <li><js>"*\/*"</js>
-        * </ul>
-        *
-        * @return The media type of this media range, lowercased, never 
<jk>null</jk>.
-        */
-       public MediaType getMediaType() {
-               return mediaType;
-       }
-
-       /**
-        * Returns the <js>'q'</js> (quality) value for this type, as described 
in Section 3.9 of RFC2616.
-        * <p>
-        * The quality value is a float between <code>0.0</code> (unacceptable) 
and <code>1.0</code> (most acceptable).
-        * <p>
-        * If 'q' value doesn't make sense for the context (e.g. this range was 
extracted from a <js>"content-*"</js> header, as opposed to <js>"accept-*"</js>
-        * header, its value will always be <js>"1"</js>.
-        *
-        * @return The 'q' value for this type, never <jk>null</jk>.
-        */
-       public Float getQValue() {
-               return qValue;
-       }
-
-       /**
-        * Returns the optional set of parameters associated to the type as 
returned by {@link #getMediaType()}.
-        * <p>
-        * The parameters are those values as described in standardized MIME 
syntax.
-        * An example of such a parameter in string form might be 
<js>"level=1"</js>.
-        * <p>
-        * Values are lowercase and never <jk>null</jk>.
-        *
-        * @return The optional list of parameters, never <jk>null</jk>.
-        */
-       public Map<String,Set<String>> getParameters() {
-               return parameters;
-       }
-
-       /**
-        * Returns the optional set of custom extensions defined for this type.
-        * <p>
-        * Values are lowercase and never <jk>null</jk>.
-        *
-        * @return The optional list of extensions, never <jk>null</jk>.
-        */
-       public Map<String,Set<String>> getExtensions() {
-               return extensions;
-       }
-
-       /**
-        * Provides a string representation of this media range, suitable for 
use as an <code>Accept</code> header value.
-        * <p>
-        * The literal text generated will be all lowercase.
-        *
-        * @return A media range suitable for use as an Accept header value, 
never <code>null</code>.
-        */
-       @Override /* Object */
-       public String toString() {
-               StringBuffer sb = new StringBuffer().append(mediaType);
-
-               for (Entry<String,Set<String>> e : parameters.entrySet()) {
-                       String k = e.getKey();
-                       for (String v : e.getValue())
-                               sb.append(';').append(k).append('=').append(v);
-               }
-
-               // '1' is equivalent to specifying no qValue. If there's no 
extensions, then we won't include a qValue.
-               if (qValue.floatValue() == 1.0) {
-                       if (! extensions.isEmpty()) {
-                               sb.append(";q=").append(qValue);
-                               for (Entry<String,Set<String>> e : 
extensions.entrySet()) {
-                                       String k = e.getKey();
-                                       for (String v : e.getValue())
-                                               
sb.append(';').append(k).append('=').append(v);
-                               }
-                       }
-               } else {
-                       sb.append(";q=").append(qValue);
-                       for (Entry<String,Set<String>> e : 
extensions.entrySet()) {
-                               String k = e.getKey();
-                               for (String v : e.getValue())
-                                       
sb.append(';').append(k).append('=').append(v);
-                       }
-               }
-               return sb.toString();
-       }
-
-       /**
-        * Returns <jk>true</jk> if the specified object is also a 
<code>MediaType</code>, and has the same qValue, type, parameters, and 
extensions.
-        *
-        * @return <jk>true</jk> if object is equivalent.
-        */
-       @Override /* Object */
-       public boolean equals(Object o) {
-
-               if (o == null || !(o instanceof MediaRange))
-                       return false;
-
-               if (this == o)
-                       return true;
-
-               MediaRange o2 = (MediaRange) o;
-               return qValue.equals(o2.qValue)
-                       && mediaType.equals(o2.mediaType)
-                       && parameters.equals(o2.parameters)
-                       && extensions.equals(o2.extensions);
-       }
-
-       /**
-        * Returns a hash based on this instance's <code>media-type</code>.
-        *
-        * @return A hash based on this instance's <code>media-type</code>.
-        */
-       @Override /* Object */
-       public int hashCode() {
-               return mediaType.hashCode();
-       }
-
-       /**
-        * Parses an <code>Accept</code> header value into an array of media 
ranges.
-        * <p>
-        * The returned media ranges are sorted such that the most acceptable 
media is available at ordinal position <js>'0'</js>, and the least acceptable 
at position n-1.
-        * <p>
-        * The syntax expected to be found in the referenced <code>value</code> 
complies with the syntax described in RFC2616, Section 14.1, as described below:
-        * <p class='bcode'>
-        *      Accept         = "Accept" ":"
-        *                        #( media-range [ accept-params ] )
-        *
-        *      media-range    = ( "*\/*"
-        *                        | ( type "/" "*" )
-        *                        | ( type "/" subtype )
-        *                        ) *( ";" parameter )
-        *      accept-params  = ";" "q" "=" qvalue *( accept-extension )
-        *      accept-extension = ";" token [ "=" ( token | quoted-string ) ]
-        * </p>
-        * This method can also be used on other headers such as 
<code>Accept-Charset</code> and <code>Accept-Encoding</code>...
-        * <p class='bcode'>
-        *      Accept-Charset = "Accept-Charset" ":"
-        *      1#( ( charset | "*" )[ ";" "q" "=" qvalue ] )
-        * </p>
-        *
-        * @param value The value to parse.  If <jk>null</jk> or empty, returns 
a single <code>MediaRange</code> is returned that represents all types.
-        * @return The media ranges described by the string.
-        * The ranges are sorted such that the most acceptable media is 
available at ordinal position <js>'0'</js>, and the least acceptable at 
position n-1.
-        */
-       public static MediaRange[] parse(String value) {
-
-               if (value == null || value.length() == 0)
-                       return DEFAULT;
-
-               value = value.toLowerCase(Locale.ENGLISH);
-
-               if (value.indexOf(',') == -1)
-                       return new MediaRange[]{new MediaRange(value)};
-
-               Set<MediaRange> ranges = new TreeSet<MediaRange>();
-
-               for (String r : StringUtils.split(value, ',')) {
-                       r = r.trim();
-
-                       if (r.isEmpty())
-                               continue;
-
-                       ranges.add(new MediaRange(r));
-               }
-
-               return ranges.toArray(new MediaRange[ranges.size()]);
-       }
-
-       /**
-        * Compares two MediaRanges for equality.
-        * <p>
-        * The values are first compared according to <code>qValue</code> 
values.
-        * Should those values be equal, the <code>type</code> is then 
lexicographically compared (case-insensitive) in ascending order,
-        *      with the <js>"*"</js> type demoted last in that order.
-        * <code>MediaRanges</code> with the same type but different sub-types 
are compared - a more specific subtype is
-        *      promoted over the 'wildcard' subtype.
-        * <code>MediaRanges</code> with the same types but with extensions are 
promoted over those same types with no extensions.
-        *
-        * @param o The range to compare to.  Never <jk>null</jk>.
-        */
-       @Override /* Comparable */
-       public int compareTo(MediaRange o) {
-
-               // Compare q-values.
-               int qCompare = Float.compare(o.qValue, qValue);
-               if (qCompare != 0)
-                       return qCompare;
-
-               // Compare media-types.
-               // Note that '*' comes alphabetically before letters, so just 
do a reverse-alphabetical comparison.
-               int i = o.mediaType.toString().compareTo(mediaType.toString());
-               return i;
-       }
-
-       /**
-        * Matches the specified media type against this range and returns a 
q-value
-        * between 0 and 1 indicating the quality of the match.
-        *
-        * @param o The media type to match against.
-        * @return A float between 0 and 1.  1 is a perfect match.  0 is no 
match at all.
-        */
-       public float matches(MediaType o) {
-               if (this.mediaType == o || mediaType.matches(o))
-                       return qValue;
-               return 0;
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/MediaType.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/MediaType.java 
b/juneau-core/src/main/java/org/apache/juneau/MediaType.java
deleted file mode 100644
index 966f445..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/MediaType.java
+++ /dev/null
@@ -1,158 +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;
-
-import java.util.*;
-import java.util.concurrent.*;
-
-import org.apache.juneau.annotation.*;
-
-
-/**
- * Describes a single media type used in content negotiation between an HTTP 
client and server, as described in
- * Section 14.1 and 14.7 of RFC2616 (the HTTP/1.1 specification).
- */
-@BeanIgnore
-public final class MediaType {
-
-       private static final ConcurrentHashMap<String,MediaType> cache = new 
ConcurrentHashMap<String,MediaType>();
-
-       /** Reusable predefined media type */
-       @SuppressWarnings("javadoc")
-       public static final MediaType
-               CSV = forString("text/csv"),
-               HTML = forString("text/html"),
-               JSON = forString("application/json"),
-               MSGPACK = forString("octal/msgpack"),
-               PLAIN = forString("text/plain"),
-               UON = forString("text/uon"),
-               URLENCODING = forString("application/x-www-form-urlencoded"),
-               XML = forString("text/xml"),
-               XMLSOAP = forString("text/xml+soap"),
-
-               RDF = forString("text/xml+rdf"),
-               RDFABBREV = forString("text/xml+rdf+abbrev"),
-               NTRIPLE = forString("text/n-triple"),
-               TURTLE = forString("text/turtle"),
-               N3 = forString("text/n3")
-       ;
-
-       private final String mediaType;
-       private final String type;                                              
                // The media type (e.g. "text" for Accept, "utf-8" for 
Accept-Charset)
-       private final String subType;                   // The media sub-type 
(e.g. "json" for Accept, not used for Accept-Charset)
-
-       /**
-        * Returns the media type for the specified string.
-        * The same media type strings always return the same objects so that 
these objects
-        * can be compared for equality using '=='.
-        * <p>
-        * <h5 class='section'>Notes:</h5>
-        * <ul>
-        *      <li>Spaces are replaced with <js>'+'</js> characters.
-        *              This gets around the issue where passing media type 
strings with <js>'+'</js> as HTTP GET parameters
-        *              get replaced with spaces by your browser.  Since spaces 
aren't supported by the spec, this
-        *              is doesn't break anything.
-        *      <li>Anything including and following the <js>';'</js> character 
is ignored (e.g. <js>";charset=X"</js>).
-        * </ul>
-        *
-        * @param s The media type string.  Will be lowercased.
-        *      <br>Returns <jk>null</jk> if input is null.
-        * @return A cached media type object.
-        */
-       public static MediaType forString(String s) {
-               if (s == null)
-                       return null;
-               MediaType mt = cache.get(s);
-               if (mt == null) {
-                       mt = new MediaType(s);
-                       cache.putIfAbsent(s, mt);
-               }
-               return cache.get(s);
-       }
-
-       private MediaType(String mt) {
-               int i = mt.indexOf(';');
-               if (i != -1)
-                       mt = mt.substring(0, i);
-
-               mt = mt.toLowerCase(Locale.ENGLISH);
-               this.mediaType = mt;
-               String _type = null, _subType = null;
-               if (mt != null) {
-                       mt = mt.replace(' ', '+');
-                       i = mt.indexOf('/');
-                       _type = (i == -1 ? mt : mt.substring(0, i));
-                       _subType = (i == -1 ? "*" : mt.substring(i+1));
-               }
-               this.type = _type;
-               this.subType = _subType;
-       }
-
-       /**
-        * Returns the <js>'type'</js> fragment of the <js>'type/subType'</js> 
string.
-        *
-        * @return The media type.
-        */
-       public String getType() {
-               return type;
-       }
-
-       /**
-        * Returns the <js>'subType'</js> fragment of the 
<js>'type/subType'</js> string.
-        *
-        * @return The media subtype.
-        */
-       public String getSubType() {
-               return subType;
-       }
-
-       /**
-        * Returns <jk>true</jk> if this media type is a match for the 
specified media type.
-        * <p>
-        * Matches if any of the following is true:
-        * <ul>
-        *      <li>Both type and subtype are the same.
-        *      <li>One or both types are <js>'*'</js> and the subtypes are the 
same.
-        *      <li>One or both subtypes are <js>'*'</js> and the types are the 
same.
-        *      <li>Either is <js>'*\/*'</js>.
-        * </ul>
-        *
-        * @param o The media type to compare with.
-        * @return <jk>true</jk> if the media types match.
-        */
-       public final boolean matches(MediaType o) {
-               if (this == o)
-                       return true;
-
-               if (type.equals(o.type) || (type.equals("*")) || 
(o.type.equals("*")))
-                       if (subType.equals(o.subType) || subType.equals("*") || 
o.subType.equals("*"))
-                               return true;
-
-               return false;
-       }
-
-       @Override /* Object */
-       public String toString() {
-               return mediaType;
-       }
-
-       @Override /* Object */
-       public int hashCode() {
-               return mediaType.hashCode();
-       }
-
-       @Override /* Object */
-       public boolean equals(Object o) {
-               return this == o;
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/Streamable.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/Streamable.java 
b/juneau-core/src/main/java/org/apache/juneau/Streamable.java
index 6cb8237..84fb539 100644
--- a/juneau-core/src/main/java/org/apache/juneau/Streamable.java
+++ b/juneau-core/src/main/java/org/apache/juneau/Streamable.java
@@ -14,6 +14,8 @@ package org.apache.juneau;
 
 import java.io.*;
 
+import org.apache.juneau.http.*;
+
 /**
  * Interface that identifies that an object can be serialized directly to an 
output stream.
  * <p>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/Writable.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/Writable.java 
b/juneau-core/src/main/java/org/apache/juneau/Writable.java
index 20dd7e0..bd9298f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/Writable.java
+++ b/juneau-core/src/main/java/org/apache/juneau/Writable.java
@@ -14,6 +14,8 @@ package org.apache.juneau;
 
 import java.io.*;
 
+import org.apache.juneau.http.*;
+
 /**
  * Interface that identifies that an object can be serialized directly to a 
writer.
  * <p>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java 
b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
index a8d1fb1..addbbb7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.csv;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserSession.java 
b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserSession.java
index 151b8b6..548cbd2 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvParserSession.java
@@ -17,6 +17,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java 
b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
index 0715bb5..48d7ae3 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
@@ -15,6 +15,7 @@ package org.apache.juneau.csv;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java 
b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
index bee169f..163928b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
@@ -16,6 +16,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Operation.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Operation.java 
b/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Operation.java
index 8dc3e50..ff9a505 100644
--- a/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Operation.java
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Operation.java
@@ -14,8 +14,8 @@ package org.apache.juneau.dto.swagger;
 
 import java.util.*;
 
-import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 
 /**
  * Describes a single API operation on a path.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c3609d05/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Swagger.java 
b/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
index c40dbff..134d4e5 100644
--- a/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
@@ -14,8 +14,8 @@ package org.apache.juneau.dto.swagger;
 
 import java.util.*;
 
-import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
 import org.apache.juneau.utils.*;
 
 /**

Reply via email to