KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sf.saxon.functions;
2 import net.sf.saxon.expr.XPathContext;
3 import net.sf.saxon.om.Item;
4 import net.sf.saxon.sort.CodepointCollator;
5 import net.sf.saxon.trans.XPathException;
6 import net.sf.saxon.value.AtomicValue;
7 import net.sf.saxon.value.BooleanValue;
8 import net.sf.saxon.value.StringValue;
9
10 import java.text.CollationElementIterator JavaDoc;
11 import java.text.RuleBasedCollator JavaDoc;
12 import java.util.Comparator JavaDoc;
13
14
15 /**
16 * This class implements the contains(), starts-with(), ends-with(),
17 * substring-before(), and substring-after() functions
18 */

19
20 public class Contains extends CollatingFunction {
21
22     public static final int CONTAINS = 0;
23     public static final int STARTSWITH = 1;
24     public static final int ENDSWITH = 2;
25     public static final int AFTER = 3;
26     public static final int BEFORE = 4;
27
28     /**
29     * Evaluate the function
30     */

31
32     public Item evaluateItem(XPathContext context) throws XPathException {
33
34         Comparator JavaDoc collator = getCollator(2, context, false);
35
36         AtomicValue arg0 = (AtomicValue)argument[0].evaluateItem(context);
37         if (arg0==null) {
38             arg0 = StringValue.EMPTY_STRING;
39         }
40
41         AtomicValue arg1 = (AtomicValue)argument[1].evaluateItem(context);
42         if (arg1==null) {
43             arg1 = StringValue.EMPTY_STRING;
44         };
45
46         String JavaDoc s0 = arg0.getStringValue();
47         String JavaDoc s1 = arg1.getStringValue();
48
49         if (collator instanceof CodepointCollator) {
50             // Using unicode code-point matching: use the Java string-matching routines directly
51
switch(operation) {
52                 case CONTAINS:
53                     return BooleanValue.get(s0.indexOf(s1) >= 0);
54                 case STARTSWITH:
55                     return BooleanValue.get(s0.startsWith(s1));
56                 case ENDSWITH:
57                     return BooleanValue.get(s0.endsWith(s1));
58                 case AFTER:
59                     int i = s0.indexOf(s1);
60                     if (i<0) return StringValue.EMPTY_STRING;
61                     return StringValue.makeStringValue(s0.substring(i+s1.length()));
62                 case BEFORE:
63                     int j = s0.indexOf(s1);
64                     if (j<0) return StringValue.EMPTY_STRING;
65                     return StringValue.makeStringValue(s0.substring(0, j));
66                 default:
67                     throw new UnsupportedOperationException JavaDoc("Unknown operation " + operation);
68             }
69         } else {
70
71             if (!(collator instanceof RuleBasedCollator JavaDoc)) {
72                 dynamicError("The collation for " + getDisplayName(context.getController().getNamePool()) +
73                         " must be a RuleBaseCollator", context);
74                 return null;
75             }
76             RuleBasedCollator JavaDoc rbc = (RuleBasedCollator JavaDoc)collator;
77             CollationElementIterator JavaDoc iter0 = rbc.getCollationElementIterator(s0);
78             CollationElementIterator JavaDoc iter1 = rbc.getCollationElementIterator(s1);
79
80             switch (operation) {
81                 case STARTSWITH:
82                     return BooleanValue.get( collationStartsWith(iter0, iter1) );
83                 case CONTAINS:
84                 case ENDSWITH:
85                     return BooleanValue.get( collationContains(iter0, iter1, null) );
86                 case AFTER:
87                     int[] ia = new int[2];
88                     boolean ba = collationContains(iter0, iter1, ia);
89                     if (ba) {
90                         return StringValue.makeStringValue(s0.substring(ia[1]));
91                     } else {
92                         return StringValue.EMPTY_STRING;
93                     }
94                 case BEFORE:
95                     int[] ib = new int[2];
96                     boolean bb = collationContains(iter0, iter1, ib);
97                     if (bb) {
98                         return StringValue.makeStringValue(s0.substring(0, ib[0]));
99                     } else {
100                         return StringValue.EMPTY_STRING;
101                     }
102                 default:
103                     throw new UnsupportedOperationException JavaDoc("Unknown operation " + operation);
104             }
105         }
106     }
107
108     /**
109     * Determine whether one string starts with another, under the terms of a given
110     * collating sequence.
111     * @param s0 iterator over the collation elements of the containing string
112     * @param s1 iterator over the collation elements of the contained string
113     */

114
115     private boolean collationStartsWith(CollationElementIterator JavaDoc s0,
116                                         CollationElementIterator JavaDoc s1) {
117         while (true) {
118             int e1 = s1.next();
119             if (e1 == -1) {
120                 return true;
121             }
122             int e0 = s0.next();
123             if (e0 != e1) {
124                 return false;
125             }
126         }
127     }
128
129     /**
130     * Determine whether one string contains another, under the terms of a given
131     * collating sequence. If operation=ENDSWITH, the match must be at the end of the first
132     * string.
133     * @param s0 iterator over the collation elements of the containing string
134     * @param s1 iterator over the collation elements of the contained string
135     * @param offsets may be null, but if it is supplied, it must be an array of two
136     * integers which, if the function returns true, will contain the start position of the
137     * first matching substring, and the offset of the first character after the first
138     * matching substring. This is not available for operation=endswith
139     * @return true if the first string contains the second
140     */

141
142     private boolean collationContains(CollationElementIterator JavaDoc s0,
143                                       CollationElementIterator JavaDoc s1,
144                                       int[] offsets ) {
145         int e1 = s1.next();
146         if (e1 == -1) {
147             return true;
148         }
149         int e0 = -1;
150         while (true) {
151             // scan the first string to find a matching character
152
while (e0 != e1) {
153                 e0 = s0.next();
154                 if (e0 == -1) {
155                     // hit the end, no match
156
return false;
157                 }
158             }
159             // matched first character, note the position of the possible match
160
int start = s0.getOffset();
161             if (collationStartsWith(s0, s1)) {
162                 if (operation == ENDSWITH) {
163                     if (s0.next() == -1) {
164                         // the match is at the end
165
return true;
166                     }
167                     // else ignore this match and keep looking
168
} else {
169                     if (offsets != null) {
170                         offsets[0] = start-1;
171                         offsets[1] = s0.getOffset();
172                     }
173                     return true;
174                 }
175             }
176             // reset the position and try again
177
s0.setOffset(start);
178
179             // workaround for a difference between JDK 1.4.0 and JDK 1.4.1
180
if (s0.getOffset() != start) {
181                 // JDK 1.4.0 takes this path
182
s0.next();
183             }
184             s1.reset();
185             e0 = -1;
186             e1 = s1.next();
187             // loop round to try again
188
}
189     }
190
191
192 }
193
194
195
196 //
197
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
198
// you may not use this file except in compliance with the License. You may obtain a copy of the
199
// License at http://www.mozilla.org/MPL/
200
//
201
// Software distributed under the License is distributed on an "AS IS" basis,
202
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
203
// See the License for the specific language governing rights and limitations under the License.
204
//
205
// The Original Code is: all this file.
206
//
207
// The Initial Developer of the Original Code is Michael H. Kay.
208
//
209
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
210
//
211
// Contributor(s): none.
212
//
213
Popular Tags