juneau-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamesbog...@apache.org
Subject [12/34] incubator-juneau git commit: Add builder classes for all serializers and parsers.
Date Fri, 10 Mar 2017 16:51:08 GMT
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
new file mode 100644
index 0000000..96bb20b
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
@@ -0,0 +1,570 @@
+// ***************************************************************************************************************************
+// * 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.uon;
+
+import static org.apache.juneau.uon.UonSerializerContext.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.urlencoding.*;
+
+/**
+ * Builder class for building instances of UON serializers.
+ */
+public class UonSerializerBuilder extends SerializerBuilder {
+
+	/**
+	 * Constructor, default settings.
+	 */
+	public UonSerializerBuilder() {
+		super();
+	}
+
+	/**
+	 * Constructor.
+	 * @param propertyStore The initial configuration settings for this builder.
+	 */
+	public UonSerializerBuilder(PropertyStore propertyStore) {
+		super(propertyStore);
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializer build() {
+		return new UonSerializer(propertyStore);
+	}
+
+
+	//--------------------------------------------------------------------------------
+	// Properties
+	//--------------------------------------------------------------------------------
+
+	/**
+	 * <b>Configuration property:</b>  Encode non-valid URI characters.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"UonSerializer.encodeChars"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk> for {@link UonSerializer}, <jk>true</jk> for {@link UrlEncodingSerializer}
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Encode non-valid URI characters with <js>"%xx"</js> constructs.
+	 * <p>
+	 * If <jk>true</jk>, non-valid URI characters will be converted to <js>"%xx"</js> sequences.
+	 * Set to <jk>false</jk> if parameter value is being passed to some other code that will already
+	 * 	perform URL-encoding of non-valid URI characters.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>UON_encodeChars</jsf>, value)</code>.
+	 * 	<li>This introduces a slight performance penalty.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see UonSerializerContext#UON_encodeChars
+	 */
+	public UonSerializerBuilder encodeChars(boolean value) {
+		return property(UON_encodeChars, value);
+	}
+
+	/**
+	 * Shortcut for calling <code>setEncodeChars(true)</code>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public UonSerializerBuilder encoding() {
+		return encodeChars(true);
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder maxDepth(int value) {
+		super.maxDepth(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder initialDepth(int value) {
+		super.initialDepth(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder detectRecursions(boolean value) {
+		super.detectRecursions(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder ignoreRecursions(boolean value) {
+		super.ignoreRecursions(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder useWhitespace(boolean value) {
+		super.useWhitespace(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder ws() {
+		super.ws();
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder addBeanTypeProperties(boolean value) {
+		super.addBeanTypeProperties(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder quoteChar(char value) {
+		super.quoteChar(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder sq() {
+		super.sq();
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder trimNullProperties(boolean value) {
+		super.trimNullProperties(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder trimEmptyCollections(boolean value) {
+		super.trimEmptyCollections(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder trimEmptyMaps(boolean value) {
+		super.trimEmptyMaps(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder trimStrings(boolean value) {
+		super.trimStrings(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder relativeUriBase(String value) {
+		super.relativeUriBase(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder absolutePathUriBase(String value) {
+		super.absolutePathUriBase(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder sortCollections(boolean value) {
+		super.sortCollections(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public UonSerializerBuilder sortMaps(boolean value) {
+		super.sortMaps(value);
+		return this;
+	}
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beansRequireDefaultConstructor(boolean value) {
+		super.beansRequireDefaultConstructor(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beansRequireSerializable(boolean value) {
+		super.beansRequireSerializable(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beansRequireSettersForGetters(boolean value) {
+		super.beansRequireSettersForGetters(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beansRequireSomeProperties(boolean value) {
+		super.beansRequireSomeProperties(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beanMapPutReturnsOldValue(boolean value) {
+		super.beanMapPutReturnsOldValue(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beanConstructorVisibility(Visibility value) {
+		super.beanConstructorVisibility(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beanClassVisibility(Visibility value) {
+		super.beanClassVisibility(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beanFieldVisibility(Visibility value) {
+		super.beanFieldVisibility(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder methodVisibility(Visibility value) {
+		super.methodVisibility(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder useJavaBeanIntrospector(boolean value) {
+		super.useJavaBeanIntrospector(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder useInterfaceProxies(boolean value) {
+		super.useInterfaceProxies(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder ignoreUnknownBeanProperties(boolean value) {
+		super.ignoreUnknownBeanProperties(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder ignoreUnknownNullBeanProperties(boolean value) {
+		super.ignoreUnknownNullBeanProperties(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder ignorePropertiesWithoutSetters(boolean value) {
+		super.ignorePropertiesWithoutSetters(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder ignoreInvocationExceptionsOnGetters(boolean value) {
+		super.ignoreInvocationExceptionsOnGetters(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder ignoreInvocationExceptionsOnSetters(boolean value) {
+		super.ignoreInvocationExceptionsOnSetters(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder sortProperties(boolean value) {
+		super.sortProperties(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder notBeanPackages(String...values) {
+		super.notBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder notBeanPackages(Collection<String> values) {
+		super.notBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder setNotBeanPackages(String...values) {
+		super.setNotBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder setNotBeanPackages(Collection<String> values) {
+		super.setNotBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder removeNotBeanPackages(String...values) {
+		super.removeNotBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder removeNotBeanPackages(Collection<String> values) {
+		super.removeNotBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder notBeanClasses(Class<?>...values) {
+		super.notBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder notBeanClasses(Collection<Class<?>> values) {
+		super.notBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder setNotBeanClasses(Class<?>...values) {
+		super.setNotBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder setNotBeanClasses(Collection<Class<?>> values) {
+		super.setNotBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder removeNotBeanClasses(Class<?>...values) {
+		super.removeNotBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder removeNotBeanClasses(Collection<Class<?>> values) {
+		super.removeNotBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beanFilters(Class<?>...values) {
+		super.beanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beanFilters(Collection<Class<?>> values) {
+		super.beanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder setBeanFilters(Class<?>...values) {
+		super.setBeanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder setBeanFilters(Collection<Class<?>> values) {
+		super.setBeanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder removeBeanFilters(Class<?>...values) {
+		super.removeBeanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder removeBeanFilters(Collection<Class<?>> values) {
+		super.removeBeanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder pojoSwaps(Class<?>...values) {
+		super.pojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder pojoSwaps(Collection<Class<?>> values) {
+		super.pojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder setPojoSwaps(Class<?>...values) {
+		super.setPojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder setPojoSwaps(Collection<Class<?>> values) {
+		super.setPojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder removePojoSwaps(Class<?>...values) {
+		super.removePojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder removePojoSwaps(Collection<Class<?>> values) {
+		super.removePojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder implClasses(Map<Class<?>,Class<?>> values) {
+		super.implClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public <T> UonSerializerBuilder implClass(Class<T> interfaceClass, Class<? extends T> implClass) {
+		super.implClass(interfaceClass, implClass);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beanDictionary(Class<?>...values) {
+		super.beanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beanDictionary(Collection<Class<?>> values) {
+		super.beanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder setBeanDictionary(Class<?>...values) {
+		super.setBeanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder setBeanDictionary(Collection<Class<?>> values) {
+		super.setBeanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder removeFromBeanDictionary(Class<?>...values) {
+		super.removeFromBeanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder removeFromBeanDictionary(Collection<Class<?>> values) {
+		super.removeFromBeanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder beanTypePropertyName(String value) {
+		super.beanTypePropertyName(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder defaultParser(Class<?> value) {
+		super.defaultParser(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder locale(Locale value) {
+		super.locale(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder timeZone(TimeZone value) {
+		super.timeZone(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder mediaType(MediaType value) {
+		super.mediaType(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder debug(boolean value) {
+		super.debug(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder property(String name, Object value) {
+		super.property(name, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder properties(Map<String,Object> properties) {
+		super.properties(properties);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder addToProperty(String name, Object value) {
+		super.addToProperty(name, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder putToProperty(String name, Object key, Object value) {
+		super.putToProperty(name, key, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder putToProperty(String name, Object value) {
+		super.putToProperty(name, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder removeFromProperty(String name, Object value) {
+		super.removeFromProperty(name, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder classLoader(ClassLoader classLoader) {
+		super.classLoader(classLoader);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public UonSerializerBuilder apply(PropertyStore copyFrom) {
+		super.apply(copyFrom);
+		return this;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerContext.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerContext.java
new file mode 100644
index 0000000..b9ce464
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerContext.java
@@ -0,0 +1,100 @@
+// ***************************************************************************************************************************
+// * 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.uon;
+
+import org.apache.juneau.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.urlencoding.*;
+
+/**
+ * Configurable properties on the {@link UonSerializer} class.
+ * <p>
+ * Context properties are set by calling {@link PropertyStore#setProperty(String, Object)} on the property store
+ * passed into the constructor.
+ * <p>
+ * See {@link PropertyStore} for more information about context properties.
+ *
+ * <h5 class='section'>Inherited configurable properties:</h5>
+ * <ul class='javahierarchy'>
+ * 	<li class='c'><a class="doclink" href="../BeanContext.html#ConfigProperties">BeanContext</a> - Properties associated with handling beans on serializers and parsers.
+ * 	<ul>
+ * 		<li class='c'><a class="doclink" href="../serializer/SerializerContext.html#ConfigProperties">SerializerContext</a> - Configurable properties common to all serializers.
+ * 	</ul>
+ * </ul>
+ */
+public class UonSerializerContext extends SerializerContext {
+
+	/**
+	 * <b>Configuration property:</b>  Encode non-valid URI characters.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"UonSerializer.encodeChars"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk> for {@link UonSerializer}, <jk>true</jk> for {@link UrlEncodingSerializer}
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Encode non-valid URI characters with <js>"%xx"</js> constructs.
+	 * <p>
+	 * If <jk>true</jk>, non-valid URI characters will be converted to <js>"%xx"</js> sequences.
+	 * Set to <jk>false</jk> if parameter value is being passed to some other code that will already
+	 * 	perform URL-encoding of non-valid URI characters.
+	 */
+	public static final String UON_encodeChars = "UonSerializer.encodeChars";
+
+	/**
+	 * <b>Configuration property:</b>  Add <js>"_type"</js> properties when needed.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"UonSerializer.addBeanTypeProperties"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * If <jk>true</jk>, then <js>"_type"</js> properties will be added to beans if their type cannot be inferred through reflection.
+	 * This is used to recreate the correct objects during parsing if the object types cannot be inferred.
+	 * For example, when serializing a {@code Map<String,Object>} field, where the bean class cannot be determined from the value type.
+	 * <p>
+	 * When present, this value overrides the {@link SerializerContext#SERIALIZER_addBeanTypeProperties} setting and is
+	 * provided to customize the behavior of specific serializers in a {@link SerializerGroup}.
+	 */
+	public static final String UON_addBeanTypeProperties = "UonSerializer.addBeanTypeProperties";
+
+
+	final boolean
+		encodeChars,
+		addBeanTypeProperties;
+
+	/**
+	 * Constructor.
+	 * <p>
+	 * Typically only called from {@link PropertyStore#getContext(Class)}.
+	 *
+	 * @param ps The property store that created this context.
+	 */
+	public UonSerializerContext(PropertyStore ps) {
+		super(ps);
+		encodeChars = ps.getProperty(UON_encodeChars, boolean.class, false);
+		addBeanTypeProperties = ps.getProperty(UON_addBeanTypeProperties, boolean.class, ps.getProperty(SERIALIZER_addBeanTypeProperties, boolean.class, true));
+	}
+
+	@Override /* Context */
+	public ObjectMap asMap() {
+		return super.asMap()
+			.append("UonSerializerContext", new ObjectMap()
+				.append("encodeChars", encodeChars)
+				.append("addBeanTypeProperties", addBeanTypeProperties)
+			);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
new file mode 100644
index 0000000..92fbe56
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
@@ -0,0 +1,88 @@
+// ***************************************************************************************************************************
+// * 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.uon;
+
+import static org.apache.juneau.msgpack.MsgPackSerializerContext.*;
+import static org.apache.juneau.uon.UonSerializerContext.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * Session object that lives for the duration of a single use of {@link UonSerializer}.
+ * <p>
+ * This class is NOT thread safe.  It is meant to be discarded after one-time use.
+ */
+public class UonSerializerSession extends SerializerSession {
+
+	private final boolean
+		encodeChars,
+		addBeanTypeProperties;
+
+	/**
+	 * Create a new session using properties specified in the context.
+	 *
+	 * @param ctx The context creating this session object.
+	 * The context contains all the configuration settings for this object.
+	 * @param output The output object.  See {@link JsonSerializerSession#getWriter()} for valid class types.
+	 * @param op The override properties.
+	 * These override any context properties defined in the context.
+	 * @param javaMethod The java method that called this serializer, usually the method in a REST servlet.
+	 * @param locale The session locale.
+	 * 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 UonSerializerSession(UonSerializerContext 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()) {
+			encodeChars = ctx.encodeChars;
+			addBeanTypeProperties = ctx.addBeanTypeProperties;
+		} else {
+			encodeChars = op.getBoolean(UON_encodeChars, ctx.encodeChars);
+			addBeanTypeProperties = op.getBoolean(MSGPACK_addBeanTypeProperties, ctx.addBeanTypeProperties);
+		}
+	}
+
+	/**
+	 * Returns the {@link UonSerializerContext#UON_encodeChars} setting value for this session.
+	 *
+	 * @return The {@link UonSerializerContext#UON_encodeChars} setting value for this session.
+	 */
+	public final boolean isEncodeChars() {
+		return encodeChars;
+	}
+
+	/**
+	 * Returns the {@link UonSerializerContext#UON_addBeanTypeProperties} setting value for this session.
+	 *
+	 * @return The {@link UonSerializerContext#UON_addBeanTypeProperties} setting value for this session.
+	 */
+	@Override /* SerializerSession */
+	public final boolean isAddBeanTypeProperties() {
+		return addBeanTypeProperties;
+	}
+
+	@Override /* SerializerSession */
+	public final UonWriter getWriter() throws Exception {
+		Object output = getOutput();
+		if (output instanceof UonWriter)
+			return (UonWriter)output;
+		return new UonWriter(this, super.getWriter(), isUseWhitespace(), isEncodeChars(), isTrimStrings(), getRelativeUriBase(), getAbsolutePathUriBase());
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java
new file mode 100644
index 0000000..96f2405
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java
@@ -0,0 +1,281 @@
+// ***************************************************************************************************************************
+// * 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.uon;
+
+import java.io.*;
+
+import org.apache.juneau.internal.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * Specialized writer for serializing UON-encoded text.
+ * <p>
+ * <h5 class='section'>Notes:</h5>
+ * <ul>
+ * 	<li>This class is not intended for external use.
+ * </ul>
+ */
+public final class UonWriter extends SerializerWriter {
+
+	private final UonSerializerSession session;
+	private final boolean encodeChars;
+
+	// Characters that do not need to be URL-encoded in strings.
+	private static final AsciiSet unencodedChars = new AsciiSet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;/?:@-_.!*'$(),~=");
+
+	// Characters that do not need to be URL-encoded in attribute names.
+	// Identical to unencodedChars, but excludes '='.
+	private static final AsciiSet unencodedCharsAttrName = new AsciiSet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;/?:@-_.!*'$(),~");
+
+	// Characters that need to be preceeded with an escape character.
+	private static final AsciiSet escapedChars = new AsciiSet("~'");
+
+	private static final AsciiSet needsQuoteChars = new AsciiSet("),=\n\t\r\b\f ");
+
+	private static final AsciiSet maybeNeedsQuotesFirstChar = new AsciiSet("),=\n\t\r\b\f tfn+-.#0123456789");
+
+	private static char[] hexArray = "0123456789ABCDEF".toCharArray();
+
+	/**
+	 * Constructor.
+	 *
+	 * @param session The session that created this writer.
+	 * @param out The writer being wrapped.
+	 * @param useWhitespace If <jk>true</jk>, tabs will be used in output.
+	 * @param encodeChars If <jk>true</jk>, special characters should be encoded.
+	 * @param trimStrings If <jk>true</jk>, strings should be trimmed before they're serialized.
+	 * @param relativeUriBase The base (e.g. <js>https://localhost:9443/contextPath"</js>) for relative URIs (e.g. <js>"my/path"</js>).
+	 * @param absolutePathUriBase The base (e.g. <js>https://localhost:9443"</js>) for relative URIs with absolute paths (e.g. <js>"/contextPath/my/path"</js>).
+	 */
+	protected UonWriter(UonSerializerSession session, Writer out, boolean useWhitespace, boolean encodeChars, boolean trimStrings, String relativeUriBase, String absolutePathUriBase) {
+		super(out, useWhitespace, trimStrings, '\'', relativeUriBase, absolutePathUriBase);
+		this.session = session;
+		this.encodeChars = encodeChars;
+	}
+
+	/**
+	 * Serializes the specified simple object as a UON string value.
+	 *
+	 * @param o The object being serialized.
+	 * @param isTopAttrName If this is a top-level attribute name we're serializing.
+	 * @return This object (for method chaining).
+	 * @throws IOException Should never happen.
+	 */
+	public final UonWriter appendObject(Object o, boolean isTopAttrName) throws IOException {
+
+		if (o instanceof Boolean)
+			return appendBoolean(o);
+		if (o instanceof Number)
+			return appendNumber(o);
+		if (o == null)
+			return append("null");
+
+		String s = session.toString(o);
+		char c0 = s.isEmpty() ? 0 : s.charAt(0);
+
+		boolean needsQuotes =
+			s.isEmpty()
+			|| c0 == '@'
+			|| c0 == '('
+			|| needsQuoteChars.contains(s)
+			|| (
+				maybeNeedsQuotesFirstChar.contains(c0)
+				&& (
+					"true".equals(s)
+					|| "false".equals(s)
+					|| "null".equals(s)
+					|| StringUtils.isNumeric(s)
+				)
+			)
+		;
+
+		AsciiSet unenc = (isTopAttrName ? unencodedCharsAttrName : unencodedChars);
+		AsciiSet esc = escapedChars;
+
+		if (needsQuotes)
+			append('\'');
+		for (int i = 0; i < s.length(); i++) {
+			char c = s.charAt(i);
+			if (esc.contains(c))
+				append('~');
+			if ((!encodeChars) || unenc.contains(c))
+				append(c);
+			else {
+				if (c == ' ')
+					append('+');
+				else {
+					int p = s.codePointAt(i);
+					if (p < 0x0080)
+						appendHex(p);
+					else if (p < 0x0800) {
+						int p1=p>>>6;
+						appendHex(p1+192).appendHex((p&63)+128);
+					} else if (p < 0x10000) {
+						int p1=p>>>6, p2=p1>>>6;
+						appendHex(p2+224).appendHex((p1&63)+128).appendHex((p&63)+128);
+					} else {
+						i++;  // Two-byte codepoint...skip past surrogate pair lower byte.
+						int p1=p>>>6, p2=p1>>>6, p3=p2>>>6;
+						appendHex(p3+240).appendHex((p2&63)+128).appendHex((p1&63)+128).appendHex((p&63)+128);
+					}
+				}
+			}
+		}
+		if (needsQuotes)
+			append('\'');
+
+		return this;
+	}
+
+	/**
+	 * Appends a boolean value to the output.
+	 *
+	 * @param o The boolean value to append to the output.
+	 * @return This object (for method chaining).
+	 * @throws IOException
+	 */
+	protected UonWriter appendBoolean(Object o) throws IOException {
+		append(o.toString());
+		return this;
+	}
+
+	/**
+	 * Appends a numeric value to the output.
+	 *
+	 * @param o The numeric value to append to the output.
+	 * @return This object (for method chaining).
+	 * @throws IOException
+	 */
+	protected UonWriter appendNumber(Object o) throws IOException {
+		append(o.toString());
+		return this;
+	}
+
+	/**
+	 * Prints out a two-byte %xx sequence for the given byte value.
+	 */
+	private UonWriter appendHex(int b) throws IOException {
+		if (b > 255)
+			throw new IOException("Invalid value passed to appendHex.  Must be in the range 0-255.  Value=" + b);
+		append('%').append(hexArray[b>>>4]).append(hexArray[b&0x0F]);
+		return this;
+	}
+
+	/**
+	 * Appends a URI to the output.
+	 *
+	 * @param uri The URI to append to the output.
+	 * @return This object (for method chaining).
+	 * @throws IOException
+	 */
+	@Override
+	public SerializerWriter appendUri(Object uri) throws IOException {
+		String s = uri.toString();
+		if (s.indexOf("://") == -1) {
+			if (StringUtils.startsWith(s, '/')) {
+				if (absolutePathUriBase != null)
+					append(absolutePathUriBase);
+			} else {
+				if (relativeUriBase != null) {
+					append(relativeUriBase);
+					if (! relativeUriBase.equals("/"))
+						append("/");
+				}
+			}
+		}
+		return appendObject(s, false);
+	}
+
+
+	//--------------------------------------------------------------------------------
+	// Overridden methods
+	//--------------------------------------------------------------------------------
+
+	@Override /* SerializerWriter */
+	public UonWriter cr(int depth) throws IOException {
+		super.cr(depth);
+		return this;
+	}
+
+	@Override /* SerializerWriter */
+	public UonWriter appendln(int indent, String text) throws IOException {
+		super.appendln(indent, text);
+		return this;
+	}
+
+	@Override /* SerializerWriter */
+	public UonWriter appendln(String text) throws IOException {
+		super.appendln(text);
+		return this;
+	}
+
+	@Override /* SerializerWriter */
+	public UonWriter append(int indent, String text) throws IOException {
+		super.append(indent, text);
+		return this;
+	}
+
+	@Override /* SerializerWriter */
+	public UonWriter append(int indent, char c) throws IOException {
+		super.append(indent, c);
+		return this;
+	}
+
+	@Override /* SerializerWriter */
+	public UonWriter q() throws IOException {
+		super.q();
+		return this;
+	}
+
+	@Override /* SerializerWriter */
+	public UonWriter i(int indent) throws IOException {
+		super.i(indent);
+		return this;
+	}
+
+	@Override /* SerializerWriter */
+	public UonWriter nl() throws IOException {
+		super.nl();
+		return this;
+	}
+
+	@Override /* SerializerWriter */
+	public UonWriter append(Object text) throws IOException {
+		super.append(text);
+		return this;
+	}
+
+	@Override /* SerializerWriter */
+	public UonWriter append(String text) throws IOException {
+		super.append(text);
+		return this;
+	}
+
+	@Override /* SerializerWriter */
+	public UonWriter appendIf(boolean b, String text) throws IOException {
+		super.appendIf(b, text);
+		return this;
+	}
+
+	@Override /* SerializerWriter */
+	public UonWriter appendIf(boolean b, char c) throws IOException {
+		super.appendIf(b, c);
+		return this;
+	}
+
+	@Override /* SerializerWriter */
+	public UonWriter append(char c) throws IOException {
+		super.append(c);
+		return this;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/Example_HTML.png
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/Example_HTML.png b/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/Example_HTML.png
new file mode 100644
index 0000000..04dcf41
Binary files /dev/null and b/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/Example_HTML.png differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/rfc_uon.txt
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/rfc_uon.txt b/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/rfc_uon.txt
new file mode 100644
index 0000000..7880064
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/rfc_uon.txt
@@ -0,0 +1,294 @@
+Network Working Group                                          J. Bognar
+Request for Comments: 9999                                                
+Category: Informational                                       Salesforce
+                                                                Feb 2017
+
+                            ***DRAFT***
+               URI Object Notation (UON): Generic Syntax
+
+
+About this document
+
+   This memo provides information for the Internet community.  It does
+   not specify an Internet standard of any kind.  Distribution of this
+   memo is unlimited.
+
+Copyright Notice
+
+  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.
+
+Abstract
+
+   This document describes a grammar that builds upon RFC2396
+   (Uniform Resource Identifiers).  Its purpose is to define a 
+   generalized object notation for URI query parameter values similar in 
+   concept to Javascript Object Notation (RFC4627).  The goal is a 
+   syntax that allows for array and map structures to be
+   such that any data structure defined in JSON can be losslessly 
+   defined in an equivalent URI-based grammar, yet be fully compliant 
+   with the RFC2396 specification. 
+
+   This grammar provides the ability to construct the following data 
+   structures in URL parameter values: 
+	
+      OBJECT
+      ARRAY
+      NUMBER
+      BOOLEAN
+      STRING
+      NULL
+
+   Example:
+
+      The following shows a sample object defined in Javascript:
+
+         var x = { 
+            id: 1, 
+            name: 'John Smith', 
+            uri: 'http://sample/addressBook/person/1', 
+            addressBookUri: 'http://sample/addressBook', 
+            birthDate: '1946-08-12T00:00:00Z', 
+            otherIds: null,
+            addresses: [ 
+               { 
+                  uri: 'http://sample/addressBook/address/1', 
+                  personUri: 'http://sample/addressBook/person/1', 
+                  id: 1, 
+                  street: '100 Main Street', 
+                  city: 'Anywhereville', 
+                  state: 'NY', 
+                  zip: 12345, 
+                  isCurrent: true,
+               } 
+            ] 
+         } 
+
+      Using the syntax defined in this document, the equivalent 
+      UON notation would be as follows:
+
+         x=(id=1,name='John+Smith',uri=http://sample/
+         addressBook/person/1,addressBookUri=http://sample/
+         addressBook,birthDate=1946-08-12T00:00:00Z,otherIds=null,
+         addresses=@((uri=http://sample/addressBook/
+         address/1,personUri=http://sample/addressBook/
+         person/1,id=1,street='100+Main+Street',city=
+         Anywhereville,state=NY,zip=12345,isCurrent=true))) 
+
+1. Language constraints
+
+   The grammar syntax is constrained to usage of characters allowed by 
+      URI notation:
+
+      uric       = reserved | unreserved | escaped
+      reserved   = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
+                   "$" | ","
+      unreserved = alphanum | mark
+      mark       = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
+
+   In particular, the URI specification disallows the following 
+   characters in unencoded form:
+
+      unwise     = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
+      delims     = "<" | ">" | "#" | "%" | <">
+
+   The exclusion of {} and [] characters eliminates the possibility of 
+   using JSON as parameter values.
+
+
+2. Grammar constructs
+
+   The grammar consists of the following language constructs:
+   
+      Objects - Values consisting of one or more child name/value pairs.
+      Arrays - Values consisting of zero or more child values.
+      Booleans - Values consisting of true/false values.
+      Numbers - Decimal and floating point values.
+      Strings - Everything else.
+
+2.1. Objects 
+
+   Objects are values consisting of one or more child name/value pairs.
+   The (...) construct is used to define an object.
+
+   Example:  A simple map with two key/value pairs:
+
+      a1=(b1=x1,b2=x2)
+
+   Example:  A nested map:
+   
+      a1=(b1=(c1=x1,c2=x2))
+
+2.2. Arrays
+
+   Arrays are values consisting of zero or more child values.
+   The @(...) construct is used to define an array.
+
+   Example:  An array of two string values:
+
+      a1=@(x1,x2)
+
+   Example:  A 2-dimensional array:
+
+      a1=@(@(x1,x2),@(x3,x4))
+
+   Example:  An array of objects:
+
+      a1=@((b1=x1,b2=x2),(c1=x1,c2=x2))
+
+2.3. Booleans
+
+   Booleans are values that can only take on values "true" or "false".  
+   
+   Example:  Two boolean values:
+
+      a1=true&a2=false
+   
+2.4. Numbers
+
+   Numbers are represented without constructs.
+   Both decimal and float numbers are supported.
+   
+   Example:  Two numerical values, one decimal and one float:
+
+      a1=123&a2=1.23e1
+
+2.5. Null values
+
+   Nulls are represented by the keyword 'null':
+
+      a1=null
+
+2.6. Strings
+
+   Strings are encapsulated in single quote (') characters.
+   
+   Example:  Simple string values:
+
+      a1='foobar'&a2='123'&a3='true'
+         
+   The quotes are optional when the string cannot be confused
+   with one of the constructs listed above (i.e. objects/arrays/
+   booleans/numbers/null). 
+   
+   Example:  A simple string value, unquoted:
+
+      a1=foobar
+    
+   Strings must be quoted for the following cases:
+      
+      - The string can be confused with a boolean or number.
+      - The string is empty.
+      - The string contains one or more whitespace characters.
+      - The string starts with one of the following characters:
+        @ (
+      - The string contains any of the following characters:
+        ) , =
+   
+   For example, the string literal "(b1=x)" should be 
+   represented as follows:
+
+      a1='(b1=x)'
+   
+   The tilde character (~) is used for escaping characters to prevent 
+   them from being confused with syntax characters.  
+
+   The following characters must be escaped in string literals:  
+
+      ' ~
+   
+   Example:  The string "foo'bar~baz"
+
+      a1='foo~'bar~~baz'
+   
+2.7. Top-level attribute names
+
+   Top-level attribute names (e.g. "a1" in "&a1=foobar") are treated
+   as strings but for one exception.  The '=' character must be
+   encoded so as not to be confused as a key/value separator.
+   Note that the '=' character must also be escaped per the UON
+   notation.
+   
+   For example, the UON equivalent of {"a=b":"a=b"} constructed as
+   a top-level query parameter string would be as follows:
+   
+      a~%3Db=a~=b
+      
+   Note that the '=' character is encoded in the attribute name,
+   but it is not necessary to have it encoded in the attribute value.
+
+2.8. URL-encoded characters
+
+   UON notation allows for any character, even UON grammar
+   characters, to be URL-encoded.
+   
+   The following query strings are fully equivalent in structure:
+   
+     a1=(b1='x1',b2='x2')
+     %61%31=%79%6f%75%20%61%72%65%20%61%20%6e%65%72%64%21
+
+
+3. BNF
+
+   The following BNF describes the syntax for top-level URI query 
+   parameter values (e.g. ?<attrname>=<value>).
+
+   attrname    = (string | null)
+   value       = (var | string | null)
+
+   string      = ("'" litchar* "'") | litchar*
+   null        = "null"
+   
+   var         = ovar | avar | nvar | boolean | number
+   ovar        = "(" [pairs] ")"
+   avar        = "@(" [values] ")"
+
+   pairs       = pair ["," pairs]
+   pair        = key "=" value	
+   values      = value ["," values]
+   key         = (string | null)
+   boolean     = "true" | "false"
+
+   escape_seq  = "~" escaped
+   encode_seq  = "%" digithex digithex
+
+   number      = [-] (decimal | float) [exp]
+   decimal     = "0" | (digit19 digit*)
+   float       = decimal "." digit+
+   exp         = "e" [("+" | "-")] digit+
+
+   litchar     = unencoded | encode_seq | escape_seq
+   escaped     = "@" | "," | "(" | ")" | "~" | "=" 
+   unencoded   = alpha | digit | 
+                 ";" | "/" | "?" | ":" | "@" |
+                 "-" | "_" | "." | "!" | "*" | "'" 
+   alpha       = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
+                 "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
+                 "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" |
+                 "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" |             
+                 "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" |
+                 "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
+   digit       = "0" | digit19
+   digit19     = "1" | "2" | "3" | "4" | "5" | "6" | "7" |
+                 "8" | "9"
+   digithex    = digit | 
+                 "A" | "B" | "C" | "D" | "E" | "F" |
+                 "a" | "b" | "c" | "d" | "e" | "f"
+
+
+
+



Mime
View raw message