Repository: decorators-squad/eo-yaml
Pull request #178 (2020-03-10 14:44:04)

Fixed and tested ReadYamlMapping.yamlSequence()/.yamlMapping()
PR for #176 

* wrote a ton of unit tests for methods .string(...)/.yamlMapping(...)/.yamlSequence(...) from ReadYamlMapping
* fixed bugs in the 3 methods
* a little refactoring
* tests for RtYamlMapping.


Patch:
diff --git a/src/main/java/com/amihaiemil/eoyaml/AllYamlLines.java b/src/main/java/com/amihaiemil/eoyaml/AllYamlLines.java
index d93be12..c670eb6 100644
--- a/src/main/java/com/amihaiemil/eoyaml/AllYamlLines.java
+++ b/src/main/java/com/amihaiemil/eoyaml/AllYamlLines.java
@@ -35,6 +35,7 @@ import java.util.Collection;
  * are cases where we need to iterate only over the lines which are
  * at the same indentation level and for that we use the decorator
  * {@link SameIndentationLevel}.
+ * @checkstyle ExecutableStatementCount (400 lines)
  * @author Mihai Andronache (amihaiemil@gmail.com)
  * @version $Id$
  * @since 1.0.0
@@ -117,10 +118,8 @@ final class AllYamlLines implements YamlLines {
                 node = new ReadPointedScalar(this);
                 break;
             default:
-                throw new IllegalStateException(
-                    "No nested Yaml node after line " + prev.number()
-                    + " which has [" + last + "] character at the end"
-                );
+                node = null;
+                break;
         }
         return node;
     }
diff --git a/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java b/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java
index 8fdb71f..12673dd 100644
--- a/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java
+++ b/src/main/java/com/amihaiemil/eoyaml/ReadYamlMapping.java
@@ -75,60 +75,110 @@ final class ReadYamlMapping extends ComparableYamlMapping {
         return kids;
     }
 
-    @Override
-    public YamlMapping yamlMapping(final String key) {
-        return (YamlMapping) this.nodeValue(key, true);
-    }
-
     @Override
     public YamlMapping yamlMapping(final YamlNode key) {
-        return (YamlMapping) this.nodeValue(key, true);
+        final YamlMapping found;
+        if(key instanceof Scalar) {
+            found = this.yamlMapping(((Scalar) key).value());
+        } else {
+            final YamlNode value = this.valueOfNodeKey(key);
+            if(value instanceof YamlMapping) {
+                found = (YamlMapping) value;
+            } else {
+                found = null;
+            }
+        }
+        return found;
     }
-
+    
     @Override
