diff --git a/pom.xml b/pom.xml index d012168..901fc6b 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ org.mongodb bson - 4.11.1 + 5.0.0 true diff --git a/src/main/java/org/javawebstack/abstractdata/AbstractElement.java b/src/main/java/org/javawebstack/abstractdata/AbstractElement.java index a2a441d..2db30ca 100644 --- a/src/main/java/org/javawebstack/abstractdata/AbstractElement.java +++ b/src/main/java/org/javawebstack/abstractdata/AbstractElement.java @@ -120,7 +120,11 @@ default String toYaml() { } static AbstractElement fromYaml(String source, boolean singleRoot) { - return new YamlParser().setSingleRoot(singleRoot).parse(source); + try { + return new YamlParser().setSingleRoot(singleRoot).parse(source); + } catch (ParseException e) { + throw new RuntimeException(e); + } } static AbstractElement fromYaml(String source) { diff --git a/src/main/java/org/javawebstack/abstractdata/yaml/LegacyYamlDumper.java b/src/main/java/org/javawebstack/abstractdata/yaml/LegacyYamlDumper.java index 4dd7f37..937540b 100644 --- a/src/main/java/org/javawebstack/abstractdata/yaml/LegacyYamlDumper.java +++ b/src/main/java/org/javawebstack/abstractdata/yaml/LegacyYamlDumper.java @@ -8,14 +8,14 @@ public class LegacyYamlDumper { protected static String dump(AbstractElement e, boolean pretty) { Yaml yaml; + DumperOptions options = new DumperOptions(); if (pretty) { - DumperOptions options = new DumperOptions(); options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); options.setPrettyFlow(true); - yaml = new Yaml(options); } else { - yaml = new Yaml(); + options.setPrettyFlow(false); } + yaml = new Yaml(options); return yaml.dump(e.toObject()); } diff --git a/src/main/java/org/javawebstack/abstractdata/yaml/LegacyYamlParser.java b/src/main/java/org/javawebstack/abstractdata/yaml/LegacyYamlParser.java index 24399ee..fe230f5 100644 --- a/src/main/java/org/javawebstack/abstractdata/yaml/LegacyYamlParser.java +++ b/src/main/java/org/javawebstack/abstractdata/yaml/LegacyYamlParser.java @@ -1,25 +1,34 @@ package org.javawebstack.abstractdata.yaml; import org.javawebstack.abstractdata.AbstractElement; +import org.javawebstack.abstractdata.AbstractNull; import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.parser.ParserException; -import java.util.HashMap; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class LegacyYamlParser { - protected static AbstractElement parse(String source, boolean singleRoot) { - Yaml yaml = new Yaml(); - Object object = yaml.load(source); - if (singleRoot && object instanceof List) { - List list = (List) object; - if (list.size() == 0) { - object = new HashMap<>(); - } else { + protected static AbstractElement parse(String source, boolean singleRoot) throws ParseException { + if(source.trim().equalsIgnoreCase("null")) + return AbstractNull.VALUE; + if(source.trim().isEmpty()) + throw new ParseException("Invalid yaml", 0); + try { + Yaml yaml = new Yaml(); + List list = new ArrayList<>(); + yaml.loadAll(source).forEach(list::add); + Object object = list; + if (singleRoot && list.size() == 1) { object = list.get(0); } + return AbstractElement.fromObject(object); + } catch (ParserException e) { + throw new ParseException(e.getMessage(), e.getProblemMark().getIndex()); } - return AbstractElement.fromObject(object); } } diff --git a/src/main/java/org/javawebstack/abstractdata/yaml/YamlParser.java b/src/main/java/org/javawebstack/abstractdata/yaml/YamlParser.java index 7eacc5a..14b8177 100644 --- a/src/main/java/org/javawebstack/abstractdata/yaml/YamlParser.java +++ b/src/main/java/org/javawebstack/abstractdata/yaml/YamlParser.java @@ -2,6 +2,8 @@ import org.javawebstack.abstractdata.AbstractElement; +import java.text.ParseException; + public class YamlParser { boolean singleRoot = false; @@ -15,7 +17,7 @@ public boolean isSingleRoot() { return singleRoot; } - public AbstractElement parse(String source) { + public AbstractElement parse(String source) throws ParseException { return LegacyYamlParser.parse(source, singleRoot); } diff --git a/src/test/java/org/javawebstack/abstractdata/yaml/YamlDumperTest.java b/src/test/java/org/javawebstack/abstractdata/yaml/YamlDumperTest.java new file mode 100644 index 0000000..d211544 --- /dev/null +++ b/src/test/java/org/javawebstack/abstractdata/yaml/YamlDumperTest.java @@ -0,0 +1,38 @@ +package org.javawebstack.abstractdata.yaml; + +import org.javawebstack.abstractdata.AbstractArray; +import org.javawebstack.abstractdata.AbstractObject; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +public class YamlDumperTest { + + @Test + public void testDump() { + AbstractObject object = new AbstractObject() + .set("a", 1) + .set("b", new AbstractArray()); + String expected = "a: 1\nb: []\n"; // Not actually minified but that's what snakeyaml outputs + String dumped = new YamlDumper().dump(object); + assertEquals(expected, dumped); + } + + @Test + public void testDumpPretty() { + AbstractObject object = new AbstractObject() + .set("a", 1) + .set("b", new AbstractArray()); + String expected = "a: 1\nb: [\n ]\n"; // Not actually expected, as it's not pretty but that's what snakeyaml calls pretty + String dumped = new YamlDumper().setPretty(true).dump(object); + assertEquals(expected, dumped); + } + + @Test + public void testSetPretty() { + YamlDumper dumper = new YamlDumper(); + assertFalse(dumper.isPretty()); + dumper.setPretty(true); + assertTrue(dumper.isPretty()); + } + +} diff --git a/src/test/java/org/javawebstack/abstractdata/yaml/YamlParserTest.java b/src/test/java/org/javawebstack/abstractdata/yaml/YamlParserTest.java new file mode 100644 index 0000000..770264f --- /dev/null +++ b/src/test/java/org/javawebstack/abstractdata/yaml/YamlParserTest.java @@ -0,0 +1,62 @@ +package org.javawebstack.abstractdata.yaml; + +import org.javawebstack.abstractdata.AbstractElement; +import org.junit.jupiter.api.Test; +import org.yaml.snakeyaml.Yaml; + +import java.text.ParseException; + +import static org.junit.jupiter.api.Assertions.*; + +public class YamlParserTest { + + @Test + public void testParse() { + AbstractElement e = assertDoesNotThrow(() -> new YamlParser().setSingleRoot(true).parse("test:\n a: 123\n b: false\n c: 'abc'")); + assertNotNull(e); + assertTrue(e.isObject()); + assertEquals(1, e.object().size()); + AbstractElement testElement = e.object().get("test"); + assertNotNull(testElement); + assertTrue(testElement.isObject()); + assertEquals(3, testElement.object().size()); + AbstractElement aElement = testElement.object().get("a"); + assertNotNull(aElement); + assertTrue(aElement.isNumber()); + assertEquals(123, aElement.number()); + AbstractElement bElement = testElement.object().get("b"); + assertNotNull(bElement); + assertTrue(bElement.isBoolean()); + assertEquals(false, bElement.bool()); + AbstractElement cElement = testElement.object().get("c"); + assertNotNull(cElement); + assertTrue(cElement.isString()); + assertEquals("abc", cElement.string()); + } + + @Test + public void testParseEmptyDocument() { + assertThrows(ParseException.class, () -> new YamlParser().parse("")); + } + + @Test + public void testParseNull() { + AbstractElement e = assertDoesNotThrow(() -> new YamlParser().parse("null")); + assertNotNull(e); + assertTrue(e.isNull()); + } + + @Test + public void testParseInvalidDocument() { + assertThrows(ParseException.class, () -> new YamlParser().parse("\"a\"1")); + } + + @Test + public void testSetSingleRoot() { + YamlParser parser = new YamlParser(); + assertFalse(parser.isSingleRoot()); + parser.setSingleRoot(true); + assertTrue(parser.isSingleRoot()); + } + +}