Repository: decorators-squad/eo-yaml (java)

Issue:
Erroneous Inclusion of Double Quotes for Parsed Double Quoted Strings
I have a YAML file with these(obscured) contents:

```
hostname: localhost
password: "Password!@#"
port: 61616
username: myuser
```

and the double quotes around the password make it into the parsed string when calling

`this.password = yamlMapping.string("password");`

in my code.  Therefore, I had to implement a regex-based hack:

`this.password = yamlMapping.string("password").replaceAll("^\"|\"$",  "");`

This is definitely annoying, and I'm almost certain that it's a bug because I scoured the web looking at pages on YAML for any sign of this behavior in other libraries.  I found no evidence that this is the intended behavior / spec.

NB: The double quotes are necessary because the # at the end of the string in the YAML file gets excised since it is the comment character for YAML.

Pull request description:
#144 fixed escaping issues + unit tests
Fixes #144 
Added escaping when printing
Added unit tests
Adapted some existing unit tests

Patch:
diff --git a/src/main/java/com/amihaiemil/eoyaml/RtYamlPrinter.java b/src/main/java/com/amihaiemil/eoyaml/RtYamlPrinter.java
index 6cb5d4e..334d562 100644
--- a/src/main/java/com/amihaiemil/eoyaml/RtYamlPrinter.java
+++ b/src/main/java/com/amihaiemil/eoyaml/RtYamlPrinter.java
@@ -202,7 +202,12 @@ final class RtYamlPrinter implements YamlPrinter {
         if (scalar instanceof PlainStringScalar
             || scalar instanceof ReadPlainScalar
         ) {
-            this.writer.append(this.indent(scalar.value(), indentation));
+            this.writer.append(
+                this.indent(
+                    new Escaped(scalar).value(),
+                    indentation
+                )
+            );
             if(!scalar.comment().value().isEmpty()) {
                 this.writer.append(" # ").append(scalar.comment().value());
             }
@@ -326,4 +331,63 @@ final class RtYamlPrinter implements YamlPrinter {
         printed.delete(printed.length()-1, printed.length());
         return printed.toString();
     }
+
+    /**
+     * A scalar which escapes its value.
+     * @author Mihai Andronache (amihaiemil@gmail.com)
+     * @version $Id$
+     * @since 4.3.1
+     */
+    static class Escaped extends BaseScalar {
+
+        /**
+         * Special chars that need escaping.
+         */
+        private final String RESERVED = "#:->|$%&";
+
+        /**
+         * Original unescaped scalar.
+         */
+        private final Scalar original;
+
+        /**
+         * Ctor.
+         * @param original Unescaped scalar.
+         */
+        Escaped(final Scalar original) {
+            this.original = original;
+        }
+
+        @Override
+        public String value() {
+            final String value = this.original.value();
+            String escaped = null;
+            if(value.startsWith("'") && value.endsWith("'")
+                || value.startsWith("\"") && value.endsWith("\"")
+            ) {
+                escaped = value;
+            } else {
+                for (int idx = 0; idx < value.length(); idx++){
+                    if(RESERVED.contains(
+                        String.valueOf(value.charAt(idx)))) {
+                        if(value.contains("\"")) {
+                            escaped = "'" + value + "'";
+                        } else {
+                            escaped = "\"" + value + "\"";
+                        }
+                        break;
+                    }
+                }
+                if(escaped == null) {
+                    escaped = value;
+                }
+            }
+            return escaped;
+        }
+
+        @Override
+        public Comment comment() {
+            return this.original.comment();
+        }
+    }
 }


Test patch:
diff --git a/src/test/java/com/amihaiemil/eoyaml/YamlMappingPrintTest.java b/src/test/java/com/amihaiemil/eoyaml/YamlMappingPrintTest.java
index 521de7a..541ddac 100644
--- a/src/test/java/com/amihaiemil/eoyaml/YamlMappingPrintTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/YamlMappingPrintTest.java
@@ -262,6 +262,39 @@ public final class YamlMappingPrintTest {
         );
     }
 
