01: // Copyright (c) 2006 Per M.A. Bothner.
02: // This is free software; for terms and warranty disclaimer see ./COPYING.
03:
04: package gnu.xquery.util;
05:
06: import gnu.lists.*;
07: import gnu.kawa.xml.*;
08:
09: /** Used to filter the output of RelativeStep.
10: * Atomic values are passed though as-is, while node values are sorted
11: * by document order and duplicates removed. An exception is thrown
12: * if there is a mix of atoms and nodes.
13: * Informally: {@code E1/E2} is implemented as:
14: * {@code RelativeStepFilter(for $dot in E1 return E2)}.
15: */
16:
17: public class RelativeStepFilter extends FilterConsumer implements
18: PositionConsumer {
19: // 'A' for atomic, 'N' for nodes, '\0' for neither.
20: char seen;
21:
22: SortedNodes snodes;
23:
24: public RelativeStepFilter(Consumer base) {
25: super (base);
26: }
27:
28: // Not sure if this is ever called ...
29: public void consume(SeqPosition position) {
30: writePosition(position.sequence, position.ipos);
31: }
32:
33: public void writeObject(Object v) {
34: if (v instanceof SeqPosition) {
35: SeqPosition n = (SeqPosition) v;
36: writePosition(n.sequence, n.ipos);
37: } else
38: super .writeObject(v);
39: }
40:
41: protected void beforeContent() {
42: if (seen == 'N')
43: throw new Error("path returns mix of atoms and nodes");
44: seen = 'A';
45: }
46:
47: public void writePosition(AbstractSequence seq, int ipos) {
48: if (seen == 'A')
49: throw new Error("path returns mix of atoms and nodes");
50: seen = 'N';
51: if (snodes == null)
52: snodes = new SortedNodes();
53: snodes.writePosition(seq, ipos);
54: }
55:
56: public void finish() {
57: if (snodes != null)
58: snodes.consume(base);
59: snodes = null;
60: }
61: }
|