KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > mediator > DOMUtils > EvaluationVisitor


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 Universite de Versailles Saint-Quentin.
4  * Copyright (C) 2003 XQuark Group.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
19  * You can also get it at http://www.gnu.org/licenses/lgpl.html
20  *
21  * For more information on this software, see http://www.xquark.org.
22  */

23
24 package org.xquark.mediator.DOMUtils;
25
26 import java.math.BigDecimal JavaDoc;
27 import java.sql.Timestamp JavaDoc;
28 import java.util.*;
29
30 import org.w3c.dom.Attr JavaDoc;
31 import org.w3c.dom.Node JavaDoc;
32 import org.xquark.schema.*;
33 import org.xquark.xpath.datamodel.*;
34 import org.xquark.xquery.parser.*;
35 import org.xquark.xquery.parser.primitivefunctions.fnfunctions.*;
36 import org.xquark.xquery.parser.primitivefunctions.xsfunctions.*;
37 import org.xquark.xquery.parser.util.Constants;
38
39 /**
40  * A simple class for evaluating en attendant the real evaluator.
41  * evaluate the expression and return true or false
42  *
43  */

44 public class EvaluationVisitor extends DefaultParserVisitor {
45     // **********************************************************************
46
// * VERSIONING
47
// **********************************************************************
48
private static final String JavaDoc RCSRevision = "$Revision: 1.23 $";
49     private static final String JavaDoc RCSName = "$Name: $";
50     // **********************************************************************
51
// * CLASS VARIABLES
52
// **********************************************************************
53
private BufferTuple buffertuple = null;
54     private ArrayList tuplelist = null;
55     private Tuple tuple = null;
56     //private XDBCResultSetInterface resultSet = null;
57

58     private boolean verdict = false;
59
60     //private BufferTuple resultbuffertuple = null;
61
private Tuple resulttuple = null;
62     private ArrayList resnodes = null;
63     private Comparable JavaDoc resvalue = null;
64
65     protected static TypedDocumentImpl docimpl = null;
66     static {
67         docimpl = new TypedDocumentImpl();
68     }
69     private SchemaManager schemamanager = null;
70
71     public static Integer JavaDoc UNKNOWN_TYPE = new Integer JavaDoc(-1);
72     public static Integer JavaDoc BOOLEAN_TYPE = new Integer JavaDoc(0);
73     public static Integer JavaDoc VALUE_TYPE = new Integer JavaDoc(1);
74     public static Integer JavaDoc NODE_TYPE = new Integer JavaDoc(2);
75     public static Integer JavaDoc TUPLE_TYPE = new Integer JavaDoc(3);
76     public static Integer JavaDoc BUFFER_TYPE = new Integer JavaDoc(4);
77     private Stack returnType = new Stack();
78
79     /**
80      *
81      */

82     public EvaluationVisitor(SchemaManager schemamanager) {
83         this.schemamanager = schemamanager;
84     }
85
86     /**
87      *
88      */

89     public EvaluationVisitor(SchemaManager schemamanager, Tuple tuple) {
90         this.schemamanager = schemamanager;
91         this.tuple = tuple;
92     }
93
94     /**
95      *
96      */

97     public EvaluationVisitor(SchemaManager schemamanager, ArrayList tuplelist) {
98         this.schemamanager = schemamanager;
99         this.tuplelist = tuplelist;
100     }
101
102     /**
103      *
104      */

105 // public EvaluationVisitor(SchemaManager schemamanager, BufferTuple buffertuple) {
106
// this.schemamanager = schemamanager;
107
// this.tuple = null;
108
// this.buffertuple = buffertuple;
109
// }
110

111     public void setReturnType(Integer JavaDoc setType) {
112         if (!returnType.isEmpty())
113             this.returnType.pop();
114         returnType.push(setType);
115     }
116
117     private void clear() {
118         //resultbuffertuple = null;
119
resulttuple = null;
120         resnodes = null;
121         resvalue = null;
122         verdict = false;
123     }
124     private void setResultTuple(Tuple tuple) {
125         //resultbuffertuple = null;
126
resulttuple = tuple;
127         resnodes = null;
128         resvalue = null;
129         verdict = false;
130     }
131     private void setResultBufferTuple(BufferTuple buffertuple) {
132         //resultbuffertuple = buffertuple;
133
resulttuple = null;
134         resnodes = null;
135         resvalue = null;
136         verdict = false;
137     }
138     private void setResnodes(ArrayList nodes) {
139         //resultbuffertuple = null;
140
resulttuple = null;
141         resnodes = nodes;
142         resvalue = null;
143         verdict = false;
144     }
145     private void setValue(Comparable JavaDoc comp) {
146         //resultbuffertuple = null;
147
resulttuple = null;
148         resnodes = null;
149         resvalue = comp;
150         verdict = false;
151     }
152     private void setVerdict(boolean bool) {
153         //resultbuffertuple = null;
154
resulttuple = null;
155         resnodes = null;
156         resvalue = null;
157         verdict = bool;
158     }
159     public void setSchemaManager(SchemaManager schemamanager) {
160         this.schemamanager = schemamanager;
161     }
162     public void reset() {
163         clear();
164         this.tuple = null;
165         this.buffertuple = null;
166         this.tuplelist = null;
167         returnType.clear();
168     }
169     public void reset(Tuple tuple) {
170         clear();
171         this.tuple = tuple;
172         this.buffertuple = null;
173         this.tuplelist = null;
174         returnType.clear();
175     }
176     public void reset(BufferTuple buffertuple) {
177         clear();
178         this.tuple = null;
179         this.buffertuple = buffertuple;
180         this.tuplelist = null;
181         returnType.clear();
182     }
183     public void reset(ArrayList tuplelist) {
184         clear();
185         if (tuplelist.size() > 1) {
186             this.tuple = null;
187             this.buffertuple = null;
188             this.tuplelist = tuplelist;
189         } else if (tuplelist.size() == 1) {
190             this.tuple = (Tuple) tuplelist.get(0);
191             this.buffertuple = null;
192             this.tuplelist = null;
193         } else {
194             this.tuple = null;
195             this.buffertuple = null;
196             this.tuplelist = null;
197         }
198         returnType.clear();
199     }
200     public boolean getVerdict() {
201         return verdict;
202     }
203     // public BufferTuple getResultBufferTuple() {
204
// return resultbuffertuple;
205
// }
206
public Tuple getResultTuple() {
207         return resulttuple;
208     }
209     public ArrayList getResNodes() {
210         return resnodes;
211     }
212     public Comparable JavaDoc getResValue() {
213         if (resvalue != null)
214             return resvalue;
215         if (resnodes != null && resnodes.size() == 1) {
216             resvalue = (Comparable JavaDoc)((TypedNode)resnodes.get(0)).getTypedValue();
217         }
218         return resvalue;
219     }
220
221     public void visit(AttributeValuePair arg) throws XQueryException {
222         if (arg.isXmlns()) {
223             setResnodes(null);
224             return;
225         }
226         if (!(arg.getExpression1() instanceof QName)) {
227             throw new XQueryException("EvaluationVisitor : name of AttributeValuePair is not a QName : " + arg.getExpression1());
228         }
229         QName attName = (QName) arg.getExpression1();
230         Object JavaDoc attValue = null;
231         if (!(arg.getExpression2() instanceof Value)) {
232             returnType.push(VALUE_TYPE);
233             arg.getExpression2().accept(this);
234             returnType.pop();
235             if (resvalue == null) {
236                 throw new XQueryException("EvaluationVisitor : value of AttributeValuePair is null : " + arg.getExpression2());
237             }
238             attValue = resvalue;
239         } else
240             attValue = ((Value) arg.getExpression2()).getObjectValue();
241         if (attValue != null) {
242             TypedAttributeImpl att = new TypedAttributeImpl(docimpl, ((QName) attName).getNameSpace(), ((QName) attName).getLocalName());
243             att.setNodeValue(attValue.toString());
244             att.setTypedValue(attValue);
245             ArrayList tmplist = new ArrayList(1);
246             tmplist.add(att);
247             setResnodes(tmplist);
248             return;
249         }
250         setResnodes(null);
251     }
252
253     public void visit(BinOpANDExpression arg) throws XQueryException {
254         //verdict = true;
255
if (tuple != null) {
256             XQueryExpression exp1 = arg.getExpression1();
257             EvaluationVisitor visitor = new EvaluationVisitor(this.schemamanager, tuple);
258             visitor.setReturnType(EvaluationVisitor.BOOLEAN_TYPE);
259             exp1.accept(visitor);
260             verdict = visitor.getVerdict();
261             if (verdict == false) {
262                 setVerdict(false);
263                 return;
264             }
265             XQueryExpression exp2 = arg.getExpression2();
266             //visitor = new EvaluationVisitor(this.schemamanager, tuple);
267
visitor.reset(tuple);
268             visitor.setReturnType(EvaluationVisitor.BOOLEAN_TYPE);
269             exp2.accept(visitor);
270             verdict &= visitor.getVerdict();
271         } else if (buffertuple != null) {
272             verdict = false;
273         } else if (tuplelist != null) {
274             XQueryExpression exp1 = arg.getExpression1();
275             EvaluationVisitor visitor = new EvaluationVisitor(this.schemamanager, tuplelist);
276             visitor.setReturnType(EvaluationVisitor.BOOLEAN_TYPE);
277             exp1.accept(visitor);
278             verdict = visitor.getVerdict();
279             if (verdict == false) {
280                 setVerdict(false);
281                 return;
282             }
283             XQueryExpression exp2 = arg.getExpression2();
284             //visitor = new EvaluationVisitor(this.schemamanager, tuplelist);
285
visitor.reset(tuplelist);
286             visitor.setReturnType(EvaluationVisitor.BOOLEAN_TYPE);
287             exp2.accept(visitor);
288             verdict &= visitor.getVerdict();
289         } else {
290             XQueryExpression exp1 = arg.getExpression1();
291             EvaluationVisitor visitor = new EvaluationVisitor(this.schemamanager);
292             visitor.setReturnType(EvaluationVisitor.BOOLEAN_TYPE);
293             exp1.accept(visitor);
294             verdict = visitor.getVerdict();
295             if (verdict == false) {
296                 setVerdict(false);
297                 return;
298             }
299             XQueryExpression exp2 = arg.getExpression2();
300             //visitor = new EvaluationVisitor(this.schemamanager);
301
visitor.reset();
302             visitor.setReturnType(EvaluationVisitor.BOOLEAN_TYPE);
303             exp2.accept(visitor);
304             verdict &= visitor.getVerdict();
305         }
306         setVerdict(verdict);
307     }
308
309     public void visit(BinOpORExpression arg) throws XQueryException {
310         //verdict = false;
311
if (tuple != null) {
312             XQueryExpression exp1 = arg.getExpression1();
313             EvaluationVisitor visitor = new EvaluationVisitor(this.schemamanager, tuple);
314             exp1.accept(visitor);
315             verdict = visitor.getVerdict();
316             XQueryExpression exp2 = arg.getExpression2();
317             //visitor = new EvaluationVisitor(this.schemamanager, tuple);
318
visitor.reset(tuple);
319             exp2.accept(visitor);
320             verdict = verdict || visitor.getVerdict();
321         } else if (buffertuple != null) {
322             verdict = false;
323         } else if (tuplelist != null) {
324             XQueryExpression exp1 = arg.getExpression1();
325             EvaluationVisitor visitor = new EvaluationVisitor(this.schemamanager, tuplelist);
326             exp1.accept(visitor);
327             verdict = visitor.getVerdict();
328             XQueryExpression exp2 = arg.getExpression2();
329             //visitor = new EvaluationVisitor(this.schemamanager, tuplelist);
330
visitor.reset(tuplelist);
331             exp2.accept(visitor);
332             verdict = verdict || visitor.getVerdict();
333         } else {
334             XQueryExpression exp1 = arg.getExpression1();
335             EvaluationVisitor visitor = new EvaluationVisitor(this.schemamanager);
336             exp1.accept(visitor);
337             verdict = visitor.getVerdict();
338             XQueryExpression exp2 = arg.getExpression2();
339             //visitor = new EvaluationVisitor(this.schemamanager);
340
visitor.reset();
341             exp2.accept(visitor);
342             verdict = verdict || visitor.getVerdict();
343         }
344         setVerdict(verdict);
345     }
346
347     // public void visit(CastTreatExpression arg) throws XQueryException
348
// public void visit(ContextDeclaration arg) throws XQueryException
349
// public void visit(Dereference arg) throws XQueryException
350

351     public void visit(Element arg) throws XQueryException {
352         XQueryExpression startTag = arg.getStartTag();
353         if (!(startTag instanceof QName))
354             throw new XQueryException("Tag of Element expression is not a QName : " + startTag);
355         QName startTagQName = (QName) startTag;
356         TypedElement element = new TypedElementImpl(docimpl, startTagQName.getNameSpace(), startTagQName.getLocalName());
357         ArrayList tmplist = arg.getAttributes();
358         if (tmplist != null && !tmplist.isEmpty()) {
359             for (int i = 0; i < tmplist.size(); i++) {
360                 AttributeValuePair attValPair = (AttributeValuePair) tmplist.get(i);
361                 returnType.push(NODE_TYPE);
362                 attValPair.accept(this);
363                 returnType.pop();
364                 if (resnodes != null) {
365                     TypedAttribute att = (TypedAttribute) resnodes.get(0);
366                     element.setAttributeNodeNS((Attr JavaDoc) att);
367                 }
368             }
369         }
370         tmplist = arg.getSubExpressions();
371         if (tmplist != null && !tmplist.isEmpty()) {
372             for (int i = 0; i < tmplist.size(); i++) {
373                 XQueryExpression subExpr = (XQueryExpression) tmplist.get(i);
374                 returnType.push(NODE_TYPE);
375                 subExpr.accept(this);
376                 returnType.pop();
377                 if (resnodes != null) {
378                     for (int j = 0; j < resnodes.size(); j++) {
379                         TypedNode resnode = (TypedNode) resnodes.get(j);
380                         if (docimpl != resnode.getOwnerDocument())
381                             resnode = (TypedNode) element.getOwnerDocument().importNode(resnode, true);
382                         if (resnode instanceof TypedAttributeImpl) {
383                             element.setAttributeNodeNS((Attr JavaDoc) resnode);
384                         } else if (resnode instanceof TypedElementImpl) {
385                             element.appendChild((Node JavaDoc) resnode);
386                         } else if (resnode instanceof TypedValueImpl) {
387                             element.appendChild((Node JavaDoc) resnode);
388                         } else {
389                             throw new XQueryException("Could not add child : " + resnode + " to parent.");
390                             // do nothing for now, warning?
391
}
392                     }
393                 }
394             }
395         }
396         tmplist = new ArrayList(1);
397         tmplist.add(element);
398         setResnodes(tmplist);
399     }
400
401     public void visit (ExternalVariable arg) throws XQueryException {
402         Variable var = (Variable)arg.getObjectValue();
403         if (var.getExpression() != null)
404             var.getExpression().accept(this);
405         else
406             var.accept(this);
407     }
408
409     // public void visit (FLWRExpression arg) throws XQueryException
410
// public void visit (FunctionCall arg) throws XQueryException
411
// public void visit(FunctionDefinition arg) throws XQueryException
412
// public void visit(InstanceOfExpression arg) throws XQueryException
413
// public void visit(InternalFunctionCall arg) throws XQueryException
414
// public void visit(ITEExpression arg) throws XQueryException
415
// public void visit(LibraryFunctionCall arg) throws XQueryException
416
// public void visit(ListOpAFTERExpression arg) throws XQueryException
417

418     public void visit(ListOpArithExpression arg) throws XQueryException {
419         XQueryExpression exp1 = arg.getExpression1();
420         XQueryExpression exp2 = arg.getExpression2();
421         int operator = arg.getOperator();
422
423         returnType.push(UNKNOWN_TYPE);
424         exp1.accept(this);
425         ArrayList trees1 = resnodes;
426         Number JavaDoc value1 = (resvalue instanceof Number JavaDoc) ? (Number JavaDoc) resvalue : null;
427         exp2.accept(this);
428         ArrayList trees2 = resnodes;
429         Number JavaDoc value2 = (resvalue instanceof Number JavaDoc) ? (Number JavaDoc) resvalue : null;
430         returnType.pop();
431
432         //TypedDocument docimpl = new TypedDocument() ;
433
//Integer retType = (Integer)returnType.pop();
434
if ((trees1 == null || trees1.isEmpty()) && (trees2 == null || trees2.isEmpty())) {
435             Number JavaDoc res = processOperation(exp1, exp2, null, null, value1, value2, operator);
436             //if (retType.equals(NODE_TYPE)) {
437
SimpleType st = getSimpleType((Comparable JavaDoc) res, schemamanager.getDoubleType());
438             TypedNode text = (TypedNode) docimpl.createTypedValue(res, st);
439             text.setTypedValue(res);
440             text.setType(st);
441             ArrayList tmplist = new ArrayList(1);
442             tmplist.add(text);
443             setResnodes(tmplist);
444             // }
445
// else if (retType.equals(VALUE_TYPE)) {
446
// setValue(new Double(res));
447
// }
448
// else
449
// clear();
450
return;
451         }
452
453         if ((trees1 == null || trees1.isEmpty()) && (trees2 != null) && (!trees2.isEmpty())) {
454             ArrayList tmplist = new ArrayList(trees2.size());
455             for (int j = 0; j < trees2.size(); j++) {
456                 TypedNode tree2 = (TypedNode) trees2.get(j);
457                 Number JavaDoc res = processOperation(exp1, exp2, null, tree2, value1, value2, operator);
458                 SimpleType st = getSimpleType((Comparable JavaDoc) res, schemamanager.getDoubleType());
459                 TypedNode text = (TypedNode) docimpl.createTypedValue(res, st);
460                 text.setTypedValue(res);
461                 text.setType(st);
462                 tmplist.add(text);
463             }
464             // if (retType.equals(NODE_TYPE)) {
465
setResnodes(tmplist);
466             // }
467
// else
468
// clear();
469
return;
470         }
471
472         if ((trees1 != null) && (!trees1.isEmpty()) && (trees2 == null) || (trees2.isEmpty())) {
473             ArrayList tmplist = new ArrayList(trees1.size());
474             for (int i = 0; i < trees1.size(); i++) {
475                 TypedNode tree1 = (TypedNode) trees1.get(i);
476                 Number JavaDoc res = processOperation(exp1, exp2, tree1, null, value1, value2, operator);
477                 SimpleType st = getSimpleType((Comparable JavaDoc) res, schemamanager.getDoubleType());
478                 TypedNode text = (TypedNode) docimpl.createTypedValue(res, st);
479                 text.setTypedValue(res);
480                 text.setType(st);
481                 tmplist.add(text);
482             }
483             // if (retType.equals(NODE_TYPE)) {
484
setResnodes(tmplist);
485             // }
486
// else
487
// clear();
488
return;
489         }
490
491         ArrayList tmplist = new ArrayList(trees1.size() * trees2.size());
492         for (int i = 0; i < trees1.size(); i++) {
493             TypedNode tree1 = (TypedNode) trees1.get(i);
494             for (int j = 0; j < trees2.size(); j++) {
495                 TypedNode tree2 = (TypedNode) trees2.get(j);
496                 Number JavaDoc res = processOperation(exp1, exp2, tree1, tree2, value1, value2, operator);
497                 SimpleType st = getSimpleType((Comparable JavaDoc) res, schemamanager.getDoubleType());
498                 TypedNode text = (TypedNode) docimpl.createTypedValue(res, st);
499                 text.setTypedValue(res);
500                 text.setType(st);
501                 tmplist.add(text);
502             }
503         }
504         // if (retType.equals(NODE_TYPE)) {
505
setResnodes(tmplist);
506         // }
507
// else
508
// clear();
509
}
510
511     // public void visit(ListOpBEFOREExpression arg) throws XQueryException
512
public void visit(ListOpCompExpression arg) throws XQueryException {
513         XQueryExpression exp1 = arg.getExpression1();
514         XQueryExpression exp2 = arg.getExpression2();
515         int operator = arg.getOperator();
516
517         returnType.push(EvaluationVisitor.NODE_TYPE);
518         resnodes = null;
519         resvalue = null;
520         exp1.accept(this);
521         //returnType.pop();
522
ArrayList trees1 = resnodes;
523         if (trees1 != null && trees1.isEmpty())
524             trees1 = null;
525         Comparable JavaDoc value1 = resvalue;
526         //returnType.push(EvaluationVisitor.NODE_TYPE);
527
resnodes = null;
528         resvalue = null;
529         exp2.accept(this);
530         returnType.pop();
531         ArrayList trees2 = resnodes;
532         if (trees2 != null && trees2.isEmpty())
533             trees2 = null;
534         Comparable JavaDoc value2 = resvalue;
535
536         if (value1 != null && value2 != null) {
537             processComparison(null, null, null, null, value1, value2, operator);
538             setVerdict(verdict);
539             return;
540         }
541
542         if (trees1 == null && trees2 == null) {
543             processComparison(exp1, exp2, null, null, value1, value2, operator);
544             return;
545         }
546
547         if (trees1 == null && trees2 != null) {
548             for (int j = 0; j < trees2.size(); j++) {
549                 TypedNode tree2 = (TypedNode) trees2.get(j);
550                 processComparison(exp1, exp2, null, tree2, value1, value2, operator);
551                 if (verdict == true) {
552                     setVerdict(true);
553                     return;
554                 }
555             }
556             setVerdict(false);
557             return;
558         }
559
560         if (trees1 != null && trees2 == null) {
561             for (int i = 0; i < trees1.size(); i++) {
562                 TypedNode tree1 = (TypedNode) trees1.get(i);
563                 processComparison(exp1, exp2, tree1, null, value1, value2, operator);
564                 if (verdict == true) {
565                     setVerdict(true);
566                     return;
567                 }
568             }
569             setVerdict(false);
570             return;
571         }
572
573         for (int i = 0; i < trees1.size(); i++) {
574             TypedNode tree1 = (TypedNode) trees1.get(i);
575             for (int j = 0; j < trees2.size(); j++) {
576                 TypedNode tree2 = (TypedNode) trees2.get(j);
577                 processComparison(exp1, exp2, tree1, tree2, value1, value2, operator);
578                 if (verdict == true) {
579                     setVerdict(true);
580                     return;
581                 }
582             }
583             setVerdict(false);
584         }
585     }
586
587     // public void visit(ListOpEXCEPTExpression arg) throws XQueryException
588
// public void visit(ListOpINTERSECTExpression arg) throws XQueryException
589

590     public void visit(ListOpUNIONExpression arg) throws XQueryException {
591         XQueryExpression exp1 = arg.getExpression1();
592         XQueryExpression exp2 = arg.getExpression2();
593
594         returnType.push(NODE_TYPE);
595         resnodes = null;
596         exp1.accept(this);
597         ArrayList trees = resnodes;
598         resnodes = null;
599         exp2.accept(this);
600         returnType.pop();
601         if (resnodes != null) {
602             if (trees == null)
603                 trees = resnodes;
604             else
605                 trees.addAll(resnodes);
606         }
607         setResnodes(trees);
608     }
609
610     public void visit(LocatedExpression arg) throws XQueryException {
611         clear();
612         if (!(arg.getStepNum(0).getExpression() instanceof Variable)) {
613             returnType.push(NODE_TYPE);
614             arg.getStepNum(0).getExpression().accept(this);
615             returnType.pop();
616             ArrayList tmplist = resnodes;
617             for (int j = 1; j < arg.getSteps().size(); j++) {
618                 tmplist = DOMUtils.getStep(tmplist, arg.getStepNum(j));
619                 if (tmplist == null || tmplist.isEmpty())
620                     break;
621             }
622             if (tmplist != null)
623                 setResnodes(tmplist);
624             return;
625         }
626         if (this.tuple == null && this.tuplelist == null) {
627             return;
628         }
629         if (tuple != null) {
630             if ((resnodes = tuple.getPath(arg.getStringValue())) != null) {
631                 setResnodes(resnodes);
632                 return;
633             }
634         } else {
635             for (int i = 0; i < tuplelist.size(); i++) {
636                 if ((resnodes = ((Tuple) tuplelist.get(i)).getPath(arg.getStringValue())) != null) {
637                     setResnodes(resnodes);
638                     return;
639                 }
640             }
641         }
642         resnodes = null;
643         ArrayList steps = arg.getSteps();
644         ArrayList tmplist = null;
645         if (tuple != null) {
646             StringBuffer JavaDoc buf = new StringBuffer JavaDoc(arg.toString(false,false,true));
647             int i;
648             for (i = steps.size() - 1; i > 0; i--) {
649                 buf.delete(buf.length() - ((Step) steps.get(i)).getStringValue().length(), buf.length());
650                 tmplist = tuple.getPath(buf.toString());
651                 if (tmplist != null)
652                     break;
653             }
654             if (tmplist == null)
655                 return;
656             for (int j = i; j < steps.size(); j++) {
657                 tmplist = DOMUtils.getStep(tmplist, arg.getStepNum(j));
658                 if (tmplist == null || tmplist.isEmpty())
659                     break;
660             }
661         } else { // tuplelist not null
662
for (int k = 0; k < tuplelist.size(); k++) {
663                 StringBuffer JavaDoc buf = new StringBuffer JavaDoc(arg.getStringValue());
664                 Tuple tuplek = (Tuple) tuplelist.get(k);
665                 int i;
666                 for (i = steps.size() - 1; i > 0; i--) {
667                     buf.delete(buf.length() - ((Step) steps.get(i)).getStringValue().length(), buf.length());
668                     tmplist = tuplek.getPath(buf.toString());
669                     if (tmplist != null)
670                         break;
671                 }
672                 if (tmplist == null)
673                     continue;
674                 for (int j = i; j < steps.size(); j++) {
675                     tmplist = DOMUtils.getStep(tmplist, arg.getStepNum(j));
676                     if (tmplist == null || tmplist.isEmpty())
677                         break;
678                 }
679                 break;
680             }
681         }
682         if (tmplist != null)
683             setResnodes(tmplist);
684     }
685     // public void visit(NodeType arg) throws XQueryException
686
// public void visit(Parameter arg) throws XQueryException
687
// public void visit(PrimitiveFunctionCall arg) throws XQueryException
688
// public void visit(QName arg) throws XQueryException
689
// public void visit(QuantifiedExpression arg) throws XQueryException
690
// public void visit(RangeExpression arg) throws XQueryException
691
// public void visit(RootNodeFunctionCall arg) throws XQueryException
692
// public void visit(SortedExpression arg) throws XQueryException
693
// public void visit(Step arg) throws XQueryException
694
// public void visit(TypeSwitchExpression arg) throws XQueryException
695

696     private Comparable JavaDoc getMinus(Comparable JavaDoc obj) throws XQueryException {
697         Comparable JavaDoc retObj = null;
698         if (obj instanceof Number JavaDoc) {
699             //BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short
700
if (obj instanceof Double JavaDoc) {
701                 retObj = new Double JavaDoc(- ((Double JavaDoc) obj).doubleValue());
702             } else if (obj instanceof Float JavaDoc) {
703                 retObj = new Float JavaDoc(- ((Float JavaDoc) obj).floatValue());
704             } else if (obj instanceof BigDecimal JavaDoc) {
705                 retObj = new BigDecimal JavaDoc(((BigDecimal JavaDoc) obj).unscaledValue().negate(), ((BigDecimal JavaDoc) obj).scale());
706             } else if (obj instanceof Integer JavaDoc) {
707                 retObj = new Integer JavaDoc(- ((Integer JavaDoc) obj).intValue());
708             } else if (obj instanceof Long JavaDoc) {
709                 retObj = new Long JavaDoc(- ((Long JavaDoc) obj).longValue());
710             }
711         } else if (obj instanceof String JavaDoc) {
712             try {
713                 retObj = new Double JavaDoc(-Double.parseDouble((String JavaDoc) obj));
714             } catch (NumberFormatException JavaDoc e) {
715                 // do nothing
716
}
717         }
718         return retObj;
719     }
720
721     public void visit(UnOpMinusExpression arg) throws XQueryException {
722         returnType.push(UNKNOWN_TYPE);
723         arg.getExpression().accept(this);
724         returnType.pop();
725         Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
726         if (resvalue != null) {
727             if (!arg.getMinus()) {
728                 if (rettype == NODE_TYPE) {
729                     ArrayList nodes = new ArrayList(1);
730                     TypedValue text = null;
731                     if (resvalue instanceof Long JavaDoc)
732                         text = docimpl.createTypedValue(resvalue, this.schemamanager.getIntegerType());
733                     else if (resvalue instanceof BigDecimal JavaDoc)
734                         text = docimpl.createTypedValue(resvalue, this.schemamanager.getDecimalType());
735                     else if (resvalue instanceof Double JavaDoc)
736                         text = docimpl.createTypedValue(resvalue, this.schemamanager.getDoubleType());
737                     else
738                         throw new XQueryException("UnOpMinusExpression could not cast resvalue");
739                     nodes.add(text);
740                     setResnodes(nodes);
741                     return;
742                 } else { //(rettype == VALUE_TYPE) {
743
setValue(resvalue);
744                     return;
745                 }
746             }
747             Comparable JavaDoc comp = getMinus(resvalue);
748             if (comp != null) {
749                 if (rettype == NODE_TYPE) {
750                     ArrayList nodes = new ArrayList(1);
751                     TypedValue text = null;
752                     if (comp instanceof Long JavaDoc)
753                         text = docimpl.createTypedValue(comp, this.schemamanager.getIntegerType());
754                     else if (resvalue instanceof BigDecimal JavaDoc)
755                         text = docimpl.createTypedValue(comp, this.schemamanager.getDecimalType());
756                     else if (comp instanceof Double JavaDoc)
757                         text = docimpl.createTypedValue(comp, this.schemamanager.getDoubleType());
758                     else
759                         throw new XQueryException("UnOpMinusExpression could not cast comp");
760                     nodes.add(text);
761                     setResnodes(nodes);
762                     return;
763                 } else { //(rettype == VALUE_TYPE) {
764
setValue(comp);
765                     return;
766                 }
767             } else
768                 throw new XQueryException("UnOpMinusExpression could not cast operator to Number");
769         } else if (resnodes != null) {
770             if (rettype == VALUE_TYPE && resnodes.size() != 1) {
771                 throw new XQueryException("UnOpMinusExpression could not get value from node list");
772             }
773             if (!arg.getMinus()) {
774                 if (rettype == NODE_TYPE) {
775                     ArrayList tmplist = new ArrayList(resnodes.size());
776                     for (int i = 0; i < resnodes.size(); i++) {
777                         TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
778                         if (tmpnode == null)
779                             tmpnode = (TypedNode) resnodes.get(0);
780                         tmplist.add(docimpl.createTypedValue((Comparable JavaDoc) tmpnode.getTypedValue(), (SimpleType) tmpnode.getType()));
781                     }
782                     setResnodes(tmplist);
783                     return;
784                 } else { // (rettype == VALUE_TYPE) {
785
TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
786                     if (tmpnode == null)
787                         tmpnode = (TypedNode) resnodes.get(0);
788                     setValue((Comparable JavaDoc) tmpnode.getTypedValue());
789                     return;
790                 }
791             }
792             ArrayList tmplist = new ArrayList(resnodes.size());
793             for (int i = 0; i < resnodes.size(); i++) {
794                 TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
795                 if (tmpnode == null)
796                     tmpnode = (TypedNode) resnodes.get(0);
797                 Comparable JavaDoc comp = getMinus((Comparable JavaDoc) tmpnode.getTypedValue());
798                 if (comp != null) {
799                     TypedValue text = docimpl.createTypedValue(comp, (SimpleType) tmpnode.getType());
800                     tmplist.add(text);
801                 }
802             }
803             if (rettype == NODE_TYPE) {
804                 setResnodes(tmplist);
805                 return;
806             } else { // (rettype == VALUE_TYPE) {
807
if (tmplist.size() == 1) {
808                     setValue((Comparable JavaDoc) ((TypedValue) tmplist.get(0)).getTypedValue());
809                     return;
810                 }
811             }
812         }
813         clear();
814     }
815
816     public void visit(Value arg) throws XQueryException {
817         clear();
818     }
819     // public void visit(ValueBoolean arg) throws XQueryException {
820
public void visit(ValueDecimal arg) throws XQueryException {
821         Integer JavaDoc rettype = returnType.isEmpty() ? UNKNOWN_TYPE : (Integer JavaDoc) returnType.peek();
822         if (rettype == NODE_TYPE) {
823             ArrayList nodes = new ArrayList(1);
824             TypedValue text = docimpl.createTypedValue(arg.getDecimalValue(), this.schemamanager.getDecimalType());
825             nodes.add(text);
826             setResnodes(nodes);
827             return;
828         } else { // rettype == VALUE_TYPE
829
setValue(arg.getDecimalValue());
830             return;
831         }
832     }
833     public void visit(ValueDouble arg) throws XQueryException {
834         Integer JavaDoc rettype = returnType.isEmpty() ? UNKNOWN_TYPE : (Integer JavaDoc) returnType.peek();
835         if (rettype == NODE_TYPE) {
836             ArrayList nodes = new ArrayList(1);
837             TypedValue text = docimpl.createTypedValue(arg.getDoubleValue(), this.schemamanager.getDoubleType());
838             nodes.add(text);
839             setResnodes(nodes);
840             return;
841         } else { // rettype == VALUE_TYPE
842
setValue(arg.getDoubleValue());
843             return;
844         }
845     }
846     public void visit(ValueFloat arg) throws XQueryException {
847         Integer JavaDoc rettype = returnType.isEmpty() ? UNKNOWN_TYPE : (Integer JavaDoc) returnType.peek();
848         if (rettype == NODE_TYPE) {
849             ArrayList nodes = new ArrayList(1);
850             TypedValue text = docimpl.createTypedValue(arg.getFloatValue(), this.schemamanager.getFloatType());
851             nodes.add(text);
852             setResnodes(nodes);
853             return;
854         } else { // rettype == VALUE_TYPE
855
setValue(arg.getFloatValue());
856             return;
857         }
858     }
859     public void visit(ValueInteger arg) throws XQueryException {
860         Integer JavaDoc rettype = returnType.isEmpty() ? UNKNOWN_TYPE : (Integer JavaDoc) returnType.peek();
861         if (rettype == NODE_TYPE) {
862             ArrayList nodes = new ArrayList(1);
863             TypedValue text = docimpl.createTypedValue(new Long JavaDoc(arg.getIntValue().longValue()), this.schemamanager.getIntegerType());
864             nodes.add(text);
865             setResnodes(nodes);
866             return;
867         } else { // rettype == VALUE_TYPE
868
setValue(new Long JavaDoc(arg.getIntValue().longValue()));
869             return;
870         }
871     }
872     public void visit(ValueString arg) throws XQueryException {
873         Integer JavaDoc rettype = returnType.isEmpty() ? UNKNOWN_TYPE : (Integer JavaDoc) returnType.peek();
874         if (rettype == NODE_TYPE) {
875             ArrayList nodes = new ArrayList(1);
876             TypedValue text = docimpl.createTypedValue(arg.getStringValue(), this.schemamanager.getStringType());
877             nodes.add(text);
878             setResnodes(nodes);
879             return;
880         } else { // rettype == VALUE_TYPE
881
setValue(arg.getStringValue());
882             return;
883         }
884     }
885     public void visit(ValueText arg) throws XQueryException {
886         Integer JavaDoc rettype = returnType.isEmpty() ? UNKNOWN_TYPE : (Integer JavaDoc) returnType.peek();
887         if (rettype == NODE_TYPE) {
888             ArrayList nodes = new ArrayList(1);
889             TypedValue text = docimpl.createTypedValue(arg.getTextValue(), this.schemamanager.getStringType());
890             nodes.add(text);
891             setResnodes(nodes);
892             return;
893         } else { // rettype == VALUE_TYPE
894
setValue(arg.getTextValue());
895             return;
896         }
897     }
898     public void visit(Variable arg) throws XQueryException {
899         if (this.tuple != null) {
900             setResnodes(tuple.getPath(arg.getStringValue()));
901             return;
902         } else if (tuplelist != null) {
903             for (int i = 0; i < tuplelist.size(); i++) {
904                 if ((resnodes = ((Tuple) tuplelist.get(i)).getPath(arg.getStringValue())) != null) {
905                     this.setResnodes(resnodes);
906                     return;
907                 }
908             }
909         }
910         this.clear();
911     }
912     // public void visit (XQueryBinaryOperatorExpression arg) throws XQueryException
913
// public void visit(XQueryBooleanOperatorExpression arg) throws XQueryException
914
public void visit(XQueryExpression arg) throws XQueryException {
915         throw new XQueryException("Class " + arg.getClass().getName() + " not supported in EvaluationVisitor");
916     }
917     public void visit(XQueryExpressionSequence arg) throws XQueryException {
918         if (arg.getSubExpressions().size() == 1)
919              ((XQueryExpression) arg.getSubExpressions().get(0)).accept(this);
920         else {
921             ArrayList expressions = arg.getSubExpressions();
922             ArrayList tmpnodes = new ArrayList();
923             returnType.push(NODE_TYPE);
924             for (int i = 0; i < expressions.size(); i++) {
925                 XQueryExpression expri = (XQueryExpression) expressions.get(i);
926                 expri.accept(this);
927                 if (resnodes != null)
928                     tmpnodes.addAll(resnodes);
929             }
930             setResnodes(tmpnodes);
931             returnType.pop();
932             //throw new XQueryException("Class " + arg.getClass().getName() + " with more than one expression not supported in EvaluationVisitor");
933
}
934     }
935     // public void visit(XQueryListBinaryOperatorExpression arg) throws XQueryException
936
// public void visit(XQueryListUnaryOperatorExpression arg) throws XQueryException
937
// public void visit (XQueryUnaryOperatorExpression arg) throws XQueryException
938

939     //-----------------------------------------------------------
940
// BOOLEAN FUNCTIONS
941
//-----------------------------------------------------------
942
public void visit(FunctionFALSE arg) throws XQueryException {
943         setVerdict(false);
944     }
945
946     public void visit(FunctionTRUE arg) throws XQueryException {
947         setVerdict(true);
948     }
949
950     //-----------------------------------------------------------
951
// AGGREGATE FUNCTIONS
952
//-----------------------------------------------------------
953

954     public void visit(FunctionAVG arg) throws XQueryException {
955         boolean isLongSum = false;
956         double doubleSum = 0;
957         long longSum = 0;
958         int count = 0;
959         // treat special case first
960
if (buffertuple != null) {
961             int index = buffertuple.getPathIndex(arg.getArgument(0).getStringValue());
962             if (index == -1)
963                 index = 0;
964             for (int i = 0; i < buffertuple.size(); i++) {
965                 Tuple tuplei = (Tuple) buffertuple.get(i);
966                 // if (tuplei.size() != 1)
967
// return;
968
Number JavaDoc valuei = null;
969                 TypedNode treei = (TypedNode) tuplei.getNodesAtIndex(index).get(0);
970                 try {
971                     if (treei.getTypedValue() != null)
972                         valuei = (Number JavaDoc) treei.getTypedValue();
973                     else
974                         valuei = (Number JavaDoc) DOMUtils.getTextLeaf(treei);
975                 } catch (ClassCastException JavaDoc cce) {
976                     // do nothing
977
}
978                 if (valuei == null)
979                     return;
980                 if (isLongSum && (valuei instanceof Integer JavaDoc || valuei instanceof Long JavaDoc)) {
981                     longSum += valuei.longValue();
982                 } else {
983                     if (isLongSum) {
984                         doubleSum = longSum;
985                         isLongSum = false;
986                     }
987                     doubleSum += valuei.doubleValue();
988                 }
989             }
990             count = buffertuple.size();
991         } else {
992             returnType.push(NODE_TYPE);
993             arg.getArgument(0).accept(this);
994             returnType.pop();
995             if (resnodes == null || resnodes.isEmpty())
996                 return;
997
998             for (int i = 0; i < resnodes.size(); i++) {
999                 Number JavaDoc valuei = null;
1000                TypedNode treei = (TypedNode) resnodes.get(i);
1001                try {
1002                    if (treei.getTypedValue() != null)
1003                        valuei = (Number JavaDoc) treei.getTypedValue();
1004                    else
1005                        valuei = (Number JavaDoc) DOMUtils.getTextLeaf(treei);
1006                } catch (ClassCastException JavaDoc cce) {
1007                    // do nothing
1008
}
1009                if (valuei == null)
1010                    return;
1011                if (isLongSum && (valuei instanceof Integer JavaDoc || valuei instanceof Long JavaDoc)) {
1012                    longSum += valuei.longValue();
1013                } else {
1014                    if (isLongSum) {
1015                        doubleSum = longSum;
1016                        isLongSum = false;
1017                    }
1018                    doubleSum += valuei.doubleValue();
1019                }
1020            }
1021            count = resnodes.size();
1022        }
1023        Integer JavaDoc retType = (Integer JavaDoc) this.returnType.peek();
1024        if (retType == TUPLE_TYPE) {
1025            Tuple tuple = new Tuple(1);
1026            TypedValue text = null;
1027            if (isLongSum)
1028                text = docimpl.createTypedValue(new BigDecimal JavaDoc(longSum / count), this.schemamanager.getDecimalType());
1029            else
1030                text = docimpl.createTypedValue(new Double JavaDoc(doubleSum / count), this.schemamanager.getDoubleType());
1031            tuple.addNodeAtIndex(0, text);
1032            this.setResultTuple(tuple);
1033            return;
1034        } else if (retType == NODE_TYPE) {
1035            ArrayList nodes = new ArrayList(1);
1036            TypedValue text = null;
1037            if (isLongSum)
1038                text = docimpl.createTypedValue(new BigDecimal JavaDoc(longSum / count), this.schemamanager.getDecimalType());
1039            else
1040                text = docimpl.createTypedValue(new Double JavaDoc(doubleSum / count), this.schemamanager.getDoubleType());
1041            nodes.add(text);
1042            setResnodes(nodes);
1043            return;
1044        } else /*if (retType == VALUE_TYPE)*/ {
1045            if (isLongSum)
1046                setValue(new BigDecimal JavaDoc(longSum / count));
1047            else
1048                setValue(new Double JavaDoc(doubleSum / count));
1049            return;
1050        }
1051        // clear();
1052

1053    }
1054
1055    public void visit(FunctionSUM arg) throws XQueryException {
1056        boolean isLongSum = false;
1057        double doubleSum = 0;
1058        long longSum = 0;
1059        // treat special case first
1060
if (buffertuple != null) {
1061            int index = buffertuple.getPathIndex(arg.getArgument(0).getStringValue());
1062            if (index == -1)
1063                index = 0;
1064            for (int i = 0; i < buffertuple.size(); i++) {
1065                Tuple tuplei = (Tuple) buffertuple.get(i);
1066                // if (tuplei.size() != 1)
1067
// return;
1068
Number JavaDoc valuei = null;
1069                TypedNode treei = (TypedNode) tuplei.getNodesAtIndex(index).get(0);
1070                try {
1071                    if (treei.getTypedValue() != null)
1072                        valuei = (Number JavaDoc) treei.getTypedValue();
1073                    else
1074                        valuei = (Number JavaDoc) DOMUtils.getTextLeaf(treei);
1075                } catch (ClassCastException JavaDoc cce) {
1076                    // do nothing
1077
}
1078                if (valuei == null)
1079                    return;
1080                if (isLongSum && (valuei instanceof Integer JavaDoc || valuei instanceof Long JavaDoc)) {
1081                    longSum += valuei.longValue();
1082                } else {
1083                    if (isLongSum) {
1084                        doubleSum = longSum;
1085                        isLongSum = false;
1086                    }
1087                    doubleSum += valuei.doubleValue();
1088                }
1089            }
1090        } else {
1091            returnType.push(NODE_TYPE);
1092            arg.getArgument(0).accept(this);
1093            returnType.pop();
1094            if (resnodes == null || resnodes.isEmpty())
1095                return;
1096
1097            for (int i = 0; i < resnodes.size(); i++) {
1098                Number JavaDoc valuei = null;
1099                TypedNode treei = (TypedNode) resnodes.get(i);
1100                try {
1101                    if (treei.getTypedValue() != null)
1102                        valuei = (Number JavaDoc) treei.getTypedValue();
1103                    else
1104                        valuei = (Number JavaDoc) DOMUtils.getTextLeaf(treei);
1105                } catch (ClassCastException JavaDoc cce) {
1106                    // do nothing
1107
}
1108                if (valuei == null)
1109                    return;
1110                if (isLongSum && (valuei instanceof Integer JavaDoc || valuei instanceof Long JavaDoc)) {
1111                    longSum += valuei.longValue();
1112                } else {
1113                    if (isLongSum) {
1114                        doubleSum = longSum;
1115                        isLongSum = false;
1116                    }
1117                    doubleSum += valuei.doubleValue();
1118                }
1119            }
1120        }
1121        Integer JavaDoc retType = (Integer JavaDoc) this.returnType.peek();
1122        if (retType == TUPLE_TYPE) {
1123            Tuple tuple = new Tuple(1);
1124            TypedValue text = null;
1125            if (isLongSum)
1126                text = docimpl.createTypedValue(new Long JavaDoc(longSum), this.schemamanager.getIntegerType());
1127            else
1128                text = docimpl.createTypedValue(new Double JavaDoc(doubleSum), this.schemamanager.getDoubleType());
1129            tuple.addNodeAtIndex(0, text);
1130            setResultTuple(tuple);
1131            return;
1132        } else if (retType == NODE_TYPE) {
1133            ArrayList nodes = new ArrayList(1);
1134            TypedValue text = null;
1135            if (isLongSum)
1136                text = docimpl.createTypedValue(new Long JavaDoc(longSum), this.schemamanager.getIntegerType());
1137            else
1138                text = docimpl.createTypedValue(new Double JavaDoc(doubleSum), this.schemamanager.getDoubleType());
1139            nodes.add(text);
1140            setResnodes(nodes);
1141            return;
1142        } else /*if (retType == VALUE_TYPE)*/ {
1143            if (isLongSum)
1144                setValue(new Long JavaDoc(longSum));
1145            else
1146                setValue(new Double JavaDoc(doubleSum));
1147            return;
1148        }
1149        // clear();
1150

1151    }
1152
1153    public void visit(FunctionMAX arg) throws XQueryException {
1154        Comparable JavaDoc max = null;
1155        TypedNode result = null;
1156        // treat special case first
1157
if (buffertuple != null) {
1158            int index = buffertuple.getPathIndex(arg.getArgument(0).getStringValue());
1159            if (index == -1)
1160                index = 0;
1161            for (int i = 0; i < buffertuple.size(); i++) {
1162                Tuple tuplei = (Tuple) buffertuple.get(i);
1163                // if (tuplei.size() != 1)
1164
// return;
1165
Comparable JavaDoc valuei = null;
1166                TypedNode treei = (TypedNode) tuplei.getNodesAtIndex(index).get(0);
1167                try {
1168                    if (treei.getTypedValue() != null)
1169                        valuei = (Comparable JavaDoc) treei.getTypedValue();
1170                    else
1171                        valuei = (Comparable JavaDoc) DOMUtils.getTextLeaf(treei);
1172                } catch (ClassCastException JavaDoc cce) {
1173                    // do nothing
1174
}
1175                if (valuei == null)
1176                    return;
1177                if (max == null) {
1178                    max = valuei;
1179                    result = treei;
1180                } else if (DOMUtils.compareObjects(valuei,max) > 0) {
1181                    max = valuei;
1182                    result = treei;
1183                }
1184            }
1185        } else {
1186            returnType.push(NODE_TYPE);
1187            arg.getArgument(0).accept(this);
1188            returnType.pop();
1189            if (resnodes == null || resnodes.isEmpty())
1190                return;
1191
1192            for (int i = 0; i < resnodes.size(); i++) {
1193                Comparable JavaDoc valuei = null;
1194                TypedNode treei = (TypedNode) resnodes.get(i);
1195                try {
1196                    if (treei.getTypedValue() != null)
1197                        valuei = (Comparable JavaDoc) treei.getTypedValue();
1198                    else
1199                        valuei = (Comparable JavaDoc) DOMUtils.getTextLeaf(treei);
1200                } catch (ClassCastException JavaDoc cce) {
1201                    // do nothing
1202
}
1203                if (valuei == null)
1204                    return;
1205                if (max == null) {
1206                    max = valuei;
1207                    result = treei;
1208                } else if (DOMUtils.compareObjects(valuei,max) > 0) {
1209                    max = valuei;
1210                    result = treei;
1211                }
1212            }
1213        }
1214
1215        Integer JavaDoc retType = (Integer JavaDoc) this.returnType.peek();
1216        if (retType == TUPLE_TYPE) {
1217            Tuple tuple = new Tuple(1);
1218            TypedValue text = docimpl.createTypedValue(max, (SimpleType) result.getType());
1219            tuple.addNodeAtIndex(0, text);
1220            setResultTuple(tuple);
1221            return;
1222        } else if (retType == NODE_TYPE) {
1223            ArrayList nodes = new ArrayList(1);
1224            TypedValue text = docimpl.createTypedValue(max, (SimpleType) result.getType());
1225            nodes.add(text);
1226            setResnodes(nodes);
1227            return;
1228        } else /*if (retType == VALUE_TYPE)*/ {
1229            setValue(max);
1230            return;
1231        }
1232        // clear();
1233

1234    }
1235
1236    public void visit(FunctionMIN arg) throws XQueryException {
1237        Comparable JavaDoc min = null;
1238        TypedNode result = null;
1239        // treat special case first
1240
if (buffertuple != null) {
1241            int index = buffertuple.getPathIndex(arg.getArgument(0).getStringValue());
1242            if (index == -1)
1243                index = 0;
1244            for (int i = 0; i < buffertuple.size(); i++) {
1245                Tuple tuplei = (Tuple) buffertuple.get(i);
1246                // if (tuplei.size() != 1)
1247
// return;
1248
Comparable JavaDoc valuei = null;
1249                TypedNode treei = (TypedNode) tuplei.getNodesAtIndex(index).get(0);
1250                try {
1251                    if (treei.getTypedValue() != null)
1252                        valuei = (Comparable JavaDoc) treei.getTypedValue();
1253                    else
1254                        valuei = (Comparable JavaDoc) DOMUtils.getTextLeaf(treei);
1255                } catch (ClassCastException JavaDoc cce) {
1256                    // do nothing
1257
}
1258                if (valuei == null)
1259                    return;
1260                if (min == null) {
1261                    min = valuei;
1262                    result = treei;
1263                } else if (DOMUtils.compareObjects(valuei,min) < 0) {
1264                    min = valuei;
1265                    result = treei;
1266                }
1267            }
1268        } else {
1269            returnType.push(NODE_TYPE);
1270            arg.getArgument(0).accept(this);
1271            returnType.pop();
1272            if (resnodes == null || resnodes.isEmpty())
1273                return;
1274
1275            for (int i = 0; i < resnodes.size(); i++) {
1276                Comparable JavaDoc valuei = null;
1277                TypedNode treei = (TypedNode) resnodes.get(i);
1278                try {
1279                    if (treei.getTypedValue() != null)
1280                        valuei = (Comparable JavaDoc) treei.getTypedValue();
1281                    else
1282                        valuei = (Comparable JavaDoc) DOMUtils.getTextLeaf(treei);
1283                } catch (ClassCastException JavaDoc cce) {
1284                    // do nothing
1285
}
1286                if (valuei == null)
1287                    return;
1288                if (min == null) {
1289                    min = valuei;
1290                    result = treei;
1291                } else if (DOMUtils.compareObjects(valuei,min) < 0) {
1292                    min = valuei;
1293                    result = treei;
1294                }
1295            }
1296        }
1297
1298        Integer JavaDoc retType = (Integer JavaDoc) this.returnType.peek();
1299        if (retType == TUPLE_TYPE) {
1300            Tuple tuple = new Tuple(1);
1301            TypedValue text = docimpl.createTypedValue(min, (SimpleType) result.getType());
1302            tuple.addNodeAtIndex(0, text);
1303            setResultTuple(tuple);
1304            return;
1305        } else if (retType == NODE_TYPE) {
1306            ArrayList nodes = new ArrayList(1);
1307            TypedValue text = docimpl.createTypedValue(min, (SimpleType) result.getType());
1308            nodes.add(text);
1309            setResnodes(nodes);
1310            return;
1311        } else /*if (retType == VALUE_TYPE)*/ {
1312            setValue(min);
1313            return;
1314        }
1315        // clear();
1316

1317    }
1318
1319    public void visit(FunctionCOUNT arg) throws XQueryException {
1320        long strvalue = 0;
1321        // treat special case first
1322
if (buffertuple != null) {
1323            strvalue = buffertuple.size();
1324        } else {
1325            returnType.push(NODE_TYPE);
1326            arg.getArgument(0).accept(this);
1327            returnType.pop();
1328            if (resnodes != null)
1329                strvalue = resnodes.size();
1330        }
1331
1332        Integer JavaDoc retType = (Integer JavaDoc) this.returnType.peek();
1333        if (retType == TUPLE_TYPE) {
1334            Tuple tuple = new Tuple(1);
1335            TypedValue text = docimpl.createTypedValue(new Long JavaDoc(strvalue), this.schemamanager.getIntegerType());
1336            tuple.addNodeAtIndex(0, text);
1337            setResultTuple(tuple);
1338            return;
1339        } else if (retType == NODE_TYPE) {
1340            ArrayList nodes = new ArrayList(1);
1341            TypedValue text = docimpl.createTypedValue(new Long JavaDoc(strvalue), this.schemamanager.getIntegerType());
1342            nodes.add(text);
1343            setResnodes(nodes);
1344            return;
1345        } else /*if (retType == VALUE_TYPE)*/ {
1346            setValue(new Long JavaDoc(strvalue));
1347            return;
1348        }
1349        //clear();
1350
}
1351
1352    //-----------------------------------------------------------
1353
// DATE/TIME FUNCTIONS
1354
//-----------------------------------------------------------
1355
// private int[] parseDate(String date) {
1356
// if (date == null)
1357
// return null;
1358
// int[] retval = new int[3];
1359
// retval[0] = Integer.parseInt(date.substring(0, 4));
1360
// retval[1] = Integer.parseInt(date.substring(5, 7));
1361
// retval[2] = Integer.parseInt(date.substring(8, 10));
1362
// return retval;
1363
// }
1364
Calendar cal = Calendar.getInstance();
1365
1366    public void visit(FunctionCURRENT_DATETIME arg) throws XQueryException {
1367        resvalue = Calendar.getInstance().getTime();
1368        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1369        if (rettype == NODE_TYPE) {
1370            ArrayList nodes = new ArrayList(1);
1371            nodes.add(docimpl.createTypedValue(resvalue, this.schemamanager.getDateTimeType()));
1372            setResnodes(nodes);
1373            return;
1374        } else { //if (rettype == VALUE_TYPE) {
1375
setValue(resvalue);
1376            return;
1377        }
1378        // clear();
1379
}
1380
1381    public void visit(FunctionDATE arg) throws XQueryException {
1382        returnType.push(VALUE_TYPE);
1383        arg.getArgument(0).accept(this);
1384        returnType.pop();
1385        if (resvalue instanceof Date) { // do nothing
1386
cal.setTime((Date) resvalue);
1387            cal.set(Calendar.HOUR, 0);
1388            cal.set(Calendar.MINUTE, 0);
1389            cal.set(Calendar.SECOND, 0);
1390            resvalue = cal.getTime();
1391        } else if (resvalue instanceof String JavaDoc) {
1392            try {
1393                resvalue = (Comparable JavaDoc) this.schemamanager.getDateType().convert((String JavaDoc) resvalue, true, null);
1394            } catch (SchemaException se) {
1395                throw new XQueryException("Argument of function date is not a valid date");
1396            }
1397        } else
1398            throw new XQueryException("Argument of function date cannot be converted");
1399        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1400        if (rettype == NODE_TYPE) {
1401            ArrayList nodes = new ArrayList(1);
1402            nodes.add(docimpl.createTypedValue(resvalue, this.schemamanager.getDateType()));
1403            setResnodes(nodes);
1404            return;
1405        } else { //if (rettype == VALUE_TYPE) {
1406
setValue(resvalue);
1407            return;
1408        }
1409        //clear();
1410
}
1411
1412    public void visit(FunctionDATETIME arg) throws XQueryException {
1413        returnType.push(VALUE_TYPE);
1414        arg.getArgument(0).accept(this);
1415        returnType.pop();
1416        if (resvalue instanceof Date) { // do nothing
1417
} else if (resvalue instanceof String JavaDoc) {
1418            try {
1419                resvalue = (Comparable JavaDoc) this.schemamanager.getDateTimeType().convert((String JavaDoc) resvalue, true, null);
1420            } catch (SchemaException se) {
1421                throw new XQueryException("Argument of function datetime is not a valid date");
1422            }
1423        } else
1424            throw new XQueryException("Argument of function datetime cannot be converted");
1425        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1426        if (rettype == NODE_TYPE) {
1427            ArrayList nodes = new ArrayList(1);
1428            nodes.add(docimpl.createTypedValue(resvalue, this.schemamanager.getDateTimeType()));
1429            setResnodes(nodes);
1430            return;
1431        } else { //if (rettype == VALUE_TYPE) {
1432
setValue(resvalue);
1433            return;
1434        }
1435        //clear();
1436
}
1437
1438    public void visit(FunctionTIME arg) throws XQueryException {
1439        returnType.push(VALUE_TYPE);
1440        arg.getArgument(0).accept(this);
1441        returnType.pop();
1442        if (resvalue instanceof Date) { // do nothing
1443
} else if (resvalue instanceof String JavaDoc) {
1444            try {
1445                resvalue = (Comparable JavaDoc) this.schemamanager.getTimeType().convert((String JavaDoc) resvalue, true, null);
1446            } catch (SchemaException se) {
1447                throw new XQueryException("Argument of function time is not a valid date");
1448            }
1449        } else
1450            throw new XQueryException("Argument of function time cannot be converted");
1451        /*
1452        StringBuffer buf = new StringBuffer();
1453        buf.append(cal.get(Calendar.HOUR));
1454        buf.append(":");
1455        buf.append(cal.get(Calendar.MINUTE));
1456        buf.append(":");
1457        buf.append(cal.get(Calendar.SECOND));
1458        */

1459        cal.setTime((Date) resvalue);
1460        cal.set(Calendar.YEAR, 0);
1461        cal.set(Calendar.MONTH, 0);
1462        cal.set(Calendar.DAY_OF_MONTH, 0);
1463        resvalue = cal.getTime();
1464        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1465        if (rettype == NODE_TYPE) {
1466            ArrayList nodes = new ArrayList(1);
1467            nodes.add(docimpl.createTypedValue(resvalue, this.schemamanager.getTimeType()));
1468            setResnodes(nodes);
1469            return;
1470        } else { //if (rettype == VALUE_TYPE) {
1471
setValue(resvalue);
1472            return;
1473        }
1474        //clear();
1475
}
1476
1477    public void visit(FunctionGET_YEAR_FROM_DATE arg) throws XQueryException {
1478        returnType.push(VALUE_TYPE);
1479        arg.getArgument(0).accept(this);
1480        returnType.pop();
1481        if (resvalue == null) {
1482            clear();
1483            return;
1484        }
1485        if (resvalue instanceof Date)
1486            throw new XQueryException("Argument of function get-year-from-date is not a date");
1487        cal.setTime((Date) resvalue);
1488        resvalue = new Long JavaDoc(cal.get(Calendar.YEAR));
1489        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1490        if (rettype == NODE_TYPE) {
1491            ArrayList nodes = new ArrayList(1);
1492            nodes.add(docimpl.createTypedValue(resvalue, this.getSimpleType(resvalue, schemamanager.getIntegerType())));
1493            setResnodes(nodes);
1494            return;
1495        } else { //if (rettype == VALUE_TYPE) {
1496
setValue(resvalue);
1497            return;
1498        }
1499        //clear();
1500
}
1501
1502    public void visit(FunctionGET_MONTH_FROM_DATE arg) throws XQueryException {
1503        returnType.push(VALUE_TYPE);
1504        arg.getArgument(0).accept(this);
1505        returnType.pop();
1506        if (resvalue == null) {
1507            clear();
1508            return;
1509        }
1510        if (resvalue instanceof Date)
1511            throw new XQueryException("Argument of function get-month-from-date is not a date");
1512        cal.setTime((Date) resvalue);
1513        resvalue = new Long JavaDoc(cal.get(Calendar.MONTH));
1514        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1515        if (rettype == NODE_TYPE) {
1516            ArrayList nodes = new ArrayList(1);
1517            nodes.add(docimpl.createTypedValue(resvalue, this.getSimpleType(resvalue, schemamanager.getIntegerType())));
1518            setResnodes(nodes);
1519            return;
1520        } else { //if (rettype == VALUE_TYPE) {
1521
setValue(resvalue);
1522            return;
1523        }
1524        //clear();
1525
}
1526
1527    //-----------------------------------------------------------
1528
// STRING FUNCTIONS
1529
//-----------------------------------------------------------
1530

1531    private Comparable JavaDoc c0 = null;
1532    private Comparable JavaDoc c1 = null;
1533
1534    private void getComparables(XQueryExpression arg0, XQueryExpression arg1) throws XQueryException {
1535        resulttuple = null;
1536        resnodes = null;
1537        c0 = null;
1538        c1 = null;
1539        if (arg0 instanceof Value)
1540            c0 = (((Value) arg0).getValue());
1541        if (arg1 instanceof Value)
1542            c1 = (((Value) arg1).getValue());
1543        if (c0 == null) {
1544            returnType.push(VALUE_TYPE);
1545            arg0.accept(this);
1546            returnType.pop();
1547            c0 = this.resvalue;
1548            if (c0 == null && resnodes != null && resnodes.size() == 1) {
1549                TypedNode node = (TypedNode) resnodes.get(0);
1550                if (node instanceof TypedValueImpl) {
1551                    c0 = (Comparable JavaDoc) node.getTypedValue();
1552                } else if (node instanceof TypedElementImpl) {
1553                    StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1554                    DOMUtils.getStringValue(node, sb);
1555                    c0 = sb.toString();
1556                }
1557            }
1558        }
1559        if (c1 == null) {
1560            returnType.push(VALUE_TYPE);
1561            arg1.accept(this);
1562            returnType.pop();
1563            c1 = this.resvalue;
1564            if (c1 == null && resnodes != null && resnodes.size() == 1) {
1565                TypedNode node = (TypedNode) resnodes.get(0);
1566                if (node instanceof TypedValueImpl) {
1567                    c1 = (Comparable JavaDoc) node.getTypedValue();
1568                } else if (node instanceof TypedElementImpl) {
1569                    StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1570                    DOMUtils.getStringValue(node, sb);
1571                    c1 = sb.toString();
1572                }
1573            }
1574        }
1575
1576    }
1577
1578    public void visit(FunctionLOWER_CASE arg) throws XQueryException {
1579        returnType.push(UNKNOWN_TYPE);
1580        arg.getArgument(0).accept(this);
1581        returnType.pop();
1582        if (resvalue != null) { // do nothing
1583
} else if (resnodes != null && resnodes.size() == 1) {
1584            TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
1585            if (tmpnode == null)
1586                tmpnode = (TypedNode) resnodes.get(0);
1587            resvalue = (Comparable JavaDoc) tmpnode.getTypedValue();
1588        }
1589        if (resvalue instanceof String JavaDoc) {
1590            resvalue = ((String JavaDoc) resvalue).toLowerCase();
1591        } else {
1592            throw new XQueryException("Argument of function lower-case is not a string");
1593        }
1594        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1595        if (rettype == VALUE_TYPE) {
1596            setValue(resvalue);
1597            return;
1598        } else if (rettype == NODE_TYPE) {
1599            ArrayList nodes = new ArrayList(1);
1600            nodes.add(docimpl.createTypedValue(resvalue, this.getSimpleType(resvalue, schemamanager.getStringType())));
1601            setResnodes(nodes);
1602            return;
1603        }
1604    }
1605
1606    public void visit(FunctionUPPER_CASE arg) throws XQueryException {
1607        returnType.push(UNKNOWN_TYPE);
1608        arg.getArgument(0).accept(this);
1609        returnType.pop();
1610        if (resvalue != null) { // do nothing
1611
} else if (resnodes != null && resnodes.size() == 1) {
1612            TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
1613            if (tmpnode == null)
1614                tmpnode = (TypedNode) resnodes.get(0);
1615            resvalue = (Comparable JavaDoc) tmpnode.getTypedValue();
1616        }
1617        if (resvalue instanceof String JavaDoc) {
1618            resvalue = ((String JavaDoc) resvalue).toUpperCase();
1619        } else {
1620            throw new XQueryException("Argument of function upper-case is not a string");
1621        }
1622        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1623        if (rettype == VALUE_TYPE) {
1624            setValue(resvalue);
1625            return;
1626        } else if (rettype == NODE_TYPE) {
1627            ArrayList nodes = new ArrayList(1);
1628            nodes.add(docimpl.createTypedValue(resvalue, this.getSimpleType(resvalue, schemamanager.getStringType())));
1629            setResnodes(nodes);
1630            return;
1631        }
1632    }
1633
1634    public void visit(FunctionCONCAT arg) throws XQueryException {
1635        StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
1636        for (int i = 0; i < arg.getArguments().size(); i++) {
1637            returnType.push(UNKNOWN_TYPE);
1638            arg.getArgument(i).accept(this);
1639            returnType.pop();
1640            if (resvalue != null) { // do nothing
1641
if (resvalue instanceof String JavaDoc)
1642                    buf.append(resvalue);
1643                else
1644                    buf.append(resvalue.toString());
1645            } else if (resnodes == null || resnodes.isEmpty()) { // do nothing
1646
} else if (resnodes != null && resnodes.size() == 1) {
1647                StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1648                DOMUtils.getStringValue((TypedNode) resnodes.get(0), sb);
1649                buf.append(sb.toString());
1650            } else if (resnodes != null && resnodes.size() > 1) {
1651                throw new XQueryException("Evaluation : incorrect argument for function concat");
1652            }
1653        }
1654        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1655        if (rettype == NODE_TYPE) {
1656            ArrayList nodes = new ArrayList(1);
1657            nodes.add(docimpl.createTypedValue(buf.toString(), this.schemamanager.getStringType()));
1658            setResnodes(nodes);
1659            return;
1660        } else { // if (rettype == VALUE_TYPE) {
1661
setValue(buf.toString());
1662            return;
1663        }
1664        // clear();
1665
}
1666
1667    public void visit(FunctionCONTAINS arg) throws XQueryException {
1668        getComparables(arg.getArgument(0), arg.getArgument(1));
1669        if (c0 != null && c1 != null) {
1670            setVerdict(((String JavaDoc) c0).indexOf((String JavaDoc) c1) != -1);
1671            return;
1672        }
1673        clear();
1674    }
1675
1676    public void visit(FunctionENDS_WITH arg) throws XQueryException {
1677        getComparables(arg.getArgument(0), arg.getArgument(1));
1678        if (c0 != null && c1 != null) {
1679            setVerdict(((String JavaDoc) c0).endsWith((String JavaDoc) c1));
1680            return;
1681        }
1682        clear();
1683    }
1684
1685    public void visit(FunctionSTARTS_WITH arg) throws XQueryException {
1686        getComparables(arg.getArgument(0), arg.getArgument(1));
1687        if (c0 != null && c1 != null) {
1688            setVerdict(((String JavaDoc) c0).startsWith((String JavaDoc) c1));
1689            return;
1690        }
1691        clear();
1692    }
1693
1694    public void visit(FunctionLOCAL_NAME arg) throws XQueryException {
1695        returnType.push(NODE_TYPE);
1696        arg.getArgument(0).accept(this);
1697        returnType.pop();
1698        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1699        //if (rettype == VALUE_TYPE) {
1700
if (this.resnodes != null && resnodes.size() == 1) {
1701            this.setValue(((TypedNode) resnodes.get(0)).getLocalName());
1702            return;
1703        }
1704        //}
1705
clear();
1706    }
1707
1708    public void visit(FunctionNAMESPACE_URI arg) throws XQueryException {
1709        returnType.push(NODE_TYPE);
1710        arg.getArgument(0).accept(this);
1711        returnType.pop();
1712        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1713        //if (rettype == VALUE_TYPE) {
1714
if (this.resnodes != null && resnodes.size() == 1) {
1715            this.setValue(((TypedNode) resnodes.get(0)).getNamespaceURI());
1716            return;
1717        }
1718        //}
1719
clear();
1720    }
1721
1722    /*
1723    2.3 fn:string
1724    fn:string() as xs:string
1725    fn:string($srcval as item?) as xs:string
1726    Returns the value of $srcval represented as a xs:string. If no argument is supplied, $srcval defaults to the context item (.).
1727    
1728    If $srcval is the empty sequence, the zero-length string is returned.
1729    
1730    If $srcval is a node, the function returns the string-value of the node, as obtained using the string-value accessor defined in the [XQuery 1.0 and XPath 2.0 Data Model].
1731    
1732    If $srcval is an atomic value, then the function returns the same string as is returned by the expression cast as xs:string ($srcval), except in the cases listed below:
1733    
1734    If the type of $srcval is xs:anyURI, the URI is converted to a string without any escaping of special characters.
1735    
1736    Note:
1737    
1738    The reason for the special rule for xs:anyURI is that, although XML Schema strongly discourages the use of spaces within URI values,
1739    the escaping of spaces can cause problems with legacy applications (for example, this applies to spaces within fragment identifiers
1740    in many HTML browsers), and should therefore be under user control.
1741    
1742    Note:
1743    
1744    The string representation of xs:double values is not backwards-compatible with the representation of number values in [XPath 1.0].
1745    Ordinary xs:double values are now represented using scientific notation; the representations of positive and negative infinity are
1746    now 'INF' and '-INF' rather than 'Infinity' and '-Infinity'. (It should be observed that '+INF' is not supported as a lexical form
1747    of infinity in [XML Schema Part 2: Datatypes] and is thus not supported by this specification; if that lexical form is added in a
1748    future version of [XML Schema Part 2: Datatypes], then it will be supported by a future version of this specification that aligns
1749    with that future version of [XML Schema Part 2: Datatypes].)
1750    However, most expressions that would have produced a number in [XPath 1.0] will produce a decimal (or integer) in [XPath 2.0],
1751    so unless there is a loss of precision caused by numeric approximation, the result of the expression will in most simple cases be
1752    the same after conversion to a string.
1753    */

1754    public void visit(FunctionSTRING arg) throws XQueryException {
1755        returnType.push(UNKNOWN_TYPE);
1756        arg.getArgument(0).accept(this);
1757        returnType.pop();
1758        if (resvalue != null) { // do nothing
1759
if (!(resvalue instanceof String JavaDoc))
1760                resvalue = resvalue.toString();
1761        } else if (resnodes == null || resnodes.isEmpty()) {
1762            resvalue = new String JavaDoc("");
1763        } else if (resnodes != null && resnodes.size() == 1) {
1764            StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1765            DOMUtils.getStringValue((TypedNode) resnodes.get(0), sb);
1766            resvalue = sb.toString();
1767        } else if (resnodes != null && resnodes.size() > 1) {
1768            throw new XQueryException("Evaluation : incorrect argument for function string");
1769        }
1770        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1771        if (rettype == NODE_TYPE) {
1772            ArrayList nodes = new ArrayList(1);
1773            TypedValue text = docimpl.createTypedValue(resvalue, this.schemamanager.getStringType());
1774            nodes.add(text);
1775            setResnodes(nodes);
1776            return;
1777        } else { //if (rettype == VALUE_TYPE) {
1778
setValue(resvalue);
1779            return;
1780        }
1781        //clear();
1782
}
1783
1784    /*
1785    7.4.7 fn:string-length
1786    fn:string-length() as xs:integer?
1787    fn:string-length($srcval as xs:string?) as xs:integer?
1788    Returns an xs:integer equal to the length in characters of the value of $srcval. If the value of $srcval is the empty sequence,
1789    the empty sequence is returned. If no argument is supplied, $srcval defaults to the string value (calculated using fn:string()) of the context item (.).
1790    
1791    Note:
1792    
1793    The value returned is the number of XML characters in the string (or equivalently, the number of Unicode code points).
1794    Some implementations may represent a code point above xFFFF using two 16-bit values known as a surrogate pair.
1795    A surrogate pair counts as one character, not two.
1796    */

1797    public void visit(FunctionSTRING_LENGTH arg) throws XQueryException {
1798        returnType.push(UNKNOWN_TYPE);
1799        arg.getArgument(0).accept(this);
1800        returnType.pop();
1801        if (resvalue != null) { // do nothing
1802
if (resvalue instanceof String JavaDoc)
1803                resvalue = new Long JavaDoc(((String JavaDoc) resvalue).length());
1804            else
1805                resvalue = new Long JavaDoc(resvalue.toString().length());
1806        } else if (resnodes == null || resnodes.isEmpty()) {
1807            resvalue = new Long JavaDoc(0);
1808        } else if (resnodes != null && resnodes.size() == 1) {
1809            StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1810            DOMUtils.getStringValue((TypedNode) resnodes.get(0), sb);
1811            resvalue = new Long JavaDoc(sb.length());
1812        } else if (resnodes != null && resnodes.size() > 1) {
1813            throw new XQueryException("Evaluation : incorrect argument for function string-length");
1814        }
1815        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1816        if (rettype == NODE_TYPE) {
1817            ArrayList nodes = new ArrayList(1);
1818            TypedValue text = docimpl.createTypedValue(resvalue, this.schemamanager.getIntegerType());
1819            nodes.add(text);
1820            setResnodes(nodes);
1821            return;
1822        } else { //if (rettype == VALUE_TYPE) {
1823
setValue(resvalue);
1824            return;
1825        }
1826        //clear();
1827
}
1828
1829    /*
1830    7.4.6 fn:substring
1831    fn:substring( $sourceString as xs:string?,
1832    $startingLoc as xs:double) as xs:string?
1833    
1834    fn:substring( $sourceString as xs:string?,
1835    $startingLoc as xs:double,
1836    $length as xs:double) as xs:string?
1837    
1838    If the value of $sourceString is the empty sequence, the empty sequence is returned.
1839    
1840    Otherwise, returns the portion of the value of $sourceString beginning at the position indicated by the value of $startingLoc and continuing
1841    for the number of characters indicated by the value of $length. More specifically, returns the characters in $sourceString whose position $p obeys:
1842    
1843    fn:round($startingLoc) <= $p < fn:round($startingLoc) + fn:round($length)
1844    
1845    In the above computation, the rules for op:numeric-less-than() and op:numeric-greater-than() apply.
1846    
1847    If $startingLoc is zero or negative, the substring includes characters from the beginning of the $sourceString.
1848    
1849    If $length is not specified, the substring includes characters to the end of $sourceString.
1850    
1851    If $length is greater than the number of characters in the value of $sourceString following $startingLoc, the substring includes characters to the end of $sourceString.
1852    
1853    The first character of a string is located at position 1, not position 0.
1854    
1855    Note:
1856    
1857    The position and length given in the second and (optional) third argument relate to the number of XML characters in the string
1858    (or equivalently, the number of Unicode code points). Some implementations may represent a code point above xFFFF using two 16-bit
1859    values known as a surrogate pair. A surrogate pair counts as one character, not two.
1860    */

1861    public void visit(FunctionSUBSTRING arg) throws XQueryException {
1862        boolean hasLength = (arg.getArguments().size() == 3) ? true : false;
1863        String JavaDoc sourceString = null;
1864        returnType.push(UNKNOWN_TYPE);
1865        arg.getArgument(0).accept(this);
1866        if (resvalue != null) {
1867            if (resvalue instanceof String JavaDoc)
1868                sourceString = (String JavaDoc) resvalue;
1869            else
1870                sourceString = resvalue.toString();
1871        } else if (resnodes != null && resnodes.size() == 1) {
1872            StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1873            DOMUtils.getStringValue((TypedNode) resnodes.get(0), sb);
1874            sourceString = sb.toString();
1875        } else if (resnodes != null && resnodes.size() > 1) {
1876            throw new XQueryException("Evaluation : incorrect first argument for function substring");
1877        }
1878        if (sourceString == null) {
1879            clear();
1880            return;
1881        }
1882        double startingLoc = 0;
1883        arg.getArgument(1).accept(this);
1884        if (resvalue != null) { // do nothing
1885
} else if (resnodes != null && resnodes.size() == 1) {
1886            TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
1887            if (tmpnode == null)
1888                tmpnode = (TypedNode) resnodes.get(0);
1889            resvalue = (Comparable JavaDoc) tmpnode.getTypedValue();
1890        } else
1891            throw new XQueryException("Evaluation : incorrect second argument for function substring");
1892        if (resvalue instanceof Number JavaDoc) {
1893            startingLoc = ((Number JavaDoc) resvalue).doubleValue();
1894        } else if (resvalue instanceof String JavaDoc) {
1895            try {
1896                startingLoc = Double.parseDouble((String JavaDoc) resvalue);
1897            } catch (NumberFormatException JavaDoc e) {
1898                // do nothing
1899
}
1900        } else
1901            throw new XQueryException("Evaluation : incorrect second argument for function substring");
1902        if (startingLoc < 1)
1903            startingLoc = 1;
1904        double length = sourceString.length();
1905        if (hasLength) {
1906            arg.getArgument(2).accept(this);
1907            if (resvalue != null) { // do nothing
1908
} else if (resnodes != null && resnodes.size() == 1) {
1909                TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
1910                if (tmpnode == null)
1911                    tmpnode = (TypedNode) resnodes.get(0);
1912                resvalue = (Comparable JavaDoc) tmpnode.getTypedValue();
1913            } else
1914                throw new XQueryException("Evaluation : incorrect third argument for function substring");
1915            if (resvalue instanceof Number JavaDoc) {
1916                length = ((Number JavaDoc) resvalue).doubleValue();
1917            } else if (resvalue instanceof String JavaDoc) {
1918                try {
1919                    length = Double.parseDouble((String JavaDoc) resvalue);
1920                } catch (NumberFormatException JavaDoc e) {
1921                    // do nothing
1922
}
1923            } else
1924                throw new XQueryException("Evaluation : incorrect third argument for function substring");
1925            if (startingLoc + length > sourceString.length())
1926                hasLength = false;
1927        }
1928        returnType.pop();
1929        if (hasLength)
1930            resvalue = sourceString.substring((int) Math.round(startingLoc) - 1, (int) (Math.round(startingLoc) + Math.round(length)) - 1);
1931        else
1932            resvalue = sourceString.substring((int) Math.round(startingLoc) - 1);
1933        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1934        if (rettype == NODE_TYPE) {
1935            ArrayList nodes = new ArrayList(1);
1936            TypedValue text = docimpl.createTypedValue(resvalue, this.schemamanager.getStringType());
1937            nodes.add(text);
1938            setResnodes(nodes);
1939            return;
1940        } else { //if (rettype == VALUE_TYPE) {
1941
setValue(resvalue);
1942            return;
1943        }
1944        //clear();
1945
}
1946
1947    //-----------------------------------------------------------
1948
// MATHEMATICAL FUNCTIONS
1949
//-----------------------------------------------------------
1950
public void visit(FunctionABS arg) throws XQueryException {
1951        returnType.push(UNKNOWN_TYPE);
1952        arg.getArgument(0).accept(this);
1953        returnType.pop();
1954        if (resvalue != null) { // do nothing
1955
} else if (resnodes != null && resnodes.size() == 1) {
1956            TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
1957            if (tmpnode == null)
1958                tmpnode = (TypedNode) resnodes.get(0);
1959            resvalue = (Comparable JavaDoc) tmpnode.getTypedValue();
1960            if (!(resvalue instanceof Number JavaDoc))
1961                throw new XQueryException("Could not apply function abs");
1962        } else
1963            throw new XQueryException("Could not apply function abs");
1964
1965        if (resvalue instanceof Long JavaDoc)
1966            resvalue = new Long JavaDoc(Math.abs(((Long JavaDoc) resvalue).longValue()));
1967        else if (resvalue instanceof BigDecimal JavaDoc)
1968            resvalue = ((BigDecimal JavaDoc) resvalue).abs();
1969        else if (resvalue instanceof Float JavaDoc)
1970            resvalue = new Float JavaDoc(Math.abs(((Float JavaDoc) resvalue).floatValue()));
1971        else if (resvalue instanceof Double JavaDoc)
1972            resvalue = new Double JavaDoc(Math.abs(((Double JavaDoc) resvalue).doubleValue()));
1973
1974        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
1975        if (rettype == VALUE_TYPE) {
1976            setValue(resvalue);
1977            return;
1978        } else { // (rettype == NODE_TYPE) {
1979
ArrayList nodes = new ArrayList(1);
1980            TypedValue text = docimpl.createTypedValue(resvalue, getSimpleType(resvalue, schemamanager.getDoubleType()));
1981            nodes.add(text);
1982            setResnodes(nodes);
1983            return;
1984        }
1985        // clear();
1986
}
1987    public void visit(FunctionCEILING arg) throws XQueryException {
1988        returnType.push(UNKNOWN_TYPE);
1989        arg.getArgument(0).accept(this);
1990        returnType.pop();
1991        if (resvalue != null) { // do nothing
1992
} else if (resnodes != null && resnodes.size() == 1) {
1993            TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
1994            if (tmpnode == null)
1995                tmpnode = (TypedNode) resnodes.get(0);
1996            resvalue = (Comparable JavaDoc) tmpnode.getTypedValue();
1997            if (!(resvalue instanceof Number JavaDoc))
1998                throw new XQueryException("Could not apply function ceiling");
1999        } else
2000            throw new XQueryException("Could not apply function ceiling");
2001
2002        if (resvalue instanceof Long JavaDoc) { // do nothing
2003
} else if (resvalue instanceof BigDecimal JavaDoc)
2004            resvalue = ((BigDecimal JavaDoc) resvalue).setScale(0, BigDecimal.ROUND_CEILING);
2005        else if (resvalue instanceof Float JavaDoc)
2006            resvalue = new Float JavaDoc(Math.ceil(((Float JavaDoc) resvalue).floatValue()));
2007        else if (resvalue instanceof Double JavaDoc)
2008            resvalue = new Double JavaDoc(Math.ceil(((Double JavaDoc) resvalue).doubleValue()));
2009
2010        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
2011        if (rettype == VALUE_TYPE) {
2012            setValue(resvalue);
2013            return;
2014        } else { // (rettype == NODE_TYPE) {
2015
ArrayList nodes = new ArrayList(1);
2016            TypedValue text = docimpl.createTypedValue(resvalue, this.getSimpleType(resvalue, schemamanager.getDoubleType()));
2017            nodes.add(text);
2018            setResnodes(nodes);
2019            return;
2020        }
2021        // clear();
2022
}
2023    public void visit(FunctionFLOOR arg) throws XQueryException {
2024        returnType.push(UNKNOWN_TYPE);
2025        arg.getArgument(0).accept(this);
2026        returnType.pop();
2027        if (resvalue != null) { // do nothing
2028
} else if (resnodes != null && resnodes.size() == 1) {
2029            TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
2030            if (tmpnode == null)
2031                tmpnode = (TypedNode) resnodes.get(0);
2032            resvalue = (Comparable JavaDoc) tmpnode.getTypedValue();
2033            if (!(resvalue instanceof Number JavaDoc))
2034                throw new XQueryException("Could not apply function floor");
2035        } else
2036            throw new XQueryException("Could not apply function floor");
2037
2038        if (resvalue instanceof Long JavaDoc) { // do nothing
2039
} else if (resvalue instanceof BigDecimal JavaDoc)
2040            resvalue = ((BigDecimal JavaDoc) resvalue).setScale(0, BigDecimal.ROUND_FLOOR);
2041        else if (resvalue instanceof Float JavaDoc)
2042            resvalue = new Float JavaDoc(Math.floor(((Float JavaDoc) resvalue).floatValue()));
2043        else if (resvalue instanceof Double JavaDoc)
2044            resvalue = new Double JavaDoc(Math.floor(((Double JavaDoc) resvalue).doubleValue()));
2045
2046        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
2047        if (rettype == VALUE_TYPE) {
2048            setValue(resvalue);
2049            return;
2050        } else { // (rettype == NODE_TYPE) {
2051
ArrayList nodes = new ArrayList(1);
2052            TypedValue text = docimpl.createTypedValue(resvalue, this.getSimpleType(resvalue, schemamanager.getDoubleType()));
2053            nodes.add(text);
2054            setResnodes(nodes);
2055            return;
2056        }
2057        // clear();
2058
}
2059    public void visit(FunctionROUND arg) throws XQueryException {
2060        returnType.push(UNKNOWN_TYPE);
2061        arg.getArgument(0).accept(this);
2062        returnType.pop();
2063        if (resvalue != null) { // do nothing
2064
} else if (resnodes != null && resnodes.size() == 1) {
2065            TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
2066            if (tmpnode == null)
2067                tmpnode = (TypedNode) resnodes.get(0);
2068            resvalue = (Comparable JavaDoc) tmpnode.getTypedValue();
2069            if (!(resvalue instanceof Number JavaDoc))
2070                throw new XQueryException("Could not apply function round");
2071        } else
2072            throw new XQueryException("Could not apply function round");
2073
2074        if (resvalue instanceof Long JavaDoc) { // do nothing
2075
} else if (resvalue instanceof BigDecimal JavaDoc)
2076            resvalue = ((BigDecimal JavaDoc) resvalue).setScale(0, BigDecimal.ROUND_UP);
2077        else if (resvalue instanceof Float JavaDoc)
2078            resvalue = new BigDecimal JavaDoc(Math.round(((Float JavaDoc) resvalue).floatValue()));
2079        else if (resvalue instanceof Double JavaDoc)
2080            resvalue = new BigDecimal JavaDoc(Math.round(((Double JavaDoc) resvalue).doubleValue()));
2081
2082        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
2083        if (rettype == VALUE_TYPE) {
2084            setValue(resvalue);
2085            return;
2086        } else { // (rettype == NODE_TYPE) {
2087
ArrayList nodes = new ArrayList(1);
2088            TypedValue text = docimpl.createTypedValue(resvalue, this.getSimpleType(resvalue, schemamanager.getDoubleType()));
2089            nodes.add(text);
2090            setResnodes(nodes);
2091            return;
2092        }
2093        // clear();
2094
}
2095
2096    /*
2097    14.1.4 fn:number
2098    fn:number() as xs:double
2099    fn:number($srcval as item?) as xs:double
2100    Returns the value indicated by $srcval or, if $srcval is not specified, the context node, converted to an xs:double. If there is no context node (that is, if there is no context item, or if the context item is not a node), NaN is returned.
2101    
2102    If $srcval is the empty sequence, returns the xs:double value NaN.
2103    
2104    If $srcval is atomic, returns the value obtained by converting it to xs:double following the rules of 17.8 Casting to numeric types.
2105    
2106    If $srcval is a node with an atomic type, returns that value converted to xs:double following the rules of 17.8 Casting to numeric types.
2107    
2108    Otherwise, converts $srcval to an xs:string as if by a call to the fn:string() function and then converts the result to an xs:double following the rules of 17.8 Casting to numeric types.
2109    
2110    If the conversion to xs:double fails because the lexical representation is not a valid lexical representation of a numeric simple type as defined in [XML Schema Part 2: Datatypes], returns the xs:double value NaN.
2111    */

2112    public void visit(FunctionNUMBER arg) throws XQueryException {
2113        returnType.push(UNKNOWN_TYPE);
2114        arg.getArgument(0).accept(this);
2115        returnType.pop();
2116        if (resvalue != null) { // do nothing
2117
} else if (resnodes != null && resnodes.size() == 1) {
2118            TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
2119            if (tmpnode == null)
2120                tmpnode = (TypedNode) resnodes.get(0);
2121            resvalue = (Comparable JavaDoc) tmpnode.getTypedValue();
2122            if (resvalue instanceof Number JavaDoc) {
2123                resvalue = new Double JavaDoc(((Number JavaDoc) resvalue).doubleValue());
2124            } else if (resvalue instanceof String JavaDoc) {
2125                try {
2126                    resvalue = new Double JavaDoc(Double.parseDouble((String JavaDoc) resvalue));
2127                } catch (NumberFormatException JavaDoc e) {
2128                    // do nothing
2129
}
2130            }
2131        } else if (resnodes != null && resnodes.size() > 1) {
2132            throw new XQueryException("Evaluation : incorrect argument for function number");
2133        }
2134        if (resvalue == null) {
2135            resvalue = new Double JavaDoc(Double.NaN);
2136        }
2137        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
2138        if (rettype == NODE_TYPE) {
2139            ArrayList nodes = new ArrayList(1);
2140            TypedValue text = docimpl.createTypedValue(resvalue, this.schemamanager.getDoubleType());
2141            nodes.add(text);
2142            setResnodes(nodes);
2143            return;
2144        } else { // (rettype == VALUE_TYPE) {
2145
setValue(resvalue);
2146            return;
2147        }
2148        // clear();
2149
}
2150
2151    //-----------------------------------------------------------
2152
// CAST/CONSTRUCTOR FUNCTIONS
2153
//-----------------------------------------------------------
2154
public void visit(FunctionDOUBLE arg) throws XQueryException {
2155        returnType.push(UNKNOWN_TYPE);
2156        arg.getArgument(0).accept(this);
2157        returnType.pop();
2158        if (resvalue != null) { // do nothing
2159
} else if (resnodes != null && resnodes.size() == 1) {
2160            TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
2161            if (tmpnode == null)
2162                tmpnode = (TypedNode) resnodes.get(0);
2163            resvalue = (Comparable JavaDoc) tmpnode.getTypedValue();
2164        } else
2165            throw new XQueryException("Could not create double");
2166
2167        if (resvalue instanceof Double JavaDoc) { // do nothing
2168
} else if (resvalue instanceof Number JavaDoc) {
2169            resvalue = new Double JavaDoc(((Number JavaDoc) resvalue).doubleValue());
2170        } else if (resvalue instanceof String JavaDoc) {
2171            try {
2172                resvalue = new Double JavaDoc(Double.parseDouble((String JavaDoc) resvalue));
2173            } catch (NumberFormatException JavaDoc e) {
2174                // do nothing
2175
}
2176        } else
2177            throw new XQueryException("Could not create double");
2178        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
2179        if (rettype == VALUE_TYPE) {
2180            setValue(resvalue);
2181            return;
2182        } else { // (rettype == NODE_TYPE) {
2183
ArrayList nodes = new ArrayList(1);
2184            TypedValue text = docimpl.createTypedValue(resvalue, this.schemamanager.getDoubleType());
2185            nodes.add(text);
2186            setResnodes(nodes);
2187            return;
2188        }
2189        //clear();
2190
}
2191
2192    public void visit(FunctionINTEGER arg) throws XQueryException {
2193        returnType.push(UNKNOWN_TYPE);
2194        arg.getArgument(0).accept(this);
2195        returnType.pop();
2196        if (resvalue != null) { // do nothing
2197
} else if (resnodes != null && resnodes.size() == 1) {
2198            TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
2199            if (tmpnode == null)
2200                tmpnode = (TypedNode) resnodes.get(0);
2201            resvalue = (Comparable JavaDoc) tmpnode.getTypedValue();
2202        } else
2203            throw new XQueryException("Could not create integer");
2204
2205        if (resvalue instanceof Long JavaDoc) { // do nothing
2206
} else if (resvalue instanceof Number JavaDoc) {
2207            resvalue = new Long JavaDoc(((Number JavaDoc) resvalue).longValue());
2208        } else if (resvalue instanceof String JavaDoc) {
2209            try {
2210                resvalue = new Long JavaDoc((String JavaDoc) resvalue);
2211            } catch (NumberFormatException JavaDoc e) {
2212                // do nothing
2213
}
2214        } else
2215            throw new XQueryException("Could not create integer");
2216        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
2217        if (rettype == VALUE_TYPE) {
2218            setValue(resvalue);
2219            return;
2220        } else { // (rettype == NODE_TYPE) {
2221
ArrayList nodes = new ArrayList(1);
2222            TypedValue text = docimpl.createTypedValue(resvalue, this.schemamanager.getIntegerType());
2223            nodes.add(text);
2224            setResnodes(nodes);
2225            return;
2226        }
2227        //clear();
2228
}
2229
2230    public void visit(FunctionDECIMAL arg) throws XQueryException {
2231        returnType.push(UNKNOWN_TYPE);
2232        arg.getArgument(0).accept(this);
2233        returnType.pop();
2234        if (resvalue != null) { // do nothing
2235
} else if (resnodes != null && resnodes.size() == 1) {
2236            TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(0)).getFirstChild();
2237            if (tmpnode == null)
2238                tmpnode = (TypedNode) resnodes.get(0);
2239            resvalue = (Comparable JavaDoc) tmpnode.getTypedValue();
2240        } else
2241            throw new XQueryException("Could not create decimal");
2242
2243        if (resvalue instanceof BigDecimal JavaDoc) { // do nothing
2244
} else if (resvalue instanceof Number JavaDoc) {
2245            resvalue = new BigDecimal JavaDoc(((Number JavaDoc) resvalue).doubleValue());
2246        } else if (resvalue instanceof String JavaDoc) {
2247            try {
2248                resvalue = new BigDecimal JavaDoc((String JavaDoc) resvalue);
2249            } catch (NumberFormatException JavaDoc e) {
2250                // do nothing
2251
}
2252        } else
2253            throw new XQueryException("Could not create decimal");
2254        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
2255        if (rettype == VALUE_TYPE) {
2256            setValue(resvalue);
2257            return;
2258        } else { // (rettype == NODE_TYPE) {
2259
ArrayList nodes = new ArrayList(1);
2260            TypedValue text = docimpl.createTypedValue(resvalue, this.schemamanager.getDecimalType());
2261            nodes.add(text);
2262            setResnodes(nodes);
2263            return;
2264        }
2265        //clear();
2266
}
2267
2268    //-----------------------------------------------------------
2269
// OTHER FUNCTIONS
2270
//-----------------------------------------------------------
2271

