1 package org.apache.torque.generator.source;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.ArrayList;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.ListIterator;
26 import java.util.Set;
27 import java.util.StringTokenizer;
28
29 import org.apache.torque.generator.GeneratorException;
30
31
32
33
34 public final class SourcePath
35 {
36
37
38
39 private static final String PATH_LEVEL_SEPARATOR = "/";
40
41
42
43
44 private static final String THIS_TOKEN = ".";
45
46
47
48
49 private static final String PARENT_TOKEN = "..";
50
51
52
53
54 private static final String ANY_ELEMENT_TOKEN = "*";
55
56
57
58
59 private SourcePath()
60 {
61 }
62
63
64
65
66
67
68
69
70
71
72
73 public static boolean hasChild(SourceElement sourceElement, String name)
74 {
75 if (name == null)
76 {
77 throw new NullPointerException("name must not be null");
78 }
79 if (sourceElement == null)
80 {
81 throw new NullPointerException("sourceElement must not be null");
82 }
83 for (SourceElement child : sourceElement.getChildren())
84 {
85 if (name.equals(child.getName()))
86 {
87 return true;
88 }
89 }
90 return false;
91 }
92
93
94
95
96
97
98
99
100
101 public static boolean hasFollowing(SourceElement sourceElement)
102 {
103 return !getFollowing(sourceElement, null).isEmpty();
104 }
105
106
107
108
109
110
111
112
113
114 public static boolean hasPreceding(SourceElement sourceElement)
115 {
116 return !getPreceding(sourceElement, sourceElement.getName()).isEmpty();
117 }
118
119
120
121
122
123
124
125
126
127 public static boolean hasFollowingSibling(SourceElement sourceElement)
128 {
129 return !getFollowing(sourceElement, sourceElement.getName()).isEmpty();
130 }
131
132
133
134
135
136
137
138
139
140 public static boolean hasPrecedingSibling(SourceElement sourceElement)
141 {
142 return !getPreceding(sourceElement, sourceElement.getName()).isEmpty();
143 }
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160 public static List<SourceElement> getPreceding(
161 SourceElement sourceElement,
162 String name)
163 {
164 if (sourceElement == null)
165 {
166 throw new NullPointerException("sourceElement must not be null");
167 }
168
169 List<SourceElement> result = new ArrayList<SourceElement>();
170 ListIterator<SourceElement> sameLevelIt
171 = getSiblingIteratorPositionedOnSelf(sourceElement);
172 if (sameLevelIt == null)
173 {
174 return result;
175 }
176 boolean first = true;
177 while (sameLevelIt.hasPrevious())
178 {
179 SourceElement sameLevelElement = sameLevelIt.previous();
180
181
182 if (first)
183 {
184 first = false;
185 continue;
186 }
187 if (name == null || name.equals(sameLevelElement.getName()))
188 {
189 result.add(sameLevelElement);
190 }
191 }
192 return result;
193
194 }
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211 public static List<SourceElement> getFollowing(
212 SourceElement sourceElement,
213 String name)
214 {
215 if (sourceElement == null)
216 {
217 throw new NullPointerException("sourceElement must not be null");
218 }
219 List<SourceElement> result = new ArrayList<SourceElement>();
220
221 ListIterator<SourceElement> sameLevelIt
222 = getSiblingIteratorPositionedOnSelf(sourceElement);
223 if (sameLevelIt == null)
224 {
225 return result;
226 }
227 while (sameLevelIt.hasNext())
228 {
229 SourceElement sameLevelElement = sameLevelIt.next();
230 if (name == null || name.equals(sameLevelElement.getName()))
231 {
232 result.add(sameLevelElement);
233 }
234 }
235 return result;
236 }
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253 private static ListIterator<SourceElement> getSiblingIteratorPositionedOnSelf(
254 SourceElement sourceElement)
255 {
256 SourceElement parent = sourceElement.getParent();
257 if (parent == null)
258 {
259 return null;
260 }
261 ListIterator<SourceElement> sameLevelIt
262 = parent.getChildren().listIterator();
263
264 boolean found = false;
265 while (sameLevelIt.hasNext())
266 {
267 SourceElement sameLevelElement = sameLevelIt.next();
268 if (sameLevelElement == sourceElement)
269 {
270 found = true;
271 break;
272 }
273 }
274 if (!found)
275 {
276 throw new IllegalArgumentException("Inconsistent source tree: "
277 + "Source element " + sourceElement.getName()
278 + " not found in the list of the children of its parent");
279 }
280 return sameLevelIt;
281 }
282
283
284
285
286
287
288
289
290
291
292
293
294 public static List<SourceElement> getElements(
295 SourceElement sourceElement,
296 String path)
297 {
298 if (sourceElement == null)
299 {
300 throw new NullPointerException("sourceElement must not be null");
301 }
302
303 if (path.equals(THIS_TOKEN))
304 {
305 List<SourceElement> result = new ArrayList<SourceElement>(1);
306 result.add(sourceElement);
307 return result;
308 }
309 StringTokenizer selectionPathTokenizer
310 = new StringTokenizer(path, PATH_LEVEL_SEPARATOR);
311 List<SourceElement> currentSelection = new ArrayList<SourceElement>();
312 currentSelection.add(sourceElement);
313 while (selectionPathTokenizer.hasMoreTokens())
314 {
315 String childName = selectionPathTokenizer.nextToken();
316 List<SourceElement> nextSelection = new ArrayList<SourceElement>();
317 for (SourceElement currentElement : currentSelection)
318 {
319 if (childName.equals(PARENT_TOKEN))
320 {
321 SourceElement parent = currentElement.getParent();
322 if (parent != null && !nextSelection.contains(parent))
323 {
324 nextSelection.add(parent);
325 }
326 }
327 else if (ANY_ELEMENT_TOKEN.equals(childName))
328 {
329 for (SourceElement child
330 : currentElement.getChildren())
331 {
332 nextSelection.add(child);
333 }
334 }
335 {
336 for (SourceElement child
337 : currentElement.getChildren(childName))
338 {
339 nextSelection.add(child);
340 }
341 }
342 }
343 currentSelection = nextSelection;
344 }
345 return currentSelection;
346 }
347
348
349
350
351
352
353
354
355
356
357
358
359
360 public static List<SourceElement> getElementsFromRoot(
361 SourceElement rootElement,
362 String path)
363 {
364 if (rootElement == null)
365 {
366 throw new NullPointerException("rootElement must not be null");
367 }
368
369 if (path == null
370 || "".equals(path.trim())
371 || PATH_LEVEL_SEPARATOR.equals(path.trim()))
372 {
373
374 List<SourceElement> result = new ArrayList<SourceElement>(1);
375 result.add(rootElement);
376 return result;
377 }
378
379 path = path.trim();
380
381 if (path.startsWith(PATH_LEVEL_SEPARATOR))
382 {
383 path = path.substring(1);
384 }
385 int firstSeparatorPos = path.indexOf(PATH_LEVEL_SEPARATOR);
386 String firstElementName;
387 if (firstSeparatorPos == -1)
388 {
389 firstElementName = path;
390 path = THIS_TOKEN;
391 }
392 else
393 {
394 firstElementName = path.substring(0, firstSeparatorPos);
395 path = path.substring(firstSeparatorPos + 1);
396 }
397 if (!ANY_ELEMENT_TOKEN.equals(firstElementName)
398 && !rootElement.getName().equals(firstElementName))
399 {
400 return new ArrayList<SourceElement>();
401 }
402 return SourcePath.getElements(rootElement, path);
403 }
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422 public static SourceElement getElement(
423 SourceElement sourceElement,
424 String path,
425 boolean acceptEmpty)
426 throws GeneratorException
427 {
428 List<SourceElement> sourceElements
429 = SourcePath.getElements(sourceElement, path);
430 if (sourceElements.isEmpty())
431 {
432 if (acceptEmpty)
433 {
434 return null;
435 }
436 else
437 {
438 throw new GeneratorException(
439 "Source element path "
440 + path
441 + " selects no element on source element "
442 + sourceElement.getName());
443 }
444 }
445 if (sourceElements.size() > 1)
446 {
447 throw new GeneratorException(
448 "Source element path "
449 + path
450 + " selects more than a single element on source element "
451 + sourceElement.getName());
452 }
453 return sourceElements.get(0);
454 }
455
456
457
458
459
460
461
462
463
464
465
466
467 public static String getPathAsString(SourceElement sourceElement)
468 throws GeneratorException
469 {
470 StringBuilder result = new StringBuilder();
471 getParentPath(sourceElement, new HashSet<SourceElement>(), result);
472 result.append(sourceElement.getName());
473 return result.toString();
474 }
475
476
477
478
479
480
481
482
483
484
485
486
487
488 private static void getParentPath(
489 SourceElement toProcess,
490 Set<SourceElement> alreadyProcessed,
491 StringBuilder result)
492 throws GeneratorException
493 {
494 SourceElement parent = toProcess.getParent();
495 if (alreadyProcessed.contains(parent))
496 {
497 throw new GeneratorException(
498 "getParentPath(): invoked on a closed loop");
499 }
500 if (parent == null)
501 {
502 return;
503 }
504 result.insert(0, parent.getName() + "/");
505 alreadyProcessed.add(parent);
506 getParentPath(parent, alreadyProcessed, result);
507 }
508 }