KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sf.saxon.functions;
2 import net.sf.saxon.expr.Expression;
3 import net.sf.saxon.expr.StaticContext;
4 import net.sf.saxon.expr.XPathContext;
5 import net.sf.saxon.om.Item;
6 import net.sf.saxon.trans.DynamicError;
7 import net.sf.saxon.trans.StaticError;
8 import net.sf.saxon.trans.XPathException;
9 import net.sf.saxon.type.RegexTranslator;
10 import net.sf.saxon.value.AtomicValue;
11 import net.sf.saxon.value.BooleanValue;
12 import net.sf.saxon.value.StringValue;
13 import net.sf.saxon.value.Value;
14
15 import java.util.regex.Pattern JavaDoc;
16 import java.util.regex.PatternSyntaxException JavaDoc;
17
18
19 /**
20 * This class implements the matches() function for regular expression matching
21 */

22
23 public class Matches extends SystemFunction {
24
25     private Pattern JavaDoc regexp;
26
27     /**
28     * Simplify and validate.
29     * This is a pure function so it can be simplified in advance if the arguments are known
30     * @return the simplified expression
31     * @throws net.sf.saxon.trans.StaticError if any error is found (e.g. invalid regular expression)
32     */

33
34      public Expression simplify(StaticContext env) throws XPathException {
35         Expression e = simplifyArguments(env);
36
37         // compile the regular expression once if possible
38
if (!(e instanceof Value)) {
39             regexp = Matches.tryToCompile(argument, 1, 2);
40         }
41
42         return e;
43     }
44
45     /**
46      * Set the Java flags from the supplied XPath flags.
47      * @param inFlags the flags as a string, e.g. "im"
48      * @return the flags as a bit-significant integer
49      * @throws net.sf.saxon.trans.StaticError if the supplied value is invalid
50      */

51
52     public static int setFlags(CharSequence JavaDoc inFlags) throws StaticError {
53         int flags = Pattern.UNIX_LINES;
54         for (int i=0; i<inFlags.length(); i++) {
55             char c = inFlags.charAt(i);
56             switch (c) {
57                 case 'm':
58                     flags |= Pattern.MULTILINE;
59                     break;
60                 case 'i':
61                     flags |= Pattern.CASE_INSENSITIVE;
62                     break;
63                 case 's':
64                     flags |= Pattern.DOTALL;
65                     break;
66                 case 'x':
67                     flags |= Pattern.COMMENTS; // note, this enables comments as well as whitespace
68
break;
69                 default:
70                     StaticError err = new StaticError("Invalid character '" + c + "' in regular expression flags");
71                     err.setErrorCode("FORX0001");
72                     throw err;
73             }
74         }
75         return flags;
76     }
77
78     /**
79      * Try to precompile the arguments to the function. This method is shared by
80      * the implementations of the three XPath functions matches(), replace(), and
81      * tokenize().
82      * @param args the supplied arguments to the function, as an array
83      * @param patternArg the position of the argument containing the regular expression
84      * @param flagsArg the position of the argument containing the flags
85      * @return the compiled regular expression, or null indicating that the information
86      * is not available statically so it cannot be precompiled
87      * @throws net.sf.saxon.trans.StaticError if any failure occurs, in particular, if the regular
88      * expression is invalid
89      */

90
91     protected static Pattern JavaDoc tryToCompile(Expression[] args, int patternArg, int flagsArg)
92     throws StaticError {
93         if (patternArg > args.length - 1) {
94             // too few arguments were supplied; the error will be reported in due course
95
return null;
96         }
97         CharSequence JavaDoc flagstr = null;
98         if (args.length-1 < flagsArg) {
99             flagstr = "";
100         } else if (args[flagsArg] instanceof StringValue) {
101             flagstr = ((StringValue)args[flagsArg]).getStringValueCS();
102         }
103
104         if (args[patternArg] instanceof StringValue && flagstr != null) {
105             int flags = Matches.setFlags(flagstr);
106
107             try {
108                 String JavaDoc javaRegex = RegexTranslator.translate(
109                         ((StringValue)args[patternArg]).getStringValueCS(), true);
110                 return Pattern.compile(javaRegex, flags);
111             } catch (RegexTranslator.RegexSyntaxException err) {
112                 StaticError e2 = new StaticError(err.getMessage());
113                 e2.setErrorCode("FORX0002");
114                 throw e2;
115             } catch (PatternSyntaxException JavaDoc err) {
116                 StaticError e2 = new StaticError(err.getMessage());
117                 e2.setErrorCode("FORX0002");
118                 throw e2;
119             }
120         } else {
121             return null;
122         }
123     }
124
125     /**
126      * Evaluate the matches() function to give a Boolean value.
127      * @param c The dynamic evaluation context
128      * @return the result as a BooleanValue, or null to indicate the empty sequence
129      * @throws XPathException on an error
130      */

131
132     public Item evaluateItem(XPathContext c) throws XPathException {
133         AtomicValue sv0 = (AtomicValue)argument[0].evaluateItem(c);
134         if (sv0==null) {
135             sv0 = StringValue.EMPTY_STRING;
136         };
137
138         Pattern JavaDoc re = regexp;
139         if (re == null) {
140
141             AtomicValue pat = (AtomicValue)argument[1].evaluateItem(c);
142             if (pat==null) return null;
143
144             CharSequence JavaDoc flags;
145             if (argument.length==2) {
146                 flags = "";
147             } else {
148                 AtomicValue sv2 = (AtomicValue)argument[2].evaluateItem(c);
149                 if (sv2==null) return null;
150                 flags = sv2.getStringValueCS();
151             }
152
153             try {
154                 String JavaDoc javaRegex = RegexTranslator.translate(pat.getStringValueCS(), true);
155                 re = Pattern.compile(javaRegex, setFlags(flags));
156             } catch (RegexTranslator.RegexSyntaxException err) {
157                 DynamicError de = new DynamicError(err);
158                 de.setErrorCode("FORX0002");
159                 de.setXPathContext(c);
160                 throw de;
161             } catch (PatternSyntaxException JavaDoc err) {
162                 DynamicError de = new DynamicError(err);
163                 de.setErrorCode("FORX0002");
164                 de.setXPathContext(c);
165                 throw de;
166             } catch (StaticError serr) {
167                 dynamicError(serr.getMessage(), serr.getErrorCodeLocalPart(), c);
168             }
169         }
170         return BooleanValue.get(re.matcher(sv0.getStringValueCS()).find());
171     }
172
173 }
174
175
176
177 //
178
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
179
// you may not use this file except in compliance with the License. You may obtain a copy of the
180
// License at http://www.mozilla.org/MPL/
181
//
182
// Software distributed under the License is distributed on an "AS IS" basis,
183
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
184
// See the License for the specific language governing rights and limitations under the License.
185
//
186
// The Original Code is: all this file.
187
//
188
// The Initial Developer of the Original Code is Michael H. Kay
189
//
190
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
191
//
192
// Contributor(s): none.
193
//
194
Popular Tags