Repository: decorators-squad/eo-yaml
Pull request #182 (2020-03-10 20:38:13)

added ReadYamlMapping.indent(int)
For #166 
Still work-in-progress. We need to at least add some tests for this method.


Patch:
diff --git a/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java b/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java
index d3f3df6..858dc32 100644
--- a/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java
+++ b/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java
@@ -168,11 +168,6 @@ final class ReadYamlMapping extends ComparableYamlMapping {
         return this.indent(0);
     }
 
-    @Override
-    public String indent(final int indentation) {
-        return this.lines.indent(indentation);
-    }
-
     /**
      * The YamlNode value associated with a String (scalar) key.
      * @param key String key.
diff --git a/src/main/java/com/amihaiemil/eoyaml/ReadYamlSequence.java b/src/main/java/com/amihaiemil/eoyaml/ReadYamlSequence.java
index 72e4ce8..09b8555 100644
--- a/src/main/java/com/amihaiemil/eoyaml/ReadYamlSequence.java
+++ b/src/main/java/com/amihaiemil/eoyaml/ReadYamlSequence.java
@@ -74,11 +74,6 @@ final class ReadYamlSequence extends ComparableYamlSequence {
         return this.indent(0);
     }
 
-    @Override
-    public String indent(final int indentation) {
-        return this.lines.indent(indentation);
-    }
-
     @Override
     public YamlMapping yamlMapping(final int index) {
         YamlMapping mapping = null;
diff --git a/src/main/java/com/amihaiemil/eoyaml/RtYamlLine.java b/src/main/java/com/amihaiemil/eoyaml/RtYamlLine.java
index eb241ee..b3ec559 100644
--- a/src/main/java/com/amihaiemil/eoyaml/RtYamlLine.java
+++ b/src/main/java/com/amihaiemil/eoyaml/RtYamlLine.java
@@ -99,7 +99,7 @@ final class RtYamlLine implements YamlLine {
     @Override
     public boolean hasNestedNode() {
         final boolean result;
-        final String specialCharacters = ":>|-";
+        final String specialCharacters = ":>|-?";
 
         final CharSequence prevLineLastChar =
             this.trimmed().substring(this.trimmed().length()-1);
diff --git a/src/main/java/com/amihaiemil/eoyaml/RtYamlMapping.java b/src/main/java/com/amihaiemil/eoyaml/RtYamlMapping.java
index 9442b97..7a12e8c 100644
--- a/src/main/java/com/amihaiemil/eoyaml/RtYamlMapping.java
+++ b/src/main/java/com/amihaiemil/eoyaml/RtYamlMapping.java
@@ -113,45 +113,6 @@ final class RtYamlMapping extends ComparableYamlMapping {
         return this.indent(0);
     }
 
-    @Override
-    public String indent(final int indentation) {
-        StringBuilder print = new StringBuilder();
-        int spaces = indentation;
-        StringBuilder indent = new StringBuilder();
-        while (spaces > 0) {
-            indent.append(" ");
-            spaces--;
-        }
-        for(final Map.Entry<YamlNode, YamlNode> entry
-            : this.mappings.entrySet()
-        ) {
-            print.append(indent);
-            YamlNode key = entry.getKey();
-            YamlNode value = entry.getValue();
-            if(key instanceof Scalar) {
-                print.append(key.toString()).append(": ");
-                if (value instanceof Scalar) {
-                    print.append(value.toString()).append("\n");
-                } else  {
-                    print
-                    .append("\n")
-                    .append(value.indent(indentation + 2))
-                        .append("\n");
-                }
-            } else {
-                print.append("?\n").append(key.indent(indentation + 2))
-                    .append("\n").append(indent).append(":\n")
-                    .append(value.indent(indentation + 2))
-                    .append("\n");
-            }
-        }
-        String printed = print.toString();
-        if(printed.length() > 0) {
-            printed = printed.substring(0, printed.length() - 1);
-        }
-        return printed;
-    }
-
     @Override
     public Set<YamlNode> keys() {
         final Set<YamlNode> keys = new TreeSet<>();
diff --git a/src/main/java/com/amihaiemil/eoyaml/RtYamlSequence.java b/src/main/java/com/amihaiemil/eoyaml/RtYamlSequence.java
index f48789a..7c122b8 100644
--- a/src/main/java/com/amihaiemil/eoyaml/RtYamlSequence.java
+++ b/src/main/java/com/amihaiemil/eoyaml/RtYamlSequence.java
@@ -102,32 +102,6 @@ final class RtYamlSequence extends ComparableYamlSequence {
         return this.indent(0);
     }
 
-    @Override
-    public String indent(final int indentation) {
-        StringBuilder print = new StringBuilder();
-        int spaces = indentation;
-        StringBuilder indent = new StringBuilder();
-        while (spaces > 0) {
-            indent.append(" ");
-            spaces--;
-        }
-        for (final YamlNode node : this.nodes) {
-            print.append(indent)
-                .append("- ");
-            if (node instanceof Scalar) {
-                print.append(node.toString()).append("\n");
-            } else  {
-                print.append("\n").append(node.indent(indentation + 2))
-                    .append("\n");
-            }
-        }
-        String printed = print.toString();
-        if(printed.length() > 0) {
-            printed = printed.substring(0, printed.length() - 1);
-        }
-        return printed;
-    }
-
     @Override
     public int size() {
         return this.nodes.size();
diff --git a/src/main/java/com/amihaiemil/eoyaml/StrictYamlSequence.java b/src/main/java/com/amihaiemil/eoyaml/StrictYamlSequence.java
index f4386b0..b153bc2 100644
--- a/src/main/java/com/amihaiemil/eoyaml/StrictYamlSequence.java
+++ b/src/main/java/com/amihaiemil/eoyaml/StrictYamlSequence.java
@@ -112,11 +112,6 @@ public final class StrictYamlSequence extends ComparableYamlSequence {
         return this.decorated.toString();
     }
 
-    @Override
-    public String indent(final int indentation) {
-        return this.decorated.indent(indentation);
-    }
-
     @Override
     public int size() {
         return this.decorated.size();
diff --git a/src/main/java/com/amihaiemil/eoyaml/YamlMapping.java b/src/main/java/com/amihaiemil/eoyaml/YamlMapping.java
index 8b8c806..cd6364c 100644
--- a/src/main/java/com/amihaiemil/eoyaml/YamlMapping.java
+++ b/src/main/java/com/amihaiemil/eoyaml/YamlMapping.java
@@ -31,6 +31,7 @@ import java.util.Set;
 
 /**
  * A Yaml mapping.
+ * @checkstyle ExecutableStatementCount (300 lines)
  * @author Mihai Andronache (amihaiemil@gmail.com)
  * @version $Id$
  * @since 1.0.0
@@ -99,4 +100,62 @@ public interface YamlMapping extends YamlNode {
      * @return Set of YamlNode keys.
      */
     Set<YamlNode> keys();
