/***************************************************************************************************
 * Copyright (c) 2003, 2004 IBM Corporation and others. All rights reserved. This program and the
 * accompanying materials are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 * 
 * Contributors: IBM Corporation - initial API and implementation
 **************************************************************************************************/
package org.eclipse.jst.j2ee.internal.ejb.project;


import java.util.Vector;

public class StringMatcher {
	public static class Position {
		int start; //inclusive
		int end; //exclusive

		public Position(int start, int end) {
			this.start = start;
			this.end = end;
		}

		public int getStart() {
			return start;
		}

		public int getEnd() {
			return end;
		}
	}

	protected String fPattern;
	protected int fLength; // pattern length
	protected boolean fIgnoreWildCards;
	protected boolean fIgnoreCase;
	protected boolean fHasLeadingStar;
	protected boolean fHasTrailingStar;
	protected String fSegments[]; //the given pattern is split into * separated segments
	/* boundary value beyond which we don't need to search in the text */
	protected int fBound = 0;
	protected static final char fSingleWildCard = '\u0000';

	/**
	 * StringMatcher constructor takes in a String object that is a simple pattern which may contain
	 * |221*|222 for 0 and many characters and |221?|222 for exactly one character. Also takes as
	 * parameter a boolean object specifying if case should be ignored
	 * 
	 * @deprecated Use StringMatcher(pattern, ignoreCase, ignoreWildCards).
	 */
	public StringMatcher(String aPattern, boolean ignoreCase) {
		this(aPattern, ignoreCase, false);
	}

	/**
	 * StringMatcher constructor takes in a String object that is a simple pattern which may contain
	 * |221*|222 for 0 and many characters and |221?|222 for exactly one character.
	 * 
	 * Literal '*' and '?' characters must be escaped in the pattern e.g., "\*" means literal "*",
	 * etc.
	 * 
	 * Escaping any other character (including the escape character itself), just results in that
	 * character in the pattern. e.g., "\a" means "a" and "\\" means "\"
	 * 
	 * If invoking the StringMatcher with string literals in Java, don't forget escape characters
	 * are represented by "\\".
	 * 
	 * @param aPattern
	 *            the pattern to match text against
	 * @param ignoreCase
	 *            if true, case is ignored
	 * @param ignoreWildCards
	 *            if true, wild cards and their escape sequences are ignored (everything is taken
	 *            literally).
	 */
	public StringMatcher(String aPattern, boolean ignoreCase, boolean ignoreWildCards) {
		fIgnoreCase = ignoreCase;
		fIgnoreWildCards = ignoreWildCards;
		fLength = aPattern.length();

		/* convert case */
		if (fIgnoreCase) {
			fPattern = aPattern.toUpperCase();
		} else {
			fPattern = aPattern;
		}

		if (fIgnoreWildCards) {
			parseNoWildCards();
		} else {
			parseWildCards();
		}
	}

	/**
	 * Find the first occurrence of the pattern between <code>start</code)(inclusive) 
	 * and <code>end</code>(exclusive).  
	 * @param <code>text</code>, the String object to search in 
	 * @param <code>start</code>, the starting index of the search range, inclusive
	 * @param <code>end</code>, the ending index of the search range, exclusive
	 * @return an <code>StringMatcher.Position</code> object that keeps the starting 
	 * (inclusive) and ending positions (exclusive) of the first occurrence of the 
	 * pattern in the specified range of the text; return null if not found or subtext
	 * is empty (start==end). A pair of zeros is returned if pattern is empty string
	 * Note that for pattern like "*abc*" with leading and trailing stars, position of "abc"
	 * is returned. For a pattern like"*??*" in text "abcdf", (1,3) is returned
	 */

	public StringMatcher.Position find(String text, int start, int end) {
		if (fPattern == null || text == null)
			throw new IllegalArgumentException();
		int localStart = start;
		int localEnd = end;
		
		int tlen = text.length();
		if (localStart < 0)
			localStart = 0;
		if (localEnd > tlen)
			localEnd = tlen;
		if (localEnd < 0 || localStart >= localEnd)
			return null;
		if (fLength == 0)
			return new Position(localStart, localStart);
		if (fIgnoreWildCards) {
			int x = posIn(text, localStart, localEnd);
			if (x < 0)
				return null;
			return new Position(x, x + fLength);
		}

		int segCount = fSegments.length;
		if (segCount == 0)//pattern contains only '*'(s)
			return new Position(localStart, localEnd);

		int curPos = localStart;
		int matchStart = -1;
		for (int i = 0; i < segCount && curPos < localEnd; ++i) {
			String current = fSegments[i];
			int nextMatch = regExpPosIn(text, curPos, localEnd, current);
			if (nextMatch < 0)
				return null;
			if (i == 0)
				matchStart = nextMatch;
			curPos = nextMatch + current.length();
		}
		return new Position(matchStart, curPos);
	}

