1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.jcr.xpath;
25
26 import java.util.ArrayList;
27 import java.util.Iterator;
28 import java.util.List;
29 import org.modeshape.common.collection.ReadOnlyIterator;
30 import org.modeshape.common.util.CheckArg;
31 import org.modeshape.common.util.HashCode;
32 import org.modeshape.common.util.ObjectUtil;
33 import org.modeshape.graph.query.model.Operator;
34 import org.modeshape.graph.query.model.Order;
35
36
37
38
39
40
41
42 public class XPath {
43
44 public static enum NodeComparisonOperator {
45 IS,
46 PRECEDES,
47 FOLLOWS;
48 }
49
50 public static abstract class Component {
51
52
53
54
55
56 public Component collapse() {
57 return this;
58 }
59 }
60
61 public static abstract class UnaryComponent extends Component {
62 protected final Component wrapped;
63
64 public UnaryComponent( Component wrapped ) {
65 this.wrapped = wrapped;
66 }
67 }
68
69 public static class Negation extends UnaryComponent {
70 public Negation( Component wrapped ) {
71 super(wrapped);
72 }
73
74 public Component getNegated() {
75 return wrapped;
76 }
77
78
79
80
81
82
83 @Override
84 public String toString() {
85 return "-" + wrapped;
86 }
87
88
89
90
91
92
93 @Override
94 public boolean equals( Object obj ) {
95 if (obj == this) return true;
96 if (obj instanceof Negation) {
97 Negation that = (Negation)obj;
98 return this.wrapped.equals(that.wrapped);
99 }
100 return false;
101 }
102 }
103
104 public static abstract class BinaryComponent extends Component {
105 private final Component left;
106 private final Component right;
107
108 public BinaryComponent( Component left,
109 Component right ) {
110 this.left = left;
111 this.right = right;
112 }
113
114
115
116
117 public Component getLeft() {
118 return left;
119 }
120
121
122
123
124 public Component getRight() {
125 return right;
126 }
127 }
128
129 public static class Comparison extends BinaryComponent {
130 private final Operator operator;
131
132 public Comparison( Component left,
133 Operator operator,
134 Component right ) {
135 super(left, right);
136 this.operator = operator;
137 }
138
139
140
141
142 public Operator getOperator() {
143 return operator;
144 }
145
146
147
148
149
150
151 @Override
152 public Component collapse() {
153 return new Comparison(getLeft().collapse(), operator, getRight().collapse());
154 }
155
156
157
158
159
160
161 @Override
162 public String toString() {
163 return getLeft() + " " + operator + " " + getRight();
164 }
165
166
167
168
169
170
171 @Override
172 public boolean equals( Object obj ) {
173 if (obj == this) return true;
174 if (obj instanceof Comparison) {
175 Comparison that = (Comparison)obj;
176 if (this.operator != that.operator) return false;
177 return this.getLeft().equals(that.getLeft()) && this.getRight().equals(that.getRight());
178 }
179 return false;
180 }
181 }
182
183 public static class NodeComparison extends BinaryComponent {
184 private final NodeComparisonOperator operator;
185
186 public NodeComparison( Component left,
187 NodeComparisonOperator operator,
188 Component right ) {
189 super(left, right);
190 this.operator = operator;
191 }
192
193
194
195
196
197
198 @Override
199 public Component collapse() {
200 return new NodeComparison(getLeft().collapse(), operator, getRight().collapse());
201 }
202
203
204
205
206
207
208 @Override
209 public String toString() {
210 return getLeft() + " " + operator + " " + getRight();
211 }
212
213
214
215
216
217
218 @Override
219 public boolean equals( Object obj ) {
220 if (obj == this) return true;
221 if (obj instanceof NodeComparison) {
222 NodeComparison that = (NodeComparison)obj;
223 if (this.operator != that.operator) return false;
224 return this.getLeft().equals(that.getLeft()) && this.getRight().equals(that.getRight());
225 }
226 return false;
227 }
228 }
229
230 public static class Add extends BinaryComponent {
231 public Add( Component left,
232 Component right ) {
233 super(left, right);
234 }
235
236
237
238
239
240
241 @Override
242 public Component collapse() {
243 return new Add(getLeft().collapse(), getRight().collapse());
244 }
245
246
247
248
249
250
251 @Override
252 public String toString() {
253 return getLeft() + " + " + getRight();
254 }
255
256
257
258
259
260
261 @Override
262 public boolean equals( Object obj ) {
263 if (obj == this) return true;
264 if (obj instanceof Add) {
265 Add that = (Add)obj;
266 return this.getLeft().equals(that.getLeft()) && this.getRight().equals(that.getRight());
267 }
268 return false;
269 }
270 }
271
272 public static class Subtract extends BinaryComponent {
273 public Subtract( Component left,
274 Component right ) {
275 super(left, right);
276 }
277
278
279
280
281
282
283 @Override
284 public Component collapse() {
285 return new Subtract(getLeft().collapse(), getRight().collapse());
286 }
287
288
289
290
291
292
293 @Override
294 public String toString() {
295 return getLeft() + " - " + getRight();
296 }
297
298
299
300
301
302
303 @Override
304 public boolean equals( Object obj ) {
305 if (obj == this) return true;
306 if (obj instanceof Subtract) {
307 Subtract that = (Subtract)obj;
308 return this.getLeft().equals(that.getLeft()) && this.getRight().equals(that.getRight());
309 }
310 return false;
311 }
312 }
313
314 public static class And extends BinaryComponent {
315 public And( Component left,
316 Component right ) {
317 super(left, right);
318 }
319
320
321
322
323
324
325 @Override
326 public Component collapse() {
327 return new And(getLeft().collapse(), getRight().collapse());
328 }
329
330
331
332
333
334
335 @Override
336 public String toString() {
337 return getLeft() + " and " + getRight();
338 }
339
340
341
342
343
344
345 @Override
346 public boolean equals( Object obj ) {
347 if (obj == this) return true;
348 if (obj instanceof And) {
349 And that = (And)obj;
350 return this.getLeft().equals(that.getLeft()) && this.getRight().equals(that.getRight());
351 }
352 return false;
353 }
354 }
355
356 public static class Union extends BinaryComponent {
357 public Union( Component left,
358 Component right ) {
359 super(left, right);
360 }
361
362
363
364
365
366
367 @Override
368 public String toString() {
369 return getLeft() + " union " + getRight();
370 }
371
372
373
374
375
376
377 @Override
378 public boolean equals( Object obj ) {
379 if (obj == this) return true;
380 if (obj instanceof Union) {
381 Union that = (Union)obj;
382 return this.getLeft().equals(that.getLeft()) && this.getRight().equals(that.getRight());
383 }
384 return false;
385 }
386 }
387
388 public static class Intersect extends BinaryComponent {
389 public Intersect( Component left,
390 Component right ) {
391 super(left, right);
392 }
393
394
395
396
397
398
399 @Override
400 public String toString() {
401 return getLeft() + " intersect " + getRight();
402 }
403
404
405
406
407
408
409 @Override
410 public boolean equals( Object obj ) {
411 if (obj == this) return true;
412 if (obj instanceof Intersect) {
413 Intersect that = (Intersect)obj;
414 return this.getLeft().equals(that.getLeft()) && this.getRight().equals(that.getRight());
415 }
416 return false;
417 }
418 }
419
420 public static class Except extends BinaryComponent {
421 public Except( Component left,
422 Component right ) {
423 super(left, right);
424 }
425
426
427
428
429
430
431 @Override
432 public String toString() {
433 return getLeft() + " except " + getRight();
434 }
435
436
437
438
439
440
441 @Override
442 public boolean equals( Object obj ) {
443 if (obj == this) return true;
444 if (obj instanceof Except) {
445 Except that = (Except)obj;
446 return this.getLeft().equals(that.getLeft()) && this.getRight().equals(that.getRight());
447 }
448 return false;
449 }
450 }
451
452 public static class Or extends BinaryComponent {
453 public Or( Component left,
454 Component right ) {
455 super(left, right);
456 }
457
458
459
460
461
462
463 @Override
464 public Component collapse() {
465 return new Or(getLeft().collapse(), getRight().collapse());
466 }
467
468
469
470
471
472
473 @Override
474 public String toString() {
475 return getLeft() + " or " + getRight();
476 }
477
478
479
480
481
482
483 @Override
484 public boolean equals( Object obj ) {
485 if (obj == this) return true;
486 if (obj instanceof Or) {
487 Or that = (Or)obj;
488 return this.getLeft().equals(that.getLeft()) && this.getRight().equals(that.getRight());
489 }
490 return false;
491 }
492 }
493
494 public static class ContextItem extends Component {
495
496
497
498
499
500 @Override
501 public boolean equals( Object obj ) {
502 return obj == this || obj instanceof ContextItem;
503 }
504
505
506
507
508
509
510 @Override
511 public String toString() {
512 return ".";
513 }
514 }
515
516 public static class Literal extends Component {
517 private final String value;
518
519 public Literal( String value ) {
520 this.value = value;
521 }
522
523
524
525
526 public String getValue() {
527 return value;
528 }
529
530 public boolean isInteger() {
531 try {
532 Integer.parseInt(value);
533 return true;
534 } catch (NumberFormatException e) {
535 return false;
536 }
537 }
538
539 public int getValueAsInteger() {
540 return Integer.parseInt(value);
541 }
542
543
544
545
546
547
548 @Override
549 public boolean equals( Object obj ) {
550 if (obj == this) return true;
551 if (obj instanceof Literal) {
552 return this.value.equals(((Literal)obj).value);
553 }
554 return false;
555 }
556
557
558
559
560
561
562 @Override
563 public String toString() {
564 return value;
565 }
566 }
567
568 public static class FunctionCall extends Component {
569 private final NameTest name;
570 private final List<Component> arguments;
571
572 public FunctionCall( NameTest name,
573 List<Component> arguments ) {
574 assert name != null;
575 assert arguments != null;
576 this.name = name;
577 this.arguments = arguments;
578 }
579
580
581
582
583 public NameTest getName() {
584 return name;
585 }
586
587
588
589
590 public List<Component> getParameters() {
591 return arguments;
592 }
593
594
595
596
597
598
599 @Override
600 public Component collapse() {
601 List<Component> args = new ArrayList<Component>(arguments.size());
602 for (Component arg : arguments) {
603 args.add(arg.collapse());
604 }
605 return new FunctionCall(name, args);
606 }
607
608
609
610
611
612
613 @Override
614 public boolean equals( Object obj ) {
615 if (obj == this) return true;
616 if (obj instanceof FunctionCall) {
617 FunctionCall that = (FunctionCall)obj;
618 return this.name.equals(that.name) && this.arguments.equals(that.arguments);
619 }
620 return false;
621 }
622
623
624
625
626
627
628 @Override
629 public String toString() {
630 return name + "(" + asString(arguments, ",") + ")";
631 }
632 }
633
634 protected static String asString( Iterable<?> components,
635 String delimiter ) {
636 StringBuilder sb = new StringBuilder();
637 for (Object component : components) {
638 if (sb.length() != 0) sb.append(delimiter);
639 sb.append(component);
640 }
641 return sb.toString();
642 }
643
644 public static class PathExpression extends Component implements Iterable<StepExpression> {
645 private final List<StepExpression> steps;
646 private final boolean relative;
647 private final OrderBy orderBy;
648
649 public PathExpression( boolean relative,
650 List<StepExpression> steps,
651 OrderBy orderBy ) {
652 this.steps = steps;
653 this.relative = relative;
654 this.orderBy = orderBy;
655 }
656
657
658
659
660 public boolean isRelative() {
661 return relative;
662 }
663
664
665
666
667
668
669 public OrderBy getOrderBy() {
670 return orderBy;
671 }
672
673
674
675
676 public List<StepExpression> getSteps() {
677 return steps;
678 }
679
680 public StepExpression getLastStep() {
681 return steps.isEmpty() ? null : steps.get(steps.size() - 1);
682 }
683
684 public PathExpression withoutLast() {
685 assert !steps.isEmpty();
686 return new PathExpression(relative, steps.subList(0, steps.size() - 1), orderBy);
687 }
688
689 public PathExpression withoutFirst() {
690 assert !steps.isEmpty();
691 return new PathExpression(relative, steps.subList(1, steps.size()), orderBy);
692 }
693
694
695
696
697
698
699 public Iterator<StepExpression> iterator() {
700 return steps.iterator();
701 }
702
703 @Override
704 public Component collapse() {
705 return steps.size() == 1 ? steps.get(0).collapse() : this;
706 }
707
708
709
710
711
712
713 @Override
714 public boolean equals( Object obj ) {
715 if (obj == this) return true;
716 if (obj instanceof PathExpression) {
717 PathExpression that = (PathExpression)obj;
718 if (this.relative != that.relative) return false;
719 if (this.orderBy != null && !this.orderBy.equals(that.orderBy)) return false;
720 if (this.orderBy == null && that.orderBy != null) return false;
721 return this.steps.equals(that.steps);
722 }
723 return false;
724 }
725
726
727
728
729
730
731 @Override
732 public String toString() {
733 return (relative ? "" : "/") + asString(steps, "/");
734 }
735 }
736
737 public static abstract class StepExpression extends Component {
738 }
739
740 public static class FilterStep extends StepExpression {
741 private final Component primaryExpression;
742 private final List<Component> predicates;
743
744 public FilterStep( Component primaryExpression,
745 List<Component> predicates ) {
746 assert primaryExpression != null;
747 assert predicates != null;
748 this.primaryExpression = primaryExpression;
749 this.predicates = predicates;
750 }
751
752
753
754
755 public Component getPrimaryExpression() {
756 return primaryExpression;
757 }
758
759
760
761
762 public List<Component> getPredicates() {
763 return predicates;
764 }
765
766 @Override
767 public Component collapse() {
768 return predicates.isEmpty() ? primaryExpression.collapse() : this;
769 }
770
771
772
773
774
775
776 @Override
777 public boolean equals( Object obj ) {
778 if (obj == this) return true;
779 if (obj instanceof FilterStep) {
780 FilterStep that = (FilterStep)obj;
781 return this.primaryExpression.equals(that.primaryExpression) && this.predicates.equals(that.predicates);
782 }
783 return false;
784 }
785
786
787
788
789
790
791 @Override
792 public String toString() {
793 return primaryExpression + (predicates.isEmpty() ? "" : predicates.toString());
794 }
795 }
796
797 public static class DescendantOrSelf extends StepExpression {
798
799
800
801
802
803 @Override
804 public boolean equals( Object obj ) {
805 return obj == this || obj instanceof DescendantOrSelf;
806 }
807
808
809
810
811
812
813 @Override
814 public String toString() {
815 return "descendant-or-self::node()";
816 }
817 }
818
819 public static class AxisStep extends StepExpression {
820 private final NodeTest nodeTest;
821 private final List<Component> predicates;
822
823 public AxisStep( NodeTest nodeTest,
824 List<Component> predicates ) {
825 assert nodeTest != null;
826 assert predicates != null;
827 this.nodeTest = nodeTest;
828 this.predicates = predicates;
829 }
830
831
832
833
834 public NodeTest getNodeTest() {
835 return nodeTest;
836 }
837
838
839
840
841 public List<Component> getPredicates() {
842 return predicates;
843 }
844
845 @Override
846 public Component collapse() {
847 return predicates.isEmpty() ? nodeTest.collapse() : this;
848 }
849
850
851
852
853
854
855 @Override
856 public boolean equals( Object obj ) {
857 if (obj == this) return true;
858 if (obj instanceof AxisStep) {
859 AxisStep that = (AxisStep)obj;
860 return this.nodeTest.equals(that.nodeTest) && this.predicates.equals(that.predicates);
861 }
862 return false;
863 }
864
865
866
867
868
869
870 @Override
871 public String toString() {
872 return nodeTest + (predicates.isEmpty() ? "" : predicates.toString());
873 }
874 }
875
876 public static class ParenthesizedExpression extends Component {
877 private final Component wrapped;
878
879 public ParenthesizedExpression() {
880 this.wrapped = null;
881 }
882
883 public ParenthesizedExpression( Component wrapped ) {
884 this.wrapped = wrapped;
885 }
886
887
888
889
890 public Component getWrapped() {
891 return wrapped;
892 }
893
894
895
896
897
898
899 @Override
900 public Component collapse() {
901 return wrapped instanceof BinaryComponent ? this : wrapped;
902 }
903
904
905
906
907
908
909 @Override
910 public boolean equals( Object obj ) {
911 if (obj == this) return true;
912 if (obj instanceof ParenthesizedExpression) {
913 ParenthesizedExpression that = (ParenthesizedExpression)obj;
914 return this.wrapped.equals(that.wrapped);
915 }
916 return false;
917 }
918
919
920
921
922
923
924 @Override
925 public String toString() {
926 return "(" + wrapped + ")";
927 }
928 }
929
930 public static abstract class NodeTest extends Component {
931 }
932
933 public static abstract class KindTest extends NodeTest {
934 }
935
936 public static class NameTest extends NodeTest {
937 private final String prefixTest;
938 private final String localTest;
939
940 public NameTest( String prefixTest,
941 String localTest ) {
942 this.prefixTest = prefixTest;
943 this.localTest = localTest;
944 }
945
946
947
948
949 public String getPrefixTest() {
950 return prefixTest;
951 }
952
953
954
955
956 public String getLocalTest() {
957 return localTest;
958 }
959
960
961
962
963
964
965
966
967 public boolean matches( String prefix,
968 String local ) {
969 if (this.prefixTest != null && !this.prefixTest.equals(prefix)) return false;
970 if (this.localTest != null && !this.localTest.equals(local)) return false;
971 return true;
972 }
973
974
975
976
977
978
979 public boolean isWildcard() {
980 return prefixTest == null && localTest == null;
981 }
982
983
984
985
986
987
988 @Override
989 public int hashCode() {
990 return HashCode.compute(this.prefixTest, this.localTest);
991 }
992
993
994
995
996
997
998 @Override
999 public boolean equals( Object obj ) {
1000 if (obj == this) return true;
1001 if (obj instanceof NameTest) {
1002 NameTest that = (NameTest)obj;
1003 return ObjectUtil.isEqualWithNulls(this.prefixTest, that.prefixTest)
1004 && ObjectUtil.isEqualWithNulls(this.localTest, that.localTest);
1005 }
1006 return false;
1007 }
1008
1009
1010
1011
1012
1013
1014 @Override
1015 public String toString() {
1016 String local = localTest != null ? localTest : "*";
1017 return prefixTest == null ? local : (prefixTest + ":" + local);
1018 }
1019 }
1020
1021 public static class AttributeNameTest extends NodeTest {
1022 private final NameTest nameTest;
1023
1024 public AttributeNameTest( NameTest nameTest ) {
1025 this.nameTest = nameTest;
1026 }
1027
1028
1029
1030
1031 public NameTest getNameTest() {
1032 return nameTest;
1033 }
1034
1035
1036
1037
1038
1039
1040 @Override
1041 public String toString() {
1042 return "@" + nameTest;
1043 }
1044
1045
1046
1047
1048
1049
1050 @Override
1051 public boolean equals( Object obj ) {
1052 if (obj == this) return true;
1053 if (obj instanceof AttributeNameTest) {
1054 AttributeNameTest that = (AttributeNameTest)obj;
1055 return this.nameTest.equals(that.nameTest);
1056 }
1057 return false;
1058 }
1059
1060 }
1061
1062 public static class AnyKindTest extends KindTest {
1063
1064
1065
1066
1067
1068 @Override
1069 public boolean equals( Object obj ) {
1070 return obj == this || obj instanceof AnyKindTest;
1071 }
1072
1073
1074
1075
1076
1077
1078 @Override
1079 public String toString() {
1080 return "node()";
1081 }
1082 }
1083
1084 public static class TextTest extends KindTest {
1085
1086
1087
1088
1089
1090 @Override
1091 public boolean equals( Object obj ) {
1092 return obj == this || obj instanceof TextTest;
1093 }
1094
1095
1096
1097
1098
1099
1100 @Override
1101 public String toString() {
1102 return "text()";
1103 }
1104 }
1105
1106 public static class CommentTest extends KindTest {
1107
1108
1109
1110
1111
1112 @Override
1113 public boolean equals( Object obj ) {
1114 return obj == this || obj instanceof CommentTest;
1115 }
1116
1117
1118
1119
1120
1121
1122 @Override
1123 public String toString() {
1124 return "comment()";
1125 }
1126 }
1127
1128 public static class ProcessingInstructionTest extends KindTest {
1129 private final String nameOrStringLiteral;
1130
1131 public ProcessingInstructionTest( String nameOrStringLiteral ) {
1132 this.nameOrStringLiteral = nameOrStringLiteral;
1133 }
1134
1135
1136
1137
1138 public String getNameOrStringLiteral() {
1139 return nameOrStringLiteral;
1140 }
1141
1142
1143
1144
1145
1146
1147 @Override
1148 public boolean equals( Object obj ) {
1149 if (obj == this) return true;
1150 if (obj instanceof ProcessingInstructionTest) {
1151 ProcessingInstructionTest that = (ProcessingInstructionTest)obj;
1152 return this.nameOrStringLiteral.equals(that.nameOrStringLiteral);
1153 }
1154 return false;
1155 }
1156
1157
1158
1159
1160
1161
1162 @Override
1163 public String toString() {
1164 return "processing-instruction(" + nameOrStringLiteral + ")";
1165 }
1166 }
1167
1168 public static class DocumentTest extends KindTest {
1169 private KindTest elementOrSchemaElementTest;
1170
1171 public DocumentTest( ElementTest elementTest ) {
1172 CheckArg.isNotNull(elementTest, "elementTest");
1173 this.elementOrSchemaElementTest = elementTest;
1174 }
1175
1176 public DocumentTest( SchemaElementTest schemaElementTest ) {
1177 CheckArg.isNotNull(schemaElementTest, "schemaElementTest");
1178 this.elementOrSchemaElementTest = schemaElementTest;
1179 }
1180
1181
1182
1183
1184 public ElementTest getElementTest() {
1185 return elementOrSchemaElementTest instanceof ElementTest ? (ElementTest)elementOrSchemaElementTest : null;
1186 }
1187
1188
1189
1190
1191 public SchemaElementTest getSchemaElementTest() {
1192 return elementOrSchemaElementTest instanceof SchemaElementTest ? (SchemaElementTest)elementOrSchemaElementTest : null;
1193 }
1194
1195
1196
1197
1198
1199
1200 @Override
1201 public boolean equals( Object obj ) {
1202 if (obj == this) return true;
1203 if (obj instanceof DocumentTest) {
1204 DocumentTest that = (DocumentTest)obj;
1205 return this.elementOrSchemaElementTest.equals(that.elementOrSchemaElementTest);
1206 }
1207 return false;
1208 }
1209
1210
1211
1212
1213
1214
1215 @Override
1216 public String toString() {
1217 return "document-node(" + elementOrSchemaElementTest + ")";
1218 }
1219 }
1220
1221 public static class AttributeTest extends KindTest {
1222 private final NameTest attributeNameOrWildcard;
1223 private final NameTest typeName;
1224
1225 public AttributeTest( NameTest attributeNameOrWildcard,
1226 NameTest typeName ) {
1227 this.attributeNameOrWildcard = attributeNameOrWildcard;
1228 this.typeName = typeName;
1229 }
1230
1231
1232
1233
1234 public NameTest getAttributeName() {
1235 return attributeNameOrWildcard;
1236 }
1237
1238
1239
1240
1241 public NameTest getTypeName() {
1242 return typeName;
1243 }
1244
1245
1246
1247
1248
1249
1250 @Override
1251 public boolean equals( Object obj ) {
1252 if (obj == this) return true;
1253 if (obj instanceof AttributeTest) {
1254 AttributeTest that = (AttributeTest)obj;
1255 return ObjectUtil.isEqualWithNulls(this.typeName, that.typeName)
1256 && ObjectUtil.isEqualWithNulls(this.attributeNameOrWildcard, that.attributeNameOrWildcard);
1257 }
1258 return false;
1259 }
1260
1261
1262
1263
1264
1265
1266 @Override
1267 public String toString() {
1268 return "attribute(" + attributeNameOrWildcard + (typeName != null ? "," + typeName : "") + ")";
1269 }
1270 }
1271
1272 public static class ElementTest extends KindTest {
1273 private final NameTest elementNameOrWildcard;
1274 private final NameTest typeName;
1275
1276 public ElementTest( NameTest elementNameOrWildcard,
1277 NameTest typeName ) {
1278 this.elementNameOrWildcard = elementNameOrWildcard;
1279 this.typeName = typeName;
1280 }
1281
1282
1283
1284
1285 public NameTest getElementName() {
1286 return elementNameOrWildcard;
1287 }
1288
1289
1290
1291
1292 public NameTest getTypeName() {
1293 return typeName;
1294 }
1295
1296
1297
1298
1299
1300
1301 @Override
1302 public boolean equals( Object obj ) {
1303 if (obj == this) return true;
1304 if (obj instanceof ElementTest) {
1305 ElementTest that = (ElementTest)obj;
1306 return ObjectUtil.isEqualWithNulls(this.typeName, that.typeName)
1307 && ObjectUtil.isEqualWithNulls(this.elementNameOrWildcard, that.elementNameOrWildcard);
1308 }
1309 return false;
1310 }
1311
1312
1313
1314
1315
1316
1317 @Override
1318 public String toString() {
1319 return "element(" + elementNameOrWildcard + (typeName != null ? "," + typeName : "") + ")";
1320 }
1321 }
1322
1323 public static class SchemaElementTest extends KindTest {
1324 private final NameTest elementDeclarationName;
1325
1326 public SchemaElementTest( NameTest elementDeclarationName ) {
1327 this.elementDeclarationName = elementDeclarationName;
1328 }
1329
1330
1331
1332
1333 public NameTest getElementDeclarationName() {
1334 return elementDeclarationName;
1335 }
1336
1337
1338
1339
1340
1341
1342 @Override
1343 public boolean equals( Object obj ) {
1344 if (obj == this) return true;
1345 if (obj instanceof SchemaElementTest) {
1346 SchemaElementTest that = (SchemaElementTest)obj;
1347 return this.elementDeclarationName.equals(that.elementDeclarationName);
1348 }
1349 return false;
1350 }
1351
1352
1353
1354
1355
1356
1357 @Override
1358 public String toString() {
1359 return "schema-element(" + elementDeclarationName + ")";
1360 }
1361 }
1362
1363 public static class SchemaAttributeTest extends KindTest {
1364 private final NameTest attributeDeclarationName;
1365
1366 public SchemaAttributeTest( NameTest attributeDeclarationName ) {
1367 this.attributeDeclarationName = attributeDeclarationName;
1368 }
1369
1370
1371
1372
1373 public NameTest getAttributeDeclarationName() {
1374 return attributeDeclarationName;
1375 }
1376
1377
1378
1379
1380
1381
1382 @Override
1383 public boolean equals( Object obj ) {
1384 if (obj == this) return true;
1385 if (obj instanceof SchemaAttributeTest) {
1386 SchemaAttributeTest that = (SchemaAttributeTest)obj;
1387 return this.attributeDeclarationName.equals(that.attributeDeclarationName);
1388 }
1389 return false;
1390 }
1391
1392
1393
1394
1395
1396
1397 @Override
1398 public String toString() {
1399 return "schema-attribute(" + attributeDeclarationName + ")";
1400 }
1401 }
1402
1403 public static class OrderBy extends Component implements Iterable<OrderBySpec> {
1404 private final List<OrderBySpec> orderBySpecifications;
1405
1406 public OrderBy( List<OrderBySpec> orderBySpecifications ) {
1407 this.orderBySpecifications = orderBySpecifications;
1408 }
1409
1410
1411
1412
1413 public List<OrderBySpec> getOrderBySpecifications() {
1414 return orderBySpecifications;
1415 }
1416
1417
1418
1419
1420
1421
1422 @Override
1423 public Component collapse() {
1424 return super.collapse();
1425 }
1426
1427
1428
1429
1430
1431
1432 public Iterator<OrderBySpec> iterator() {
1433 return new ReadOnlyIterator<OrderBySpec>(orderBySpecifications.iterator());
1434 }
1435
1436
1437
1438
1439
1440
1441 @Override
1442 public boolean equals( Object obj ) {
1443 if (obj == this) return true;
1444 if (obj instanceof OrderBy) {
1445 OrderBy that = (OrderBy)obj;
1446 return this.orderBySpecifications.equals(that.orderBySpecifications);
1447 }
1448 return false;
1449 }
1450
1451
1452
1453
1454
1455
1456 @Override
1457 public String toString() {
1458 StringBuilder sb = new StringBuilder();
1459 sb.append("order-by(");
1460 boolean first = true;
1461 for (OrderBySpec spec : orderBySpecifications) {
1462 if (first) first = false;
1463 else sb.append(',');
1464 sb.append(spec);
1465 }
1466 sb.append(')');
1467 return sb.toString();
1468 }
1469 }
1470
1471 public static class OrderBySpec {
1472 private final Order order;
1473 private final FunctionCall scoreFunction;
1474 private final NameTest attributeName;
1475
1476 public OrderBySpec( Order order,
1477 FunctionCall scoreFunction ) {
1478 assert order != null;
1479 assert scoreFunction != null;
1480 this.order = order;
1481 this.scoreFunction = scoreFunction;
1482 this.attributeName = null;
1483 }
1484
1485 public OrderBySpec( Order order,
1486 NameTest attributeName ) {
1487 assert order != null;
1488 assert attributeName != null;
1489 this.order = order;
1490 this.scoreFunction = null;
1491 this.attributeName = attributeName;
1492 }
1493
1494
1495
1496
1497
1498
1499 public NameTest getAttributeName() {
1500 return attributeName;
1501 }
1502
1503
1504
1505
1506
1507
1508
1509 public FunctionCall getScoreFunction() {
1510 return scoreFunction;
1511 }
1512
1513
1514
1515
1516
1517
1518 public Order getOrder() {
1519 return order;
1520 }
1521
1522
1523
1524
1525
1526
1527 @Override
1528 public boolean equals( Object obj ) {
1529 if (obj == this) return true;
1530 if (obj instanceof OrderBySpec) {
1531 OrderBySpec that = (OrderBySpec)obj;
1532 if (this.order != that.order) return false;
1533 if (this.attributeName != null && !this.attributeName.equals(that.attributeName)) return false;
1534 if (this.scoreFunction != null && !this.scoreFunction.equals(that.scoreFunction)) return false;
1535 return true;
1536 }
1537 return false;
1538 }
1539
1540
1541
1542
1543
1544
1545 @Override
1546 public String toString() {
1547 StringBuilder sb = new StringBuilder();
1548 if (scoreFunction != null) {
1549 sb.append(scoreFunction.toString());
1550 } else {
1551 sb.append('@').append(attributeName.toString());
1552 }
1553 switch (order) {
1554 case ASCENDING:
1555 sb.append(" ascending");
1556 break;
1557 case DESCENDING:
1558 sb.append(" descending");
1559 break;
1560 }
1561 return sb.toString();
1562 }
1563 }
1564 }