+
+    /**
+     * Indent this YamlMapping. This is a default method since indentation
+     * logic should be identical for any kind of YamlMapping, regardless of
+     * its implementation.
+     * @param indentation Indentation to start with. Usually, it's 0, since we
+     *  don't want to have spaces at the beginning. But in the case of nested
+     *  YamlNodes, this value may be > 0.
+     * @return String indented YamlMapping, by the specified indentation.
+     */
+    default String indent(final int indentation) {
+        if(indentation < 0) {
+            throw new IllegalArgumentException(
+                "Indentation level has to be >=0"
+            );
+        }
+        final StringBuilder print = new StringBuilder();
+        int spaces = indentation;
+        final StringBuilder indent = new StringBuilder();
+        while (spaces > 0) {
+            indent.append(" ");
+            spaces--;
+        }
+        for(final YamlNode key : this.keys()) {
+            print.append(indent);
+            final YamlNode value = this.value(key);
+            if(key instanceof Scalar) {
+                print.append(key.toString()).append(": ");
+                if (value instanceof Scalar) {
+                    print.append(value.toString()).append("\n");
+                } else  {
+                    print
+                        .append("\n")
+                        .append(value.indent(indentation + 2))
+                        .append("\n");
+                }
+            } else {
+                print
+                    .append("?\n")
+                    .append(key.indent(indentation + 2)).append("\n")
+                    .append(indent).append(":");
+                if(value instanceof Scalar) {
+                    print
+                        .append(" ").append(value);
+                } else {
+                    print
+                        .append("\n")
+                        .append(value.indent(indentation + 2));
+                }
+                print.append("\n");
+            }
+        }
+        String printed = print.toString();
+        if(printed.length() > 0) {
+            printed = printed.substring(0, printed.length() - 1);
+        }
+        return printed;
+    }
 }
