/***************************************************************************** * Sun Public License Notice * * The contents of this file are subject to the Sun Public License Version * 1.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is available at http://www.sun.com/ * * The Original Code is the CVS Client Library. * The Initial Developer of the Original Code is Thomas Singer. * Portions created by Thomas Singer Copyright (C) 2001. * All Rights Reserved. * * Contributor(s): Thomas Singer, Milos Kleint *****************************************************************************/ package org.netbeans.lib.cvsclient.util; import org.jetbrains.annotations.NonNls; import java.util.ArrayList; import java.util.List; /** * @author Thomas Singer */ public final class SimpleStringPattern implements IStringPattern { private static final char MATCH_EACH = '*'; private static final char MATCH_ONE = '?'; private final List<SubPattern> subPatterns = new ArrayList(); /** * Creates a SimpleStringPattern for the specified definition. * The definition might contain two special characters ('*' and '?'). */ public SimpleStringPattern(@NonNls String definition) { splitInSubPattern(definition); } /** * Returns whether the specified string matches thiz pattern. */ public boolean doesMatch(String string) { int index = 0; SubPattern subPattern = null; for (int i = 0, length = subPatterns.size(); i < length ; i++) { subPattern = subPatterns.get(i); 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); } 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) { final String match = definition.substring(prevIndex, index); addSubPattern(match, prevSubPattern); prevSubPattern = MATCH_EACH; index++; continue; } index = definition.indexOf(MATCH_ONE, prevIndex); if (index >= 0) { final String match = definition.substring(prevIndex, index); addSubPattern(match, prevSubPattern); prevSubPattern = MATCH_ONE; index++; continue; } } final String match = definition.substring(prevIndex); addSubPattern(match, prevSubPattern); } private void addSubPattern(String match, char subPatternMode) { final SubPattern subPattern; 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); } public String toString() { final StringBuilder buffer = new StringBuilder(); for (int i = 0, length = subPatterns.size(); i < length; i++) { final SubPattern subPattern = subPatterns.get(i); buffer.append(subPattern.toString()); } return buffer.toString(); } private static abstract class SubPattern { protected final String match; protected SubPattern(String match) { this.match = match; } /** * @param string ... the whole string to compile for matching * @param index ... the index in string where this' compile should begin * @return ... if successful the next compile-position, if not -1 */ public abstract int doesMatch(String string, int index); public boolean checkEnding(String string) { return false; } } private static class MatchExactSubPattern extends SubPattern { public MatchExactSubPattern(String match) { super(match); } public int doesMatch(String string, int index) { if (!string.startsWith(match, index)) { return -1; } return index + match.length(); } public String toString() { return match; } } private static final class MatchEachCharPattern extends SubPattern { private MatchEachCharPattern(String match) { super(match); } public int doesMatch(String string, int index) { final int matchIndex = string.indexOf(match, index); if (matchIndex < 0) { return -1; } return matchIndex + match.length(); } public boolean checkEnding(String string) { return string.endsWith(match); } public String toString() { return MATCH_EACH + match; } } private static final class MatchOneCharPattern extends MatchExactSubPattern { private MatchOneCharPattern(String match) { super(match); } public int doesMatch(String string, int index) { index++; if (string.length() < index) { return -1; } return super.doesMatch(string, index); } public String toString() { return MATCH_ONE + match; } } }