	/**
	 * match the given <code>text</code> with the pattern
	 * 
	 * @return true if matched eitherwise false
	 * @param <code>text</code>, a String object
	 */
	public boolean match(String text) {
		return match(text, 0, text.length());
	}

	/**
	 * Given the starting (inclusive) and the ending (exclusive) poisitions in the <code>text</code>,
	 * determine if the given substring matches with aPattern
	 * 
	 * @return true if the specified portion of the text matches the pattern
	 * @param String
	 *            <code>text</code>, a String object that contains the substring to match
	 * @param int
	 *            <code>start<code> marks the starting position (inclusive) of the substring
	 * @param int <code>end<code> marks the ending index (exclusive) of the substring
	 */
	public boolean match(String text, int start, int end) {
		if (null == fPattern || null == text)
			throw new IllegalArgumentException();

		int localStart = start;
		int localEnd = end;
		
		if (localStart > localEnd)
			return false;

		if (fIgnoreWildCards)
			return fPattern.regionMatches(fIgnoreCase, 0, text, localStart, fLength);
		int segCount = fSegments.length;
		if (segCount == 0)//pattern contains only '*'(s) or empty pattern
			return true;
		if (localStart == localEnd)
			return fLength == 0;
		if (fLength == 0)
			return localStart == localEnd;

		int tlen = text.length();
		if (localStart < 0)
			localStart = 0;
		if (localEnd > tlen)
			localEnd = tlen;

		int tCurPos = localStart;
		int bound = localEnd - fBound;
		if (bound < 0)
			return false;
		int i = 0;
		String current = fSegments[i];
		int segLength = current.length();

		/* process first segment */
		if (!fHasLeadingStar) {
			if (!regExpRegionMatches(text, localStart, current, 0, segLength)) {
				return false;
			}
			++i;
			tCurPos = tCurPos + segLength;
		}

		/* process middle segments */
		for (; i < segCount && tCurPos <= bound; ++i) {
			current = fSegments[i];
			int currentMatch;
			int k = current.indexOf(fSingleWildCard);
			if (k < 0) {
				currentMatch = textPosIn(text, tCurPos, localEnd, current);
				if (currentMatch < 0)
					return false;
			} else {
				currentMatch = regExpPosIn(text, tCurPos, localEnd, current);
				if (currentMatch < 0)
					return false;
			}
			tCurPos = currentMatch + current.length();
		}

		/* process final segment */
		if (!fHasTrailingStar && tCurPos != localEnd) {
			int clen = current.length();
			return regExpRegionMatches(text, localEnd - clen, current, 0, clen);
		}
		return i == segCount;
	}

	/**
	 * This method parses the given pattern into segments seperated by wildcard '*' characters.
	 * Since wildcards are not being used in this case, the pattern consists of a single segment.
	 */
	private void parseNoWildCards() {
		fSegments = new String[1];
		fSegments[0] = fPattern;
		fBound = fLength;
	}

