blob: dfb6c37c034456ba7b0523583a73a52800f48bad [file] [log] [blame]
/*****************************************************************************
* 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;
}
}
}