anchors = new HashMap();
@@ -68,31 +72,42 @@ public YamlConfig getConfig () {
return config;
}
- /** Return the object with the given alias, or null. This is only valid after objects have been read and before {@link #close()} */
+ /** Return the object with the given alias, or null. This is only valid after objects have been read and before
+ * {@link #close()} */
public Object get (String alias) {
return anchors.get(alias);
}
+ private void addAnchor (String key, Object value) {
+ if (config.readConfig.anchors) anchors.put(key, value);
+ }
+
public void close () throws IOException {
parser.close();
anchors.clear();
}
/** Reads the next YAML document and deserializes it into an object. The type of object is defined by the YAML tag. If there is
- * no YAML tag, the object will be an {@link ArrayList}, {@link HashMap}, or String. */
+ * no YAML tag, the object will be an {@link ArrayList}, {@link HashMap}, or String.
+ *
+ * This method creates and configures an instance of a class specified by the YAML data, so should be used only with YAML data
+ * from a trusted source. */
public Object read () throws YamlException {
return read(null);
}
/** Reads an object of the specified type from YAML.
- * @param type The type of object to read. If null, behaves the same as {{@link #read()}. */
+ * @param type The type of object to read. If null, behaves the same as {{@link #read()}.
+ * @throws YamlReaderException if the YAML data specifies a type that is incompatible with the specified type. */
public T read (Class type) throws YamlException {
return read(type, null);
}
/** Reads an array, Map, List, or Collection object of the specified type from YAML, using the specified element type.
- * @param type The type of object to read. If null, behaves the same as {{@link #read()}. */
+ * @param type The type of object to read. If null, behaves the same as {{@link #read()}.
+ * @throws YamlReaderException if the YAML data specifies a type that is incompatible with the specified type. */
public T read (Class type, Class elementType) throws YamlException {
+ anchors.clear();
try {
while (true) {
Event event = parser.getNextEvent();
@@ -100,7 +115,9 @@ public T read (Class type, Class elementType) throws YamlException {
if (event.type == STREAM_END) return null;
if (event.type == DOCUMENT_START) break;
}
- return (T)readValue(type, elementType, null);
+ Object object = readValue(type, elementType, null);
+ parser.getNextEvent(); // consume it(DOCUMENT_END)
+ return (T)object;
} catch (ParserException ex) {
throw new YamlException("Error parsing YAML.", ex);
} catch (TokenizerException ex) {
@@ -108,9 +125,34 @@ public T read (Class type, Class elementType) throws YamlException {
}
}
- /** Reads an object from the YAML. Can be overidden to take some action for any of the objects returned. */
- protected Object readValue (Class type, Class elementType, Class defaultType) throws YamlException, ParserException,
- TokenizerException {
+ /** Returns an iterator that reads all documents from YAML into objects.
+ * @param type The type of object to read. If null, behaves the same as {{@link #read()}. */
+ public Iterator readAll (final Class type) {
+ return new Iterator() {
+ public boolean hasNext () {
+ Event event = parser.peekNextEvent();
+ return event != null && event.type != STREAM_END;
+ }
+
+ public T next () {
+ try {
+ return read(type);
+ } catch (YamlException ex) {
+ throw new RuntimeException("Error reading YAML document for iterator.", ex);
+ }
+ }
+
+ public void remove () {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /** Reads an object from the YAML. Can be overidden to take some action for any of the objects returned.
+ * @param type May be null.
+ * @throws YamlReaderException if the YAML data specifies a type that is incompatible with the specified type. */
+ protected Object readValue (Class type, Class elementType, Class defaultType)
+ throws YamlException, ParserException, TokenizerException {
String tag = null, anchor = null;
Event event = parser.peekNextEvent();
@@ -119,7 +161,7 @@ protected Object readValue (Class type, Class elementType, Class defaultType) th
parser.getNextEvent();
anchor = ((AliasEvent)event).anchor;
Object value = anchors.get(anchor);
- if (value == null) throw new YamlReaderException("Unknown anchor: " + anchor);
+ if (value == null && config.readConfig.anchors) throw new YamlReaderException("Unknown anchor: " + anchor);
return value;
case MAPPING_START:
case SEQUENCE_START:
@@ -133,34 +175,127 @@ protected Object readValue (Class type, Class elementType, Class defaultType) th
default:
}
- if (tag != null) {
- type = config.tagToClass.get(tag);
- if (type == null) {
- try {
- if (config.readConfig.classLoader != null)
- type = Class.forName(tag, true, config.readConfig.classLoader);
- else
- type = Class.forName(tag);
- } catch (ClassNotFoundException ex) {
- throw new YamlReaderException("Unable to find class specified by tag: " + tag);
+ return readValueInternal(this.chooseType(tag, defaultType, type), elementType, anchor);
+ }
+
+ private Class> chooseType (String tag, Class> defaultType, Class> providedType) throws YamlReaderException {
+ if (tag != null && config.readConfig.classTags) {
+ Class> userConfiguredByTag = config.tagToClass.get(tag);
+ if (userConfiguredByTag != null) return userConfiguredByTag;
+
+ ClassLoader classLoader = (config.readConfig.classLoader == null ? this.getClass().getClassLoader()
+ : config.readConfig.classLoader);
+
+ tag = tag.replace("!", "");
+ try {
+ Class> loadedFromTag = findTagClass(tag, classLoader);
+ if (loadedFromTag != null) {
+ if (providedType != null && !providedType.isAssignableFrom(loadedFromTag)) {
+ throw new YamlReaderException("Class specified by tag is incompatible with expected type: "
+ + loadedFromTag.getName() + " (expected " + providedType.getName() + ")");
+ }
+ return loadedFromTag;
}
+ } catch (ClassNotFoundException e) {
+ throw new YamlReaderException("Unable to find class specified by tag: " + tag);
}
- } else if (defaultType != null) {
- type = defaultType;
}
- return readValueInternal(type, elementType, anchor);
+ if (defaultType != null) return defaultType;
+
+ return providedType; // May be null.
+ }
+
+ /** Used during reading when a tag is present, and {@link YamlConfig#setClassTag(String, Class)} was not used for that tag.
+ * Attempts to load the class corresponding to that tag.
+ *
+ * If this returns a non-null Class, that will be used as the deserialization type regardless of whether a type was explicitly
+ * asked for or if a default type exists.
+ *
+ * If this returns null, no guidance will be provided by the tag and we will fall back to the default type or a requested
+ * target type, if any exist.
+ *
+ * If this throws a ClassNotFoundException, parsing will fail.
+ *
+ * The default implementation is simply {@code
+ * Class.forName(tag, true, classLoader);
+ * } and never returns null.
+ *
+ * You can override this to handle cases where you do not want to respect the type tags found in a document, eg if they were
+ * output by another program using classes that do not exist on your classpath. */
+ protected Class> findTagClass (String tag, ClassLoader classLoader) throws ClassNotFoundException {
+ return Class.forName(tag, true, classLoader);
+ }
+
+ /**
+ * Reads a scalar value from the parser and converts it to the specified type.
+ * @param type The type to convert the scalar to.
+ * @param anchor The anchor of the scalar, or null.
+ * @return The converted scalar value.
+ * @throws YamlException
+ * @throws ParserException
+ */
+ private Object readScalarValue(Class> type, String anchor) throws YamlException, ParserException {
+ Event event = parser.getNextEvent();
+ if (event.type != SCALAR) {
+ throw new YamlReaderException("Expected scalar for primitive type '" + type.getClass() + "' but found: " + event.type);
+ }
+
+ String value = ((ScalarEvent) event).value;
+ try {
+ Object convertedValue;
+ if (value == null) {
+ convertedValue = null;
+ } else if (type == String.class) {
+ convertedValue = value;
+ } else if (type == Integer.TYPE || type == Integer.class) {
+ convertedValue = Integer.decode(value);
+ } else if (type == Boolean.TYPE || type == Boolean.class) {
+ convertedValue = Boolean.valueOf(value);
+ } else if (type == Float.TYPE || type == Float.class) {
+ convertedValue = Float.valueOf(value);
+ } else if (type == Double.TYPE || type == Double.class) {
+ convertedValue = Double.valueOf(value);
+ } else if (type == Long.TYPE || type == Long.class) {
+ convertedValue = Long.decode(value);
+ } else if (type == Short.TYPE || type == Short.class) {
+ convertedValue = Short.decode(value);
+ } else if (type == Character.TYPE || type == Character.class) {
+ convertedValue = value.charAt(0);
+ } else if (type == Byte.TYPE || type == Byte.class) {
+ convertedValue = Byte.decode(value);
+ } else {
+ throw new YamlException("Unknown field type.");
+ }
+ if (anchor != null) {
+ addAnchor(anchor, convertedValue);
+ }
+ return convertedValue;
+ } catch (Exception ex) {
+ throw new YamlReaderException("Unable to convert value to required type \"" + type + "\": " + value, ex);
+ }
}
- private Object readValueInternal (Class type, Class elementType, String anchor) throws YamlException, ParserException,
- TokenizerException {
+ private Object readValueInternal (Class type, Class elementType, String anchor)
+ throws YamlException, ParserException, TokenizerException {
if (type == null || type == Object.class) {
Event event = parser.peekNextEvent();
switch (event.type) {
case MAPPING_START:
- type = HashMap.class;
+ type = LinkedHashMap.class;
break;
case SCALAR:
+ if (config.readConfig.guessNumberTypes) {
+ String value = ((ScalarEvent)event).value;
+ if (value != null) {
+ Number number = parseNumber(value);
+ if (number != null) {
+ if (anchor != null) addAnchor(anchor, number);
+ parser.getNextEvent();
+ return number;
+ }
+ }
+ }
type = String.class;
break;
case SEQUENCE_START:
@@ -171,61 +306,19 @@ private Object readValueInternal (Class type, Class elementType, String anchor)
}
}
- if (type == String.class) {
- Event event = parser.getNextEvent();
- if (event.type != SCALAR) throw new YamlReaderException("Expected scalar for String type but found: " + event.type);
- String value = ((ScalarEvent)event).value;
- if (anchor != null) anchors.put(anchor, value);
- return value;
+ if (Beans.isScalar(type)) {
+ return readScalarValue(type, anchor);
}
- if (Beans.isScalar(type)) {
- Event event = parser.getNextEvent();
- if (event.type != SCALAR)
- throw new YamlReaderException("Expected scalar for primitive type '" + type.getClass() + "' but found: " + event.type);
- String value = ((ScalarEvent)event).value;
- try {
- Object convertedValue;
- if (type == String.class) {
- convertedValue = value;
- } else if (type == Integer.TYPE) {
- convertedValue = value.length() == 0 ? 0 : Integer.decode(value);
- } else if (type == Integer.class) {
- convertedValue = value.length() == 0 ? null : Integer.decode(value);
- } else if (type == Boolean.TYPE) {
- convertedValue = value.length() == 0 ? false : Boolean.valueOf(value);
- } else if (type == Boolean.class) {
- convertedValue = value.length() == 0 ? null : Boolean.valueOf(value);
- } else if (type == Float.TYPE) {
- convertedValue = value.length() == 0 ? 0 : Float.valueOf(value);
- } else if (type == Float.class) {
- convertedValue = value.length() == 0 ? null : Float.valueOf(value);
- } else if (type == Double.TYPE) {
- convertedValue = value.length() == 0 ? 0 : Double.valueOf(value);
- } else if (type == Double.class) {
- convertedValue = value.length() == 0 ? null : Double.valueOf(value);
- } else if (type == Long.TYPE) {
- convertedValue = value.length() == 0 ? 0 : Long.decode(value);
- } else if (type == Long.class) {
- convertedValue = value.length() == 0 ? null : Long.decode(value);
- } else if (type == Short.TYPE) {
- convertedValue = value.length() == 0 ? 0 : Short.decode(value);
- } else if (type == Short.class) {
- convertedValue = value.length() == 0 ? null : Short.decode(value);
- } else if (type == Character.TYPE) {
- convertedValue = value.length() == 0 ? 0 : value.charAt(0);
- } else if (type == Character.class) {
- convertedValue = value.length() == 0 ? null : value.charAt(0);
- } else if (type == Byte.TYPE) {
- convertedValue = value.length() == 0 ? 0 : Byte.decode(value);
- } else if (type == Byte.class) {
- convertedValue = value.length() == 0 ? null : Byte.decode(value);
- } else
- throw new YamlException("Unknown field type.");
- if (anchor != null) anchors.put(anchor, convertedValue);
- return convertedValue;
- } catch (Exception ex) {
- throw new YamlReaderException("Unable to convert value to required type \"" + type + "\": " + value, ex);
+ for (Entry entry : config.scalarSerializers.entrySet()) {
+ if (entry.getKey().isAssignableFrom(type)) {
+ ScalarSerializer serializer = entry.getValue();
+ Event event = parser.getNextEvent();
+ if (event.type != SCALAR) throw new YamlReaderException("Expected scalar for type '" + type
+ + "' to be deserialized by scalar serializer '" + serializer.getClass().getName() + "' but found: " + event.type);
+ Object value = serializer.read(((ScalarEvent)event).value);
+ if (anchor != null) addAnchor(anchor, value);
+ return value;
}
}
@@ -233,7 +326,7 @@ private Object readValueInternal (Class type, Class elementType, String anchor)
Event event = parser.getNextEvent();
if (event.type != SCALAR) throw new YamlReaderException("Expected scalar for enum type but found: " + event.type);
String enumValueName = ((ScalarEvent)event).value;
- if (enumValueName.length() == 0) return null;
+ if (enumValueName == null) return null;
try {
return Enum.valueOf(type, enumValueName);
} catch (Exception ex) {
@@ -241,19 +334,6 @@ private Object readValueInternal (Class type, Class elementType, String anchor)
}
}
- for (Entry entry : config.scalarSerializers.entrySet()) {
- if (entry.getKey().isAssignableFrom(type)) {
- ScalarSerializer serializer = entry.getValue();
- Event event = parser.getNextEvent();
- if (event.type != SCALAR)
- throw new YamlReaderException("Expected scalar for type '" + type + "' to be deserialized by scalar serializer '"
- + serializer.getClass().getName() + "' but found: " + event.type);
- Object value = serializer.read(((ScalarEvent)event).value);
- if (anchor != null) anchors.put(anchor, value);
- return value;
- }
- }
-
Event event = parser.peekNextEvent();
switch (event.type) {
case MAPPING_START: {
@@ -265,7 +345,8 @@ private Object readValueInternal (Class type, Class elementType, String anchor)
} catch (InvocationTargetException ex) {
throw new YamlReaderException("Error creating object.", ex);
}
- if (anchor != null) anchors.put(anchor, object);
+ if (anchor != null) addAnchor(anchor, object);
+ ArrayList keys = new ArrayList();
while (true) {
if (parser.peekNextEvent().type == MAPPING_END) {
parser.getNextEvent();
@@ -282,15 +363,54 @@ private Object readValueInternal (Class type, Class elementType, String anchor)
}
if (object instanceof Map) {
// Add to map.
+ if (config.tagSuffix != null) {
+ Event nextEvent = parser.peekNextEvent();
+ switch (nextEvent.type) {
+ case MAPPING_START:
+ case SEQUENCE_START:
+ ((Map)object).put(key + config.tagSuffix, ((CollectionStartEvent)nextEvent).tag);
+ break;
+ case SCALAR:
+ ((Map)object).put(key + config.tagSuffix, ((ScalarEvent)nextEvent).tag);
+ break;
+ }
+ }
if (!isExplicitKey) value = readValue(elementType, null, null);
- ((Map)object).put(key, value);
+ if (!config.allowDuplicates && ((Map)object).containsKey(key)) {
+ throw new YamlReaderException("Duplicate key found '" + key + "'");
+ }
+ if (config.readConfig.autoMerge && "<<".equals(key) && value != null)
+ mergeMap((Map)object, value);
+ else
+ ((Map)object).put(key, value);
} else {
// Set field on object.
try {
+ if (!config.allowDuplicates && keys.contains(key)) {
+ throw new YamlReaderException("Duplicate key found '" + key + "'");
+ }
+ keys.add(key);
+
Property property = Beans.getProperty(type, (String)key, config.beanProperties, config.privateFields, config);
- if (property == null)
+ if (property == null) {
+ if (config.readConfig.ignoreUnknownProperties) {
+ // if next event is sequence, mapping... start, go though all of it until
+ // corresponding sequence, mapping... end
+ Event nextEvent = parser.peekNextEvent();
+ EventType nextType = nextEvent.type;
+ if (nextType == SEQUENCE_START || nextType == MAPPING_START) {
+ skipRange();
+ } else {
+ // go though the next event, because this is a value of missing property
+ parser.getNextEvent();
+ }
+
+ continue;
+ }
throw new YamlReaderException("Unable to find property '" + key + "' on class: " + type.getName());
+ }
Class propertyElementType = config.propertyToElementType.get(property);
+ if (propertyElementType == null) propertyElementType = property.getElementType();
Class propertyDefaultType = config.propertyToDefaultType.get(property);
if (!isExplicitKey) value = readValue(property.getType(), propertyElementType, propertyDefaultType);
property.set(object, value);
@@ -303,7 +423,7 @@ private Object readValueInternal (Class type, Class elementType, String anchor)
if (object instanceof DeferredConstruction) {
try {
object = ((DeferredConstruction)object).construct();
- if (anchor != null) anchors.put(anchor, object); // Update anchor with real object.
+ if (anchor != null) addAnchor(anchor, object); // Update anchor with real object.
} catch (InvocationTargetException ex) {
throw new YamlReaderException("Error creating object.", ex);
}
@@ -325,7 +445,7 @@ private Object readValueInternal (Class type, Class elementType, String anchor)
elementType = type.getComponentType();
} else
throw new YamlReaderException("A sequence is not a valid value for the type: " + type.getName());
- if (!type.isArray() && anchor != null) anchors.put(anchor, collection);
+ if (!type.isArray() && anchor != null) addAnchor(anchor, collection);
while (true) {
event = parser.peekNextEvent();
if (event.type == SEQUENCE_END) {
@@ -339,22 +459,32 @@ private Object readValueInternal (Class type, Class elementType, String anchor)
int i = 0;
for (Object object : collection)
Array.set(array, i++, object);
- if (anchor != null) anchors.put(anchor, array);
+ if (anchor != null) addAnchor(anchor, array);
return array;
}
- case SCALAR:
- // Interpret an empty scalar as null.
- System.out.println(((ScalarEvent)event).value);
- if (((ScalarEvent)event).value.length() == 0) {
- event = parser.getNextEvent();
- return null;
- }
- // Fall through.
default:
throw new YamlReaderException("Expected data for a " + type.getName() + " field but found: " + event.type);
}
}
+ /** see http://yaml.org/type/merge.html */
+ @SuppressWarnings("unchecked")
+ private void mergeMap (Map dest, Object source) throws YamlReaderException {
+ if (source instanceof Collection) {
+ for (Object item : ((Collection)source))
+ mergeMap(dest, item);
+ } else if (source instanceof Map) {
+ Map map = (Map)source;
+ for (Map.Entry entry : map.entrySet()) {
+ if (!dest.containsKey(entry.getKey())) dest.put(entry.getKey(), entry.getValue());
+
+ }
+ } else
+ throw new YamlReaderException("Expected a mapping or a sequence of mappings for a '<<' merge field but found: "
+ + source.getClass().getSimpleName());
+
+ }
+
/** Returns a new object of the requested type. */
protected Object createObject (Class type) throws InvocationTargetException {
// Use deferred construction if a non-zero-arg constructor is available.
@@ -373,8 +503,54 @@ public YamlReaderException (String message) {
}
}
+ private Number parseNumber(String value) {
+ Number number = null;
+ try {
+ number = Long.decode(value);
+ } catch (NumberFormatException e) {
+ }
+ if (number == null) {
+ try {
+ number = Double.parseDouble(value);
+ } catch (NumberFormatException e) {
+ }
+ }
+ return number;
+ }
+
+ private void skipRange () {
+ Event nextEvent;
+ int depth = 0;
+ do {
+ nextEvent = parser.getNextEvent();
+ switch (nextEvent.type) {
+ case SEQUENCE_START:
+ depth++;
+ break;
+ case MAPPING_START:
+ depth++;
+ break;
+ case SEQUENCE_END:
+ depth--;
+ break;
+ case MAPPING_END:
+ depth--;
+ break;
+ default:
+ // ignore
+ break;
+ }
+ } while (depth > 0);
+ }
+
public static void main (String[] args) throws Exception {
YamlReader reader = new YamlReader(new FileReader("test/test.yml"));
- System.out.println(reader.read());
+ Object object = reader.read();
+ System.out.println(object);
+ StringWriter string = new StringWriter();
+ YamlWriter writer = new YamlWriter(string);
+ writer.write(object);
+ writer.close();
+ System.out.println(string);
}
}
diff --git a/src/com/esotericsoftware/yamlbeans/YamlWriter.java b/src/com/esotericsoftware/yamlbeans/YamlWriter.java
index 6e62de8..9fee0f6 100644
--- a/src/com/esotericsoftware/yamlbeans/YamlWriter.java
+++ b/src/com/esotericsoftware/yamlbeans/YamlWriter.java
@@ -16,20 +16,6 @@
package com.esotericsoftware.yamlbeans;
-import com.esotericsoftware.yamlbeans.Beans.Property;
-import com.esotericsoftware.yamlbeans.YamlConfig.WriteConfig;
-import com.esotericsoftware.yamlbeans.emitter.Emitter;
-import com.esotericsoftware.yamlbeans.emitter.EmitterException;
-import com.esotericsoftware.yamlbeans.parser.AliasEvent;
-import com.esotericsoftware.yamlbeans.parser.DocumentEndEvent;
-import com.esotericsoftware.yamlbeans.parser.DocumentStartEvent;
-import com.esotericsoftware.yamlbeans.parser.Event;
-import com.esotericsoftware.yamlbeans.parser.MappingStartEvent;
-import com.esotericsoftware.yamlbeans.parser.ScalarEvent;
-import com.esotericsoftware.yamlbeans.parser.SequenceStartEvent;
-import com.esotericsoftware.yamlbeans.scalar.ScalarSerializer;
-
-import java.beans.IntrospectionException;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Array;
@@ -44,9 +30,24 @@
import java.util.Map.Entry;
import java.util.Set;
+import com.esotericsoftware.yamlbeans.Beans.Property;
+import com.esotericsoftware.yamlbeans.YamlConfig.WriteClassName;
+import com.esotericsoftware.yamlbeans.YamlConfig.WriteConfig;
+import com.esotericsoftware.yamlbeans.document.YamlElement;
+import com.esotericsoftware.yamlbeans.emitter.Emitter;
+import com.esotericsoftware.yamlbeans.emitter.EmitterException;
+import com.esotericsoftware.yamlbeans.parser.AliasEvent;
+import com.esotericsoftware.yamlbeans.parser.DocumentEndEvent;
+import com.esotericsoftware.yamlbeans.parser.DocumentStartEvent;
+import com.esotericsoftware.yamlbeans.parser.Event;
+import com.esotericsoftware.yamlbeans.parser.MappingStartEvent;
+import com.esotericsoftware.yamlbeans.parser.ScalarEvent;
+import com.esotericsoftware.yamlbeans.parser.SequenceStartEvent;
+import com.esotericsoftware.yamlbeans.scalar.ScalarSerializer;
+
/** Serializes Java objects as YAML.
* @author Nathan Sweet */
-public class YamlWriter {
+public class YamlWriter implements AutoCloseable {
private final YamlConfig config;
private final Emitter emitter;
private boolean started;
@@ -91,7 +92,8 @@ private void writeInternal (Object object) throws YamlException {
emitter.emit(Event.STREAM_START);
started = true;
}
- emitter.emit(new DocumentStartEvent(config.writeConfig.explicitFirstDocument, null, null));
+ emitter.emit(new DocumentStartEvent(config.writeConfig.explicitFirstDocument, config.writeConfig.version,
+ config.writeConfig.tags));
isRoot = true;
writeValue(object, config.writeConfig.writeRootTags ? null : object.getClass(), null, null);
emitter.emit(new DocumentEndEvent(config.writeConfig.explicitEndDocument));
@@ -102,11 +104,6 @@ private void writeInternal (Object object) throws YamlException {
}
}
- /** Returns the YAML emitter, which allows the YAML output to be configured. */
- public Emitter getEmitter () {
- return emitter;
- }
-
/** Writes any buffered objects, then resets the list of anchored objects.
* @see WriteConfig#setAutoAnchor(boolean) */
public void clearAnchors () throws YamlException {
@@ -132,13 +129,17 @@ public void close () throws YamlException {
}
}
- private void writeValue (Object object, Class fieldClass, Class elementType, Class defaultType) throws EmitterException,
- IOException, YamlException {
+ private void writeValue (Object object, Class fieldClass, Class elementType, Class defaultType)
+ throws EmitterException, IOException, YamlException {
boolean isRoot = this.isRoot;
this.isRoot = false;
- if (object == null) {
- emitter.emit(new ScalarEvent(null, null, new boolean[] {true, true}, null, (char)0));
+ if (object instanceof YamlElement) {
+ ((YamlElement)object).emitEvent(emitter, config.writeConfig);
+ return;
+ } else if (object == null) {
+ emitter.emit(
+ new ScalarEvent(null, null, new boolean[] { true, true }, null, this.config.writeConfig.quote.c));
return;
}
@@ -146,18 +147,13 @@ private void writeValue (Object object, Class fieldClass, Class elementType, Cla
boolean unknownType = fieldClass == null;
if (unknownType) fieldClass = valueClass;
- if (object instanceof Enum) {
- emitter.emit(new ScalarEvent(null, null, new boolean[] {true, true}, ((Enum)object).name(), (char)0));
- return;
- }
-
String anchor = null;
- if (!Beans.isScalar(valueClass)) {
+ if (!Beans.isScalar(valueClass) && !(object instanceof Enum)) {
anchor = anchoredObjects.get(object);
if (config.writeConfig.autoAnchor) {
Integer count = referenceCount.get(object);
if (count == null) {
- emitter.emit(new AliasEvent(anchoredObjects.get(object)));
+ emitter.emit(new AliasEvent(anchor));
return;
}
if (count > 1) {
@@ -172,7 +168,8 @@ private void writeValue (Object object, Class fieldClass, Class elementType, Cla
String tag = null;
boolean showTag = false;
- if (unknownType || valueClass != fieldClass || config.writeConfig.alwaysWriteClassName) {
+ if ((unknownType || valueClass != fieldClass || config.writeConfig.writeClassName == WriteClassName.ALWAYS)
+ && config.writeConfig.writeClassName != WriteClassName.NEVER) {
showTag = true;
if ((unknownType || fieldClass == List.class) && valueClass == ArrayList.class) showTag = false;
if ((unknownType || fieldClass == Map.class) && valueClass == HashMap.class) showTag = false;
@@ -187,18 +184,27 @@ private void writeValue (Object object, Class fieldClass, Class elementType, Cla
for (Entry entry : config.scalarSerializers.entrySet()) {
if (entry.getKey().isAssignableFrom(valueClass)) {
ScalarSerializer serializer = entry.getValue();
- emitter.emit(new ScalarEvent(null, tag, new boolean[] {tag == null, tag == null}, serializer.write(object), (char)0));
+ emitter.emit(new ScalarEvent(null, tag, new boolean[] { tag == null, tag == null },
+ serializer.write(object), this.config.writeConfig.quote.c));
return;
}
}
if (Beans.isScalar(valueClass)) {
- emitter.emit(new ScalarEvent(null, null, new boolean[] {true, true}, String.valueOf(object), (char)0));
+ emitter.emit(new ScalarEvent(null, tag, new boolean[] { true, true }, String.valueOf(object),
+ this.config.writeConfig.quote.c));
+ return;
+ }
+
+ if (object instanceof Enum) {
+ emitter.emit(new ScalarEvent(null, object.getClass().getName(),
+ new boolean[] { object.getClass().equals(fieldClass), object.getClass().equals(fieldClass) },
+ ((Enum) object).name(), this.config.writeConfig.quote.c));
return;
}
if (object instanceof Collection) {
- emitter.emit(new SequenceStartEvent(anchor, tag, !showTag, false));
+ emitter.emit(new SequenceStartEvent(anchor, tag, !showTag, config.writeConfig.isFlowStyle()));
for (Object item : (Collection)object) {
if (isRoot && !config.writeConfig.writeRootElementTags) elementType = item.getClass();
writeValue(item, elementType, null, null);
@@ -208,12 +214,29 @@ private void writeValue (Object object, Class fieldClass, Class elementType, Cla
}
if (object instanceof Map) {
- emitter.emit(new MappingStartEvent(anchor, tag, !showTag, false));
- for (Object item : ((Map)object).entrySet()) {
+ emitter.emit(new MappingStartEvent(anchor, tag, !showTag, config.writeConfig.isFlowStyle()));
+ Map map = (Map)object;
+ for (Object item : map.entrySet()) {
Entry entry = (Entry)item;
- writeValue(entry.getKey(), null, null, null);
- if (isRoot && !config.writeConfig.writeRootElementTags) elementType = entry.getValue().getClass();
- writeValue(entry.getValue(), elementType, null, null);
+ Object key = entry.getKey(), value = entry.getValue();
+ if (isRoot && !config.writeConfig.writeRootElementTags) elementType = value.getClass();
+ if (config.tagSuffix != null && key instanceof String) {
+ // Skip tag keys.
+ if (((String)key).endsWith(config.tagSuffix)) continue;
+
+ // Write value with tag, if found.
+ if (value instanceof String) {
+ Object valueTag = map.get(key + config.tagSuffix);
+ if (valueTag instanceof String) {
+ writeValue(key, null, null, null);
+ emitter.emit(new ScalarEvent(null, (String) valueTag, new boolean[] { false, false },
+ (String) value, this.config.writeConfig.quote.c));
+ continue;
+ }
+ }
+ }
+ writeValue(key, null, null, null);
+ writeValue(value, elementType, null, null);
}
emitter.emit(Event.MAPPING_END);
return;
@@ -221,7 +244,7 @@ private void writeValue (Object object, Class fieldClass, Class elementType, Cla
if (fieldClass.isArray()) {
elementType = fieldClass.getComponentType();
- emitter.emit(new SequenceStartEvent(anchor, null, true, false));
+ emitter.emit(new SequenceStartEvent(anchor, null, true, config.writeConfig.isFlowStyle()));
for (int i = 0, n = Array.getLength(object); i < n; i++)
writeValue(Array.get(object, i), elementType, null, null);
emitter.emit(Event.SEQUENCE_END);
@@ -243,13 +266,8 @@ private void writeValue (Object object, Class fieldClass, Class elementType, Cla
}
}
- Set properties;
- try {
- properties = Beans.getProperties(valueClass, config.beanProperties, config.privateFields, config);
- } catch (IntrospectionException ex) {
- throw new YamlException("Error inspecting class: " + valueClass.getName(), ex);
- }
- emitter.emit(new MappingStartEvent(anchor, tag, !showTag, false));
+ Set properties = Beans.getProperties(valueClass, config.beanProperties, config.privateFields, config);
+ emitter.emit(new MappingStartEvent(anchor, tag, !showTag, config.writeConfig.isFlowStyle()));
for (Property property : properties) {
try {
Object propertyValue = property.get(object);
@@ -259,7 +277,8 @@ private void writeValue (Object object, Class fieldClass, Class elementType, Cla
if (propertyValue == null && prototypeValue == null) continue;
if (propertyValue != null && prototypeValue != null && prototypeValue.equals(propertyValue)) continue;
}
- emitter.emit(new ScalarEvent(null, null, new boolean[] {true, true}, property.getName(), (char)0));
+ emitter.emit(
+ new ScalarEvent(null, null, new boolean[] {true, true}, property.getName(), this.config.writeConfig.quote.c));
Class propertyElementType = config.propertyToElementType.get(property);
Class propertyDefaultType = config.propertyToDefaultType.get(property);
writeValue(propertyValue, property.getType(), propertyElementType, propertyDefaultType);
@@ -299,14 +318,9 @@ private void countObjectReferences (Object object) throws YamlException {
return;
}
- // Value must be a bean.
+ // Value must be an object.
- Set properties;
- try {
- properties = Beans.getProperties(object.getClass(), config.beanProperties, config.privateFields, config);
- } catch (IntrospectionException ex) {
- throw new YamlException("Error inspecting class: " + object.getClass().getName(), ex);
- }
+ Set properties = Beans.getProperties(object.getClass(), config.beanProperties, config.privateFields, config);
for (Property property : properties) {
if (Beans.isScalar(property.getType())) continue;
Object propertyValue;
diff --git a/src/com/esotericsoftware/yamlbeans/constants/Unicode.java b/src/com/esotericsoftware/yamlbeans/constants/Unicode.java
new file mode 100644
index 0000000..3581d7f
--- /dev/null
+++ b/src/com/esotericsoftware/yamlbeans/constants/Unicode.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2008 Nathan Sweet, Copyright (c) 2006 Ola Bini
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
+ * is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.esotericsoftware.yamlbeans.constants;
+
+public final class Unicode {
+
+ static public final char BELL = '\u0007';
+ static public final char BACKSPACE = '\u0008';
+ static public final char HORIZONTAL_TABULATION = '\u0009';
+ static public final char VERTICAL_TABULATION = '\u000b';
+ static public final char FORM_FEED = '\u000c';
+ static public final char ESCAPE = '\u001b';
+ static public final char SPACE = '\u0020';
+ static public final char TILDE = '\u007e';
+ static public final char NEXT_LINE = '\u0085';
+ static public final char NO_BREAK_SPACE = '\u00a0';
+
+ private Unicode() {
+ }
+}
diff --git a/src/com/esotericsoftware/yamlbeans/document/YamlAlias.java b/src/com/esotericsoftware/yamlbeans/document/YamlAlias.java
new file mode 100644
index 0000000..0078fb8
--- /dev/null
+++ b/src/com/esotericsoftware/yamlbeans/document/YamlAlias.java
@@ -0,0 +1,21 @@
+package com.esotericsoftware.yamlbeans.document;
+
+import java.io.IOException;
+
+import com.esotericsoftware.yamlbeans.YamlConfig.WriteConfig;
+import com.esotericsoftware.yamlbeans.emitter.Emitter;
+import com.esotericsoftware.yamlbeans.emitter.EmitterException;
+import com.esotericsoftware.yamlbeans.parser.AliasEvent;
+
+public class YamlAlias extends YamlElement {
+
+ @Override
+ public void emitEvent(Emitter emitter, WriteConfig config) throws EmitterException, IOException {
+ emitter.emit(new AliasEvent(anchor));
+ }
+
+ @Override
+ public String toString() {
+ return "*" + anchor;
+ }
+}
diff --git a/src/com/esotericsoftware/yamlbeans/document/YamlDocument.java b/src/com/esotericsoftware/yamlbeans/document/YamlDocument.java
new file mode 100644
index 0000000..8401da1
--- /dev/null
+++ b/src/com/esotericsoftware/yamlbeans/document/YamlDocument.java
@@ -0,0 +1,31 @@
+package com.esotericsoftware.yamlbeans.document;
+
+import java.util.Iterator;
+
+import com.esotericsoftware.yamlbeans.YamlException;
+
+public interface YamlDocument {
+
+ String getTag();
+ int size();
+ YamlEntry getEntry(String key) throws YamlException;
+ YamlEntry getEntry(int index) throws YamlException;
+ boolean deleteEntry(String key) throws YamlException;
+ void setEntry(String key, boolean value) throws YamlException;
+ void setEntry(String key, Number value) throws YamlException;
+ void setEntry(String key, String value) throws YamlException;
+ void setEntry(String key, YamlElement value) throws YamlException;
+ YamlElement getElement(int item) throws YamlException;
+ void deleteElement(int element) throws YamlException;
+ void setElement(int item, boolean value) throws YamlException;
+ void setElement(int item, Number value) throws YamlException;
+ void setElement(int item, String value) throws YamlException;
+ void setElement(int item, YamlElement element) throws YamlException;
+ void addElement(boolean value) throws YamlException;
+ void addElement(Number value) throws YamlException;
+ void addElement(String value) throws YamlException;
+ void addElement(YamlElement element) throws YamlException;
+
+ Iterator iterator();
+
+}
diff --git a/src/com/esotericsoftware/yamlbeans/document/YamlDocumentReader.java b/src/com/esotericsoftware/yamlbeans/document/YamlDocumentReader.java
new file mode 100644
index 0000000..2e3f76f
--- /dev/null
+++ b/src/com/esotericsoftware/yamlbeans/document/YamlDocumentReader.java
@@ -0,0 +1,215 @@
+package com.esotericsoftware.yamlbeans.document;
+
+import static com.esotericsoftware.yamlbeans.parser.EventType.*;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Iterator;
+
+import com.esotericsoftware.yamlbeans.Version;
+import com.esotericsoftware.yamlbeans.YamlException;
+import com.esotericsoftware.yamlbeans.parser.AliasEvent;
+import com.esotericsoftware.yamlbeans.parser.Event;
+import com.esotericsoftware.yamlbeans.parser.MappingStartEvent;
+import com.esotericsoftware.yamlbeans.parser.Parser;
+import com.esotericsoftware.yamlbeans.parser.Parser.ParserException;
+import com.esotericsoftware.yamlbeans.parser.ScalarEvent;
+import com.esotericsoftware.yamlbeans.parser.SequenceStartEvent;
+import com.esotericsoftware.yamlbeans.tokenizer.Tokenizer.TokenizerException;
+
+public class YamlDocumentReader {
+
+ Parser parser;
+
+ public YamlDocumentReader(String yaml) {
+ this(new StringReader(yaml));
+ }
+
+ public YamlDocumentReader(String yaml, Version version) {
+ this(new StringReader(yaml), version);
+ }
+
+ public YamlDocumentReader(Reader reader) {
+ this(reader, null);
+ }
+
+ public YamlDocumentReader(Reader reader, Version version) {
+ if(version==null)
+ version = Version.DEFAULT_VERSION;
+ parser = new Parser(reader, version);
+ }
+
+ public YamlDocument read() throws YamlException {
+ return read(YamlDocument.class);
+ }
+
+ @SuppressWarnings("unchecked")
+ public T read(Class type) throws YamlException {
+ try {
+ while (true) {
+ Event event = parser.peekNextEvent();
+ if (event == null)
+ return null;
+ switch (event.type) {
+ case STREAM_START:
+ parser.getNextEvent(); // consume it
+ break;
+ case STREAM_END:
+ parser.getNextEvent(); // consume it
+ return null;
+ case DOCUMENT_START:
+ parser.getNextEvent(); // consume it
+ return (T)readDocument();
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ } catch (ParserException ex) {
+ throw new YamlException("Error parsing YAML.", ex);
+ } catch (TokenizerException ex) {
+ throw new YamlException("Error tokenizing YAML.", ex);
+ }
+ }
+
+ public Iterator readAll(final Class type) {
+ Iterator iterator = new Iterator() {
+
+ public boolean hasNext() {
+ Event event = parser.peekNextEvent();
+ return event != null && event.type != STREAM_END;
+ }
+
+ public T next() {
+ try {
+ return read(type);
+ } catch (YamlException e) {
+ throw new RuntimeException("Iterative reading documents exception", e);
+ }
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ return iterator;
+ }
+
+ private YamlElement readDocument() {
+ YamlElement yamlElement = null;
+ Event event = parser.peekNextEvent();
+ switch (event.type) {
+ case SCALAR:
+ yamlElement = readScalar();
+ break;
+ case ALIAS:
+ yamlElement = readAlias();
+ break;
+ case MAPPING_START:
+ yamlElement = readMapping();
+ break;
+ case SEQUENCE_START:
+ yamlElement = readSequence();
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+ parser.getNextEvent(); // consume it(DOCUMENT_END)
+ return yamlElement;
+ }
+
+ private YamlMapping readMapping() {
+ Event event = parser.getNextEvent();
+ if(event.type!=MAPPING_START)
+ throw new IllegalStateException();
+ YamlMapping element = new YamlMapping();
+ MappingStartEvent mapping = (MappingStartEvent)event;
+ element.setTag(mapping.tag);
+ element.setAnchor(mapping.anchor);
+ readMappingElements(element);
+ return element;
+ }
+
+ private void readMappingElements(YamlMapping mapping) {
+ while(true) {
+ Event event = parser.peekNextEvent();
+ if(event.type == MAPPING_END) {
+ parser.getNextEvent(); // consume it
+ return;
+ } else {
+ YamlEntry entry = readEntry();
+ mapping.addEntry(entry);
+ }
+ }
+ }
+
+ private YamlEntry readEntry() {
+ YamlScalar scalar = readScalar();
+ YamlElement value = readValue();
+ return new YamlEntry(scalar, value);
+ }
+
+ private YamlElement readValue() {
+ Event event = parser.peekNextEvent();
+ switch(event.type) {
+ case SCALAR:
+ return readScalar();
+ case ALIAS:
+ return readAlias();
+ case MAPPING_START:
+ return readMapping();
+ case SEQUENCE_START:
+ return readSequence();
+ default:
+ throw new IllegalStateException();
+ }
+ }
+
+ private YamlAlias readAlias() {
+ Event event = parser.getNextEvent();
+ if(event.type!=ALIAS)
+ throw new IllegalStateException();
+ YamlAlias element = new YamlAlias();
+ AliasEvent alias = (AliasEvent)event;
+ element.setAnchor(alias.anchor);
+ return element;
+ }
+
+ private YamlSequence readSequence() {
+ Event event = parser.getNextEvent();
+ if(event.type!=SEQUENCE_START)
+ throw new IllegalStateException();
+ YamlSequence element = new YamlSequence();
+ SequenceStartEvent sequence = (SequenceStartEvent)event;
+ element.setTag(sequence.tag);
+ element.setAnchor(sequence.anchor);
+ readSequenceElements(element);
+ return element;
+ }
+
+ private void readSequenceElements(YamlSequence sequence) {
+ while(true) {
+ Event event = parser.peekNextEvent();
+ if(event.type==SEQUENCE_END) {
+ parser.getNextEvent(); // consume it
+ return;
+ } else {
+ YamlElement element = readValue();
+ sequence.addElement(element);
+ }
+ }
+ }
+
+ private YamlScalar readScalar() {
+ Event event = parser.getNextEvent();
+ if(event.type!= SCALAR)
+ throw new IllegalStateException();
+ ScalarEvent scalar = (ScalarEvent)event;
+ YamlScalar element = new YamlScalar();
+ element.setTag(scalar.tag);
+ element.setAnchor(scalar.anchor);
+ element.setValue(scalar.value);
+ return element;
+ }
+
+}
diff --git a/src/com/esotericsoftware/yamlbeans/document/YamlElement.java b/src/com/esotericsoftware/yamlbeans/document/YamlElement.java
new file mode 100644
index 0000000..b350aa5
--- /dev/null
+++ b/src/com/esotericsoftware/yamlbeans/document/YamlElement.java
@@ -0,0 +1,31 @@
+package com.esotericsoftware.yamlbeans.document;
+
+import java.io.IOException;
+
+import com.esotericsoftware.yamlbeans.YamlConfig.WriteConfig;
+import com.esotericsoftware.yamlbeans.emitter.Emitter;
+import com.esotericsoftware.yamlbeans.emitter.EmitterException;
+
+public abstract class YamlElement {
+
+ String tag;
+ String anchor;
+
+ public void setTag(String tag) {
+ this.tag = tag;
+ }
+
+ public void setAnchor(String anchor) {
+ this.anchor = anchor;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
+ public String getAnchor() {
+ return anchor;
+ }
+
+ public abstract void emitEvent(Emitter emitter, WriteConfig config) throws EmitterException, IOException;
+}
diff --git a/src/com/esotericsoftware/yamlbeans/document/YamlEntry.java b/src/com/esotericsoftware/yamlbeans/document/YamlEntry.java
new file mode 100644
index 0000000..43af578
--- /dev/null
+++ b/src/com/esotericsoftware/yamlbeans/document/YamlEntry.java
@@ -0,0 +1,65 @@
+package com.esotericsoftware.yamlbeans.document;
+
+import java.io.IOException;
+
+import com.esotericsoftware.yamlbeans.YamlConfig.WriteConfig;
+import com.esotericsoftware.yamlbeans.emitter.Emitter;
+import com.esotericsoftware.yamlbeans.emitter.EmitterException;
+import com.esotericsoftware.yamlbeans.parser.ScalarEvent;
+
+public class YamlEntry {
+
+ YamlScalar key;
+ YamlElement value;
+
+ public YamlEntry(YamlScalar key, YamlElement value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(key.toString());
+ sb.append(':');
+ sb.append(value.toString());
+ return sb.toString();
+ }
+
+ public YamlScalar getKey() {
+ return key;
+ }
+
+ public YamlElement getValue() {
+ return value;
+ }
+
+ public void setKey(YamlScalar key) {
+ this.key = key;
+ }
+
+ public void setValue(YamlElement value) {
+ this.value = value;
+ }
+
+ public void setValue(boolean value) {
+ this.value = new YamlScalar(value);
+ }
+
+ public void setValue(Number value) {
+ this.value = new YamlScalar(value);
+ }
+
+ public void setValue(String value) {
+ this.value = new YamlScalar(value);
+ }
+
+ public void emitEvent(Emitter emitter, WriteConfig config) throws EmitterException, IOException {
+ key.emitEvent(emitter, config);
+ if(value==null)
+ emitter.emit(new ScalarEvent(null, null, new boolean[] {true, true}, null, config.getQuote().getStyle()));
+ else
+ value.emitEvent(emitter, config);
+ }
+
+}
diff --git a/src/com/esotericsoftware/yamlbeans/document/YamlMapping.java b/src/com/esotericsoftware/yamlbeans/document/YamlMapping.java
new file mode 100644
index 0000000..eae6097
--- /dev/null
+++ b/src/com/esotericsoftware/yamlbeans/document/YamlMapping.java
@@ -0,0 +1,149 @@
+package com.esotericsoftware.yamlbeans.document;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.esotericsoftware.yamlbeans.YamlException;
+import com.esotericsoftware.yamlbeans.YamlConfig.WriteConfig;
+import com.esotericsoftware.yamlbeans.emitter.Emitter;
+import com.esotericsoftware.yamlbeans.emitter.EmitterException;
+import com.esotericsoftware.yamlbeans.parser.Event;
+import com.esotericsoftware.yamlbeans.parser.MappingStartEvent;
+
+public class YamlMapping extends YamlElement implements YamlDocument {
+
+ // use a list to keep the sequence
+ List entries = new LinkedList();
+
+ public int size() {
+ return entries.size();
+ }
+
+ public void addEntry(YamlEntry entry) {
+ entries.add(entry);
+ }
+
+ public boolean deleteEntry(String key) {
+ for(int index = 0; index < entries.size(); index++) {
+ if(key.equals(entries.get(index).getKey().getValue())) {
+ entries.remove(index);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public YamlEntry getEntry(String key) throws YamlException {
+ for(YamlEntry entry : entries) {
+ if(key.equals(entry.getKey().getValue()))
+ return entry;
+ }
+ return null;
+ }
+
+ public YamlEntry getEntry(int index) throws YamlException {
+ return entries.get(index);
+ }
+
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ if(anchor!=null) {
+ sb.append('&');
+ sb.append(anchor);
+ sb.append(' ');
+ }
+ if(tag!=null) {
+ sb.append(" !");
+ sb.append(tag);
+ }
+ if(!entries.isEmpty()) {
+ sb.append('{');
+ for(YamlEntry entry : entries) {
+ sb.append(entry.toString());
+ sb.append(',');
+ }
+ sb.setLength(sb.length() - 1);
+ sb.append('}');
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public void emitEvent(Emitter emitter, WriteConfig config) throws EmitterException, IOException {
+ emitter.emit(new MappingStartEvent(anchor, tag, tag==null, config.isFlowStyle()));
+ for(YamlEntry entry : entries)
+ entry.emitEvent(emitter, config);
+ emitter.emit(Event.MAPPING_END);
+ }
+
+ public void setEntry(String key, boolean value) throws YamlException {
+ setEntry(key, new YamlScalar(value));
+ }
+
+ public void setEntry(String key, Number value) throws YamlException {
+ setEntry(key, new YamlScalar(value));
+ }
+
+ public void setEntry(String key, String value) throws YamlException {
+ setEntry(key, new YamlScalar(value));
+ }
+
+ public void setEntry(String key, YamlElement value) throws YamlException {
+ YamlEntry entry = getEntry(key);
+ if(entry!=null)
+ entry.setValue(value);
+ else {
+ entry = new YamlEntry(new YamlScalar(key), value);
+ addEntry(entry);
+ }
+
+ }
+
+ public YamlElement getElement(int item) throws YamlException {
+ throw new YamlException("Can only get element on sequence!");
+ }
+
+ public void deleteElement(int element) throws YamlException {
+ throw new YamlException("Can only delete element on sequence!");
+ }
+
+ public void setElement(int item, boolean element) throws YamlException {
+ throw new YamlException("Can only set element on sequence!");
+ }
+
+ public void setElement(int item, Number element) throws YamlException {
+ throw new YamlException("Can only set element on sequence!");
+ }
+
+ public void setElement(int item, String element) throws YamlException {
+ throw new YamlException("Can only set element on sequence!");
+ }
+
+ public void setElement(int item, YamlElement element) throws YamlException {
+ throw new YamlException("Can only set element on sequence!");
+ }
+
+ public void addElement(boolean element) throws YamlException {
+ throw new YamlException("Can only add element on sequence!");
+ }
+
+ public void addElement(Number element) throws YamlException {
+ throw new YamlException("Can only add element on sequence!");
+ }
+
+ public void addElement(String element) throws YamlException {
+ throw new YamlException("Can only add element on sequence!");
+ }
+
+ public void addElement(YamlElement element) throws YamlException {
+ throw new YamlException("Can only add element on sequence!");
+ }
+
+ public Iterator iterator() {
+ return entries.iterator();
+ }
+}
diff --git a/src/com/esotericsoftware/yamlbeans/document/YamlScalar.java b/src/com/esotericsoftware/yamlbeans/document/YamlScalar.java
new file mode 100644
index 0000000..9050d3c
--- /dev/null
+++ b/src/com/esotericsoftware/yamlbeans/document/YamlScalar.java
@@ -0,0 +1,49 @@
+package com.esotericsoftware.yamlbeans.document;
+
+import java.io.IOException;
+
+import com.esotericsoftware.yamlbeans.YamlConfig.WriteConfig;
+import com.esotericsoftware.yamlbeans.emitter.Emitter;
+import com.esotericsoftware.yamlbeans.emitter.EmitterException;
+import com.esotericsoftware.yamlbeans.parser.ScalarEvent;
+
+public class YamlScalar extends YamlElement {
+
+ String value;
+
+ public YamlScalar() {
+ }
+
+ public YamlScalar(Object value) {
+ this.value = String.valueOf(value);
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ if(anchor!=null) {
+ sb.append('&');
+ sb.append(anchor);
+ sb.append(' ');
+ }
+ sb.append(value);
+ if(tag!=null) {
+ sb.append(" !");
+ sb.append(tag);
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public void emitEvent(Emitter emitter, WriteConfig config) throws EmitterException, IOException {
+ emitter.emit(new ScalarEvent(anchor, tag, new boolean[] {true, true}, value, config.getQuote().getStyle()));
+ }
+}
diff --git a/src/com/esotericsoftware/yamlbeans/document/YamlSequence.java b/src/com/esotericsoftware/yamlbeans/document/YamlSequence.java
new file mode 100644
index 0000000..1519ac2
--- /dev/null
+++ b/src/com/esotericsoftware/yamlbeans/document/YamlSequence.java
@@ -0,0 +1,127 @@
+package com.esotericsoftware.yamlbeans.document;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.esotericsoftware.yamlbeans.YamlConfig.WriteConfig;
+import com.esotericsoftware.yamlbeans.YamlException;
+import com.esotericsoftware.yamlbeans.emitter.Emitter;
+import com.esotericsoftware.yamlbeans.emitter.EmitterException;
+import com.esotericsoftware.yamlbeans.parser.Event;
+import com.esotericsoftware.yamlbeans.parser.SequenceStartEvent;
+
+public class YamlSequence extends YamlElement implements YamlDocument {
+
+ List elements = new LinkedList();
+
+ public int size() {
+ return elements.size();
+ }
+
+ public void addElement(YamlElement element) {
+ elements.add(element);
+ }
+
+ public void deleteElement(int item) throws YamlException {
+ elements.remove(item);
+ }
+
+ public YamlElement getElement(int item) throws YamlException {
+ return elements.get(item);
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ if(anchor!=null) {
+ sb.append('&');
+ sb.append(anchor);
+ sb.append(' ');
+ }
+ if(tag!=null) {
+ sb.append(" !");
+ sb.append(tag);
+ }
+ if(!elements.isEmpty()) {
+ sb.append('[');
+ for(YamlElement element : elements) {
+ sb.append(element.toString());
+ sb.append(',');
+ }
+ sb.setLength(sb.length() - 1);
+ sb.append(']');
+ }
+ return sb.toString();
+ }
+
+
+ @Override
+ public void emitEvent(Emitter emitter, WriteConfig config) throws EmitterException, IOException {
+ emitter.emit(new SequenceStartEvent(anchor, tag, tag==null, config.isFlowStyle()));
+ for (YamlElement element : elements)
+ element.emitEvent(emitter, config);
+ emitter.emit(Event.SEQUENCE_END);
+ }
+
+ public YamlEntry getEntry(String key) throws YamlException {
+ throw new YamlException("Can only get entry on mapping!");
+ }
+
+ public YamlEntry getEntry(int index) throws YamlException {
+ throw new YamlException("Can only get entry on mapping!");
+ }
+
+ public boolean deleteEntry(String key) throws YamlException {
+ throw new YamlException("Can only delete entry on mapping!");
+ }
+
+ public void setEntry(String key, boolean value) throws YamlException {
+ throw new YamlException("Can only set entry on mapping!");
+ }
+
+ public void setEntry(String key, Number value) throws YamlException {
+ throw new YamlException("Can only set entry on mapping!");
+ }
+
+ public void setEntry(String key, String value) throws YamlException {
+ throw new YamlException("Can only set entry on mapping!");
+ }
+
+ public void setEntry(String key, YamlElement value) throws YamlException {
+ throw new YamlException("Can only set entry on mapping!");
+ }
+
+ public void setElement(int item, boolean value) throws YamlException {
+ elements.set(item, new YamlScalar(value));
+ }
+
+ public void setElement(int item, Number value) throws YamlException {
+ elements.set(item, new YamlScalar(value));
+ }
+
+ public void setElement(int item, String value) throws YamlException {
+ elements.set(item, new YamlScalar(value));
+ }
+
+ public void setElement(int item, YamlElement element) throws YamlException {
+ elements.set(item, element);
+ }
+
+ public void addElement(boolean value) throws YamlException {
+ elements.add(new YamlScalar(value));
+ }
+
+ public void addElement(Number value) throws YamlException {
+ elements.add(new YamlScalar(value));
+ }
+
+ public void addElement(String value) throws YamlException {
+ elements.add(new YamlScalar(value));
+ }
+
+ public Iterator iterator() {
+ return elements.iterator();
+ }
+}
diff --git a/src/com/esotericsoftware/yamlbeans/emitter/Emitter.java b/src/com/esotericsoftware/yamlbeans/emitter/Emitter.java
index 30436d0..16735dc 100644
--- a/src/com/esotericsoftware/yamlbeans/emitter/Emitter.java
+++ b/src/com/esotericsoftware/yamlbeans/emitter/Emitter.java
@@ -18,20 +18,18 @@
import static com.esotericsoftware.yamlbeans.parser.EventType.*;
+import com.esotericsoftware.yamlbeans.Version;
import com.esotericsoftware.yamlbeans.parser.CollectionStartEvent;
import com.esotericsoftware.yamlbeans.parser.DocumentEndEvent;
import com.esotericsoftware.yamlbeans.parser.DocumentStartEvent;
import com.esotericsoftware.yamlbeans.parser.Event;
import com.esotericsoftware.yamlbeans.parser.MappingStartEvent;
import com.esotericsoftware.yamlbeans.parser.NodeEvent;
-import com.esotericsoftware.yamlbeans.parser.Parser;
import com.esotericsoftware.yamlbeans.parser.ScalarEvent;
import com.esotericsoftware.yamlbeans.parser.SequenceStartEvent;
import java.io.BufferedWriter;
-import java.io.FileReader;
import java.io.IOException;
-import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
@@ -140,11 +138,11 @@ public void expect () throws IOException {
if (event.type == DOCUMENT_START) {
DocumentStartEvent documentStartEvent = (DocumentStartEvent)event;
if (documentStartEvent.version != null) {
- if (documentStartEvent.version.major != 1)
+ if (documentStartEvent.version.getMajor() != 1)
throw new EmitterException("Unsupported YAML version: " + documentStartEvent.version);
writer.writeVersionDirective(documentStartEvent.version.toString());
}
- if ((documentStartEvent.version != null && documentStartEvent.version.equals(1, 0)) || config.version.equals(1, 0)) {
+ if ((documentStartEvent.version == Version.V1_0)) {
isVersion10 = true;
tagPrefixes = new HashMap(DEFAULT_TAG_PREFIXES_1_0);
} else
@@ -204,6 +202,9 @@ public void expect () throws IOException {
writer.writeIndicator("]", false, false, false);
state = states.remove(0);
} else {
+ if (config.prettyFlow) {
+ writer.writeIndent(flowLevel * config.indentSize);
+ }
if (config.canonical || writer.column > config.wrapColumn) writer.writeIndent(indent);
states.add(0, S_FLOW_SEQUENCE_ITEM);
expectNode(false, true, false, false);
@@ -215,14 +216,19 @@ public void expect () throws IOException {
if (event.type == SEQUENCE_END) {
indent = indents.remove(0);
flowLevel--;
+ if (config.prettyFlow) {
+ writer.writeIndent(flowLevel * config.indentSize);
+ }
if (config.canonical) {
- writer.writeIndicator(",", false, false, false);
writer.writeIndent(indent);
}
writer.writeIndicator("]", false, false, false);
state = states.remove(0);
} else {
writer.writeIndicator(",", false, false, false);
+ if (config.prettyFlow) {
+ writer.writeIndent(flowLevel * config.indentSize);
+ }
if (config.canonical || writer.column > config.wrapColumn) writer.writeIndent(indent);
states.add(0, S_FLOW_SEQUENCE_ITEM);
expectNode(false, true, false, false);
@@ -237,6 +243,9 @@ public void expect () throws IOException {
writer.writeIndicator("}", false, false, false);
state = states.remove(0);
} else {
+ if (config.prettyFlow) {
+ writer.writeIndent(flowLevel * config.indentSize);
+ }
if (config.canonical || writer.column > config.wrapColumn) writer.writeIndent(indent);
if (!config.canonical && checkSimpleKey()) {
states.add(0, S_FLOW_MAPPING_SIMPLE_VALUE);
@@ -269,14 +278,19 @@ public void expect () throws IOException {
if (event.type == MAPPING_END) {
indent = indents.remove(0);
flowLevel--;
+ if (config.prettyFlow) {
+ writer.writeIndent(flowLevel * config.indentSize);
+ }
if (config.canonical) {
- writer.writeIndicator(",", false, false, false);
writer.writeIndent(indent);
}
writer.writeIndicator("}", false, false, false);
state = states.remove(0);
} else {
writer.writeIndicator(",", false, false, false);
+ if (config.prettyFlow) {
+ writer.writeIndent(flowLevel * config.indentSize);
+ }
if (config.canonical || writer.column > config.wrapColumn) writer.writeIndent(indent);
if (!config.canonical && checkSimpleKey()) {
states.add(0, S_FLOW_MAPPING_SIMPLE_VALUE);
@@ -478,7 +492,7 @@ boolean checkSimpleKey () {
length += analysis.scalar.length();
}
- return length < 128
+ return length < 1024
&& (event.type == ALIAS || event.type == SCALAR && !analysis.empty && !analysis.multiline || checkEmptySequence() || checkEmptyMapping());
}
@@ -526,14 +540,20 @@ private char chooseScalarStyle () {
ScalarEvent ev = (ScalarEvent)event;
if (analysis == null) analysis = ScalarAnalysis.analyze(ev.value, config.escapeUnicode);
if (ev.style == '"' || config.canonical) return '"';
- if (ev.style == 0 && !(simpleKeyContext && (analysis.empty || analysis.multiline))
- && (flowLevel != 0 && analysis.allowFlowPlain || flowLevel == 0 && analysis.allowBlockPlain)) return 0;
- if (ev.style == 0 && ev.implicit[0] && !(simpleKeyContext && (analysis.empty || analysis.multiline))
- && (flowLevel != 0 && analysis.allowFlowPlain || flowLevel == 0 && analysis.allowBlockPlain)) return 0;
- if ((ev.style == '|' || ev.style == '>') && flowLevel == 0 && analysis.allowBlock) return '\'';
- if ((ev.style == 0 || ev.style == '\'') && analysis.allowSingleQuoted && !(simpleKeyContext && analysis.multiline))
+ if ((ev.style == 0 || ev.style == '|' || ev.style == '>')
+ && !(simpleKeyContext && (analysis.empty || analysis.multiline))
+ && ((flowLevel != 0 && analysis.allowFlowPlain) || (flowLevel == 0 && analysis.allowBlockPlain))) {
+ return 0;
+ }
+ if ((ev.style == 0 || ev.style == '\'') && analysis.allowSingleQuoted
+ && !(simpleKeyContext && analysis.multiline)) {
return '\'';
- if (ev.style == 0 && analysis.multiline && flowLevel == 0 && analysis.allowBlock) return '|';
+ }
+ if ((ev.style == 0 || ev.style == '|' || ev.style == '>') && analysis.multiline && flowLevel == 0
+ && analysis.allowBlock) {
+ return ev.style == 0 ? '|' : ev.style;
+ }
+
return '"';
}
@@ -640,14 +660,4 @@ private interface EmitterState {
DEFAULT_TAG_PREFIXES_1_1.put("!", "!");
DEFAULT_TAG_PREFIXES_1_1.put("tag:yaml.org,2002:", "!!");
}
-
- public static void main (String[] args) throws IOException {
- Parser parser = new Parser(new FileReader("test/test.yml"));
- Emitter emitter = new Emitter(new OutputStreamWriter(System.out));
- while (true) {
- Event event = parser.getNextEvent();
- if (event == null) break;
- emitter.emit(event);
- }
- }
}
diff --git a/src/com/esotericsoftware/yamlbeans/emitter/EmitterConfig.java b/src/com/esotericsoftware/yamlbeans/emitter/EmitterConfig.java
index be73ae5..5e313b5 100644
--- a/src/com/esotericsoftware/yamlbeans/emitter/EmitterConfig.java
+++ b/src/com/esotericsoftware/yamlbeans/emitter/EmitterConfig.java
@@ -16,22 +16,14 @@
package com.esotericsoftware.yamlbeans.emitter;
-import com.esotericsoftware.yamlbeans.Version;
-
/** @author Nathan Sweet */
public class EmitterConfig {
- Version version = new Version(1, 1);
boolean canonical;
boolean useVerbatimTags = true;
int indentSize = 3;
int wrapColumn = 100;
boolean escapeUnicode = true;
-
- /** Sets the YAML version to output. Default is 1.1. */
- public void setVersion (Version version) {
- if (version == null) throw new IllegalArgumentException("version cannot be null.");
- this.version = version;
- }
+ boolean prettyFlow;
/** If true, the YAML output will be canonical. Default is false. */
public void setCanonical (boolean canonical) {
@@ -50,7 +42,7 @@ public void setWrapColumn (int wrapColumn) {
this.wrapColumn = wrapColumn;
}
- /** If false, tags will never be surrounded by angle brackets (eg, "!"). Default is true. */
+ /** If false, tags will never be surrounded by angle brackets (eg, "!<java.util.LinkedList>"). Default is true. */
public void setUseVerbatimTags (boolean useVerbatimTags) {
this.useVerbatimTags = useVerbatimTags;
}
@@ -59,4 +51,9 @@ public void setUseVerbatimTags (boolean useVerbatimTags) {
public void setEscapeUnicode (boolean escapeUnicode) {
this.escapeUnicode = escapeUnicode;
}
+
+ /** If true, the YAML output will be pretty flow. Default is false. */
+ public void setPrettyFlow(boolean prettyFlow) {
+ this.prettyFlow = prettyFlow;
+ }
}
diff --git a/src/com/esotericsoftware/yamlbeans/emitter/EmitterWriter.java b/src/com/esotericsoftware/yamlbeans/emitter/EmitterWriter.java
index 7cdebc0..fd9efa9 100644
--- a/src/com/esotericsoftware/yamlbeans/emitter/EmitterWriter.java
+++ b/src/com/esotericsoftware/yamlbeans/emitter/EmitterWriter.java
@@ -21,24 +21,26 @@
import java.util.HashMap;
import java.util.Map;
+import com.esotericsoftware.yamlbeans.constants.Unicode;
+
/** @author Nathan Sweet
* @author Ola Bini */
class EmitterWriter {
private static final Map ESCAPE_REPLACEMENTS = new HashMap();
static {
ESCAPE_REPLACEMENTS.put((int)'\0', "0");
- ESCAPE_REPLACEMENTS.put((int)'\u0007', "a");
- ESCAPE_REPLACEMENTS.put((int)'\u0008', "b");
- ESCAPE_REPLACEMENTS.put((int)'\u0009', "t");
+ ESCAPE_REPLACEMENTS.put((int)Unicode.BELL, "a");
+ ESCAPE_REPLACEMENTS.put((int)Unicode.BACKSPACE, "b");
+ ESCAPE_REPLACEMENTS.put((int)Unicode.HORIZONTAL_TABULATION, "t");
ESCAPE_REPLACEMENTS.put((int)'\n', "n");
- ESCAPE_REPLACEMENTS.put((int)'\u000b', "v");
- ESCAPE_REPLACEMENTS.put((int)'\u000c', "f");
+ ESCAPE_REPLACEMENTS.put((int)Unicode.VERTICAL_TABULATION, "v");
+ ESCAPE_REPLACEMENTS.put((int)Unicode.FORM_FEED, "f");
ESCAPE_REPLACEMENTS.put((int)'\r', "r");
- ESCAPE_REPLACEMENTS.put((int)'\u001b', "e");
+ ESCAPE_REPLACEMENTS.put((int)Unicode.ESCAPE, "e");
ESCAPE_REPLACEMENTS.put((int)'"', "\"");
ESCAPE_REPLACEMENTS.put((int)'\\', "\\");
- ESCAPE_REPLACEMENTS.put((int)'\u0085', "N");
- ESCAPE_REPLACEMENTS.put((int)'\u00a0', "_");
+ ESCAPE_REPLACEMENTS.put((int)Unicode.NEXT_LINE, "N");
+ ESCAPE_REPLACEMENTS.put((int)Unicode.NO_BREAK_SPACE, "_");
}
private final Writer writer;
@@ -105,7 +107,7 @@ public void writeDoubleQuoted (String text, boolean split, int indent, int wrapC
while (ending <= text.length()) {
int ch = 0;
if (ending < text.length()) ch = text.codePointAt(ending);
- if (ch == 0 || "\"\\\u0085".indexOf(ch) != -1 || !('\u0020' <= ch && ch <= '\u007E')) {
+ if (ch == 0 || "\"\\\u0085".indexOf(ch) != -1 || !(Unicode.SPACE <= ch && ch <= Unicode.TILDE)) {
if (start < ending) {
data = text.substring(start, ending);
column += data.length();
@@ -180,7 +182,7 @@ public void writeSingleQuoted (String text, boolean split, int indent, int wrapC
start = ending;
}
} else if (breaks) {
- if (ceh == 0 || !('\n' == ceh || '\u0085' == ceh)) {
+ if (ceh == 0 || !('\n' == ceh || Unicode.NEXT_LINE == ceh)) {
data = text.substring(start, ending);
for (int i = 0, j = data.length(); i < j; i++) {
char cha = data.charAt(i);
@@ -192,7 +194,7 @@ public void writeSingleQuoted (String text, boolean split, int indent, int wrapC
writeIndent(indent);
start = ending;
}
- } else if (ceh == 0 || !('\n' == ceh || '\u0085' == ceh)) {
+ } else if (ceh == 0 || !('\n' == ceh || Unicode.NEXT_LINE == ceh)) {
if (start < ending) {
data = text.substring(start, ending);
column += data.length();
@@ -208,7 +210,7 @@ public void writeSingleQuoted (String text, boolean split, int indent, int wrapC
}
if (ceh != 0) {
spaces = ceh == ' ';
- breaks = ceh == '\n' || ceh == '\u0085';
+ breaks = ceh == '\n' || ceh == Unicode.NEXT_LINE;
}
ending++;
}
@@ -228,7 +230,7 @@ public void writeFolded (String text, int indent, int wrapColumn) throws IOExcep
char ceh = 0;
if (ending < text.length()) ceh = text.charAt(ending);
if (breaks) {
- if (ceh == 0 || !('\n' == ceh || '\u0085' == ceh)) {
+ if (ceh == 0 || !('\n' == ceh || Unicode.NEXT_LINE == ceh)) {
if (!leadingSpace && ceh != 0 && ceh != ' ' && text.charAt(start) == '\n') writeLineBreak(null);
leadingSpace = ceh == ' ';
data = text.substring(start, ending);
@@ -253,14 +255,14 @@ public void writeFolded (String text, int indent, int wrapColumn) throws IOExcep
}
start = ending;
}
- } else if (ceh == 0 || ' ' == ceh || '\n' == ceh || '\u0085' == ceh) {
+ } else if (ceh == 0 || ' ' == ceh || '\n' == ceh || Unicode.NEXT_LINE == ceh) {
data = text.substring(start, ending);
writer.write(data);
if (ceh == 0) writeLineBreak(null);
start = ending;
}
if (ceh != 0) {
- breaks = '\n' == ceh || '\u0085' == ceh;
+ breaks = '\n' == ceh || Unicode.NEXT_LINE == ceh;
spaces = ceh == ' ';
}
ending++;
@@ -278,7 +280,7 @@ public void writeLiteral (String text, int indent) throws IOException {
char ceh = 0;
if (ending < text.length()) ceh = text.charAt(ending);
if (breaks) {
- if (ceh == 0 || !('\n' == ceh || '\u0085' == ceh)) {
+ if (ceh == 0 || !('\n' == ceh || Unicode.NEXT_LINE == ceh)) {
data = text.substring(start, ending);
for (int i = 0, j = data.length(); i < j; i++) {
char cha = data.charAt(i);
@@ -290,13 +292,13 @@ public void writeLiteral (String text, int indent) throws IOException {
if (ceh != 0) writeIndent(indent);
start = ending;
}
- } else if (ceh == 0 || '\n' == ceh || '\u0085' == ceh) {
+ } else if (ceh == 0 || '\n' == ceh || Unicode.NEXT_LINE == ceh) {
data = text.substring(start, ending);
writer.write(data);
if (ceh == 0) writeLineBreak(null);
start = ending;
}
- if (ceh != 0) breaks = '\n' == ceh || '\u0085' == ceh;
+ if (ceh != 0) breaks = '\n' == ceh || Unicode.NEXT_LINE == ceh;
ending++;
}
}
@@ -330,7 +332,7 @@ public void writePlain (String text, boolean split, int indent, int wrapColumn)
start = ending;
}
} else if (breaks) {
- if (ceh != '\n' && ceh != '\u0085') {
+ if (ceh != '\n' && ceh != Unicode.NEXT_LINE) {
if (text.charAt(start) == '\n') writeLineBreak(null);
data = text.substring(start, ending);
for (int i = 0, j = data.length(); i < j; i++) {
@@ -345,7 +347,7 @@ public void writePlain (String text, boolean split, int indent, int wrapColumn)
indentation = false;
start = ending;
}
- } else if (ceh == 0 || ' ' == ceh || '\n' == ceh || '\u0085' == ceh) {
+ } else if (ceh == 0 || ' ' == ceh || '\n' == ceh || Unicode.NEXT_LINE == ceh) {
data = text.substring(start, ending);
column += data.length();
writer.write(data);
@@ -353,14 +355,14 @@ public void writePlain (String text, boolean split, int indent, int wrapColumn)
}
if (ceh != 0) {
spaces = ceh == ' ';
- breaks = ceh == '\n' || ceh == '\u0085';
+ breaks = ceh == '\n' || ceh == Unicode.NEXT_LINE;
}
ending++;
}
}
public void writeLineBreak (String data) throws IOException {
- if (data == null) data = "\n";
+ if (data == null) data = System.getProperty("line.separator");
whitespace = true;
indentation = true;
column = 0;
@@ -377,7 +379,7 @@ private String determineChomp (String text) {
tail = " " + tail;
char ceh = tail.charAt(tail.length() - 1);
char ceh2 = tail.charAt(tail.length() - 2);
- return ceh == '\n' || ceh == '\u0085' ? ceh2 == '\n' || ceh2 == '\u0085' ? "+" : "" : "-";
+ return ceh == '\n' || ceh == Unicode.NEXT_LINE ? ceh2 == '\n' || ceh2 == Unicode.NEXT_LINE ? "+" : "" : "-";
}
public void close () throws IOException {
diff --git a/src/com/esotericsoftware/yamlbeans/emitter/ScalarAnalysis.java b/src/com/esotericsoftware/yamlbeans/emitter/ScalarAnalysis.java
index f1b3384..02b78f4 100644
--- a/src/com/esotericsoftware/yamlbeans/emitter/ScalarAnalysis.java
+++ b/src/com/esotericsoftware/yamlbeans/emitter/ScalarAnalysis.java
@@ -18,6 +18,8 @@
import java.util.regex.Pattern;
+import com.esotericsoftware.yamlbeans.constants.Unicode;
+
/** @author Nathan Sweet
* @author Ola Bini */
class ScalarAnalysis {
@@ -48,7 +50,8 @@ private ScalarAnalysis (String scalar, boolean empty, boolean multiline, boolean
}
static public ScalarAnalysis analyze (String scalar, boolean escapeUnicode) {
- if (scalar == null || "".equals(scalar)) return new ScalarAnalysis(scalar, true, false, false, true, true, true, false);
+ if (scalar == null) return new ScalarAnalysis(scalar, true, false, false, true, true, true, false);
+ if ("".equals(scalar)) return new ScalarAnalysis(scalar, false, false, false, false, false, true, false);
boolean blockIndicators = false;
boolean flowIndicators = false;
boolean lineBreaks = false;
@@ -105,11 +108,11 @@ static public ScalarAnalysis analyze (String scalar, boolean escapeUnicode) {
blockIndicators = true;
}
}
- if (ceh == '\n' || '\u0085' == ceh) lineBreaks = true;
+ if (ceh == '\n' || Unicode.NEXT_LINE == ceh) lineBreaks = true;
if (escapeUnicode) {
- if (ceh != '\n' && ceh != '\t' && !('\u0020' <= ceh && ceh <= '\u007E')) specialCharacters = true;
+ if (ceh != '\n' && ceh != '\t' && !(Unicode.SPACE <= ceh && ceh <= Unicode.TILDE)) specialCharacters = true;
}
- if (' ' == ceh || '\n' == ceh || '\u0085' == ceh) {
+ if (' ' == ceh || '\n' == ceh || Unicode.NEXT_LINE == ceh) {
if (spaces && breaks) {
if (ceh != ' ') mixed = true;
} else if (spaces) {
diff --git a/src/com/esotericsoftware/yamlbeans/parser/Parser.java b/src/com/esotericsoftware/yamlbeans/parser/Parser.java
index d387ea2..0ffedf2 100644
--- a/src/com/esotericsoftware/yamlbeans/parser/Parser.java
+++ b/src/com/esotericsoftware/yamlbeans/parser/Parser.java
@@ -51,7 +51,7 @@ public class Parser {
Event peekedEvent;
public Parser (Reader reader) {
- this(reader, new Version(1, 1));
+ this(reader, Version.DEFAULT_VERSION);
}
public Parser (Reader reader, Version defaultVersion) {
@@ -79,7 +79,6 @@ public Event getNextEvent () throws ParserException, TokenizerException {
while (!parseStack.isEmpty()) {
Event event = parseStack.remove(0).produce();
if (event != null) {
- // System.out.println("Parser: " + event);
return event;
}
}
@@ -128,15 +127,24 @@ public Event produce () {
};
table[P_IMPLICIT_DOCUMENT] = new Production() {
public Event produce () {
- TokenType type = tokenizer.peekNextTokenType();
- if (!(type == DIRECTIVE || type == DOCUMENT_START || type == STREAM_END)) {
- parseStack.add(0, table[P_DOCUMENT_END]);
- parseStack.add(0, table[P_BLOCK_NODE]);
- parseStack.add(0, table[P_DOCUMENT_START_IMPLICIT]);
+ if (isNextTokenImplicitDocument()) {
+ parseImplicitDocument();
}
return null;
}
+
+ private boolean isNextTokenImplicitDocument() {
+ TokenType type = tokenizer.peekNextTokenType();
+ return type != DIRECTIVE && type != DOCUMENT_START && type != STREAM_END;
+ }
+
+ private void parseImplicitDocument() {
+ parseStack.add(0, table[P_DOCUMENT_END]);
+ parseStack.add(0, table[P_BLOCK_NODE]);
+ parseStack.add(0, table[P_DOCUMENT_START_IMPLICIT]);
+ }
};
+
table[P_EXPLICIT_DOCUMENT] = new Production() {
public Event produce () {
if (tokenizer.peekNextTokenType() != STREAM_END) {
@@ -223,7 +231,7 @@ public Event produce () {
if (tokenizer.peekNextTokenType() == ANCHOR) anchor = ((AnchorToken)tokenizer.getNextToken()).getInstanceName();
}
String tag = null;
- if (tagHandle != null && !tagHandle.equals("!")) {
+ if (tagHandle != null) {
if (!tagHandles.containsKey(tagHandle)) throw new ParserException("Undefined tag handle: " + tagHandle);
tag = tagHandles.get(tagHandle) + tagSuffix;
} else
@@ -580,7 +588,7 @@ public Event produce () {
};
table[P_EMPTY_SCALAR] = new Production() {
public Event produce () {
- return new ScalarEvent(null, null, new boolean[] {true, false}, "", (char)0);
+ return new ScalarEvent(null, null, new boolean[] {true, false}, null, (char)0);
}
};
}
@@ -591,9 +599,9 @@ DocumentStartEvent processDirectives (boolean explicit) {
DirectiveToken token = (DirectiveToken)tokenizer.getNextToken();
if (token.getDirective().equals("YAML")) {
if (documentVersion != null) throw new ParserException("Duplicate YAML directive.");
- documentVersion = new Version(token.getValue());
- if (documentVersion.major != 1)
- throw new ParserException("Unsupported YAML version (1.x is required): " + documentVersion);
+ documentVersion = Version.getVersion(token.getValue());
+ if (documentVersion == null || documentVersion.getMajor() != 1)
+ throw new ParserException("Unsupported YAML version (1.x is required): " + token.getValue());
} else if (token.getDirective().equals("TAG")) {
String[] values = token.getValue().split(" ");
String handle = values[0];
@@ -611,7 +619,7 @@ DocumentStartEvent processDirectives (boolean explicit) {
Map tags = null;
if (!tagHandles.isEmpty()) tags = new HashMap(tagHandles);
- Map baseTags = version.minor == 0 ? DEFAULT_TAGS_1_0 : DEFAULT_TAGS_1_1;
+ Map baseTags = version.getMinor() == 0 ? DEFAULT_TAGS_1_0 : DEFAULT_TAGS_1_1;
for (String key : baseTags.keySet())
if (!tagHandles.containsKey(key)) tagHandles.put(key, baseTags.get(key));
return new DocumentStartEvent(explicit, version, tags);
diff --git a/src/com/esotericsoftware/yamlbeans/tokenizer/Tokenizer.java b/src/com/esotericsoftware/yamlbeans/tokenizer/Tokenizer.java
index 9281cff..9bdd96a 100644
--- a/src/com/esotericsoftware/yamlbeans/tokenizer/Tokenizer.java
+++ b/src/com/esotericsoftware/yamlbeans/tokenizer/Tokenizer.java
@@ -42,7 +42,7 @@ public class Tokenizer {
private final static String BLANK_OR_LINEBR = " \r\n\u0085";
private final static String S4 = "\0 \t\r\n\u0028[]{}";
private final static String ALPHA = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
- private final static String STRANGE_CHAR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789][-';/?:@&=+$,.!~*()%";
+ private final static String STRANGE_CHAR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-#;/?:@&=+$,_.!~*'()[]";
private final static String RN = "\r\n";
private final static String BLANK_T = " \t";
private final static String SPACES_AND_STUFF = "'\"\\\0 \t\r\n\u0085";
@@ -51,7 +51,7 @@ public class Tokenizer {
private final static Pattern NON_PRINTABLE = Pattern.compile("[^\u0009\n\r\u0020-\u007E\u0085\u00A0-\u00FF]");
private final static Pattern NOT_HEXA = Pattern.compile("[^0-9A-Fa-f]");
private final static Pattern NON_ALPHA = Pattern.compile("[^-0-9A-Za-z_]");
- private final static Pattern R_FLOWZERO = Pattern.compile("[\0 \t\r\n\u0085]|(:[\0 \t\r\n\u0028])");
+ private final static Pattern R_FLOWZERO = Pattern.compile("[\0 \t\r\n\u0085]|(:[\0 \t\r\n\u0085])");
private final static Pattern R_FLOWNONZERO = Pattern.compile("[\0 \t\r\n\u0085\\[\\]{},:?]");
private final static Pattern END_OR_START = Pattern.compile("^(---|\\.\\.\\.)[\0 \t\r\n\u0085]$");
private final static Pattern ENDING = Pattern.compile("^---[\0 \t\r\n\u0085]$");
@@ -133,7 +133,6 @@ public Token getNextToken () throws TokenizerException {
if (!tokens.isEmpty()) {
tokensTaken++;
Token token = tokens.remove(0);
- // System.out.println("Tokenizer: " + token);
return token;
}
return null;
@@ -311,8 +310,8 @@ private Token fetchMoreTokens () {
}
if (BEG.matcher(prefix(2)).find()) return fetchPlain();
if (ch == '\t') throw new TokenizerException("Tabs cannot be used for indentation.");
- throw new TokenizerException("While scanning for the next token, a character that cannot begin a token was found: "
- + ch(ch));
+ throw new TokenizerException(
+ "While scanning for the next token, a character that cannot begin a token was found: " + ch(ch));
}
private int nextPossibleSimpleKey () {
@@ -569,14 +568,12 @@ private String scanDirectiveName () {
length++;
ch = peek(length);
}
- if (zlen)
- throw new TokenizerException("While scanning for a directive name, expected an alpha or numeric character but found: "
- + ch(ch));
+ if (zlen) throw new TokenizerException(
+ "While scanning for a directive name, expected an alpha or numeric character but found: " + ch(ch));
String value = prefixForward(length);
// forward(length);
- if (NULL_BL_LINEBR.indexOf(peek()) == -1)
- throw new TokenizerException("While scanning for a directive name, expected an alpha or numeric character but found: "
- + ch(ch));
+ if (NULL_BL_LINEBR.indexOf(peek()) == -1) throw new TokenizerException(
+ "While scanning for a directive name, expected an alpha or numeric character but found: " + ch(ch));
return value;
}
@@ -657,9 +654,8 @@ private Token scanAnchor (Token tok) {
throw new TokenizerException("While scanning an " + name + ", a non-alpha, non-numeric character was found.");
String value = prefixForward(length);
// forward(length);
- if (NON_ALPHA_OR_NUM.indexOf(peek()) == -1)
- throw new TokenizerException("While scanning an " + name + ", expected an alpha or numeric character but found: "
- + ch(peek()));
+ if (NON_ALPHA_OR_NUM.indexOf(peek()) == -1) throw new TokenizerException(
+ "While scanning an " + name + ", expected an alpha or numeric character but found: " + ch(peek()));
if (tok instanceof AnchorToken)
((AnchorToken)tok).setInstanceName(value);
else
@@ -709,7 +705,7 @@ private Token scanBlockScalar (char style) {
StringBuilder chunks = new StringBuilder();
forward();
Object[] chompi = scanBlockScalarIndicators();
- boolean chomping = ((Boolean)chompi[0]).booleanValue();
+ int chomping = ((Integer)chompi[0]).intValue();
int increment = ((Integer)chompi[1]).intValue();
scanBlockScalarIgnoredLine();
int minIndent = indent + 1;
@@ -750,7 +746,9 @@ private Token scanBlockScalar (char style) {
break;
}
- if (chomping) {
+ if (chomping == 0) {
+ chunks.append(lineBreak);
+ } else if (chomping == 2) {
chunks.append(lineBreak);
chunks.append(breaks);
}
@@ -759,36 +757,33 @@ private Token scanBlockScalar (char style) {
}
private Object[] scanBlockScalarIndicators () {
- boolean chomping = false;
+ int chomping = 0; // 0 = clip, 1 = strip, 2 = keep
int increment = -1;
char ch = peek();
if (ch == '-' || ch == '+') {
- chomping = ch == '+';
+ chomping = ch == '-' ? 1 : 2;
forward();
ch = peek();
if (Character.isDigit(ch)) {
increment = Integer.parseInt(("" + ch));
- if (increment == 0)
- throw new TokenizerException(
- "While scanning a black scaler, expected indentation indicator between 1 and 9 but found: 0");
+ if (increment == 0) throw new TokenizerException(
+ "While scanning a black scaler, expected indentation indicator between 1 and 9 but found: 0");
forward();
}
} else if (Character.isDigit(ch)) {
increment = Integer.parseInt(("" + ch));
- if (increment == 0)
- throw new TokenizerException(
- "While scanning a black scaler, expected indentation indicator between 1 and 9 but found: 0");
+ if (increment == 0) throw new TokenizerException(
+ "While scanning a black scaler, expected indentation indicator between 1 and 9 but found: 0");
forward();
ch = peek();
if (ch == '-' || ch == '+') {
- chomping = ch == '+';
+ chomping = ch == '-' ? 1 : 2;
forward();
}
}
- if (NULL_BL_LINEBR.indexOf(peek()) == -1)
- throw new TokenizerException("While scanning a block scalar, expected chomping or indentation indicators but found: "
- + ch(peek()));
- return new Object[] {Boolean.valueOf(chomping), increment};
+ if (NULL_BL_LINEBR.indexOf(peek()) == -1) throw new TokenizerException(
+ "While scanning a block scalar, expected chomping or indentation indicators but found: " + ch(peek()));
+ return new Object[] {Integer.valueOf(chomping), increment};
}
private String scanBlockScalarIgnoredLine () {
@@ -952,7 +947,7 @@ private Token scanPlain () {
chunks.append(prefixForward(length));
// forward(length);
spaces = scanPlainSpaces();
- if (spaces == null || flowLevel == 0 && column < ind) break;
+ if (spaces.length() == 0 || flowLevel == 0 && column < ind) break;
}
return new ScalarToken(chunks.toString(), true);
}
@@ -960,7 +955,8 @@ private Token scanPlain () {
private String scanPlainSpaces () {
StringBuilder chunks = new StringBuilder();
int length = 0;
- while (peek(length) == ' ')
+ // YAML recognizes two white space characters: space and tab.
+ while (peek(length) == ' ' || peek(length) == '\t')
length++;
String whitespaces = prefixForward(length);
// forward(length);
@@ -1034,7 +1030,7 @@ private String scanUriEscapes (String name) {
while (peek() == '%') {
forward();
try {
- bytes.append(Integer.parseInt(prefix(2), 16));
+ bytes.append(Character.toChars(Integer.parseInt(prefix(2), 16)));
} catch (NumberFormatException nfe) {
throw new TokenizerException("While scanning a " + name
+ ", expected a URI escape sequence of 2 hexadecimal numbers but found: " + ch(peek(1)) + " and " + ch(peek(2)));
diff --git a/test/com/esotericsoftware/yamlbeans/BeansTest.java b/test/com/esotericsoftware/yamlbeans/BeansTest.java
new file mode 100644
index 0000000..6f9cde0
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/BeansTest.java
@@ -0,0 +1,734 @@
+
+package com.esotericsoftware.yamlbeans;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.*;
+
+import static org.junit.Assert.*;
+
+@SuppressWarnings("synthetic-access")
+public class BeansTest {
+
+ private static final double DELTA = 0.0001;
+
+ private YamlConfig yamlConfig;
+
+ @Before
+ public void setup () throws Exception {
+ yamlConfig = new YamlConfig();
+ }
+
+ @Test
+ public void isScalar () throws Exception {
+ // Scalar Type
+ assertTrue(Beans.isScalar(String.class));
+ assertTrue(Beans.isScalar(Integer.class));
+ assertTrue(Beans.isScalar(Boolean.class));
+ assertTrue(Beans.isScalar(Float.class));
+ assertTrue(Beans.isScalar(Long.class));
+ assertTrue(Beans.isScalar(Double.class));
+ assertTrue(Beans.isScalar(Short.class));
+ assertTrue(Beans.isScalar(Byte.class));
+ assertTrue(Beans.isScalar(Character.class));
+ // Other Type
+ assertFalse(Beans.isScalar(Void.class));
+ assertFalse(Beans.isScalar(Number.class));
+ assertFalse(Beans.isScalar(Beans.class));
+ assertFalse(Beans.isScalar(YamlReader.class));
+ assertFalse(Beans.isScalar(YamlWriter.class));
+ }
+
+ @Test
+ public void getDeferredConstruction () throws Exception {
+ DeferredConstruction construction = Beans.getDeferredConstruction(MockClass.class, yamlConfig);
+ assertEquals(null, construction);
+ }
+
+ @Test
+ public void getDeferredConstructionWithPrivateConstructor () throws Exception {
+ DeferredConstruction construction = Beans.getDeferredConstruction(MockClassWithPrivateConstructor.class, yamlConfig);
+ assertEquals(null, construction);
+ }
+
+ @Test
+ public void createObject () throws Exception {
+ MockClass mockClass = (MockClass)Beans.createObject(MockClass.class, false);
+ MockClassWithPrivateConstructor mockClassWithPrivateConstructor = (MockClassWithPrivateConstructor)Beans
+ .createObject(MockClassWithPrivateConstructor.class, true);
+ List listCase = (List)Beans.createObject(List.class, false);
+ Set setCase = (Set)Beans.createObject(Set.class, false);
+ Map mapCase = (Map)Beans.createObject(Map.class, false);
+
+ assertNotNull(mockClass);
+ assertNotNull(mockClassWithPrivateConstructor);
+ assertNotNull(listCase);
+ assertNotNull(setCase);
+ assertNotNull(mapCase);
+
+ if (!(listCase instanceof ArrayList)) {
+ fail();
+ }
+ if (!(setCase instanceof HashSet)) {
+ fail();
+ }
+ if (!(mapCase instanceof HashMap)) {
+ fail();
+ }
+
+ try {
+ MockClassWithoutNoArgConstructor mockClassWithoutNoArgConstructor = (MockClassWithoutNoArgConstructor)Beans
+ .createObject(MockClassWithoutNoArgConstructor.class, false);
+ fail();
+ } catch (InvocationTargetException e) {
+
+ }
+ try {
+ mockClassWithPrivateConstructor = (MockClassWithPrivateConstructor)Beans
+ .createObject(MockClassWithPrivateConstructor.class, false);
+ fail();
+ } catch (InvocationTargetException e) {
+
+ }
+ }
+
+ @Test
+ public void getPropertiesWithNullType () throws Exception {
+ try {
+ Beans.getProperties(null, false, false, yamlConfig);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // nothing
+ }
+ }
+
+ @Test
+ public void getPropertiesWithBeanProperties () throws Exception {
+ final Set properties = Beans.getProperties(MockClass.class, true, false, yamlConfig);
+ assertEquals(9, properties.size());
+ }
+
+ @Test
+ public void getPropertiesWithPrivateFields () throws Exception {
+ final Set properties = Beans.getProperties(MockClass.class, false, true, yamlConfig);
+ assertEquals(9, properties.size());
+ }
+
+ @Test
+ public void getPropertyWithNullType () throws Exception {
+ try {
+ Beans.getProperty(null, null, false, false, yamlConfig);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // nothing
+ }
+ }
+
+ @Test
+ public void getPropertyWithNullName () throws Exception {
+ try {
+ Beans.getProperty(MockClass.class, null, false, false, yamlConfig);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // nothing
+ }
+ }
+
+ @Test
+ public void getPropertyWithEmptyName () throws Exception {
+ try {
+ Beans.getProperty(MockClass.class, "", false, false, yamlConfig);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // nothing
+ }
+
+ }
+
+ @Test
+ public void getPropertyBooleanTypeWithBeanProperties () throws Exception {
+ final Beans.Property booleanTypeProperty = Beans.getProperty(MockClass.class, "booleanType", true, false, yamlConfig);
+
+ assertTrue(booleanTypeProperty instanceof Beans.MethodProperty);
+ assertEquals(MockClass.class, booleanTypeProperty.getDeclaringClass());
+ assertEquals("booleanType", booleanTypeProperty.getName());
+ assertEquals(boolean.class, booleanTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(false, mockClass.booleanType);
+
+ booleanTypeProperty.set(mockClass, true);
+ assertEquals(true, booleanTypeProperty.get(mockClass));
+
+ booleanTypeProperty.set(mockClass, false);
+ assertEquals(false, booleanTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyCharTypeWithBeanProperties () throws Exception {
+ final Beans.Property charTypeProperty = Beans.getProperty(MockClass.class, "charType", true, false, yamlConfig);
+
+ assertTrue(charTypeProperty instanceof Beans.MethodProperty);
+ assertEquals(MockClass.class, charTypeProperty.getDeclaringClass());
+ assertEquals("charType", charTypeProperty.getName());
+ assertEquals(char.class, charTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(0, mockClass.charType);
+
+ charTypeProperty.set(mockClass, 'a');
+ assertEquals('a', charTypeProperty.get(mockClass));
+
+ charTypeProperty.set(mockClass, Character.MAX_VALUE);
+ assertEquals(Character.MAX_VALUE, charTypeProperty.get(mockClass));
+
+ charTypeProperty.set(mockClass, Character.MIN_VALUE);
+ assertEquals(Character.MIN_VALUE, charTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyByteTypeWithBeanProperties () throws Exception {
+ final Beans.Property byteTypeProperty = Beans.getProperty(MockClass.class, "byteType", true, false, yamlConfig);
+
+ assertTrue(byteTypeProperty instanceof Beans.MethodProperty);
+ assertEquals(MockClass.class, byteTypeProperty.getDeclaringClass());
+ assertEquals("byteType", byteTypeProperty.getName());
+ assertEquals(byte.class, byteTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(0, mockClass.byteType);
+
+ byteTypeProperty.set(mockClass, (byte)1);
+ assertEquals((byte)1, byteTypeProperty.get(mockClass));
+
+ byteTypeProperty.set(mockClass, Byte.MAX_VALUE);
+ assertEquals(Byte.MAX_VALUE, byteTypeProperty.get(mockClass));
+
+ byteTypeProperty.set(mockClass, Byte.MIN_VALUE);
+ assertEquals(Byte.MIN_VALUE, byteTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyShortTypeWithBeanProperties () throws Exception {
+ final Beans.Property shortTypeProperty = Beans.getProperty(MockClass.class, "shortType", true, false, yamlConfig);
+
+ assertTrue(shortTypeProperty instanceof Beans.MethodProperty);
+ assertEquals(MockClass.class, shortTypeProperty.getDeclaringClass());
+ assertEquals("shortType", shortTypeProperty.getName());
+ assertEquals(short.class, shortTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(0, mockClass.shortType);
+
+ shortTypeProperty.set(mockClass, (short)1);
+ assertEquals((short)1, shortTypeProperty.get(mockClass));
+
+ shortTypeProperty.set(mockClass, Short.MAX_VALUE);
+ assertEquals(Short.MAX_VALUE, shortTypeProperty.get(mockClass));
+
+ shortTypeProperty.set(mockClass, Short.MIN_VALUE);
+ assertEquals(Short.MIN_VALUE, shortTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyIntTypeWithBeanProperties () throws Exception {
+ final Beans.Property intTypeProperty = Beans.getProperty(MockClass.class, "intType", true, false, yamlConfig);
+
+ assertTrue(intTypeProperty instanceof Beans.MethodProperty);
+ assertEquals(MockClass.class, intTypeProperty.getDeclaringClass());
+ assertEquals("intType", intTypeProperty.getName());
+ assertEquals(int.class, intTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(0, mockClass.intType);
+
+ intTypeProperty.set(mockClass, 1);
+ assertEquals(1, intTypeProperty.get(mockClass));
+
+ intTypeProperty.set(mockClass, Integer.MAX_VALUE);
+ assertEquals(Integer.MAX_VALUE, intTypeProperty.get(mockClass));
+
+ intTypeProperty.set(mockClass, Integer.MIN_VALUE);
+ assertEquals(Integer.MIN_VALUE, intTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyLongTypeWithBeanProperties () throws Exception {
+ final Beans.Property longTypeProperty = Beans.getProperty(MockClass.class, "longType", true, false, yamlConfig);
+
+ assertTrue(longTypeProperty instanceof Beans.MethodProperty);
+ assertEquals(MockClass.class, longTypeProperty.getDeclaringClass());
+ assertEquals("longType", longTypeProperty.getName());
+ assertEquals(long.class, longTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(0, mockClass.longType);
+
+ longTypeProperty.set(mockClass, 1l);
+ assertEquals(1l, longTypeProperty.get(mockClass));
+
+ longTypeProperty.set(mockClass, Long.MAX_VALUE);
+ assertEquals(Long.MAX_VALUE, longTypeProperty.get(mockClass));
+
+ longTypeProperty.set(mockClass, Long.MIN_VALUE);
+ assertEquals(Long.MIN_VALUE, longTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyFloatTypeWithBeanProperties () throws Exception {
+ final Beans.Property floatTypeProperty = Beans.getProperty(MockClass.class, "floatType", true, false, yamlConfig);
+
+ assertTrue(floatTypeProperty instanceof Beans.MethodProperty);
+ assertEquals(MockClass.class, floatTypeProperty.getDeclaringClass());
+ assertEquals("floatType", floatTypeProperty.getName());
+ assertEquals(float.class, floatTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals((float)0, mockClass.floatType, DELTA);
+
+ floatTypeProperty.set(mockClass, (float)1.0);
+ assertEquals((float)1.0, floatTypeProperty.get(mockClass));
+
+ floatTypeProperty.set(mockClass, Float.MAX_VALUE);
+ assertEquals(Float.MAX_VALUE, floatTypeProperty.get(mockClass));
+
+ floatTypeProperty.set(mockClass, Float.MIN_VALUE);
+ assertEquals(Float.MIN_VALUE, floatTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyDoubleTypeWithBeanProperties () throws Exception {
+ final Beans.Property doubleTypeProperty = Beans.getProperty(MockClass.class, "doubleType", true, false, yamlConfig);
+
+ assertTrue(doubleTypeProperty instanceof Beans.MethodProperty);
+ assertEquals(MockClass.class, doubleTypeProperty.getDeclaringClass());
+ assertEquals("doubleType", doubleTypeProperty.getName());
+ assertEquals(double.class, doubleTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals((double)0, mockClass.doubleType, DELTA);
+
+ doubleTypeProperty.set(mockClass, (double)1.0);
+ assertEquals((double)1.0, doubleTypeProperty.get(mockClass));
+
+ doubleTypeProperty.set(mockClass, Double.MAX_VALUE);
+ assertEquals(Double.MAX_VALUE, doubleTypeProperty.get(mockClass));
+
+ doubleTypeProperty.set(mockClass, Double.MIN_VALUE);
+ assertEquals(Double.MIN_VALUE, doubleTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyStringTypeWithBeanProperties () throws Exception {
+ final Beans.Property stringTypeProperty = Beans.getProperty(MockClass.class, "stringType", true, false, yamlConfig);
+
+ assertTrue(stringTypeProperty instanceof Beans.MethodProperty);
+ assertEquals(MockClass.class, stringTypeProperty.getDeclaringClass());
+ assertEquals("stringType", stringTypeProperty.getName());
+ assertEquals(String.class, stringTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(null, mockClass.stringType);
+
+ stringTypeProperty.set(mockClass, "4cho");
+ assertEquals("4cho", stringTypeProperty.get(mockClass));
+
+ stringTypeProperty.set(mockClass, "ghkim");
+ assertEquals("ghkim", stringTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyNullWithBeanProperties () throws Exception {
+ final Beans.Property nullProperty = Beans.getProperty(MockClass.class, "nullType", true, false, yamlConfig);
+
+ assertNull(nullProperty);
+ }
+
+ @Test
+ public void getPropertyBooleanTypeWithPrivateFields () throws Exception {
+ final Beans.Property booleanTypeProperty = Beans.getProperty(MockClass.class, "booleanType", false, true, null);
+
+ assertTrue(booleanTypeProperty instanceof Beans.FieldProperty);
+ assertEquals(MockClass.class, booleanTypeProperty.getDeclaringClass());
+ assertEquals("booleanType", booleanTypeProperty.getName());
+ assertEquals(boolean.class, booleanTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(false, mockClass.booleanType);
+
+ booleanTypeProperty.set(mockClass, true);
+ assertEquals(true, booleanTypeProperty.get(mockClass));
+
+ booleanTypeProperty.set(mockClass, false);
+ assertEquals(false, booleanTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyCharTypeWithPrivateFields () throws Exception {
+ final Beans.Property charTypeProperty = Beans.getProperty(MockClass.class, "charType", false, true, yamlConfig);
+
+ assertTrue(charTypeProperty instanceof Beans.FieldProperty);
+ assertEquals(MockClass.class, charTypeProperty.getDeclaringClass());
+ assertEquals("charType", charTypeProperty.getName());
+ assertEquals(char.class, charTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(0, mockClass.charType);
+
+ charTypeProperty.set(mockClass, 'a');
+ assertEquals('a', charTypeProperty.get(mockClass));
+
+ charTypeProperty.set(mockClass, Character.MAX_VALUE);
+ assertEquals(Character.MAX_VALUE, charTypeProperty.get(mockClass));
+
+ charTypeProperty.set(mockClass, Character.MIN_VALUE);
+ assertEquals(Character.MIN_VALUE, charTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyByteTypeWithPrivateFields () throws Exception {
+ final Beans.Property byteTypeProperty = Beans.getProperty(MockClass.class, "byteType", false, true, yamlConfig);
+
+ assertTrue(byteTypeProperty instanceof Beans.FieldProperty);
+ assertEquals(MockClass.class, byteTypeProperty.getDeclaringClass());
+ assertEquals("byteType", byteTypeProperty.getName());
+ assertEquals(byte.class, byteTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(0, mockClass.byteType);
+
+ byteTypeProperty.set(mockClass, (byte)1);
+ assertEquals((byte)1, byteTypeProperty.get(mockClass));
+
+ byteTypeProperty.set(mockClass, Byte.MAX_VALUE);
+ assertEquals(Byte.MAX_VALUE, byteTypeProperty.get(mockClass));
+
+ byteTypeProperty.set(mockClass, Byte.MIN_VALUE);
+ assertEquals(Byte.MIN_VALUE, byteTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyShortTypeWithPrivateFields () throws Exception {
+ final Beans.Property shortTypeProperty = Beans.getProperty(MockClass.class, "shortType", false, true, yamlConfig);
+
+ assertTrue(shortTypeProperty instanceof Beans.FieldProperty);
+ assertEquals(MockClass.class, shortTypeProperty.getDeclaringClass());
+ assertEquals("shortType", shortTypeProperty.getName());
+ assertEquals(short.class, shortTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(0, mockClass.shortType);
+
+ shortTypeProperty.set(mockClass, (short)1);
+ assertEquals((short)1, shortTypeProperty.get(mockClass));
+
+ shortTypeProperty.set(mockClass, Short.MAX_VALUE);
+ assertEquals(Short.MAX_VALUE, shortTypeProperty.get(mockClass));
+
+ shortTypeProperty.set(mockClass, Short.MIN_VALUE);
+ assertEquals(Short.MIN_VALUE, shortTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyIntTypeWithPrivateFields () throws Exception {
+ final Beans.Property intTypeProperty = Beans.getProperty(MockClass.class, "intType", false, true, yamlConfig);
+
+ assertTrue(intTypeProperty instanceof Beans.FieldProperty);
+ assertEquals(MockClass.class, intTypeProperty.getDeclaringClass());
+ assertEquals("intType", intTypeProperty.getName());
+ assertEquals(int.class, intTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(0, mockClass.intType);
+
+ intTypeProperty.set(mockClass, 1);
+ assertEquals(1, intTypeProperty.get(mockClass));
+
+ intTypeProperty.set(mockClass, Integer.MAX_VALUE);
+ assertEquals(Integer.MAX_VALUE, intTypeProperty.get(mockClass));
+
+ intTypeProperty.set(mockClass, Integer.MIN_VALUE);
+ assertEquals(Integer.MIN_VALUE, intTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyLongTypeWithPrivateFields () throws Exception {
+ final Beans.Property longTypeProperty = Beans.getProperty(MockClass.class, "longType", false, true, yamlConfig);
+
+ assertTrue(longTypeProperty instanceof Beans.FieldProperty);
+ assertEquals(MockClass.class, longTypeProperty.getDeclaringClass());
+ assertEquals("longType", longTypeProperty.getName());
+ assertEquals(long.class, longTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(0, mockClass.longType);
+
+ longTypeProperty.set(mockClass, 1l);
+ assertEquals(1l, longTypeProperty.get(mockClass));
+
+ longTypeProperty.set(mockClass, Long.MAX_VALUE);
+ assertEquals(Long.MAX_VALUE, longTypeProperty.get(mockClass));
+
+ longTypeProperty.set(mockClass, Long.MIN_VALUE);
+ assertEquals(Long.MIN_VALUE, longTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyFloatTypeWithPrivateFields () throws Exception {
+ final Beans.Property floatTypeProperty = Beans.getProperty(MockClass.class, "floatType", false, true, yamlConfig);
+
+ assertTrue(floatTypeProperty instanceof Beans.FieldProperty);
+ assertEquals(MockClass.class, floatTypeProperty.getDeclaringClass());
+ assertEquals("floatType", floatTypeProperty.getName());
+ assertEquals(float.class, floatTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals((float)0, mockClass.floatType, DELTA);
+
+ floatTypeProperty.set(mockClass, (float)1.0);
+ assertEquals((float)1.0, floatTypeProperty.get(mockClass));
+
+ floatTypeProperty.set(mockClass, Float.MAX_VALUE);
+ assertEquals(Float.MAX_VALUE, floatTypeProperty.get(mockClass));
+
+ floatTypeProperty.set(mockClass, Float.MIN_VALUE);
+ assertEquals(Float.MIN_VALUE, floatTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyDoubleTypeWithPrivateFields () throws Exception {
+ final Beans.Property doubleTypeProperty = Beans.getProperty(MockClass.class, "doubleType", false, true, yamlConfig);
+
+ assertTrue(doubleTypeProperty instanceof Beans.FieldProperty);
+ assertEquals(MockClass.class, doubleTypeProperty.getDeclaringClass());
+ assertEquals("doubleType", doubleTypeProperty.getName());
+ assertEquals(double.class, doubleTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals((double)0, mockClass.doubleType, DELTA);
+
+ doubleTypeProperty.set(mockClass, (double)1.0);
+ assertEquals((double)1.0, doubleTypeProperty.get(mockClass));
+
+ doubleTypeProperty.set(mockClass, Double.MAX_VALUE);
+ assertEquals(Double.MAX_VALUE, doubleTypeProperty.get(mockClass));
+
+ doubleTypeProperty.set(mockClass, Double.MIN_VALUE);
+ assertEquals(Double.MIN_VALUE, doubleTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyStringTypeWithPrivateFields () throws Exception {
+ final Beans.Property stringTypeProperty = Beans.getProperty(MockClass.class, "stringType", false, true, yamlConfig);
+
+ assertTrue(stringTypeProperty instanceof Beans.FieldProperty);
+ assertEquals(MockClass.class, stringTypeProperty.getDeclaringClass());
+ assertEquals("stringType", stringTypeProperty.getName());
+ assertEquals(String.class, stringTypeProperty.getType());
+
+ MockClass mockClass = new MockClass();
+ assertEquals(null, mockClass.stringType);
+
+ stringTypeProperty.set(mockClass, "4cho");
+ assertEquals("4cho", stringTypeProperty.get(mockClass));
+
+ stringTypeProperty.set(mockClass, "ghkim");
+ assertEquals("ghkim", stringTypeProperty.get(mockClass));
+ }
+
+ @Test
+ public void getPropertyNullWithPrivateFields () throws Exception {
+ final Beans.Property nullProperty = Beans.getProperty(MockClass.class, "nullType", false, true, yamlConfig);
+
+ assertNull(nullProperty);
+ }
+
+ private static class MockClass {
+
+ private boolean booleanType;
+ private char charType;
+ private byte byteType;
+ private short shortType;
+ private int intType;
+ private long longType;
+ private float floatType;
+ private double doubleType;
+ private String stringType;
+
+ public MockClass () {
+
+ }
+
+ public boolean isBooleanType () {
+ return booleanType;
+ }
+
+ public void setBooleanType (boolean booleanType) {
+ this.booleanType = booleanType;
+ }
+
+ public char getCharType () {
+ return charType;
+ }
+
+ public void setCharType (char charType) {
+ this.charType = charType;
+ }
+
+ public byte getByteType () {
+ return byteType;
+ }
+
+ public void setByteType (byte byteType) {
+ this.byteType = byteType;
+ }
+
+ public short getShortType () {
+ return shortType;
+ }
+
+ public void setShortType (short shortType) {
+ this.shortType = shortType;
+ }
+
+ public int getIntType () {
+ return intType;
+ }
+
+ public void setIntType (int intType) {
+ this.intType = intType;
+ }
+
+ public long getLongType () {
+ return longType;
+ }
+
+ public void setLongType (long longType) {
+ this.longType = longType;
+ }
+
+ public float getFloatType () {
+ return floatType;
+ }
+
+ public void setFloatType (float floatType) {
+ this.floatType = floatType;
+ }
+
+ public double getDoubleType () {
+ return doubleType;
+ }
+
+ public void setDoubleType (double doubleType) {
+ this.doubleType = doubleType;
+ }
+
+ public String getStringType () {
+ return stringType;
+ }
+
+ public void setStringType (String stringType) {
+ this.stringType = stringType;
+ }
+ }
+
+ private static class MockClassWithPrivateConstructor {
+
+ private boolean booleanType;
+ private char charType;
+ private byte byteType;
+ private short shortType;
+ private int intType;
+ private long longType;
+ private float floatType;
+ private double doubleType;
+ private String stringType;
+
+ private MockClassWithPrivateConstructor () {
+
+ }
+
+ public boolean isBooleanType () {
+ return booleanType;
+ }
+
+ public void setBooleanType (boolean booleanType) {
+ this.booleanType = booleanType;
+ }
+
+ public char getCharType () {
+ return charType;
+ }
+
+ public void setCharType (char charType) {
+ this.charType = charType;
+ }
+
+ public byte getByteType () {
+ return byteType;
+ }
+
+ public void setByteType (byte byteType) {
+ this.byteType = byteType;
+ }
+
+ public short getShortType () {
+ return shortType;
+ }
+
+ public void setShortType (short shortType) {
+ this.shortType = shortType;
+ }
+
+ public int getIntType () {
+ return intType;
+ }
+
+ public void setIntType (int intType) {
+ this.intType = intType;
+ }
+
+ public long getLongType () {
+ return longType;
+ }
+
+ public void setLongType (long longType) {
+ this.longType = longType;
+ }
+
+ public float getFloatType () {
+ return floatType;
+ }
+
+ public void setFloatType (float floatType) {
+ this.floatType = floatType;
+ }
+
+ public double getDoubleType () {
+ return doubleType;
+ }
+
+ public void setDoubleType (double doubleType) {
+ this.doubleType = doubleType;
+ }
+
+ public String getStringType () {
+ return stringType;
+ }
+
+ public void setStringType (String stringType) {
+ this.stringType = stringType;
+ }
+ }
+
+ private static class MockClassWithoutNoArgConstructor {
+
+ private Object anyType;
+
+ public MockClassWithoutNoArgConstructor (Object anyType) {
+ this.anyType = anyType;
+ }
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/BooleanTest.java b/test/com/esotericsoftware/yamlbeans/BooleanTest.java
new file mode 100644
index 0000000..ac7a69d
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/BooleanTest.java
@@ -0,0 +1,91 @@
+package com.esotericsoftware.yamlbeans;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+
+public class BooleanTest extends TestCase {
+ public void testBooleanBean() throws Exception {
+ // Create a bean with a value differing from it's default
+ BeanWithBoolean val = new BeanWithBoolean();
+ val.setBool(true);
+ val.setBoolObj(true);
+ val.setBoolean(true);
+
+ // Store the bean
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ YamlWriter yamlWriter = new YamlWriter(new OutputStreamWriter(out));
+ yamlWriter.write(val);
+ yamlWriter.close();
+
+ // Load the bean
+ ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+ YamlReader yamlReader = new YamlReader(new InputStreamReader(in));
+ BeanWithBoolean got = yamlReader.read(BeanWithBoolean.class);
+
+ assertEquals(val, got);
+ }
+
+ public static class BeanWithBoolean {
+ private boolean bool = false;
+ private Boolean boolObj = false;
+ private boolean isBoolean = false;
+
+ public boolean isBool() {
+ return bool;
+ }
+
+ public void setBool(boolean bool) {
+ this.bool = bool;
+ }
+
+ public Boolean getBoolObj() {
+ return boolObj;
+ }
+
+ public void setBoolObj(Boolean boolObj) {
+ this.boolObj = boolObj;
+ }
+
+ public boolean isBoolean() {
+ return isBoolean;
+ }
+
+ public void setBoolean(boolean isBoolean) {
+ this.isBoolean = isBoolean;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ BeanWithBoolean that = (BeanWithBoolean) o;
+
+ if (bool != that.bool) return false;
+ if (isBoolean != that.isBoolean) return false;
+ return !(boolObj != null ? !boolObj.equals(that.boolObj) : that.boolObj != null);
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (bool ? 1 : 0);
+ result += (isBoolean ? 2 : 0);
+ result = 31 * result + (boolObj != null ? boolObj.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "BeanWithBoolean{" +
+ "bool=" + bool +
+ ", boolObj=" + boolObj +
+ ", isBoolean=" + isBoolean +
+ '}';
+ }
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/GenericTest.java b/test/com/esotericsoftware/yamlbeans/GenericTest.java
new file mode 100644
index 0000000..a04d3a8
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/GenericTest.java
@@ -0,0 +1,179 @@
+package com.esotericsoftware.yamlbeans;
+
+import com.esotericsoftware.yamlbeans.YamlConfig.WriteClassName;
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import java.io.StringWriter;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public class GenericTest extends TestCase {
+
+ private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ private static final String YAML
+ = "integerList: " + LINE_SEPARATOR
+ + "- 1" + LINE_SEPARATOR
+ + "- 100500" + LINE_SEPARATOR
+ + "- 10" + LINE_SEPARATOR
+ + "stringMap: " + LINE_SEPARATOR
+ + " a: av" + LINE_SEPARATOR
+ + " b: bv" + LINE_SEPARATOR
+ + "structList: " + LINE_SEPARATOR
+ + "- i: 10" + LINE_SEPARATOR
+ + " str: aaa" + LINE_SEPARATOR
+ + "- i: 20" + LINE_SEPARATOR
+ + " str: bbb" + LINE_SEPARATOR
+ + "structMap: " + LINE_SEPARATOR
+ + " a: " + LINE_SEPARATOR
+ + " i: 1" + LINE_SEPARATOR
+ + " str: aa" + LINE_SEPARATOR
+ + " b: " + LINE_SEPARATOR
+ + " i: 2" + LINE_SEPARATOR
+ + " str: ab" + LINE_SEPARATOR;
+
+ public void testRead() throws YamlException {
+ Test test = createTest();
+
+ Test read = new YamlReader(YAML).read(Test.class);
+ Assert.assertEquals(test, read);
+ }
+
+ public void testWrite() throws YamlException {
+ Test test = createTest();
+ StringWriter stringWriter = new StringWriter();
+
+ YamlWriter yamlWriter = new YamlWriter(stringWriter);
+ yamlWriter.getConfig().writeConfig.setWriteClassname(WriteClassName.NEVER);
+ yamlWriter.write(test);
+ yamlWriter.close();
+
+ Assert.assertEquals(YAML, stringWriter.getBuffer().toString());
+ }
+
+ private Test createTest() {
+ Map stringMap = new LinkedHashMap();
+ stringMap.put("a", "av");
+ stringMap.put("b", "bv");
+
+ Map structMap = new LinkedHashMap();
+ structMap.put("a", new Struct(1, "aa"));
+ structMap.put("b", new Struct(2, "ab"));
+
+ List integerList = new LinkedList();
+ integerList.add(1);
+ integerList.add(100500);
+ integerList.add(10);
+
+ List structList = new LinkedList();
+ structList.add(new Struct(10, "aaa"));
+ structList.add(new Struct(20, "bbb"));
+
+ Test test = new Test();
+ test.stringMap = stringMap;
+ test.structMap = structMap;
+ test.integerList = integerList;
+ test.structList = structList;
+
+ return test;
+ }
+
+ static class Struct {
+
+ public int i;
+ public String str;
+
+ Struct(int i, String str) {
+ this.i = i;
+ this.str = str;
+ }
+
+ Struct() {
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Struct)) {
+ return false;
+ }
+
+ Struct struct = (Struct) o;
+
+ if (i != struct.i) {
+ return false;
+ }
+ if (str != null ? !str.equals(struct.str) : struct.str != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = i;
+ result = 31 * result + (str != null ? str.hashCode() : 0);
+ return result;
+ }
+ }
+
+ static class Test {
+
+ public Map stringMap;
+ public Map structMap;
+ public List integerList;
+ public List structList;
+ public Map> multiMap;
+ public Map wildMap;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Test)) {
+ return false;
+ }
+
+ Test test = (Test) o;
+
+ if (integerList != null ? !integerList.equals(test.integerList) : test.integerList != null) {
+ return false;
+ }
+ if (stringMap != null ? !stringMap.equals(test.stringMap) : test.stringMap != null) {
+ return false;
+ }
+ if (structList != null ? !structList.equals(test.structList) : test.structList != null) {
+ return false;
+ }
+ if (structMap != null ? !structMap.equals(test.structMap) : test.structMap != null) {
+ return false;
+ }
+ if (multiMap != null ? !multiMap.equals(test.multiMap) : test.multiMap != null) {
+ return false;
+ }
+ if (wildMap != null ? !wildMap.equals(test.wildMap) : test.wildMap != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = stringMap != null ? stringMap.hashCode() : 0;
+ result = 31 * result + (structMap != null ? structMap.hashCode() : 0);
+ result = 31 * result + (integerList != null ? integerList.hashCode() : 0);
+ result = 31 * result + (structList != null ? structList.hashCode() : 0);
+ result = 31 * result + (multiMap != null ? multiMap.hashCode() : 0);
+ result = 31 * result + (wildMap != null ? wildMap.hashCode() : 0);
+ return result;
+ }
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/MergeTest.java b/test/com/esotericsoftware/yamlbeans/MergeTest.java
new file mode 100644
index 0000000..48e448b
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/MergeTest.java
@@ -0,0 +1,72 @@
+package com.esotericsoftware.yamlbeans;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.Map;
+
+import org.junit.Test;
+
+import com.esotericsoftware.yamlbeans.YamlReader.YamlReaderException;
+
+import static org.junit.Assert.*;
+
+public class MergeTest {
+
+ @SuppressWarnings("rawtypes")
+ @Test
+ public void testMerge() throws FileNotFoundException, YamlException {
+ InputStream input = new FileInputStream("test/test-merge.yml");
+ Reader reader = new InputStreamReader(input);
+ Map data = new YamlReader(reader).read(Map.class);
+ Map stuff = (Map)data.get("merged");
+ assertEquals("v1", stuff.get("v1"));
+ assertEquals("v2", stuff.get("v2"));
+ assertEquals("v3", stuff.get("v3"));
+ assertNull(stuff.get("<<"));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testMergeMultipleMaps() throws YamlException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("test1: &1\n").append(" - key1: value1\n").append(" - key2: value2\n");
+ sb.append("test2:\n").append(" << : *1");
+
+ YamlReader yamlReader = new YamlReader(sb.toString());
+ Map map = (Map) yamlReader.read();
+ assertEquals("value1", ((Map) map.get("test2")).get("key1"));
+ assertEquals("value2", ((Map) map.get("test2")).get("key2"));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testMergeUpdateValue() throws YamlException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("test1: &1\n").append(" - key1: value1\n").append(" - key2: value2\n").append(" - key3: value3\n");
+
+ sb.append("test2:\n").append(" key2: value22\n").append(" << : *1\n").append(" key3: value33\n");
+
+ YamlReader yamlReader = new YamlReader(sb.toString());
+ Map map = (Map) yamlReader.read();
+ assertEquals("value1", ((Map) map.get("test2")).get("key1"));
+ assertEquals("value22", ((Map) map.get("test2")).get("key2"));
+ assertEquals("value33", ((Map) map.get("test2")).get("key3"));
+ }
+
+ @Test
+ public void testMergeExpectThrowYamlReaderException() throws YamlException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("test1: &1 123\n");
+ sb.append("<< : *1\n");
+
+ YamlReader yamlReader = new YamlReader(sb.toString());
+ try {
+ yamlReader.read();
+ fail("Expected a mapping or a sequence of mappings");
+ } catch (YamlReaderException e) {
+ }
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/SafeYamlConfigTest.java b/test/com/esotericsoftware/yamlbeans/SafeYamlConfigTest.java
new file mode 100644
index 0000000..7d59e3c
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/SafeYamlConfigTest.java
@@ -0,0 +1,69 @@
+
+package com.esotericsoftware.yamlbeans;
+
+import static junit.framework.Assert.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+public class SafeYamlConfigTest {
+ private static final String TESTOBJECT_TAG = "!com.esotericsoftware.yamlbeans.SafeYamlConfigTest$TestObject";
+ private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ @Test
+ public void testDeserializationOfClassTag () throws YamlException {
+ SafeYamlConfig yamlConfig = new SafeYamlConfig();
+ StringBuilder yamlData = new StringBuilder();
+ yamlData.append(TESTOBJECT_TAG).append(LINE_SEPARATOR).append("a: test").append(LINE_SEPARATOR);
+ YamlReader reader = new YamlReader(yamlData.toString(), yamlConfig);
+ Object data = reader.read();
+ assertTrue(data instanceof HashMap);
+ Map dataMap = (Map)data;
+ assertTrue(dataMap.containsKey("a"));
+ assertEquals("test", dataMap.get("a"));
+ }
+
+ @Test
+ public void testIgnoreAnchor () throws YamlException {
+ SafeYamlConfig yamlConfig = new SafeYamlConfig();
+ StringBuilder yamlData = new StringBuilder();
+ yamlData.append("oldest friend:").append(LINE_SEPARATOR).append(" &1 !contact").append(LINE_SEPARATOR)
+ .append(" name: Bob").append(LINE_SEPARATOR).append(" age: 29").append(LINE_SEPARATOR).append("best friend: *1")
+ .append(LINE_SEPARATOR);
+ YamlReader reader = new YamlReader(yamlData.toString(), yamlConfig);
+ Object data = reader.read();
+ assertTrue(data instanceof HashMap);
+ Map dataMap = (Map)data;
+ assertTrue(dataMap.containsKey("oldest friend"));
+ Map old = (Map)dataMap.get("oldest friend");
+ assertTrue(old.containsKey("name"));
+ assertEquals("Bob", old.get("name"));
+ assertNull(dataMap.get("best friend"));
+ }
+
+ static class TestObject {
+ private String a;
+ public int age;
+ public String name;
+ public Object object;
+ public List objects;
+
+ private TestObject () {
+ }
+
+ public TestObject (String a) {
+ this.a = a;
+ }
+
+ public String getA () {
+ return a;
+ }
+
+ public void setA (String a) {
+ this.a = a;
+ }
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/TagDirectiveTest.java b/test/com/esotericsoftware/yamlbeans/TagDirectiveTest.java
new file mode 100644
index 0000000..1ab6adf
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/TagDirectiveTest.java
@@ -0,0 +1,84 @@
+package com.esotericsoftware.yamlbeans;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Iterator;
+
+import org.junit.Test;
+
+import com.esotericsoftware.yamlbeans.document.YamlDocumentReader;
+import com.esotericsoftware.yamlbeans.document.YamlElement;
+import com.esotericsoftware.yamlbeans.document.YamlSequence;
+
+public class TagDirectiveTest {
+
+ private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ @Test
+ public void testTagDirective() throws YamlException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("%TAG !yaml! tag:yaml.org,2002:").append(LINE_SEPARATOR);
+ sb.append("---").append(LINE_SEPARATOR);
+ sb.append("!yaml!str \"foo\"");
+
+ YamlReader yamlReader = new YamlReader(sb.toString());
+ assertEquals("foo", yamlReader.read().toString());
+ }
+
+ @Test(expected = YamlException.class)
+ public void testRepeatedTagDirective() throws YamlException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("%TAG %TAG ! !foo").append(LINE_SEPARATOR);
+ sb.append("%TAG %TAG ! !foo").append(LINE_SEPARATOR);
+ sb.append("---").append(LINE_SEPARATOR);
+ sb.append("bar");
+
+ new YamlReader(sb.toString()).read();
+ }
+
+ @Test
+ public void testTagHandles() throws YamlException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("%TAG ! !").append(LINE_SEPARATOR);
+ sb.append("%TAG !yaml! tag:yaml.org,2002:").append(LINE_SEPARATOR);
+ sb.append("%TAG !o! tag:ben-kiki.org,2000:").append(LINE_SEPARATOR);
+ sb.append("---").append(LINE_SEPARATOR);
+ sb.append("- !foo bar").append(LINE_SEPARATOR);
+ sb.append("- !!str string").append(LINE_SEPARATOR);
+ sb.append("- !o!type baz").append(LINE_SEPARATOR);
+ YamlDocumentReader yamlDocumentReader = new YamlDocumentReader(sb.toString());
+ Iterator iterator = yamlDocumentReader.read(YamlSequence.class).iterator();
+
+ YamlElement yamlElement = iterator.next();
+ assertEquals("!foo", yamlElement.getTag());
+
+ yamlElement = iterator.next();
+ assertEquals("tag:yaml.org,2002:str", yamlElement.getTag());
+
+ yamlElement = iterator.next();
+ assertEquals("tag:ben-kiki.org,2000:type", yamlElement.getTag());
+ }
+
+ @Test
+ public void testVersion() throws YamlException {
+ String yaml = "!str test";
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.readConfig.setDefaultVersion(Version.V1_0);
+ YamlReader yamlReader = new YamlReader(yaml, yamlConfig);
+ assertEquals("test", yamlReader.read());
+
+ yaml = "!!str test";
+ yamlConfig.readConfig.setDefaultVersion(Version.V1_1);
+ yamlReader = new YamlReader(yaml, yamlConfig);
+ assertEquals("test", yamlReader.read());
+
+ yaml = "!!str test";
+ yamlConfig.readConfig.setDefaultVersion(Version.V1_0);
+ yamlReader = new YamlReader(yaml, yamlConfig);
+ try {
+ yamlReader.read();
+ } catch (YamlException e) {
+ assertEquals("Error parsing YAML.", e.getMessage());
+ }
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/VersionTest.java b/test/com/esotericsoftware/yamlbeans/VersionTest.java
new file mode 100644
index 0000000..d763010
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/VersionTest.java
@@ -0,0 +1,39 @@
+package com.esotericsoftware.yamlbeans;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+
+public class VersionTest {
+
+ @Test
+ public void testV1_0() {
+ Version version = Version.V1_0;
+ assertEquals(1, version.getMajor());
+ assertEquals(0, version.getMinor());
+ assertEquals("1.0", version.toString());
+ }
+
+ @Test
+ public void testV1_1() {
+ Version version = Version.V1_1;
+ assertEquals(1, version.getMajor());
+ assertEquals(1, version.getMinor());
+ assertEquals("1.1", version.toString());
+ }
+
+ @Test
+ public void testGetVersion() {
+ assertEquals(Version.V1_0, Version.getVersion("1.0"));
+ assertEquals(Version.V1_1, Version.getVersion("1.1"));
+ assertNull(Version.getVersion(null));
+ assertNull(Version.getVersion("0"));
+ assertNull(Version.getVersion(".0"));
+ assertNull(Version.getVersion("0.1"));
+ assertNull(Version.getVersion("1.2"));
+ assertNull(Version.getVersion("2.0"));
+ assertNull(Version.getVersion("1.a"));
+ assertNull(Version.getVersion("a.1"));
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/YamlConfigTest.java b/test/com/esotericsoftware/yamlbeans/YamlConfigTest.java
new file mode 100644
index 0000000..ddb2bb2
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/YamlConfigTest.java
@@ -0,0 +1,677 @@
+package com.esotericsoftware.yamlbeans;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.esotericsoftware.yamlbeans.YamlConfig.Quote;
+import com.esotericsoftware.yamlbeans.YamlReader.YamlReaderException;
+import com.esotericsoftware.yamlbeans.scalar.DateSerializer;
+
+@SuppressWarnings("synthetic-access")
+public class YamlConfigTest {
+
+ private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ private static final String TESTOBJECT_TAG = "!com.esotericsoftware.yamlbeans.YamlConfigTest$TestObject";
+
+ private YamlConfig yamlConfig;
+
+ @Before
+ public void setup() throws Exception {
+ yamlConfig = new YamlConfig();
+ }
+
+ @Test
+ public void testSetClassTag() throws YamlException {
+ yamlConfig.setClassTag("String", String.class);
+ yamlConfig.setClassTag("!Int", Integer.class);
+ String yaml = "!String test\n---\n!Int 1";
+ YamlReader yamlReader = new YamlReader(yaml, yamlConfig);
+ assertEquals("test", yamlReader.read());
+ assertEquals(1, yamlReader.read());
+
+ try {
+ yamlConfig.setClassTag(null, String.class);
+ } catch (IllegalArgumentException e) {
+ assertEquals("tag cannot be null.", e.getMessage());
+ }
+
+ try {
+ yamlConfig.setClassTag("str", null);
+ } catch (IllegalArgumentException e) {
+ assertEquals("type cannot be null.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSetScalarSerializer() throws YamlException {
+ TimeZone timeZone = TimeZone.getTimeZone("GMT+0");
+ TimeZone.setDefault(timeZone);
+
+ yamlConfig.setScalarSerializer(Date.class, new DateSerializer());
+ String yaml = "!java.util.Date 1970-01-01 00:00:00";
+ YamlReader yamlReader = new YamlReader(yaml, yamlConfig);
+ Object object = yamlReader.read();
+ assertEquals(Date.class, object.getClass());
+ assertEquals(0, ((Date) object).getTime());
+
+ try {
+ yamlConfig.setScalarSerializer(null, new DateSerializer());
+ } catch (IllegalArgumentException e) {
+ assertEquals("type cannot be null.", e.getMessage());
+ }
+
+ try {
+ yamlConfig.setScalarSerializer(Date.class, null);
+ } catch (IllegalArgumentException e) {
+ assertEquals("serializer cannot be null.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSetPropertyElementType() throws YamlException {
+ yamlConfig.setPropertyElementType(TestObject.class, "objects", Date.class);
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("objects:" + LINE_SEPARATOR);
+ sb.append("- 2020-06-30 00:00:00" + LINE_SEPARATOR);
+
+ YamlReader yamlReader = new YamlReader(sb.toString(), yamlConfig);
+ TestObject testObject = yamlReader.read(TestObject.class);
+ assertEquals(Date.class, testObject.objects.get(0).getClass());
+
+ try {
+ yamlConfig.setPropertyElementType(null, "objects", Date.class);
+ } catch (IllegalArgumentException e) {
+ assertEquals("type cannot be null.", e.getMessage());
+ }
+
+ try {
+ yamlConfig.setPropertyElementType(TestObject.class, null, Date.class);
+ } catch (IllegalArgumentException e) {
+ assertEquals("propertyName cannot be null.", e.getMessage());
+ }
+
+ try {
+ yamlConfig.setPropertyElementType(TestObject.class, "objects", null);
+ } catch (IllegalArgumentException e) {
+ assertEquals("propertyType cannot be null.", e.getMessage());
+ }
+
+ try {
+ yamlConfig.setPropertyElementType(TestObject.class, "aaa", Object.class);
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("does not have a property named"));
+ }
+
+ try {
+ yamlConfig.setPropertyElementType(TestObject.class, "object", Date.class);
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("class must be a Collection or Map"));
+ }
+ }
+
+ @Test
+ public void testSetPropertyDefaultType() throws YamlException {
+ yamlConfig.setPropertyDefaultType(TestObject.class, "object", Date.class);
+
+ String yaml = "object: 2020-06-30 00:00:00";
+
+ YamlReader yamlReader = new YamlReader(yaml, yamlConfig);
+ TestObject testObject = yamlReader.read(TestObject.class);
+ assertEquals(Date.class, testObject.object.getClass());
+
+ try {
+ yamlConfig.setPropertyDefaultType(null, "object", Date.class);
+ } catch (IllegalArgumentException e) {
+ assertEquals("type cannot be null.", e.getMessage());
+ }
+
+ try {
+ yamlConfig.setPropertyDefaultType(TestObject.class, null, Date.class);
+ } catch (IllegalArgumentException e) {
+ assertEquals("propertyName cannot be null.", e.getMessage());
+ }
+
+ try {
+ yamlConfig.setPropertyDefaultType(TestObject.class, "object", null);
+ } catch (IllegalArgumentException e) {
+ assertEquals("defaultType cannot be null.", e.getMessage());
+ }
+
+ try {
+ yamlConfig.setPropertyDefaultType(TestObject.class, "aaa", Date.class);
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("does not have a property named"));
+ }
+ }
+
+ @Test
+ public void testSetBeanProperties() throws YamlException {
+ String yaml = "a: test";
+ YamlReader yamlReader = new YamlReader(yaml, yamlConfig);
+ TestObject testObject = yamlReader.read(TestObject.class);
+ assertEquals("test", testObject.a);
+
+ yamlConfig.setBeanProperties(false);
+ yamlReader = new YamlReader(yaml, yamlConfig);
+ try {
+ yamlReader.read(TestObject.class);
+ } catch (YamlReaderException e) {
+ assertTrue(e.getMessage().contains("Unable to find property"));
+ }
+ }
+
+ @Test
+ public void testSetPrivateConstructors() throws YamlException {
+ String yaml = "a: test";
+ YamlReader yamlReader = new YamlReader(yaml, yamlConfig);
+ TestObject testObject = yamlReader.read(TestObject.class);
+ assertEquals("test", testObject.a);
+
+ yamlConfig.setPrivateConstructors(false);
+ yamlReader = new YamlReader(yaml, yamlConfig);
+ try {
+ yamlReader.read(TestObject.class);
+ } catch (YamlReaderException e) {
+ assertTrue(e.getMessage().contains("Error creating object"));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testSetTagSuffix() throws YamlException {
+ StringWriter stringWriter = new StringWriter();
+ yamlConfig.setTagSuffix("tag");
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ Map map = new HashMap();
+ map.put("a", "111");
+ map.put("atag", "!222");
+ yamlWriter.write(map);
+ yamlWriter.close();
+
+ assertEquals("a: !222 111" + LINE_SEPARATOR, stringWriter.toString());
+
+ yamlConfig.setClassTag("!222", String.class);
+ YamlReader yamlReader = new YamlReader(stringWriter.toString(), yamlConfig);
+ Map result = yamlReader.read(Map.class);
+ assertEquals(map.toString(), result.toString());
+ }
+
+ @Test
+ public void testSetExplicitEndDocument() throws YamlException {
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("test");
+ yamlWriter.close();
+
+ assertEquals("test" + LINE_SEPARATOR, stringWriter.toString());
+
+ stringWriter = new StringWriter();
+ yamlConfig.writeConfig.setExplicitEndDocument(true);
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("test");
+ yamlWriter.close();
+ assertEquals("test" + LINE_SEPARATOR + "..." + LINE_SEPARATOR, stringWriter.toString());
+ }
+
+ @Test
+ public void testSetWriteRootTags() throws YamlException {
+ TestObject to = new TestObject();
+ to.a = "test";
+
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(to);
+ yamlWriter.close();
+
+ assertEquals(TESTOBJECT_TAG + LINE_SEPARATOR + "a: test" + LINE_SEPARATOR, stringWriter.toString());
+
+ yamlConfig.writeConfig.setWriteRootTags(false);
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(to);
+ yamlWriter.close();
+ assertEquals("a: test" + LINE_SEPARATOR, stringWriter.toString());
+ }
+
+ @Test
+ public void testSetWriteRootElementTags() throws YamlException {
+ TestObject to1 = new TestObject();
+ to1.a = "test";
+ List list = new ArrayList();
+ list.add(to1);
+
+ TestObject to2 = new TestObject();
+ to2.a = "test";
+ Map map = new HashMap();
+ map.put("test", to2);
+
+ yamlConfig.writeConfig.setWriteRootElementTags(true);
+ int indentSize = 3;
+ StringWriter stringWriter = new StringWriter();
+ yamlConfig.writeConfig.setIndentSize(indentSize);
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(list);
+ yamlWriter.write(map);
+ yamlWriter.close();
+
+ assertEquals("- " + TESTOBJECT_TAG + LINE_SEPARATOR + multipleSpaces(indentSize) + "a: test" + LINE_SEPARATOR
+ + "--- " + LINE_SEPARATOR + "test: " + TESTOBJECT_TAG + LINE_SEPARATOR + multipleSpaces(indentSize)
+ + "a: test" + LINE_SEPARATOR, stringWriter.toString());
+
+ yamlConfig.writeConfig.setWriteRootElementTags(false);
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(list);
+ yamlWriter.write(map);
+ yamlWriter.close();
+
+ assertEquals(
+ "-" + multipleSpaces(indentSize - 1) + "a: test" + LINE_SEPARATOR + "--- " + LINE_SEPARATOR + "test: "
+ + LINE_SEPARATOR + multipleSpaces(indentSize) + "a: test" + LINE_SEPARATOR,
+ stringWriter.toString());
+ }
+
+ @Test
+ public void testSetWriteDefaultValues() throws YamlException {
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ TestObject testObject = new TestObject();
+ yamlWriter.write(testObject);
+ yamlWriter.close();
+
+ assertEquals(TESTOBJECT_TAG + " {}" + LINE_SEPARATOR, stringWriter.toString());
+
+ yamlConfig.writeConfig.setWriteDefaultValues(true);
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(testObject);
+ yamlWriter.close();
+ assertFalse((TESTOBJECT_TAG + " {}" + LINE_SEPARATOR).equals(stringWriter.toString()));
+ assertTrue(stringWriter.toString().contains(TESTOBJECT_TAG + LINE_SEPARATOR));
+ assertTrue(stringWriter.toString().contains("a: " + LINE_SEPARATOR));
+
+ assertTrue(stringWriter.toString().contains("object: " + LINE_SEPARATOR));
+ }
+
+ @Test
+ public void testSetKeepBeanPropertyOrder() throws YamlException {
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ TestObject testObject = new TestObject();
+ testObject.name = "Jack";
+ testObject.age = 18;
+ yamlWriter.write(testObject);
+ yamlWriter.close();
+
+ assertEquals(TESTOBJECT_TAG + LINE_SEPARATOR + "name: Jack" + LINE_SEPARATOR + "age: 18" + LINE_SEPARATOR,
+ stringWriter.toString());
+
+ yamlConfig.writeConfig.setKeepBeanPropertyOrder(true);
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(testObject);
+ yamlWriter.close();
+ assertEquals(TESTOBJECT_TAG + LINE_SEPARATOR + "age: 18" + LINE_SEPARATOR + "name: Jack" + LINE_SEPARATOR,
+ stringWriter.toString());
+ }
+
+ @Test
+ public void testSetVersion() throws YamlException {
+
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("test");
+ yamlWriter.close();
+ assertEquals("test" + LINE_SEPARATOR, stringWriter.toString());
+
+ Version version = Version.V1_0;
+ yamlConfig.writeConfig.setVersion(version);
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("test");
+ yamlWriter.close();
+ assertEquals("%YAML 1.0" + LINE_SEPARATOR + "--- test" + LINE_SEPARATOR, stringWriter.toString());
+
+ version = Version.V1_1;
+ yamlConfig.writeConfig.setVersion(version);
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("test");
+ yamlWriter.close();
+ assertEquals("%YAML 1.1" + LINE_SEPARATOR + "--- test" + LINE_SEPARATOR, stringWriter.toString());
+ }
+
+ @Test
+ public void testSetTags() throws YamlException {
+ Map tags = new HashMap();
+ tags.put("!foo!", "bar");
+ yamlConfig.writeConfig.setTags(tags);
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("test");
+ yamlWriter.close();
+ assertEquals("%TAG !foo! bar" + LINE_SEPARATOR + "--- test" + LINE_SEPARATOR, stringWriter.toString());
+ }
+
+ @Test
+ public void testSetCanonical() throws YamlException {
+ int indentSize = 3;
+ yamlConfig.writeConfig.setIndentSize(indentSize);
+ yamlConfig.writeConfig.setCanonical(true);
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("test");
+ yamlWriter.close();
+ assertEquals("--- " + LINE_SEPARATOR + "!java.lang.String \"test\"" + LINE_SEPARATOR, stringWriter.toString());
+
+ List list = new ArrayList();
+ list.add("111");
+ list.add("222");
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(list);
+ yamlWriter.close();
+ assertEquals("--- " + LINE_SEPARATOR + "[" + LINE_SEPARATOR + multipleSpaces(indentSize)
+ + "!java.lang.String \"111\"," + LINE_SEPARATOR + multipleSpaces(indentSize)
+ + "!java.lang.String \"222\"" + LINE_SEPARATOR + "]" + LINE_SEPARATOR, stringWriter.toString());
+
+ Map map = new HashMap();
+ map.put("key", "value");
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(map);
+ yamlWriter.close();
+ assertEquals(
+ "--- " + LINE_SEPARATOR + "{" + LINE_SEPARATOR + multipleSpaces(indentSize)
+ + "? !java.lang.String \"key\"" + LINE_SEPARATOR + multipleSpaces(indentSize)
+ + ": !java.lang.String \"value\"" + LINE_SEPARATOR + "}" + LINE_SEPARATOR,
+ stringWriter.toString());
+ }
+
+ @Test
+ public void testSetIndentSize() throws YamlException {
+ int indentSize = 5;
+ List list = new ArrayList();
+ list.add(1);
+
+ StringWriter stringWriter = new StringWriter();
+ yamlConfig.writeConfig.setCanonical(true);
+ yamlConfig.writeConfig.setIndentSize(indentSize);
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(list);
+ yamlWriter.close();
+ assertEquals("--- " + LINE_SEPARATOR + "[" + LINE_SEPARATOR + multipleSpaces(indentSize)
+ + "!java.lang.Integer \"1\"" + LINE_SEPARATOR + "]" + LINE_SEPARATOR, stringWriter.toString());
+
+ try {
+ yamlConfig.writeConfig.setIndentSize(1);
+ } catch (Exception e) {
+ assertEquals("indentSize cannot be less than 2.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSetWrapColumn() throws YamlException {
+ String yaml = "aaaaaa aaaaa";
+ int indentSize = 3;
+ yamlConfig.writeConfig.setIndentSize(indentSize);
+ yamlConfig.writeConfig.setWrapColumn(5);
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(yaml);
+ yamlWriter.close();
+
+ assertEquals("aaaaaa" + LINE_SEPARATOR + multipleSpaces(indentSize) + "aaaaa" + LINE_SEPARATOR,
+ stringWriter.toString());
+
+ YamlReader yamlReader = new YamlReader(stringWriter.toString());
+ assertEquals(yaml, yamlReader.read(String.class));
+
+ try {
+ yamlConfig.writeConfig.setWrapColumn(3);
+ } catch (IllegalArgumentException e) {
+ assertEquals("wrapColumn must be greater than 4.", e.getMessage());
+ }
+
+ }
+
+ @Test
+ public void testSetUseVerbatimTags() throws YamlException {
+ List list = new LinkedList();
+ list.add(1);
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(list);
+ yamlWriter.close();
+
+ assertEquals("!java.util.LinkedList" + LINE_SEPARATOR + "- 1" + LINE_SEPARATOR, stringWriter.toString());
+
+ stringWriter = new StringWriter();
+ yamlConfig.writeConfig.setUseVerbatimTags(true);
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(list);
+ yamlWriter.close();
+
+ assertEquals("!" + LINE_SEPARATOR + "- 1" + LINE_SEPARATOR, stringWriter.toString());
+ }
+
+ @Test
+ public void testSetQuoteChar() throws YamlException {
+ TestObject testObject = new TestObject();
+ testObject.age = 18;
+ testObject.name = "xxx";
+ StringWriter stringWriter = new StringWriter();
+ yamlConfig.writeConfig.setWriteRootTags(false);
+ yamlConfig.writeConfig.setQuoteChar(Quote.NONE);
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(testObject);
+ yamlWriter.close();
+ assertEquals("name: xxx" + LINE_SEPARATOR + "age: 18" + LINE_SEPARATOR, stringWriter.toString());
+
+ stringWriter = new StringWriter();
+ yamlConfig.writeConfig.setQuoteChar(Quote.SINGLE);
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(testObject);
+ yamlWriter.close();
+ assertEquals("\'name\': \'xxx\'" + LINE_SEPARATOR + "\'age\': \'18\'" + LINE_SEPARATOR,
+ stringWriter.toString());
+
+ stringWriter = new StringWriter();
+ yamlConfig.writeConfig.setQuoteChar(Quote.DOUBLE);
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(testObject);
+ yamlWriter.close();
+ assertEquals("\"name\": \"xxx\"" + LINE_SEPARATOR + "\"age\": \"18\"" + LINE_SEPARATOR,
+ stringWriter.toString());
+
+ stringWriter = new StringWriter();
+ yamlConfig.writeConfig.setQuoteChar(Quote.LITERAL);
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("test\ntest");
+ yamlWriter.close();
+ assertEquals("|-" + LINE_SEPARATOR + " test" + LINE_SEPARATOR + " test" + LINE_SEPARATOR,
+ stringWriter.toString());
+
+ stringWriter = new StringWriter();
+ yamlConfig.writeConfig.setQuoteChar(Quote.FOLDED);
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("test\ntest");
+ yamlWriter.close();
+ assertEquals(">-" + LINE_SEPARATOR + " test" + LINE_SEPARATOR + LINE_SEPARATOR + " test" + LINE_SEPARATOR,
+ stringWriter.toString());
+ }
+
+ @Test
+ public void testSetDefaultVersion() throws YamlException {
+ String yaml = "!!str test";
+ yamlConfig.readConfig.setDefaultVersion(Version.V1_1);
+ YamlReader yamlReader = new YamlReader(yaml, yamlConfig);
+ assertEquals("test", yamlReader.read(String.class));
+
+ try {
+ yamlConfig.readConfig.setDefaultVersion(null);
+ } catch (IllegalArgumentException e) {
+ assertEquals("defaultVersion cannot be null.", e.getMessage());
+ }
+
+ }
+
+ @Test
+ public void testConstructorParameters() throws YamlException {
+ yamlConfig.readConfig.setConstructorParameters(TestObject.class, new Class[] { String.class },
+ new String[] { "a" });
+ YamlReader yamlReader = new YamlReader("a: test", yamlConfig);
+ assertEquals("test", yamlReader.read(TestObject.class).a);
+
+ try {
+ yamlConfig.readConfig.setConstructorParameters(null, new Class[] { String.class }, new String[] { "a" });
+ } catch (IllegalArgumentException e) {
+ assertEquals("type cannot be null.", e.getMessage());
+ }
+
+ try {
+ yamlConfig.readConfig.setConstructorParameters(TestObject.class, null, new String[] { "a" });
+ } catch (IllegalArgumentException e) {
+ assertEquals("parameterTypes cannot be null.", e.getMessage());
+ }
+
+ try {
+ yamlConfig.readConfig.setConstructorParameters(TestObject.class, new Class[] { String.class }, null);
+ } catch (IllegalArgumentException e) {
+ assertEquals("parameterNames cannot be null.", e.getMessage());
+ }
+
+ try {
+ yamlConfig.readConfig.setConstructorParameters(TestObject.class, new Class[] { String.class, String.class },
+ new String[] { "a", "name" });
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().startsWith("Unable to find constructor: "));
+ }
+
+ }
+
+ @Test
+ public void testSetFlowStyle() throws YamlException {
+ List list = new ArrayList();
+ list.add("111");
+ list.add("222");
+ list.add("333");
+
+ Map map = new HashMap();
+ map.put("key", "value");
+
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(list);
+ yamlWriter.close();
+
+ assertEquals("- 111" + LINE_SEPARATOR + "- 222" + LINE_SEPARATOR + "- 333" + LINE_SEPARATOR,
+ stringWriter.toString());
+
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(map);
+ yamlWriter.close();
+ assertEquals("key: value" + LINE_SEPARATOR, stringWriter.toString());
+
+ yamlConfig.writeConfig.setFlowStyle(true);
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(list);
+ yamlWriter.close();
+ assertEquals("[111, 222, 333]" + LINE_SEPARATOR, stringWriter.toString());
+
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(map);
+ yamlWriter.close();
+ assertEquals("{key: value}" + LINE_SEPARATOR, stringWriter.toString());
+ }
+
+ @Test
+ public void testSetPrettyFlow() throws YamlException {
+ Map map = new LinkedHashMap();
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+
+ List list = new ArrayList();
+ list.add("111");
+ list.add("222");
+ list.add("333");
+
+ yamlConfig.writeConfig.setWriteRootTags(false);
+ yamlConfig.writeConfig.setFlowStyle(true);
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(map);
+ yamlWriter.close();
+ assertEquals("{key1: value1, key2: value2}" + LINE_SEPARATOR, stringWriter.toString());
+
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(list);
+ yamlWriter.close();
+ assertEquals("[111, 222, 333]" + LINE_SEPARATOR, stringWriter.toString());
+
+ yamlConfig.writeConfig.setPrettyFlow(true);
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(map);
+ yamlWriter.close();
+ assertEquals("{" + LINE_SEPARATOR + " key1: value1," + LINE_SEPARATOR + " key2: value2" + LINE_SEPARATOR
+ + "}" + LINE_SEPARATOR, stringWriter.toString());
+
+ stringWriter = new StringWriter();
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(list);
+ yamlWriter.close();
+ assertEquals("[" + LINE_SEPARATOR + " 111," + LINE_SEPARATOR + " 222," + LINE_SEPARATOR + " 333"
+ + LINE_SEPARATOR + "]" + LINE_SEPARATOR, stringWriter.toString());
+ }
+
+ private String multipleSpaces(int indentSize) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < indentSize; i++) {
+ sb.append(" ");
+ }
+ return sb.toString();
+ }
+
+ static class TestObject {
+ private String a;
+ public int age;
+ public String name;
+ public Object object;
+ public List objects;
+
+ private TestObject() {
+ }
+
+ public TestObject(String a) {
+ this.a = a;
+ }
+
+ public String getA() {
+ return a;
+ }
+
+ public void setA(String a) {
+ this.a = a;
+ }
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/YamlReaderTest.java b/test/com/esotericsoftware/yamlbeans/YamlReaderTest.java
index 6b94992..1af7479 100644
--- a/test/com/esotericsoftware/yamlbeans/YamlReaderTest.java
+++ b/test/com/esotericsoftware/yamlbeans/YamlReaderTest.java
@@ -16,9 +16,16 @@
package com.esotericsoftware.yamlbeans;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+
+import com.esotericsoftware.yamlbeans.YamlReader.YamlReaderException;
+
import junit.framework.TestCase;
/** @author Nathan Sweet */
@@ -28,7 +35,7 @@ public void testSimpleFields () throws Exception {
"stringValue: moo\ufec9moo\n" + //
"intValue: !!int 123\n" + //
"floatValue: 0.3\n" + //
- "doubleValue: 0.0002\n" + //
+ "doubleValue: 0.0002 # comment\n" + //
"longValue: 999999\n" + //
"shortValue: 125\n" + //
"charValue: j\n" + //
@@ -155,11 +162,30 @@ public void testCyclicReferences () throws Exception {
assertTrue(root.right.right == null);
}
+ public void testReaderMaintainsOrderWhenReadingMap() throws Exception {
+ YamlReader reader = new YamlReader("a: b\nkey1: value1\nc: d\n");
+ Map map = (Map)reader.read();
+ Iterator entrySetIterator = map.entrySet().iterator();
+
+ Map.Entry mapEntry = (Map.Entry)entrySetIterator.next();
+ assertEquals(mapEntry.getKey(), "a");
+ assertEquals(mapEntry.getValue(), "b");
+
+ mapEntry = (Map.Entry)entrySetIterator.next();
+ assertEquals(mapEntry.getKey(), "key1");
+ assertEquals(mapEntry.getValue(), "value1");
+
+ mapEntry = (Map.Entry)entrySetIterator.next();
+ assertEquals(mapEntry.getKey(), "c");
+ assertEquals(mapEntry.getValue(), "d");
+ }
+
private Test read (String yaml) throws Exception {
if (true) {
System.out.println(yaml);
System.out.println("===");
- System.out.println(new YamlReader(yaml).read(null));
+ Object obj = new YamlReader(yaml).read(null);
+ System.out.println(obj);
System.out.println();
System.out.println();
}
@@ -292,4 +318,499 @@ public void setZ (int z) {
this.z = z;
}
}
+
+ static class ACD {
+ public int a, c, d = 4;
+ }
+
+ public void testIgnoreUnknownProperties () {
+ String input = "a: 1\nb: 2\nc: 3";
+ YamlConfig config = new YamlConfig();
+ try {
+ new YamlReader(input, config).read(ACD.class);
+ fail("Unknown properties were not supposed to be allowed.");
+ } catch (YamlException e) {
+ }
+
+ config.readConfig.setIgnoreUnknownProperties(true);
+ try {
+ ACD pojo = new YamlReader(input, config).read(ACD.class);
+ assertEquals(1, pojo.a);
+ assertEquals(3, pojo.c);
+ assertEquals(4, pojo.d);
+ } catch (YamlException e) {
+ fail("Unknown properties were supposed to be allowed.");
+ }
+ }
+
+ public void testIgnoreUnknownPropertiesSprcialType() throws Exception {
+ String input = "a: 1\nb: 2\nc: 3\n" + "sequence: \n" + " - 1\n" + " - 2\n" + "mapping: \n key: value\n"
+ + "stream: {a: 7}\ndocument: ---\na: 9\n...\n";
+
+ YamlConfig config = new YamlConfig();
+ config.readConfig.setIgnoreUnknownProperties(true);
+ try {
+ ACD pojo = new YamlReader(input, config).read(ACD.class);
+ assertEquals(1, pojo.a);
+ assertEquals(3, pojo.c);
+ assertEquals(4, pojo.d);
+ } catch (YamlException e) {
+ fail("Unknown properties were supposed to be allowed.");
+ }
+ }
+
+ public void testDuplicateKeysAreNotAllowedIfAllowDuplicateIsSetSo () {
+ String inputWithDuplicates = "a: 1\na: 2\nc: 3";
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.setAllowDuplicates(false);
+ YamlReader yamlReader = new YamlReader(inputWithDuplicates, yamlConfig);
+ try {
+ yamlReader.read();
+ fail("Duplicates should not have been allowed.");
+ } catch (YamlException e) {
+ }
+
+ String inputWithoutDuplicates = "a: 1\nb: 2\nc: 3";
+ YamlReader yamlReader1 = new YamlReader(inputWithoutDuplicates, yamlConfig);
+ try {
+ yamlReader1.read();
+ } catch (YamlException e) {
+ fail("Duplicates should have been allowed.");
+ }
+ }
+
+ public void testDuplicateKeysAreAllowedIfAllowDuplicateIsSetSo () {
+ String inputWithDuplicates = "a: 1\na: 2\nc: 3";
+ YamlReader yamlReader = new YamlReader(inputWithDuplicates);
+ try {
+ yamlReader.read();
+ } catch (YamlException e) {
+ e.printStackTrace();
+ fail("Duplicates should have been allowed.");
+ }
+
+ String inputWithoutDuplicates = "a: 1\nb: 2\nc: 3";
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.setAllowDuplicates(false);
+ YamlReader yamlReader1 = new YamlReader(inputWithoutDuplicates, yamlConfig);
+ try {
+ yamlReader1.read();
+ } catch (YamlException e) {
+ e.printStackTrace();
+ fail("Duplicates should have been allowed.");
+ }
+ }
+
+ private static class TypeTagIgnoringReader extends YamlReader {
+
+ public TypeTagIgnoringReader(String yaml) {
+ super(yaml);
+ }
+
+ @Override
+ protected Class> findTagClass(String tag, ClassLoader classLoader) {
+ // Ignore all tags.
+ return null;
+ }
+
+ }
+
+ public void testIgnoreTypeTagsTopLevel () throws YamlException {
+ // We are parsing this document that was output by another program using YamlBeans, that includes
+ // a type tag for a class that we don't have on our classpath.
+ String input = "!com.example.not.on.classpath.Fish\n" + //
+ "species: Walleye\n" + //
+ "weight: 24";
+
+ try {
+ new YamlReader(input).read(Map.class);
+ fail("A type tag with an unknown class fails to parse, even if we ask for it as a simple Map.");
+ } catch (YamlException e) {
+ // Expected behavior.
+ }
+
+ // If we ignore type tags, the type tag in the document does not override our request for a Map.
+ Map, ?> map = new TypeTagIgnoringReader(input).read(Map.class);
+ assertEquals("Walleye", map.get("species"));
+ }
+
+ static class Lake {
+ public String name;
+ public List fish;
+ }
+
+ static class Fish {
+ public String species;
+ public int weight;
+ }
+
+ public void testIgnoreTypeTagsEmbedded () throws YamlException {
+ // We are parsing this document that was output by another program using YamlBeans, that includes
+ // type tags for multiple classes that we don't have on our classpath. One of those type tags is
+ // embedded within the document, not at the top level.
+ String input = "!com.example.not.on.classpath.Lake\n" + //
+ "name: Superior\n" + //
+ "fish:\n" +
+ " - !com.example.not.on.classpath.Fish\n" + //
+ " species: Walleye\n" + //
+ " weight: 24";
+
+ try {
+ new YamlReader(input).read(Lake.class);
+ fail("A type tag with an unknown class fails to parse, even if we ask for it as a known class.");
+ } catch (YamlException e) {
+ // Expected behavior.
+ }
+
+ // If we ignore type tags, we can specify the return type & embedded types instead of failing to parse.
+ Lake lake = new TypeTagIgnoringReader(input).read(Lake.class);
+ assertEquals("Superior", lake.name);
+ assertEquals(1, lake.fish.size());
+ assertEquals("Walleye", lake.fish.get(0).species);
+ }
+
+ /**
+ * issue #105
+ *
+ * @throws YamlException
+ */
+ public void testGuessNumberTypes() throws YamlException {
+
+ long invoice = 3484312312313131l;
+ Map map = new HashMap();
+ map.put("invoice", invoice);
+ map.put("date", "2001-01-23");
+
+ YamlConfig config = new YamlConfig();
+ config.readConfig.setGuessNumberTypes(true);
+ StringWriter sw = new StringWriter();
+ YamlWriter writer = new YamlWriter(sw, config);
+ writer.write(map);
+ writer.close();
+ YamlReader reader = new YamlReader(sw.toString(), config);
+ Map result = (Map) reader.read();
+ long invoiceValue = (Long) result.get("invoice");
+ assertEquals(invoice, invoiceValue);
+
+ Double money = 123.456;
+ map.put("money", money);
+
+ writer = new YamlWriter(sw, config);
+ writer.write(map);
+ writer.close();
+
+ reader = new YamlReader(sw.toString(), config);
+ result = (Map) reader.read();
+ double moneyValue = (Double) result.get("money");
+ assertEquals(money, moneyValue);
+ }
+
+ public void testGuessOctNumberAndHexNumber() throws YamlException {
+
+ // Octal number string
+ String str = "{octNumber: 011}";
+ YamlConfig config = new YamlConfig();
+ config.readConfig.guessNumberTypes = true;
+ YamlReader reader = new YamlReader(str, config);
+ int octNumber = ((Map) reader.read()).get("octNumber").intValue();
+ assertEquals(9, octNumber);
+
+ // Hex number string
+ str = "{hexNumber: 0x11}";
+ reader = new YamlReader(str, config);
+ int hexNumber = ((Map) reader.read()).get("hexNumber").intValue();
+ assertEquals(17, hexNumber);
+ }
+
+ /**
+ * issue #34
+ *
+ * @throws YamlException
+ */
+ public void testWhiteSpaceCharacters() throws YamlException {
+
+ String stringWithSpace = "test test";
+ YamlReader reader = new YamlReader(stringWithSpace);
+ assertEquals(stringWithSpace, reader.read(String.class));
+
+ String stringWithTab = "test\ttesttest";
+ reader = new YamlReader(stringWithTab);
+ assertEquals(stringWithTab, reader.read(String.class));
+
+ String stringWithSpaceAndTab = "test test\ttest \ttest";
+ reader = new YamlReader(stringWithSpaceAndTab);
+ assertEquals(stringWithSpaceAndTab, reader.read(String.class));
+ }
+
+ /**
+ * Test multiple documents, the document is a scalar, followed by "---" or
+ * "...", the test read is normal.
+ *
+ * @throws YamlException
+ */
+ public void testReadMultiTpyeDocuments() throws YamlException {
+ String yaml = "scalar\n---\nkey: value\n---\nscalar\n...\n";
+ YamlReader reader = new YamlReader(yaml);
+ String str = reader.read(String.class);
+ assertEquals("scalar", str);
+
+ Map map = (Map) reader.read(HashMap.class);
+ assertEquals("value", map.get("key"));
+
+ str = reader.read(String.class);
+ assertEquals("scalar", str);
+ }
+
+ public void testRead() throws YamlException {
+ String yaml = "test";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals("test", reader.read(String.class));
+ assertEquals(null, reader.read());
+ assertEquals(null, reader.read());
+ }
+
+ public void testReadAll() throws YamlException {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("- 1").append("\n");
+ sb.append("- 2").append("\n");
+ sb.append("- 3").append("\n");
+ sb.append("---\n").append("key: value").append("\n");
+ sb.append("--- !com.esotericsoftware.yamlbeans.YamlReaderTest$Test\n");
+ sb.append("stringValue: test\n");
+ YamlReader reader = new YamlReader(sb.toString());
+ Iterator iterator = reader.readAll(Object.class);
+ List list = new ArrayList();
+ while (iterator.hasNext()) {
+ list.add(iterator.next());
+ }
+ assertEquals(3, list.size());
+ assertEquals("test", ((Test) list.get(2)).stringValue);
+ }
+
+ public void testReadAllCallingNextExpectThrowsRuntimeException() {
+ String yaml = "\ttest";
+ YamlReader reader = new YamlReader(yaml);
+ Iterator iterator = reader.readAll(Object.class);
+ try {
+ iterator.next();
+ fail();
+ } catch (RuntimeException e) {
+ }
+ }
+
+ public void testReadAllCallingRemoveExpectThrowsUnsupportedOperationException() {
+ String yaml = "test";
+ YamlReader reader = new YamlReader(yaml);
+ Iterator iterator = reader.readAll(Object.class);
+ try {
+ iterator.remove();
+ fail();
+ } catch (Exception e) {
+ }
+ }
+
+ public void testGetAnchor() throws YamlException {
+ String yaml = "&1 test\n---\naaa: &2 111\nbbb: &1 222";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals(null, reader.get("1"));
+ reader.read();
+ assertEquals("test", reader.get("1"));
+
+ reader.read();
+ assertEquals("222", reader.get("1"));
+ assertEquals("111", reader.get("2"));
+ }
+
+ public void testGetAnchorsUseGuessNumberTypes() throws YamlException {
+ String yaml = "number: &1 123";
+ YamlReader reader = new YamlReader(yaml);
+ reader.read();
+ assertEquals("123", reader.get("1"));
+
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.readConfig.guessNumberTypes = true;
+ reader = new YamlReader(yaml, yamlConfig);
+ reader.read();
+ assertEquals(123, ((Long) reader.get("1")).intValue());
+ }
+
+ public void testAnchorAndAlias() throws YamlException {
+ String yaml = "key: &1 value\nkey1: *1\n---\nkey: *1";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals("value", ((Map) reader.read()).get("key1"));
+ assertEquals("value", reader.get("1"));
+
+ try {
+ reader.read();
+ } catch (YamlReaderException e) {
+ assertTrue(e.getMessage().contains("Unknown anchor: "));
+ }
+ }
+
+ public void testReadExpectExpectThrowsParserException() {
+ String yaml = "[1,2,3";
+ YamlReader reader = new YamlReader(yaml);
+ try {
+ reader.read();
+ fail("Expect to throw ParserException.");
+ } catch (YamlException e) {
+ }
+ }
+
+ public void testYamlConfigReadConfigClassLoader() throws YamlException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("--- !com.esotericsoftware.yamlbeans.YamlReaderTest$Test\n");
+ sb.append("stringValue: test\n");
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.readConfig.classLoader = this.getClass().getClassLoader();
+ YamlReader reader = new YamlReader(sb.toString(), yamlConfig);
+ assertEquals("test", reader.read(Test.class).stringValue);
+ }
+
+ public void testYamlConfigReadConfigClassTags() throws YamlException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("--- !com.esotericsoftware.yamlbeans.YamlReaderTest$Test\n");
+ sb.append("stringValue: test\n");
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.readConfig.setClassTags(false);
+ yamlConfig.setPropertyDefaultType(Test.class, "stringValue", String.class);
+ YamlReader reader = new YamlReader(sb.toString(), yamlConfig);
+ assertEquals("test", reader.read(Test.class).stringValue);
+ }
+
+ public void testReadScalarTypeIsNull() throws YamlException {
+ String yaml = "key: ";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals(null, ((Map) reader.read()).get("key"));
+ }
+
+ public void testReadScalarTypeIsString() throws YamlException {
+ String yaml = "String";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals("String", reader.read(String.class));
+ }
+
+ public void testReadScalarTypeIsInteger() throws YamlException {
+ String yaml = "123";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals(123, (int) reader.read(Integer.class));
+
+ reader = new YamlReader(yaml);
+ assertEquals(123, (int) reader.read(int.class));
+ }
+
+ public void testReadScalarTypeIsBoolean() throws YamlException {
+ String yaml = "true";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals(true, (boolean) reader.read(Boolean.class));
+
+ reader = new YamlReader(yaml);
+ assertEquals(true, (boolean) reader.read(boolean.class));
+ }
+
+ public void testReadScalarTypeIsFloat() throws YamlException {
+ String yaml = "1.23";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals(1.23f, reader.read(Float.class));
+
+ reader = new YamlReader(yaml);
+ assertEquals(1.23f, reader.read(float.class));
+ }
+
+ public void testReadScalarTypeIsDouble() throws YamlException {
+ String yaml = "1.23";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals(1.23, reader.read(Double.class));
+
+ reader = new YamlReader(yaml);
+ assertEquals(1.23, reader.read(double.class));
+ }
+
+ public void testReadScalarTypeIsLong() throws YamlException {
+ String yaml = "100";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals(100, (long) reader.read(Long.class));
+
+ reader = new YamlReader(yaml);
+ assertEquals(100, (long) reader.read(long.class));
+ }
+
+ public void testReadScalarTypeIsShort() throws YamlException {
+ String yaml = "100";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals(100, (short) reader.read(Short.class));
+
+ reader = new YamlReader(yaml);
+ assertEquals(100, (short) reader.read(short.class));
+ }
+
+ public void testReadScalarTypeIsCharacter() throws YamlException {
+ String yaml = "A";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals('A', (char) reader.read(Character.class));
+
+ reader = new YamlReader(yaml);
+ assertEquals('A', (char) reader.read(char.class));
+ }
+
+ public void testReadScalarTypeIsByte() throws YamlException {
+ String yaml = "1";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals(1, (byte) reader.read(Byte.class));
+
+ reader = new YamlReader(yaml);
+ assertEquals(1, (byte) reader.read(byte.class));
+ }
+
+ public void testReadEnumExpectThrowsYamlReaderException() throws YamlException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("--- !com.esotericsoftware.yamlbeans.YamlReaderTest$Test\n");
+ sb.append("testEnum: d\n");
+ YamlReader reader = new YamlReader(sb.toString());
+ try {
+ reader.read();
+ fail("Unable to find enum value");
+ } catch (YamlReaderException e) {
+ }
+ }
+
+ public void testReadExplicitKey() throws YamlException {
+ String yaml = "? key: value";
+ YamlReader reader = new YamlReader(yaml);
+ assertEquals("value", ((Map) reader.read()).get("key"));
+ }
+
+ public void testReadYamlConfigTagSuffix() throws YamlException {
+ String yaml = "key: !!str 123456";
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.tagSuffix = "-test";
+ YamlReader reader = new YamlReader(yaml, yamlConfig);
+ Map map = (Map) reader.read();
+ assertEquals("tag:yaml.org,2002:str", map.get("key-test"));
+
+ yaml = "info: !!map\n !!str key: !!str 123456";
+ reader = new YamlReader(yaml, yamlConfig);
+ map = (Map) reader.read();
+ assertEquals("tag:yaml.org,2002:map", map.get("info-test"));
+ }
+
+ public void testReadYamlConfigAllowDuplicates() throws YamlException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("--- !com.esotericsoftware.yamlbeans.YamlReaderTest$Test\n");
+ sb.append("stringValue: test\n");
+ sb.append("stringValue: test\n");
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.allowDuplicates = true;
+ YamlReader reader = new YamlReader(sb.toString(), yamlConfig);
+ reader.read();
+
+ yamlConfig.allowDuplicates = false;
+ reader = new YamlReader(sb.toString(), yamlConfig);
+ try {
+ reader.read();
+ fail("must be throws YamlReaderException");
+ } catch (YamlReaderException e) {
+ }
+ }
}
diff --git a/test/com/esotericsoftware/yamlbeans/YamlWriterTest.java b/test/com/esotericsoftware/yamlbeans/YamlWriterTest.java
index fdabc9e..9bf6d91 100644
--- a/test/com/esotericsoftware/yamlbeans/YamlWriterTest.java
+++ b/test/com/esotericsoftware/yamlbeans/YamlWriterTest.java
@@ -24,6 +24,7 @@
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -32,7 +33,12 @@
/** @author Nathan Sweet */
public class YamlWriterTest extends TestCase {
+
+ private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
public void testPrivateFields () throws Exception {
+ YamlWriter yamlWriter = new com.esotericsoftware.yamlbeans.YamlWriter(new java.io.OutputStreamWriter(System.out));
+
ArrayList list = new ArrayList();
list.add("abc");
list.add("123");
@@ -212,14 +218,14 @@ public void testExplicitDocumentEnd () throws Exception {
YamlWriter writer = new YamlWriter(buffer, config);
writer.write("test");
writer.close();
- assertEquals("test\n...\n", buffer.toString());
+ assertEquals("test" + LINE_SEPARATOR + "..." + LINE_SEPARATOR, buffer.toString());
buffer = new StringWriter();
writer = new YamlWriter(buffer, config);
writer.write("test");
writer.write("test");
writer.close();
- assertEquals("test\n...\n--- test\n...\n", buffer.toString());
+ assertEquals("test" + LINE_SEPARATOR + "..." + LINE_SEPARATOR + "--- test" + LINE_SEPARATOR + "..." + LINE_SEPARATOR, buffer.toString());
}
void checkWriterOutput (String example, String expected) throws Exception {
@@ -231,14 +237,14 @@ void checkWriterOutput (String example, String expected) throws Exception {
}
public void testSingleQuotesDoubling () throws Exception {
- checkWriterOutput("abc", "abc\n");
- checkWriterOutput("abc def", "abc def\n");
+ checkWriterOutput("abc", "abc" + LINE_SEPARATOR);
+ checkWriterOutput("abc def", "abc def" + LINE_SEPARATOR);
// single quotes around output as soon as we have a colon in the input
- checkWriterOutput("abc: def", "'abc: def'\n");
- checkWriterOutput("abc: def'ghi", "'abc: def''ghi'\n");
- checkWriterOutput("abc: def 'ghi", "'abc: def ''ghi'\n");
+ checkWriterOutput("abc: def", "'abc: def'" + LINE_SEPARATOR);
+ checkWriterOutput("abc: def'ghi", "'abc: def''ghi'" + LINE_SEPARATOR);
+ checkWriterOutput("abc: def 'ghi", "'abc: def ''ghi'" + LINE_SEPARATOR);
// That was the initial bug:
- checkWriterOutput("A: 'X'", "'A: ''X'''\n");
+ checkWriterOutput("A: 'X'", "'A: ''X'''" + LINE_SEPARATOR);
}
public void testObjectField () throws Exception {
@@ -304,6 +310,23 @@ public String write (File file) throws YamlException {
assertEquals(object.file, roundTrip.file);
}
+ public void testSetAlias() throws YamlException {
+ Map map = new LinkedHashMap();
+ Test test = new Test();
+ test.stringValue = "test";
+ map.put("key1", test);
+ map.put("key2", test);
+
+ StringWriter sw = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(sw);
+ yamlWriter.setAlias(test, "t");
+ yamlWriter.write(map);
+ yamlWriter.close();
+ assertEquals("!java.util.LinkedHashMap" + LINE_SEPARATOR
+ + "key1: &t !com.esotericsoftware.yamlbeans.YamlWriterTest$Test" + LINE_SEPARATOR
+ + " stringValue: test" + LINE_SEPARATOR + "key2: *t" + LINE_SEPARATOR, sw.toString());
+ }
+
private Object roundTrip (Object object) throws Exception {
return roundTrip(object, null, new YamlConfig());
}
diff --git a/test/com/esotericsoftware/yamlbeans/document/YamlDocumentTest.java b/test/com/esotericsoftware/yamlbeans/document/YamlDocumentTest.java
new file mode 100644
index 0000000..c2b6523
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/document/YamlDocumentTest.java
@@ -0,0 +1,292 @@
+package com.esotericsoftware.yamlbeans.document;
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.esotericsoftware.yamlbeans.Version;
+import com.esotericsoftware.yamlbeans.YamlConfig;
+import com.esotericsoftware.yamlbeans.YamlConfig.WriteClassName;
+import com.esotericsoftware.yamlbeans.YamlException;
+import com.esotericsoftware.yamlbeans.YamlWriter;
+
+import junit.framework.TestCase;
+
+public class YamlDocumentTest extends TestCase {
+ protected void setUp () throws Exception {
+ System.setProperty("line.separator", "\n");
+ }
+
+ @Test
+ public void testThatTaggedDocumentIsCopied() throws Exception {
+ testEquals("--- !someTag\nscalar: value\n");
+ }
+
+ @Test
+ public void testThatScalarValueIsCopied() throws Exception {
+ testEquals("scalar: value\n");
+ }
+
+ @Test
+ public void testThatTaggedScalarValueIsCopied() throws Exception {
+ testEquals("scalar: value !someTag\n");
+ }
+
+ @Test
+ public void testThatAnchoredScalarValueIsCopied() throws Exception {
+ testEquals("scalar: &anchor value\n");
+ }
+
+ @Test
+ public void testThatAliasedScalarValueIsCopied() throws Exception {
+ testEquals("scalar: *alias\n");
+ }
+
+ @Test
+ public void testThatSequenceValueIsCopied() throws Exception {
+ testEquals("- scalar1: value\n- scalar2: value\n");
+ }
+
+ @Test
+ public void testThatTaggedSequenceValueIsCopied() throws Exception {
+ testEquals("- scalar1: value !someTag1\n- scalar2: value !someTag2\n");
+ }
+
+ @Test
+ public void testThatAnchoredSequenceValueIsCopied() throws Exception {
+ testEquals("sequence: &anchor\n- scalar1: value\n- scalar2: value\n");
+ }
+
+ @Test
+ public void testThatAliasedSequenceValueIsCopied() throws Exception {
+ testEquals("sequence: *alias\n");
+ }
+
+ @Test
+ public void testThatMappingValueIsCopied() throws Exception {
+ testEquals("mapping: \n scalar1: value\n scalar2: value\n");
+ }
+
+ @Test
+ public void testThatTaggedMappingValueIsCopied() throws Exception {
+ testEquals("mapping: !someTag1\n scalar1: value\n scalar2: value !someTag2\n");
+ }
+
+
+ @Test
+ public void testThatAnchoredMappingValueIsCopied() throws Exception {
+ testEquals("mapping: &anchor\n scalar1: value\n scalar2: value\n");
+ }
+
+ @Test
+ public void testThatAliasedMappingValueIsCopied() throws Exception {
+ testEquals("mapping: *alias\n");
+ }
+
+ @Test
+ public void testThatMappingEntryIsChanged() throws YamlException {
+ YamlDocument yaml = readDocument("scalar: value\n");
+ yaml.setEntry("scalar", 123);
+ String actual = writeDocument(yaml);
+ assertEquals("scalar: 123\n", actual);
+ }
+
+ @Test
+ public void testThatMappingEntryIsAdded() throws YamlException {
+ YamlDocument yaml = readDocument("scalar: value\n");
+ yaml.setEntry("scalar2", 123);
+ String actual = writeDocument(yaml);
+ assertEquals("scalar: value\nscalar2: 123\n", actual);
+ }
+
+ @Test
+ public void testThatMappingEntryIsRemoved() throws YamlException {
+ YamlDocument yaml = readDocument("scalar: value\nscalar2: 123\n");
+ yaml.deleteEntry("scalar2");
+ String actual = writeDocument(yaml);
+ assertEquals("scalar: value\n", actual);
+ }
+
+ @Test
+ public void testThatSequenceItemIsChanged() throws YamlException {
+ YamlDocument yaml = readDocument("- value\n");
+ yaml.setElement(0, 123);
+ String actual = writeDocument(yaml);
+ assertEquals("- 123\n", actual);
+ }
+
+ @Test
+ public void testThatSequenceItemIsAdded() throws YamlException {
+ YamlDocument yaml = readDocument("- value\n");
+ yaml.addElement(123);
+ String actual = writeDocument(yaml);
+ assertEquals("- value\n- 123\n", actual);
+ }
+
+ @Test
+ public void testThatSequenceItemIsRemoved() throws YamlException {
+ YamlDocument yaml = readDocument("- value\n- 123\n");
+ yaml.deleteElement(0);
+ String actual = writeDocument(yaml);
+ assertEquals("- 123\n", actual);
+ }
+
+ @Test
+ public void testYamlSequenceIterator() throws YamlException {
+ YamlDocument yaml = readDocument("- 111\n- 222\n");
+ @SuppressWarnings("unchecked")
+ Iterator iterator = yaml.iterator();
+ assertEquals(true, iterator.hasNext());
+ YamlScalar yamlScalar = iterator.next();
+ assertEquals("111", yamlScalar.getValue());
+ assertEquals(true, iterator.hasNext());
+ yamlScalar = iterator.next();
+ assertEquals("222", yamlScalar.getValue());
+ assertEquals(false, iterator.hasNext());
+ try {
+ iterator.next();
+ fail("Already read to the end.");
+ } catch (Exception e) {
+ }
+ }
+
+ @Test
+ public void testYamlMappingIterator() throws YamlException {
+ YamlDocument yaml = readDocument("name: Andi\nage: 18\n");
+ @SuppressWarnings("unchecked")
+ Iterator iterator = yaml.iterator();
+ assertEquals(true, iterator.hasNext());
+ YamlEntry yamlEntry = iterator.next();
+ assertEquals("Andi", ((YamlScalar) yamlEntry.getValue()).getValue());
+ assertEquals(true, iterator.hasNext());
+ yamlEntry = iterator.next();
+ assertEquals("18", ((YamlScalar) yamlEntry.getValue()).getValue());
+ assertEquals(false, iterator.hasNext());
+ try {
+ iterator.next();
+ fail("Already read to the end.");
+ } catch (Exception e) {
+ }
+ }
+
+ @Test
+ public void testVersion1_0() throws YamlException {
+ String yaml = "version: !str 1.0";
+ YamlDocumentReader reader = new YamlDocumentReader(yaml, Version.V1_0);
+ YamlMapping yamlMapping = (YamlMapping) reader.read();
+ assertEquals("1.0", ((YamlScalar) yamlMapping.getEntry("version").getValue()).getValue());
+ }
+
+ @Test
+ public void testVersion1_0ThrowsYamlException() {
+ String yaml = "version: !!str 1.1";
+ YamlDocumentReader reader = new YamlDocumentReader(yaml, Version.V1_0);
+ try {
+ reader.read();
+ fail("1.0 Version tag is single '!'");
+ } catch (YamlException e) {
+ }
+ }
+
+ @Test
+ public void testVersion1_1() throws YamlException {
+ String yaml = "version: !!str 1.1";
+ YamlDocumentReader reader = new YamlDocumentReader(yaml, Version.V1_1);
+ YamlMapping yamlMapping = (YamlMapping) reader.read();
+ assertEquals("1.1", ((YamlScalar) yamlMapping.getEntry("version").getValue()).getValue());
+ }
+
+ @Test
+ public void testReadMultipleDocuments() throws YamlException {
+ String yaml = "key: 111\n---\nkey: 222";
+ YamlDocumentReader reader = new YamlDocumentReader(yaml);
+ assertEquals(true, reader.read() != null);
+ assertEquals(true, reader.read() != null);
+ assertEquals(true, reader.read() == null);
+ assertEquals(true, reader.read() == null);
+ }
+
+ @Test
+ public void testReadThrowsYamlException() {
+ String yaml = "\tkey: value";
+ YamlDocumentReader reader = new YamlDocumentReader(yaml);
+ try {
+ reader.read();
+ fail("Tabs cannot be used for indentation.");
+ } catch (YamlException e) {
+ }
+ }
+
+ @Test
+ public void testReadAll() throws YamlException {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("&1 scalar").append("\n");
+ sb.append("---\n").append("*1").append("\n");
+ sb.append("---\n").append("key: value").append("\n");
+ sb.append("---\n").append("- 1\n").append("- 2\n").append("- 3\n");
+ YamlDocumentReader reader = new YamlDocumentReader(sb.toString());
+ Iterator iterator = reader.readAll(YamlElement.class);
+ List list = new ArrayList();
+ while (iterator.hasNext()) {
+ list.add(iterator.next());
+ }
+ assertEquals(4, list.size());
+ assertEquals(true, YamlScalar.class == list.get(0).getClass());
+ assertEquals(true, YamlAlias.class == list.get(1).getClass());
+ assertEquals(true, YamlMapping.class == list.get(2).getClass());
+ assertEquals(true, YamlSequence.class == list.get(3).getClass());
+ }
+
+ @Test
+ public void testReadAllCallingNextThrowsRuntimeException() {
+ String yaml = "\ttest";
+ YamlDocumentReader reader = new YamlDocumentReader(yaml);
+ Iterator iterator = reader.readAll(YamlElement.class);
+ try {
+ iterator.next();
+ fail("");
+ } catch (Exception e) {
+ }
+ }
+
+ @Test
+ public void testReadAllCallingRemoveUnsupportedOperationException() {
+ String yaml = "test";
+ YamlDocumentReader reader = new YamlDocumentReader(yaml);
+ Iterator iterator = reader.readAll(YamlElement.class);
+ try {
+ iterator.remove();
+ fail("");
+ } catch (Exception e) {
+ }
+ }
+
+ private YamlDocument readDocument(String yaml) throws YamlException {
+ YamlDocumentReader reader = new YamlDocumentReader(yaml);
+ return reader.read();
+ }
+
+ private String writeDocument(YamlDocument yaml) throws YamlException {
+ StringWriter writer = new StringWriter();
+ YamlConfig config = new YamlConfig();
+ config.writeConfig.setExplicitFirstDocument(yaml.getTag()!=null);
+ config.writeConfig.setWriteClassname(WriteClassName.NEVER);
+ config.writeConfig.setAutoAnchor(false);
+ YamlWriter yamlWriter = new YamlWriter(writer, config);
+ yamlWriter.write(yaml);
+ yamlWriter.close();
+ return writer.toString();
+ }
+
+ private void testEquals(String yaml) throws Exception {
+ YamlDocument document = readDocument(yaml);
+ String actual = writeDocument(document);
+ assertEquals(yaml, actual);
+ }
+
+
+}
diff --git a/test/com/esotericsoftware/yamlbeans/document/YamlMappingTest.java b/test/com/esotericsoftware/yamlbeans/document/YamlMappingTest.java
new file mode 100644
index 0000000..938d2d2
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/document/YamlMappingTest.java
@@ -0,0 +1,136 @@
+package com.esotericsoftware.yamlbeans.document;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.esotericsoftware.yamlbeans.YamlException;
+
+public class YamlMappingTest {
+
+ private YamlMapping yamlMapping = null;
+
+ @Before
+ public void setUp() throws YamlException {
+ String yaml = "key1: value1\nkey2: value2\nkey3: value3\n";
+ YamlDocumentReader reader = new YamlDocumentReader(yaml);
+ yamlMapping = (YamlMapping) reader.read();
+ yamlMapping.setAnchor("mapping");
+ yamlMapping.setTag("HashMap");
+ }
+
+ @Test
+ public void testSize() {
+ assertEquals(3, yamlMapping.size());
+ }
+
+ @Test
+ public void testAddEntry() throws YamlException {
+ YamlScalar key = new YamlScalar();
+ key.setValue("test");
+ YamlScalar value = new YamlScalar();
+ value.setValue("111");
+ YamlEntry entry = new YamlEntry(key, value);
+ yamlMapping.addEntry(entry);
+
+ assertEquals(entry, yamlMapping.getEntry("test"));
+ }
+
+ @Test
+ public void testDeleteEntry() {
+ assertEquals(true, yamlMapping.deleteEntry("key1"));
+ assertEquals(false, yamlMapping.deleteEntry("key4"));
+ }
+
+ @Test
+ public void testGetEntryByKey() throws YamlException {
+ assertEquals(true, yamlMapping.getEntry("key1") != null);
+ assertEquals(true, yamlMapping.getEntry("key4") == null);
+ }
+
+ @Test
+ public void testGetEntryByIndex() throws YamlException {
+ assertEquals(true, yamlMapping.getEntry(0) != null);
+ }
+
+ @Test(expected = IndexOutOfBoundsException.class)
+ public void testGetEntryByIndexThrowsIndexOutOfBoundsException() throws YamlException {
+ yamlMapping.getEntry(3);
+ }
+
+ @Test
+ public void testToString() {
+ assertEquals("&mapping !HashMap{key1:value1,key2:value2,key3:value3}", yamlMapping.toString());
+ }
+
+ @Test
+ public void testSetEntryUseBooleanValue() throws YamlException {
+ yamlMapping.setEntry("test", true);
+ assertEquals("true", ((YamlScalar) yamlMapping.getEntry("test").getValue()).getValue());
+ }
+
+ @Test
+ public void testSetEntryUseNumberValue() throws YamlException {
+ yamlMapping.setEntry("test", 1);
+ assertEquals("1", ((YamlScalar) yamlMapping.getEntry("test").getValue()).getValue());
+ }
+
+ @Test
+ public void testSetEntryUseStringValue() throws YamlException {
+ yamlMapping.setEntry("test", "test");
+ assertEquals("test", ((YamlScalar) yamlMapping.getEntry("test").getValue()).getValue());
+ }
+
+ @Test(expected = YamlException.class)
+ public void testGetElementByItemThrowsYamlException() throws YamlException {
+ yamlMapping.getElement(0);
+ }
+
+ @Test(expected = YamlException.class)
+ public void testDeleteElementThrowsYamlException() throws YamlException {
+ yamlMapping.deleteElement(0);
+ }
+
+ @Test(expected = YamlException.class)
+ public void testSetElementUseBooleanThrowsYamlException() throws YamlException {
+ yamlMapping.setElement(0, true);
+ }
+
+ @Test(expected = YamlException.class)
+ public void testSetElementUseNumberThrowsYamlException() throws YamlException {
+ yamlMapping.setElement(0, 1);
+ }
+
+ @Test(expected = YamlException.class)
+ public void testSetElementUseStringThrowsYamlException() throws YamlException {
+ yamlMapping.setElement(0, "test");
+ }
+
+ @Test(expected = YamlException.class)
+ public void testSetElementUseYamlElementThrowsYamlException() throws YamlException {
+ YamlElement YamlElement = new YamlScalar();
+ yamlMapping.setElement(0, YamlElement);
+ }
+
+ @Test(expected = YamlException.class)
+ public void testAddElementUseBooleanThrowsYamlException() throws YamlException {
+ yamlMapping.addElement(true);
+ }
+
+ @Test(expected = YamlException.class)
+ public void testAddElementUseNumberThrowsYamlException() throws YamlException {
+ yamlMapping.addElement(1);
+ }
+
+ @Test(expected = YamlException.class)
+ public void testAddElementUseStringThrowsYamlException() throws YamlException {
+ yamlMapping.addElement("test");
+ }
+
+ @Test(expected = YamlException.class)
+ public void testAddElementUseYamlElementThrowsYamlException() throws YamlException {
+ YamlElement YamlElement = new YamlScalar();
+ yamlMapping.addElement(YamlElement);
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/document/YamlSequenceTest.java b/test/com/esotericsoftware/yamlbeans/document/YamlSequenceTest.java
new file mode 100644
index 0000000..3ab6f3b
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/document/YamlSequenceTest.java
@@ -0,0 +1,129 @@
+package com.esotericsoftware.yamlbeans.document;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.esotericsoftware.yamlbeans.YamlException;
+
+public class YamlSequenceTest {
+ private YamlSequence yamlSequence = null;
+
+ @Before
+ public void setUp() throws YamlException {
+ String yaml = "- 1\n- 2\n- 3\n";
+ YamlDocumentReader reader = new YamlDocumentReader(yaml);
+ yamlSequence = (YamlSequence) reader.read();
+ yamlSequence.setAnchor("sequence");
+ yamlSequence.setTag("LinkedList");
+ }
+
+ @Test
+ public void testSize() {
+ assertEquals(3, yamlSequence.size());
+ }
+
+ @Test
+ public void testAddElement() throws YamlException {
+ YamlElement yamlElement = new YamlScalar();
+ yamlSequence.addElement(yamlElement);
+ assertEquals(yamlElement, yamlSequence.getElement(3));
+ }
+
+ @Test
+ public void testDeleteElement() throws YamlException {
+ yamlSequence.deleteElement(0);
+ assertEquals(2, yamlSequence.size());
+ }
+
+ @Test
+ public void testToStrig() {
+ assertEquals("&sequence !LinkedList[1,2,3]", yamlSequence.toString());
+ }
+
+ @Test(expected = YamlException.class)
+ public void testGetEntryByKeyThrowsYamlException() throws YamlException {
+ yamlSequence.getEntry("key");
+ }
+
+ @Test(expected = YamlException.class)
+ public void testGetEntryByIndexThrowsYamlException() throws YamlException {
+ yamlSequence.getEntry(0);
+ }
+
+ @Test(expected = YamlException.class)
+ public void testDeleteEntryByKeyThrowsYamlException() throws YamlException {
+ yamlSequence.deleteEntry("key");
+ }
+
+ @Test(expected = YamlException.class)
+ public void testSetEntryUseBooleanValueThrowsYamlException() throws YamlException {
+ yamlSequence.setEntry("key", true);
+ }
+
+ @Test(expected = YamlException.class)
+ public void testSetEntryUseNumberValueThrowsYamlException() throws YamlException {
+ yamlSequence.setEntry("key", 1);
+ }
+
+ @Test(expected = YamlException.class)
+ public void testSetEntryUseStringValueThrowsYamlException() throws YamlException {
+ yamlSequence.setEntry("key", "111");
+ }
+
+ @Test(expected = YamlException.class)
+ public void testSetEntryUseYamlElementValueThrowsYamlException() throws YamlException {
+ YamlElement yamlElement = new YamlScalar();
+ yamlSequence.setEntry("key", yamlElement);
+ }
+
+ @Test
+ public void testSetElementUseBooleanValue() throws YamlException {
+ yamlSequence.setElement(0, true);
+ YamlScalar yamlScalar = (YamlScalar) yamlSequence.getElement(0);
+ assertEquals("true", yamlScalar.getValue());
+ }
+
+ @Test
+ public void testSetElementUseNumberValue() throws YamlException {
+ yamlSequence.setElement(0, 1);
+ YamlScalar yamlScalar = (YamlScalar) yamlSequence.getElement(0);
+ assertEquals("1", yamlScalar.getValue());
+ }
+
+ @Test
+ public void testSetElementUseStringValue() throws YamlException {
+ yamlSequence.setElement(0, "testStr");
+ YamlScalar yamlScalar = (YamlScalar) yamlSequence.getElement(0);
+ assertEquals("testStr", yamlScalar.getValue());
+ }
+
+ @Test
+ public void testSetElementUseYamlElementValue() throws YamlException {
+ YamlElement yamlElement = new YamlScalar();
+ yamlSequence.setElement(0, yamlElement);
+ assertEquals(yamlElement, yamlSequence.getElement(0));
+ }
+
+ @Test
+ public void testAddElementUseBoolean() throws YamlException {
+ yamlSequence.addElement(true);
+ YamlScalar yamlScalar = (YamlScalar) yamlSequence.getElement(yamlSequence.size() - 1);
+ assertEquals("true", yamlScalar.getValue());
+ }
+
+ @Test
+ public void testAddElementUseNumber() throws YamlException {
+ yamlSequence.addElement(1);
+ YamlScalar yamlScalar = (YamlScalar) yamlSequence.getElement(yamlSequence.size() - 1);
+ assertEquals("1", yamlScalar.getValue());
+ }
+
+ @Test
+ public void testAddElementUseString() throws YamlException {
+ yamlSequence.addElement("testStr");
+ YamlScalar yamlScalar = (YamlScalar) yamlSequence.getElement(yamlSequence.size() - 1);
+ assertEquals("testStr", yamlScalar.getValue());
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/emitter/EmitterTest.java b/test/com/esotericsoftware/yamlbeans/emitter/EmitterTest.java
new file mode 100644
index 0000000..aa773b8
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/emitter/EmitterTest.java
@@ -0,0 +1,160 @@
+package com.esotericsoftware.yamlbeans.emitter;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.BufferedWriter;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.esotericsoftware.yamlbeans.YamlConfig;
+import com.esotericsoftware.yamlbeans.YamlException;
+import com.esotericsoftware.yamlbeans.YamlWriter;
+import com.esotericsoftware.yamlbeans.parser.DocumentStartEvent;
+import com.esotericsoftware.yamlbeans.parser.Event;
+import com.esotericsoftware.yamlbeans.parser.Parser;
+import com.esotericsoftware.yamlbeans.parser.ScalarEvent;
+
+public class EmitterTest {
+ private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ private StringWriter stringWriter = null;
+ private Emitter emitter = null;
+
+ @Before
+ public void setup() {
+ stringWriter = new StringWriter();
+ emitter = new Emitter(stringWriter);
+ }
+
+ @Test
+ public void testEmitterConstructor() throws IOException {
+ try {
+ new Emitter(null);
+ } catch (IllegalArgumentException e) {
+ assertEquals("stream cannot be null.", e.getMessage());
+ }
+
+ StringWriter writer = new StringWriter();
+ new Emitter(writer);
+
+ BufferedWriter bufferedWriter = new BufferedWriter(writer);
+ EmitterConfig emitterConfig = new EmitterConfig();
+ new Emitter(bufferedWriter, emitterConfig);
+ }
+
+ @Test(expected = EmitterException.class)
+ public void testStateStreamStart() throws IOException {
+ emitter.emit(Event.STREAM_START);
+ emitter.emit(new DocumentStartEvent(false, null, null));
+ emitter.emit(Event.DOCUMENT_END_TRUE);
+ }
+
+ @Test(expected = EmitterException.class)
+ public void testStateNOTHING() throws EmitterException, IOException {
+ emitter.emit(Event.STREAM_START);
+ emitter.emit(Event.STREAM_END);
+ assertEquals(3, emitter.state);
+ emitter.emit(Event.DOCUMENT_END_TRUE);
+ }
+
+ @Test(expected = EmitterException.class)
+ public void testDocumentEnd() throws EmitterException, IOException {
+ emitter.emit(Event.STREAM_START);
+ emitter.emit(new DocumentStartEvent(false, null, null));
+ emitter.emit(new ScalarEvent(null, null, new boolean[] { true, true }, "test", '\0'));
+ emitter.emit(Event.STREAM_END);
+ }
+
+ @Test
+ public void testEmptySequence() throws YamlException {
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.writeConfig.setFlowStyle(true);
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ List list = new ArrayList();
+ yamlWriter.write(list);
+ yamlWriter.close();
+ assertEquals("[]" + LINE_SEPARATOR, stringWriter.toString());
+ }
+
+ @Test
+ public void testStateFlowMapingKey() throws YamlException {
+ Map map = new LinkedHashMap();
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.writeConfig.setFlowStyle(true);
+ yamlConfig.writeConfig.setWriteRootTags(false);
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(map);
+ yamlWriter.close();
+ assertEquals("{key1: value1, key2: value2}" + LINE_SEPARATOR, stringWriter.toString());
+
+ }
+
+ @Test
+ public void testStateFlowMapingKeyCanonicalIsTrue() throws EmitterException, IOException {
+ Map map = new LinkedHashMap();
+ map.put("key1", "value1");
+ map.put("key2", "value2");
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.writeConfig.setFlowStyle(true);
+ yamlConfig.writeConfig.setWriteRootTags(false);
+ yamlConfig.writeConfig.setCanonical(true);
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write(map);
+ yamlWriter.close();
+ assertEquals(
+ "--- " + LINE_SEPARATOR + "{" + LINE_SEPARATOR + " ? !java.lang.String \"key1\"" + LINE_SEPARATOR
+ + " : !java.lang.String \"value1\"," + LINE_SEPARATOR + " ? !java.lang.String \"key2\""
+ + LINE_SEPARATOR + " : !java.lang.String \"value2\"" + LINE_SEPARATOR + "}" + LINE_SEPARATOR,
+ stringWriter.toString());
+ }
+
+ @Test(expected = EmitterException.class)
+ public void testDocumentStart() throws EmitterException, IOException {
+ emitter.emit(Event.STREAM_START);
+ emitter.emit(new ScalarEvent(null, null, new boolean[] { true, true }, "test", '\0'));
+ }
+
+ @Test
+ public void testBlockMappingValueMultiline() throws EmitterException, IOException {
+ Map map = new HashMap();
+ map.put("555\n666", "value");
+ YamlWriter yamlWriter = new YamlWriter(stringWriter);
+ yamlWriter.write(map);
+ yamlWriter.close();
+
+ assertEquals("? |-" + LINE_SEPARATOR + " 555" + LINE_SEPARATOR + " 666" + LINE_SEPARATOR + ": value"
+ + LINE_SEPARATOR, stringWriter.toString());
+ }
+
+ @Test(expected = EmitterException.class)
+ public void testExpectNode() throws EmitterException, IOException {
+ emitter.emit(Event.STREAM_START);
+ emitter.emit(new DocumentStartEvent(false, null, null));
+ emitter.emit(Event.MAPPING_END);
+ }
+
+ @Test
+ public void testParserToEmitter() throws EmitterException, IOException {
+ Parser parser = new Parser(new FileReader("test/test.yml"));
+ Emitter emitter = new Emitter(new OutputStreamWriter(System.out));
+ while (true) {
+ Event event = parser.getNextEvent();
+ if (event == null)
+ break;
+ emitter.emit(event);
+ }
+ emitter.close();
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/emitter/EmitterWriterTest.java b/test/com/esotericsoftware/yamlbeans/emitter/EmitterWriterTest.java
new file mode 100644
index 0000000..44e742e
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/emitter/EmitterWriterTest.java
@@ -0,0 +1,73 @@
+package com.esotericsoftware.yamlbeans.emitter;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.StringWriter;
+import org.junit.Test;
+
+import com.esotericsoftware.yamlbeans.YamlConfig;
+import com.esotericsoftware.yamlbeans.YamlException;
+import com.esotericsoftware.yamlbeans.YamlWriter;
+import com.esotericsoftware.yamlbeans.YamlConfig.Quote;
+
+public class EmitterWriterTest {
+
+ private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ @Test
+ public void testWriteDoubleQuoted() throws YamlException {
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.writeConfig.setQuoteChar(Quote.DOUBLE);
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("\u0001\u0011\u0111\u1111\u0007");
+ yamlWriter.close();
+
+ assertEquals("\"\\u0001\\u0011\\u0111\\u1111\\a\"" + LINE_SEPARATOR, stringWriter.toString());
+
+ stringWriter = new StringWriter();
+ yamlConfig.writeConfig.setWrapColumn(5);
+ yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("testt est");
+ yamlWriter.close();
+ assertEquals("\"testt\\" + LINE_SEPARATOR + " \\ e\\" + LINE_SEPARATOR + " st\"" + LINE_SEPARATOR,
+ stringWriter.toString());
+ }
+
+ @Test
+ public void testWriteSingleQuoted() throws YamlException {
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.writeConfig.setQuoteChar(Quote.SINGLE);
+
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("\ntest");
+ yamlWriter.close();
+ assertEquals("\'" + LINE_SEPARATOR + " test\'" + LINE_SEPARATOR, stringWriter.toString());
+
+ }
+
+ @Test
+ public void testWriteFolded() throws YamlException {
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.writeConfig.setQuoteChar(Quote.FOLDED);
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("111\n222 333");
+ yamlWriter.close();
+ assertEquals(">-" + LINE_SEPARATOR + " 111" + LINE_SEPARATOR + LINE_SEPARATOR + " 222 333" + LINE_SEPARATOR,
+ stringWriter.toString());
+ }
+
+ @Test
+ public void testWriteLiteral() throws YamlException {
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.writeConfig.setQuoteChar(Quote.LITERAL);
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter yamlWriter = new YamlWriter(stringWriter, yamlConfig);
+ yamlWriter.write("111\n222");
+ yamlWriter.close();
+ assertEquals("|-" + LINE_SEPARATOR + " 111" + LINE_SEPARATOR + " 222" + LINE_SEPARATOR,
+ stringWriter.toString());
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/issues/issue101/Issue101Test.java b/test/com/esotericsoftware/yamlbeans/issues/issue101/Issue101Test.java
new file mode 100644
index 0000000..30791ed
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/issues/issue101/Issue101Test.java
@@ -0,0 +1,34 @@
+package com.esotericsoftware.yamlbeans.issues.issue101;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.esotericsoftware.yamlbeans.YamlException;
+import com.esotericsoftware.yamlbeans.YamlReader;
+
+public class Issue101Test {
+
+ private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ @Test
+ public void test() throws YamlException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("!com.esotericsoftware.yamlbeans.issues.issue101.Issue101Test$TestObject").append(LINE_SEPARATOR);
+ sb.append("test: test");
+ YamlReader yamlReader = new YamlReader(sb.toString());
+ TestObject testObject = (TestObject) yamlReader.read();
+ assertEquals("test", testObject.test);
+
+ sb = new StringBuilder();
+ sb.append("!").append(LINE_SEPARATOR);
+ sb.append("test: test");
+ yamlReader = new YamlReader(sb.toString());
+ testObject = (TestObject) yamlReader.read();
+ assertEquals("test", testObject.test);
+ }
+
+ static class TestObject {
+ public String test;
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/issues/issue37/Issue37Test.java b/test/com/esotericsoftware/yamlbeans/issues/issue37/Issue37Test.java
new file mode 100644
index 0000000..a1c6e92
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/issues/issue37/Issue37Test.java
@@ -0,0 +1,39 @@
+package com.esotericsoftware.yamlbeans.issues.issue37;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.StringWriter;
+
+import org.junit.Test;
+
+import com.esotericsoftware.yamlbeans.YamlConfig;
+import com.esotericsoftware.yamlbeans.YamlException;
+import com.esotericsoftware.yamlbeans.YamlReader;
+import com.esotericsoftware.yamlbeans.YamlWriter;
+
+public class Issue37Test {
+
+ private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ @Test
+ public void test() throws YamlException {
+
+ TestObject testObject = new TestObject();
+ testObject.sexType = SexType.FEMALE;
+
+ YamlConfig yamlConfig = new YamlConfig();
+ yamlConfig.setScalarSerializer(SexType.class, new SexTypeSerializer());
+ StringWriter sw = new StringWriter();
+ YamlWriter writer = new YamlWriter(sw, yamlConfig);
+ writer.write(testObject);
+ writer.close();
+ System.out.println(sw.toString());
+
+ assertEquals("!com.esotericsoftware.yamlbeans.issues.issue37.TestObject" + LINE_SEPARATOR + "sexType: female"
+ + LINE_SEPARATOR, sw.toString());
+
+ YamlReader reader = new YamlReader(sw.toString(), yamlConfig);
+ TestObject obj = reader.read(TestObject.class);
+ assertEquals(SexType.FEMALE, obj.sexType);
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/issues/issue37/SexType.java b/test/com/esotericsoftware/yamlbeans/issues/issue37/SexType.java
new file mode 100644
index 0000000..8e4833a
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/issues/issue37/SexType.java
@@ -0,0 +1,6 @@
+package com.esotericsoftware.yamlbeans.issues.issue37;
+
+public enum SexType {
+
+ MALE, FEMALE;
+}
diff --git a/test/com/esotericsoftware/yamlbeans/issues/issue37/SexTypeSerializer.java b/test/com/esotericsoftware/yamlbeans/issues/issue37/SexTypeSerializer.java
new file mode 100644
index 0000000..91784b7
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/issues/issue37/SexTypeSerializer.java
@@ -0,0 +1,15 @@
+package com.esotericsoftware.yamlbeans.issues.issue37;
+
+import com.esotericsoftware.yamlbeans.YamlException;
+import com.esotericsoftware.yamlbeans.scalar.ScalarSerializer;
+
+public class SexTypeSerializer implements ScalarSerializer {
+
+ public String write(SexType object) throws YamlException {
+ return object.name().toLowerCase();
+ }
+
+ public SexType read(String value) throws YamlException {
+ return SexType.valueOf(value.toUpperCase());
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/issues/issue37/TestObject.java b/test/com/esotericsoftware/yamlbeans/issues/issue37/TestObject.java
new file mode 100644
index 0000000..22c7fb4
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/issues/issue37/TestObject.java
@@ -0,0 +1,7 @@
+package com.esotericsoftware.yamlbeans.issues.issue37;
+
+public class TestObject {
+
+ public SexType sexType;
+
+}
diff --git a/test/com/esotericsoftware/yamlbeans/issues/issue52/YamlEnumTest.java b/test/com/esotericsoftware/yamlbeans/issues/issue52/YamlEnumTest.java
new file mode 100644
index 0000000..e9d21e0
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/issues/issue52/YamlEnumTest.java
@@ -0,0 +1,85 @@
+package com.esotericsoftware.yamlbeans.issues.issue52;
+
+import com.esotericsoftware.yamlbeans.YamlReader;
+import com.esotericsoftware.yamlbeans.YamlWriter;
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+public class YamlEnumTest extends TestCase {
+
+ public static class TestObject {
+ public EnumIface[] enumArray = new EnumIface[] { CustomEnum.V1, CustomEnum.V2 };
+ }
+
+ public interface EnumIface {
+
+ }
+
+ public enum CustomEnum implements EnumIface {
+ V1, V2
+ }
+
+ public static class NonEnum implements EnumIface {
+ public String v1, v2;
+
+ public NonEnum() {
+ }
+
+ public NonEnum(String v1, String v2) {
+ this.v1 = v1;
+ this.v2 = v2;
+ }
+ }
+
+ public YamlEnumTest() {
+ }
+
+ public static String write(Object object) throws IOException {
+ StringWriter stringWriter = new StringWriter();
+ YamlWriter writer = new YamlWriter(stringWriter);
+
+ writer.getConfig().setPrivateFields(false);
+ writer.write(object);
+ writer.close();
+
+ String string = stringWriter.toString();
+ System.out.println("Wrote: \n" + string);
+
+ return string;
+ }
+
+ public void read(String string) throws IOException {
+ YamlReader reader = new YamlReader(string);
+ reader.read(TestObject.class);
+ reader.close();
+ }
+
+ public void testNonEnum() throws IOException {
+ TestObject testObject = new TestObject();
+ testObject.enumArray = new EnumIface[] { new NonEnum("v1", "v2"), new NonEnum("v1", "v2") };
+
+ read(write(testObject));
+ }
+
+ public void testOnlyEnums() throws IOException {
+ TestObject testObject = new TestObject();
+ testObject.enumArray = new EnumIface[] { CustomEnum.V1, CustomEnum.V2 };
+
+ read(write(testObject));
+ }
+
+ public void testMixEnumsAndNonEnums() throws IOException {
+ TestObject testObject = new TestObject();
+ testObject.enumArray = new EnumIface[] { new NonEnum("v1", "v2"), CustomEnum.V2 };
+
+ read(write(testObject));
+ }
+
+ public void testFixedEnum() throws IOException {
+ read("!com.esotericsoftware.yamlbeans.issues.issue52.YamlEnumTest$TestObject\n" + "enumArray:\n"
+ + "- !com.esotericsoftware.yamlbeans.issues.issue52.YamlEnumTest$CustomEnum V1\n"
+ + "- !com.esotericsoftware.yamlbeans.issues.issue52.YamlEnumTest$CustomEnum V2\n");
+ }
+}
diff --git a/test/com/esotericsoftware/yamlbeans/tokenizer/TokenizerTest.java b/test/com/esotericsoftware/yamlbeans/tokenizer/TokenizerTest.java
new file mode 100644
index 0000000..6a328bf
--- /dev/null
+++ b/test/com/esotericsoftware/yamlbeans/tokenizer/TokenizerTest.java
@@ -0,0 +1,198 @@
+package com.esotericsoftware.yamlbeans.tokenizer;
+
+import com.esotericsoftware.yamlbeans.tokenizer.Tokenizer.TokenizerException;
+import org.junit.Test;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Iterator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class TokenizerTest {
+
+ private Token STREAM_START = new Token(TokenType.STREAM_START);
+ private Token STREAM_END = new Token(TokenType.STREAM_END);
+ private Token VALUE = new Token(TokenType.VALUE);
+ private Token KEY = new Token(TokenType.KEY);
+ private Token BLOCK_MAPPING_START = new Token(TokenType.BLOCK_MAPPING_START);
+ private Token BLOCK_END = new Token(TokenType.BLOCK_END);
+
+ /**
+ * Purpose: Getting the next token correctly
+ * Input: getNextToken() gets the next token and moves to the next token
+ * Expected:
+ * return Token.STREAM_START
+ * return Token.BLOCK_MAPPING_START
+ * return Token.KEY
+ * ...
+ * return Token.STREAM.END
+ * return null
+ */
+ @Test
+ public void testGetNextToken() throws FileNotFoundException {
+ Tokenizer tokenizer = new Tokenizer(new FileReader("test/test1.yml"));
+ assertEquals(tokenizer.getNextToken() + "", STREAM_START + "");
+ assertEquals(tokenizer.getNextToken() + "", BLOCK_MAPPING_START + "");
+ assertEquals(tokenizer.getNextToken() + "", KEY + "");
+ assertEquals(tokenizer.getNextToken() + "", "");
+ assertEquals(tokenizer.getNextToken() + "", VALUE + "");
+ assertEquals(tokenizer.getNextToken() + "", "");
+ assertEquals(tokenizer.getNextToken() + "", BLOCK_END + "");
+ assertEquals(tokenizer.getNextToken() + "", STREAM_END + "");
+ assertNull(tokenizer.getNextToken());
+ }
+
+ /**
+ * Purpose: Ensuring that the constructor Tokenizer(Reader) is working properly
+ * Input: Tokenizer(Reader) FileReader("test/test1.yml") -> Tokenizer(FileReader("test/test1.yml"))
+ * Expected:
+ * peekNextToken() = Token.STREAM_START
+ * Tokenizer(BufferedReader(FileReader("test/test1.yml"))) = Tokenizer(FileReader("test/test1.yml"))
+ * Tokenizer(null) throws IllegalArgumentException.class
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testTokenizerReader() throws FileNotFoundException {
+ Tokenizer tokenizer = new Tokenizer(new FileReader("test/test1.yml"));
+ assertEquals(tokenizer.peekNextToken() + "", STREAM_START + "");
+ Tokenizer tokenizer_nbuffered = new Tokenizer((new BufferedReader(new FileReader("test/test1.yml"))));
+
+ Iterator tokenizer_iter = tokenizer.iterator();
+ Iterator tokenizer_nbuffered_iter = tokenizer_nbuffered.iterator();
+
+ while (tokenizer_iter.hasNext() || tokenizer_nbuffered_iter.hasNext()) {
+ assertEquals(tokenizer_iter.next() + "", tokenizer_nbuffered_iter.next() + "");
+ }
+
+ Tokenizer tokenizer_null = new Tokenizer((FileReader) null);
+ }
+
+ /**
+ * Purpose: Ensuring that the constructor Tokenizer(String) is working properly
+ * Input: Tokenizer(String) FileReader("12: 13") = Tokenizer(FileReader("test/test1.yml")), The content of "test/test1.yml" is "12: 13"
+ * Expected:
+ * Tokenizer(FileReader("12: 13")) = Tokenizer(FileReader("test/test1.yml")), The content of "test/test1.yml" is "12: 13"
+ */
+ @Test
+ public void testTokenizerString() throws FileNotFoundException {
+ Iterator tokenizer_iter = new Tokenizer(new FileReader("test/test1.yml")).iterator();
+ Iterator tokenizer_string_iter = new Tokenizer("12: 13").iterator();
+
+ while (tokenizer_iter.hasNext() || tokenizer_string_iter.hasNext()) {
+ assertEquals(tokenizer_iter.next() + "", tokenizer_string_iter.next() + "");
+ }
+ }
+
+ /**
+ * Purpose: peeking the next token correctly
+ * Input: peekNextToken() peeks the next token and does not move to the next token
+ * Expected:
+ * return Token.STREAM_START
+ * (moves by another function)
+ * return Token.BLOCK_MAPPING_START
+ * (moves by another function)
+ * return Token.KEY
+ * (moves by another function)
+ * ...
+ * return Token.STREAM.END
+ * (moves by another function)
+ * return null
+ */
+ @Test
+ public void testPeekNextToken() throws FileNotFoundException {
+ Tokenizer tokenizer = new Tokenizer(new FileReader("test/test1.yml"));
+ assertEquals(tokenizer.peekNextToken() + "", STREAM_START + "");
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextToken() + "", BLOCK_MAPPING_START + "");
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextToken() + "", KEY + "");
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextToken() + "", "");
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextToken() + "", VALUE + "");
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextToken() + "", "");
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextToken() + "", BLOCK_END + "");
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextToken() + "", STREAM_END + "");
+ tokenizer.getNextToken();
+ assertNull(tokenizer.peekNextToken());
+ }
+
+ /**
+ * Purpose: peeking the type of the next token correctly
+ * Input: peekNextToken() peeks the type of the next token and does not move to the next token
+ * Expected:
+ * return TokenType.STREAM_START
+ * (moves by another function)
+ * return TokenType.BLOCK_MAPPING_START
+ * (moves by another function)
+ * return TokenType.KEY
+ * (moves by another function)
+ * ...
+ * return TokenType.STREAM.END
+ * (moves by another function)
+ * return null
+ */
+ @Test
+ public void testPeekNextTokenType() throws FileNotFoundException {
+ Tokenizer tokenizer = new Tokenizer(new FileReader("test/test1.yml"));
+ assertEquals(tokenizer.peekNextTokenType(), TokenType.STREAM_START);
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextTokenType(), TokenType.BLOCK_MAPPING_START);
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextTokenType(), TokenType.KEY);
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextTokenType(), TokenType.SCALAR);
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextTokenType(), TokenType.VALUE);
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextTokenType(), TokenType.SCALAR);
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextTokenType(), TokenType.BLOCK_END);
+ tokenizer.getNextToken();
+ assertEquals(tokenizer.peekNextTokenType(), TokenType.STREAM_END);
+ tokenizer.getNextToken();
+ assertNull(tokenizer.peekNextTokenType());
+ }
+
+
+ /**
+ * Purpose: Ensuring that the iterator's functions are working properly
+ * Input: iterator().hasNext() returns the same value as (Tokenizer.peekNextToken != null)
+ * iterator().next() returns the same value as Tokenizer.getNextToken()
+ * Expected:
+ * Tokenizer.iterator().hasNext() = (Tokenizer.peekNextToken != null)
+ * Tokenizer.iterator().next() = Tokenizer.getNextToken()
+ * Tokenizer.iterator().remove() throws UnsupportedOperationException.class
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testIterator() throws FileNotFoundException {
+ Tokenizer tokenizer = new Tokenizer(new FileReader("test/test1.yml"));
+ Iterator iter = new Tokenizer(new FileReader("test/test1.yml")).iterator();
+ assertEquals(iter.hasNext(), tokenizer.peekNextToken() != null);
+ assertEquals(iter.next(), tokenizer.getNextToken());
+ iter.remove();
+ }
+
+ /**
+ * Purpose: Getting the next token in a closed reader
+ * Input: close() Tokenizer.reader -> Tokenizer.reader.close()
+ * Expected:
+ * Tokenizer.getNextToken() = Token.STREAM_START
+ * Tokenizer.getNextToken() throws TokenizerException.class
+ */
+ @Test(expected = TokenizerException.class)
+ public void testClose() throws IOException {
+ Tokenizer tokenizer = new Tokenizer(new FileReader("test/test1.yml"));
+ tokenizer.close();
+
+ assertEquals(tokenizer.getNextToken() + "", STREAM_START + "");
+ tokenizer.getNextToken();
+ }
+
+}
\ No newline at end of file
diff --git a/test/test-merge.yml b/test/test-merge.yml
new file mode 100644
index 0000000..c32529c
--- /dev/null
+++ b/test/test-merge.yml
@@ -0,0 +1,6 @@
+stuff: &anchor
+ v1: v1
+ v2: v2
+merged:
+ <<: *anchor
+ v3: v3
\ No newline at end of file
diff --git a/test/test.yml b/test/test.yml
index c1bd737..f31b51b 100644
--- a/test/test.yml
+++ b/test/test.yml
@@ -1,14 +1,13 @@
---- !net.sourceforge.yamlbeans.YamlWriterTest$Test
booleanValue: true
date: 2008-08-13 03:26:24
-child: &1 !net.sourceforge.yamlbeans.YamlWriterTest$Test2
+child: &1
value: weeeee
doubleValue: 1.5
floatValue: 1.2
intValue: 123
-listValues: !java.util.LinkedList
+listValues:
- woo
-- !net.sourceforge.yamlbeans.YamlWriterTest$Test {}
+- {}
- 123
- *1
mooCow: yay
diff --git a/test/test1.yml b/test/test1.yml
new file mode 100644
index 0000000..8068c9c
--- /dev/null
+++ b/test/test1.yml
@@ -0,0 +1 @@
+12: 13
\ No newline at end of file