01: // Copyright (c) 2002, 2006 Per M.A. Bothner.
02: // This is free software; for terms and warranty disclaimer see ./COPYING.
03:
04: package gnu.xquery.util;
05:
06: import gnu.mapping.*;
07: import gnu.lists.*;
08: import gnu.xml.TextUtils;
09: import gnu.kawa.xml.*;
10: import gnu.kawa.functions.*;
11:
12: public class MinMax {
13: public static Object min(Object arg, NamedCollator collation) {
14: return minMax(arg, false, collation);
15: }
16:
17: public static Object max(Object arg, NamedCollator collation) {
18: return minMax(arg, true, collation);
19: }
20:
21: public static Object minMax(Object arg, boolean returnMax,
22: NamedCollator collation) {
23: if (arg instanceof Values) {
24: TreeList tlist = (TreeList) arg;
25: int pos = 0;
26: int flags = returnMax ? Compare.TRUE_IF_GRT
27: : Compare.TRUE_IF_LSS;
28: Object cur = tlist.getPosNext(pos);
29: if (cur == Sequence.eofValue)
30: return Values.empty;
31: Object result = convert(cur);
32: for (;;) {
33: pos = tlist.nextPos(pos);
34: cur = tlist.getPosNext(pos);
35: if (cur == Sequence.eofValue)
36: return result;
37: cur = convert(cur);
38:
39: if (result instanceof Number || cur instanceof Number) {
40: int code1 = Arithmetic.classifyValue(result);
41: int code2 = Arithmetic.classifyValue(cur);
42: int rcode = NumberCompare.compare(result, code1,
43: cur, code2, false);
44: if (rcode == -3)
45: throw new IllegalArgumentException(
46: "values cannot be compared");
47: int code = code1 < code2 ? code2 : code1;
48: boolean castNeeded;
49: if (rcode == -2) {
50: result = NumberValue.NaN;
51: castNeeded = true; // For simplicity.
52: } else if (!NumberCompare.checkCompareCode(rcode,
53: flags)) {
54: castNeeded = code != code2;
55: result = cur;
56: } else {
57: castNeeded = code != code1;
58: }
59: if (castNeeded)
60: result = Arithmetic.convert(result, code);
61: } else {
62: if (!Compare.atomicCompare(flags, result, cur,
63: collation))
64: result = cur;
65: }
66: }
67: } else {
68: arg = convert(arg);
69: // An easy way to check that arg has a valid type.
70: Compare.atomicCompare(Compare.TRUE_IF_GRT, arg, arg,
71: collation);
72: return arg;
73: }
74: }
75:
76: static Object convert(Object arg) {
77: arg = KNode.atomicValue(arg);
78: if (arg instanceof UntypedAtomic)
79: arg = (Double) XDataType.doubleType.valueOf(TextUtils
80: .stringValue(arg));
81: return arg;
82: }
83: }
|