2272    public void visit(FunctionDATA arg) throws XQueryException {
2273        returnType.push(UNKNOWN_TYPE);
2274        arg.getArgument(0).accept(this);
2275        returnType.pop();
2276        Integer JavaDoc rettype = (Integer JavaDoc) returnType.peek();
2277        if (resvalue != null) {
2278            if (rettype == VALUE_TYPE) {
2279                setValue(resvalue);
2280                return;
2281            } else { // (rettype == NODE_TYPE) {
2282
ArrayList nodes = new ArrayList(1);
2283                TypedValue text = docimpl.createTypedValue(resvalue, this.getSimpleType(resvalue, schemamanager.getAnySimpleType()));
2284                nodes.add(text);
2285                setResnodes(nodes);
2286                return;
2287            }
2288        } else if (resnodes != null) {
2289            ArrayList tmplist = new ArrayList(resnodes.size());
2290            for (int i = 0; i < resnodes.size(); i++) {
2291                TypedNode tmpnode = (TypedNode) ((TypedNode) resnodes.get(i)).getFirstChild();
2292                // change 02/09/2003
2293
if (tmpnode == null || tmpnode.getTypedValue() == null)
2294                    tmpnode = (TypedNode) resnodes.get(i);
2295                Comparable JavaDoc comp = (Comparable JavaDoc) tmpnode.getTypedValue();
2296                if (comp != null)
2297                    tmplist.add(docimpl.createTypedValue(comp, this.getSimpleType(comp, schemamanager.getAnySimpleType())));
2298// else
2299
// throw new XQueryException("Could not apply function data");
2300
}
2301            if (rettype == VALUE_TYPE) {
2302                if (tmplist.size() == 1) {
2303                    TypedNode tmpnode = (TypedNode) ((TypedNode) tmplist.get(0)).getFirstChild();
2304                    if (tmpnode == null)
2305                        tmpnode = (TypedNode) tmplist.get(0);
2306                    setValue((Comparable JavaDoc) tmpnode.getTypedValue());
2307                    return;
2308                }
2309            } else { // (rettype == NODE_TYPE) {
2310
setResnodes(tmplist);
2311                return;
2312            }
2313        }
2314// else
2315
// throw new XQueryException("Could not apply function data");
2316
// clear();
2317
}
2318
2319    public void visit(FunctionEXISTS arg) throws XQueryException {
2320        returnType.push(NODE_TYPE);
2321        arg.getArgument(0).accept(this);
2322        returnType.pop();
2323        setVerdict(resnodes != null && !resnodes.isEmpty());
2324    }
2325
2326    public void visit(FunctionEMPTY arg) throws XQueryException {
2327        if (buffertuple != null && !buffertuple.isEmpty()) {
2328            setVerdict(false);
2329            return;
2330        }
2331        returnType.push(NODE_TYPE);
2332        arg.getArgument(0).accept(this);
2333        returnType.pop();
2334        setVerdict(resnodes == null || resnodes.isEmpty());
2335    }
2336
2337    public void visit(FunctionNOT arg) throws XQueryException {
2338        arg.getArgument(0).accept(this);
2339        setVerdict(!verdict);
2340    }
2341
2342    public void visit(FunctionDISTINCT_VALUES arg) throws XQueryException {
2343        returnType.push(NODE_TYPE);
2344        arg.getArgument(0).accept(this);
2345        returnType.pop();
2346        if (resnodes != null) {
2347            // cloning must be done otherwise context tuple could be changed
2348
resnodes = (ArrayList) resnodes.clone();
2349            for (int i = 0; i < resnodes.size(); i++) {
2350                TypedNode nodei = (TypedNode) resnodes.get(i);
2351                for (int j = 0; j < i; j++) {
2352                    TypedNode nodej = (TypedNode) resnodes.get(j);
2353                    if (DOMUtils.compareTree(nodei, nodej)) {
2354                        resnodes.remove(i);
2355                        i--;
2356                        break;
2357                    }
2358                }
2359            }
2360        }
2361        setResnodes(resnodes);
2362    }
2363
2364    public void visit(FunctionDEEP_EQUALS arg) throws XQueryException {
2365        resulttuple = null;
2366        resnodes = null;
2367        XQueryExpression arg0 = arg.getArgument(0);
2368        XQueryExpression arg1 = arg.getArgument(1);
2369        if (arg0 instanceof Value && arg1 instanceof Value)
2370            processComparison(arg0, arg1, null, null, null, null, Constants.EQ_COMPOP);
2371        else {
2372            if (arg0 instanceof Value) {
2373                if (tuple != null) {
2374                    ArrayList nodes1 = tuple.getNodesAtIndex(tuple.getParent().getPathIndex(arg1.getStringValue()));
2375                    if (nodes1 != null && nodes1.size() == 1) {
2376                        processComparison(arg0, arg1, (TypedNode) null, (TypedNode) nodes1.get(0), null, null, Constants.EQ_COMPOP);
2377                    }
2378                } else if (tuplelist != null) {
2379                    for (int i = 0; i < tuplelist.size(); i++) {
2380                        Tuple tuplei = (Tuple) tuplelist.get(i);
2381                        ArrayList nodes1 = tuplei.getNodesAtIndex(tuplei.getParent().getPathIndex(arg1.getStringValue()));
2382                        if (nodes1 != null && nodes1.size() == 1) {
2383                            processComparison(arg0, arg1, (TypedNode) null, (TypedNode) nodes1.get(0), null, null, Constants.EQ_COMPOP);
2384                            break;
2385                        }
2386                    }
2387                }
2388            } else if (arg1 instanceof Value) {
2389                if (tuple != null) {
2390                    ArrayList nodes0 = tuple.getNodesAtIndex(tuple.getParent().getPathIndex(arg0.getStringValue()));
2391                    if (nodes0 != null && nodes0.size() == 1) {
2392                        processComparison(arg0, arg1, (TypedNode) nodes0.get(0), (TypedNode) null, null, null, Constants.EQ_COMPOP);
2393                    }
2394                } else if (tuplelist != null) {
2395                    for (int i = 0; i < tuplelist.size(); i++) {
2396                        Tuple tuplei = (Tuple) tuplelist.get(i);
2397                        ArrayList nodes0 = tuplei.getNodesAtIndex(tuplei.getParent().getPathIndex(arg0.getStringValue()));
2398                        if (nodes0 != null && nodes0.size() == 1) {
2399                            processComparison(arg0, arg1, (TypedNode) nodes0.get(0), (TypedNode) null, null, null, Constants.EQ_COMPOP);
2400                            break;
2401                        }
2402                    }
2403                }
2404            } else {
2405                if (this.tuple != null) {
2406                    ArrayList nodes0 = tuple.getNodesAtIndex(tuple.getParent().getPathIndex(arg0.getStringValue()));
2407                    ArrayList nodes1 = tuple.getNodesAtIndex(tuple.getParent().getPathIndex(arg1.getStringValue()));
2408                    verdict = DOMUtils.compareTree(nodes0, nodes1);
2409                } else if (tuplelist != null) {
2410                    ArrayList nodes0 = null;
2411                    ArrayList nodes1 = null;
2412                    for (int i = 0; i < tuplelist.size(); i++) {
2413                        Tuple tmptuple = (Tuple) tuplelist.get(i);
2414                        if (nodes0 == null)
2415                            nodes0 = tmptuple.getNodesAtIndex(tmptuple.getParent().getPathIndex(arg0.getStringValue()));
2416                        if (nodes1 == null)
2417                            nodes1 = tmptuple.getNodesAtIndex(tmptuple.getParent().getPathIndex(arg1.getStringValue()));
2418                        if (nodes0 != null && nodes1 != null)
2419                            break;
2420                    }
2421                    verdict = DOMUtils.compareTree(nodes0, nodes1);
2422                } else if (buffertuple != null) {
2423                    throw new XQueryException("FunctionVALUE_EQUALS on BufferTuple not yet implemented");
2424                }
2425            }
2426        }
2427    }
2428
2429    //-----------------------------------------------------------
2430
// PRIVATE METHODS
2431
//-----------------------------------------------------------
2432

