http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ab8f0faa/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlParserSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlParserSession.java
new file mode 100644
index 0000000..62de10e
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlParserSession.java
@@ -0,0 +1,669 @@
+// 
***************************************************************************************************************************
+// * 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.yaml.proto;
+
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.transform.*;
+
+/**
+ * Session object that lives for the duration of a single use of {@link 
YamlParser}.
+ *
+ * <p>
+ * This class is NOT thread safe.
+ * It is typically discarded after one-time use although it can be reused 
against multiple inputs.
+ */
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public final class YamlParserSession extends ReaderParserSession {
+
+       private static final AsciiSet decChars = new AsciiSet("0123456789");
+
+       /**
+        * 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 args
+        *      Runtime session arguments.
+        */
+       protected YamlParserSession(YamlParserContext ctx, ParserSessionArgs 
args) {
+               super(ctx, args);
+       }
+
+       /**
+        * Returns <jk>true</jk> if the specified character is whitespace.
+        *
+        * <p>
+        * The definition of whitespace is different for strict vs lax mode.
+        * Strict mode only interprets 0x20 (space), 0x09 (tab), 0x0A (line 
feed) and 0x0D (carriage return) as whitespace.
+        * Lax mode uses {@link Character#isWhitespace(int)} to make the 
determination.
+        *
+        * @param cp The codepoint.
+        * @return <jk>true</jk> if the specified character is whitespace.
+        */
+       protected final boolean isWhitespace(int cp) {
+               if (isStrict())
+                               return cp <= 0x20 && (cp == 0x09 || cp == 0x0A 
|| cp == 0x0D || cp == 0x20);
+               return Character.isWhitespace(cp);
+       }
+
+       /**
+        * Returns <jk>true</jk> if the specified character is whitespace or 
'/'.
+        *
+        * @param cp The codepoint.
+        * @return <jk>true</jk> if the specified character is whitespace or 
'/'.
+        */
+       protected final boolean isCommentOrWhitespace(int cp) {
+               if (cp == '/')
+                       return true;
+               if (isStrict())
+                       return cp <= 0x20 && (cp == 0x09 || cp == 0x0A || cp == 
0x0D || cp == 0x20);
+               return Character.isWhitespace(cp);
+       }
+
+       @Override /* ParserSession */
+       protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws 
Exception {
+               ParserReader r = pipe.getParserReader();
+               if (r == null)
+                       return null;
+               T o = parseAnything(type, r, getOuter(), null);
+               validateEnd(r);
+               return o;
+       }
+
+       @Override /* ReaderParserSession */
+       protected <K,V> Map<K,V> doParseIntoMap(ParserPipe pipe, Map<K,V> m, 
Type keyType, Type valueType) throws Exception {
+               ParserReader r = pipe.getParserReader();
+               m = parseIntoMap2(r, m, (ClassMeta<K>)getClassMeta(keyType), 
(ClassMeta<V>)getClassMeta(valueType), null);
+               validateEnd(r);
+               return m;
+       }
+
+       @Override /* ReaderParserSession */
+       protected <E> Collection<E> doParseIntoCollection(ParserPipe pipe, 
Collection<E> c, Type elementType) throws Exception {
+               ParserReader r = pipe.getParserReader();
+               c = parseIntoCollection2(r, c, getClassMeta(elementType), null);
+               validateEnd(r);
+               return c;
+       }
+
+       private <T> T parseAnything(ClassMeta<T> eType, ParserReader r, Object 
outer, BeanPropertyMeta pMeta) throws Exception {
+
+               if (eType == null)
+                       eType = (ClassMeta<T>)object();
+               PojoSwap<T,Object> swap = 
(PojoSwap<T,Object>)eType.getPojoSwap(this);
+               ClassMeta<?> sType = swap == null ? eType : 
swap.getSwapClassMeta(this);
+               setCurrentClass(sType);
+
+               Object o = null;
+
+               skipCommentsAndSpace(r);
+               int c = r.peek();
+               if (c == -1) {
+                       if (isStrict())
+                               throw new ParseException(r.getLocation(this), 
"Empty input.");
+                       // Let o be null.
+               } else if ((c == ',' || c == '}' || c == ']')) {
+                       if (isStrict())
+                               throw new ParseException(r.getLocation(this), 
"Missing value detected.");
+                       // Handle bug in Cognos 10.2.1 that can product 
non-existent values.
+                       // Let o be null;
+               } else if (c == 'n') {
+                       parseKeyword("null", r);
+               } else if (sType.isObject()) {
+                       if (c == '{') {
+                               ObjectMap m2 = new ObjectMap(this);
+                               parseIntoMap2(r, m2, string(), object(), pMeta);
+                               o = cast(m2, pMeta, eType);
+                       } else if (c == '[') {
+                               o = parseIntoCollection2(r, new 
ObjectList(this), object(), pMeta);
+                       } else if (c == '\'' || c == '"') {
+                               o = parseString(r);
+                               if (sType.isChar())
+                                       o = o.toString().charAt(0);
+                       } else if (c >= '0' && c <= '9' || c == '-' || c == 
'.') {
+                               o = parseNumber(r, null);
+                       } else if (c == 't') {
+                               parseKeyword("true", r);
+                               o = Boolean.TRUE;
+                       } else {
+                               parseKeyword("false", r);
+                               o = Boolean.FALSE;
+                       }
+               } else if (sType.isBoolean()) {
+                       o = parseBoolean(r);
+               } else if (sType.isCharSequence()) {
+                       o = parseString(r);
+               } else if (sType.isChar()) {
+                       o = parseString(r).charAt(0);
+               } else if (sType.isNumber()) {
+                       o = parseNumber(r, (Class<? extends 
Number>)sType.getInnerClass());
+               } else if (sType.isMap()) {
+                       Map m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : new ObjectMap(this));
+                       o = parseIntoMap2(r, m, sType.getKeyType(), 
sType.getValueType(), pMeta);
+               } else if (sType.isCollection()) {
+                       if (c == '{') {
+                               ObjectMap m = new ObjectMap(this);
+                               parseIntoMap2(r, m, string(), object(), pMeta);
+                               o = cast(m, pMeta, eType);
+                       } else {
+                               Collection l = 
(sType.canCreateNewInstance(outer) ? (Collection)sType.newInstance() : new 
ObjectList(this));
+                               o = parseIntoCollection2(r, l, sType, pMeta);
+                       }
+               } else if (sType.canCreateNewBean(outer)) {
+                       BeanMap m = newBeanMap(outer, sType.getInnerClass());
+                       o = parseIntoBeanMap2(r, m).getBean();
+               } else if (sType.canCreateNewInstanceFromString(outer) && (c == 
'\'' || c == '"')) {
+                       o = sType.newInstanceFromString(outer, parseString(r));
+               } else if (sType.canCreateNewInstanceFromNumber(outer) && 
isFirstNumberChar((char)c)) {
+                       o = sType.newInstanceFromNumber(this, outer, 
parseNumber(r, sType.getNewInstanceFromNumberClass()));
+               } else if (sType.isArray() || sType.isArgs()) {
+                       if (c == '{') {
+                               ObjectMap m = new ObjectMap(this);
+                               parseIntoMap2(r, m, string(), object(), pMeta);
+                               o = cast(m, pMeta, eType);
+                       } else {
+                               ArrayList l = 
(ArrayList)parseIntoCollection2(r, new ArrayList(), sType, pMeta);
+                               o = toArray(sType, l);
+                       }
+               } else if (c == '{') {
+                       Map m = new ObjectMap(this);
+                       parseIntoMap2(r, m, sType.getKeyType(), 
sType.getValueType(), pMeta);
+                       if (m.containsKey(getBeanTypePropertyName(eType)))
+                               o = cast((ObjectMap)m, pMeta, eType);
+                       else
+                               throw new ParseException(r.getLocation(this), 
"Class ''{0}'' could not be instantiated.  Reason: ''{1}''",
+                                               
sType.getInnerClass().getName(), sType.getNotABeanReason());
+               } else if (sType.canCreateNewInstanceFromString(outer) && ! 
isStrict()) {
+                       o = sType.newInstanceFromString(outer, parseString(r));
+               } else {
+                       throw new ParseException(r.getLocation(this), 
"Unrecognized syntax for class type ''{0}'', starting character ''{1}''",
+                               sType, (char)c);
+               }
+
+               if (swap != null && o != null)
+                       o = swap.unswap(this, o, eType);
+
+               if (outer != null)
+                       setParent(eType, o, outer);
+
+               return (T)o;
+       }
+
+       private Number parseNumber(ParserReader r, Class<? extends Number> 
type) throws Exception {
+               int c = r.peek();
+               if (c == '\'' || c == '"')
+                       return parseNumber(r, parseString(r), type);
+               return parseNumber(r, parseNumberString(r), type);
+       }
+
+       private Number parseNumber(ParserReader r, String s, Class<? extends 
Number> type) throws Exception {
+
+               // JSON has slightly different number rules from Java.
+               // Strict mode enforces these different rules, lax does not.
+               if (isStrict()) {
+
+                       // Lax allows blank strings to represent 0.
+                       // Strict does not allow blank strings.
+                       if (s.length() == 0)
+                               throw new ParseException(r.getLocation(this), 
"Invalid JSON number: ''{0}''", s);
+
+                       // Need to weed out octal and hexadecimal formats:  
0123,-0123,0x123,-0x123.
+                       // Don't weed out 0 or -0.
+                       boolean isNegative = false;
+                       char c = s.charAt(0);
+                       if (c == '-') {
+                               isNegative = true;
+                               c = (s.length() == 1 ? 'x' : s.charAt(1));
+                       }
+
+                       // JSON doesn't allow '.123' and '-.123'.
+                       if (c == '.')
+                               throw new ParseException(loc(r), "Invalid JSON 
number: ''{0}''", s);
+
+                       // '01' is not a valid number, but '0.1', '0e1', '0e+1' 
are valid.
+                       if (c == '0' && s.length() > (isNegative ? 2 : 1)) {
+                               char c2 = s.charAt((isNegative ? 2 : 1));
+                               if (c2 != '.' && c2 != 'e' && c2 != 'E')
+                                       throw new ParseException(loc(r), 
"Invalid JSON number: ''{0}''", s);
+                       }
+
+                       // JSON doesn't allow '1.' or '0.e1'.
+                       int i = s.indexOf('.');
+                       if (i != -1 && (s.length() == (i+1) || ! 
decChars.contains(s.charAt(i+1))))
+                               throw new ParseException(loc(r), "Invalid JSON 
number: ''{0}''", s);
+
+               }
+               return StringUtils.parseNumber(s, type);
+       }
+
+       private Boolean parseBoolean(ParserReader r) throws Exception {
+               int c = r.peek();
+               if (c == '\'' || c == '"')
+                       return Boolean.valueOf(parseString(r));
+               if (c == 't') {
+                       parseKeyword("true", r);
+                       return Boolean.TRUE;
+               }
+               parseKeyword("false", r);
+               return Boolean.FALSE;
+       }
+
+
+       private <K,V> Map<K,V> parseIntoMap2(ParserReader r, Map<K,V> m, 
ClassMeta<K> keyType,
+                       ClassMeta<V> valueType, BeanPropertyMeta pMeta) throws 
Exception {
+
+               if (keyType == null)
+                       keyType = (ClassMeta<K>)string();
+
+               int S0=0; // Looking for outer {
+               int S1=1; // Looking for attrName start.
+               int S3=3; // Found attrName end, looking for :.
+               int S4=4; // Found :, looking for valStart: { [ " ' LITERAL.
+               int S5=5; // Looking for , or }
+               int S6=6; // Found , looking for attr start.
+
+               int state = S0;
+               String currAttr = null;
+               int c = 0;
+               while (c != -1) {
+                       c = r.read();
+                       if (state == S0) {
+                               if (c == '{')
+                                       state = S1;
+                       } else if (state == S1) {
+                               if (c == '}') {
+                                       return m;
+                               } else if (isCommentOrWhitespace(c)) {
+                                       skipCommentsAndSpace(r.unread());
+                               } else {
+                                       currAttr = parseFieldName(r.unread());
+                                       state = S3;
+                               }
+                       } else if (state == S3) {
+                               if (c == ':')
+                                       state = S4;
+                       } else if (state == S4) {
+                               if (isCommentOrWhitespace(c)) {
+                                       skipCommentsAndSpace(r.unread());
+                               } else {
+                                       K key = convertAttrToType(m, currAttr, 
keyType);
+                                       V value = parseAnything(valueType, 
r.unread(), m, pMeta);
+                                       setName(valueType, value, key);
+                                       m.put(key, value);
+                                       state = S5;
+                               }
+                       } else if (state == S5) {
+                               if (c == ',')
+                                       state = S6;
+                               else if (isCommentOrWhitespace(c))
+                                       skipCommentsAndSpace(r.unread());
+                               else if (c == '}') {
+                                       return m;
+                               } else {
+                                       break;
+                               }
+                       } else if (state == S6) {
+                               if (c == '}') {
+                                       break;
+                               } else if (isCommentOrWhitespace(c)) {
+                                       skipCommentsAndSpace(r.unread());
+                               } else {
+                                       currAttr = parseFieldName(r.unread());
+                                       state = S3;
+                               }
+                       }
+               }
+               if (state == S0)
+                       throw new ParseException(loc(r), "Expected '{' at 
beginning of JSON object.");
+               if (state == S1)
+                       throw new ParseException(loc(r), "Could not find 
attribute name on JSON object.");
+               if (state == S3)
+                       throw new ParseException(loc(r), "Could not find ':' 
following attribute name on JSON object.");
+               if (state == S4)
+                       throw new ParseException(loc(r), "Expected one of the 
following characters: {,[,',\",LITERAL.");
+               if (state == S5)
+                       throw new ParseException(loc(r), "Could not find '}' 
marking end of JSON object.");
+               if (state == S6)
+                       throw new ParseException(loc(r), "Unexpected '}' found 
in JSON object.");
+
+               return null; // Unreachable.
+       }
+
+       /*
+        * Parse a JSON attribute from the character array at the specified 
position, then
+        * set the position marker to the last character in the field name.
+        */
+       private String parseFieldName(ParserReader r) throws Exception {
+               int c = r.peek();
+               if (c == '\'' || c == '"')
+                       return parseString(r);
+               if (isStrict())
+                       throw new ParseException(loc(r), "Unquoted attribute 
detected.");
+               r.mark();
+               // Look for whitespace.
+               while (c != -1) {
+                       c = r.read();
+                       if (c == ':' || isWhitespace(c) || c == '/') {
+                               r.unread();
+                               String s = r.getMarked().intern();
+                               return s.equals("null") ? null : s;
+                       }
+               }
+               throw new ParseException(loc(r), "Could not find the end of the 
field name.");
+       }
+
+       private <E> Collection<E> parseIntoCollection2(ParserReader r, 
Collection<E> l,
+                       ClassMeta<?> type, BeanPropertyMeta pMeta) throws 
Exception {
+
+               int S0=0; // Looking for outermost [
+               int S1=1; // Looking for starting [ or { or " or ' or LITERAL 
or ]
+               int S2=2; // Looking for , or ]
+               int S3=3; // Looking for starting [ or { or " or ' or LITERAL
+
+               int argIndex = 0;
+
+               int state = S0;
+               int c = 0;
+               while (c != -1) {
+                       c = r.read();
+                       if (state == S0) {
+                               if (c == '[')
+                                       state = S1;
+                       } else if (state == S1) {
+                               if (c == ']') {
+                                       return l;
+                               } else if (isCommentOrWhitespace(c)) {
+                                       skipCommentsAndSpace(r.unread());
+                               } else if (c != -1) {
+                                       l.add((E)parseAnything(type.isArgs() ? 
type.getArg(argIndex++) : type.getElementType(), r.unread(), l, pMeta));
+                                       state = S2;
+                               }
+                       } else if (state == S2) {
+                               if (c == ',') {
+                                       state = S3;
+                               } else if (isCommentOrWhitespace(c)) {
+                                       skipCommentsAndSpace(r.unread());
+                               } else if (c == ']') {
+                                       return l;
+                               } else {
+                                       break;  // Invalid character found.
+                               }
+                       } else if (state == S3) {
+                               if (isCommentOrWhitespace(c)) {
+                                       skipCommentsAndSpace(r.unread());
+                               } else if (c == ']') {
+                                       break;
+                               } else if (c != -1) {
+                                       l.add((E)parseAnything(type.isArgs() ? 
type.getArg(argIndex++) : type.getElementType(), r.unread(), l, pMeta));
+                                       state = S2;
+                               }
+                       }
+               }
+               if (state == S0)
+                       throw new ParseException(loc(r), "Expected '[' at 
beginning of JSON array.");
+               if (state == S1)
+                       throw new ParseException(loc(r), "Expected one of the 
following characters: {,[,',\",LITERAL.");
+               if (state == S2)
+                       throw new ParseException(loc(r), "Expected ',' or 
']'.");
+               if (state == S3)
+                       throw new ParseException(loc(r), "Unexpected trailing 
comma in array.");
+
+               return null;  // Unreachable.
+       }
+
+       private <T> BeanMap<T> parseIntoBeanMap2(ParserReader r, BeanMap<T> m) 
throws Exception {
+
+               int S0=0; // Looking for outer {
+               int S1=1; // Looking for attrName start.
+               int S3=3; // Found attrName end, looking for :.
+               int S4=4; // Found :, looking for valStart: { [ " ' LITERAL.
+               int S5=5; // Looking for , or }
+
+               int state = S0;
+               String currAttr = "";
+               int c = 0;
+               int currAttrLine = -1, currAttrCol = -1;
+               while (c != -1) {
+                       c = r.read();
+                       if (state == S0) {
+                               if (c == '{')
+                                       state = S1;
+                       } else if (state == S1) {
+                               if (c == '}') {
+                                       return m;
+                               } else if (isCommentOrWhitespace(c)) {
+                                       skipCommentsAndSpace(r.unread());
+                               } else {
+                                       r.unread();
+                                       currAttrLine= r.getLine();
+                                       currAttrCol = r.getColumn();
+                                       currAttr = parseFieldName(r);
+                                       state = S3;
+                               }
+                       } else if (state == S3) {
+                               if (c == ':')
+                                       state = S4;
+                       } else if (state == S4) {
+                               if (isCommentOrWhitespace(c)) {
+                                       skipCommentsAndSpace(r.unread());
+                               } else {
+                                       if (! 
currAttr.equals(getBeanTypePropertyName(m.getClassMeta()))) {
+                                               BeanPropertyMeta pMeta = 
m.getPropertyMeta(currAttr);
+                                               setCurrentProperty(pMeta);
+                                               if (pMeta == null) {
+                                                       
onUnknownProperty(r.getPipe(), currAttr, m, currAttrLine, currAttrCol);
+                                                       parseAnything(object(), 
r.unread(), m.getBean(false), null); // Read content anyway to ignore it
+                                               } else {
+                                                       ClassMeta<?> cm = 
pMeta.getClassMeta();
+                                                       Object value = 
parseAnything(cm, r.unread(), m.getBean(false), pMeta);
+                                                       setName(cm, value, 
currAttr);
+                                                       pMeta.set(m, currAttr, 
value);
+                                               }
+                                               setCurrentProperty(null);
+                                       }
+                                       state = S5;
+                               }
+                       } else if (state == S5) {
+                               if (c == ',')
+                                       state = S1;
+                               else if (isCommentOrWhitespace(c))
+                                       skipCommentsAndSpace(r.unread());
+                               else if (c == '}') {
+                                       return m;
+                               }
+                       }
+               }
+               if (state == S0)
+                       throw new ParseException(loc(r), "Expected '{' at 
beginning of JSON object.");
+               if (state == S1)
+                       throw new ParseException(loc(r), "Could not find 
attribute name on JSON object.");
+               if (state == S3)
+                       throw new ParseException(loc(r), "Could not find ':' 
following attribute name on JSON object.");
+               if (state == S4)
+                       throw new ParseException(loc(r), "Expected one of the 
following characters: {,[,',\",LITERAL.");
+               if (state == S5)
+                       throw new ParseException(loc(r), "Could not find '}' 
marking end of JSON object.");
+
+               return null; // Unreachable.
+       }
+
+       /*
+        * Starting from the specified position in the character array, returns 
the
+        * position of the character " or '.
+        * If the string consists of a concatenation of strings (e.g. 'AAA' + 
"BBB"), this method
+        * will automatically concatenate the strings and return the result.
+        */
+       private String parseString(ParserReader r) throws Exception  {
+               r.mark();
+               int qc = r.read();              // The quote character being 
used (" or ')
+               if (qc != '"' && isStrict()) {
+                       String msg = (
+                               qc == '\''
+                               ? "Invalid quote character \"{0}\" being used."
+                               : "Did not find quote character marking 
beginning of string.  Character=\"{0}\""
+                       );
+                       throw new ParseException(loc(r), msg, (char)qc);
+               }
+               final boolean isQuoted = (qc == '\'' || qc == '"');
+               String s = null;
+               boolean isInEscape = false;
+               int c = 0;
+               while (c != -1) {
+                       c = r.read();
+                       // Strict syntax requires that all control characters 
be escaped.
+                       if (isStrict() && c <= 0x1F)
+                               throw new ParseException("Unescaped control 
character encountered: ''0x{0}''", String.format("%04X", c));
+                       if (isInEscape) {
+                               switch (c) {
+                                       case 'n': r.replace('\n'); break;
+                                       case 'r': r.replace('\r'); break;
+                                       case 't': r.replace('\t'); break;
+                                       case 'f': r.replace('\f'); break;
+                                       case 'b': r.replace('\b'); break;
+                                       case '\\': r.replace('\\'); break;
+                                       case '/': r.replace('/'); break;
+                                       case '\'': r.replace('\''); break;
+                                       case '"': r.replace('"'); break;
+                                       case 'u': {
+                                               String n = r.read(4);
+                                               try {
+                                                       
r.replace(Integer.parseInt(n, 16), 6);
+                                               } catch (NumberFormatException 
e) {
+                                                       throw new 
ParseException(loc(r), "Invalid Unicode escape sequence in string.");
+                                               }
+                                               break;
+                                       }
+                                       default:
+                                               throw new 
ParseException(loc(r), "Invalid escape sequence in string.");
+                               }
+                               isInEscape = false;
+                       } else {
+                               if (c == '\\') {
+                                       isInEscape = true;
+                                       r.delete();
+                               } else if (isQuoted) {
+                                       if (c == qc) {
+                                               s = r.getMarked(1, -1);
+                                               break;
+                                       }
+                               } else {
+                                       if (c == ',' || c == '}' || c == ']' || 
isWhitespace(c)) {
+                                               s = r.getMarked(0, -1);
+                                               r.unread();
+                                               break;
+                                       } else if (c == -1) {
+                                               s = r.getMarked(0, 0);
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               if (s == null)
+                       throw new ParseException(loc(r), "Could not find 
expected end character ''{0}''.", (char)qc);
+
+               // Look for concatenated string (i.e. whitespace followed by +).
+               skipCommentsAndSpace(r);
+               if (r.peek() == '+') {
+                       if (isStrict())
+                               throw new ParseException(loc(r), "String 
concatenation detected.");
+                       r.read();       // Skip past '+'
+                       skipCommentsAndSpace(r);
+                       s += parseString(r);
+               }
+               return trim(s); // End of input reached.
+       }
+
+       /*
+        * Looks for the keywords true, false, or null.
+        * Throws an exception if any of these keywords are not found at the 
specified position.
+        */
+       private void parseKeyword(String keyword, ParserReader r) throws 
Exception {
+               try {
+                       String s = r.read(keyword.length());
+                       if (s.equals(keyword))
+                               return;
+                       throw new ParseException(loc(r), "Unrecognized 
syntax.");
+               } catch (IndexOutOfBoundsException e) {
+                       throw new ParseException(loc(r), "Unrecognized 
syntax.");
+               }
+       }
+
+       /*
+        * Doesn't actually parse anything, but moves the position beyond any 
whitespace or comments.
+        * If positionOnNext is 'true', then the cursor will be set to the 
point immediately after
+        * the comments and whitespace.  Otherwise, the cursor will be set to 
the last position of
+        * the comments and whitespace.
+        */
+       private void skipCommentsAndSpace(ParserReader r) throws Exception {
+               int c = 0;
+               while ((c = r.read()) != -1) {
+                       if (! isWhitespace(c)) {
+                               if (c == '/') {
+                                       if (isStrict())
+                                               throw new 
ParseException(loc(r), "Javascript comment detected.");
+                                       skipComments(r);
+                               } else {
+                                       r.unread();
+                                       return;
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Doesn't actually parse anything, but when positioned at the 
beginning of comment,
+        * it will move the pointer to the last character in the comment.
+        */
+       private void skipComments(ParserReader r) throws ParseException, 
IOException {
+               int c = r.read();
+               //  "/* */" style comments
+               if (c == '*') {
+                       while (c != -1)
+                               if ((c = r.read()) == '*')
+                                       if ((c = r.read()) == '/')
+                                               return;
+               //  "//" style comments
+               } else if (c == '/') {
+                       while (c != -1) {
+                               c = r.read();
+                               if (c == -1 || c == '\n')
+                                       return;
+                       }
+               }
+               throw new ParseException(loc(r), "Open ended comment.");
+       }
+
+       /*
+        * Call this method after you've finished a parsing a string to make 
sure that if there's any
+        * remainder in the input, that it consists only of whitespace and 
comments.
+        */
+       private void validateEnd(ParserReader r) throws Exception {
+               skipCommentsAndSpace(r);
+               int c = r.read();
+               if (c != -1 && c != ';')  // var x = {...}; expressions can end 
with a semicolon.
+                       throw new ParseException(loc(r), "Remainder after 
parse: ''{0}''.", (char)c);
+       }
+
+       private ObjectMap loc(ParserReader r) {
+               return getLastLocation().append("line", 
r.getLine()).append("column", r.getColumn());
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ab8f0faa/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializer.java
new file mode 100644
index 0000000..c8598b5
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializer.java
@@ -0,0 +1,146 @@
+// 
***************************************************************************************************************************
+// * 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.yaml.proto;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * Serializes POJO models to JSON.
+ *
+ * <h5 class='section'>Media types:</h5>
+ *
+ * Handles <code>Accept</code> types: <code>application/json, text/json</code>
+ * <p>
+ * Produces <code>Content-Type</code> types: <code>application/json</code>
+ *
+ * <h5 class='section'>Description:</h5>
+ *
+ * The conversion is as follows...
+ * <ul class='spaced-list'>
+ *     <li>
+ *             Maps (e.g. {@link HashMap HashMaps}, {@link TreeMap TreeMaps}) 
are converted to JSON objects.
+ *     <li>
+ *             Collections (e.g. {@link HashSet HashSets}, {@link LinkedList 
LinkedLists}) and Java arrays are converted to
+ *             JSON arrays.
+ *     <li>
+ *             {@link String Strings} are converted to JSON strings.
+ *     <li>
+ *             {@link Number Numbers} (e.g. {@link Integer}, {@link Long}, 
{@link Double}) are converted to JSON numbers.
+ *     <li>
+ *             {@link Boolean Booleans} are converted to JSON booleans.
+ *     <li>
+ *             {@code nulls} are converted to JSON nulls.
+ *     <li>
+ *             {@code arrays} are converted to JSON arrays.
+ *     <li>
+ *             {@code beans} are converted to JSON objects.
+ * </ul>
+ *
+ * <p>
+ * The types above are considered "JSON-primitive" object types.
+ * Any non-JSON-primitive object types are transformed into JSON-primitive 
object types through
+ * {@link org.apache.juneau.transform.PojoSwap PojoSwaps} associated through 
the
+ * {@link CoreObjectBuilder#pojoSwaps(Class...)} method.
+ * Several default transforms are provided for transforming Dates, Enums, 
Iterators, etc...
+ *
+ * <p>
+ * This serializer provides several serialization options.
+ * Typically, one of the predefined DEFAULT serializers will be sufficient.
+ * However, custom serializers can be constructed to fine-tune behavior.
+ *
+ * <h5 class='section'>Configurable properties:</h5>
+ *
+ * This class has the following properties associated with it:
+ * <ul>
+ *     <li>{@link YamlSerializerContext}
+ *     <li>{@link SerializerContext}
+ *     <li>{@link BeanContext}
+ * </ul>
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode'>
+ *     <jc>// Use one of the default serializers to serialize a POJO</jc>
+ *     String json = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(someObject);
+ *
+ *     <jc>// Create a custom serializer for lax syntax using single quote 
characters</jc>
+ *     JsonSerializer serializer = <jk>new</jk> 
JsonSerializerBuilder().simple().sq().build();
+ *
+ *     <jc>// Clone an existing serializer and modify it to use 
single-quotes</jc>
+ *     JsonSerializer serializer = 
JsonSerializer.<jsf>DEFAULT</jsf>.builder().sq().build();
+ *
+ *     <jc>// Serialize a POJO to JSON</jc>
+ *     String json = serializer.serialize(someObject);
+ * </p>
+ */
+public class YamlSerializer extends WriterSerializer {
+
+       /** Default serializer, all default settings.*/
+       public static final YamlSerializer DEFAULT = new 
YamlSerializer(PropertyStore.create());
+
+
+       final YamlSerializerContext ctx;
+
+       /**
+        * Constructor.
+        *
+        * @param propertyStore
+        *      The property store containing all the settings for this object.
+        */
+       public YamlSerializer(PropertyStore propertyStore) {
+               this(propertyStore, "application/yaml", "application/yaml", 
"application/yaml+*", "text/yaml", "text/yaml+*");
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param propertyStore
+        *      The property store containing all the settings for this object.
+        * @param produces
+        *      The media type that this serializer produces.
+        * @param accept
+        *      The accept media types that the serializer can handle.
+        *      <p>
+        *      Can contain meta-characters per the <code>media-type</code> 
specification of
+        *      <a class="doclink" 
href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1";>RFC2616/14.1</a>
+        *      <p>
+        *      If empty, then assumes the only media type supported is 
<code>produces</code>.
+        *      <p>
+        *      For example, if this serializer produces 
<js>"application/json"</js> but should handle media types of
+        *      <js>"application/json"</js> and <js>"text/json"</js>, then the 
arguments should be:
+        *      <br><code><jk>super</jk>(propertyStore, 
<js>"application/json"</js>, <js>"application/json"</js>, 
<js>"text/json"</js>);</code>
+        *      <br>...or...
+        *      <br><code><jk>super</jk>(propertyStore, 
<js>"application/json"</js>, <js>"*&#8203;/json"</js>);</code>
+        */
+       public YamlSerializer(PropertyStore propertyStore, String produces, 
String...accept) {
+               super(propertyStore, produces, accept);
+               this.ctx = createContext(YamlSerializerContext.class);
+       }
+
+       @Override /* CoreObject */
+       public YamlSerializerBuilder builder() {
+               return new YamlSerializerBuilder(propertyStore);
+       }
+
+
+       
//--------------------------------------------------------------------------------
+       // Entry point methods
+       
//--------------------------------------------------------------------------------
+
+       @Override /* Serializer */
+       public WriterSerializerSession createSession(SerializerSessionArgs 
args) {
+               return new YamlSerializerSession(ctx, args);
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ab8f0faa/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerBuilder.java
new file mode 100644
index 0000000..69bdcb4
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerBuilder.java
@@ -0,0 +1,658 @@
+// 
***************************************************************************************************************************
+// * 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.yaml.proto;
+
+import static org.apache.juneau.json.JsonSerializerContext.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * Builder class for building instances of JSON serializers.
+ */
+public class YamlSerializerBuilder extends SerializerBuilder {
+
+       /**
+        * Constructor, default settings.
+        */
+       public YamlSerializerBuilder() {
+               super();
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param propertyStore The initial configuration settings for this 
builder.
+        */
+       public YamlSerializerBuilder(PropertyStore propertyStore) {
+               super(propertyStore);
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializer build() {
+               return new YamlSerializer(propertyStore);
+       }
+
+
+       
//--------------------------------------------------------------------------------
+       // Properties
+       
//--------------------------------------------------------------------------------
+
+       /**
+        * <b>Configuration property:</b>  Simple JSON mode.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"JsonSerializer.simpleMode"</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>, JSON attribute names will only be quoted when 
necessary.
+        * Otherwise, they are always quoted.
+        *
+        * <h5 class='section'>Notes:</h5>
+        * <ul>
+        *      <li>This is equivalent to calling 
<code>property(<jsf>JSON_simpleMode</jsf>, value)</code>.
+        * </ul>
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        * @see YamlSerializerContext#JSON_simpleMode
+        */
+       public YamlSerializerBuilder simple(boolean value) {
+               return property(JSON_simpleMode, value);
+       }
+
+       /**
+        * Shortcut for calling <code>setSimpleMode(<jk>true</jk>).sq()</code>.
+        *
+        * @return This object (for method chaining).
+        */
+       public YamlSerializerBuilder simple() {
+               return simple(true).sq();
+       }
+
+       /**
+        * <b>Configuration property:</b>  Prefix solidus <js>'/'</js> 
characters with escapes.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"JsonSerializer.escapeSolidus"</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>, solidus (e.g. slash) characters should be escaped.
+        * The JSON specification allows for either format.
+        * However, if you're embedding JSON in an HTML script tag, this 
setting prevents confusion when trying to
+        * serialize <xt>&lt;\/script&gt;</xt>.
+        *
+        * <h5 class='section'>Notes:</h5>
+        * <ul>
+        *      <li>This is equivalent to calling 
<code>property(<jsf>JSON_escapeSolidus</jsf>, value)</code>.
+        * </ul>
+        *
+        * @param value The new value for this property.
+        * @return This object (for method chaining).
+        * @see YamlSerializerContext#JSON_escapeSolidus
+        */
+       public YamlSerializerBuilder escapeSolidus(boolean value) {
+               return property(JSON_escapeSolidus, value);
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder maxDepth(int value) {
+               super.maxDepth(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder initialDepth(int value) {
+               super.initialDepth(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder detectRecursions(boolean value) {
+               super.detectRecursions(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder ignoreRecursions(boolean value) {
+               super.ignoreRecursions(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder useWhitespace(boolean value) {
+               super.useWhitespace(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder ws() {
+               super.ws();
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder maxIndent(int value) {
+               super.maxIndent(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder addBeanTypeProperties(boolean value) {
+               super.addBeanTypeProperties(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder quoteChar(char value) {
+               super.quoteChar(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder sq() {
+               super.sq();
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder trimNullProperties(boolean value) {
+               super.trimNullProperties(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder trimEmptyCollections(boolean value) {
+               super.trimEmptyCollections(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder trimEmptyMaps(boolean value) {
+               super.trimEmptyMaps(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder trimStrings(boolean value) {
+               super.trimStrings(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder uriContext(UriContext value) {
+               super.uriContext(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder uriResolution(UriResolution value) {
+               super.uriResolution(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder uriRelativity(UriRelativity value) {
+               super.uriRelativity(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder sortCollections(boolean value) {
+               super.sortCollections(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder sortMaps(boolean value) {
+               super.sortMaps(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder abridged(boolean value) {
+               super.abridged(value);
+               return this;
+       }
+
+       @Override /* SerializerBuilder */
+       public YamlSerializerBuilder listener(Class<? extends 
SerializerListener> value) {
+               super.listener(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beansRequireDefaultConstructor(boolean 
value) {
+               super.beansRequireDefaultConstructor(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beansRequireSerializable(boolean value) {
+               super.beansRequireSerializable(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beansRequireSettersForGetters(boolean 
value) {
+               super.beansRequireSettersForGetters(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beansRequireSomeProperties(boolean value) {
+               super.beansRequireSomeProperties(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beanMapPutReturnsOldValue(boolean value) {
+               super.beanMapPutReturnsOldValue(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beanConstructorVisibility(Visibility 
value) {
+               super.beanConstructorVisibility(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beanClassVisibility(Visibility value) {
+               super.beanClassVisibility(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beanFieldVisibility(Visibility value) {
+               super.beanFieldVisibility(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder methodVisibility(Visibility value) {
+               super.methodVisibility(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder useJavaBeanIntrospector(boolean value) {
+               super.useJavaBeanIntrospector(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder useInterfaceProxies(boolean value) {
+               super.useInterfaceProxies(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder ignoreUnknownBeanProperties(boolean value) 
{
+               super.ignoreUnknownBeanProperties(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder ignoreUnknownNullBeanProperties(boolean 
value) {
+               super.ignoreUnknownNullBeanProperties(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder ignorePropertiesWithoutSetters(boolean 
value) {
+               super.ignorePropertiesWithoutSetters(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder 
ignoreInvocationExceptionsOnGetters(boolean value) {
+               super.ignoreInvocationExceptionsOnGetters(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder 
ignoreInvocationExceptionsOnSetters(boolean value) {
+               super.ignoreInvocationExceptionsOnSetters(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder sortProperties(boolean value) {
+               super.sortProperties(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder notBeanPackages(String...values) {
+               super.notBeanPackages(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder notBeanPackages(Collection<String> values) 
{
+               super.notBeanPackages(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder setNotBeanPackages(String...values) {
+               super.setNotBeanPackages(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder setNotBeanPackages(Collection<String> 
values) {
+               super.setNotBeanPackages(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder removeNotBeanPackages(String...values) {
+               super.removeNotBeanPackages(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder removeNotBeanPackages(Collection<String> 
values) {
+               super.removeNotBeanPackages(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder notBeanClasses(Class<?>...values) {
+               super.notBeanClasses(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder notBeanClasses(Collection<Class<?>> 
values) {
+               super.notBeanClasses(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder setNotBeanClasses(Class<?>...values) {
+               super.setNotBeanClasses(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder setNotBeanClasses(Collection<Class<?>> 
values) {
+               super.setNotBeanClasses(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder removeNotBeanClasses(Class<?>...values) {
+               super.removeNotBeanClasses(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder removeNotBeanClasses(Collection<Class<?>> 
values) {
+               super.removeNotBeanClasses(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beanFilters(Class<?>...values) {
+               super.beanFilters(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beanFilters(Collection<Class<?>> values) {
+               super.beanFilters(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder setBeanFilters(Class<?>...values) {
+               super.setBeanFilters(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder setBeanFilters(Collection<Class<?>> 
values) {
+               super.setBeanFilters(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder removeBeanFilters(Class<?>...values) {
+               super.removeBeanFilters(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder removeBeanFilters(Collection<Class<?>> 
values) {
+               super.removeBeanFilters(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder pojoSwaps(Class<?>...values) {
+               super.pojoSwaps(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder pojoSwaps(Collection<Class<?>> values) {
+               super.pojoSwaps(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder setPojoSwaps(Class<?>...values) {
+               super.setPojoSwaps(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder setPojoSwaps(Collection<Class<?>> values) {
+               super.setPojoSwaps(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder removePojoSwaps(Class<?>...values) {
+               super.removePojoSwaps(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder removePojoSwaps(Collection<Class<?>> 
values) {
+               super.removePojoSwaps(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder implClasses(Map<Class<?>,Class<?>> values) 
{
+               super.implClasses(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public <T> YamlSerializerBuilder implClass(Class<T> interfaceClass, 
Class<? extends T> implClass) {
+               super.implClass(interfaceClass, implClass);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder includeProperties(Map<String,String> 
values) {
+               super.includeProperties(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder includeProperties(String beanClassName, 
String properties) {
+               super.includeProperties(beanClassName, properties);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder includeProperties(Class<?> beanClass, 
String properties) {
+               super.includeProperties(beanClass, properties);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder excludeProperties(Map<String,String> 
values) {
+               super.excludeProperties(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder excludeProperties(String beanClassName, 
String properties) {
+               super.excludeProperties(beanClassName, properties);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder excludeProperties(Class<?> beanClass, 
String properties) {
+               super.excludeProperties(beanClass, properties);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beanDictionary(Class<?>...values) {
+               super.beanDictionary(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beanDictionary(Collection<Class<?>> 
values) {
+               super.beanDictionary(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder setBeanDictionary(Class<?>...values) {
+               super.setBeanDictionary(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder setBeanDictionary(Collection<Class<?>> 
values) {
+               super.setBeanDictionary(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder 
removeFromBeanDictionary(Class<?>...values) {
+               super.removeFromBeanDictionary(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder 
removeFromBeanDictionary(Collection<Class<?>> values) {
+               super.removeFromBeanDictionary(values);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder beanTypePropertyName(String value) {
+               super.beanTypePropertyName(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder defaultParser(Class<?> value) {
+               super.defaultParser(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder locale(Locale value) {
+               super.locale(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder timeZone(TimeZone value) {
+               super.timeZone(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder mediaType(MediaType value) {
+               super.mediaType(value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder debug() {
+               super.debug();
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder property(String name, Object value) {
+               super.property(name, value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder properties(Map<String,Object> properties) {
+               super.properties(properties);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder addToProperty(String name, Object value) {
+               super.addToProperty(name, value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder putToProperty(String name, Object key, 
Object value) {
+               super.putToProperty(name, key, value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder putToProperty(String name, Object value) {
+               super.putToProperty(name, value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder removeFromProperty(String name, Object 
value) {
+               super.removeFromProperty(name, value);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder classLoader(ClassLoader classLoader) {
+               super.classLoader(classLoader);
+               return this;
+       }
+
+       @Override /* CoreObjectBuilder */
+       public YamlSerializerBuilder 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/ab8f0faa/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerContext.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerContext.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerContext.java
new file mode 100644
index 0000000..5714d42
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerContext.java
@@ -0,0 +1,130 @@
+// 
***************************************************************************************************************************
+// * 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.yaml.proto;
+
+import org.apache.juneau.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * Configurable properties on the {@link YamlSerializer} 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.
+ *
+ * <h6 class='topic'>Inherited configurable properties</h6>
+ * <ul class='doctree'>
+ *     <li class='jc'>
+ *             <a class="doclink" 
href="../BeanContext.html#ConfigProperties">BeanContext</a>
+ *             - Properties associated with handling beans on serializers and 
parsers.
+ *             <ul>
+ *                     <li class='jc'>
+ *                     <a class="doclink" 
href="../serializer/SerializerContext.html#ConfigProperties">SerializerContext</a>
+ *                     - Configurable properties common to all serializers.
+ *             </ul>
+ *     </li>
+ * </ul>
+ */
+public final class YamlSerializerContext extends SerializerContext {
+
+       /**
+        * <b>Configuration property:</b>  Simple JSON mode.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"JsonSerializer.simpleMode"</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>, JSON attribute names will only be quoted when 
necessary.
+        * Otherwise, they are always quoted.
+        */
+       public static final String JSON_simpleMode = 
"JsonSerializer.simpleMode";
+
+       /**
+        * <b>Configuration property:</b>  Prefix solidus <js>'/'</js> 
characters with escapes.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"JsonSerializer.escapeSolidus"</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>, solidus (e.g. slash) characters should be escaped.
+        * The JSON specification allows for either format.
+        * However, if you're embedding JSON in an HTML script tag, this 
setting prevents confusion when trying to serialize
+        * <xt>&lt;\/script&gt;</xt>.
+        */
+       public static final String JSON_escapeSolidus = 
"JsonSerializer.escapeSolidus";
+
+       /**
+        * <b>Configuration property:</b>  Add <js>"_type"</js> properties when 
needed.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"JsonSerializer.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 JSON_addBeanTypeProperties = 
"JsonSerializer.addBeanTypeProperties";
+
+       final boolean
+               simpleMode,
+               escapeSolidus,
+               addBeanTypeProperties;
+
+       /**
+        * Constructor.
+        *
+        * <p>
+        * Typically only called from {@link PropertyStore#getContext(Class)}.
+        *
+        * @param ps The property store that created this context.
+        */
+       public YamlSerializerContext(PropertyStore ps) {
+               super(ps);
+               simpleMode = ps.getProperty(JSON_simpleMode, boolean.class, 
false);
+               escapeSolidus = ps.getProperty(JSON_escapeSolidus, 
boolean.class, false);
+               addBeanTypeProperties = 
ps.getProperty(JSON_addBeanTypeProperties, boolean.class,
+                       ps.getProperty(SERIALIZER_addBeanTypeProperties, 
boolean.class, true));
+       }
+
+       @Override /* Context */
+       public ObjectMap asMap() {
+               return super.asMap()
+                       .append("JsonSerializerContext", new ObjectMap()
+                               .append("simpleMode", simpleMode)
+                               .append("escapeSolidus", escapeSolidus)
+                               .append("addBeanTypeProperties", 
addBeanTypeProperties)
+                       );
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ab8f0faa/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerSession.java
new file mode 100644
index 0000000..1f252c9
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerSession.java
@@ -0,0 +1,244 @@
+// 
***************************************************************************************************************************
+// * 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.yaml.proto;
+
+import static org.apache.juneau.json.JsonSerializerContext.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.transform.*;
+
+/**
+ * Session object that lives for the duration of a single use of {@link 
YamlSerializer}.
+ *
+ * <p>
+ * This class is NOT thread safe.
+ * It is typically discarded after one-time use although it can be reused 
within the same thread.
+ */
+public class YamlSerializerSession extends WriterSerializerSession {
+
+       private final boolean
+               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 args
+        *      Runtime arguments.
+        *      These specify session-level information such as locale and URI 
context.
+        *      It also include session-level properties that override the 
properties defined on the bean and
+        *      serializer contexts.
+        */
+       protected YamlSerializerSession(YamlSerializerContext ctx, 
SerializerSessionArgs args) {
+               super(ctx, args);
+               ObjectMap p = getProperties();
+               if (p.isEmpty()) {
+                       addBeanTypeProperties = ctx.addBeanTypeProperties;
+               } else {
+                       addBeanTypeProperties = 
p.getBoolean(JSON_addBeanTypeProperties, ctx.addBeanTypeProperties);
+               }
+       }
+
+
+       @Override /* SerializerSesssion */
+       protected void doSerialize(SerializerPipe out, Object o) throws 
Exception {
+               serializeAnything(getJsonWriter(out), o, 
getExpectedRootType(o), "root", null);
+       }
+
+       /*
+        * Workhorse method.
+        * Determines the type of object, and then calls the appropriate 
type-specific serialization method.
+        */
+       @SuppressWarnings({ "rawtypes", "unchecked" })
+       SerializerWriter serializeAnything(YamlWriter out, Object o, 
ClassMeta<?> eType,        String attrName, BeanPropertyMeta pMeta) throws 
Exception {
+
+               if (o == null) {
+                       out.append("~");
+                       return out;
+               }
+
+               if (eType == null)
+                       eType = object();
+
+               ClassMeta<?> aType;                     // The actual type
+               ClassMeta<?> sType;                     // The serialized type
+
+               aType = push(attrName, o, eType);
+               boolean isRecursion = aType == null;
+
+               // Handle recursion
+               if (aType == null) {
+                       o = null;
+                       aType = object();
+               }
+
+               sType = aType;
+               String typeName = getBeanTypeName(eType, aType, pMeta);
+
+               // Swap if necessary
+               PojoSwap swap = aType.getPojoSwap(this);
+               if (swap != null) {
+                       o = swap.swap(this, o);
+                       sType = swap.getSwapClassMeta(this);
+
+                       // If the getSwapClass() method returns Object, we need 
to figure out
+                       // the actual type now.
+                       if (sType.isObject())
+                               sType = getClassMetaForObject(o);
+               }
+
+               // '\0' characters are considered null.
+               if (o == null || (sType.isChar() && ((Character)o).charValue() 
== 0))
+                       out.append("~");
+               else if (sType.isNumber() || sType.isBoolean())
+                       out.append(o);
+               else if (sType.isBean())
+                       serializeBeanMap(out, toBeanMap(o), typeName);
+               else if (sType.isUri() || (pMeta != null && pMeta.isUri()))
+                       out.uriValue(o);
+               else if (sType.isMap()) {
+                       if (o instanceof BeanMap)
+                               serializeBeanMap(out, (BeanMap)o, typeName);
+                       else
+                               serializeMap(out, (Map)o, eType);
+               }
+               else if (sType.isCollection()) {
+                       serializeCollection(out, (Collection) o, eType);
+               }
+               else if (sType.isArray()) {
+                       serializeCollection(out, toList(sType.getInnerClass(), 
o), eType);
+               }
+               else if (sType.isReader() || sType.isInputStream()) {
+                       IOUtils.pipe(o, out);
+               }
+               else
+                       out.stringValue(toString(o));
+
+               if (! isRecursion)
+                       pop();
+               return out;
+       }
+
+       @SuppressWarnings({ "rawtypes", "unchecked" })
+       private SerializerWriter serializeMap(YamlWriter out, Map m, 
ClassMeta<?> type) throws Exception {
+
+               ClassMeta<?> keyType = type.getKeyType(), valueType = 
type.getValueType();
+
+               m = sort(m);
+
+               int i = indent;
+
+               Iterator mapEntries = m.entrySet().iterator();
+
+               while (mapEntries.hasNext()) {
+                       Map.Entry e = (Map.Entry) mapEntries.next();
+                       Object value = e.getValue();
+
+                       Object key = generalize(e.getKey(), keyType);
+
+                       out.attr(toString(key)).append(':').s();
+
+                       serializeAnything(out, value, valueType, (key == null ? 
null : toString(key)), null);
+
+                       if (mapEntries.hasNext())
+                               out.nl(i);
+               }
+
+               out.cre(i-1);
+
+               return out;
+       }
+
+       private SerializerWriter serializeBeanMap(YamlWriter out, BeanMap<?> m, 
String typeName) throws Exception {
+               int i = indent;
+               out.append('{');
+
+               boolean addComma = false;
+               for (BeanPropertyValue p : m.getValues(isTrimNulls(), typeName 
!= null ? createBeanTypeNameProperty(m, typeName) : null)) {
+                       BeanPropertyMeta pMeta = p.getMeta();
+                       ClassMeta<?> cMeta = p.getClassMeta();
+                       String key = p.getName();
+                       Object value = p.getValue();
+                       Throwable t = p.getThrown();
+                       if (t != null)
+                               onBeanGetterException(pMeta, t);
+
+                       if (canIgnoreValue(cMeta, key, value))
+                               continue;
+
+                       if (addComma)
+                               out.append(',').smi(i);
+
+                       out.cr(i).attr(key).append(':').s(i);
+
+                       serializeAnything(out, value, cMeta, key, pMeta);
+
+                       addComma = true;
+               }
+               out.cre(i-1).append('}');
+               return out;
+       }
+
+       @SuppressWarnings({"rawtypes", "unchecked"})
+       private SerializerWriter serializeCollection(YamlWriter out, Collection 
c, ClassMeta<?> type) throws Exception {
+
+               ClassMeta<?> elementType = type.getElementType();
+
+               c = sort(c);
+
+               out.append('[');
+
+               for (Iterator i = c.iterator(); i.hasNext();) {
+                       Object value = i.next();
+                       out.cr(indent);
+                       serializeAnything(out, value, elementType, 
"<iterator>", null);
+                       if (i.hasNext())
+                               out.append(',').smi(indent);
+               }
+               out.cre(indent-1).append(']');
+               return out;
+       }
+
+
+       /**
+        * Returns the {@link YamlSerializerContext#JSON_addBeanTypeProperties} 
setting value for this session.
+        *
+        * @return The {@link YamlSerializerContext#JSON_addBeanTypeProperties} 
setting value for this session.
+        */
+       @Override /* SerializerSession */
+       protected final boolean isAddBeanTypeProperties() {
+               return addBeanTypeProperties;
+       }
+
+       /**
+        * Converts the specified output target object to an {@link YamlWriter}.
+        *
+        * @param out The output target object.
+        * @return The output target object wrapped in an {@link YamlWriter}.
+        * @throws Exception
+        */
+       protected final YamlWriter getJsonWriter(SerializerPipe out) throws 
Exception {
+               Object output = out.getRawOutput();
+               if (output instanceof YamlWriter)
+                       return (YamlWriter)output;
+               YamlWriter w = new YamlWriter(out.getWriter(), getQuoteChar(), 
isTrimStrings(), getUriResolver());
+               out.setWriter(w);
+               return w;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ab8f0faa/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlWriter.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlWriter.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlWriter.java
new file mode 100644
index 0000000..f9345b0
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlWriter.java
@@ -0,0 +1,288 @@
+// 
***************************************************************************************************************************
+// * 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.yaml.proto;
+
+import java.io.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * Specialized writer for serializing JSON.
+ *
+ * <h5 class='section'>Notes:</h5>
+ * <ul>
+ *     <li>This class is not intended for external use.
+ * </ul>
+ */
+public final class YamlWriter extends SerializerWriter {
+
+       // Characters that trigger special handling of serializing attribute 
values.
+       private static final AsciiSet
+               encodedChars = new AsciiSet("\n\t\b\f\r'\"\\");
+
+       private static final KeywordSet reservedWords = new KeywordSet(
+               "y","Y","yes","Yes","YES","n","N","no","No","NO",
+                "true","True","TRUE","false","False","FALSE",
+                "on","On","ON","off","Off","OFF"
+       );
+
+
+
+       // Characters that represent attribute name characters that don't 
trigger quoting.
+       // These are actually more strict than the actual Javascript 
specification, but
+       // can be narrowed in the future if necessary.
+       // For example, we quote attributes that start with $ even though we 
don't need to.
+       private static final AsciiSet validAttrChars = new 
AsciiSet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
+       private static final AsciiSet validFirstAttrChars = new 
AsciiSet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_");
+
+       private final AsciiSet ec;
+
+       /**
+        * Constructor.
+        *
+        * @param out The writer being wrapped.
+        * @param quoteChar The quote character to use (i.e. <js>'\''</js> or 
<js>'"'</js>)
+        * @param trimStrings If <jk>true</jk>, strings will be trimmed before 
being serialized.
+        * @param uriResolver The URI resolver for resolving URIs to absolute 
or root-relative form.
+        */
+       protected YamlWriter(Writer out, char quoteChar, boolean trimStrings, 
UriResolver uriResolver) {
+               super(out, true, Integer.MAX_VALUE, trimStrings, quoteChar, 
uriResolver);
+               this.ec = encodedChars;
+       }
+
+       /**
+        * Serializes the specified object as a JSON string value.
+        *
+        * @param s The object being serialized.
+        * @return This object (for method chaining).
+        * @throws IOException Should never happen.
+        */
+       public YamlWriter stringValue(String s) throws IOException {
+               if (s == null)
+                       return this;
+               boolean doConvert = false;
+               for (int i = 0; i < s.length() && ! doConvert; i++) {
+                       char c = s.charAt(i);
+                       doConvert |= ec.contains(c);
+               }
+               q();
+               if (! doConvert) {
+                       out.append(s);
+               } else {
+                       for (int i = 0; i < s.length(); i++) {
+                               char c = s.charAt(i);
+                               if (ec.contains(c)) {
+                                       if (c == '\n')
+                                               out.append('\\').append('n');
+                                       else if (c == '\t')
+                                               out.append('\\').append('t');
+                                       else if (c == '\b')
+                                               out.append('\\').append('b');
+                                       else if (c == '\f')
+                                               out.append('\\').append('f');
+                                       else if (c == quoteChar)
+                                               
out.append('\\').append(quoteChar);
+                                       else if (c == '\\')
+                                               out.append('\\').append('\\');
+                                       else if (c != '\r')
+                                               out.append(c);
+                               } else {
+                                       out.append(c);
+                               }
+                       }
+               }
+               q();
+               return this;
+       }
+
+       /**
+        * Serializes the specified object as a JSON attribute name.
+        *
+        * @param s The object being serialized.
+        * @return This object (for method chaining).
+        * @throws IOException Should never happen.
+        */
+       public YamlWriter attr(String s) throws IOException {
+               /*
+                * Converts a Java string to an acceptable JSON attribute name. 
If
+                * useStrictJson is false, then quotes will only be used if the 
attribute
+                * name consists of only alphanumeric characters.
+                */
+               boolean doConvert = false;              // Always convert when 
not in lax mode.
+
+               // If the attribute is null, it must always be printed as null 
without quotes.
+               // Technically, this isn't part of the JSON spec, but it does 
allow for null key values.
+               if (s == null) {
+                       s = "~";
+                       doConvert = false;
+
+               } else {
+
+                       // Look for characters that would require the attribute 
to be quoted.
+                       // All possible numbers should be caught here.
+                       if (! doConvert) {
+                               for (int i = 0; i < s.length() && ! doConvert; 
i++) {
+                                       char c = s.charAt(i);
+                                       doConvert |= ! (i == 0 ? 
validFirstAttrChars.contains(c) : validAttrChars.contains(c));
+                               }
+                       }
+
+                       // Reserved words and blanks must be quoted.
+                       if (! doConvert) {
+                               if (s.isEmpty() || reservedWords.contains(s))
+                                       doConvert = true;
+                       }
+               }
+
+               // If no conversion necessary, just print the attribute as-is.
+               if (doConvert)
+                       stringValue(s);
+               else
+                       out.append(s);
+
+               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
+        */
+       public SerializerWriter uriValue(Object uri) throws IOException {
+               return stringValue(uriResolver.resolve(uri));
+       }
+
+       
//--------------------------------------------------------------------------------
+       // Overridden methods
+       
//--------------------------------------------------------------------------------
+
+       @Override /* SerializerWriter */
+       public YamlWriter cr(int depth) throws IOException {
+               super.cr(depth);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter cre(int depth) throws IOException {
+               super.cre(depth);
+               return this;
+       }
+
+       /**
+        * Performs an indentation only if we're currently past max indentation.
+        *
+        * @param depth The current indentation depth.
+        * @return This object (for method chaining).
+        * @throws IOException
+        */
+       public YamlWriter smi(int depth) throws IOException {
+               if (depth > maxIndent)
+                       super.s();
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter appendln(int indent, String text) throws IOException {
+               super.appendln(indent, text);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter appendln(String text) throws IOException {
+               super.appendln(text);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter append(int indent, String text) throws IOException {
+               super.append(indent, text);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter append(int indent, char c) throws IOException {
+               super.append(indent, c);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter s() throws IOException {
+               super.s();
+               return this;
+       }
+
+       /**
+        * Adds a space only if the current indentation level is below 
maxIndent.
+        *
+        * @param indent
+        * @return This object (for method chaining).
+        * @throws IOException
+        */
+       public YamlWriter s(int indent) throws IOException {
+               if (indent <= maxIndent)
+                       super.s();
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter q() throws IOException {
+               super.q();
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter i(int indent) throws IOException {
+               super.i(indent);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter nl(int indent) throws IOException {
+               super.nl(indent);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter append(Object text) throws IOException {
+               super.append(text);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter append(String text) throws IOException {
+               super.append(text);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter appendIf(boolean b, String text) throws IOException {
+               super.appendIf(b, text);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter appendIf(boolean b, char c) throws IOException {
+               super.appendIf(b, c);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public YamlWriter append(char c) throws IOException {
+               super.append(c);
+               return this;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ab8f0faa/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/annotation/Yaml.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/annotation/Yaml.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/annotation/Yaml.java
new file mode 100644
index 0000000..08e2e50
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/annotation/Yaml.java
@@ -0,0 +1,36 @@
+// 
***************************************************************************************************************************
+// * 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.yaml.proto.annotation;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation for specifying various YAML options for the YAML serializers and 
parsers.
+ *
+ * <p>
+ * Can be applied to Java types.
+ *
+ * <p>
+ * Can be used for the following:
+ * <ul class='spaced-list'>
+ * </ul>
+ */
+@Documented
+@Target({TYPE})
+@Retention(RUNTIME)
+@Inherited
+public @interface Yaml {
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ab8f0faa/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/annotation/package.html
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/annotation/package.html
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/annotation/package.html
new file mode 100644
index 0000000..df41b35
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/annotation/package.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<!--
+/***************************************************************************************************************************
+ * 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.
+ *
+ 
***************************************************************************************************************************/
+ -->
+<html>
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+       <style type="text/css">
+               /* For viewing in Page Designer */
+               @IMPORT url("../../../../../../../javadoc.css");
+
+               /* For viewing in REST interface */
+               @IMPORT url("../htdocs/javadoc.css");
+               body { 
+                       margin: 20px; 
+               }       
+       </style>
+       <script>
+               /* Replace all @code and @link tags. */ 
+               window.onload = function() {
+                       document.body.innerHTML = 
document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>');
+                       document.body.innerHTML = 
document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, 
'<code>$3</code>');
+               }
+       </script>
+</head>
+<body>
+<p>JSON annotations</p>
+</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ab8f0faa/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_HTML.png
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_HTML.png
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_HTML.png
new file mode 100644
index 0000000..b4a3576
Binary files /dev/null and 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_HTML.png
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ab8f0faa/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_JSON.png
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_JSON.png
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_JSON.png
new file mode 100644
index 0000000..13b5c22
Binary files /dev/null and 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_JSON.png
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ab8f0faa/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_JSONSchema.png
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_JSONSchema.png
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_JSONSchema.png
new file mode 100644
index 0000000..bf1cdc6
Binary files /dev/null and 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_JSONSchema.png
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ab8f0faa/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_JSONSimple.png
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_JSONSimple.png
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_JSONSimple.png
new file mode 100644
index 0000000..935e8a9
Binary files /dev/null and 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/doc-files/Example_JSONSimple.png
 differ

Reply via email to