KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > instruct > AnalyzeString


1 package net.sf.saxon.instruct;
2
3 import net.sf.saxon.expr.*;
4 import net.sf.saxon.functions.Matches;
5 import net.sf.saxon.om.Item;
6 import net.sf.saxon.om.NamePool;
7 import net.sf.saxon.pattern.NoNodeTest;
8 import net.sf.saxon.style.StandardNames;
9 import net.sf.saxon.trans.DynamicError;
10 import net.sf.saxon.trans.XPathException;
11 import net.sf.saxon.type.ItemType;
12 import net.sf.saxon.type.RegexTranslator;
13 import net.sf.saxon.type.Type;
14 import net.sf.saxon.type.SchemaType;
15 import net.sf.saxon.value.SequenceType;
16
17 import java.io.PrintStream JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.regex.Pattern JavaDoc;
21 import java.util.regex.PatternSyntaxException JavaDoc;
22
23 /**
24  * An xsl:analyze-string elements in the stylesheet. New at XSLT 2.0<BR>
25  */

26
27 public class AnalyzeString extends Instruction {
28
29     private Expression select;
30     private Expression regex;
31     private Expression flags;
32     private Expression matching;
33     private Expression nonMatching;
34     private Pattern JavaDoc pattern; // a regex pattern, not an XSLT pattern!
35

36     /**
37      * Construct an AnalyzeString instruction
38      *
39      * @param select the expression containing the input string
40      * @param regex the regular expression
41      * @param flags the flags parameter
42      * @param matching actions to be applied to a matching substring
43      * @param nonMatching actions to be applied to a non-matching substring
44      * @param pattern the compiled regular expression, if it was known statically
45      */

46     public AnalyzeString(Expression select,
47                          Expression regex,
48                          Expression flags,
49                          Expression matching,
50                          Expression nonMatching,
51                          Pattern JavaDoc pattern) {
52         this.select = select;
53         this.regex = regex;
54         this.flags = flags;
55         this.matching = matching;
56         this.nonMatching = nonMatching;
57         this.pattern = pattern;
58
59         Iterator JavaDoc kids = iterateSubExpressions();
60         while (kids.hasNext()) {
61             Expression child = (Expression)kids.next();
62             adoptChildExpression(child);
63         }
64
65     }
66
67     public int getInstructionNameCode() {
68         return StandardNames.XSL_ANALYZE_STRING;
69     }
70
71     /**
72      * Get the expression used to process matching substrings
73      */

74
75     public Expression getMatchingExpression() {
76         return matching;
77     }
78
79     /**
80      * Get the expression used to process non-matching substrings
81      */

82
83     public Expression getNonMatchingExpression() {
84         return nonMatching;
85     }
86
87
88     /**
89      * Simplify an expression. This performs any static optimization (by rewriting the expression
90      * as a different expression).
91      *
92      * @return the simplified expression
93      * @throws XPathException if an error is discovered during expression
94      * rewriting
95      */

96
97     public Expression simplify(StaticContext env) throws XPathException {
98         select = select.simplify(env);
99         regex = regex.simplify(env);
100         flags = flags.simplify(env);
101         if (matching != null) {
102             matching = matching.simplify(env);
103         }
104         if (nonMatching != null) {
105             nonMatching = nonMatching.simplify(env);
106         }
107         return this;
108     }
109
110     public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException {
111         select = select.typeCheck(env, contextItemType);
112         adoptChildExpression(select);
113         regex = regex.typeCheck(env, contextItemType);
114         adoptChildExpression(regex);
115         flags = flags.typeCheck(env, contextItemType);
116         adoptChildExpression(flags);
117         if (matching != null) {
118             matching = matching.typeCheck(env, Type.STRING_TYPE);
119             adoptChildExpression(matching);
120         }
121         if (nonMatching != null) {
122             nonMatching = nonMatching.typeCheck(env, Type.STRING_TYPE);
123             adoptChildExpression(nonMatching);
124         }
125         // Following type checking has already been done in the case of XSLT xsl:analyze-string, but is
126
// needed where the instruction is generated from saxon:analyze-string extension function
127
RoleLocator role =
128                 new RoleLocator(RoleLocator.INSTRUCTION, "analyze-string/select", 0, null);
129         role.setSourceLocator(this);
130         select = TypeChecker.staticTypeCheck(select, SequenceType.SINGLE_STRING, false, role, env);
131
132         role = new RoleLocator(RoleLocator.INSTRUCTION, "analyze-string/regex", 0, null);
133         role.setSourceLocator(this);
134         regex = TypeChecker.staticTypeCheck(regex, SequenceType.SINGLE_STRING, false, role, env);
135
136         role = new RoleLocator(RoleLocator.INSTRUCTION, "analyze-string/flags", 0, null);
137         role.setSourceLocator(this);
138         flags = TypeChecker.staticTypeCheck(flags, SequenceType.SINGLE_STRING, false, role, env);
139
140         return this;
141     }
142
143
144     public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException {
145         select = select.optimize(opt, env, contextItemType);
146         adoptChildExpression(select);
147         regex = regex.optimize(opt, env, contextItemType);
148         adoptChildExpression(regex);
149         flags = flags.optimize(opt, env, contextItemType);
150         adoptChildExpression(flags);
151         if (matching != null) {
152             matching = matching.optimize(opt, env, Type.STRING_TYPE);
153             adoptChildExpression(matching);
154         }
155         if (nonMatching != null) {
156             nonMatching = nonMatching.optimize(opt, env, Type.STRING_TYPE);
157             adoptChildExpression(nonMatching);
158         }
159         return this;
160     }
161
162     /**
163      * Check that any elements and attributes constructed or returned by this expression are acceptable
164      * in the content model of a given complex type. It's always OK to say yes, since the check will be
165      * repeated at run-time. The process of checking element and attribute constructors against the content
166      * model of a complex type also registers the type of content expected of those constructors, so the
167      * static validation can continue recursively.
168      */

169
170     public void checkPermittedContents(SchemaType parentType, StaticContext env, boolean whole) throws XPathException {
171         if (matching != null) {
172             matching.checkPermittedContents(parentType, env, false);
173         }
174         if (nonMatching != null) {
175             nonMatching.checkPermittedContents(parentType, env, false);
176         }
177     }
178
179     /**
180      * Get the item type of the items returned by evaluating this instruction
181      *
182      * @return the static item type of the instruction
183      */

184
185     public ItemType getItemType() {
186         if (matching != null) {
187             if (nonMatching != null) {
188                 return Type.getCommonSuperType(matching.getItemType(), nonMatching.getItemType());
189             } else {
190                 return matching.getItemType();
191             }
192         } else {
193             if (nonMatching != null) {
194                 return nonMatching.getItemType();
195             } else {
196                 return NoNodeTest.getInstance();
197             }
198         }
199     }
200
201     /**
202      * Compute the dependencies of an expression, as the union of the
203      * dependencies of its subexpressions. (This is overridden for path expressions
204      * and filter expressions, where the dependencies of a subexpression are not all
205      * propogated). This method should be called only once, to compute the dependencies;
206      * after that, getDependencies should be used.
207      *
208      * @return the depencies, as a bit-mask
209      */

210
211     public int computeDependencies() {
212         // some of the dependencies in the "action" part and in the grouping and sort keys aren't relevant,
213
// because they don't depend on values set outside the for-each-group expression
214
int dependencies = 0;
215         dependencies |= select.getDependencies();
216         dependencies |= regex.getDependencies();
217         dependencies |= flags.getDependencies();
218         if (matching != null) {
219             dependencies |= (matching.getDependencies() &~
220                     (StaticProperty.DEPENDS_ON_FOCUS | StaticProperty.DEPENDS_ON_REGEX_GROUP));
221         }
222         if (nonMatching != null) {
223             dependencies |= (nonMatching.getDependencies() &~
224                     (StaticProperty.DEPENDS_ON_FOCUS | StaticProperty.DEPENDS_ON_REGEX_GROUP));
225         }
226         return dependencies;
227     }
228
229     /**
230      * Handle promotion offers, that is, non-local tree rewrites.
231      *
232      * @param offer The type of rewrite being offered
233      * @throws XPathException
234      */

235
236     protected void promoteInst(PromotionOffer offer) throws XPathException {
237         select = doPromotion(select, offer);
238         regex = doPromotion(regex, offer);
239         flags = doPromotion(flags, offer);
240         if (matching != null) {
241             matching = doPromotion(matching, offer);
242         }
243         if (nonMatching != null) {
244             nonMatching = doPromotion(nonMatching, offer);
245         }
246     }
247
248     /**
249      * Get all the XPath expressions associated with this instruction
250      * (in XSLT terms, the expression present on attributes of the instruction,
251      * as distinct from the child instructions in a sequence construction)
252      */

253
254     public Iterator JavaDoc iterateSubExpressions() {
255         ArrayList JavaDoc list = new ArrayList JavaDoc(5);
256         list.add(select);
257         list.add(regex);
258         list.add(flags);
259         if (matching != null) {
260             list.add(matching);
261         }
262         if (nonMatching != null) {
263             list.add(nonMatching);
264         }
265         return list.iterator();
266     }
267
268     public TailCall processLeavingTail(XPathContext context) throws XPathException {
269         RegexIterator iter = getRegexIterator(context);
270         XPathContextMajor c2 = context.newContext();
271         c2.setOrigin(this);
272         c2.setCurrentIterator(iter);
273         c2.setCurrentRegexIterator(iter);
274
275         while (true) {
276             Item it = iter.next();
277             if (it == null) {
278                 break;
279             }
280             if (iter.isMatching()) {
281                 if (matching != null) {
282                     matching.process(c2);
283                 }
284             } else {
285                 if (nonMatching != null) {
286                     nonMatching.process(c2);
287                 }
288             }
289         }
290
291         return null;
292
293     }
294
295     /**
296      * Get an iterator over the substrings defined by the regular expression
297      *
298      * @param context the evaluation context
299      * @return an iterator that returns matching and nonmatching substrings
300      * @throws XPathException
301      */

302
303     private RegexIterator getRegexIterator(XPathContext context) throws XPathException {
304         String JavaDoc input = select.evaluateAsString(context);
305
306         Pattern JavaDoc re = pattern;
307         if (re == null) {
308             int jflags = Matches.setFlags(flags.evaluateAsString(context));
309             try {
310                 String JavaDoc javaRegex = RegexTranslator.translate(regex.evaluateAsString(context), true);
311                 re = Pattern.compile(javaRegex, jflags);
312             } catch (RegexTranslator.RegexSyntaxException err) {
313                 throw new DynamicError(err);
314             } catch (PatternSyntaxException JavaDoc err) {
315                 throw new DynamicError(err);
316             }
317         }
318
319         RegexIterator iter = new RegexIterator(input, re);
320         return iter;
321     }
322
323     // TODO: implement an iterate() method (as a MappingIterator).
324

325     /**
326      * Diagnostic print of expression structure. The expression is written to the System.err
327      * output stream
328      *
329      * @param level indentation level for this expression
330      * @param out
331      */

332
333     public void display(int level, NamePool pool, PrintStream JavaDoc out) {
334         out.println(ExpressionTool.indent(level) + "analyze-string");
335         out.println(ExpressionTool.indent(level) + "select = ");
336         select.display(level + 1, pool, out);
337         out.println(ExpressionTool.indent(level) + "regex = ");
338         regex.display(level + 1, pool, out);
339         out.println(ExpressionTool.indent(level) + "flags = ");
340         flags.display(level + 1, pool, out);
341         if (matching != null) {
342             out.println(ExpressionTool.indent(level) + "matching = ");
343             matching.display(level + 1, pool, out);
344         }
345         if (nonMatching != null) {
346             out.println(ExpressionTool.indent(level) + "non-matching = ");
347             nonMatching.display(level + 1, pool, out);
348         }
349     }
350 }
351
352 //
353
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
354
// you may not use this file except in compliance with the License. You may obtain a copy of the
355
// License at http://www.mozilla.org/MPL/
356
//
357
// Software distributed under the License is distributed on an "AS IS" basis,
358
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
359
// See the License for the specific language governing rights and limitations under the License.
360
//
361
// The Original Code is: all this file.
362
//
363
// The Initial Developer of the Original Code is Michael H. Kay
364
//
365
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
366
//
367
// Contributor(s):
368
// Portions marked "e.g." are from Edwin Glaser (edwin@pannenleiter.de)
369
//
370
Popular Tags