diff --git a/src/main/java/com/amihaiemil/eoyaml/YamlSequence.java b/src/main/java/com/amihaiemil/eoyaml/YamlSequence.java
index 8fd9066..b62dd4f 100644
--- a/src/main/java/com/amihaiemil/eoyaml/YamlSequence.java
+++ b/src/main/java/com/amihaiemil/eoyaml/YamlSequence.java
@@ -71,4 +71,43 @@ public interface YamlSequence extends YamlNode, Iterable<YamlNode> {
      * @return Iterator of YamlNode.
      */
     Iterator<YamlNode> iterator();
+    
+    /**
+     * Indent this YamlSequence. This is a default method since indentation
+     * logic should be identical for any kind of YamlSequence, regardless of
+     * its implementation.
+     * @param indentation Indentation to start with. Usually, it's 0, since we
+     *  don't want to have spaces at the beginning. But in the case of nested
+     *  YamlNodes, this value may be > 0.
+     * @return String indented YamlSequence, by the specified indentation.
+     */
+    default String indent(final int indentation) {
+        if(indentation < 0) {
+            throw new IllegalArgumentException(
+                "Indentation level has to be >=0"
+            );
+        }
+        final StringBuilder print = new StringBuilder();
+        int spaces = indentation;
+        final StringBuilder indent = new StringBuilder();
+        while (spaces > 0) {
+            indent.append(" ");
+            spaces--;
+        }
+        for (final YamlNode node : this.values()) {
+            print.append(indent)
+                .append("- ");
+            if (node instanceof Scalar) {
+                print.append(node.toString()).append("\n");
+            } else  {
+                print.append("\n").append(node.indent(indentation + 2))
+                    .append("\n");
+            }
+        }
+        String printed = print.toString();
+        if(printed.length() > 0) {
+            printed = printed.substring(0, printed.length() - 1);
+        }
+        return printed;
+    }
 }


