JUNEAU-33 - HTML5 DOM objects.

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

Branch: refs/heads/master
Commit: 74a90ffa768766d7d89106e54f38507150b525a6
Parents: d8b8e98
Author: JamesBognar <[email protected]>
Authored: Thu Feb 2 16:13:59 2017 -0500
Committer: JamesBognar <[email protected]>
Committed: Thu Feb 2 16:13:59 2017 -0500

----------------------------------------------------------------------
 .../java/org/apache/juneau/jena/RdfParser.java  |   4 +-
 .../apache/juneau/jena/RdfParserSession.java    |   5 +-
 .../org/apache/juneau/jena/RdfSerializer.java   |   4 +-
 .../juneau/jena/RdfSerializerSession.java       |   5 +-
 .../java/org/apache/juneau/MediaRangeTest.java  |  66 ++++
 .../juneau/a/rttests/RoundTripBeanMapsTest.java |   2 +-
 .../org/apache/juneau/ini/ConfigFileTest.java   |   4 +-
 .../juneau/transforms/LocalizedDatesTest.java   |   2 +-
 .../org/apache/juneau/xml/XmlContentTest.java   |   8 +-
 .../java/org/apache/juneau/BeanContext.java     |  24 +-
 .../java/org/apache/juneau/BeanSession.java     |  17 +-
 .../main/java/org/apache/juneau/ClassMeta.java  |  38 +-
 .../main/java/org/apache/juneau/MediaRange.java | 212 +++++------
 .../main/java/org/apache/juneau/MediaType.java  | 155 ++++++++
 .../main/java/org/apache/juneau/Swappable.java  |   8 +-
 .../main/java/org/apache/juneau/Writable.java   |   2 +-
 .../org/apache/juneau/dto/html5/package.html    |   2 +-
 .../apache/juneau/dto/swagger/Operation.java    |  23 +-
 .../org/apache/juneau/dto/swagger/Swagger.java  |  25 +-
 .../apache/juneau/encoders/EncoderGroup.java    | 168 +++++----
 .../apache/juneau/encoders/EncoderMatch.java    |  47 +++
 .../apache/juneau/html/HtmlDocSerializer.java   |   4 +-
 .../juneau/html/HtmlDocSerializerSession.java   |   5 +-
 .../java/org/apache/juneau/html/HtmlParser.java |   5 +-
 .../apache/juneau/html/HtmlParserSession.java   |   5 +-
 .../juneau/html/HtmlSchemaDocSerializer.java    |   4 +-
 .../org/apache/juneau/html/HtmlSerializer.java  |   4 +-
 .../juneau/html/HtmlSerializerSession.java      |   5 +-
 .../apache/juneau/ini/ConfigFileWritable.java   |   4 +-
 .../java/org/apache/juneau/json/JsonParser.java |   5 +-
 .../apache/juneau/json/JsonParserSession.java   |   6 +-
 .../org/apache/juneau/json/JsonSerializer.java  |   4 +-
 .../juneau/json/JsonSerializerSession.java      |   6 +-
 .../apache/juneau/msgpack/MsgPackParser.java    |   5 +-
 .../juneau/msgpack/MsgPackParserSession.java    |   6 +-
 .../juneau/msgpack/MsgPackSerializer.java       |   4 +-
 .../msgpack/MsgPackSerializerSession.java       |   6 +-
 .../java/org/apache/juneau/parser/Parser.java   |  44 ++-
 .../org/apache/juneau/parser/ParserGroup.java   | 150 ++++----
 .../org/apache/juneau/parser/ParserMatch.java   |  53 +++
 .../org/apache/juneau/parser/ParserSession.java |   5 +-
 .../apache/juneau/serializer/Serializer.java    |  45 ++-
 .../juneau/serializer/SerializerGroup.java      | 161 +++++----
 .../juneau/serializer/SerializerMatch.java      |  47 +++
 .../juneau/serializer/SerializerSession.java    |   6 +-
 .../apache/juneau/serializer/StringObject.java  |   2 +-
 .../juneau/serializer/WriterSerializer.java     |   2 +-
 .../org/apache/juneau/transform/PojoSwap.java   |  12 +-
 .../apache/juneau/urlencoding/UonParser.java    |   5 +-
 .../juneau/urlencoding/UonParserSession.java    |   7 +-
 .../juneau/urlencoding/UonSerializer.java       |   4 +-
 .../urlencoding/UonSerializerSession.java       |   5 +-
 .../juneau/urlencoding/UrlEncodingParser.java   |   5 +-
 .../urlencoding/UrlEncodingParserSession.java   |   5 +-
 .../urlencoding/UrlEncodingSerializer.java      |   6 +-
 .../UrlEncodingSerializerSession.java           |   5 +-
 .../java/org/apache/juneau/xml/XmlParser.java   |   5 +-
 .../org/apache/juneau/xml/XmlParserSession.java |   5 +-
 .../apache/juneau/xml/XmlSchemaSerializer.java  |   6 +-
 .../org/apache/juneau/xml/XmlSerializer.java    |   4 +-
 .../apache/juneau/xml/XmlSerializerSession.java |   5 +-
 juneau-core/src/main/javadoc/overview.html      |  16 +-
 .../apache/juneau/rest/client/RestClient.java   |   2 +-
 .../juneau/rest/client/RestRequestEntity.java   |   4 +-
 .../rest/client/SerializedNameValuePair.java    |   4 +-
 .../apache/juneau/rest/jaxrs/BaseProvider.java  |  27 +-
 .../org/apache/juneau/rest/test/GzipTest.java   |   2 +-
 .../org/apache/juneau/rest/ReaderResource.java  |   6 +-
 .../org/apache/juneau/rest/RestRequest.java     |  74 ++--
 .../org/apache/juneau/rest/RestResponse.java    |  29 +-
 .../org/apache/juneau/rest/RestServlet.java     |   8 +-
 .../apache/juneau/rest/jaxrs/BaseProvider.java  | 189 ----------
 .../juneau/rest/jaxrs/DefaultProvider.java      |  71 ----
 .../juneau/rest/jaxrs/JuneauProvider.java       |  96 -----
 .../org/apache/juneau/rest/jaxrs/package.html   | 360 -------------------
 .../rest/jaxrs/rdf/DefaultJenaProvider.java     |  91 -----
 .../apache/juneau/rest/jaxrs/rdf/package.html   |  34 --
 .../juneau/rest/response/DefaultHandler.java    |  22 +-
 .../juneau/rest/response/WritableHandler.java   |   4 +-
 79 files changed, 1093 insertions(+), 1439 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/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 604d98a..c62938d 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
