These steps show how the object model is created for this xpath expression:
/Task[name = 'sample task' or @containingProject[name = 'a project']]
We obtains these list of operation and token after the parsing of the xpath expression:
compiler.getOpMap() = [1, 60, 29, 58, 50, 4, 4, 35, 40, 51, 6, 34, -2, 1, 30, 45, 2, 42, 5, 14, 29, 9, 40, 6, 6, 34, -2, 3, -1, 21, 3, 5, 29, 26, 39, 23, 6, 34, -2, 8, 30, 17, 5, 14, 29, 9, 40, 6, 6, 34, -2, 10, -1, 21, 3, 12, -1, -1, -1, -1, 0, 0, 0, 0]
Codes in red matches opCodes from the OpCodes class.
compiler.getTokenQueue() = [/, Task, [, name, =, sample task, or, @,
containingProject, [, name, =, a project, ], ], null, null, null, null]
These arrays are be passed as parameters of the StartXPath constructor. The build(int position) method starts the conversion of the operation codes array to the object model.
position | opCode | class | token |
0 | 1 = OP_XPATH | XPathPredicate |
Current Stack is initialized in XPathPredicate class.
position | opCode | class | token |
2 | 29 = OP_LOCATIONPATH | LocationPath |
Move to next opCode.
position | opCode | class | token |
4 | 50 = FROM_ROOT | FromRoot |
Determine if it is a subPredicate. (subPredicate = false)
position | opCode | class | token |
7 | 35 = NODETYPE_ROOT | Root |
Move to next opCode.
position | opCode | class | token |
8 | 40 = FROM_CHILDREN | FromChildren |
Determine if it is a subPredicate. (subPredicate = true)
position | opCode | class | token |
11 | 34 = NODENAME | Name | Task |
Initialize the first Table.
position | opCode | class | token |
14 | 30 = OP_PREDICATE | XPathPredicate |
Determine which Stack will be used.
position | opCode | class | token |
16 | 2 = OP_OR | Or |
Initialize the Predicate.
position | opCode | class | token |
18 | 5 = OP_EQUALS | Equals |
Initialize the FieldCondition.
position | opCode | class | token |
20 | 29 = OP_LOCATIONPATH | LocationPath |
Move to next opCode.
position | opCode | class | token |
22 | 40 = FROM_CHILDREN | FromChildren |
Determine if it is a subPredicate. (subPredicate = true)
position | opCode | class | token |
25 | 34 = NODENAME | Name | name |
Set FieldCondition.property to token value.
position | opCode | class | token |
29 | 21 = OP_LITERAL | Literal | 'sample task' |
Set FieldCondition.value to token value.
position | opCode | class | token |
32 | 29 = OP_LOCATIONPATH | LocationPath |
Move to next opCode.
position | opCode | class | token |
34 | 39 = FROM_ATTRIBUTES | FromAttribute |
Calls because of the @ character. Move to the next opCode
position | opCode | class | token |
37 | 34 = NODENAME | Name | containingProject |
Create a new Predicate with new ContainerCondition that contains a new Table in its subTable Stack. Table name will start with @ because the preceding operator is FROM_ATTRIBUTE and will be followed by the token value.
position | opCode | class | token |
40 | 30 = OP_PREDICATE | XPathPredicate |
Define the subTable Stack as the current Stack.
position | opCode | class | token |
42 | 5 = OP_EQUALS | Equals |
Create a new Predicate under Table of the current Stack and add a FieldCondition to it.
position | opCode | class | token |
44 | 29 = OP_LOCATIONPATH | LocationPath |
Move to next opCode.
position | opCode | class | token |
46 | 40 = FROM_CHILDREN | FromChildren |
Determine if it is a subPredicate. (subPredicate = true)
position | opCode | class | token |
49 | 34 = NODENAME | Name | name |
Set FieldCondition.property to token value.
position | opCode | class | token |
53 | 21 = OP_LITERAL | Literal | 'a project' |
Set FieldCondition.value to token value.
In the StartXPath.notifyPostBuild method. The predicate of each Table is converted to an ArrayList of Conditions that is kept in the Table.conditions field. The conditions of this ArrayList will be use to perfom the conversion to an SQL string.