2433    private SimpleType getSimpleType(Comparable JavaDoc obj, SimpleType defaultType) {
2434        if (obj instanceof Long JavaDoc)
2435            return this.schemamanager.getIntegerType();
2436        else if (obj instanceof BigDecimal JavaDoc)
2437            return this.schemamanager.getDecimalType();
2438        else if (obj instanceof Float JavaDoc)
2439            return this.schemamanager.getFloatType();
2440        else if (obj instanceof Double JavaDoc)
2441            return this.schemamanager.getDoubleType();
2442        else if (obj instanceof String JavaDoc)
2443            return this.schemamanager.getStringType();
2444        else if (obj instanceof Date)
2445            return this.schemamanager.getDateTimeType();
2446        return defaultType;
2447    }
2448
2449    private void processComparison(XQueryExpression exp1, XQueryExpression exp2, TypedNode tree1, TypedNode tree2, Comparable JavaDoc value1, Comparable JavaDoc value2, int operator) {
2450        //Comparable value1 = null;
2451
boolean doublecompare = false;
2452        double value1double = 0;
2453        if (value1 == null) {
2454            if (exp1 instanceof ValueInteger) {
2455                value1 = new Long JavaDoc(((ValueInteger) exp1).getIntValue().longValue());
2456                // value1double = ((Number) value1).doubleValue();
2457
} else if (exp1 instanceof ValueDecimal) {
2458                value1 = ((ValueDecimal) exp1).getDecimalValue();
2459                // value1double = ((Number) value1).doubleValue();
2460
} else if (exp1 instanceof ValueFloat) {
2461                value1 = ((ValueFloat) exp1).getFloatValue();
2462                // value1double = ((Number) value1).doubleValue();
2463
} else if (exp1 instanceof ValueDouble) {
2464                value1 = ((ValueDouble) exp1).getDoubleValue();
2465                // value1double = ((Number) value1).doubleValue();
2466
} else if (exp1 instanceof ValueString) {
2467                value1 = ((ValueString) exp1).getValue();
2468            } else if (tree1 != null) {
2469                if (tree1.getTypedValue() != null)
2470                    value1 = (Comparable JavaDoc) tree1.getTypedValue();
2471                else
2472                    value1 = (Comparable JavaDoc) DOMUtils.getTextLeaf(tree1);
2473                // if (value1 != null && !(value1 instanceof String) && !(value1 instanceof Timestamp)) {
2474
// value1double = ((Number) value1).doubleValue();
2475
// doublecompare = true;
2476
// }
2477
}
2478        }
2479        if (value1 != null && !(value1 instanceof String JavaDoc) && !(value1 instanceof Timestamp JavaDoc) && !(value1 instanceof Date)) {
2480            value1double = ((Number JavaDoc) value1).doubleValue();
2481            doublecompare = true;
2482        }
2483        //Comparable value2 = null;
2484
double value2double = 0;
2485        if (value2 == null) {
2486            if (exp2 instanceof ValueInteger) {
2487                value2 = new Long JavaDoc(((ValueInteger) exp2).getIntValue().longValue());
2488                // value2double = ((Number) value2).doubleValue();
2489
} else if (exp2 instanceof ValueDecimal) {
2490                value2 = ((ValueDecimal) exp2).getDecimalValue();
2491                // value2double = ((Number) value2).doubleValue();
2492
} else if (exp2 instanceof ValueFloat) {
2493                value2 = ((ValueFloat) exp2).getFloatValue();
2494                // value2double = ((Number) value2).doubleValue();
2495
} else if (exp2 instanceof ValueDouble) {
2496                value2 = ((ValueDouble) exp2).getDoubleValue();
2497                // value2double = ((Number) value2).doubleValue();
2498
} else if (exp2 instanceof ValueString)
2499                value2 = ((ValueString) exp2).getValue();
2500            else if (tree2 != null) {
2501                if (tree2.getTypedValue() != null)
2502                    value2 = (Comparable JavaDoc) tree2.getTypedValue();
2503                else
2504                    value2 = (Comparable JavaDoc) DOMUtils.getTextLeaf(tree2);
2505                // if (value2 != null && !(value2 instanceof String) && !(value2 instanceof Timestamp)) {
2506
// value2double = ((Number) value2).doubleValue();
2507
// }
2508
// else
2509
// doublecompare = false;
2510
}
2511        }
2512        if (value2 != null && !(value2 instanceof String JavaDoc) && !(value2 instanceof Timestamp JavaDoc) && !(value2 instanceof Date)) {
2513            value2double = ((Number JavaDoc) value2).doubleValue();
2514        } else
2515            doublecompare = false;
2516        // if (value1 == null && value2 == null /*&& tree1 == null && tree2 == null*/)
2517
// if ((operator == Constants.GEQ_COMPOP) || (operator == Constants.LEQ_COMPOP) || (operator == Constants.EQ_COMPOP)) { verdict = true ; return ; }
2518
// else { verdict = false ; return ; }
2519
/*
2520        if (value1 == null && value2 != null) { verdict = false ; return ; }
2521        if (value2 == null && value1 != null) { verdict = false ; return ; }
2522        if (value1 != null && value2 != null) {
2523            if (value1 instanceof String && !(value2 instanceof String)) { verdict = false ; return ; }
2524            if (value2 instanceof String && !(value1 instanceof String)) { verdict = false ; return ; }
2525        }
2526        */

2527        boolean stringcomp = false;
2528        if (value1 == null) {
2529            if (value2 != null) {
2530                setVerdict(false);
2531                return;
2532            }
2533        } else {
2534            if (value2 == null) {
2535                setVerdict(false);
2536                return;
2537            } else {
2538                if (value1 instanceof String JavaDoc) {
2539                    if (!(value2 instanceof String JavaDoc)) {
2540                        value2 = value2.toString();
2541                        if (value2 == null) {
2542                            setVerdict(false);
2543                            return;
2544                        }
2545                        stringcomp = true;
2546                    }
2547                } else if (value2 instanceof String JavaDoc) {
2548                    value1 = value1.toString();
2549                    if (value1 == null) {
2550                        setVerdict(false);
2551                        return;
2552                    }
2553                    stringcomp = true;
2554                }
2555            }
2556        }
2557        //if ((tree1 == null) && (tree2 != null)) { verdict = false ; return ; }
2558
//if ((tree2 == null) && (tree1 != null)) { verdict = false ; return ; }
2559
switch (operator) {
2560            case Constants.LT_VALUECOMP :
2561            case Constants.LT_COMPOP :
2562                if ((value1 == null) && (value2 == null))
2563                    setVerdict(false);
2564                else if (stringcomp || !doublecompare)
2565                    setVerdict((DOMUtils.compareObjects(value1,value2) < 0));
2566                else
2567                    setVerdict((value1double < value2double));
2568                return;
2569            case Constants.GT_VALUECOMP :
2570            case Constants.GT_COMPOP :
2571                if ((value1 == null) && (value2 == null))
2572                    setVerdict(false);
2573                else if (stringcomp || !doublecompare)
2574                    setVerdict((DOMUtils.compareObjects(value1,value2) > 0));
2575                else
2576                    setVerdict((value1double > value2double));
2577                return;
2578            case Constants.GE_VALUECOMP :
2579            case Constants.GEQ_COMPOP :
2580                if ((value1 == null) && (value2 == null))
2581                    setVerdict(true);
2582                else if (stringcomp || !doublecompare)
2583                    setVerdict((DOMUtils.compareObjects(value1,value2) >= 0));
2584                else
2585                    setVerdict((value1double >= value2double));
2586                return;
2587            case Constants.LE_VALUECOMP :
2588            case Constants.LEQ_COMPOP :
2589                if ((value1 == null) && (value2 == null))
2590                    setVerdict(true);
2591                else if (stringcomp || !doublecompare)
2592                    setVerdict((DOMUtils.compareObjects(value1,value2) <= 0));
2593                else
2594                    setVerdict((value1double <= value2double));
2595                return;
2596            case Constants.EQ_VALUECOMP :
2597            case Constants.EQ_COMPOP :
2598                if ((value1 == null) && (value2 == null))
2599                    setVerdict(true);
2600                else if (stringcomp || !doublecompare)
2601                    setVerdict((DOMUtils.compareObjects(value1,value2) == 0));
2602                else
2603                    setVerdict((value1double == value2double));
2604                return;
2605            case Constants.NE_VALUECOMP :
2606            case Constants.NEQ_COMPOP :
2607                if ((value1 == null) && (value2 == null))
2608                    setVerdict(false);
2609                else if (stringcomp || !doublecompare)
2610                    setVerdict((DOMUtils.compareObjects(value1,value2) != 0));
2611                else
2612                    setVerdict((value1double != value2double));
2613                return;
2614                /*
2615                case Constants.EQQ_COMPOP :
2616                    setVerdict(Tuple.compareTree(tree1, tree2));
2617                    return;
2618                 */

2619        }
2620        clear();
2621    }
2622
2623    private Number JavaDoc processOperation(XQueryExpression exp1, XQueryExpression exp2, TypedNode tree1, TypedNode tree2, Number JavaDoc value1, Number JavaDoc value2, int operator) throws XQueryException {
2624        if (value1 == null) {
2625            if (exp1 instanceof ValueInteger)
2626                value1 = new Long JavaDoc(((ValueInteger) exp1).getIntValue().longValue());
2627            else if (exp1 instanceof ValueDecimal)
2628                value1 = ((ValueDecimal) exp1).getDecimalValue();
2629            else if (exp1 instanceof ValueFloat)
2630                value1 = ((ValueFloat) exp1).getFloatValue();
2631            else if (exp1 instanceof ValueDouble)
2632                value1 = ((ValueDouble) exp1).getDoubleValue();
2633            else if (tree1 != null)
2634                if (tree1.getTypedValue() != null)
2635                    value1 = (Number JavaDoc) tree1.getTypedValue();
2636                else
2637                    value1 = (Number JavaDoc) DOMUtils.getTextLeaf(tree1);
2638        }
2639        if (value2 == null) {
2640            if (exp2 instanceof ValueInteger)
2641                value2 = new Long JavaDoc(((ValueInteger) exp2).getIntValue().longValue());
2642            else if (exp2 instanceof ValueDecimal)
2643                value2 = ((ValueDecimal) exp2).getDecimalValue();
2644            else if (exp2 instanceof ValueFloat)
2645                value2 = ((ValueFloat) exp2).getFloatValue();
2646            else if (exp2 instanceof ValueDouble)
2647                value2 = ((ValueDouble) exp2).getDoubleValue();
2648            else if (tree2 != null)
2649                if (tree2.getTypedValue() != null)
2650                    value2 = (Number JavaDoc) tree2.getTypedValue();
2651                else
2652                    value2 = (Number JavaDoc) DOMUtils.getTextLeaf(tree2);
2653        }
2654
2655        boolean integerOp = false;
2656        boolean decimalOp = false;
2657        boolean floatOp = false;
2658        if (value1 instanceof Long JavaDoc) {
2659            if (value2 instanceof Long JavaDoc)
2660                integerOp = true;
2661            else if (value2 instanceof BigDecimal JavaDoc) {
2662                value1 = new BigDecimal JavaDoc(value1.longValue());
2663                decimalOp = true;
2664            }
2665        } else if (value1 instanceof BigDecimal JavaDoc) {
2666            if (value2 instanceof BigDecimal JavaDoc)
2667                decimalOp = true;
2668            else if (value2 instanceof Long JavaDoc) {
2669                value2 = new BigDecimal JavaDoc(value2.longValue());
2670                decimalOp = true;
2671            }
2672        } else if (value1 instanceof Float JavaDoc) {
2673            if (value2 instanceof Float JavaDoc)
2674                floatOp = true;
2675            if (!(value2 instanceof Double JavaDoc)) {
2676                value2 = new Float JavaDoc(value2.doubleValue());
2677                floatOp = true;
2678            }
2679        }
2680
2681        switch (operator) {
2682            case Constants.DIVIDE_ARITHMETICS :
2683                //if (integerOp) {
2684
// try {
2685
// return value1.intValue() / value2.intValue();
2686
// } catch (ArithmeticException ae) {
2687
// throw new XQueryException("Division by zero");
2688
// }
2689
// } else
2690
if (decimalOp) {
2691                    try {
2692                        return ((BigDecimal JavaDoc) value1).divide((BigDecimal JavaDoc) value2, 38, BigDecimal.ROUND_UP);
2693                    } catch (ArithmeticException JavaDoc ae) {
2694                        throw new XQueryException("Division by zero");
2695                    }
2696                } else if (floatOp)
2697                    return new Float JavaDoc(value1.floatValue() / value2.floatValue());
2698                return new Double JavaDoc(value1.doubleValue() / value2.doubleValue());
2699            case Constants.MINUS_ARITHMETICS :
2700                if (integerOp)
2701                    return new Long JavaDoc(value1.longValue() - value2.longValue());
2702                else if (decimalOp)
2703                    return ((BigDecimal JavaDoc) value1).subtract((BigDecimal JavaDoc) value2);
2704                else if (floatOp)
2705                    return new Float JavaDoc(value1.floatValue() - value2.floatValue());
2706                return new Double JavaDoc(value1.doubleValue() - value2.doubleValue());
2707            case Constants.MODULO_ARITHMETICS :
2708                if (integerOp)
2709                    return new Long JavaDoc(value1.longValue() % value2.longValue());
2710                else if (floatOp)
2711                    return new Float JavaDoc(value1.floatValue() % value2.floatValue());
2712                return new Double JavaDoc(value1.doubleValue() % value2.doubleValue());
2713            case Constants.MULTIPLY_ARITHMETICS :
2714                if (integerOp)
2715                    return new Long JavaDoc(value1.longValue() * value2.longValue());
2716                else if (decimalOp)
2717                    return ((BigDecimal JavaDoc) value1).multiply((BigDecimal JavaDoc) value2);
2718                else if (floatOp)
2719                    return new Float JavaDoc(value1.floatValue() * value2.floatValue());
2720                return new Double JavaDoc(value1.doubleValue() * value2.doubleValue());
2721            case Constants.PLUS_ARITHMETICS :
2722                if (integerOp)
2723                    return new Long JavaDoc(value1.longValue() + value2.longValue());
2724                else if (decimalOp)
2725                    return ((BigDecimal JavaDoc) value1).add((BigDecimal JavaDoc) value2);
2726                else if (floatOp)
2727                    return new Float JavaDoc(value1.floatValue() + value2.floatValue());
2728                return new Double JavaDoc(value1.doubleValue() + value2.doubleValue());
2729        }
2730        throw new XQueryException("Could not process operation");
2731    }
2732
2733}
2734
Popular Tags