Repository: decorators-squad/eo-yaml
Pull request #362 (2020-06-17 19:21:43)

guessIndentation flag for YamlInput
PR for #361 

* All the ``Yaml.createYamlInput(...)`` methods have been overriden to accept the boolean flag ``guessIndentation`` -- if this flag is set to true, we will try to "guess" the correct indentation ourselves (i.e. instead of throwing an exception, we will set the expected indentation for each misplaced line).

* TODO: edit the README/Wiki to reflect this change.


Patch:
diff --git a/src/main/java/com/amihaiemil/eoyaml/AllYamlLines.java b/src/main/java/com/amihaiemil/eoyaml/AllYamlLines.java
index 6b8e12c..2067a51 100644
--- a/src/main/java/com/amihaiemil/eoyaml/AllYamlLines.java
+++ b/src/main/java/com/amihaiemil/eoyaml/AllYamlLines.java
@@ -29,6 +29,7 @@ package com.amihaiemil.eoyaml;
 
 import com.amihaiemil.eoyaml.exceptions.YamlReadingException;
 import java.util.Collection;
+import java.util.Iterator;
 
 /**
  * YamlLines default implementation. "All" refers to the fact that
@@ -72,11 +73,14 @@ final class AllYamlLines implements YamlLines {
     }
 
     @Override
-    public YamlNode toYamlNode(final YamlLine prev) {
+    public YamlNode toYamlNode(
+        final YamlLine prev,
+        final boolean guessIndentation
+    ) {
         final YamlNode node;
         final String prevLine = prev.trimmed();
         if(prevLine.isEmpty()) {
-            node = this.mappingSequenceOrPlainScalar(prev);
+            node = this.mappingSequenceOrPlainScalar(prev, guessIndentation);
         } else {
             final String lastChar = prevLine.substring(prevLine.length() - 1);
 
@@ -85,21 +89,33 @@ final class AllYamlLines implements YamlLines {
             } else if (lastChar.equals(Follows.FOLDED_BLOCK_SCALAR)) {
                 node = new ReadFoldedBlockScalar(prev, this);
             } else if (prevLine.matches(Follows.FOLDED_SEQUENCE)) {
-                node = new ReadYamlSequence(prev, this);
+                node = new ReadYamlSequence(prev, this, guessIndentation);
             } else {
-                node = this.mappingSequenceOrPlainScalar(prev);
+                node = this.mappingSequenceOrPlainScalar(
+                    prev, guessIndentation
+                );
             }
         }
         return node;
     }
 
+    @Override
+    public Iterator<YamlLine> iterator() {
+        return this.lines.iterator();
+    }
+
     /**
      * Try to figure out what YAML node (mapping, sequence or scalar) is found
      * after the given line.
      * @param prev YamlLine just previous to the node we're trying to find.
+     * @param guessIndentation If true, we will guess the correct indentation,
+     *  if any YAML line is misplaced.
      * @return Found YamlNode.
      */
