IgnoreFilePattern { @NotNull static PathPart createPattern(@NotNull final String pattern) { if (pattern.length() <= 0) { throw new IllegalArgumentException("pattern cannot be empty"); } char[] pat = pattern.replace('\\', '/').replace(File.separatorChar, '/').toCharArray(); int lastPos = pat.length - 1; boolean isAbsolute = false; int startPos = 0; while (startPos <= lastPos && pat[startPos] == '/' ) { isAbsolute = true; startPos++; } PathPart ret = null; ParseState state = ParseState.END_PATH; { boolean isDir = false; while (lastPos > startPos && pat[lastPos] == '/') { isDir = true; lastPos--; } if (isDir) { ret = new StrictStarStarPart(null); } } List<String> pieces = new ArrayList<>(); int lastPartPos = lastPos; while (lastPos >= startPos) { char c = pat[lastPos]; switch (state) { case END_PATH: if (c == '/') { lastPartPos = lastPos; } else if (c == '*') { pieces.add(0, "*"); lastPartPos = lastPos; state = ParseState.JUST_FOUND_STAR_AT_END; } else { state = ParseState.TEXT_PATH; } break; case JUST_FOUND_STAR_AT_END: if (c == '*') { ret = new StrictStarStarPart(ret); lastPartPos = lastPos; pieces.clear(); state = ParseState.JUST_FOUND_STAR_STAR_AT_END; } else if (c == '/') { ret = new SingleAnyMatchPart(ret); pieces.clear(); lastPartPos = lastPos; state = ParseState.END_PATH; } else { state = ParseState.STAR_PATH; } break; case JUST_FOUND_STAR_IN_MIDDLE: if (c == '*') { ret = new StarMatchPart(ret, pieces.toArray(EMPTY), isFileSystemCaseSensitive()); lastPartPos = lastPos; pieces.clear(); ret = new StrictStarStarPart(ret); state = ParseState.JUST_FOUND_STAR_STAR_IN_MIDDLE; } else if (c == '/') { ret = new StarMatchPart(ret, pieces.toArray(EMPTY), isFileSystemCaseSensitive()); lastPartPos = lastPos; pieces.clear(); state = ParseState.END_PATH; } else { state = ParseState.STAR_PATH; } break; case JUST_FOUND_STAR_STAR_AT_END: case JUST_FOUND_STAR_STAR_IN_MIDDLE: if (c == '*') { pieces.add(0, "*"); lastPartPos = lastPos; state = ParseState.JUST_FOUND_STAR_AT_END; } else if (c == '/') { lastPartPos = lastPos; pieces.clear(); state = ParseState.END_PATH; } else { lastPartPos = lastPos; pieces.add(0, "*"); state = ParseState.STAR_PATH; } break; case STAR_PATH: if (c == '*') { pieces.add(0, new String(pat, lastPos + 1, lastPartPos - lastPos - 1)); pieces.add(0, "*"); lastPartPos = lastPos; state = ParseState.JUST_FOUND_STAR_IN_MIDDLE; } else if (c == '/') { pieces.add(0, new String(pat, lastPos, lastPartPos - lastPos - 1)); ret = new StarMatchPart(ret, pieces.toArray(EMPTY), isFileSystemCaseSensitive()); lastPartPos = lastPos; pieces.clear(); state = ParseState.END_PATH; } break; case TEXT_PATH: if (c == '*') { pieces.add(0, new String(pat, lastPos + 1, lastPartPos - lastPos)); pieces.add(0, "*"); lastPartPos = lastPos; state = ParseState.JUST_FOUND_STAR_IN_MIDDLE; } else if (c == '/') { ret = new ExactMatchPart(ret, new String(pat, lastPos + 1, lastPartPos - lastPos), isFileSystemCaseSensitive()); lastPartPos = lastPos; pieces.clear(); state = ParseState.END_PATH; } break; } lastPos--; } switch (state) { case JUST_FOUND_STAR_AT_END: ret = new SingleAnyMatchPart(ret); break; case JUST_FOUND_STAR_IN_MIDDLE: ret = new StarMatchPart(ret, pieces.toArray(EMPTY), isFileSystemCaseSensitive()); break; case STAR_PATH: pieces.add(0, new String(pat, startPos, lastPartPos - startPos)); ret = new StarMatchPart(ret, pieces.toArray(EMPTY), isFileSystemCaseSensitive()); break; case TEXT_PATH: ret = new ExactMatchPart(ret, new String(pat, startPos, lastPartPos - startPos), isFileSystemCaseSensitive()); break; case JUST_FOUND_STAR_STAR_AT_END: case JUST_FOUND_STAR_STAR_IN_MIDDLE: case END_PATH: break; } if ((!isAbsolute && !(ret instanceof StrictStarStarPart)) || (isAbsolute && ret == null)) { ret = new StrictStarStarPart(ret); } if (ret == null) { ret = new ExactMatchPart(null, "", isFileSystemCaseSensitive()); } return ret; } IgnoreFilePattern(@NotNull PathPart rootPart, boolean isNegative);   IgnoreFilePattern(@Nullable String original, @NotNull PathPart rootPart, boolean isNegative); boolean isIgnoreMatchType(); @Override String toString(); boolean matches(final List<String> pathParts);  }
@Test public void testCreatePattern_Empty() { try { IgnoreFilePattern.createPattern(""); fail("did not throw IAE"); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), is("pattern cannot be empty")); } }
@Test public void testCreatePattern_Slash() { IgnoreFilePattern.PathPart res = IgnoreFilePattern.createPattern("/"); assertThat(res, instanceOf(IgnoreFilePattern.StrictStarStarPart.class)); assertThat(res.match("a"), isMatch().isLast().hasNext()); assertThat(res.match(""), isMatch().isLast().hasNext()); }
@Test public void testCreatePattern_StarStar() { IgnoreFilePattern.PathPart res = IgnoreFilePattern.createPattern("**"); assertThat(res, instanceOf(IgnoreFilePattern.StrictStarStarPart.class)); assertThat(res.match("a"), isMatch().isLast().hasNext()); assertThat(res.match(""), isMatch().isLast().hasNext()); IgnoreFilePattern.PathNameMatchResult match = res.match("a"); assertThat(match.next, is(res)); }
@Test public void testCreatePattern_SlashStarStar() { IgnoreFilePattern.PathPart res = IgnoreFilePattern.createPattern("/**"); assertThat(res, instanceOf(IgnoreFilePattern.StrictStarStarPart.class)); assertThat(res.match("a"), isMatch().isLast().hasNext()); assertThat(res.match(""), isMatch().isLast().hasNext()); IgnoreFilePattern.PathNameMatchResult match = res.match("a"); assertThat(match.next, is(res)); }
@Test public void testCreatePattern_SlashAStar() { IgnoreFilePattern.PathPart res = IgnoreFilePattern.createPattern("/a*"); assertThat(res, instanceOf(IgnoreFilePattern.StarMatchPart.class)); assertThat(res.match("a"), isMatch().isLast()); assertThat(res.match("ab"), isMatch().isLast()); assertThat(res.match("b"), notMatch()); assertThat(res.match("ba"), notMatch()); assertThat(res.match(""), notMatch()); }
@Test public void testCreatePattern_SlashStarA() { IgnoreFilePattern.PathPart res = IgnoreFilePattern.createPattern("/*a"); assertThat(res, instanceOf(IgnoreFilePattern.StarMatchPart.class)); assertThat(res.match("a"), isMatch().isLast()); assertThat(res.match("ba"), isMatch().isLast()); assertThat(res.match("b"), notMatch()); assertThat(res.match("ab"), notMatch()); assertThat(res.match(""), notMatch()); }
@Test public void testCreatePattern_SlashAStarB() { IgnoreFilePattern.PathPart res = IgnoreFilePattern.createPattern("/a*b"); assertThat(res, instanceOf(IgnoreFilePattern.StarMatchPart.class)); assertThat(res.match("a"), notMatch()); assertThat(res.match("ab"), isMatch().isLast()); assertThat(res.match("b"), notMatch()); assertThat(res.match("ab"), isMatch().isLast()); assertThat(res.match("acb"), isMatch().isLast()); assertThat(res.match("abc"), notMatch()); assertThat(res.match(""), notMatch()); }
@Test public void testCreatePattern_SlashAStarBStarC() { IgnoreFilePattern.PathPart res = IgnoreFilePattern.createPattern("/a*b*c"); assertThat(res, instanceOf(IgnoreFilePattern.StarMatchPart.class)); assertThat(res.match("a"), notMatch()); assertThat(res.match("b"), notMatch()); assertThat(res.match("c"), notMatch()); assertThat(res.match("ab"), notMatch()); assertThat(res.match("bc"), notMatch()); assertThat(res.match("aeb"), notMatch()); assertThat(res.match("bec"), notMatch()); assertThat(res.match("acb"), notMatch()); assertThat(res.match("bac"), notMatch()); assertThat(res.match("acb"), notMatch()); assertThat(res.match("abc"), isMatch().isLast()); assertThat(res.match("aabbcc"), isMatch().isLast()); assertThat(res.match("aebec"), isMatch().isLast()); assertThat(res.match(""), notMatch()); }
@Test public void testCreatePattern_SlashAStarBStarCStarD() { IgnoreFilePattern.PathPart res = IgnoreFilePattern.createPattern("/a*b*c*d"); assertThat(res, instanceOf(IgnoreFilePattern.StarMatchPart.class)); assertThat(res.match("a"), notMatch()); assertThat(res.match("b"), notMatch()); assertThat(res.match("c"), notMatch()); assertThat(res.match("ab"), notMatch()); assertThat(res.match("bc"), notMatch()); assertThat(res.match("aeb"), notMatch()); assertThat(res.match("bec"), notMatch()); assertThat(res.match("acb"), notMatch()); assertThat(res.match("bac"), notMatch()); assertThat(res.match("acb"), notMatch()); assertThat(res.match("abd"), notMatch()); assertThat(res.match("abc"), notMatch()); assertThat(res.match("abcde"), notMatch()); assertThat(res.match("bcd"), notMatch()); assertThat(res.match("ad"), notMatch()); assertThat(res.match("abed"), notMatch()); assertThat(res.match("abcd"), isMatch().isLast()); assertThat(res.match("aabbccdd"), isMatch().isLast()); assertThat(res.match("aebeced"), isMatch().isLast()); assertThat(res.match(""), notMatch()); }
@Test public void testCreatePattern_SlashAStarBStarCStarDStarE() { IgnoreFilePattern.PathPart res = IgnoreFilePattern.createPattern("/a*b*c*d*e"); assertThat(res, instanceOf(IgnoreFilePattern.StarMatchPart.class)); assertThat(res.match("a"), notMatch()); assertThat(res.match("b"), notMatch()); assertThat(res.match("c"), notMatch()); assertThat(res.match("ab"), notMatch()); assertThat(res.match("bc"), notMatch()); assertThat(res.match("aeb"), notMatch()); assertThat(res.match("bec"), notMatch()); assertThat(res.match("acb"), notMatch()); assertThat(res.match("bac"), notMatch()); assertThat(res.match("acb"), notMatch()); assertThat(res.match("abd"), notMatch()); assertThat(res.match("abc"), notMatch()); assertThat(res.match("abcd"), notMatch()); assertThat(res.match("bcd"), notMatch()); assertThat(res.match("ad"), notMatch()); assertThat(res.match("abed"), notMatch()); assertThat(res.match("abcde"), isMatch().isLast()); assertThat(res.match("aabbcbcdcddee"), isMatch().isLast()); assertThat(res.match("aebecedefe"), isMatch().isLast()); assertThat(res.match(""), notMatch()); }
@Test public void testCreatePattern_DoublePath() { IgnoreFilePattern.PathPart res1 = IgnoreFilePattern.createPattern("/a/b/"); assertThat(res1, instanceOf(IgnoreFilePattern.ExactMatchPart.class)); assertThat(res1.match("a"), isMatch().requiresMore().hasNext()); assertThat(res1.match("b"), notMatch()); IgnoreFilePattern.PathPart res2 = res1.match("a").next; assertThat(res2, instanceOf(IgnoreFilePattern.ExactMatchPart.class)); assertThat(res2.match("a"), notMatch()); assertThat(res2.match("b"), isMatch().requiresMore().hasNext()); IgnoreFilePattern.PathPart res3 = res2.match("b").next; assertThat(res3, instanceOf(IgnoreFilePattern.StrictStarStarPart.class)); assertThat(res3.match("a"), isMatch().isLast().hasNext()); assertThat(res3.match("b"), isMatch().isLast().hasNext()); }