Subversion Repositories general

Rev

Rev 1006 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1005 dev 1
package ak.zpath;
2
 
3
import java.util.List;
4
import java.util.ArrayList;
5
import java.text.ParseException;
6
 
7
public class PathCreator
8
{
9
  private PathElement element;
10
  private List        elements;
11
  private PathParser  pathParser = new PathParser();
12
 
13
  public PathCreator()
14
  {
15
  }
16
 
17
  public List createPath(String path)
18
    throws ParseException
19
  {
20
    List  tokens = pathParser.parse(path);
21
    Token firstToken;
22
    int   pos    = -1;
23
 
24
    if(tokens.size() == 0)
25
      throw new PathCreateException("Empty path", null);
26
 
27
    firstToken = (Token)tokens.get(0);
28
    elements   = new ArrayList();
29
 
30
    if(firstToken.getType() == Token.TOKEN_SLASH) {
31
      // the path starts with slash
32
      PathElement slashElement = new PathElement();
33
 
34
      slashElement.setName("/");
35
      elements.add(slashElement);
36
      pos = 0;
37
    }
38
 
39
    element = null;
40
    stateElementStart(tokens, pos);
41
    if(element != null) elements.add(element);  // add the last element
42
 
43
    return elements;
44
  }
45
 
46
  private int stateElementStart(List tokens, int pos)
47
    throws PathCreateException
48
  {
49
    Token token = (Token)tokens.get(++pos);
50
 
51
    if(element != null) elements.add(element);
52
    element = new PathElement();
53
 
54
    switch(token.getType()) {
55
      case Token.TOKEN_NAME:
56
        element.setName(token.getValue());
57
        pos = stateElementName(tokens, pos);
58
        break;
59
 
60
      default:
61
        throw new PathCreateException("Element name expected", token);
62
    }
63
 
64
    return pos;
65
  }
66
 
67
  private int stateElementName(List tokens, int pos)
68
    throws PathCreateException
69
  {
70
    if(++pos >= tokens.size()) return pos;
71
 
72
    Token token = (Token)tokens.get(pos);
73
 
74
    switch(token.getType()) {
75
      case Token.TOKEN_SLASH:
76
        pos = stateElementStart(tokens, pos);
77
        break;
78
 
79
      case Token.TOKEN_OPEN_BRACKET:
80
        pos = stateElementCondition(tokens, pos);
81
        break;
82
 
83
      case Token.TOKEN_SHARP:
84
        pos = stateOperandText(tokens, pos);
85
        break;
86
 
87
      case Token.TOKEN_AT:
88
        pos = stateOperandAttribute(tokens, pos);
89
        break;
90
 
91
      default:
92
        throw new PathCreateException(
93
          "Element condition or operand expected", token);
94
    }
95
 
96
    return pos;
97
  }
98
 
99
  private int stateOperandText(List tokens, int pos)
100
    throws PathCreateException
101
  {
102
    Token token = (Token)tokens.get(++pos);
103
 
104
    element.setFirstOperand(PathElement.OPERAND_TEXT, null);
105
 
106
    switch(token.getType()) {
107
      case Token.TOKEN_ASSIGN:
108
        element.setOperation(PathElement.OPERATION_ASSIGN);
109
        pos = stateSecondOperand(tokens, pos);
110
        break;
111
 
112
      case Token.TOKEN_APPEND:
113
        element.setOperation(PathElement.OPERATION_APPEND);
114
        pos = stateSecondOperand(tokens, pos);
115
        break;
116
 
117
      default:
118
        throw new PathCreateException(
119
          "Assign or append operation expected", token);
120
    }
121
 
122
    return pos;
123
  }
124
 
125
  private int stateOperandAttribute(List tokens, int pos)
126
    throws PathCreateException
127
  {
128
    Token token = (Token)tokens.get(++pos);
129
 
130
    switch(token.getType()) {
131
      case Token.TOKEN_NAME: {
132
        element.setFirstOperand(PathElement.OPERAND_ATTRIBUTE, token.getValue());
133
        token = (Token)tokens.get(++pos);
134
        switch(token.getType()) {
135
          case Token.TOKEN_ASSIGN:
136
            element.setOperation(PathElement.OPERATION_ASSIGN);
137
            pos = stateSecondOperand(tokens, pos);
138
            break;
139
 
140
          case Token.TOKEN_APPEND:
141
            element.setOperation(PathElement.OPERATION_APPEND);
142
            pos = stateSecondOperand(tokens, pos);
143
            break;
144
 
145
          default:
146
            throw new PathCreateException(
147
              "Assign or append operation expected", token);
148
        }
149
        break;
150
      }
151
 
152
      default:
153
        throw new PathCreateException("Attribute name expected", token);
154
    }
155
 
156
    return pos;
157
  }
158
 
159
  private int stateSecondOperand(List tokens, int pos)
160
    throws PathCreateException
161
  {
162
    Token token = (Token)tokens.get(++pos);
163
 
164
    switch(token.getType()) {
165
      case Token.TOKEN_VARIABLE:
166
        element.setSecondOperand(PathElement.OPERAND_VARIABLE, token.getValue());
167
        if(pos < tokens.size() - 1)
168
          throw new PathCreateException("Path end expected", token);
169
        break;
170
 
171
      case Token.TOKEN_STRING:
172
        element.setSecondOperand(PathElement.OPERAND_STRING, token.getValue());
173
        if(pos < tokens.size() - 1)
174
          throw new PathCreateException("Path end expected", token);
175
        break;
176
 
177
      default:
178
        throw new PathCreateException("Second operand expected", token);
179
    }
180
 
181
    element.validateOperands(); // must be end of the path
182
 
183
    return pos;
184
  }
185
 
186
  private int stateElementCondition(List tokens, int pos)
187
    throws PathCreateException
188
  {
189
    Token token = (Token)tokens.get(++pos);
190
 
191
    switch(token.getType()) {
192
      case Token.TOKEN_NEW:
193
        pos = stateNew(tokens, pos);
194
        break;
195
 
196
      case Token.TOKEN_SHARP:
197
      case Token.TOKEN_AT:
198
        pos = stateLogicalCondition(tokens, pos);
199
        break;
200
 
1006 dev 201
      case Token.TOKEN_INDEX:
202
        pos = stateIndex(tokens, pos);
203
        break;
204
 
1005 dev 205
      default:
206
        throw new PathCreateException("Element condition expected", token);
207
    }
208
 
209
    return pos;
210
  }
211
 
212
  private int stateLogicalCondition(List tokens, int pos)
213
    throws PathCreateException
214
  {
215
    Token token = (Token)tokens.get(pos); // do not go to the next token
216
 
217
    switch(token.getType()) {
218
      case Token.TOKEN_SHARP:
219
        pos = stateConditionText(tokens, pos);
220
        break;
221
 
222
      case Token.TOKEN_AT:
223
        pos = stateConditionAttribute(tokens, pos);
224
        break;
225
 
226
      default:
227
        throw new PathCreateException("Element condition expected", token);
228
    }
229
 
230
    return pos;
231
  }
232
 
1006 dev 233
  private int stateIndex(List tokens, int pos)
234
    throws PathCreateException
235
  {
236
    Token token = (Token)tokens.get(pos);
237
 
238
    try {
239
      element.setIndex(Integer.parseInt(token.getValue()));
240
    }
241
    catch(NumberFormatException ex) {
242
        throw new PathCreateException(
243
          "Cannot parse '" + token.getValue() + "' as integer", token);
244
    }
245
 
246
    token = (Token)tokens.get(++pos);
247
 
248
    switch(token.getType()) {
249
      case Token.TOKEN_CLOSE_BRACKET:
250
        pos = stateConditionEnd(tokens, pos);
251
        break;
252
 
253
      case Token.TOKEN_AND:
254
        pos++; // go to next token for stateLogicalCondition
255
        pos = stateLogicalCondition(tokens, pos);
256
        break;
257
 
258
      default:
259
        throw new PathCreateException(
260
          "End of conditions or next condition expected", token);
261
    }
262
 
263
    return pos;
264
  }
265
 
1005 dev 266
  private int stateConditionText(List tokens, int pos)
267
    throws PathCreateException
268
  {
269
    Token token = (Token)tokens.get(++pos);
270
 
271
    element.addCondition();
272
    element.setFirstCondition(PathElement.OPERAND_TEXT, null);
273
 
274
    switch(token.getType()) {
275
      case Token.TOKEN_EQUAL:
276
        element.setConditionOperation(PathElement.OPERATION_EQUAL);
277
        pos = stateConditionSecond(tokens, pos);
278
        break;
279
 
280
      default:
281
        throw new PathCreateException("Compare operator expected", token);
282
    }
283
 
284
    return pos;
285
  }
286
 
287
  private int stateConditionAttribute(List tokens, int pos)
288
    throws PathCreateException
289
  {
290
    Token token = (Token)tokens.get(++pos);
291
 
292
    element.addCondition();
293
 
294
    switch(token.getType()) {
295
      case Token.TOKEN_NAME: {
296
        element.setFirstCondition(
297
          PathElement.OPERAND_ATTRIBUTE, token.getValue());
298
        token = (Token)tokens.get(++pos);
299
        switch(token.getType()) {
300
          case Token.TOKEN_EQUAL:
301
            element.setConditionOperation(PathElement.OPERATION_EQUAL);
302
            pos = stateConditionSecond(tokens, pos);
303
            break;
304
 
1007 dev 305
		      case Token.TOKEN_CLOSE_BRACKET:
306
		        pos = stateConditionEnd(tokens, pos);
307
		        break;
308
 
309
		      case Token.TOKEN_AND:
310
		        pos++; // go to next token for stateLogicalCondition
311
		        pos = stateLogicalCondition(tokens, pos);
312
		        break;
313
 
1005 dev 314
          default:
315
            throw new PathCreateException("Compare operation expected", token);
316
        }
317
        break;
318
      }
319
 
320
      default:
321
        throw new PathCreateException("Attibute name expected", token);
322
    }
323
 
324
    return pos;
325
  }
326
 
327
  private int stateConditionSecond(List tokens, int pos)
328
    throws PathCreateException
329
  {
330
    Token token = (Token)tokens.get(++pos);
331
    switch(token.getType()) {
332
      case Token.TOKEN_VARIABLE:
333
        element.setSecondCondition(
334
          PathElement.OPERAND_VARIABLE, token.getValue());
335
        break;
336
 
337
      case Token.TOKEN_STRING:
338
        element.setSecondCondition(
339
          PathElement.OPERAND_STRING, token.getValue());
340
        break;
341
 
342
      default:
343
        throw new PathCreateException(
344
          "Second condition operand expected", token);
345
    }
346
    element.validateCondition(); // must be end of condition
347
 
348
    token = (Token)tokens.get(++pos);
349
    switch(token.getType()) {
350
      case Token.TOKEN_CLOSE_BRACKET:
351
        pos = stateConditionEnd(tokens, pos);
352
        break;
353
 
354
      case Token.TOKEN_AND:
355
        pos++; // go to next token for stateLogicalCondition
356
        pos = stateLogicalCondition(tokens, pos);
357
        break;
358
 
359
      default:
360
        throw new PathCreateException(
361
          "End of conditions or next condition expected", token);
362
    }
363
 
364
    return pos;
365
  }
366
 
367
  private int stateNew(List tokens, int pos)
368
    throws PathCreateException
369
  {
370
    Token token = (Token)tokens.get(++pos);
371
 
372
    element.setNew();
373
 
374
    switch(token.getType()) {
375
      case Token.TOKEN_CLOSE_BRACKET:
376
        pos = stateConditionEnd(tokens, pos);
377
        break;
378
 
379
      default:
380
        throw new PathCreateException("End of conditions expected", token);
381
    }
382
 
383
    return pos;
384
  }
385
 
386
  private int stateConditionEnd(List tokens, int pos)
387
    throws PathCreateException
388
  {
389
    if(++pos >= tokens.size()) return pos;
390
 
391
    Token token = (Token)tokens.get(pos);
392
 
393
    switch(token.getType()) {
394
      case Token.TOKEN_SLASH:
395
        stateElementStart(tokens, pos); // start new path element
396
        break;
397
 
398
      case Token.TOKEN_SHARP:
399
        pos = stateOperandText(tokens, pos);
400
        break;
401
 
402
      case Token.TOKEN_AT:
403
        pos = stateOperandAttribute(tokens, pos);
404
        break;
405
 
406
      default:
407
        throw new PathCreateException(
408
          "End of element description expected", token);
409
    }
410
 
411
    return pos;
412
  }
413
}