@@ -432,8 +432,8 @@ public class RdfParser extends ReaderParser {
        
//--------------------------------------------------------------------------------
 
        @Override /* Parser */
-       public RdfParserSession createSession(Object input, ObjectMap op, 
Method javaMethod, Object outer, Locale locale, TimeZone timeZone) {
-               return new RdfParserSession(getContext(RdfParserContext.class), 
op, input, javaMethod, outer, locale, timeZone);
+       public RdfParserSession createSession(Object input, ObjectMap op, 
Method javaMethod, Object outer, Locale locale, TimeZone timeZone, MediaType 
mediaType) {
+               return new RdfParserSession(getContext(RdfParserContext.class), 
op, input, javaMethod, outer, locale, timeZone, mediaType);
        }
 
        @Override /* CoreApi */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/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 2c73a00..4433b38 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
@@ -62,9 +62,10 @@ public class RdfParserSession extends ParserSession {
         *      If <jk>null</jk>, then the locale defined on the context is 
used.
         * @param timeZone The session timezone.
         *      If <jk>null</jk>, then the timezone defined on the context is 
used.
+        * @param mediaType The session media type (e.g. 
<js>"application/json"</js>).
         */
-       protected RdfParserSession(RdfParserContext ctx, ObjectMap op, Object 
input, Method javaMethod, Object outer, Locale locale, TimeZone timeZone) {
-               super(ctx, op, input, javaMethod, outer, locale, timeZone);
+       protected RdfParserSession(RdfParserContext ctx, ObjectMap op, Object 
input, Method javaMethod, Object outer, Locale locale, TimeZone timeZone, 
MediaType mediaType) {
+               super(ctx, op, input, javaMethod, outer, locale, timeZone, 
mediaType);
                ObjectMap jenaSettings = new ObjectMap();
                jenaSettings.putAll(ctx.jenaSettings);
                if (op == null || op.isEmpty()) {

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/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 0728b39..83bad9d 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
@@ -397,8 +397,8 @@ public class RdfSerializer extends WriterSerializer {
        
//--------------------------------------------------------------------------------
 
        @Override /* Serializer */
-       public RdfSerializerSession createSession(Object output, ObjectMap op, 
Method javaMethod, Locale locale, TimeZone timeZone) {
-               return new 
RdfSerializerSession(getContext(RdfSerializerContext.class), op, output, 
javaMethod, locale, timeZone);
+       public RdfSerializerSession createSession(Object output, ObjectMap op, 
Method javaMethod, Locale locale, TimeZone timeZone, MediaType mediaType) {
+               return new 
RdfSerializerSession(getContext(RdfSerializerContext.class), op, output, 
javaMethod, locale, timeZone, mediaType);
        }
 
        @Override /* CoreApi */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/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 a204ab8..1c8b55b 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
@@ -55,9 +55,10 @@ public final class RdfSerializerSession extends 
SerializerSession {
         *      If <jk>null</jk>, then the locale defined on the context is 
used.
         * @param timeZone The session timezone.
         *      If <jk>null</jk>, then the timezone defined on the context is 
used.
+        * @param mediaType The session media type (e.g. 
<js>"application/json"</js>).
         */
-       protected RdfSerializerSession(RdfSerializerContext ctx, ObjectMap op, 
Object output, Method javaMethod, Locale locale, TimeZone timeZone) {
-               super(ctx, op, output, javaMethod, locale, timeZone);
+       protected RdfSerializerSession(RdfSerializerContext ctx, ObjectMap op, 
Object output, Method javaMethod, Locale locale, TimeZone timeZone, MediaType 
mediaType) {
+               super(ctx, op, output, javaMethod, locale, timeZone, mediaType);
                ObjectMap jenaSettings = new ObjectMap();
                jenaSettings.put("rdfXml.tab", isUseIndentation() ? 2 : 0);
                jenaSettings.put("rdfXml.attributeQuoteChar", 
Character.toString(getQuoteChar()));

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/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
new file mode 100644
index 0000000..f3fd216
--- /dev/null
+++ b/juneau-core-test/src/test/java/org/apache/juneau/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;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.juneau.json.JsonSerializer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * 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/74a90ffa/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
 
b/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
index 4ab6325..c610ee5 100755
--- 
a/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
+++ 
b/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
@@ -989,7 +989,7 @@ public class RoundTripBeanMapsTest extends RoundTripTest {
 
                Object r = s.serialize(n.n2);
                n = new N(2);
-               ParserSession session = p.createSession(r, null, null, n, null, 
null);
+               ParserSession session = p.createSession(r, null, null, n, null, 
null, null);
 
                N.N2 n2 = p.parse(session, 
BeanContext.DEFAULT.getClassMeta(N.N2.class));
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileTest.java 
b/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileTest.java
index 4ad91c8..6ea5a29 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileTest.java
@@ -1270,8 +1270,8 @@ public class ConfigFileTest {
                cfw.toWritable().writeTo(sw);
                assertTextEquals("a = b|", sw);
 
-               assertEquals("text/plain", cf.toWritable().getMediaType());
-               assertEquals("text/plain", cfw.toWritable().getMediaType());
+               assertEquals("text/plain", 
cf.toWritable().getMediaType().toString());
+               assertEquals("text/plain", 
cfw.toWritable().getMediaType().toString());
        }
 
        
//====================================================================================================

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core-test/src/test/java/org/apache/juneau/transforms/LocalizedDatesTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/transforms/LocalizedDatesTest.java
 
b/juneau-core-test/src/test/java/org/apache/juneau/transforms/LocalizedDatesTest.java
index 913c9a4..25fe320 100644
--- 
a/juneau-core-test/src/test/java/org/apache/juneau/transforms/LocalizedDatesTest.java
+++ 
b/juneau-core-test/src/test/java/org/apache/juneau/transforms/LocalizedDatesTest.java
@@ -625,7 +625,7 @@ public class LocalizedDatesTest {
 
        @Test
        public void test() {
-               BeanSession session = cf.getBeanContext().createSession(null, 
sessionLocale, sessionTimeZone);
+               BeanSession session = cf.getBeanContext().createSession(null, 
sessionLocale, sessionTimeZone, null);
                String actual = session.convertToType(calendar, String.class);
                assertEquals(expected, actual);
                Object c2 = session.convertToType(actual, calendar.getClass());

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java 
b/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java
index 80dd8cb..6872723 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java
@@ -47,7 +47,7 @@ public class XmlContentTest {
                t.f2 = null;
 
                sw = new StringWriter();
-               session = s1.createSession(sw, new 
ObjectMap("{"+SERIALIZER_trimNullProperties+":false}"), null, null, null);
+               session = s1.createSession(sw, new 
ObjectMap("{"+SERIALIZER_trimNullProperties+":false}"), null, null, null, null);
                s1.serialize(session, t);
                r = sw.toString();
                assertEquals("<A f1='f1'>_x0000_</A>", r);
@@ -55,7 +55,7 @@ public class XmlContentTest {
                assertEqualObjects(t, t2);
 
                sw = new StringWriter();
-               session = s2.createSession(sw, new 
ObjectMap("{"+SERIALIZER_trimNullProperties+":false}"), null, null, null);
+               session = s2.createSession(sw, new 
ObjectMap("{"+SERIALIZER_trimNullProperties+":false}"), null, null, null, null);
                s2.serialize(session, t);
                r = sw.toString();
                assertEquals("<A f1='f1'>_x0000_</A>\n", r);
@@ -155,7 +155,7 @@ public class XmlContentTest {
                t.f2 = null;
 
                sw = new StringWriter();
-               session = s1.createSession(sw, new 
ObjectMap("{"+SERIALIZER_trimNullProperties+":false}"), null, null, null);
+               session = s1.createSession(sw, new 
ObjectMap("{"+SERIALIZER_trimNullProperties+":false}"), null, null, null, null);
                s1.serialize(session, t);
                r = sw.toString();
                assertEquals("<A f1='f1'>_x0000_</A>", r);
@@ -163,7 +163,7 @@ public class XmlContentTest {
                assertEqualObjects(t, t2);
 
                sw = new StringWriter();
-               session = s2.createSession(sw, new 
ObjectMap("{"+SERIALIZER_trimNullProperties+":false}"), null, null, null);
+               session = s2.createSession(sw, new 
ObjectMap("{"+SERIALIZER_trimNullProperties+":false}"), null, null, null, null);
                s2.serialize(session, t);
                r = sw.toString();
                assertEquals("<A f1='f1'>_x0000_</A>\n", r);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/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 69d7542..a699825 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
@@ -927,6 +927,20 @@ public class BeanContext extends Context {
        public static final String BEAN_timeZone = "BeanContext.timeZone";
 
        /**
+        * <b>Configuration property:</b>  Media type.
+        * <p>
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.mediaType"</js>
+        *      <li><b>Data type:</b> <code>MediaType</code>
+        *      <li><b>Default:</b> <jk>null</jk>
+        *      <li><b>Session-overridable:</b> <jk>true</jk>
+        * </ul>
+        * <p>
+        * Specifies a default media type value for serializer and parser 
sessions.
+        */
+       public static final String BEAN_mediaType = "BeanContext.mediaType";
+
+       /**
         * <b>Configuration property:</b>  Debug mode.
         * <p>
         * <ul>
@@ -1032,6 +1046,7 @@ public class BeanContext extends Context {
        final ClassLoader classLoader;
        final Locale locale;
        final TimeZone timeZone;
+       final MediaType mediaType;
 
        final Map<Class,ClassMeta> cmCache;
        final ClassMeta<Object> cmObject;  // Reusable ClassMeta that 
represents general Objects.
@@ -1135,6 +1150,7 @@ public class BeanContext extends Context {
 
                locale = pm.get(BEAN_locale, Locale.class, Locale.getDefault());
                timeZone = pm.get(BEAN_timeZone, TimeZone.class, null);
+               mediaType = pm.get(BEAN_mediaType, MediaType.class, null);
 
                if (! cmCacheCache.containsKey(hashCode)) {
                        ConcurrentHashMap<Class,ClassMeta> cm = new 
ConcurrentHashMap<Class,ClassMeta>();
@@ -1164,10 +1180,11 @@ public class BeanContext extends Context {
         *      Typically used by time-sensitive {@link PojoSwap PojoSwaps} to 
provide timezone-specific output.
         *      If <jk>null</jk> the system default timezone is assumed on 
{@link Date} objects, or the
         *              locale specified on {@link Calendar} objects are used.
+        * @param mediaType The session media type (e.g. 
<js>"application/json"</js>).
         * @return A new session object.
         */
-       public BeanSession createSession(ObjectMap op, Locale locale, TimeZone 
timeZone) {
-               return new BeanSession(this, op, locale, timeZone);
+       public BeanSession createSession(ObjectMap op, Locale locale, TimeZone 
timeZone, MediaType mediaType) {
+               return new BeanSession(this, op, locale, timeZone, mediaType);
        }
 
        /**
@@ -1179,7 +1196,7 @@ public class BeanContext extends Context {
         * @return A new session object.
         */
        public BeanSession createSession() {
-               return new BeanSession(this, null, this.locale, this.timeZone);
+               return new BeanSession(this, null, this.locale, this.timeZone, 
this.mediaType);
        }
 
        /**
@@ -1911,6 +1928,7 @@ public class BeanContext extends Context {
                                .append("sortProperties", sortProperties)
                                .append("locale", locale)
                                .append("timeZone", timeZone)
+                               .append("mediaType", mediaType)
                        );
        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/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 9d2e5fe..dd1ccdf 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
@@ -37,6 +37,7 @@ public class BeanSession extends Session {
        private final BeanContext ctx;
        private final Locale locale;
        private final TimeZone timeZone;
+       private final MediaType mediaType;
        private final boolean debug;
        private Stack<StringBuilder> sbStack = new Stack<StringBuilder>();
 
@@ -51,18 +52,21 @@ public class BeanSession extends Session {
         *      If <jk>null</jk>, then the locale defined on the context is 
used.
         * @param timeZone The session timezone.
         *      If <jk>null</jk>, then the timezone defined on the context is 
used.
+        * @param mediaType The session media type (e.g. 
<js>"application/json"</js>).
         */
-       protected BeanSession(BeanContext ctx, ObjectMap op, Locale locale, 
TimeZone timeZone) {
+       protected BeanSession(BeanContext ctx, ObjectMap op, Locale locale, 
TimeZone timeZone, MediaType mediaType) {
                super(ctx, op);
                this.ctx = ctx;
                if (op == null || op.isEmpty()) {
                        this.locale = (locale != null ? locale : ctx.locale);
                        this.timeZone = (timeZone != null ? timeZone : 
ctx.timeZone);
                        this.debug = ctx.debug;
+                       this.mediaType = mediaType != null ? mediaType : 
ctx.mediaType;
                } else {
                        this.locale = (locale == null ? op.get(Locale.class, 
BEAN_locale, ctx.locale) : locale);
                        this.timeZone = (timeZone == null ? 
op.get(TimeZone.class, BEAN_timeZone, ctx.timeZone) : timeZone);
                        this.debug = op.getBoolean(BEAN_debug, false);
+                       this.mediaType = (mediaType == null ? 
op.get(MediaType.class, BEAN_mediaType, ctx.mediaType) : mediaType);
                }
        }
 
@@ -1070,6 +1074,17 @@ public class BeanSession extends Session {
                return ctx.classLoader;
        }
 
+       /**
+        * Returns the media type specified for this session.
+        * <p>
+        * For example, <js>"application/json"</js>.
+        *
+        * @return The media type for this session, or <jk>null</jk> if not 
specified.
+        */
+       public final MediaType getMediaType() {
+               return mediaType;
+       }
+
        @Override /* Session */
        public final ObjectMap asMap() {
                return super.asMap()

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java 
b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
index 38ee551..d7f112b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
@@ -24,6 +24,8 @@ import java.util.*;
 
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.serializer.*;
 import org.apache.juneau.transform.*;
 import org.apache.juneau.utils.*;
 
@@ -65,13 +67,15 @@ public final class ClassMeta<T> implements Type {
        InvocationHandler invocationHandler;              // The invocation 
handler for this class (if it has one).
        BeanMeta<T> beanMeta;                             // The bean meta for 
this bean class (if it's a bean).
        String dictionaryName, resolvedDictionaryName;    // The dictionary 
name of this class if it has one.
-       Method fromStringMethod;                          // The static 
valueOf(String) or fromString(String) method (if it has one).
+       Method fromStringMethod;                          // The static 
valueOf(String) or fromString(String) or forString(String) method (if it has 
one).
        Constructor<? extends T> noArgConstructor;        // The no-arg 
constructor for this class (if it has one).
        Constructor<T> stringConstructor;                 // The X(String) 
constructor (if it has one).
        Constructor<T> numberConstructor;                 // The X(Number) 
constructor (if it has one).
+       Constructor<T> swapConstructor;                   // The X(Swappable) 
constructor (if it has one).
        Class<? extends Number> numberConstructorType;    // The class type of 
the object in the number constructor.
        Constructor<T> objectMapConstructor;              // The X(ObjectMap) 
constructor (if it has one).
        Method toObjectMapMethod;                         // The toObjectMap() 
method (if it has one).
+       Method swapMethod;                                // The swap() method 
(if it has one).
        Method namePropertyMethod;                        // The method to set 
the name on an object (if it has one).
        Method parentPropertyMethod;                      // The method to set 
the parent on an object (if it has one).
        String notABeanReason;                            // If this isn't a 
bean, the reason why.
@@ -206,7 +210,7 @@ public final class ClassMeta<T> implements Type {
                        // valueOf() is used by enums.
                        // parse() is used by the java logging Level class.
                        // forName() is used by Class and Charset
-                       for (String methodName : new 
String[]{"fromString","valueOf","parse","parseString","forName"}) {
+                       for (String methodName : new 
String[]{"fromString","valueOf","parse","parseString","forName","forString"}) {
                                if (this.fromStringMethod == null) {
                                        for (Method m : c.getMethods()) {
                                                if (isStatic(m) && isPublic(m) 
&& isNotDeprecated(m)) {
@@ -240,6 +244,11 @@ public final class ClassMeta<T> implements Type {
                                                        this.toObjectMapMethod 
= m;
                                                        break;
                                                }
+                                       } else if (mName.equals("swap")) {
+                                               if 
(m.getParameterTypes().length == 1 && m.getParameterTypes()[0] == 
BeanSession.class) {
+                                                       this.swapMethod = m;
+                                                       break;
+                                               }
                                        }
                                }
                        }
@@ -266,6 +275,8 @@ public final class ClassMeta<T> implements Type {
                                                        this.stringConstructor 
= cs;
                                                else if 
(ObjectMap.class.isAssignableFrom(arg))
                                                        
this.objectMapConstructor = cs;
+                                               else if (swapMethod != null && 
swapMethod.getReturnType().getClass().isAssignableFrom(arg))
+                                                       this.swapConstructor = 
cs;
                                                else if (classCategory != 
NUMBER && (Number.class.isAssignableFrom(arg) || (arg.isPrimitive() && (arg == 
int.class || arg == short.class || arg == long.class || arg == float.class || 
arg == double.class)))) {
                                                        this.numberConstructor 
= cs;
                                                        
this.numberConstructorType = (Class<? extends 
Number>)ClassUtils.getWrapperIfPrimitive(arg);
@@ -274,6 +285,29 @@ public final class ClassMeta<T> implements Type {
                                }
                        }
 
+                       if (swapMethod != null) {
+                               this.pojoSwap = new PojoSwap<T,Object>(c, 
swapMethod.getReturnType()) {
+                                       @Override
+                                       public Object swap(BeanSession session, 
Object o) throws SerializeException {
+                                               try {
+                                                       return 
swapMethod.invoke(o, session);
+                                               } catch (Exception e) {
+                                                       throw new 
SerializeException(e);
+                                               }
+                                       }
+                                       @Override
+                                       public T unswap(BeanSession session, 
Object f, ClassMeta<?> hint) throws ParseException {
+                                               try {
+                                                       if (swapConstructor != 
null)
+                                                               return 
swapConstructor.newInstance(f);
+                                                       return 
super.unswap(session, f, hint);
+                                               } catch (Exception e) {
+                                                       throw new 
ParseException(e);
+                                               }
+                                       }
+                               };
+                       }
+
                        // Note:  Primitive types are normally abstract.
                        isAbstract = Modifier.isAbstract(c.getModifiers()) && ! 
isPrimitive();
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/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
index 36d862f..8ef60fd 100644
--- a/juneau-core/src/main/java/org/apache/juneau/MediaRange.java
+++ b/juneau-core/src/main/java/org/apache/juneau/MediaRange.java
@@ -13,20 +13,100 @@
 package org.apache.juneau;
 
 import java.util.*;
+import java.util.Map;
 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 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)
+       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.
         *
         * <h6 class='topic'>Examples:</h6>
@@ -38,17 +118,8 @@ public final class MediaRange implements 
Comparable<MediaRange>  {
         *
         * @return The media type of this media range, lowercased, never 
<jk>null</jk>.
         */
-       public String getMediaType() {
-               return type + "/" + subType;
-       }
-
-       /**
-        * Return just the type portion of this media range.
-        *
-        * @return The type portion of this media range.
-        */
-       public String getType() {
-               return type;
+       public MediaType getMediaType() {
+               return mediaType;
        }
 
        /**
@@ -99,14 +170,13 @@ public final class MediaRange implements 
Comparable<MediaRange>  {
         */
        @Override /* Object */
        public String toString() {
-               StringBuffer sb = new 
StringBuffer().append(type).append('/').append(subType);
+               StringBuffer sb = new StringBuffer().append(mediaType);
 
-               if (! parameters.isEmpty())
-                       for (Entry<String,Set<String>> e : 
parameters.entrySet()) {
-                               String k = e.getKey();
-                               for (String v : e.getValue())
-                                       
sb.append(';').append(k).append('=').append(v);
-                       }
+               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) {
@@ -145,8 +215,7 @@ public final class MediaRange implements 
Comparable<MediaRange>  {
 
                MediaRange o2 = (MediaRange) o;
                return qValue.equals(o2.qValue)
-                       && type.equals(o2.type)
-                       && subType.equals(o2.subType)
+                       && mediaType.equals(o2.mediaType)
                        && parameters.equals(o2.parameters)
                        && extensions.equals(o2.extensions);
        }
@@ -158,24 +227,7 @@ public final class MediaRange implements 
Comparable<MediaRange>  {
         */
        @Override /* Object */
        public int hashCode() {
-               return type.hashCode() + subType.hashCode();
-       }
-
-       /**
-        * Creates a <code>MediaRange</code> object with the referenced values.
-        *
-        * @param type The MIME type of this media range (e.g. 
<js>"application"</js> in <js>"application/json"</js>)
-        * @param subType The MIME subtype of this media range (e.g. 
<js>"json"</js> in <js>"application/json"</js>).
-        * @param parameters The optional parameters for this range.
-        * @param qValue The quality value of this range.  Must be between 
<code>0</code> and <code>1.0</code>.
-        * @param extensions The optional extensions to this quality value.
-        */
-       private MediaRange(String type, String subType, Map<String,Set<String>> 
parameters, Float qValue, Map<String,Set<String>> extensions) {
-               this.type = type;
-               this.subType = subType;
-               this.parameters = (parameters == null ? new 
TreeMap<String,Set<String>>() : parameters);
-               this.extensions = (extensions == null ? new 
TreeMap<String,Set<String>>() : extensions);
-               this.qValue = qValue;
+               return mediaType.hashCode();
        }
 
        /**
@@ -207,58 +259,23 @@ public final class MediaRange implements 
Comparable<MediaRange>  {
         */
        public static MediaRange[] parse(String value) {
 
-               Set<MediaRange> ranges = new TreeSet<MediaRange>();
-
                if (value == null || value.length() == 0)
-                       return new MediaRange[]{new MediaRange("*", "*", null, 
1f, null)};
+                       return DEFAULT;
 
                value = value.toLowerCase(Locale.ENGLISH);
 
-               for (String r : value.trim().split("\\s*,\\s*")) {
-                       r = r.trim();
-
-                       if (r.isEmpty())
-                               continue;
-
-                       String[] tokens = r.split("\\s*;\\s*");
+               if (value.indexOf(',') == -1)
+                       return new MediaRange[]{new MediaRange(value)};
 
-                       tokens[0] = tokens[0].replace(' ', '+');
+               Set<MediaRange> ranges = new TreeSet<MediaRange>();
 
-                       // There is at least a type.
-                       String[] t = tokens[0].split("/");
-                       String type = t[0], subType = (t.length == 1 ? "*" : 
t[1]);
+               for (String r : StringUtils.split(value, ',')) {
+                       r = r.trim();
 
-                       // Only the type of the range is specified
-                       if (tokens.length == 1) {
-                               ranges.add(new MediaRange(type, subType, null, 
1f, null));
+                       if (r.isEmpty())
                                continue;
-                       }
 
-                       Float qValue = 1f;
-                       Map<String,Set<String>> params = new 
TreeMap<String,Set<String>>();
-                       Map<String,Set<String>> exts = new 
TreeMap<String,Set<String>>();
-
-                       boolean isInExtensions = false;
-                       for (int i = 1; i < tokens.length; i++) {
-                               String[] parm = tokens[i].split("\\s*=\\s*");
-                               if (parm.length == 2) {
-                                       String k = parm[0], v = parm[1];
-                                       if (isInExtensions) {
-                                               if (! exts.containsKey(parm[0]))
-                                                       exts.put(parm[0], new 
TreeSet<String>());
-                                               exts.get(parm[0]).add(parm[1]);
-                                       } else if (k.equals("q")) {
-                                               qValue = new Float(v);
-                                               isInExtensions = true;
-                                       } else /*(! isInExtensions)*/ {
-                                               if (! 
params.containsKey(parm[0]))
-                                                       params.put(parm[0], new 
TreeSet<String>());
-                                               
params.get(parm[0]).add(parm[1]);
-                                       }
-                               }
-                       }
-
-                       ranges.add(new MediaRange(type, subType, params, 
qValue, exts));
+                       ranges.add(new MediaRange(r));
                }
 
                return ranges.toArray(new MediaRange[ranges.size()]);
@@ -286,31 +303,20 @@ public final class MediaRange implements 
Comparable<MediaRange>  {
 
                // Compare media-types.
                // Note that '*' comes alphabetically before letters, so just 
do a reverse-alphabetical comparison.
-               int i = o.type.compareTo(type);
-               if (i == 0)
-                       i = o.subType.compareTo(subType);
+               int i = o.mediaType.toString().compareTo(mediaType.toString());
                return i;
        }
 
        /**
-        * Returns <jk>true</jk> if the specified <code>MediaRange</code> 
matches this range.
-        * <p>
-        * This implies the types and subtypes are the same as or encompasses 
the other (e.g. <js>'application/xml'</js> and <js>'application/*'</js>).
+        * 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 other media rage.
-        * @return <jk>true</jk> if the media ranges are the same or one 
encompasses the other.
+        * @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 boolean matches(MediaRange o) {
-               if (this == o)
-                       return true;
-
-               if (qValue == 0 || o.qValue == 0)
-                       return false;
-
-               if (type.equals(o.type) || (type.equals("*")) || 
(o.type.equals("*")))
-                       if (subType.equals(o.subType) || subType.equals("*") || 
o.subType.equals("*"))
-                               return true;
-
-               return false;
+       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/74a90ffa/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
new file mode 100644
index 0000000..a6bd4ef
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/MediaType.java
@@ -0,0 +1,155 @@
+// 
***************************************************************************************************************************
+// * 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 Map<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>
+        * Note:  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.
+        * <p>
+        * Anything including and following the <js>';'</js> character is 
ignored (e.g. <js>";charset=X"</js>).
+        *
+        * @param s - The media type string.  Will be lowercased.
+        *      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>.
+        *
+        * @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/74a90ffa/juneau-core/src/main/java/org/apache/juneau/Swappable.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/Swappable.java 
b/juneau-core/src/main/java/org/apache/juneau/Swappable.java
index f9da08e..46a15a1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/Swappable.java
+++ b/juneau-core/src/main/java/org/apache/juneau/Swappable.java
@@ -20,7 +20,7 @@ package org.apache.juneau;
  * Allows fine-tuned controlling of serialization of classes by allowing you 
to create a surrogate
  * form of the class that then gets serialized instead of the original class.
  * <p>
- * During serialization, the {@link #swap(String)} method is used to convert 
this object into a serialized
+ * During serialization, the {@link #swap(BeanSession)} method is used to 
convert this object into a serialized
  * form.
  * <p>
  * Serialized form can be any object that can be serialized by this framework.
@@ -35,8 +35,10 @@ public interface Swappable<T> {
        /**
         * Method to implement that converts this object to a surrogate 
serialized form.
         *
-        * @param mediaType The media type string being serialized to (e.g. 
<js>"application/json"</js>).
+        * @param session The current bean session.
+        *      For example, you can use this to access the media type (e.g. 
<js>"application/json"</js>) and return
+        *      different values for different media types.
         * @return The surrogate object.
         */
-       public T swap(String mediaType);
+       public T swap(BeanSession session);
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/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 6590517..747990f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/Writable.java
+++ b/juneau-core/src/main/java/org/apache/juneau/Writable.java
@@ -36,5 +36,5 @@ public interface Writable {
         *
         * @return The media type, or <jk>null</jk> if the media type is not 
known.
         */
-       String getMediaType();
+       MediaType getMediaType();
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/dto/html5/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/html5/package.html 
b/juneau-core/src/main/java/org/apache/juneau/dto/html5/package.html
index f5b39d9..9523ea7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/dto/html5/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/html5/package.html
@@ -174,7 +174,7 @@
        <h3 class='topic' onclick='toggle(this)'>1.2 - Parsing HTML5</h3>
        <div class='topic'>
                <p>
-                       Use the {@link org.apache.juneau.xml.HtmlParser} to 
convert HTML5 documents back into their original POJOs:
+                       Use the {@link org.apache.juneau.html.HtmlParser} to 
convert HTML5 documents back into their original POJOs:
                </p>
                <p class='bcode'>
        <jc>// Get an HTML parser to convert our generated HTML5 documents back 
into POJOs.</jc>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/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 dbb0253..6978dab 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,6 +14,7 @@ package org.apache.juneau.dto.swagger;
 
 import java.util.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 
 /**
@@ -85,8 +86,8 @@ public class Operation {
        private String description;
        private ExternalDocumentation externalDocs;
        private String operationId;
-       private List<String> consumes;
-       private List<String> produces;
+       private List<MediaType> consumes;
+       private List<MediaType> produces;
        private List<ParameterInfo> parameters;
        private Map<String,ResponseInfo> responses;
        private List<String> schemes;
@@ -271,7 +272,7 @@ public class Operation {
         *
         * @return The value of the <property>consumes</property> property on 
this bean, or <jk>null</jk> if it is not set.
         */
-       public List<String> getConsumes() {
+       public List<MediaType> getConsumes() {
                return consumes;
        }
 
@@ -286,7 +287,7 @@ public class Operation {
         * @param consumes The new value for the <property>consumes</property> 
property on this bean.
         * @return This object (for method chaining).
         */
-       public Operation setConsumes(List<String> consumes) {
+       public Operation setConsumes(List<MediaType> consumes) {
                this.consumes = consumes;
                return this;
        }
@@ -303,7 +304,7 @@ public class Operation {
         * @return This object (for method chaining).
         */
        @SuppressWarnings("hiding")
-       public Operation addConsumes(String...consumes) {
+       public Operation addConsumes(MediaType...consumes) {
                return addConsumes(Arrays.asList(consumes));
        }
 
@@ -319,9 +320,9 @@ public class Operation {
         * @return This object (for method chaining).
         */
        @SuppressWarnings("hiding")
-       public Operation addConsumes(Collection<String> consumes) {
+       public Operation addConsumes(Collection<MediaType> consumes) {
                if (this.consumes == null)
-                       this.consumes = new LinkedList<String>();
+                       this.consumes = new LinkedList<MediaType>();
                this.consumes.addAll(consumes);
                return this;
        }
@@ -336,7 +337,7 @@ public class Operation {
         *
         * @return The value of the <property>produces</property> property on 
this bean, or <jk>null</jk> if it is not set.
         */
-       public List<String> getProduces() {
+       public List<MediaType> getProduces() {
                return produces;
        }
 
@@ -351,7 +352,7 @@ public class Operation {
         * @param produces The new value for the <property>produces</property> 
property on this bean.
         * @return This object (for method chaining).
         */
-       public Operation setProduces(List<String> produces) {
+       public Operation setProduces(List<MediaType> produces) {
                this.produces = produces;
                return this;
        }
@@ -368,9 +369,9 @@ public class Operation {
         * @return This object (for method chaining).
         */
        @SuppressWarnings("hiding")
-       public Operation addProduces(String...produces) {
+       public Operation addProduces(MediaType...produces) {
                if (this.produces == null)
-                       this.produces = new LinkedList<String>();
+                       this.produces = new LinkedList<MediaType>();
                this.produces.addAll(Arrays.asList(produces));
                return this;
        }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/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 90d9d4a..698b854 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,6 +14,7 @@ package org.apache.juneau.dto.swagger;
 
 import java.util.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 
 /**
@@ -29,8 +30,8 @@ public class Swagger {
        private Info info;
        private String host, basePath;
        private List<String> schemes;
-       private List<String> consumes;
-       private List<String> produces;
+       private List<MediaType> consumes;
+       private List<MediaType> produces;
        private Map<String,Map<String,Operation>> paths;
        private Map<String,SchemaInfo> definitions;
        private Map<String,ParameterInfo> parameters;
@@ -237,7 +238,7 @@ public class Swagger {
         *
         * @return The value of the <property>consumes</property> property on 
this bean, or <jk>null</jk> if it is not set.
         */
-       public List<String> getConsumes() {
+       public List<MediaType> getConsumes() {
                return consumes;
        }
 
@@ -251,7 +252,7 @@ public class Swagger {
         * @param consumes The new value for the <property>consumes</property> 
property on this bean.
         * @return This object (for method chaining).
         */
-       public Swagger setConsumes(List<String> consumes) {
+       public Swagger setConsumes(List<MediaType> consumes) {
                this.consumes = consumes;
                return this;
        }
@@ -267,7 +268,7 @@ public class Swagger {
         * @return This object (for method chaining).
         */
        @SuppressWarnings("hiding")
-       public Swagger addConsumes(String...consumes) {
+       public Swagger addConsumes(MediaType...consumes) {
                return addConsumes(Arrays.asList(consumes));
        }
 
@@ -282,9 +283,9 @@ public class Swagger {
         * @return This object (for method chaining).
         */
        @SuppressWarnings("hiding")
-       public Swagger addConsumes(Collection<String> consumes) {
+       public Swagger addConsumes(Collection<MediaType> consumes) {
                if (this.consumes == null)
-                       this.consumes = new LinkedList<String>();
+                       this.consumes = new LinkedList<MediaType>();
                this.consumes.addAll(consumes);
                return this;
        }
@@ -298,7 +299,7 @@ public class Swagger {
         *
         * @return The value of the <property>produces</property> property on 
this bean, or <jk>null</jk> if it is not set.
         */
-       public List<String> getProduces() {
+       public List<MediaType> getProduces() {
                return produces;
        }
 
@@ -312,7 +313,7 @@ public class Swagger {
         * @param produces The new value for the <property>produces</property> 
property on this bean.
         * @return This object (for method chaining).
         */
-       public Swagger setProduces(List<String> produces) {
+       public Swagger setProduces(List<MediaType> produces) {
                this.produces = produces;
                return this;
        }
@@ -328,7 +329,7 @@ public class Swagger {
         * @return This object (for method chaining).
         */
        @SuppressWarnings("hiding")
-       public Swagger addProduces(String...produces) {
+       public Swagger addProduces(MediaType...produces) {
                return addProduces(Arrays.asList(produces));
        }
 
@@ -343,9 +344,9 @@ public class Swagger {
         * @return This object (for method chaining).
         */
        @SuppressWarnings("hiding")
-       public Swagger addProduces(Collection<String> produces) {
+       public Swagger addProduces(Collection<MediaType> produces) {
                if (this.produces == null)
-                       this.produces = new LinkedList<String>();
+                       this.produces = new LinkedList<MediaType>();
                this.produces.addAll(produces);
                return this;
        }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroup.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroup.java 
b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroup.java
index ff0a4d4..3cb2050 100644
--- a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroup.java
+++ b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderGroup.java
@@ -15,8 +15,11 @@ package org.apache.juneau.encoders;
 import static org.apache.juneau.internal.ArrayUtils.*;
 
 import java.util.*;
+import java.util.concurrent.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.serializer.*;
 
 /**
  * Represents the group of {@link Encoder encoders} keyed by codings.
@@ -25,7 +28,7 @@ import org.apache.juneau.*;
  * <p>
  *     Maintains a set of encoders and the codings that they can handle.
  * <p>
- *     The {@link #findMatch(String)} and {@link #getEncoder(String)} methods 
are then
+ *     The {@link #getEncoderMatch(String)} and {@link #getEncoder(String)} 
methods are then
  *             used to find appropriate encoders for specific 
<code>Accept-Encoding</code>
  *             and <code>Content-Encoding</code> header values.
  *
@@ -51,79 +54,54 @@ import org.apache.juneau.*;
  *     IEncoder encoder = g.getEncoder(matchedCoding);
  * </p>
  */
-public final class EncoderGroup {
+public final class EncoderGroup extends Lockable {
 
-       private Map<String,EncoderEntry> entryMap = new 
TreeMap<String,EncoderEntry>(String.CASE_INSENSITIVE_ORDER);
-       private LinkedList<EncoderEntry> tempEntries = new 
LinkedList<EncoderEntry>();
-       private EncoderEntry[] entries;
+       // Maps Accept-Encoding headers to matching encoders.
+       private final Map<String,EncoderMatch> cache = new 
ConcurrentHashMap<String,EncoderMatch>();
 
-       /**
-        * Returns the coding string for the matching encoder that can handle 
the specified <code>Accept-Encoding</code>
-        *      or <code>Content-Encoding</code> header value.
-        * <p>
-        *      Returns <jk>null</jk> if no encoders can handle it.
-        * <p>
-        *      This method is fully compliant with the RFC2616/14.3 and 14.11 
specifications.
-        *
-        * @param acceptEncoding The <code>Accept-Encoding</code> or 
<code>Content-Encoding</code> value.
-        * @return The coding value (e.g. <js>"gzip"</js>).
-        */
-       public String findMatch(String acceptEncoding) {
-               if (getEntries().length == 0)
-                       return null;
-
-               MediaRange[] ae = MediaRange.parse(acceptEncoding);
-
-               if (ae.length == 0)
-                       ae = MediaRange.parse("*");
-
-               for (MediaRange a : ae)
-                       for (EncoderEntry e : getEntries())
-                               for (MediaRange a2 : e.encodingRanges)
-                                       if (a.matches(a2))
-                                               return a2.getType();
-
-               return null;
-       }
+       private final CopyOnWriteArrayList<Encoder> encoders = new 
CopyOnWriteArrayList<Encoder>();
 
        /**
-        * Adds the specified encoders to this group.
+        * Adds the specified encoder to the beginning of this group.
         *
-        * @param e The encoders to instantiate and add to this group.
+        * @param e - The encoder to add to this group.
         * @return This object (for method chaining).
-        * @throws Exception If an instantiation error occurred.
         */
-       public EncoderGroup append(Class<? extends Encoder>...e) throws 
Exception {
-               for (Class<? extends Encoder> r : reverse(e))
-                       append(r.newInstance());
+       public EncoderGroup append(Encoder e) {
+               checkLock();
+               synchronized(encoders) {
+                       cache.clear();
+                       encoders.add(0, e);
+               }
                return this;
        }
 
        /**
-        * Adds the specified encoders to this group.
+        * Registers the specified encoders with this group.
         *
-        * @param e The encoder to instantiate and add to this group.
+        * @param e The encoders to append to this group.
         * @return This object (for method chaining).
-        * @throws Exception If an instantiation error occurred.
+        * @throws Exception Thrown if {@link Encoder} could not be constructed.
         */
-       public EncoderGroup append(Class<? extends Encoder> e) throws Exception 
{
-               append(e.newInstance());
+       public EncoderGroup append(Class<? extends Encoder>...e) throws 
Exception {
+               for (Class<? extends Encoder> ee : ArrayUtils.reverse(e))
+                       append(ee);
                return this;
        }
 
        /**
-        * Adds the specified encoders to this group.
+        * Same as {@link #append(Class[])}, except specify a single class to 
avoid unchecked compile warnings.
         *
-        * @param e The encoders to add to this group.
+        * @param e The encoder to append to this group.
         * @return This object (for method chaining).
+        * @throws Exception Thrown if {@link Serializer} could not be 
constructed.
         */
-       public EncoderGroup append(Encoder...e) {
-               entries = null;
-               for (Encoder r : reverse(e)) {
-                       EncoderEntry ee = new EncoderEntry(r);
-                       tempEntries.addFirst(ee);
-                       for (String s : ee.encodings)
-                               this.entryMap.put(s, ee);
+       public EncoderGroup append(Class<? extends Encoder> e) throws Exception 
{
+               try {
+                       append(e.newInstance());
+               } catch (NoClassDefFoundError x) {
+                       // Ignore if dependent library not found (e.g. Jena).
+                       System.err.println(e);
                }
                return this;
        }
@@ -135,20 +113,66 @@ public final class EncoderGroup {
         * @return This object (for method chaining).
         */
        public EncoderGroup append(EncoderGroup g) {
-               for (EncoderEntry e : reverse(g.getEntries()))
-                       append(e.encoder);
+               for (Encoder e : reverse(g.encoders.toArray(new 
Encoder[g.encoders.size()])))
+                       append(e);
                return this;
        }
 
        /**
+        * Returns the coding string for the matching encoder that can handle 
the specified <code>Accept-Encoding</code>
+        *      or <code>Content-Encoding</code> header value.
+        * <p>
+        *      Returns <jk>null</jk> if no encoders can handle it.
+        * <p>
+        *      This method is fully compliant with the RFC2616/14.3 and 14.11 
specifications.
+        *
+        * @param acceptEncoding The <code>Accept-Encoding</code> or 
<code>Content-Encoding</code> value.
+        * @return The coding value (e.g. <js>"gzip"</js>).
+        */
+       public EncoderMatch getEncoderMatch(String acceptEncoding) {
+               if (encoders.size() == 0)
+                       return null;
+
+               EncoderMatch em = cache.get(acceptEncoding);
+               if (em != null)
+                       return em;
+
+               MediaRange[] ae = MediaRange.parse(acceptEncoding);
+
+               if (ae.length == 0)
+                       ae = MediaRange.parse("*/*");
+
+               Map<Float,EncoderMatch> m = null;
+
+               for (MediaRange a : ae) {
+                       for (Encoder e : encoders) {
+                               for (String c : e.getCodings()) {
+                                       MediaType mt = MediaType.forString(c);
+                                       float q = a.matches(mt);
+                                       if (q == 1) {
+                                               em = new EncoderMatch(mt, e);
+                                               cache.put(acceptEncoding, em);
+                                               return em;
+                                       } else if (q > 0) {
+                                               if (m == null)
+                                                       m = new 
TreeMap<Float,EncoderMatch>(Collections.reverseOrder());
+                                               m.put(q, new EncoderMatch(mt, 
e));
+                                       }
+                               }
+                       }
+               }
+               return (m == null ? null : m.values().iterator().next());
+       }
+
+       /**
         * Returns the encoder registered with the specified coding (e.g. 
<js>"gzip"</js>).
         *
         * @param coding The coding string.
         * @return The encoder, or <jk>null</jk> if encoder isn't registered 
with that coding.
         */
        public Encoder getEncoder(String coding) {
-               EncoderEntry e = entryMap.get(coding);
-               return (e == null ? null : e.encoder);
+               EncoderMatch em = getEncoderMatch(coding);
+               return (em == null ? null : em.getEncoder());
        }
 
        /**
@@ -158,36 +182,10 @@ public final class EncoderGroup {
         */
        public List<String> getSupportedEncodings() {
                List<String> l = new ArrayList<String>();
-               for (EncoderEntry e : getEntries())
-                       for (String enc : e.encodings)
+               for (Encoder e : encoders)
+                       for (String enc : e.getCodings())
                                if (! l.contains(enc))
                                        l.add(enc);
                return l;
        }
-
-       private EncoderEntry[] getEntries() {
-               if (entries == null)
-                       entries = tempEntries.toArray(new 
EncoderEntry[tempEntries.size()]);
-               return entries;
-       }
-
-       static class EncoderEntry {
-               Encoder encoder;
-               MediaRange[] encodingRanges;
-               String[] encodings;
-
-               EncoderEntry(Encoder e) {
-                       encoder = e;
-
-                       encodings = new String[e.getCodings().length];
-                       int i = 0;
-                       for (String enc : e.getCodings())
-                               encodings[i++] = enc;
-
-                       List<MediaRange> l = new LinkedList<MediaRange>();
-                       for (i = 0; i < encodings.length; i++)
-                               
l.addAll(Arrays.asList(MediaRange.parse(encodings[i])));
-                       encodingRanges = l.toArray(new MediaRange[l.size()]);
-               }
-       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderMatch.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderMatch.java 
b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderMatch.java
new file mode 100644
index 0000000..e05b3e7
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/encoders/EncoderMatch.java
@@ -0,0 +1,47 @@
+// 
***************************************************************************************************************************
+// * 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 org.apache.juneau.*;
+
+/**
+ * Represents a encoder and encoding that matches an HTTP 
<code>Accept-Encoding</code> header value.
+ */
+public final class EncoderMatch {
+
+       private final MediaType mediaType;
+       private final Encoder encoder;
+
+       EncoderMatch(MediaType mediaType, Encoder encoder) {
+               this.mediaType = mediaType;
+               this.encoder = encoder;
+       }
+
+       /**
+        * Returns the encoding of the encoder that matched the HTTP 
<code>Accept-Encoding</code> header value.
+        *
+        * @return The encoding of the match.
+        */
+       public String getEncoding() {
+               return mediaType.getType();
+       }
+
+       /**
+        * Returns the encoder that matched the HTTP 
<code>Accept-Encoding</code> header value.
+        *
+        * @return The encoder of the match.
+        */
+       public Encoder getEncoder() {
+               return encoder;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java 
b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
index badac2a..de30779 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
@@ -61,8 +61,8 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        
//--------------------------------------------------------------------------------
 
        @Override /* Serializer */
-       public HtmlDocSerializerSession createSession(Object output, ObjectMap 
op, Method javaMethod, Locale locale, TimeZone timeZone) {
-               return new 
HtmlDocSerializerSession(getContext(HtmlDocSerializerContext.class), op, 
output, javaMethod, locale, timeZone);
+       public HtmlDocSerializerSession createSession(Object output, ObjectMap 
op, Method javaMethod, Locale locale, TimeZone timeZone, MediaType mediaType) {
+               return new 
HtmlDocSerializerSession(getContext(HtmlDocSerializerContext.class), op, 
output, javaMethod, locale, timeZone, mediaType);
        }
 
        @Override /* Serializer */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
 
b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
index 0ad7e8f..de55239 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
@@ -51,10 +51,11 @@ public final class HtmlDocSerializerSession extends 
HtmlSerializerSession {
         *      If <jk>null</jk>, then the locale defined on the context is 
used.
         * @param timeZone The session timezone.
         *      If <jk>null</jk>, then the timezone defined on the context is 
used.
+        * @param mediaType The session media type (e.g. 
<js>"application/json"</js>).
         */
        @SuppressWarnings({ "unchecked", "rawtypes" })
-       protected HtmlDocSerializerSession(HtmlDocSerializerContext ctx, 
ObjectMap op, Object output, Method javaMethod, Locale locale, TimeZone 
timeZone) {
-               super(ctx, op, output, javaMethod, locale, timeZone);
+       protected HtmlDocSerializerSession(HtmlDocSerializerContext ctx, 
ObjectMap op, Object output, Method javaMethod, Locale locale, TimeZone 
timeZone, MediaType mediaType) {
+               super(ctx, op, output, javaMethod, locale, timeZone, mediaType);
                if (op == null || op.isEmpty()) {
                        title = ctx.title;
                        description = ctx.description;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java 
b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
index 4afe08c..1a88144 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
@@ -22,6 +22,7 @@ import java.util.*;
 import javax.xml.stream.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.MediaType;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
@@ -533,8 +534,8 @@ public final class HtmlParser extends XmlParser {
        
//--------------------------------------------------------------------------------
 
        @Override /* Parser */
-       public HtmlParserSession createSession(Object input, ObjectMap op, 
Method javaMethod, Object outer, Locale locale, TimeZone timeZone) {
-               return new 
HtmlParserSession(getContext(HtmlParserContext.class), op, input, javaMethod, 
outer, locale, timeZone);
+       public HtmlParserSession createSession(Object input, ObjectMap op, 
Method javaMethod, Object outer, Locale locale, TimeZone timeZone, MediaType 
mediaType) {
+               return new 
HtmlParserSession(getContext(HtmlParserContext.class), op, input, javaMethod, 
outer, locale, timeZone, mediaType);
        }
 
        @Override /* Parser */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserSession.java 
b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserSession.java
index 95febd7..80645af 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParserSession.java
@@ -60,9 +60,10 @@ public final class HtmlParserSession extends 
XmlParserSession {
         *      If <jk>null</jk>, then the locale defined on the context is 
used.
         * @param timeZone The session timezone.
         *      If <jk>null</jk>, then the timezone defined on the context is 
used.
+        * @param mediaType The session media type (e.g. 
<js>"application/json"</js>).
         */
-       public HtmlParserSession(HtmlParserContext ctx, ObjectMap op, Object 
input, Method javaMethod, Object outer, Locale locale, TimeZone timeZone) {
-               super(ctx, op, input, javaMethod, outer, locale, timeZone);
+       public HtmlParserSession(HtmlParserContext ctx, ObjectMap op, Object 
input, Method javaMethod, Object outer, Locale locale, TimeZone timeZone, 
MediaType mediaType) {
+               super(ctx, op, input, javaMethod, outer, locale, timeZone, 
mediaType);
        }
 
        /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java 
b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
index 44c50b9..1c481f5 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
@@ -65,8 +65,8 @@ public final class HtmlSchemaDocSerializer extends 
HtmlDocSerializer {
        }
 
        @Override /* Serializer */
-       public HtmlDocSerializerSession createSession(Object output, ObjectMap 
op, Method javaMethod, Locale locale, TimeZone timeZone) {
-               return new 
HtmlDocSerializerSession(getContext(HtmlDocSerializerContext.class), op, 
output, javaMethod, locale, timeZone);
+       public HtmlDocSerializerSession createSession(Object output, ObjectMap 
op, Method javaMethod, Locale locale, TimeZone timeZone, MediaType mediaType) {
+               return new 
HtmlDocSerializerSession(getContext(HtmlDocSerializerContext.class), op, 
output, javaMethod, locale, timeZone, mediaType);
        }
 
        @Override /* ISchemaSerializer */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java 
b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
index b835030..995015a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
@@ -650,8 +650,8 @@ public class HtmlSerializer extends XmlSerializer {
        
//--------------------------------------------------------------------------------
 
        @Override /* Serializer */
-       public HtmlSerializerSession createSession(Object output, ObjectMap op, 
Method javaMethod, Locale locale, TimeZone timeZone) {
-               return new 
HtmlSerializerSession(getContext(HtmlSerializerContext.class), op, output, 
javaMethod, locale, timeZone);
+       public HtmlSerializerSession createSession(Object output, ObjectMap op, 
Method javaMethod, Locale locale, TimeZone timeZone, MediaType mediaType) {
+               return new 
HtmlSerializerSession(getContext(HtmlSerializerContext.class), op, output, 
javaMethod, locale, timeZone, mediaType);
        }
 
        @Override /* Serializer */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java 
b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
index 8404adc..b97bb9e 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
@@ -55,9 +55,10 @@ public class HtmlSerializerSession extends 
XmlSerializerSession {
         *      If <jk>null</jk>, then the locale defined on the context is 
used.
         * @param timeZone The session timezone.
         *      If <jk>null</jk>, then the timezone defined on the context is 
used.
+        * @param mediaType The session media type (e.g. 
<js>"application/json"</js>).
         */
-       protected HtmlSerializerSession(HtmlSerializerContext ctx, ObjectMap 
op, Object output, Method javaMethod, Locale locale, TimeZone timeZone) {
-               super(ctx, op, output, javaMethod, locale, timeZone);
+       protected HtmlSerializerSession(HtmlSerializerContext ctx, ObjectMap 
op, Object output, Method javaMethod, Locale locale, TimeZone timeZone, 
MediaType mediaType) {
+               super(ctx, op, output, javaMethod, locale, timeZone, mediaType);
                String labelParameter;
                if (op == null || op.isEmpty()) {
                        anchorText = Enum.valueOf(AnchorText.class, 
ctx.uriAnchorText);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileWritable.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileWritable.java 
b/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileWritable.java
index 0945080..5bc7009 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileWritable.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileWritable.java
@@ -38,7 +38,7 @@ class ConfigFileWritable implements Writable {
        }
 
        @Override /* Writable */
-       public String getMediaType() {
-               return "text/plain";
+       public MediaType getMediaType() {
+               return MediaType.PLAIN;
        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java 
b/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
index be41f20..e141dd0 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
@@ -19,6 +19,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.MediaType;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
@@ -782,8 +783,8 @@ public final class JsonParser extends ReaderParser {
        
//--------------------------------------------------------------------------------
 
        @Override /* Parser */
-       public JsonParserSession createSession(Object input, ObjectMap op, 
Method javaMethod, Object outer, Locale locale, TimeZone timeZone) {
-               return new 
JsonParserSession(getContext(JsonParserContext.class), op, input, javaMethod, 
outer, locale, timeZone);
+       public JsonParserSession createSession(Object input, ObjectMap op, 
Method javaMethod, Object outer, Locale locale, TimeZone timeZone, MediaType 
mediaType) {
+               return new 
JsonParserSession(getContext(JsonParserContext.class), op, input, javaMethod, 
outer, locale, timeZone, mediaType);
        }
 
        @Override /* Parser */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/json/JsonParserSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/json/JsonParserSession.java 
b/juneau-core/src/main/java/org/apache/juneau/json/JsonParserSession.java
index 72650ec..11acf28 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonParserSession.java
@@ -17,6 +17,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.MediaType;
 import org.apache.juneau.parser.*;
 
 /**
@@ -49,9 +50,10 @@ public final class JsonParserSession extends ParserSession {
         *      If <jk>null</jk>, then the locale defined on the context is 
used.
         * @param timeZone The session timezone.
         *      If <jk>null</jk>, then the timezone defined on the context is 
used.
+        * @param mediaType The session media type (e.g. 
<js>"application/json"</js>).
         */
-       public JsonParserSession(JsonParserContext ctx, ObjectMap op, Object 
input, Method javaMethod, Object outer, Locale locale, TimeZone timeZone) {
-               super(ctx, op, input, javaMethod, outer, locale, timeZone);
+       public JsonParserSession(JsonParserContext ctx, ObjectMap op, Object 
input, Method javaMethod, Object outer, Locale locale, TimeZone timeZone, 
MediaType mediaType) {
+               super(ctx, op, input, javaMethod, outer, locale, timeZone, 
mediaType);
        }
 
        @Override /* ParserSession */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java 
b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
index ed87019..43ba2b5 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
@@ -331,8 +331,8 @@ public class JsonSerializer extends WriterSerializer {
        
//--------------------------------------------------------------------------------
 
        @Override /* Serializer */
-       public JsonSerializerSession createSession(Object output, ObjectMap op, 
Method javaMethod, Locale locale, TimeZone timeZone) {
-               return new 
JsonSerializerSession(getContext(JsonSerializerContext.class), op, output, 
javaMethod, locale, timeZone);
+       public JsonSerializerSession createSession(Object output, ObjectMap op, 
Method javaMethod, Locale locale, TimeZone timeZone, MediaType mediaType) {
+               return new 
JsonSerializerSession(getContext(JsonSerializerContext.class), op, output, 
javaMethod, locale, timeZone, mediaType);
        }
 
        @Override /* Serializer */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java 
b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
index b354fb7..ae0fb4a 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
@@ -18,6 +18,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.MediaType;
 import org.apache.juneau.serializer.*;
 
 /**
@@ -42,9 +43,10 @@ public final class JsonSerializerSession extends 
SerializerSession {
         *      If <jk>null</jk>, then the locale defined on the context is 
used.
         * @param timeZone The session timezone.
         *      If <jk>null</jk>, then the timezone defined on the context is 
used.
+        * @param mediaType The session media type (e.g. 
<js>"application/json"</js>).
         */
-       protected JsonSerializerSession(JsonSerializerContext ctx, ObjectMap 
op, Object output, Method javaMethod, Locale locale, TimeZone timeZone) {
-               super(ctx, op, output, javaMethod, locale, timeZone);
+       protected JsonSerializerSession(JsonSerializerContext ctx, ObjectMap 
op, Object output, Method javaMethod, Locale locale, TimeZone timeZone, 
MediaType mediaType) {
+               super(ctx, op, output, javaMethod, locale, timeZone, mediaType);
                if (op == null || op.isEmpty()) {
                        simpleMode = ctx.simpleMode;
                        useWhitespace = ctx.useWhitespace;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/74a90ffa/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java 
b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
index 2d1c764..a3f731a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
@@ -18,6 +18,7 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.MediaType;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.transform.*;
@@ -190,8 +191,8 @@ public final class MsgPackParser extends InputStreamParser {
        
//--------------------------------------------------------------------------------
 
        @Override /* Parser */
-       public MsgPackParserSession createSession(Object input, ObjectMap op, 
Method javaMethod, Object outer, Locale locale, TimeZone timeZone) {
-               return new 
MsgPackParserSession(getContext(MsgPackParserContext.class), op, input, 
javaMethod, outer, locale, timeZone);
+       public MsgPackParserSession createSession(Object input, ObjectMap op, 
Method javaMethod, Object outer, Locale locale, TimeZone timeZone, MediaType 
mediaType) {
+               return new 
MsgPackParserSession(getContext(MsgPackParserContext.class), op, input, 
javaMethod, outer, locale, timeZone, mediaType);
        }
 
        @Override /* Parser */


Reply via email to