-    public YamlSequence yamlSequence(final String key) {
-        return (YamlSequence) this.nodeValue(key, false);
+    public YamlMapping yamlMapping(final String key) {
+        final YamlMapping found;
+        final YamlNode value = this.valueOfStringKey(key);
+        if(value instanceof YamlMapping) {
+            found = (YamlMapping) value;
+        } else {
+            found = null;
+        }
+        return found;
     }
 
     @Override
     public YamlSequence yamlSequence(final YamlNode key) {
-        return (YamlSequence) this.nodeValue(key, false);
+        final YamlSequence found;
+        if(key instanceof Scalar) {
+            found = this.yamlSequence(((Scalar) key).value());
+        } else {
+            final YamlNode value = this.valueOfNodeKey(key);
+            if(value instanceof YamlSequence) {
+                found = (YamlSequence) value;
+            } else {
+                found = null;
+            }
+        }
+        return found;
+    }
+    
+    @Override
+    public YamlSequence yamlSequence(final String key) {
+        final YamlSequence found;
+        final YamlNode value = this.valueOfStringKey(key);
+        if(value instanceof YamlSequence) {
+            found = (YamlSequence) value;
+        } else {
+            found = null;
+        }
+        return found;
     }
 
     @Override
-    public String string(final String key) {
+    public String string(final YamlNode key) {
         String value = null;
-        for (final YamlLine line : this.lines) {
-            final String trimmed = line.trimmed();
-            if(trimmed.startsWith(key + ":")) {
-                value = trimmed.substring(trimmed.indexOf(":") + 1).trim();
+        if(key instanceof Scalar) {
+            value = this.string(((Scalar) key).value());
+        } else {
+            boolean foundComplexKey = false;
+            for (final YamlLine line : this.lines) {
+                final String trimmed = line.trimmed();
+                if("?".equals(trimmed)) {
+                    final YamlNode keyNode = this.lines.nested(line.number())
+                            .toYamlNode(line);
+                    if(keyNode.equals(key)) {
+                        foundComplexKey = true;
+                        continue;
+                    }
+                }
+                if(foundComplexKey) {
+                    if(trimmed.endsWith(":")) {
+                        break;
+                    }
+                    if(trimmed.startsWith(":")) {
+                        value = trimmed.substring(
+                            trimmed.indexOf(":") + 1
+                        ).trim();
+                        break;
+                    }
+                }
             }
         }
         return value;
     }
 
     @Override
-    public String string(final YamlNode key) {
+    public String string(final String key) {
         String value = null;
-        boolean found = false;
         for (final YamlLine line : this.lines) {
             final String trimmed = line.trimmed();
-            if("?".equals(trimmed)) {
-                final YamlNode keyNode = this.lines.nested(line.number())
-                        .toYamlNode(line);
-                if(keyNode.equals(key)) {
-                    found = true;
-                    continue;
-                }
+            if(trimmed.endsWith(key + ":")) {
+                continue;
             }
-            if(found && trimmed.startsWith(":")) {
+            if(trimmed.startsWith(key + ":")) {
                 value = trimmed.substring(trimmed.indexOf(":") + 1).trim();
-                break;
             }
         }
         return value;
     }
-
+    
     @Override
     public String toString() {
         return this.indent(0);
@@ -140,37 +190,28 @@ final class ReadYamlMapping extends ComparableYamlMapping {
     }
 
     /**
-     * The YamlNode value associated with a String key.
+     * The YamlNode value associated with a String (scalar) key.
      * @param key String key.
-     * @param map Is the value a map or a sequence?
      * @return YamlNode.
      */
-    private YamlNode nodeValue(final String key, final boolean map) {
+    private YamlNode valueOfStringKey(final String key) {
         YamlNode value = null;
         for (final YamlLine line : this.lines) {
             final String trimmed = line.trimmed();
-            if(trimmed.startsWith(key + ":")) {
-                if (map) {
-                    value = new ReadYamlMapping(
-                        this.lines.nested(line.number())
-                    );
-                } else {
-                    value = new ReadYamlSequence(
-                        this.lines.nested(line.number())
-                    );
-                }
+            if(trimmed.endsWith(key + ":")) {
+                value = this.lines.nested(line.number()).toYamlNode(line);
             }
         }
         return value;
     }
 
     /**
-     * The YamlNode value associated with a String key.
+     * The YamlNode value associated with a YamlNode key
+     * (a "complex" key starting with '?').
      * @param key YamlNode key.
-     * @param map Is the value a map or a sequence?
      * @return YamlNode.
      */
-    private YamlNode nodeValue(final YamlNode key, final boolean map) {
+    private YamlNode valueOfNodeKey(final YamlNode key) {
         YamlNode value = null;
         for (final YamlLine line : this.lines) {
             final String trimmed = line.trimmed();
@@ -180,15 +221,12 @@ final class ReadYamlMapping extends ComparableYamlMapping {
                 );
                 final YamlNode keyNode = keyLines.toYamlNode(line);
                 if(keyNode.equals(key)) {
-                    int colonLine = line.number() + keyLines.count() + 1;
-                    if (map) {
-                        value = new ReadYamlMapping(
-                            this.lines.nested(colonLine)
-                        );
-                    } else {
-                        value = new ReadYamlSequence(
-                            this.lines.nested(colonLine)
-                        );
+                    final YamlLine colonLine = this.lines.line(
+                        line.number() + keyLines.count() + 1
+                    );
+                    if(":".equals(colonLine.trimmed())) {
+                        value = this.lines.nested(colonLine.number())
+                                    .toYamlNode(colonLine);
                     }
                 }
             }
diff --git a/src/main/java/com/amihaiemil/eoyaml/YamlLines.java b/src/main/java/com/amihaiemil/eoyaml/YamlLines.java
index 820481a..a758121 100644
--- a/src/main/java/com/amihaiemil/eoyaml/YamlLines.java
+++ b/src/main/java/com/amihaiemil/eoyaml/YamlLines.java
@@ -127,4 +127,24 @@ interface YamlLines extends Iterable<YamlLine> {
         return new AllYamlLines(nestedLines);
     }
 
+    /**
+     * Get a certain YamlLine.
+     * @param number Number of the line.
+     * @return YamlLine or throws {@link IndexOutOfBoundsException}.
+     */
+    default YamlLine line(final int number) {
+        final Collection<YamlLine> lines = this.lines();
+        int index = 0;
+        for(final YamlLine line : lines){
+            if(index == number) {
+                return line;
+            }
+            index++;
+        }
+        throw new IllegalArgumentException(
+            "Couldn't find line " + number
+          + ". Pay attention, there are "
+          + this.lines().size() + " lines!");
+    }
+
 }


Test patch:
diff --git a/src/test/java/com/amihaiemil/eoyaml/ReadYamlMappingTest.java b/src/test/java/com/amihaiemil/eoyaml/ReadYamlMappingTest.java
index 82a8ab6..89dbbe0 100644
--- a/src/test/java/com/amihaiemil/eoyaml/ReadYamlMappingTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/ReadYamlMappingTest.java
@@ -39,6 +39,7 @@ import org.junit.Test;
 
 /**
  * Unit tests for {@link ReadYamlMapping}.
+ * @checkstyle MethodName (1000 lines)
  * @author Mihai Andronache (amihaiemil@gmail.com)
  * @version $Id$
  * @since 1.0.0
@@ -263,7 +264,9 @@ public final class ReadYamlMappingTest {
     @Test
     public void returnsStringWithYamlMappingKey(){
         final YamlMapping key = new RtYamlMappingBuilder()
-            .add("complex1", "mapping1").add("complex2", "mapping2").build();
+            .add("complex1", "mapping1")
+            .add("complex2", "mapping2")
+            .build();
         final List<YamlLine> lines = new ArrayList<>();
         lines.add(new RtYamlLine("first: something", 0));
         lines.add(new RtYamlLine("? ", 1));
@@ -298,7 +301,341 @@ public final class ReadYamlMappingTest {
             third, Matchers.equalTo("something")
         );
     }
+    
+    /**
+     * ReadYamlMapping.string(...) returns null if the queried
+     * Scalar is not present.
+     */
+    @Test
+    public void returnsNullOnMissingScalar() {
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: somethingElse", 0));
+        lines.add(new RtYamlLine("second:", 1));
+        lines.add(new RtYamlLine("  - some", 2));
+        lines.add(new RtYamlLine("  - sequence", 3));
+        lines.add(new RtYamlLine("third: something", 4));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.string("notthere"), Matchers.nullValue());
+        MatcherAssert.assertThat(map.string(
+            new Scalar("notthere")), Matchers.nullValue()
+        );
+    }
+    
+    /**
+     * ReadYamlMapping.string(YamlMapping) returns null if the queried
+     * Scalar is not present.
+     */
+    @Test
+    public void returnsNullOnMissingScalarWithMappingKey() {
+        final YamlMapping key = new RtYamlMappingBuilder()
+            .add("complex1", "mapping1")
+            .add("complex2", "mapping2")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: somethingElse", 0));
+        lines.add(new RtYamlLine("second:", 1));
+        lines.add(new RtYamlLine("  - some", 2));
+        lines.add(new RtYamlLine("  - sequence", 3));
+        lines.add(new RtYamlLine("third: something", 4));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.string(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.string(YamlSequence) returns null if the queried
+     * Scalar is not present.
+     */
+    @Test
+    public void returnsNullOnMissingScalarWithSequenceKey() {
+        final YamlSequence key = new RtYamlSequenceBuilder()
+            .add("sequence")
+            .add("key")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: somethingElse", 0));
+        lines.add(new RtYamlLine("second:", 1));
+        lines.add(new RtYamlLine("  - some", 2));
+        lines.add(new RtYamlLine("  - sequence", 3));
+        lines.add(new RtYamlLine("third: something", 4));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.string(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.string(...) returns null if the queried value
+     * is present but it is not actually a Scalar.
+     */
+    @Test
+    public void returnsNullOnMisreadScalar() {
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: somethingElse", 0));
+        lines.add(new RtYamlLine("second:", 1));
+        lines.add(new RtYamlLine("  - some", 2));
+        lines.add(new RtYamlLine("  - sequence", 3));
+        lines.add(new RtYamlLine("third: something", 4));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.string("second"), Matchers.nullValue());
+        MatcherAssert.assertThat(map.string(
+            new Scalar("second")), Matchers.nullValue()
+        );
+    }
+    
+    /**
+     * ReadYamlMapping.string(YamlMapping) returns null if the queried value
+     * is present but it is not actually a Scalar.
+     */
+    @Test
+    public void returnsNullOnMisreadScalarWithMappingKey() {
+        final YamlMapping key = new RtYamlMappingBuilder()
+            .add("complex1", "mapping1")
+            .add("complex2", "mapping2")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  complex1: mapping1", 2));
+        lines.add(new RtYamlLine("  complex2: mapping2", 3));
+        lines.add(new RtYamlLine(":", 4));
+        lines.add(new RtYamlLine(" - some", 5));
+        lines.add(new RtYamlLine(" - sequence", 6));
+        lines.add(new RtYamlLine("second: something", 7));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.string(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.string(YamlSequence) returns null if the queried value
+     * is present but it is not actually a Scalar.
+     */
+    @Test
+    public void returnsNullOnMisreadScalarWithSequenceKey() {
+        final YamlSequence key = new RtYamlSequenceBuilder()
+            .add("sequence")
+            .add("key")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  - sequence", 2));
+        lines.add(new RtYamlLine("  - key", 3));
+        lines.add(new RtYamlLine(":", 4));
+        lines.add(new RtYamlLine(" - some", 5));
+        lines.add(new RtYamlLine(" - sequence", 6));
+        lines.add(new RtYamlLine("second: something", 7));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.string(key), Matchers.nullValue());
+    }
 
+    /**
+     * ReadYamlMapping.yamlSequence(...) returns null if the queried
+     * YamlSequence is not present.
+     */
+    @Test
+    public void returnsNullOnMissingYamlSequence() {
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: somethingElse", 0));
+        lines.add(new RtYamlLine("second:", 1));
+        lines.add(new RtYamlLine("  - some", 2));
+        lines.add(new RtYamlLine("  - sequence", 3));
+        lines.add(new RtYamlLine("third: something", 4));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(
+            map.yamlSequence("notthere"), Matchers.nullValue()
+        );
+        MatcherAssert.assertThat(map.yamlSequence(
+            new Scalar("notthere")), Matchers.nullValue()
+        );
+    }
+    
+    /**
+     * ReadYamlMapping.yamlSequence(...) returns null if the queried
+     * YamlSequence is not present, based on a complex key.
+     */
+    @Test
+    public void returnsNullOnMissingYamlSequenceWithMappingKey() {
+        final YamlMapping key = new RtYamlMappingBuilder()
+            .add("complex1", "mapping1")
+            .add("complex2", "mapping2")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  some: other", 2));
+        lines.add(new RtYamlLine("  complex: key", 3));
+        lines.add(new RtYamlLine(": ", 4));
+        lines.add(new RtYamlLine("  map: value", 5));
+        lines.add(new RtYamlLine("second: something", 6));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.yamlSequence(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.yamlMapping(...) returns null if the queried
+     * YamlMapping is not present.
+     */
+    @Test
+    public void returnsNullOnMissingYamlMappingWithSequenceKey() {
+        final YamlSequence key = new RtYamlSequenceBuilder()
+            .add("sequence")
+            .add("key")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  - someOther", 2));
+        lines.add(new RtYamlLine("  - sequenceKey", 3));
+        lines.add(new RtYamlLine(": ", 4));
+        lines.add(new RtYamlLine("  map: value", 5));
+        lines.add(new RtYamlLine("second: something", 6));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.yamlMapping(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.yamlMapping(String) returns null if the queried
+     * key has a value that is a Scalar.
+     */
+    @Test
+    public void returnsNullOnMisreadYamlMapping_Scalar() {
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: somethingElse", 0));
+        lines.add(new RtYamlLine("second:", 1));
+        lines.add(new RtYamlLine("  - some", 2));
+        lines.add(new RtYamlLine("  - sequence", 3));
+        lines.add(new RtYamlLine("third: something", 4));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(
+            map.yamlMapping("first"), Matchers.nullValue()
+        );
+        MatcherAssert.assertThat(map.yamlMapping(
+            new Scalar("first")), Matchers.nullValue()
+        );
+    }
+    
+    /**
+     * ReadYamlMapping.yamlMapping(String) returns null if the queried
+     * key has a value that is a YamlSequence.
+     */
+    @Test
+    public void returnsNullOnMisreadYamlMapping_Sequence() {
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: somethingElse", 0));
+        lines.add(new RtYamlLine("second:", 1));
+        lines.add(new RtYamlLine("  - some", 2));
+        lines.add(new RtYamlLine("  - sequence", 3));
+        lines.add(new RtYamlLine("third: something", 4));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(
+            map.yamlMapping("second"), Matchers.nullValue()
+        );
+        MatcherAssert.assertThat(map.yamlMapping(
+            new Scalar("second")), Matchers.nullValue()
+        );
+    }
+    
+    /**
+     * ReadYamlMapping.yamlMapping(YamlNode) returns null if the queried
+     * complex key has a Scalar value.
+     */
+    @Test
+    public void returnsNullOnMisreadYamlMapping_ScalarWithMappingKey() {
+        final YamlMapping key = new RtYamlMappingBuilder()
+            .add("complex1", "mapping1")
+            .add("complex2", "mapping2")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  complex1: mapping1", 2));
+        lines.add(new RtYamlLine("  complex2: mapping2", 3));
+        lines.add(new RtYamlLine(": scalarValue", 4));
+        lines.add(new RtYamlLine("second: something", 6));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.yamlMapping(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.yamlMapping(YamlNode) returns null if the queried
+     * complex key has a YamlSequence value.
+     */
+    @Test
+    public void returnsNullOnMisreadYamlMapping_SequenceWithMappingKey() {
+        final YamlMapping key = new RtYamlMappingBuilder()
+            .add("complex1", "mapping1")
+            .add("complex2", "mapping2")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  complex1: mapping1", 2));
+        lines.add(new RtYamlLine("  complex2: mapping2", 3));
+        lines.add(new RtYamlLine(":", 4));
+        lines.add(new RtYamlLine("  - some", 5));
+        lines.add(new RtYamlLine("  - seq", 6));
+        lines.add(new RtYamlLine("second: something", 7));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.yamlMapping(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.yamlMapping(YamlNode) returns null if the queried
+     * complex key has a Scalar value.
+     */
+    @Test
+    public void returnsNullOnMisreadYamlMapping_ScalarWithSequenceKey() {
+        final YamlSequence key = new RtYamlSequenceBuilder()
+            .add("sequence")
+            .add("key")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  - sequence", 2));
+        lines.add(new RtYamlLine("  - key", 3));
+        lines.add(new RtYamlLine(": scalarValue", 4));
+        lines.add(new RtYamlLine("second: something", 6));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.yamlMapping(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.yamlMapping(YamlNode) returns null if the queried
+     * complex key has a YamlSequence value.
+     */
+    @Test
+    public void returnsNullOnMisreadYamlMapping_SequenceWithSequenceKey() {
+        final YamlSequence key = new RtYamlSequenceBuilder()
+            .add("sequence")
+            .add("key")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  - sequence", 2));
+        lines.add(new RtYamlLine("  - key", 3));
+        lines.add(new RtYamlLine(":", 4));
+        lines.add(new RtYamlLine("  - some", 5));
+        lines.add(new RtYamlLine("  - sequence", 6));
+        lines.add(new RtYamlLine("second: something", 7));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.yamlMapping(key), Matchers.nullValue());
+    }
+    
     /**
      * An empty ReadYamlMapping can be printed.
      * @throws Exception if something goes wrong
@@ -310,4 +647,208 @@ public final class ReadYamlMappingTest {
         );
         MatcherAssert.assertThat(map.toString(), Matchers.isEmptyString());
     }
+        
+    /**
+     * ReadYamlMapping.yamlMapping(...) returns null if the queried
+     * YamlMapping is not present.
+     */
+    @Test
+    public void returnsNullOnMissingYamlMapping() {
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: somethingElse", 0));
+        lines.add(new RtYamlLine("second:", 1));
+        lines.add(new RtYamlLine("  - some", 2));
+        lines.add(new RtYamlLine("  - sequence", 3));
+        lines.add(new RtYamlLine("third: something", 4));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(
+            map.yamlMapping("notthere"), Matchers.nullValue()
+        );
+        MatcherAssert.assertThat(map.yamlMapping(
+            new Scalar("notthere")), Matchers.nullValue()
+        );
+    }
+    
+    /**
+     * ReadYamlMapping.yamlMapping(...) returns null if the queried
+     * YamlMapping is not present.
+     */
+    @Test
+    public void returnsNullOnMissingYamlMappingWithMappingKey() {
+        final YamlMapping key = new RtYamlMappingBuilder()
+            .add("complex1", "mapping1")
+            .add("complex2", "mapping2")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  some: other", 2));
+        lines.add(new RtYamlLine("  complex: key", 3));
+        lines.add(new RtYamlLine(": ", 4));
+        lines.add(new RtYamlLine("  map: value", 5));
+        lines.add(new RtYamlLine("second: something", 6));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.yamlMapping(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.yamlSequence(...) returns null if the queried
+     * YamlSequence is not present.
+     */
+    @Test
+    public void returnsNullOnMissingYamlSequenceWithSequenceKey() {
+        final YamlSequence key = new RtYamlSequenceBuilder()
+            .add("sequence")
+            .add("key")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  - someOther", 2));
+        lines.add(new RtYamlLine("  - sequenceKey", 3));
+        lines.add(new RtYamlLine(": ", 4));
+        lines.add(new RtYamlLine("  map: value", 5));
+        lines.add(new RtYamlLine("second: something", 6));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.yamlSequence(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.yamlSequence(String) returns null if the queried
+     * key has a value that is a Scalar.
+     */
+    @Test
+    public void returnsNullOnMisreadYamlSequence_Scalar() {
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: somethingElse", 0));
+        lines.add(new RtYamlLine("second:", 1));
+        lines.add(new RtYamlLine("  - some", 2));
+        lines.add(new RtYamlLine("  - sequence", 3));
+        lines.add(new RtYamlLine("third: something", 4));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(
+            map.yamlSequence("first"), Matchers.nullValue()
+        );
+        MatcherAssert.assertThat(map.yamlSequence(
+            new Scalar("first")), Matchers.nullValue()
+        );
+    }
+    
+    /**
+     * ReadYamlMapping.yamlSequence(String) returns null if the queried
+     * key has a value that is a YamlMapping.
+     */
+    @Test
+    public void returnsNullOnMisreadYamlSequence_Mapping() {
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: somethingElse", 0));
+        lines.add(new RtYamlLine("second:", 1));
+        lines.add(new RtYamlLine("  key1: map", 2));
+        lines.add(new RtYamlLine("  key2: notSeq", 3));
+        lines.add(new RtYamlLine("third: something", 4));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(
+            map.yamlSequence("second"), Matchers.nullValue()
+        );
+        MatcherAssert.assertThat(map.yamlSequence(
+            new Scalar("second")), Matchers.nullValue()
+        );
+    }
+    
+    /**
+     * ReadYamlMapping.yamlSequence(YamlNode) returns null if the queried
+     * complex key has a Scalar value.
+     */
+    @Test
+    public void returnsNullOnMisreadYamlSequence_ScalarWithMappingKey() {
+        final YamlMapping key = new RtYamlMappingBuilder()
+            .add("complex1", "mapping1")
+            .add("complex2", "mapping2")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  complex1: mapping1", 2));
+        lines.add(new RtYamlLine("  complex2: mapping2", 3));
+        lines.add(new RtYamlLine(": scalarValue", 4));
+        lines.add(new RtYamlLine("second: something", 6));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.yamlSequence(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.yamlSequence(YamlNode) returns null if the queried
+     * complex key has a YamlMapping value.
+     */
+    @Test
+    public void returnsNullOnMisreadYamlSequence_MappingWithMappingKey() {
+        final YamlMapping key = new RtYamlMappingBuilder()
+            .add("complex1", "mapping1")
+            .add("complex2", "mapping2")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  complex1: mapping1", 2));
+        lines.add(new RtYamlLine("  complex2: mapping2", 3));
+        lines.add(new RtYamlLine(":", 4));
+        lines.add(new RtYamlLine("  some: map", 5));
+        lines.add(new RtYamlLine("  not: seq", 6));
+        lines.add(new RtYamlLine("second: something", 7));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.yamlSequence(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.yamlSequence(YamlNode) returns null if the queried
+     * complex key has a Scalar value.
+     */
+    @Test
+    public void returnsNullOnMisreadYamlSequence_ScalarWithSequenceKey() {
+        final YamlSequence key = new RtYamlSequenceBuilder()
+            .add("sequence")
+            .add("key")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  - sequence", 2));
+        lines.add(new RtYamlLine("  - key", 3));
+        lines.add(new RtYamlLine(": scalarValue", 4));
+        lines.add(new RtYamlLine("second: something", 6));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.yamlSequence(key), Matchers.nullValue());
+    }
+    
+    /**
+     * ReadYamlMapping.yamlSequence(YamlNode) returns null if the queried
+     * complex key has a YamlMapping value.
+     */
+    @Test
+    public void returnsNullOnMisreadYamlSequence_MappingWithSequenceKey() {
+        final YamlSequence key = new RtYamlSequenceBuilder()
+            .add("sequence")
+            .add("key")
+            .build();
+        final List<YamlLine> lines = new ArrayList<>();
+        lines.add(new RtYamlLine("first: something", 0));
+        lines.add(new RtYamlLine("? ", 1));
+        lines.add(new RtYamlLine("  - sequence", 2));
+        lines.add(new RtYamlLine("  - key", 3));
+        lines.add(new RtYamlLine(":", 4));
+        lines.add(new RtYamlLine("  some: map", 5));
+        lines.add(new RtYamlLine("  not: seq", 6));
+        lines.add(new RtYamlLine("second: something", 7));
+        final YamlMapping map = new ReadYamlMapping(new AllYamlLines(lines));
+        
+        MatcherAssert.assertThat(map.yamlSequence(key), Matchers.nullValue());
+    }
 }
diff --git a/src/test/java/com/amihaiemil/eoyaml/RtYamlMappingTest.java b/src/test/java/com/amihaiemil/eoyaml/RtYamlMappingTest.java
index 89564d2..cc87382 100644
--- a/src/test/java/com/amihaiemil/eoyaml/RtYamlMappingTest.java
+++ b/src/test/java/com/amihaiemil/eoyaml/RtYamlMappingTest.java
@@ -31,10 +31,12 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.io.IOUtils;
 import org.hamcrest.MatcherAssert;
@@ -52,62 +54,58 @@ import org.mockito.Mockito;
 public final class RtYamlMappingTest {
 
     /**
-     * RtYamlMapping can fetch its children.
+     * RtYamlMapping can fetch its key-ordered children.
      */
     @Test
-    public void fetchesChildren() {
+    public void fetchesOrderedChildren() {
         Map<YamlNode, YamlNode> mappings = new HashMap<>();
-        mappings.put(new Scalar("key1"), Mockito.mock(YamlNode.class));
-        mappings.put(new Scalar("key2"), Mockito.mock(YamlNode.class));
-        mappings.put(new Scalar("key3"), Mockito.mock(YamlNode.class));
+        mappings.put(new Scalar("key2"), new Scalar("value1"));
+        mappings.put(new Scalar("key3"), new Scalar("value2"));
+        mappings.put(new Scalar("key1"), new Scalar("value3"));
         YamlMapping map = new RtYamlMapping(mappings);
+        final Collection<YamlNode> children = map.children();
+        MatcherAssert.assertThat(
+            children, Matchers.not(Matchers.emptyIterable())
+        );
+        MatcherAssert.assertThat(children.size(), Matchers.equalTo(3));
+        final Iterator<YamlNode> iterator = children.iterator();
+        MatcherAssert.assertThat(
+            iterator.next(), Matchers.equalTo(new Scalar("value3"))
+        );
         MatcherAssert.assertThat(
-            map.children(), Matchers.not(Matchers.emptyIterable())
+            iterator.next(), Matchers.equalTo(new Scalar("value1"))
+        );
+        MatcherAssert.assertThat(
+            iterator.next(), Matchers.equalTo(new Scalar("value2"))
         );
-        MatcherAssert.assertThat(map.children().size(), Matchers.equalTo(3));
     }
 
     /**
-     * RtYamlMapping can fetch its keys.
+     * RtYamlMapping can fetch its ordered keys.
      */
     @Test
-    public void fetchesKeys() {
+    public void fetchesOrderedKeys() {
         Map<YamlNode, YamlNode> mappings = new HashMap<>();
+        mappings.put(new Scalar("key3"), Mockito.mock(YamlNode.class));
         mappings.put(new Scalar("key1"), Mockito.mock(YamlNode.class));
         mappings.put(new Scalar("key2"), Mockito.mock(YamlNode.class));
-        mappings.put(new Scalar("key3"), Mockito.mock(YamlNode.class));
         YamlMapping map = new RtYamlMapping(mappings);
+        final Set<YamlNode> keys = map.keys();
         MatcherAssert.assertThat(
-            map.keys(), Matchers.not(Matchers.emptyIterable())
+            keys, Matchers.not(Matchers.emptyIterable())
         );
-        MatcherAssert.assertThat(map.keys().size(), Matchers.equalTo(3));
-
-    }
-
-    /**
-     * RtYamlMapping is ordered by keys.
-     */
-    @Test
-    public void orderedKeys() {
-        Map<YamlNode, YamlNode> mappings = new HashMap<>();
-        Scalar one = new Scalar("value1");
-        Scalar two = new Scalar("value2");
-        Scalar three = new Scalar("value3");
-
-        mappings.put(new Scalar("key3"), one);
-        mappings.put(new Scalar("key2"), two);
-        mappings.put(new Scalar("key1"), three);
-        RtYamlMapping map = new RtYamlMapping(mappings);
-        Iterator<YamlNode> children = map.children().iterator();
+        MatcherAssert.assertThat(keys.size(), Matchers.equalTo(3));
+        final Iterator<YamlNode> iterator = keys.iterator();
         MatcherAssert.assertThat(
-            (Scalar) children.next(), Matchers.equalTo(three)
+            iterator.next(), Matchers.equalTo(new Scalar("key1"))
         );
         MatcherAssert.assertThat(
-            (Scalar) children.next(), Matchers.equalTo(two)
+            iterator.next(), Matchers.equalTo(new Scalar("key2"))
         );
         MatcherAssert.assertThat(
-            (Scalar) children.next(), Matchers.equalTo(one)
+            iterator.next(), Matchers.equalTo(new Scalar("key3"))
         );
+
     }
 
     /**
@@ -130,6 +128,27 @@ public final class RtYamlMappingTest {
             map.string(key), Matchers.equalTo(value)
         );
     }
+    
+    /**
+     * RtYamlMapping can return null if the queried Scalar is missing or
+     * the found value is not actually a Scalar.
+     */
+    @Test
+    public void returnsNullOnMissingScalar() {
+        Map<YamlNode, YamlNode> mappings = new HashMap<>();
+        Scalar key = new Scalar("missing");
+        mappings.put(new Scalar("key3"), Mockito.mock(YamlSequence.class));
+        mappings.put(new Scalar("key4"), Mockito.mock(YamlNode.class));
+        mappings.put(new Scalar("key1"), Mockito.mock(YamlMapping.class));
+        RtYamlMapping map = new RtYamlMapping(mappings);
+
+        MatcherAssert.assertThat(map.string("missing"), Matchers.nullValue());
+        MatcherAssert.assertThat(map.string(key), Matchers.nullValue());
+        
+        MatcherAssert.assertThat(
+            map.string(new Scalar("keÿ3")), Matchers.nullValue()
+        );
+    }
 
     /**
      * RtYamlMapping can return a YamlMapping.
@@ -145,6 +164,25 @@ public final class RtYamlMappingTest {
             map.yamlMapping("key1"), Matchers.notNullValue()
         );
     }
+    
+    /**
+     * RtYamlMapping can return null if the queried YamlMapping is missing or
+     * if the found value is not actually a YamlMapping.
+     */
+    @Test
+    public void returnsNullOnMissingYamlMapping() {
+        Map<YamlNode, YamlNode> mappings = new HashMap<>();
+        mappings.put(new Scalar("key3"), Mockito.mock(YamlSequence.class));
+        mappings.put(new Scalar("key1"), Mockito.mock(YamlMapping.class));
+        RtYamlMapping map = new RtYamlMapping(mappings);
+
+        MatcherAssert.assertThat(
+            map.yamlMapping("key4"), Matchers.nullValue()
+        );
+        MatcherAssert.assertThat(
+            map.yamlMapping("key3"), Matchers.nullValue()
+        );
+    }
 
     /**
      * RtYamlMapping can return a YamlSequence.
@@ -159,6 +197,24 @@ public final class RtYamlMappingTest {
             map.yamlSequence("key3"), Matchers.notNullValue()
         );
     }
+    
+    /**
+     * RtYamlMapping can return null if the queried YamlSequence is missing or
+     * if the found value is not actually a YamlSequence.
+     */
+    @Test
+    public void returnsNullOnMissingYamlSequence() {
+        Map<YamlNode, YamlNode> mappings = new HashMap<>();
+        mappings.put(new Scalar("key3"), Mockito.mock(YamlSequence.class));
+        mappings.put(new Scalar("key1"), Mockito.mock(YamlMapping.class));
+        RtYamlMapping map = new RtYamlMapping(mappings);
+        MatcherAssert.assertThat(
+            map.yamlSequence("key4"), Matchers.nullValue()
+        );
+        MatcherAssert.assertThat(
+            map.yamlSequence("key1"), Matchers.nullValue()
+        );
+    }
 
     /**
      * RtYamlMapping can return null if the specified key is missig.