-    private YamlNode mappingSequenceOrPlainScalar(final YamlLine prev) {
+    private YamlNode mappingSequenceOrPlainScalar(
+        final YamlLine prev,
+        final boolean guessIndentation
+    ) {
         final YamlNode node;
         final YamlLine first = new Skip(
             this,
@@ -111,13 +127,12 @@ final class AllYamlLines implements YamlLines {
             line -> line.trimmed().startsWith("!!")
         ).iterator().next();
         if (first.trimmed().startsWith("-")){
-            node = new ReadYamlSequence(prev, this);
+            node = new ReadYamlSequence(prev, this, guessIndentation);
         } else if(first.trimmed().contains(":")) {
-            node = new ReadYamlMapping(prev, this);
+            node = new ReadYamlMapping(prev, this, guessIndentation);
         } else if(this.original().size() == 1) {
             node = new ReadPlainScalar(this, first);
         } else {
-            System.out.println("LINE IS: [" + first.trimmed() + "]");
             throw new YamlReadingException(
                 "Could not parse YAML starting at line " + (first.number() + 1)
                 + " . It should be a sequence (line should start with '-'), "
diff --git a/src/main/java/com/amihaiemil/eoyaml/Backwards.java b/src/main/java/com/amihaiemil/eoyaml/Backwards.java
index cb174ed..02d2695 100644
--- a/src/main/java/com/amihaiemil/eoyaml/Backwards.java
+++ b/src/main/java/com/amihaiemil/eoyaml/Backwards.java
@@ -56,8 +56,11 @@ final class Backwards implements YamlLines {
     }
 
     @Override
-    public YamlNode toYamlNode(final YamlLine prev) {
-        return this.lines.toYamlNode(prev);
+    public YamlNode toYamlNode(
+        final YamlLine prev,
+        final boolean guessIndentation
+    ) {
+        return this.lines.toYamlNode(prev, guessIndentation);
     }
 
     @Override
diff --git a/src/main/java/com/amihaiemil/eoyaml/FirstCommentFound.java b/src/main/java/com/amihaiemil/eoyaml/FirstCommentFound.java
index 47d3e7a..18aaaed 100644
--- a/src/main/java/com/amihaiemil/eoyaml/FirstCommentFound.java
+++ b/src/main/java/com/amihaiemil/eoyaml/FirstCommentFound.java
@@ -106,7 +106,10 @@ final class FirstCommentFound implements YamlLines {
     }
 
     @Override
-    public YamlNode toYamlNode(final YamlLine prev) {
-        return this.lines.toYamlNode(prev);
+    public YamlNode toYamlNode(
+        final YamlLine prev,
+        final boolean guessIndentation
+    ) {
+        return this.lines.toYamlNode(prev, guessIndentation);
     }
 }
diff --git a/src/main/java/com/amihaiemil/eoyaml/GreaterIndentation.java b/src/main/java/com/amihaiemil/eoyaml/GreaterIndentation.java
index f4d667a..107b69b 100644
--- a/src/main/java/com/amihaiemil/eoyaml/GreaterIndentation.java
+++ b/src/main/java/com/amihaiemil/eoyaml/GreaterIndentation.java
@@ -96,7 +96,10 @@ final class GreaterIndentation implements YamlLines {
     }
 
     @Override
-    public YamlNode toYamlNode(final YamlLine prev) {
-        return this.yamlLines.toYamlNode(prev);
+    public YamlNode toYamlNode(
+        final YamlLine prev,
+        final boolean guessIndentation
+    ) {
+        return this.yamlLines.toYamlNode(prev, guessIndentation);
     }
 }
diff --git a/src/main/java/com/amihaiemil/eoyaml/Indented.java b/src/main/java/com/amihaiemil/eoyaml/Indented.java
new file mode 100644
index 0000000..053a3c6
--- /dev/null
+++ b/src/main/java/com/amihaiemil/eoyaml/Indented.java
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2016-2020, Mihai Emil Andronache
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ *  list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright notice,
+ *  this list of conditions and the following disclaimer in the documentation
+ *  and/or other materials provided with the distribution.
+ * Neither the name of the copyright holder nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+package com.amihaiemil.eoyaml;
+
+/**
+ * An YAML Line indented by us. We override the line's
+ * initial indentation with a given value.
+ * @author Mihai Andronache (amihaiemil@gmail.com)
+ * @version $Id$
+ * @since 5.1.0
+ */
+final class Indented implements YamlLine {
+
+    /**
+     * Original YAML line.
+     */
+    private final YamlLine original;
+
+    /**
+     * Given indentation.
+     */
+    private int indentation;
+
+    /**
+     * Ctor.
+     * @param original Original YamlLine.
+     * @param indentation Given indentation.
+     */
+    Indented(final YamlLine original, final int indentation) {
+        this.original = original;
+        this.indentation = indentation;
+    }
+
+    @Override
+    public String trimmed() {
+        return this.original.trimmed();
+    }
+
+    @Override
+    public String comment() {
+        return this.original.comment();
+    }
+
+    @Override
+    public int number() {
+        return this.original.number();
+    }
+
+    @Override
+    public int indentation() {
+        return this.indentation;
+    }
+
+    @Override
+    public boolean requireNestedIndentation() {
+        return this.original.requireNestedIndentation();
+    }
+
+    @Override
+    public int compareTo(final YamlLine other) {
+        return this.original.compareTo(other);
+    }
+}
diff --git a/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java b/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java
index f884e0e..4e0ec42 100644
--- a/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java
+++ b/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java
@@ -68,12 +68,31 @@ final class ReadYamlMapping extends BaseYamlMapping {
      */
     private final YamlLines significant;
 
+    /**
+     * If set to true we will try to guess the correct indentation
+     * of misplaced lines.
+     */
+    private final boolean guessIndentation;
+
     /**
      * Ctor.
      * @param lines Given lines.
      */
     ReadYamlMapping(final AllYamlLines lines) {
-        this(new YamlLine.NullYamlLine(), lines);
+        this(lines, Boolean.FALSE);
+    }
+
+    /**
+     * Ctor.
+     * @param lines Given lines.
+     * @param guessIndentation If true, we will try to guess the correct
+     *  indentation of misplaced lines.
+     */
+    ReadYamlMapping(
+        final AllYamlLines lines,
+        final boolean guessIndentation
+    ) {
+        this(new YamlLine.NullYamlLine(), lines, guessIndentation);
     }
 
     /**
@@ -82,6 +101,21 @@ final class ReadYamlMapping extends BaseYamlMapping {
      * @param lines Given lines.
      */
     ReadYamlMapping(final YamlLine previous, final AllYamlLines lines) {
+        this(previous, lines, Boolean.FALSE);
+    }
+
+    /**
+     * Ctor.
+     * @param previous Line just before the start of this mapping.
+     * @param lines Given lines.
+     * @param guessIndentation If true, we will try to guess the correct
+     *  indentation of misplaced lines.
+     */
+    ReadYamlMapping(
+        final YamlLine previous,
+        final AllYamlLines lines,
+        final boolean guessIndentation
+    ) {
         this.previous = previous;
         this.all = lines;
         this.significant = new SameIndentationLevel(
@@ -94,9 +128,11 @@ final class ReadYamlMapping extends BaseYamlMapping {
                     line -> line.trimmed().startsWith("..."),
                     line -> line.trimmed().startsWith("%"),
                     line -> line.trimmed().startsWith("!!")
-                )
+                ),
+                guessIndentation
             )
         );
+        this.guessIndentation = guessIndentation;
     }
 
     @Override
@@ -111,7 +147,9 @@ final class ReadYamlMapping extends BaseYamlMapping {
             ) {
                 continue;
             } else if ("?".equals(trimmed)) {
-                keys.add(this.significant.toYamlNode(line));
+                keys.add(
+                    this.significant.toYamlNode(line, this.guessIndentation)
+                );
             } else {
                 if(!trimmed.contains(":")) {
                     continue;
@@ -201,7 +239,9 @@ final class ReadYamlMapping extends BaseYamlMapping {
                     || trimmed.matches("^" + tryKey + "\\:[ ]*\\>$")
                     || trimmed.matches("^" + tryKey + "\\:[ ]*\\|$")
                 ) {
-                    value = this.significant.toYamlNode(line);
+                    value = this.significant.toYamlNode(
+                        line, this.guessIndentation
+                    );
                 } else if((trimmed.startsWith(tryKey + ":")
                     || trimmed.startsWith("- " + tryKey + ":"))
                     && trimmed.length() > 1
@@ -229,14 +269,18 @@ final class ReadYamlMapping extends BaseYamlMapping {
             final YamlLine line = linesIt.next();
             final String trimmed = line.trimmed();
             if("?".equals(trimmed)) {
-                final YamlNode keyNode = this.significant.toYamlNode(line);
+                final YamlNode keyNode = this.significant.toYamlNode(
+                    line, this.guessIndentation
+                );
                 if(keyNode.equals(key)) {
                     final YamlLine colonLine = linesIt.next();
                     if(":".equals(colonLine.trimmed())
                         || colonLine.trimmed().matches("^\\:[ ]*\\>$")
                         || colonLine.trimmed().matches("^\\:[ ]*\\|$")
                     ) {
-                        value = this.significant.toYamlNode(colonLine);
+                        value = this.significant.toYamlNode(
+                            colonLine, this.guessIndentation
+                        );
                     } else if(colonLine.trimmed().startsWith(":")
                         && (colonLine.trimmed().length() > 1)
                     ){
diff --git a/src/main/java/com/amihaiemil/eoyaml/ReadYamlSequence.java b/src/main/java/com/amihaiemil/eoyaml/ReadYamlSequence.java
index 7761b4e..9a0c947 100644
--- a/src/main/java/com/amihaiemil/eoyaml/ReadYamlSequence.java
+++ b/src/main/java/com/amihaiemil/eoyaml/ReadYamlSequence.java
@@ -64,12 +64,31 @@ final class ReadYamlSequence extends BaseYamlSequence {
      */
     private final YamlLines significant;
 
+    /**
+     * If set to true we will try to guess the correct indentation
+     * of misplaced lines.
+     */
+    private final boolean guessIndentation;
+
     /**
      * Ctor.
      * @param lines Given lines.
      */
     ReadYamlSequence(final AllYamlLines lines) {
-        this(new YamlLine.NullYamlLine(), lines);
+        this(lines, false);
+    }
+
+    /**
+     * Ctor.
+     * @param lines Given lines.
+     * @param guessIndentation If set to true, we will try to
+     *  guess the correct indentation of misplaced lines.
+     */
+    ReadYamlSequence(
+        final AllYamlLines lines,
+        final boolean guessIndentation
+    ) {
+        this(new YamlLine.NullYamlLine(), lines, guessIndentation);
     }
 
     /**
@@ -78,6 +97,21 @@ final class ReadYamlSequence extends BaseYamlSequence {
      * @param lines Given lines.
      */
     ReadYamlSequence(final YamlLine previous, final AllYamlLines lines) {
+        this(previous, lines, false);
+    }
+
+    /**
+     * Ctor.
+     * @param previous Line just before the start of this sequence.
+     * @param lines Given lines.
+     * @param guessIndentation If set to true, we will try to guess the
+     *  correct indentation of misplaced lines.
+     */
+    ReadYamlSequence(
+        final YamlLine previous,
+        final AllYamlLines lines,
+        final boolean guessIndentation
+    ) {
         this.previous = previous;
         this.all = lines;
         this.significant = new SameIndentationLevel(
@@ -90,9 +124,11 @@ final class ReadYamlSequence extends BaseYamlSequence {
                     line -> line.trimmed().startsWith("..."),
                     line -> line.trimmed().startsWith("%"),
                     line -> line.trimmed().startsWith("!!")
-                )
+                ),
+                guessIndentation
             )
         );
+        this.guessIndentation = guessIndentation;
     }
 
     @Override
@@ -108,15 +144,18 @@ final class ReadYamlSequence extends BaseYamlSequence {
                     || trimmed.endsWith("|")
                     || trimmed.endsWith(">")
                 ) {
-                    kids.add(this.significant.toYamlNode(line));
+                    kids.add(
+                        this.significant.toYamlNode(
+                            line, this.guessIndentation
+                        )
+                    );
                 } else {
                     if(trimmed.matches("^.*\\-.*\\:.*$")) {
                         kids.add(
                             new ReadYamlMapping(
-                                new RtYamlLine(
-                                    "# Mapping at dash line", line.number()-1
-                                ),
-                                this.all
+                                new RtYamlLine("", line.number()-1),
+                                this.all,
+                                this.guessIndentation
                             )
                         );
                     } else {
diff --git a/src/main/java/com/amihaiemil/eoyaml/ReadYamlStream.java b/src/main/java/com/amihaiemil/eoyaml/ReadYamlStream.java
index 6872c52..8cdc558 100644
--- a/src/main/java/com/amihaiemil/eoyaml/ReadYamlStream.java
+++ b/src/main/java/com/amihaiemil/eoyaml/ReadYamlStream.java
@@ -49,11 +49,27 @@ final class ReadYamlStream extends BaseYamlStream {
      */
     private final YamlLines startMarkers;
 
+    /**
+     * If set to true we will try to guess the correct indentation
+     * of misplaced lines.
+     */
+    private final boolean guessIndentation;
+
     /**
      * Constructor.
      * @param lines All YAML lines as they are read from the input.
      */
     ReadYamlStream(final AllYamlLines lines) {
+        this(lines, false);
+    }
+
+    /**
+     * Constructor.
+     * @param lines All YAML lines as they are read from the input.
+     * @param guessIndentation If set to true, we will try to guess
+     *  the correct indentation of misplaced lines.
+     */
+    ReadYamlStream(final AllYamlLines lines, final boolean guessIndentation) {
         this.startMarkers = new WellIndented(
             new StartMarkers(
                 new Skip(
@@ -68,6 +84,7 @@ final class ReadYamlStream extends BaseYamlStream {
             line -> line.trimmed().startsWith("#"),
             line -> line.trimmed().startsWith("%")
         );
+        this.guessIndentation = guessIndentation;
     }
 
     @Override
@@ -76,7 +93,11 @@ final class ReadYamlStream extends BaseYamlStream {
         for(final YamlLine startDoc : this.startMarkers) {
             final YamlLines document = this.readDocument(startDoc);
             if(!document.original().isEmpty()) {
-                values.add(document.toYamlNode(startDoc));
+                values.add(
+                    document.toYamlNode(
+                        startDoc, this.guessIndentation
+                    )
+                );
             }
         }
         return values;
diff --git a/src/main/java/com/amihaiemil/eoyaml/RtYamlInput.java b/src/main/java/com/amihaiemil/eoyaml/RtYamlInput.java
index 932c03d..8656316 100644
--- a/src/main/java/com/amihaiemil/eoyaml/RtYamlInput.java
+++ b/src/main/java/com/amihaiemil/eoyaml/RtYamlInput.java
@@ -46,29 +46,46 @@ final class RtYamlInput implements YamlInput {
     /**
      * Source of the input.
      */
-    private InputStream source;
+    private final InputStream source;
+
+    /**
+     * If set to true, we will try to guess the correct indentation
+     * of misplaced lines.
+     */
+    private final boolean guessIndentation;
 
     /**
      * Ctor.
      * @param source Given source.
      */
     RtYamlInput(final InputStream source) {
+        this(source, false);
+    }
+
+    /**
+     * Ctor.
+     * @param source Given source.
+     * @param guessIndentation If set to true, we will try to guess
+     *  the correct indentation of misplaced lines.
+     */
+    RtYamlInput(final InputStream source, final boolean guessIndentation) {
         this.source = source;
+        this.guessIndentation = guessIndentation;
     }
 
     @Override
     public YamlMapping readYamlMapping() throws IOException {
-        return new ReadYamlMapping(this.readInput());
+        return new ReadYamlMapping(this.readInput(), this.guessIndentation);
     }
 
     @Override
     public YamlSequence readYamlSequence() throws IOException {
-        return new ReadYamlSequence(this.readInput());
+        return new ReadYamlSequence(this.readInput(), this.guessIndentation);
     }
 
     @Override
     public YamlStream readYamlStream() throws IOException {
-        return new ReadYamlStream(this.readInput());
+        return new ReadYamlStream(this.readInput(), this.guessIndentation);
     }
 
     @Override
diff --git a/src/main/java/com/amihaiemil/eoyaml/SameIndentationLevel.java b/src/main/java/com/amihaiemil/eoyaml/SameIndentationLevel.java
index 0161b24..7b3abca 100644
--- a/src/main/java/com/amihaiemil/eoyaml/SameIndentationLevel.java
+++ b/src/main/java/com/amihaiemil/eoyaml/SameIndentationLevel.java
@@ -99,8 +99,11 @@ final class SameIndentationLevel implements YamlLines {
     }
 
     @Override
-    public YamlNode toYamlNode(final YamlLine prev) {
-        return this.yamlLines.toYamlNode(prev);
+    public YamlNode toYamlNode(
+        final YamlLine prev,
+        final boolean guessIndentation
+    ) {
+        return this.yamlLines.toYamlNode(prev, guessIndentation);
     }
 
 }
diff --git a/src/main/java/com/amihaiemil/eoyaml/Skip.java b/src/main/java/com/amihaiemil/eoyaml/Skip.java
index 35ec6b8..96f19a4 100644
--- a/src/main/java/com/amihaiemil/eoyaml/Skip.java
+++ b/src/main/java/com/amihaiemil/eoyaml/Skip.java
@@ -91,8 +91,11 @@ final class Skip implements YamlLines {
     }
 
     @Override
-    public YamlNode toYamlNode(final YamlLine prev) {
-        return this.yamlLines.toYamlNode(prev);
+    public YamlNode toYamlNode(
+        final YamlLine prev,
+        final boolean guessIndentation
+    ) {
+        return this.yamlLines.toYamlNode(prev, guessIndentation);
     }
 
     /**
diff --git a/src/main/java/com/amihaiemil/eoyaml/StartMarkers.java b/src/main/java/com/amihaiemil/eoyaml/StartMarkers.java
index 386e4cb..9a31687 100644
--- a/src/main/java/com/amihaiemil/eoyaml/StartMarkers.java
+++ b/src/main/java/com/amihaiemil/eoyaml/StartMarkers.java
@@ -103,7 +103,10 @@ final class StartMarkers implements YamlLines {
     }
 
     @Override
-    public YamlNode toYamlNode(final YamlLine prev) {
-        return this.yamlLines.toYamlNode(prev);
+    public YamlNode toYamlNode(
+        final YamlLine prev,
+        final boolean guessIndentation
+    ) {
+        return this.yamlLines.toYamlNode(prev, guessIndentation);
     }
 }
diff --git a/src/main/java/com/amihaiemil/eoyaml/WellIndented.java b/src/main/java/com/amihaiemil/eoyaml/WellIndented.java
index 6a5fad3..03a33a2 100644
--- a/src/main/java/com/amihaiemil/eoyaml/WellIndented.java
+++ b/src/main/java/com/amihaiemil/eoyaml/WellIndented.java
@@ -36,11 +36,6 @@ import java.util.List;
 /**
  * YamlLines decorator which iterates over them and verifies
  * that their indentation is correct.<br><br>
- * Initially, we used to do this validation at line level, right when each
- * line is being read (in {@link RtYamlInput}). However, we decided
- * to do it at YamlLines level, as a decorator, because
- * in some cases, we need to eliminate some of them first (markers,
- * directives etc). <br><br>
  *
  * This class can be used as follows:
  *
@@ -61,7 +56,9 @@ import java.util.List;
  *     )
  * );//Iterate over the lines which are at the same indentation level
  * </pre>
- *
+ * @checkstyle ExecutableStatementCount (400 lines)
+ * @checkstyle CyclomaticComplexity (400 lines)
+ * @checkstyle NestedIfDepth (400 lines)
  * @author Mihai Andronache (amihaiemil@gmail.com)
  * @version $Id$
  * @since 3.1.2
@@ -74,12 +71,31 @@ final class WellIndented implements YamlLines {
      */
     private final YamlLines yamlLines;
 
+    /**
+     * If this is true, then we will try to adjust a wrong indentation,
+     * instead of throwin an exception. This mechanism is not safe becuase
+     * the resulting YAML might not be the expected one.
+     */
+    private final boolean guessIndentation;
+
     /**
      * Ctor.
      * @param yamlLines The Yaml lines.
      */
     WellIndented(final YamlLines yamlLines) {
+        this(yamlLines, false);
+    }
+
+    /**
+     * Ctor.
+     * @param yamlLines The Yaml lines.
+     * @param guessIndentation If indentation is not correct, try to
+     *  adjust it instead of throwing an exception. This mechanism is not
+     *  safe because the resulting YAML might not be the expected one.
+     */
+    WellIndented(final YamlLines yamlLines, final boolean guessIndentation) {
         this.yamlLines = yamlLines;
+        this.guessIndentation = guessIndentation;
     }
 
     /**
@@ -108,21 +124,29 @@ final class WellIndented implements YamlLines {
                     int lineIndent = line.indentation();
                     if(previous.requireNestedIndentation()) {
                         if(lineIndent != prevIndent + 2) {
-                            throw new YamlIndentationException(
-                                "Indentation of line " + (line.number() + 1)
-                                + " is not ok. It should be greater than the one"
-                                + " of line " + (previous.number() + 1)
-                                + " by 2 spaces."
-                            );
+                            if(this.guessIndentation) {
+                                line = new Indented(line, prevIndent + 2);
+                            } else {
+                                throw new YamlIndentationException(
+                                    "Indentation of line " + (line.number() + 1)
+                                  + " is not ok. It should be greater than the one"
+                                  + " of line " + (previous.number() + 1)
+                                  + " by 2 spaces."
+                                );
+                            }
                         }
                     } else {
                         if(!"---".equals(previous.trimmed()) && lineIndent > prevIndent) {
-                            throw new YamlIndentationException(
-                                "Indentation of line " + (line.number() +1) + " is "
-                                + "greater than the one of line "
-                                + (previous.number() + 1) + ". "
-                                + "It should be less or equal."
-                            );
+                            if(this.guessIndentation) {
+                                line = new Indented(line, prevIndent);
+                            } else {
+                                throw new YamlIndentationException(
+                                    "Indentation of line " + (line.number() + 1) + " is "
+                                  + "greater than the one of line "
+                                  + (previous.number() + 1) + ". "
+                                  + "It should be less or equal."
+                                );
+                            }
                         }
                     }
                 }
@@ -139,8 +163,11 @@ final class WellIndented implements YamlLines {
     }
 
     @Override
-    public YamlNode toYamlNode(final YamlLine prev) {
-        return this.yamlLines.toYamlNode(prev);
+    public YamlNode toYamlNode(
+        final YamlLine prev,
+        final boolean guessIndent
+    ) {
+        return this.yamlLines.toYamlNode(prev, guessIndent);
     }
 
 }
diff --git a/src/main/java/com/amihaiemil/eoyaml/Yaml.java b/src/main/java/com/amihaiemil/eoyaml/Yaml.java
index 2f4f35a..7c26c46 100644
--- a/src/main/java/com/amihaiemil/eoyaml/Yaml.java
+++ b/src/main/java/com/amihaiemil/eoyaml/Yaml.java
@@ -83,7 +83,26 @@ public final class Yaml {
      */
     public static YamlInput createYamlInput(final File input)
         throws FileNotFoundException {
-        return Yaml.createYamlInput(new FileInputStream(input));
+        return Yaml.createYamlInput(input, Boolean.FALSE);
+    }
+
+    /**
+     * Create a {@link YamlInput} from a File.
+     * @return YamlInput, reader of Yaml.
+     * @param input File to read from.
+     * @param guessIndentation If set to true, we will try to guess the correct
+     *  indentation of misplaced lines. The default value is false
+     *  and an exception is thrown if indentation is not correct.
+     * @throws FileNotFoundException If the file is not found.
+     */
+    public static YamlInput createYamlInput(
+        final File input,
+        final boolean guessIndentation
+    ) throws FileNotFoundException {
+        return Yaml.createYamlInput(
+            new FileInputStream(input),
+            guessIndentation
+        );
     }
 
     /**
@@ -92,8 +111,24 @@ public final class Yaml {
      * @return YamlInput, reader of Yaml.
      */
     public static YamlInput createYamlInput(final String input) {
+        return Yaml.createYamlInput(input, Boolean.FALSE);
+    }
+
+    /**
+     * Create a {@link YamlInput} from a String.
+     * @param input String to read from.
+     * @param guessIndentation If set to true, we will try to guess the correct
+     *  indentation of misplaced lines. The default value is false
+     *  and an exception is thrown if indentation is not correct.
+     * @return YamlInput, reader of Yaml.
+     */
+    public static YamlInput createYamlInput(
+        final String input,
+        final boolean guessIndentation
+    ) {
         return Yaml.createYamlInput(
-            new ByteArrayInputStream(input.getBytes())
+            new ByteArrayInputStream(input.getBytes()),
+            guessIndentation
         );
     }
 
@@ -103,7 +138,22 @@ public final class Yaml {
      * @return YamlInput, reader of Yaml.
      */
     public static YamlInput createYamlInput(final InputStream input) {
-        return new RtYamlInput(input);
+        return Yaml.createYamlInput(input, Boolean.FALSE);
+    }
+
+    /**
+     * Create a {@link YamlInput} from an InputStream.
+     * @param input InputStream to read from.
+     * @param guessIndentation If set to true, we will try to guess the correct
+     *  indentation of misplaced lines. The default value is false
+     *  and an exception is thrown if indentation is not correct.
+     * @return YamlInput, reader of Yaml.
+     */
+    public static YamlInput createYamlInput(
+        final InputStream input,
+        final boolean guessIndentation
+    ) {
+        return new RtYamlInput(input, guessIndentation);
     }
 
     /**
diff --git a/src/main/java/com/amihaiemil/eoyaml/YamlLines.java b/src/main/java/com/amihaiemil/eoyaml/YamlLines.java
index bf79eb5..3ca17cb 100644
--- a/src/main/java/com/amihaiemil/eoyaml/YamlLines.java
+++ b/src/main/java/com/amihaiemil/eoyaml/YamlLines.java
@@ -50,18 +50,18 @@ interface YamlLines extends Iterable<YamlLine> {
     /**
      * Turn these lines into a YamlNode.
      * @param prev Previous YamlLine
+     * @param guessIndentation If set to true, we will try to guess
+     *  the correct indentation of misplaced lines.
      * @return YamlNode
      */
-    YamlNode toYamlNode(final YamlLine prev);
+    YamlNode toYamlNode(final YamlLine prev, final boolean guessIndentation);
 
     /**
      * Default iterator which doesn't skip any line,
      * iterates over all of them.
      * @return Iterator of YamlLine.
      */
-    default Iterator<YamlLine> iterator() {
-        return this.original().iterator();
-    }
+    Iterator<YamlLine> iterator();
 
     /**
      * Get a certain YamlLine.


Test patch:
diff --git a/src/test/java/com/amihaiemil/eoyaml/AllYamlLinesTest.java b/src/test/java/com/amihaiemil/eoyaml/AllYamlLinesTest.java
index d6bc24a..e5868de 100644
--- a/src/test/java/com/amihaiemil/eoyaml/AllYamlLinesTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/AllYamlLinesTest.java
@@ -79,7 +79,10 @@ public final class AllYamlLinesTest {
         lines.add(new RtYamlLine("line3", 3));
         final YamlLines yamlLines = new AllYamlLines(lines);
         MatcherAssert.assertThat(
-            yamlLines.toYamlNode(new RtYamlLine("literalScalar:|", 0)),
+            yamlLines.toYamlNode(
+                new RtYamlLine("literalScalar:|", 0),
+                false
+            ),
             Matchers.instanceOf(ReadLiteralBlockScalar.class)
         );
     }
@@ -96,7 +99,10 @@ public final class AllYamlLinesTest {
         lines.add(new RtYamlLine("of text", 3));
         final YamlLines yamlLines = new AllYamlLines(lines);
         MatcherAssert.assertThat(
-            yamlLines.toYamlNode(new RtYamlLine("foldedScalar:>", 0)),
+            yamlLines.toYamlNode(
+                new RtYamlLine("foldedScalar:>", 0),
+                false
+            ),
             Matchers.instanceOf(ReadFoldedBlockScalar.class)
         );
     }
@@ -113,7 +119,7 @@ public final class AllYamlLinesTest {
         lines.add(new RtYamlLine("value3", 3));
         final YamlLines yamlLines = new AllYamlLines(lines);
         final YamlNode seq =  yamlLines.toYamlNode(
-            new RtYamlLine("foldedSequence:|-", 0)
+            new RtYamlLine("foldedSequence:|-", 0), false
         );
         MatcherAssert.assertThat(
             seq, Matchers.instanceOf(ReadYamlSequence.class)
@@ -150,7 +156,7 @@ public final class AllYamlLinesTest {
         lines.add(new RtYamlLine("value3", 3));
         final YamlLines yamlLines = new AllYamlLines(lines);
         final YamlNode seq =  yamlLines.toYamlNode(
-            new RtYamlLine("foldedSequence:| -", 0)
+            new RtYamlLine("foldedSequence:| -", 0), false
         );
         MatcherAssert.assertThat(
             seq, Matchers.instanceOf(ReadYamlSequence.class)
@@ -185,7 +191,7 @@ public final class AllYamlLinesTest {
         lines.add(new RtYamlLine("for: test", 2));
         final YamlLines yamlLines = new AllYamlLines(lines);
         MatcherAssert.assertThat(
-            yamlLines.toYamlNode(new RtYamlLine("---", 0)),
+            yamlLines.toYamlNode(new RtYamlLine("---", 0), false),
             Matchers.instanceOf(ReadYamlMapping.class)
         );
     }
@@ -201,7 +207,7 @@ public final class AllYamlLinesTest {
         lines.add(new RtYamlLine("- sequence", 2));
         final YamlLines yamlLines = new AllYamlLines(lines);
         MatcherAssert.assertThat(
-            yamlLines.toYamlNode(new RtYamlLine("?", 0)),
+            yamlLines.toYamlNode(new RtYamlLine("?", 0), false),
             Matchers.instanceOf(ReadYamlSequence.class)
         );
     }
@@ -216,7 +222,7 @@ public final class AllYamlLinesTest {
         lines.add(new RtYamlLine("justAScalar", 1));
         final YamlLines yamlLines = new AllYamlLines(lines);
         MatcherAssert.assertThat(
-            yamlLines.toYamlNode(new RtYamlLine("---", 0)),
+            yamlLines.toYamlNode(new RtYamlLine("---", 0), false),
             Matchers.instanceOf(ReadPlainScalar.class)
         );
     }
@@ -237,7 +243,7 @@ public final class AllYamlLinesTest {
         lines.add(new RtYamlLine("a folded or literal scalar", 4));
         final YamlLines yamlLines = new AllYamlLines(lines);
         try {
-            yamlLines.toYamlNode(new RtYamlLine("---", -1));
+            yamlLines.toYamlNode(new RtYamlLine("---", -1), false);
             Assert.fail("Expected IllegalStateException!");
         } catch (final YamlReadingException ex) {
             final String message = ex.getMessage();
diff --git a/src/test/java/com/amihaiemil/eoyaml/BackwardsTest.java b/src/test/java/com/amihaiemil/eoyaml/BackwardsTest.java
index 5fc605f..717ea66 100644
--- a/src/test/java/com/amihaiemil/eoyaml/BackwardsTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/BackwardsTest.java
@@ -67,9 +67,9 @@ public final class BackwardsTest {
         final YamlLines initial = Mockito.mock(YamlLines.class);
         final YamlLine prev = Mockito.mock(YamlLine.class);
         final YamlNode node = Mockito.mock(YamlNode.class);
-        Mockito.when(initial.toYamlNode(prev)).thenReturn(node);
+        Mockito.when(initial.toYamlNode(prev, false)).thenReturn(node);
         MatcherAssert.assertThat(
-            new Backwards(initial).toYamlNode(prev),
+            new Backwards(initial).toYamlNode(prev, false),
             Matchers.is(node)
         );
     }
diff --git a/src/test/java/com/amihaiemil/eoyaml/FirstCommentFoundTest.java b/src/test/java/com/amihaiemil/eoyaml/FirstCommentFoundTest.java
index 22d57c4..e310e70 100644
--- a/src/test/java/com/amihaiemil/eoyaml/FirstCommentFoundTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/FirstCommentFoundTest.java
@@ -66,9 +66,9 @@ public final class FirstCommentFoundTest {
         final YamlLines initial = Mockito.mock(YamlLines.class);
         final YamlLine prev = Mockito.mock(YamlLine.class);
         final YamlNode node = Mockito.mock(YamlNode.class);
-        Mockito.when(initial.toYamlNode(prev)).thenReturn(node);
+        Mockito.when(initial.toYamlNode(prev, false)).thenReturn(node);
         MatcherAssert.assertThat(
-            new FirstCommentFound(initial).toYamlNode(prev),
+            new FirstCommentFound(initial).toYamlNode(prev, false),
             Matchers.is(node)
         );
     }
diff --git a/src/test/java/com/amihaiemil/eoyaml/SkipTest.java b/src/test/java/com/amihaiemil/eoyaml/SkipTest.java
index 13f54dd..f85ab79 100644
--- a/src/test/java/com/amihaiemil/eoyaml/SkipTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/SkipTest.java
@@ -167,9 +167,9 @@ public final class SkipTest {
         final YamlLines initial = Mockito.mock(YamlLines.class);
         final YamlLine prev = Mockito.mock(YamlLine.class);
         final YamlNode node = Mockito.mock(YamlNode.class);
-        Mockito.when(initial.toYamlNode(prev)).thenReturn(node);
+        Mockito.when(initial.toYamlNode(prev, false)).thenReturn(node);
         MatcherAssert.assertThat(
-            new Skip(initial).toYamlNode(prev),
+            new Skip(initial).toYamlNode(prev, false),
             Matchers.is(node)
         );
     }
diff --git a/src/test/java/com/amihaiemil/eoyaml/StartMarkersTest.java b/src/test/java/com/amihaiemil/eoyaml/StartMarkersTest.java
index c7e2009..2d1c904 100644
--- a/src/test/java/com/amihaiemil/eoyaml/StartMarkersTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/StartMarkersTest.java
@@ -68,9 +68,9 @@ public final class StartMarkersTest {
         final YamlLines lines = Mockito.mock(YamlLines.class);
         final YamlLine prev = Mockito.mock(YamlLine.class);
         final YamlNode result = Mockito.mock(YamlNode.class);
-        Mockito.when(lines.toYamlNode(prev)).thenReturn(result);
+        Mockito.when(lines.toYamlNode(prev, false)).thenReturn(result);
         MatcherAssert.assertThat(
-            new StartMarkers(lines).toYamlNode(prev),
+            new StartMarkers(lines).toYamlNode(prev, false),
             Matchers.is(result)
         );
     }
diff --git a/src/test/java/com/amihaiemil/eoyaml/WellIndentedTest.java b/src/test/java/com/amihaiemil/eoyaml/WellIndentedTest.java
index 9d61a6d..35b6bea 100644
--- a/src/test/java/com/amihaiemil/eoyaml/WellIndentedTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/WellIndentedTest.java
@@ -70,9 +70,9 @@ public final class WellIndentedTest {
         final YamlLines lines = Mockito.mock(YamlLines.class);
         final YamlLine prev = Mockito.mock(YamlLine.class);
         final YamlNode result = Mockito.mock(YamlNode.class);
-        Mockito.when(lines.toYamlNode(prev)).thenReturn(result);
+        Mockito.when(lines.toYamlNode(prev, false)).thenReturn(result);
         MatcherAssert.assertThat(
-            new WellIndented(lines).toYamlNode(prev),
+            new WellIndented(lines).toYamlNode(prev, false),
             Matchers.is(result)
         );
     }
diff --git a/src/test/java/com/amihaiemil/eoyaml/YamlIndentationTestCase.java b/src/test/java/com/amihaiemil/eoyaml/YamlIndentationTestCase.java
new file mode 100644
index 0000000..2803f5e
--- /dev/null
+++ b/src/test/java/com/amihaiemil/eoyaml/YamlIndentationTestCase.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright (c) 2016-2020, Mihai Emil Andronache
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ *  list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright notice,
+ *  this list of conditions and the following disclaimer in the documentation
+ *  and/or other materials provided with the distribution.
+ * Neither the name of the copyright holder nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+package com.amihaiemil.eoyaml;
+
+import com.amihaiemil.eoyaml.exceptions.YamlIndentationException;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+
+import java.io.File;
+
+/**
+ * Test cases regarding an input YAML's indentation, particularly
+ * disabling validation of indentation and trying to guess the correct
+ * one.
+ * @author Mihai Andronache (amihaiemil@gmail.com)
+ * @version $Id$
+ * @since 5.1.0
+ */
+public final class YamlIndentationTestCase {
+
+    /**
+     * A Yaml mapping containing an unindented sequence throws exception
+     * because of bad indentation.
+     * @throws Exception If something goes wrong.
+     */
+    @Test (expected = YamlIndentationException.class)
+    public void unintendedSequenceException() throws Exception {
+        final YamlMapping map = Yaml.createYamlInput(
+            new File("src/test/resources/badSequenceIndentationInMapping.yml"),
+            Boolean.FALSE
+        ).readYamlMapping();
+        System.out.println(map);
+    }
+
+    /**
+     * A Yaml mapping containing an unindented sequence can be read
+     * if we guess the correct indentation.
+     * @throws Exception If something goes wrong.
+     */
+    @Test
+    public void readsUnintendedSequenceException() throws Exception {
+        final YamlMapping map = Yaml.createYamlInput(
+            new File("src/test/resources/badSequenceIndentationInMapping.yml"),
+            Boolean.TRUE
+        ).readYamlMapping();
+        final YamlSequence developers = map.yamlSequence("developers");
+        MatcherAssert.assertThat(
+            developers,
+            Matchers.iterableWithSize(3)
+        );
+        MatcherAssert.assertThat(
+            developers.string(0),
+            Matchers.equalTo("amihaiemil")
+        );
+        MatcherAssert.assertThat(
+            developers.string(1),
+            Matchers.equalTo("sherif")
+        );
+        MatcherAssert.assertThat(
+            developers.string(2),
+            Matchers.equalTo("rultor")
+        );
+    }
+
+    /**
+     * A badly indented YAML mapping throws an exception.
+     * @throws Exception If something goes wrong.
+     */
+    @Test (expected = YamlIndentationException.class)
+    public void complainsOnBadlyIndentedMapping() throws Exception {
+        final YamlMapping map = Yaml.createYamlInput(
+            new File("src/test/resources/badMappingIndentation.yml"),
+            Boolean.FALSE
+        ).readYamlMapping();
+        System.out.println(map);
+    }
+
+    /**
+     * A badly indented YAML can be read if we try to guess the indentation.
+     * @throws Exception If something goes wrong.
+     */
+    @Test
+    public void readsBadlyIndentedMapping() throws Exception {
+        final YamlMapping map = Yaml.createYamlInput(
+            new File("src/test/resources/badMappingIndentation.yml"),
+            Boolean.TRUE
+        ).readYamlMapping();
+        System.out.println(map);
+        MatcherAssert.assertThat(
+            map.string("name"),
+            Matchers.equalTo("eo-yaml")
+        );
+        MatcherAssert.assertThat(
+            map.yamlSequence("developers"),
+            Matchers.nullValue()
+        );
+        MatcherAssert.assertThat(
+            map.yamlMapping("contributors"),
+            Matchers.notNullValue()
+        );
+        final YamlSequence developers = map
+            .yamlMapping("contributors")
+            .yamlSequence("developers");
+        MatcherAssert.assertThat(
+            developers,
+            Matchers.iterableWithSize(3)
+        );
+        MatcherAssert.assertThat(
+            developers.string(0),
+            Matchers.equalTo("amihaiemil")
+        );
+        MatcherAssert.assertThat(
+            developers.string(1),
+            Matchers.equalTo("sherif")
+        );
+        MatcherAssert.assertThat(
+            developers.string(2),
+            Matchers.equalTo("rultor")
+        );
+    }
+}
diff --git a/src/test/resources/badMappingIndentation.yml b/src/test/resources/badMappingIndentation.yml
new file mode 100644
index 0000000..b1b4ae3
--- /dev/null
+++ b/src/test/resources/badMappingIndentation.yml
@@ -0,0 +1,6 @@
+name: eo-yaml
+contributors:
+developers:
+- amihaiemil # Elements of this sequence should be indented by 4 spaces.
+- sherif
+- rultor
\ No newline at end of file
diff --git a/src/test/resources/badSequenceIndentationInMapping.yml b/src/test/resources/badSequenceIndentationInMapping.yml
new file mode 100644
index 0000000..3bca14e
--- /dev/null
+++ b/src/test/resources/badSequenceIndentationInMapping.yml
@@ -0,0 +1,4 @@
+developers:
+- amihaiemil # Elements of a child sequence should be indented by 2 spaces.
+- sherif
+- rultor
\ No newline at end of file