	/**
	 * This method parses the given pattern into segments seperated by wildcard '*' characters.
	 * 
	 * @param p,
	 *            a String object that is a simple regular expression with |221*|222 and/or
	 *            |221?|222
	 */
	private void parseWildCards() {
		if (fPattern.startsWith("*"))//$NON-NLS-1$
			fHasLeadingStar = true;
		if (fPattern.endsWith("*")) {//$NON-NLS-1$
			/* make sure it's not an escaped wildcard */
			if (fLength > 1 && fPattern.charAt(fLength - 2) != '\\') {
				fHasTrailingStar = true;
			}
		}

		Vector temp = new Vector();

		int pos = 0;
		StringBuffer buf = new StringBuffer();
		while (pos < fLength) {
			char c = fPattern.charAt(pos++);
			switch (c) {
				case '\\' :
					if (pos >= fLength) {
						buf.append(c);
					} else {
						char next = fPattern.charAt(pos++);
						/* if it's an escape sequence */
						if (next == '*' || next == '?' || next == '\\') {
							buf.append(next);
						} else {
							/* not an escape sequence, just insert literally */
							buf.append(c);
							buf.append(next);
						}
					}
					break;
				case '*' :
					if (buf.length() > 0) {
						/* new segment */
						temp.addElement(buf.toString());
						fBound += buf.length();
						buf.setLength(0);
					}
					break;
				case '?' :
					/* append special character representing single match wildcard */
					buf.append(fSingleWildCard);
					break;
				default :
					buf.append(c);
			}
		}

		/* add last buffer to segment list */
		if (buf.length() > 0) {
			temp.addElement(buf.toString());
			fBound += buf.length();
		}

		fSegments = new String[temp.size()];
		temp.copyInto(fSegments);
	}

	/**
	 * @param <code>text</code>, a string which contains no wildcard
	 * @param <code>start</code>, the starting index in the text for search, inclusive
	 * @param <code>end</code>, the stopping point of search, exclusive
	 * @return the starting index in the text of the pattern , or -1 if not found
	 */
	protected int posIn(String text, int start, int end) {//no wild card in pattern
		int max = end - fLength;

		if (!fIgnoreCase) {
			int i = text.indexOf(fPattern, start);
			if (i == -1 || i > max)
				return -1;
			return i;
		}

		for (int i = start; i <= max; ++i) {
			if (text.regionMatches(true, i, fPattern, 0, fLength))
				return i;
		}

		return -1;
	}

	/**
	 * @param <code>text</code>, a simple regular expression that may only contain '?'(s)
	 * @param <code>start</code>, the starting index in the text for search, inclusive
	 * @param <code>end</code>, the stopping point of search, exclusive
	 * @param <code>p</code>, a simple regular expression that may contains '?'
	 * @param <code>caseIgnored</code>, wether the pattern is not casesensitive
	 * @return the starting index in the text of the pattern , or -1 if not found
	 */
	protected int regExpPosIn(String text, int start, int end, String p) {
		int plen = p.length();

		int max = end - plen;
		for (int i = start; i <= max; ++i) {
			if (regExpRegionMatches(text, i, p, 0, plen))
				return i;
		}
		return -1;
	}

	/**
	 * 
	 * @return boolean
	 * @param <code>text</code>, a String to match
	 * @param <code>start</code>, int that indicates the starting index of match, inclusive
	 * @param <code>end</code> int that indicates the ending index of match, exclusive
	 * @param <code>p</code>, String, String, a simple regular expression that may contain '?'
	 * @param <code>ignoreCase</code>, boolean indicating whether code>p</code> is case sensitive
	 */
	protected boolean regExpRegionMatches(String text, int tStart, String p, int pStart, int plen) {
		int localTStart = tStart;
		int localPStart = pStart;
		int localPlen = plen;
		while (localPlen-- > 0) {
			char tchar = text.charAt(localTStart++);
			char pchar = p.charAt(localPStart++);

			/* process wild cards */
			if (!fIgnoreWildCards) {
				/* skip single wild cards */
				if (pchar == fSingleWildCard) {
					continue;
				}
			}
			if (pchar == tchar)
				continue;
			if (fIgnoreCase) {
				char tc = Character.toUpperCase(tchar);
				if (tc == pchar)
					continue;
			}
			return false;
		}
		return true;
	}

	/**
	 * @param <code>text</code>, the string to match
	 * @param <code>start</code>, the starting index in the text for search, inclusive
	 * @param <code>end</code>, the stopping point of search, exclusive
	 * @param code>p
	 *            </code>, a string that has no wildcard
	 * @param <code>
	 *            ignoreCase</code>, boolean indicating wether code>p</code> is case sensitive
	 * @return the starting index in the text of the pattern , or -1 if not found
	 */
	protected int textPosIn(String text, int start, int end, String p) {

		int plen = p.length();
		int max = end - plen;

		if (!fIgnoreCase) {
			int i = text.indexOf(p, start);
			if (i == -1 || i > max)
				return -1;
			return i;
		}

		for (int i = 0; i <= max; ++i) {
			if (text.regionMatches(true, i, p, 0, plen))
				return i;
		}

		return -1;
	}
}