+    /**
+     * When a scalar value in a mapping contains a reserved symbol,
+     * it should be escaped (wrapped between quotes or apostrophes).
+     */
+    @Test
+    public void printsEscapedScalars() {
+        final YamlMapping map = Yaml.createYamlMappingBuilder()
+            .add("time", "15:00")
+            .add("color", "#314132")
+            .add("gt", "&gt;")
+            .add("cash", "$15")
+            .add("compare", "a>b")
+            .add("xor", "a || b")
+            .add("degrees", "-15C")
+            .add("percentage", "3% reads \"3 per cent\"")
+            .build();
+        final StringBuilder expected = new StringBuilder();
+        expected
+            .append("time: \"15:00\"").append(System.lineSeparator())
+            .append("color: \"#314132\"").append(System.lineSeparator())
+            .append("gt: \"&gt;\"").append(System.lineSeparator())
+            .append("cash: \"$15\"").append(System.lineSeparator())
+            .append("compare: \"a>b\"").append(System.lineSeparator())
+            .append("xor: \"a || b\"").append(System.lineSeparator())
+            .append("degrees: \"-15C\"").append(System.lineSeparator())
+            .append("percentage: '3% reads \"3 per cent\"'");
+        MatcherAssert.assertThat(
+            map.toString(),
+            Matchers.equalTo(expected.toString())
+        );
+    }
+
+
     /**
      * Read a test resource file's contents.
      * @param fileName File to read.
diff --git a/src/test/java/com/amihaiemil/eoyaml/YamlSequencePrintTest.java b/src/test/java/com/amihaiemil/eoyaml/YamlSequencePrintTest.java
index 278b876..35d69bb 100644
--- a/src/test/java/com/amihaiemil/eoyaml/YamlSequencePrintTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/YamlSequencePrintTest.java
@@ -243,6 +243,42 @@ public final class YamlSequencePrintTest {
         );
     }
 
+    /**
+     * When a scalar value in a sequence contains a reserved symbol,
+     * it should be escaped (wrapped between quotes or apostrophes).
+     */
+    @Test
+    public void printsEscapedScalars() {
+        final YamlMapping map = Yaml.createYamlMappingBuilder()
+            .add(
+                "sequence",
+                Yaml.createYamlSequenceBuilder()
+                    .add("15:00")
+                    .add("#314132")
+                    .add("&gt;")
+                    .add("$15")
+                    .add("a>b")
+                    .add("a || b")
+                    .add("-15C")
+                    .add("3% reads \"3 per cent\"")
+                    .build()
+            ).build();
+        final StringBuilder expected = new StringBuilder();
+        expected
+            .append("- \"15:00\"").append(System.lineSeparator())
+            .append("- \"#314132\"").append(System.lineSeparator())
+            .append("- \"&gt;\"").append(System.lineSeparator())
+            .append("- \"$15\"").append(System.lineSeparator())
+            .append("- \"a>b\"").append(System.lineSeparator())
+            .append("- \"a || b\"").append(System.lineSeparator())
+            .append("- \"-15C\"").append(System.lineSeparator())
+            .append("- '3% reads \"3 per cent\"'");
+        MatcherAssert.assertThat(
+            map.yamlSequence("sequence").toString(),
+            Matchers.equalTo(expected.toString())
+        );
+    }
+
     /**
      * Read a test resource file's contents.
      * @param fileName File to read.
diff --git a/src/test/resources/commentedMapping.yml b/src/test/resources/commentedMapping.yml
index a0e1172..1ec478a 100644
--- a/src/test/resources/commentedMapping.yml
+++ b/src/test/resources/commentedMapping.yml
@@ -5,4 +5,4 @@ developers:
   - rultor
   - salikjan
   - sherif
-name: eo-yaml # name of the project
\ No newline at end of file
+name: "eo-yaml" # name of the project
\ No newline at end of file
diff --git a/src/test/resources/complexMapping.yml b/src/test/resources/complexMapping.yml
index 507d672..c0831a8 100644
--- a/src/test/resources/complexMapping.yml
+++ b/src/test/resources/complexMapping.yml
@@ -2,11 +2,11 @@
   - Atlanta Braves
   - New York Yankees
 :
-  - 2001-07-02
-  - 2001-08-12
-  - 2001-08-14
+  - "2001-07-02"
+  - "2001-08-12"
+  - "2001-08-14"
 ?
   - Chicago cubs
   - Detroit Tigers
 :
-  - 2001-07-23
\ No newline at end of file
+  - "2001-07-23"
\ No newline at end of file
diff --git a/src/test/resources/printing_tests/yamlMappingAllNodes.txt b/src/test/resources/printing_tests/yamlMappingAllNodes.txt
index f8e058b..a364329 100644
--- a/src/test/resources/printing_tests/yamlMappingAllNodes.txt
+++ b/src/test/resources/printing_tests/yamlMappingAllNodes.txt
@@ -17,9 +17,9 @@ key5:
   - Atlanta Braves
   - New York Yankees
 :
-  - 2001-07-02
-  - 2001-08-12
-  - 2001-08-14
+  - "2001-07-02"
+  - "2001-08-12"
+  - "2001-08-14"
 ?
   map: asKey
 : scalar
\ No newline at end of file
diff --git a/src/test/resources/simpleMapping.yml b/src/test/resources/simpleMapping.yml
index 27cc6b6..379615e 100644
--- a/src/test/resources/simpleMapping.yml
+++ b/src/test/resources/simpleMapping.yml
@@ -3,4 +3,4 @@ developers:
   - rultor
   - salikjan
   - sherif
-name: eo-yaml
\ No newline at end of file
+name: "eo-yaml"
\ No newline at end of file
diff --git a/src/test/resources/streamMixed.yml b/src/test/resources/streamMixed.yml
index ff6ebdc..415449e 100644
--- a/src/test/resources/streamMixed.yml
+++ b/src/test/resources/streamMixed.yml
@@ -4,7 +4,7 @@
     - rultor
     - salikjan
     - sherif
-  name: eo-yaml
+  name: "eo-yaml"
 ---
   - yegor
   - paolo
@@ -12,4 +12,4 @@
 ---
   architect: felicia
   developer: sara
-  name: docker-java-api
\ No newline at end of file
+  name: "docker-java-api"
\ No newline at end of file
diff --git a/src/test/resources/streamOfMappings.yml b/src/test/resources/streamOfMappings.yml
index 3251925..9e18f98 100644
--- a/src/test/resources/streamOfMappings.yml
+++ b/src/test/resources/streamOfMappings.yml
@@ -4,13 +4,13 @@
     - rultor
     - salikjan
     - sherif
-  name: eo-yaml
+  name: "eo-yaml"
 ---
   architect: vlad
   developers:
     - andrei
-  name: eo-json-impl
+  name: "eo-json-impl"
 ---
   architect: felicia
   developer: sara
-  name: docker-java-api
\ No newline at end of file
+  name: "docker-java-api"
\ No newline at end of file