KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > functions > Subsequence


1 package net.sf.saxon.functions;
2 import net.sf.saxon.expr.PositionIterator;
3 import net.sf.saxon.expr.TailExpression;
4 import net.sf.saxon.expr.XPathContext;
5 import net.sf.saxon.expr.Token;
6 import net.sf.saxon.om.SequenceIterator;
7 import net.sf.saxon.om.EmptyIterator;
8 import net.sf.saxon.trans.XPathException;
9 import net.sf.saxon.type.ItemType;
10 import net.sf.saxon.value.AtomicValue;
11 import net.sf.saxon.value.NumericValue;
12 import net.sf.saxon.value.IntegerValue;
13
14 /**
15 * Implements the XPath 2.0 subsequence() function
16 */

17
18
19 public class Subsequence extends SystemFunction {
20
21     // Ideally, we would simply convert this at compile time to a filter expression.
22
// Unfortunately, this is not always possible, because a filter expression changes
23
// the focus for evaluating the filter expression, while this function does not.
24

25     /**
26     * Determine the data type of the items in the sequence
27     * @return the type of the argument
28     */

29
30     public ItemType getItemType() {
31         return argument[0].getItemType();
32     }
33
34     /**
35     * Get the static properties of this expression (other than its type). The result is
36     * bit-significant. These properties are used for optimizations. In general, if
37     * property bit is set, it is true, but if it is unset, the value is unknown.
38     */

39
40     public int computeSpecialProperties() {
41         return argument[0].getSpecialProperties();
42     }
43
44     /**
45     * Evaluate the function to return an iteration of selected nodes.
46     */

47
48     public SequenceIterator iterate(XPathContext context) throws XPathException {
49         SequenceIterator seq = argument[0].iterate(context);
50         AtomicValue startVal0 = (AtomicValue)argument[1].evaluateItem(context);
51         NumericValue startVal = (NumericValue)startVal0.getPrimitiveValue();
52
53         if (argument.length == 2) {
54             long lstart;
55             if (startVal instanceof IntegerValue) {
56                 lstart = ((IntegerValue)startVal).longValue();
57                 if (lstart <= 1) {
58                     return seq;
59                 }
60             } else {
61                 startVal = startVal.round();
62                 if (startVal.compareTo(IntegerValue.PLUS_ONE) <= 0) {
63                     return seq;
64                 } else if (startVal.compareTo(IntegerValue.MAX_LONG) > 0) {
65                     return EmptyIterator.getInstance();
66                 } else if (startVal.isNaN()) {
67                     return EmptyIterator.getInstance();
68                 } else {
69                     lstart = startVal.longValue();
70                 }
71             }
72
73             if (lstart > Integer.MAX_VALUE) {
74                 // we don't allow sequences longer than an this
75
return EmptyIterator.getInstance();
76             }
77
78             return new TailExpression.TailIterator(seq, (int)lstart);
79
80         } else {
81
82             // There are three arguments
83

84             AtomicValue lengthVal0 = (AtomicValue)argument[2].evaluateItem(context);
85             NumericValue lengthVal = (NumericValue)lengthVal0.getPrimitiveValue();
86
87             if (startVal instanceof IntegerValue && lengthVal instanceof IntegerValue) {
88                 long lstart = ((IntegerValue)startVal).longValue();
89                 if (lstart > Integer.MAX_VALUE) {
90                     return EmptyIterator.getInstance();
91                 }
92                 long llength = ((IntegerValue)lengthVal).longValue();
93                 if (llength > Integer.MAX_VALUE) {
94                     llength = Integer.MAX_VALUE;
95                 }
96                 if (llength < 1) {
97                     return EmptyIterator.getInstance();
98                 }
99                 long lend = lstart + llength - 1;
100                 if (lend < 1) {
101                     return EmptyIterator.getInstance();
102                 }
103                 int start = (lstart < 1 ? 1 : (int)lstart);
104                 return PositionIterator.make(seq, start, (int)lend);
105             } else {
106                 if (startVal.isNaN()) {
107                     return EmptyIterator.getInstance();
108                 }
109                 if (startVal.compareTo(IntegerValue.MAX_LONG) > 0) {
110                     return EmptyIterator.getInstance();
111                 }
112                 startVal = startVal.round();
113
114                 if (lengthVal.isNaN()) {
115                     return EmptyIterator.getInstance();
116                 }
117                 lengthVal = lengthVal.round();
118
119                 if (lengthVal.compareTo(IntegerValue.ZERO) <= 0) {
120                     return EmptyIterator.getInstance();
121                 }
122                 NumericValue rend = startVal
123                         .arithmetic(Token.PLUS, lengthVal, context)
124                         .arithmetic(Token.MINUS, IntegerValue.PLUS_ONE, context);
125                 if (rend.compareTo(IntegerValue.ZERO) <= 0) {
126                     return EmptyIterator.getInstance();
127                 }
128
129                 long lstart;
130                 if (startVal.compareTo(IntegerValue.PLUS_ONE) <= 0) {
131                     lstart = 1;
132                 } else {
133                     lstart = startVal.longValue();
134                 }
135                 if (lstart > Integer.MAX_VALUE) {
136                     return EmptyIterator.getInstance();
137                 }
138
139                 long lend;
140                 if (rend.compareTo(IntegerValue.MAX_LONG) >= 0) {
141                     lend = Integer.MAX_VALUE;
142                 } else {
143                     lend = rend.longValue();
144                 }
145                 return PositionIterator.make(seq, (int)lstart, (int)lend);
146
147             }
148         }
149     }
150
151 }
152
153 //
154
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
155
// you may not use this file except in compliance with the License. You may obtain a copy of the
156
// License at http://www.mozilla.org/MPL/
157
//
158
// Software distributed under the License is distributed on an "AS IS" basis,
159
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
160
// See the License for the specific language governing rights and limitations under the License.
161
//
162
// The Original Code is: all this file.
163
//
164
// The Initial Developer of the Original Code is Michael H. Kay.
165
//
166
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
167
//
168
// Contributor(s): none.
169
//
170
Popular Tags