KeyPathParser { public static Path parse(String path) { path = path == null ? "" : path.trim(); if (path.length() < 1) { throw new IllegalArgumentException("Empty or null input"); } List<Element> elements = new ArrayList<>(); StringBuilder value = new StringBuilder(); State state = State.START; char[] chars = path.toCharArray(); int i; for (i = 0; i < chars.length; i++) { state = state.next(chars[i], i, elements, value); } state = state.next((char) 0, i, elements, value); if (state != State.EOF) { throw new ParsingException("Unexpected end of file"); } return new Path(Collections.unmodifiableList(elements)); }  static Path parse(String path);  }
@Test public void rootOnly() { Path path = KeyPathParser.parse("$"); assertThat(path.elements().size(), is(1)); assertThat(path.elements().get(0).isRoot(), is(true)); assertThat(path.elements().get(0).id(), is("$")); }
@Test public void oneSingleCharElement() { Path path = KeyPathParser.parse("$[\"a\"]"); assertThat(path.elements().size(), is(2)); assertThat(path.elements().get(0).isRoot(), is(true)); assertThat(path.elements().get(0).id(), is("$")); assertThat(path.elements().get(1).isRoot(), is(false)); assertThat(path.elements().get(1).id(), is("a")); }
@Test(expected = ParsingException.class) public void oneSingleCharsElement() { Path path = KeyPathParser.parse("$[\"\"]"); assertThat(path.elements().size(), is(2)); assertThat(path.elements().get(0).isRoot(), is(true)); assertThat(path.elements().get(0).id(), is("$")); assertThat(path.elements().get(1).isRoot(), is(false)); assertThat(path.elements().get(1).id(), is("")); }
@Test public void oneSingleMultiCharElement() { Path path = KeyPathParser.parse("$[\"abc\"]"); assertThat(path.elements().size(), is(2)); assertThat(path.elements().get(0).isRoot(), is(true)); assertThat(path.elements().get(0).id(), is("$")); assertThat(path.elements().get(1).isRoot(), is(false)); assertThat(path.elements().get(1).id(), is("abc")); }
@Test public void multipleElements() { Path path = KeyPathParser.parse("$[\"a\"][\"bc\"][\"d\"]"); assertThat(path.elements().size(), is(4)); assertThat(path.elements().get(0).isRoot(), is(true)); assertThat(path.elements().get(0).id(), is("$")); assertThat(path.elements().get(1).isRoot(), is(false)); assertThat(path.elements().get(1).id(), is("a")); assertThat(path.elements().get(2).isRoot(), is(false)); assertThat(path.elements().get(2).id(), is("bc")); assertThat(path.elements().get(3).isRoot(), is(false)); assertThat(path.elements().get(3).id(), is("d")); }
@Test public void specialCharsInElement() { Path path = KeyPathParser.parse("$[\"a.b\"][\"cd\"]"); assertThat(path.elements().size(), is(3)); assertThat(path.elements().get(0).isRoot(), is(true)); assertThat(path.elements().get(0).id(), is("$")); assertThat(path.elements().get(1).isRoot(), is(false)); assertThat(path.elements().get(1).id(), is("a.b")); assertThat(path.elements().get(2).isRoot(), is(false)); assertThat(path.elements().get(2).id(), is("cd")); }
@Test public void oneSingleCharElementDots() { Path path = KeyPathParser.parse("$.a"); assertThat(path.elements().size(), is(2)); assertThat(path.elements().get(0).isRoot(), is(true)); assertThat(path.elements().get(0).id(), is("$")); assertThat(path.elements().get(1).isRoot(), is(false)); assertThat(path.elements().get(1).id(), is("a")); }
@Test public void oneSingleMultiCharElementDots() { Path path = KeyPathParser.parse("$.abc"); assertThat(path.elements().size(), is(2)); assertThat(path.elements().get(0).isRoot(), is(true)); assertThat(path.elements().get(0).id(), is("$")); assertThat(path.elements().get(1).isRoot(), is(false)); assertThat(path.elements().get(1).id(), is("abc")); }
@Test public void multipleElementsDots() { Path path = KeyPathParser.parse("$.a.bc.d"); assertThat(path.elements().size(), is(4)); assertThat(path.elements().get(0).isRoot(), is(true)); assertThat(path.elements().get(0).id(), is("$")); assertThat(path.elements().get(1).isRoot(), is(false)); assertThat(path.elements().get(1).id(), is("a")); assertThat(path.elements().get(2).isRoot(), is(false)); assertThat(path.elements().get(2).id(), is("bc")); assertThat(path.elements().get(3).isRoot(), is(false)); assertThat(path.elements().get(3).id(), is("d")); }
@Test public void unquotedFollowedByQuoted() { Path path = KeyPathParser.parse("$.a[\"b\"]"); assertThat(path.elements().size(), is(3)); assertThat(path.elements().get(0).isRoot(), is(true)); assertThat(path.elements().get(0).id(), is("$")); assertThat(path.elements().get(1).isRoot(), is(false)); assertThat(path.elements().get(1).id(), is("a")); assertThat(path.elements().get(2).isRoot(), is(false)); assertThat(path.elements().get(2).id(), is("b")); }
@Test(expected = IllegalArgumentException.class) public void nullPath() { KeyPathParser.parse(null); }
@Test(expected = IllegalArgumentException.class) public void empty() { KeyPathParser.parse(""); }
@Test(expected = IllegalArgumentException.class) public void blank() { KeyPathParser.parse(" "); }
@Test(expected = ParsingException.class) public void exepectedFirstElement() { KeyPathParser.parse("$."); }
@Test(expected = ParsingException.class) public void exepectedFirstElementQuote() { KeyPathParser.parse("$[\""); }
@Test(expected = ParsingException.class) public void exepectedFirstElementBrace() { KeyPathParser.parse("$["); }
@Test(expected = ParsingException.class) public void expectedSubsequentElement() { KeyPathParser.parse("$[\"a\"]."); }
@Test(expected = ParsingException.class) public void expectedSubsequentElementDots() { KeyPathParser.parse("$.a."); }
@Test(expected = ParsingException.class) public void expectedSubsequentElementDots2() { KeyPathParser.parse("$[\"a\"]."); }
@Test(expected = ParsingException.class) public void unfinishedQuote() { KeyPathParser.parse("$[\"a]"); }
@Test(expected = ParsingException.class) public void unfinishedParen() { KeyPathParser.parse("$[\"a\""); }
@Test(expected = ParsingException.class) public void missingRoot() { KeyPathParser.parse("[\"a\"][\"b\"]"); }
@Test(expected = ParsingException.class) public void missingRootDots() { KeyPathParser.parse("a.b"); }
@Test(expected = ParsingException.class) public void unexpectedCharacterAfterEndValueValue() { KeyPathParser.parse("$/"); }
@Test(expected = ParsingException.class) public void unexpectedCharacterAfterUnquotedValue() { KeyPathParser.parse("$.a/"); }