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; |
} |
} |