Test patch:
diff --git a/src/test/java/com/amihaiemil/eoyaml/ReadYamlMappingTest.java b/src/test/java/com/amihaiemil/eoyaml/ReadYamlMappingTest.java
index 295492d..017c76d 100644
--- a/src/test/java/com/amihaiemil/eoyaml/ReadYamlMappingTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/ReadYamlMappingTest.java
@@ -60,7 +60,7 @@ public final class ReadYamlMappingTest {
         lines.add(new RtYamlLine("  fifth: values", 3));
         lines.add(new RtYamlLine("third: something", 4));
         final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
-        System.out.println(map);
+        System.out.print(map);
         final YamlMapping second = map.yamlMapping("second");
         MatcherAssert.assertThat(second, Matchers.notNullValue());
         MatcherAssert.assertThat(
@@ -176,7 +176,8 @@ public final class ReadYamlMappingTest {
         lines.add(new RtYamlLine(": simpleValue", 12));
         
         final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
-        final Collection<YamlNode> children = map.values();
+        System.out.print(map);
+        final Collection<YamlNode> children = map.children();
         MatcherAssert.assertThat(
             children, Matchers.iterableWithSize(5)
         );
@@ -276,7 +277,8 @@ public final class ReadYamlMappingTest {
         lines.add(new RtYamlLine(": value", 4));
         lines.add(new RtYamlLine("second: something", 6));
         final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
-        System.out.println(map);
+        System.out.print(map);
+        System.out.println(">>>");
         final String value = map.string(key);
         MatcherAssert.assertThat(value, Matchers.notNullValue());
         MatcherAssert.assertThat(value, Matchers.equalTo("value"));
@@ -479,7 +481,8 @@ public final class ReadYamlMappingTest {
         lines.add(new RtYamlLine(" - sequence", 6));
         lines.add(new RtYamlLine("second: something", 7));
         final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
-        
+        System.out.print(map);
+        System.out.println(">>>");
         MatcherAssert.assertThat(map.string(key), Matchers.nullValue());
     }
     
diff --git a/src/test/java/com/amihaiemil/eoyaml/RtYamlInputTest.java b/src/test/java/com/amihaiemil/eoyaml/RtYamlInputTest.java
index b9ae4a3..06d1cf8 100644
--- a/src/test/java/com/amihaiemil/eoyaml/RtYamlInputTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/RtYamlInputTest.java
@@ -93,6 +93,78 @@ public final class RtYamlInputTest {
             read, Matchers.equalTo(expected)
         );
     }
+    
+    /**
+     * RtYamlnput can read and indent a complex mapping.
+     * @throws Exception If something goes wrong.
+     */
+    @Test
+    public void readsAndIndentsComplexMapping() throws Exception {
+        YamlMapping expected = Yaml.createYamlMappingBuilder()
+                .add("first", "value1")
+                .add("second", "value2")
+                .add("third",
+                    Yaml.createYamlSequenceBuilder()
+                        .add("singleElementSequence")
+                        .build()
+                ).add(
+                    Yaml.createYamlSequenceBuilder()
+                        .add("sequence")
+                        .add("key")
+                        .build(),
+                    "scalar"
+                ).add(
+                    Yaml.createYamlMappingBuilder()
+                        .add("map", "asKey")
+                        .add("map1", "asKey2")
+                        .build(),
+                    Yaml.createYamlMappingBuilder()
+                        .add("someMapping",  "value")
+                        .build()
+                )
+                .build();
+        System.out.println(expected);
+        YamlMapping actual = new RtYamlInput(
+            new FileInputStream(
+                new File("src/test/resources/indentedComplexMapping.yml")
+            )
+        ).readYamlMapping();
+        MatcherAssert.assertThat(expected, Matchers.equalTo(actual));
+    }
+    
+    /**
+     * RtYamlnput can read and indent a complex sequence.
+     * @throws Exception If something goes wrong.
+     */
+    @Test
+    public void readsAndIndentsComplexSequence() throws Exception {
+        final YamlSequence expected = Yaml.createYamlSequenceBuilder()
+            .add("amihaiemil")
+            .add("salikjan")
+            .add(
+                Yaml.createYamlSequenceBuilder()
+                    .add("element1")
+                    .add("element2")
+                    .add("element3")
+                    .build()
+            )
+            .add(
+                Yaml.createYamlMappingBuilder()
+                    .add("rule1", "test")
+                    .add("rule2", "test2")
+                    .add("rule3", "test3")
+                    .build()
+            )
+            .build();
+        final YamlSequence actual = new RtYamlInput(
+            new FileInputStream(
+                new File("src/test/resources/complexSequence.yml")
+            )
+        ).readYamlSequence();
+        MatcherAssert.assertThat(
+            actual.indent(0), Matchers.equalTo(expected.indent(0))
+        );
+    }
 
     /**
      * A YamlSequence in block style can be read.
diff --git a/src/test/resources/indentedComplexMapping.yml b/src/test/resources/indentedComplexMapping.yml
new file mode 100644
index 0000000..34ef6a1
--- /dev/null
+++ b/src/test/resources/indentedComplexMapping.yml
@@ -0,0 +1,13 @@
+first: value1
+second: value2
+third: 
+  - singleElementSequence
+?
+  - sequence
+  - key
+: scalar
+?
+  map: asKey
+  map1: asKey2
+:
+  someMapping: value
\ No newline at end of file