/*******************************************************************************
* Copyright (c) 2010 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.usage.util.reader;
import java.io.Reader;
/**
* @author Andre Dietisheim
*/
public class ReadUntilAlternativesImpl extends ReadUntilImpl {
private char[][] allAlternatives;
private char[] currentAlternative;
private int alternativesIndex = -1;
public ReadUntilAlternativesImpl(Reader reader, String... stringAlternatives) {
super(reader);
initAlternativesCharSequences(stringAlternatives);
}
private void initAlternativesCharSequences(String... stringAlternatives) {
this.allAlternatives = new char[stringAlternatives.length][];
for (int i = 0; i < stringAlternatives.length; i++) {
this.allAlternatives[i] = stringAlternatives[i].toCharArray();
}
}
@Override
protected int getNumberOfCharactersToMatch() {
if (currentAlternative != null) {
return currentAlternative.length;
} else {
return 0;
}
}
@Override
protected boolean doesMatch(char character) {
if (currentAlternative == null || currentAlternative[getMatchingIndex()] != character) {
// current alternative does not match new character, select a new
// alternative
boolean newAlternativeSelected = matchAlternative(character);
if (!newAlternativeSelected) {
// no alternative matches current character + new one
setMatchingIndex(0);
}
return newAlternativeSelected;
} else {
return true;
}
}
/**
* Returns whether the given character matches an alternative (in other
* words the given character matches an alternative at the current matching
* index).
*
* @param character
* the character
* @return true, if successful
*/
private boolean matchAlternative(char character) {
for (int i = alternativesIndex + 1; i < allAlternatives.length; i++) {
char[] alternative = allAlternatives[i];
if (doesMatch(character, alternative)) {
this.currentAlternative = alternative;
this.alternativesIndex = i;
return true;
}
}
this.currentAlternative = null;
this.alternativesIndex = -1;
return false;
}
/**
* Returns whether the given potentially matching alternative (String)
* matches the currently selected alternative and the additional character.
*
* @param character
* @param potentiallyMatchingAlternative
* the new alternative that could match
* @return
*/
private boolean doesMatch(char character, char[] potentiallyMatchingAlternative) {
int currentMatchingIndex = getMatchingIndex();
for (int j = 0; j < currentMatchingIndex; j++) {
if (potentiallyMatchingAlternative[j] != currentAlternative[j]) {
return false;
}
}
return potentiallyMatchingAlternative[currentMatchingIndex] == character;
}
@Override
protected char[] getCharactersToMatch() {
return currentAlternative;
}
public String getAlternative() {
if (alternativesIndex >= 0) {
return new String(allAlternatives[alternativesIndex]);
} else {
return null;
}
}
}