KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > xquery > util > SequenceUtils


1 // Copyright (c) 2001, 2004, 2006 Per M.A. Bothner and Brainfood Inc.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.xquery.util;
5 import gnu.mapping.Values;
6 import gnu.mapping.*;
7 import gnu.lists.*;
8 import gnu.xml.NodeTree;
9 import gnu.kawa.xml.*;
10 import gnu.math.DFloNum;
11 /* #ifdef use:org.w3c.dom.Node */
12 // import org.w3c.dom.Node;
13
/* #endif */
14
15 public class SequenceUtils
16 {
17   public static Object JavaDoc zeroOrOne (Object JavaDoc arg)
18   {
19     // Assumes arg is normalized.
20
if (arg instanceof Values && ! ((Values) arg).isEmpty())
21       throw new IllegalArgumentException JavaDoc();
22     return arg;
23   }
24
25   public static Object JavaDoc oneOrMore (Object JavaDoc arg)
26   {
27     if (arg instanceof Values && ((Values) arg).isEmpty())
28       throw new IllegalArgumentException JavaDoc();
29     return arg;
30   }
31
32   public static Object JavaDoc exactlyOne (Object JavaDoc arg)
33   {
34     // Assumes arg is normalized.
35
if (arg instanceof Values)
36       throw new IllegalArgumentException JavaDoc();
37     return arg;
38   }
39
40   public static boolean isEmptySequence(Object JavaDoc arg)
41   {
42     return arg instanceof Values && ((Values) arg).isEmpty();
43   }
44
45   public static boolean exists (Object JavaDoc arg)
46   {
47     return ! (arg instanceof Values && ((Values) arg).isEmpty());
48   }
49
50   public static void insertBefore$X (Object JavaDoc target, long position,
51                                      Object JavaDoc inserts, CallContext ctx)
52   {
53     Consumer out = ctx.consumer;
54     boolean written = false;
55     if (position <= 0)
56       position = 1;
57     if (target instanceof Values)
58       {
59         Values values = (Values) target;
60         int ipos = 0;
61         long i = 0;
62         for (;;)
63           {
64             int next = values.nextPos(ipos);
65             if ((next == 0 && ! written) || ++i == position)
66               {
67                 Values.writeValues(inserts, out);
68                 written = true;
69               }
70             if (next == 0)
71               break;
72             values.consumePosRange(ipos, next, out);
73             ipos = next;
74           }
75       }
76     else
77       {
78         if (position <= 1)
79           Values.writeValues(inserts, out);
80         out.writeObject(target);
81         if (position > 1)
82           Values.writeValues(inserts, out);
83       }
84   }
85
86   public static void remove$X (Object JavaDoc arg, long position, CallContext ctx)
87   {
88     Consumer out = ctx.consumer;
89     if (arg instanceof Values)
90       {
91         Values values = (Values) arg;
92         int ipos = 0;
93         long i = 0;
94         for (;;)
95           {
96             int next = values.nextPos(ipos);
97             if (next == 0)
98               break;
99             if (++i != position )
100               values.consumePosRange(ipos, next, out);
101             ipos = next;
102           }
103       }
104     else if (position != 1)
105       out.writeObject(arg);
106   }
107
108   /** Implements the standard XQuery function {@code reverse}. */
109   public static void reverse$X (Object JavaDoc arg, CallContext ctx)
110   {
111     Consumer out = ctx.consumer;
112     if (! (arg instanceof Values))
113       {
114         out.writeObject(arg);
115         return;
116       }
117     Values vals = (Values) arg;
118     int ipos = 0;
119     int[] poses = new int[100];
120     int n = 0;
121     for (;;)
122       {
123         if (n >= poses.length)
124           {
125             int[] t = new int[2 * n];
126             System.arraycopy(poses, 0, t, 0, n);
127             poses = t;
128           }
129         poses[n++] = ipos;
130         ipos = vals.nextPos(ipos);
131         if (ipos == 0)
132           break;
133       }
134     for (int i = n-1; --i >= 0; )
135       vals.consumePosRange(poses[i], poses[i+1], out);
136   }
137
138   public static void indexOf$X (Object JavaDoc seqParam, Object JavaDoc srchParam,
139                                 NamedCollator collator, CallContext ctx)
140   {
141     Consumer out = ctx.consumer;
142     if (seqParam instanceof Values)
143       {
144         Values vals = (Values) seqParam;
145         int ipos = vals.startPos();
146         int i = 1;
147         for (; (ipos = vals.nextPos(ipos)) != 0; i++)
148           if (Compare.apply(Compare.LENIENT_EQ,
149                             vals.getPosPrevious(ipos),
150                             srchParam, collator))
151             out.writeInt(i);
152       }
153     else if (Compare.apply(Compare.LENIENT_EQ, seqParam, srchParam, collator))
154       out.writeInt(1);
155   }
156
157   public static final NodeType textOrElement
158     = new NodeType("element-or-text", NodeType.GROUP_OK|NodeType.TEXT_OK);
159
160   public static boolean deepEqualChildren (NodeTree seq1, int ipos1,
161                                            NodeTree seq2, int ipos2,
162                                            NamedCollator collator)
163   {
164     NodeType filter = textOrElement;
165     int child1 = seq1.firstChildPos(ipos1, filter);
166     int child2 = seq2.firstChildPos(ipos2, filter);
167     for (;;)
168       {
169     if (child1 == 0 || child2 == 0)
170           return child1 == child2;
171         if (! deepEqual(seq1, child1, seq2, child2, collator))
172           return false;
173         child1 = seq1.nextMatching(child1, filter, -1, false);
174         child2 = seq2.nextMatching(child2, filter, -1, false);
175       }
176   }
177
178   public static boolean deepEqual (NodeTree seq1, int ipos1,
179                                    NodeTree seq2, int ipos2,
180                                    NamedCollator collator)
181   {
182     int kind1 = seq1.getNextKind(ipos1);
183     int kind2 = seq1.getNextKind(ipos2);
184     switch (kind1)
185       {
186       case Sequence.GROUP_VALUE:
187         if (kind1 != kind2)
188           return false;
189         // Assumes local-name and namespace-URI are interned.
190
String JavaDoc loc1 = seq1.posLocalName(ipos1);
191         String JavaDoc loc2 = seq2.posLocalName(ipos2);
192         if (loc1 != loc2)
193           return false;
194         String JavaDoc ns1 = seq1.posNamespaceURI(ipos1);
195         String JavaDoc ns2 = seq2.posNamespaceURI(ipos2);
196         if (ns1 != ns2)
197           return false;
198         int attr1 = seq1.firstAttributePos(ipos1);
199         int nattr1 = 0;
200         for (;;)
201           {
202             if (attr1 == 0
203                 || seq1.getNextKind(attr1) != Sequence.ATTRIBUTE_VALUE)
204               break;
205             nattr1++;
206             String JavaDoc local = seq1.posLocalName(attr1);
207             String JavaDoc ns = seq1.posNamespaceURI(attr1);
208             int attr2 = seq2.getAttributeI(ipos2, ns, local);
209             if (attr2 == 0)
210               return false;
211             String JavaDoc aval1 = KNode.getNodeValue(seq1, attr1);
212             String JavaDoc aval2 = KNode.getNodeValue(seq2, attr2);
213             if (! deepEqualItems(aval1, aval2, collator))
214               return false;
215             attr1 = seq1.nextPos(attr1);
216           }
217         int nattr2 = seq2.getAttributeCount(ipos2);
218         if (nattr1 != nattr2)
219           return false;
220         /* ... fall through ... */
221       case Sequence.DOCUMENT_VALUE:
222         return deepEqualChildren(seq1, ipos1, seq2, ipos2, collator);
223       case Sequence.ATTRIBUTE_VALUE:
224         if (seq1.posLocalName(ipos1) != seq2.posLocalName(ipos2)
225             || seq1.posNamespaceURI(ipos1) != seq2.posNamespaceURI(ipos2))
226           return false;
227         return deepEqualItems(KAttr.getObjectValue(seq1, ipos1),
228                               KAttr.getObjectValue(seq2, ipos2),
229                               collator);
230       case Sequence.PROCESSING_INSTRUCTION_VALUE:
231         if (! seq1.posTarget(ipos1).equals(seq2.posTarget(ipos2)))
232           return false;
233         return KNode.getNodeValue(seq1, ipos1)
234           .equals(KNode.getNodeValue(seq2, ipos2));
235       case Sequence.COMMENT_VALUE:
236       case Sequence.CDATA_VALUE:
237       default:
238         if (kind1 != kind2)
239           return false;
240         return KNode.getNodeValue(seq1, ipos1)
241           .equals(KNode.getNodeValue(seq2, ipos2));
242       }
243   }
244
245   public static boolean deepEqualItems (Object JavaDoc arg1, Object JavaDoc arg2,
246                                         NamedCollator collator)
247   {
248     if (NumberValue.isNaN(arg1) && NumberValue.isNaN(arg2))
249       return true;
250     return Compare.atomicCompare(Compare.TRUE_IF_EQU, arg1, arg2, collator);
251   }
252
253   public static boolean deepEqual (Object JavaDoc arg1, Object JavaDoc arg2,
254                                    NamedCollator collator)
255   {
256     if (arg1 == arg2)
257       return true;
258     if (arg1 == null || arg1 == Values.empty)
259       return arg2 == null || arg2 == Values.empty;
260     if (arg2 == null || arg2 == Values.empty)
261       return false;
262     int ipos1 = 1, ipos2 = 1;
263     boolean is1seq = arg1 instanceof Values;
264     boolean is2seq = arg2 instanceof Values;
265     Values vals1 = is1seq ? (Values) arg1 : null;
266     Values vals2 = is2seq ? (Values) arg2 : null;
267     boolean first = true;
268     for (;;)
269       {
270         if (is1seq)
271           {
272             if (first)
273               ipos1 = vals1.startPos();
274             ipos1 = vals1.nextPos(ipos1);
275           }
276         if (is2seq)
277           {
278             if (first)
279               ipos2 = vals2.startPos();
280             ipos2 = vals2.nextPos(ipos2);
281           }
282         if (ipos1 == 0 || ipos2 == 0)
283           return ipos1 == ipos2;
284         Object JavaDoc item1 = is1seq ? vals1.getPosPrevious(ipos1) : arg1;
285         Object JavaDoc item2 = is2seq ? vals2.getPosPrevious(ipos2) : arg2;
286
287         if (! (item1 instanceof KNode) && !( item2 instanceof KNode))
288           {
289             try
290               {
291                 if (! deepEqualItems(arg1, arg2, collator))
292                   return false;
293               }
294             catch (Throwable JavaDoc ex)
295               {
296                 return false;
297               }
298           }
299         else if (item1 instanceof KNode && item2 instanceof KNode)
300           {
301             KNode node1 = (KNode) item1;
302             KNode node2 = (KNode) item2;
303             if (! deepEqual((NodeTree) node1.sequence, node1.ipos,
304                             (NodeTree) node2.sequence, node2.ipos,
305                             collator))
306               return false;
307           }
308         else
309           return false;
310
311         if (first)
312           {
313             first = false;
314             if (! is1seq)
315               ipos1 = 0;
316             if (! is2seq)
317               ipos2 = 0;
318           }
319       }
320   }
321 }
322
Popular Tags