Subversion Repositories general

Compare Revisions

Ignore whitespace Rev 1004 → Rev 1005

/zpath/trunk/src/ak/zpath/PathCreator.java
0,0 → 1,367
package ak.zpath;
 
import java.util.List;
import java.util.ArrayList;
import java.text.ParseException;
 
public class PathCreator
{
private PathElement element;
private List elements;
private PathParser pathParser = new PathParser();
 
public PathCreator()
{
}
 
public List createPath(String path)
throws ParseException
{
List tokens = pathParser.parse(path);
Token firstToken;
int pos = -1;
 
if(tokens.size() == 0)
throw new PathCreateException("Empty path", null);
 
firstToken = (Token)tokens.get(0);
elements = new ArrayList();
 
if(firstToken.getType() == Token.TOKEN_SLASH) {
// the path starts with slash
PathElement slashElement = new PathElement();
 
slashElement.setName("/");
elements.add(slashElement);
pos = 0;
}
 
element = null;
stateElementStart(tokens, pos);
if(element != null) elements.add(element); // add the last element
 
return elements;
}
 
private int stateElementStart(List tokens, int pos)
throws PathCreateException
{
Token token = (Token)tokens.get(++pos);
 
if(element != null) elements.add(element);
element = new PathElement();
 
switch(token.getType()) {
case Token.TOKEN_NAME:
element.setName(token.getValue());
pos = stateElementName(tokens, pos);
break;
 
default:
throw new PathCreateException("Element name expected", token);
}
 
return pos;
}
 
private int stateElementName(List tokens, int pos)
throws PathCreateException
{
if(++pos >= tokens.size()) return pos;
 
Token token = (Token)tokens.get(pos);
 
switch(token.getType()) {
case Token.TOKEN_SLASH:
pos = stateElementStart(tokens, pos);
break;
 
case Token.TOKEN_OPEN_BRACKET:
pos = stateElementCondition(tokens, pos);
break;
 
case Token.TOKEN_SHARP:
pos = stateOperandText(tokens, pos);
break;
 
case Token.TOKEN_AT:
pos = stateOperandAttribute(tokens, pos);
break;
 
default:
throw new PathCreateException(
"Element condition or operand expected", token);
}
 
return pos;
}
 
private int stateOperandText(List tokens, int pos)
throws PathCreateException
{
Token token = (Token)tokens.get(++pos);
 
element.setFirstOperand(PathElement.OPERAND_TEXT, null);
 
switch(token.getType()) {
case Token.TOKEN_ASSIGN:
element.setOperation(PathElement.OPERATION_ASSIGN);
pos = stateSecondOperand(tokens, pos);
break;
 
case Token.TOKEN_APPEND:
element.setOperation(PathElement.OPERATION_APPEND);
pos = stateSecondOperand(tokens, pos);
break;
 
default:
throw new PathCreateException(
"Assign or append operation expected", token);
}
 
return pos;
}
 
private int stateOperandAttribute(List tokens, int pos)
throws PathCreateException
{
Token token = (Token)tokens.get(++pos);
 
switch(token.getType()) {
case Token.TOKEN_NAME: {
element.setFirstOperand(PathElement.OPERAND_ATTRIBUTE, token.getValue());
token = (Token)tokens.get(++pos);
switch(token.getType()) {
case Token.TOKEN_ASSIGN:
element.setOperation(PathElement.OPERATION_ASSIGN);
pos = stateSecondOperand(tokens, pos);
break;
 
case Token.TOKEN_APPEND:
element.setOperation(PathElement.OPERATION_APPEND);
pos = stateSecondOperand(tokens, pos);
break;
 
default:
throw new PathCreateException(
"Assign or append operation expected", token);
}
break;
}
 
default:
throw new PathCreateException("Attribute name expected", token);
}
 
return pos;
}
 
private int stateSecondOperand(List tokens, int pos)
throws PathCreateException
{
Token token = (Token)tokens.get(++pos);
 
switch(token.getType()) {
case Token.TOKEN_VARIABLE:
element.setSecondOperand(PathElement.OPERAND_VARIABLE, token.getValue());
if(pos < tokens.size() - 1)
throw new PathCreateException("Path end expected", token);
break;
 
case Token.TOKEN_STRING:
element.setSecondOperand(PathElement.OPERAND_STRING, token.getValue());
if(pos < tokens.size() - 1)
throw new PathCreateException("Path end expected", token);
break;
 
default:
throw new PathCreateException("Second operand expected", token);
}
 
element.validateOperands(); // must be end of the path
 
return pos;
}
 
private int stateElementCondition(List tokens, int pos)
throws PathCreateException
{
Token token = (Token)tokens.get(++pos);
 
switch(token.getType()) {
case Token.TOKEN_NEW:
pos = stateNew(tokens, pos);
break;
 
case Token.TOKEN_SHARP:
case Token.TOKEN_AT:
pos = stateLogicalCondition(tokens, pos);
break;
 
default:
throw new PathCreateException("Element condition expected", token);
}
 
return pos;
}
 
private int stateLogicalCondition(List tokens, int pos)
throws PathCreateException
{
Token token = (Token)tokens.get(pos); // do not go to the next token
 
switch(token.getType()) {
case Token.TOKEN_SHARP:
pos = stateConditionText(tokens, pos);
break;
 
case Token.TOKEN_AT:
pos = stateConditionAttribute(tokens, pos);
break;
 
default:
throw new PathCreateException("Element condition expected", token);
}
 
return pos;
}
 
private int stateConditionText(List tokens, int pos)
throws PathCreateException
{
Token token = (Token)tokens.get(++pos);
 
element.addCondition();
element.setFirstCondition(PathElement.OPERAND_TEXT, null);
 
switch(token.getType()) {
case Token.TOKEN_EQUAL:
element.setConditionOperation(PathElement.OPERATION_EQUAL);
pos = stateConditionSecond(tokens, pos);
break;
 
default:
throw new PathCreateException("Compare operator expected", token);
}
 
return pos;
}
 
private int stateConditionAttribute(List tokens, int pos)
throws PathCreateException
{
Token token = (Token)tokens.get(++pos);
 
element.addCondition();
 
switch(token.getType()) {
case Token.TOKEN_NAME: {
element.setFirstCondition(
PathElement.OPERAND_ATTRIBUTE, token.getValue());
token = (Token)tokens.get(++pos);
switch(token.getType()) {
case Token.TOKEN_EQUAL:
element.setConditionOperation(PathElement.OPERATION_EQUAL);
pos = stateConditionSecond(tokens, pos);
break;
 
default:
throw new PathCreateException("Compare operation expected", token);
}
break;
}
 
default:
throw new PathCreateException("Attibute name expected", token);
}
 
return pos;
}
 
private int stateConditionSecond(List tokens, int pos)
throws PathCreateException
{
Token token = (Token)tokens.get(++pos);
switch(token.getType()) {
case Token.TOKEN_VARIABLE:
element.setSecondCondition(
PathElement.OPERAND_VARIABLE, token.getValue());
break;
 
case Token.TOKEN_STRING:
element.setSecondCondition(
PathElement.OPERAND_STRING, token.getValue());
break;
 
default:
throw new PathCreateException(
"Second condition operand expected", token);
}
element.validateCondition(); // must be end of condition
 
token = (Token)tokens.get(++pos);
switch(token.getType()) {
case Token.TOKEN_CLOSE_BRACKET:
pos = stateConditionEnd(tokens, pos);
break;
 
case Token.TOKEN_AND:
pos++; // go to next token for stateLogicalCondition
pos = stateLogicalCondition(tokens, pos);
break;
 
default:
throw new PathCreateException(
"End of conditions or next condition expected", token);
}
 
return pos;
}
 
private int stateNew(List tokens, int pos)
throws PathCreateException
{
Token token = (Token)tokens.get(++pos);
 
element.setNew();
 
switch(token.getType()) {
case Token.TOKEN_CLOSE_BRACKET:
pos = stateConditionEnd(tokens, pos);
break;
 
default:
throw new PathCreateException("End of conditions expected", token);
}
 
return pos;
}
 
private int stateConditionEnd(List tokens, int pos)
throws PathCreateException
{
if(++pos >= tokens.size()) return pos;
 
Token token = (Token)tokens.get(pos);
 
switch(token.getType()) {
case Token.TOKEN_SLASH:
stateElementStart(tokens, pos); // start new path element
break;
 
case Token.TOKEN_SHARP:
pos = stateOperandText(tokens, pos);
break;
 
case Token.TOKEN_AT:
pos = stateOperandAttribute(tokens, pos);
break;
 
default:
throw new PathCreateException(
"End of element description expected", token);
}
 
return pos;
}
}