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.AbstractList;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30
31
32
33
34 public class SourceElement
35 {
36
37
38
39 private String name;
40
41
42
43
44 private List<SourceElement> parents = new ParentList(this);
45
46
47
48
49 private List<SourceElement> children = new ChildList(this);
50
51
52
53
54 private Map<String, Object> attributes = new HashMap<String, Object>();
55
56
57
58
59
60
61
62
63 public SourceElement(String name)
64 {
65 if (name == null)
66 {
67 throw new NullPointerException("name must not be null");
68 }
69 this.name = name;
70 }
71
72
73
74
75
76
77
78
79 public SourceElement(SourceElementName sourceElementName)
80 {
81 this(sourceElementName.getName());
82 }
83
84
85
86
87
88
89 public String getName()
90 {
91 return name;
92 }
93
94
95
96
97
98
99
100 public SourceElement getParent()
101 {
102 if (parents.size() == 0)
103 {
104 return null;
105 }
106 return parents.get(0);
107 }
108
109
110
111
112
113
114
115
116 public List<SourceElement> getParents()
117 {
118 return parents;
119 }
120
121
122
123
124
125
126
127
128 public List<SourceElement> getChildren()
129 {
130 return children;
131 }
132
133
134
135
136
137
138
139
140
141
142
143
144
145 public List<SourceElement> getChildren(String name)
146 {
147 if (name == null)
148 {
149 throw new NullPointerException("name must not be null");
150 }
151 List<SourceElement> result = new ArrayList<SourceElement>();
152 for (SourceElement sourceElement : children)
153 {
154 if (name.equals(sourceElement.getName()))
155 {
156 result.add(sourceElement);
157 }
158 }
159 return result;
160 }
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175 public List<SourceElement> getChildren(SourceElementName sourceElementName)
176 {
177 return getChildren(sourceElementName.getName());
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191 public SourceElement getChild(String name)
192 {
193 for (SourceElement sourceElement : children)
194 {
195 if (name.equals(sourceElement.getName()))
196 {
197 return sourceElement;
198 }
199 }
200 return null;
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215 public SourceElement getChild(SourceElementName sourceElementName)
216 {
217 return getChild(sourceElementName.getName());
218 }
219
220
221
222
223
224
225
226
227
228
229 public boolean hasChild(String name)
230 {
231 return SourcePath.hasChild(this, name);
232 }
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248 public List<SourceElement> getFollowing(String name)
249 {
250 return SourcePath.getFollowing(this, name);
251 }
252
253
254
255
256
257
258
259 public boolean hasFollowing()
260 {
261 return SourcePath.hasFollowing(this);
262 }
263
264
265
266
267
268
269
270 public boolean hasPreceding()
271 {
272 return SourcePath.hasPreceding(this);
273 }
274
275
276
277
278
279
280
281 public boolean hasFollowingSibling()
282 {
283 return SourcePath.hasFollowingSibling(this);
284 }
285
286
287
288
289
290
291
292 public boolean hasPrecedingSibling()
293 {
294 return SourcePath.hasPrecedingSibling(this);
295 }
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310 public List<SourceElement> getPreceding(String name)
311 {
312 return SourcePath.getPreceding(this, name);
313 }
314
315
316
317
318
319
320
321 public Object getTextAttribute()
322 {
323 return attributes.get(null);
324 }
325
326
327
328
329
330
331
332
333 public Object getAttribute(String name)
334 {
335 return attributes.get(name);
336 }
337
338
339
340
341
342
343
344
345
346
347 public Object getAttribute(SourceAttributeName sourceAttributeName)
348 {
349 return getAttribute(sourceAttributeName.getName());
350 }
351
352
353
354
355
356
357
358
359
360
361 public Object setAttribute(String name, Object value)
362 {
363 if (value == null)
364 {
365 return attributes.remove(name);
366 }
367 return attributes.put(name, value);
368 }
369
370
371
372
373
374
375
376
377
378
379 public Object setAttribute(
380 SourceAttributeName sourceAttributeName,
381 Object value)
382 {
383 return setAttribute(sourceAttributeName.getName(), value);
384 }
385
386
387
388
389
390
391
392 public Set<String> getAttributeNames()
393 {
394 return attributes.keySet();
395 }
396
397
398
399
400
401
402
403
404
405 public SourceElement copy()
406 {
407 Map<SourceElement, SourceElement> copied
408 = new HashMap<SourceElement, SourceElement>();
409 return copy(this, copied);
410 }
411
412
413
414
415
416
417
418
419
420
421 private SourceElement copy(SourceElement toCopy,
422 Map<SourceElement, SourceElement> copiedElements)
423 {
424 SourceElement copied = copiedElements.get(toCopy);
425 if (copied != null)
426 {
427 return copied;
428 }
429 copied = new SourceElement(toCopy.getName());
430 copiedElements.put(toCopy, copied);
431
432 for (String attributeName : toCopy.getAttributeNames())
433 {
434 copied.setAttribute(attributeName, toCopy.getAttribute(attributeName));
435 }
436
437 {
438 List<SourceElement> childrenOfCopied = copied.getChildren();
439 for (SourceElement child : toCopy.getChildren())
440 {
441 SourceElement copiedChild = copy(child, copiedElements);
442 if (!childrenOfCopied.contains(copiedChild))
443 {
444 childrenOfCopied.add(copiedChild);
445 }
446 }
447 }
448
449 {
450 List<SourceElement> parentsOfCopied = copied.getParents();
451 for (SourceElement parent : toCopy.getParents())
452 {
453 SourceElement copiedParent
454 = copy(parent, copiedElements);
455 if (!parentsOfCopied.contains(copiedParent))
456 {
457 parentsOfCopied.add(copiedParent);
458 }
459 }
460 }
461
462 return copied;
463 }
464
465
466
467
468
469
470
471
472
473
474
475
476 public boolean graphEquals(SourceElement toCompare)
477 {
478 Set<SourceElement> alreadyCompared = new HashSet<SourceElement>();
479 return graphEquals(this, toCompare, alreadyCompared);
480 }
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497 private boolean graphEquals(SourceElement reference,
498 SourceElement toCompare,
499 Set<SourceElement> compared)
500 {
501 if ((reference == null && toCompare != null)
502 || (reference != null && toCompare == null))
503 {
504 return false;
505 }
506 if (reference == null && toCompare == null)
507 {
508 return true;
509 }
510
511 if (compared.contains(reference))
512 {
513
514
515
516
517 return true;
518 }
519
520 compared.add(reference);
521
522 if (!reference.getName().equals(toCompare.getName()))
523 {
524 return false;
525 }
526
527 if (reference.getAttributeNames().size()
528 != toCompare.getAttributeNames().size())
529 {
530 return false;
531 }
532
533 for (String attributeName : reference.getAttributeNames())
534 {
535 Object referenceAttributeContent
536 = reference.getAttribute(attributeName);
537 Object toCompareAttributeContent
538 = toCompare.getAttribute(attributeName);
539 if (referenceAttributeContent == null)
540 {
541 if (toCompareAttributeContent != null)
542 {
543 return false;
544 }
545 }
546 else
547 {
548 if (!referenceAttributeContent.equals(
549 toCompareAttributeContent))
550 {
551 return false;
552 }
553 }
554 }
555
556 if (!graphEquals(reference.getParent(), toCompare.getParent(), compared))
557 {
558 return false;
559 }
560
561 if (reference.getChildren().size()
562 != toCompare.getChildren().size())
563 {
564 return false;
565 }
566
567 Iterator<SourceElement> referenceChildIt
568 = reference.getChildren().iterator();
569 Iterator<SourceElement> toCompareChildIt
570 = toCompare.getChildren().iterator();
571 while (referenceChildIt.hasNext())
572 {
573 SourceElement referenceChild = referenceChildIt.next();
574 SourceElement toCompareChild = toCompareChildIt.next();
575 if (!graphEquals(referenceChild, toCompareChild, compared))
576 {
577 return false;
578 }
579 }
580 return true;
581 }
582
583 @Override
584 public String toString()
585 {
586 Set<SourceElement> alreadyProcessed = new HashSet<SourceElement>();
587 StringBuilder result = new StringBuilder();
588 toString(alreadyProcessed, result);
589 return result.toString();
590 }
591
592
593
594
595
596
597
598
599 private void toString(
600 Set<SourceElement> alreadyProcessed,
601 StringBuilder result)
602 {
603 alreadyProcessed.add(this);
604 result.append("(name=").append(name)
605 .append(",attributes=(");
606 Iterator<Map.Entry<String, Object>> entryIt
607 = attributes.entrySet().iterator();
608 while (entryIt.hasNext())
609 {
610 Map.Entry<String, Object> entry = entryIt.next();
611 result.append(entry.getKey()).append("=").append(entry.getValue());
612 if (entryIt.hasNext())
613 {
614 result.append(",");
615 }
616 }
617 result.append("),children=(");
618 Iterator<SourceElement> childIt = children.iterator();
619 while (childIt.hasNext())
620 {
621 SourceElement child = childIt.next();
622 if (alreadyProcessed.contains(child))
623 {
624 result.append("<<loop detected>>");
625 }
626 else
627 {
628 child.toString(alreadyProcessed, result);
629 }
630 if (childIt.hasNext())
631 {
632 result.append(",");
633 }
634 }
635 result.append("))");
636 }
637
638
639
640
641
642 private static class ChildList extends AbstractList<SourceElement>
643 {
644
645 private SourceElement sourceElement;
646
647
648 private List<SourceElement> children
649 = new ArrayList<SourceElement>();
650
651
652
653
654
655
656
657
658
659 public ChildList(SourceElement sourceElement)
660 {
661 if (sourceElement == null)
662 {
663 throw new NullPointerException(
664 "sourceElement must not be null");
665 }
666 this.sourceElement = sourceElement;
667 }
668
669 @Override
670 public SourceElement get(int index)
671 {
672 return children.get(index);
673 }
674
675 @Override
676 public int size()
677 {
678 return children.size();
679 }
680
681 @Override
682 public void add(int position, SourceElement child)
683 {
684 if (children.contains(child))
685 {
686 throw new IllegalArgumentException(
687 "Element " + child + " is already a child of "
688 + sourceElement);
689 }
690 children.add(position, child);
691 List<SourceElement> parents = child.getParents();
692 if (!parents.contains(sourceElement))
693 {
694 parents.add(sourceElement);
695 }
696 }
697
698 @Override
699 public SourceElement remove(int index)
700 {
701 SourceElement result = children.remove(index);
702 result.getParents().remove(sourceElement);
703 return result;
704 }
705
706 @Override
707 public SourceElement set(int index, SourceElement child)
708 {
709
710
711 if (children.contains(child) && !children.get(index).equals(child))
712 {
713 throw new IllegalArgumentException(
714 "Element " + child + " is already a child of "
715 + sourceElement);
716 }
717 SourceElement previousChild = children.set(index, child);
718 previousChild.getParents().remove(sourceElement);
719 List<SourceElement> parents = child.getParents();
720 if (!parents.contains(sourceElement))
721 {
722 parents.add(sourceElement);
723 }
724 return previousChild;
725 }
726 }
727
728
729
730
731 private static class ParentList extends AbstractList<SourceElement>
732 {
733
734 private SourceElement sourceElement;
735
736
737 private List<SourceElement> parents
738 = new ArrayList<SourceElement>();
739
740
741
742
743
744
745
746
747
748 public ParentList(SourceElement sourceElement)
749 {
750 if (sourceElement == null)
751 {
752 throw new NullPointerException(
753 "sourceElement must not be null");
754 }
755 this.sourceElement = sourceElement;
756 }
757
758 @Override
759 public SourceElement get(int index)
760 {
761 return parents.get(index);
762 }
763
764 @Override
765 public int size()
766 {
767 return parents.size();
768 }
769
770 @Override
771 public void add(int position, SourceElement parent)
772 {
773 if (parents.contains(parent))
774 {
775 throw new IllegalArgumentException(
776 "Element " + parent + " is already a parent of "
777 + sourceElement);
778 }
779 parents.add(position, parent);
780 List<SourceElement> children = parent.getChildren();
781 if (!children.contains(sourceElement))
782 {
783 children.add(sourceElement);
784 }
785 }
786
787 @Override
788 public SourceElement remove(int index)
789 {
790 SourceElement result = parents.remove(index);
791 result.getChildren().remove(sourceElement);
792 return result;
793 }
794
795 @Override
796 public SourceElement set(int index, SourceElement parent)
797 {
798
799
800 if (parents.contains(parent) && !parents.get(index).equals(parent))
801 {
802 throw new IllegalArgumentException(
803 "Element " + parent + " is already a parent of "
804 + sourceElement);
805 }
806 SourceElement previousParent = parents.set(index, parent);
807 previousParent.getChildren().remove(sourceElement);
808 List<SourceElement> children = parent.getChildren();
809 if (!children.contains(sourceElement))
810 {
811 children.add(sourceElement);
812 }
813 return previousParent;
814 }
815 }
816 }