/*******************************************************************************
* Copyright (c) 2007, 2009 Red Hat, Inc.
* 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat - initial API and implementation
*******************************************************************************/
package org.eclipse.linuxtools.internal.rpm.ui.editor.rules;
import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IPredicateRule;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.Token;
public class AuthorEmailRule implements IPredicateRule {
/** Buffer used for pattern detection */
private StringBuilder fBuffer = new StringBuilder();
/** The success token */
private IToken token;
protected static final char START_CHAR = '<';
protected static final char END_CHAR = '>';
protected static final char[] INTER_CHARS = { '@', '.' };
protected static final int STATE_START = 0;
protected static final int STATE_OPENED = 1;
protected static final int STATE_AT = 2;
protected static final int STATE_PERIOD = 3;
protected static final int STATE_DONE = 4;
public AuthorEmailRule(IToken token) {
this.token = token;
}
@Override
public IToken getSuccessToken() {
return token;
}
@Override
public IToken evaluate(ICharacterScanner scanner, boolean resume) {
/*
* whether we think we're reading the ending sequence, i.e. the next
* section heading
*/
int state = STATE_START;
fBuffer.setLength(0);
int c;
do {
c = scanner.read();
fBuffer.append((char) c);
// we have reached the end of file or line prematurely, this is not
// considered success
if (c == ICharacterScanner.EOF || (char) c == '\n') {
unreadBuffer(scanner, fBuffer);
return Token.UNDEFINED;
}
// we encountered the opening character at the beginning
if (state == STATE_START && (char) c == START_CHAR) {
state++;
} else if (state == STATE_OPENED) {
// we encountered the first neccessary intermediary char
if ((char) c == INTER_CHARS[0]) {
state++;
}
// check if we have a valid char
if (! (Character.isLetterOrDigit((char) c) || c == '.' || c == '_' || c == '-' || c == '@')){
unreadBuffer(scanner, fBuffer);
return Token.UNDEFINED;
}
// we just keep reading
} else if (state == STATE_AT) {
// we encountered the second neccessary intermediary char
if ((char) c == INTER_CHARS[1]) {
state++;
}
// check if we have a valid char
if (! (Character.isLetterOrDigit((char) c) || c == '.' || c == '_' || c == '-')){
unreadBuffer(scanner, fBuffer);
return Token.UNDEFINED;
}
// we just keep reading
} else if (state == STATE_PERIOD) {
// the last char before the ending char cannot be a '.'
if ((char) c == END_CHAR && fBuffer.charAt(fBuffer.length() - 1) != '.') {
state++;
} else if ((char) c == END_CHAR){
unreadBuffer(scanner, fBuffer);
return Token.UNDEFINED;
}
} else {
unreadBuffer(scanner, fBuffer);
return Token.UNDEFINED;
}
} while (state != STATE_DONE);
// we've gone through all states until we've reached STATE_DONE, success
return token;
}
@Override
public IToken evaluate(ICharacterScanner scanner) {
return evaluate(scanner, false);
}
/**
* Returns the characters in the buffer to the scanner.
*
* @param scanner
* the scanner to be used
*/
protected void unreadBuffer(ICharacterScanner scanner, StringBuilder buffer) {
for (int i = buffer.length() - 1; i >= 0; i--) {
scanner.unread();
}
}
}