KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > expr > MinimaxComparison


1 package net.sf.saxon.expr;
2 import net.sf.saxon.om.Item;
3 import net.sf.saxon.om.SequenceIterator;
4 import net.sf.saxon.trans.XPathException;
5 import net.sf.saxon.type.ItemType;
6 import net.sf.saxon.type.Type;
7 import net.sf.saxon.value.BooleanValue;
8 import net.sf.saxon.value.NumericValue;
9 import net.sf.saxon.value.Value;
10 import net.sf.saxon.value.AtomicValue;
11
12
13 /**
14  * Class to handle many-to-many A less-than B comparisons by evaluating min(A) < max(B), and
15  * similarly for greater-than, etc. This expression is used only where it is known that the
16  * comparisons will all be numeric: that is, where at least one of the operands has a static
17  * type that is a numeric sequence.
18  */

19
20 public class MinimaxComparison extends BinaryExpression {
21
22     public MinimaxComparison(Expression p0, int operator, Expression p1) {
23         super(p0, operator, p1);
24     }
25
26     /**
27     * Determine the static cardinality. Returns [1..1]
28     */

29
30     public int computeCardinality() {
31         return StaticProperty.EXACTLY_ONE;
32     }
33
34     /**
35     * Type-check the expression.
36     */

37
38     public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException {
39         operand0 = operand0.optimize(opt, env, contextItemType);
40         operand1 = operand1.optimize(opt, env, contextItemType);
41
42         // if either operand is a statically-known list of values, we only need
43
// to retain the minimum or maximum value, depending on the operator.
44

45         if (operand0 instanceof Value) {
46             NumericValue[] range = getRange(operand0.iterate(null));
47             if (range==null) {
48                 return BooleanValue.FALSE;
49             }
50             if (operator == Token.LT || operator == Token.LE) {
51                 operand0 = range[0];
52             } else {
53                 operand0 = range[1];
54             }
55         }
56         if (operand1 instanceof Value) {
57             NumericValue[] range = getRange(operand1.iterate(null));
58             if (range==null) {
59                 return BooleanValue.FALSE;
60             }
61             if (operator == Token.GT || operator == Token.GE) {
62                 operand1 = range[0];
63             } else {
64                 operand1 = range[1];
65             }
66         }
67         return this;
68     }
69
70     /**
71     * Determine the data type of the expression
72     * @return Type.BOOLEAN
73     */

74
75     public ItemType getItemType() {
76         return Type.BOOLEAN_TYPE;
77     }
78
79     /**
80     * Evaluate the expression in a given context
81     * @param context the given context for evaluation
82     * @return a BooleanValue representing the result of the numeric comparison of the two operands
83     */

84
85     public Item evaluateItem(XPathContext context) throws XPathException {
86         return BooleanValue.get(effectiveBooleanValue(context));
87     }
88
89     /**
90     * Evaluate the expression in a boolean context
91     * @param context the given context for evaluation
92     * @return a boolean representing the result of the numeric comparison of the two operands
93     */

94
95     public boolean effectiveBooleanValue(XPathContext context) throws XPathException {
96
97         NumericValue[] range1 = getRange(operand0.iterate(context));
98         NumericValue[] range2 = getRange(operand1.iterate(context));
99
100         if (range1==null) return false;
101         if (range2==null) return false;
102
103         // Now test how the min of one sequence compares to the max of the other
104
switch(operator) {
105             case Token.LT:
106                 return range1[0].compareTo( range2[1] ) < 0;
107             case Token.LE:
108                 return range1[0].compareTo( range2[1] ) <= 0;
109             case Token.GT:
110                 return range1[1].compareTo( range2[0] ) > 0;
111             case Token.GE:
112                 return range1[1].compareTo( range2[0] ) >= 0;
113             default:
114                 throw new UnsupportedOperationException JavaDoc("Unknown operator " + operator);
115         }
116     }
117
118     /**
119     * Get the value range of a sequence, in the form of an array of two SimpleValues, these
120     * being the minimum and maximum respectively. NaN values are ignored.
121     * @return null if the sequence is empty or if all values are NaN
122     */

123
124     private static NumericValue[] getRange(SequenceIterator iter) throws XPathException {
125         NumericValue[] range = null;
126         while (true) {
127             AtomicValue av = (AtomicValue)iter.next();
128             if (av == null) break;
129             NumericValue val = (NumericValue)av.getPrimitiveValue();
130
131             if (val.isNaN()) continue;
132
133             if (range == null) {
134                 range = new NumericValue[2];
135                 range[0] = val;
136                 range[1] = val;
137             } else {
138                 if (val.compareTo(range[0]) < 0) {
139                     range[0] = val;
140                 }
141                 if (val.compareTo(range[1]) > 0) {
142                     range[1] = val;
143                 }
144             }
145         }
146         return range;
147     }
148
149 }
150
151 //
152
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
153
// you may not use this file except in compliance with the License. You may obtain a copy of the
154
// License at http://www.mozilla.org/MPL/
155
//
156
// Software distributed under the License is distributed on an "AS IS" basis,
157
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
158
// See the License for the specific language governing rights and limitations under the License.
159
//
160
// The Original Code is: all this file.
161
//
162
// The Initial Developer of the Original Code is Michael H. Kay
163
//
164
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
165
//
166
// Contributor(s): none.
167
//
168
Popular Tags