/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.netbeans.lib.cvsclient.util; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * @author Thomas Singer */ public class SimpleStringPattern implements StringPattern { private static final char MATCH_EACH = '*'; private static final char MATCH_ONE = '?'; private final List subPatterns = new LinkedList(); /** * Creates a SimpleStringPattern for the specified definition. The definition might contain two special characters ('*' and '?'). */ public SimpleStringPattern(String definition) { splitInSubPattern(definition); } /** * Returns whether the specified string matches thiz pattern. */ @Override public boolean doesMatch(String string) { int index = 0; SubPattern subPattern = null; for (Iterator it = subPatterns.iterator(); it.hasNext();) { subPattern = (SubPattern) it.next(); index = subPattern.doesMatch(string, index); if (index < 0) { return false; } } if (index == string.length()) { return true; } if (subPattern == null) { return false; } return subPattern.checkEnding(string, index); } private void splitInSubPattern(String definition) { char prevSubPattern = ' '; int prevIndex = 0; for (int index = 0; index >= 0;) { prevIndex = index; index = definition.indexOf(MATCH_EACH, prevIndex); if (index >= 0) { String match = definition.substring(prevIndex, index); addSubPattern(match, prevSubPattern); prevSubPattern = MATCH_EACH; index++; continue; } index = definition.indexOf(MATCH_ONE, prevIndex); if (index >= 0) { String match = definition.substring(prevIndex, index); addSubPattern(match, prevSubPattern); prevSubPattern = MATCH_ONE; index++; continue; } } String match = definition.substring(prevIndex); addSubPattern(match, prevSubPattern); } private void addSubPattern(String match, char subPatternMode) { SubPattern subPattern = null; switch (subPatternMode) { case MATCH_EACH: subPattern = new MatchEachCharPattern(match); break; case MATCH_ONE: subPattern = new MatchOneCharPattern(match); break; default: subPattern = new MatchExactSubPattern(match); break; } subPatterns.add(subPattern); } @Override public String toString() { StringBuffer buffer = new StringBuffer(); for (Iterator it = subPatterns.iterator(); it.hasNext();) { SubPattern subPattern = (SubPattern) it.next(); buffer.append(subPattern.toString()); } return buffer.toString(); } @Override public boolean equals(Object obj) { if (!(obj instanceof SimpleStringPattern)) { return false; } return subPatterns.equals(((SimpleStringPattern) obj).subPatterns); } @Override public int hashCode() { return -subPatterns.hashCode(); } public static void main(String[] arguments) { StringPattern sp = new SimpleStringPattern("a*b"); // NOI18N test(sp, "ab", true); // NOI18N test(sp, "aab", true); // NOI18N test(sp, "ba", false); // NOI18N test(sp, "abc", false); // NOI18N sp = new SimpleStringPattern("*.txt"); // NOI18N test(sp, "datei.txt", true); // NOI18N test(sp, ".txt", true); // NOI18N test(sp, "datei.tx", false); // NOI18N test(sp, "datei.txt.txt", true); // NOI18N sp = new SimpleStringPattern("datei*1*"); // NOI18N test(sp, "datei0.txt", false); // NOI18N test(sp, "datei1.txt", true); // NOI18N test(sp, "datei.tx", false); // NOI18N test(sp, "datei1.txt.txt", true); // NOI18N sp = new SimpleStringPattern("Makefile"); // NOI18N test(sp, "Makefile", true); // NOI18N test(sp, "Makefile.mak", false); // NOI18N test(sp, "Makefile1", false); // NOI18N test(sp, ".Makefile", false); // NOI18N test(sp, ".Makefile.", false); // NOI18N sp = new SimpleStringPattern("*~"); // NOI18N test(sp, "datei~", true); // NOI18N test(sp, "datei~1", false); // NOI18N test(sp, "datei~1~", true); // NOI18N // Equality: SimpleStringPattern pattern1 = new SimpleStringPattern("*.class"); SimpleStringPattern pattern2 = new SimpleStringPattern("*.class"); System.err.println(pattern1 + ".equals(" + pattern2 + ") = " + pattern1.equals(pattern2)); pattern1 = new SimpleStringPattern("?.class"); pattern2 = new SimpleStringPattern("*.class"); System.err.println(pattern1 + ".equals(" + pattern2 + ") = " + pattern1.equals(pattern2)); pattern1 = new SimpleStringPattern("*.clazz"); pattern2 = new SimpleStringPattern("*.class"); System.err.println(pattern1 + ".equals(" + pattern2 + ") = " + pattern1.equals(pattern2)); } private static void test(StringPattern sp, String testString, boolean shouldResult) { System.err.print('"' + sp.toString() + '"' + ": " + testString + " " + shouldResult); // NOI18N boolean doesMatch = sp.doesMatch(testString); if (doesMatch == shouldResult) { System.err.println(" proved"); // NOI18N } else { System.err.println(" **denied**"); // NOI18N } } private static abstract class SubPattern { protected final String match; protected SubPattern(String match) { this.match = match; } /** * @parameter string ... the whole string to test for matching * @parameter index ... the index in string where this' test should begin * @returns ... if successful the next test-position, if not -1 */ public abstract int doesMatch(String string, int index); public boolean checkEnding(String string, int index) { return false; } @Override public boolean equals(Object obj) { if (!this.getClass().isInstance(obj)) { return false; } return match.equals(((SubPattern) obj).match); } @Override public int hashCode() { return -match.hashCode(); } } private static class MatchExactSubPattern extends SubPattern { public MatchExactSubPattern(String match) { super(match); } @Override public int doesMatch(String string, int index) { if (!string.startsWith(match, index)) { return -1; } return index + match.length(); } @Override public String toString() { return match; } } private static class MatchEachCharPattern extends SubPattern { public MatchEachCharPattern(String match) { super(match); } @Override public int doesMatch(String string, int index) { int matchIndex = string.indexOf(match, index); if (matchIndex < 0) { return -1; } return matchIndex + match.length(); } @Override public boolean checkEnding(String string, int index) { return string.endsWith(match); } @Override public String toString() { return MATCH_EACH + match; } } private static class MatchOneCharPattern extends MatchExactSubPattern { public MatchOneCharPattern(String match) { super(match); } @Override public int doesMatch(String string, int index) { index++; if (string.length() < index) { return -1; } return super.doesMatch(string, index); } @Override public String toString() { return MATCH_ONE + match; } } }