001: package net.sf.saxon.pattern;
002:
003: import net.sf.saxon.expr.*;
004: import net.sf.saxon.instruct.Executable;
005: import net.sf.saxon.om.NodeInfo;
006: import net.sf.saxon.trans.XPathException;
007: import net.sf.saxon.type.ItemType;
008: import net.sf.saxon.type.Type;
009: import net.sf.saxon.event.LocationProvider;
010:
011: import java.io.Serializable;
012: import java.util.Iterator;
013: import java.util.Collections;
014:
015: /**
016: * A Pattern represents the result of parsing an XSLT pattern string. <br>
017: * Patterns are created by calling the static method Pattern.make(string). <br>
018: * The pattern is used to test a particular node by calling match().
019: */
020:
021: public abstract class Pattern implements Serializable, Container {
022:
023: private String originalText;
024: private Executable executable;
025: private String systemId; // the module where the pattern occurred
026: private int lineNumber; // the line number where the pattern occurred
027:
028: /**
029: * Static method to make a Pattern by parsing a String. <br>
030: * @param pattern The pattern text as a String
031: * @param env An object defining the compile-time context for the expression
032: * @return The pattern object
033: */
034:
035: public static Pattern make(String pattern, StaticContext env,
036: Executable exec) throws XPathException {
037:
038: Pattern pat = (new ExpressionParser()).parsePattern(pattern,
039: env);
040: pat.setSystemId(env.getSystemId());
041: pat.setLineNumber(env.getLineNumber());
042: // System.err.println("Simplified [" + pattern + "] to " + pat.getClass() + " default prio = " + pat.getDefaultPriority());
043: // set the pattern text for use in diagnostics
044: pat.setOriginalText(pattern);
045: pat.setExecutable(exec);
046: pat = pat.simplify(env);
047: return pat;
048: }
049:
050: public Executable getExecutable() {
051: return executable;
052: }
053:
054: public void setExecutable(Executable executable) {
055: this .executable = executable;
056: }
057:
058: /**
059: * Get the LocationProvider allowing location identifiers to be resolved.
060: */
061:
062: public LocationProvider getLocationProvider() {
063: return executable.getLocationMap();
064: }
065:
066: /**
067: * Set the original text of the pattern for use in diagnostics
068: */
069:
070: public void setOriginalText(String text) {
071: originalText = text;
072: }
073:
074: /**
075: * Simplify the pattern by applying any context-independent optimisations.
076: * Default implementation does nothing.
077: * @return the optimised Pattern
078: */
079:
080: public Pattern simplify(StaticContext env) throws XPathException {
081: return this ;
082: }
083:
084: /**
085: * Type-check the pattern.
086: * Default implementation does nothing. This is only needed for patterns that contain
087: * variable references or function calls.
088: * @return the optimised Pattern
089: */
090:
091: public Pattern analyze(StaticContext env, ItemType contextItemType)
092: throws XPathException {
093: return this ;
094: }
095:
096: /**
097: * Get the dependencies of the pattern. The only possible dependency for a pattern is
098: * on local variables. This is analyzed in those patterns where local variables may appear.
099: */
100:
101: public int getDependencies() {
102: return 0;
103: }
104:
105: /**
106: * Iterate over the subexpressions within this pattern
107: */
108:
109: public Iterator iterateSubExpressions() {
110: return Collections.EMPTY_LIST.iterator();
111: }
112:
113: /**
114: * Offer promotion for subexpressions within this pattern. The offer will be accepted if the subexpression
115: * is not dependent on the factors (e.g. the context item) identified in the PromotionOffer.
116: * By default the offer is not accepted - this is appropriate in the case of simple expressions
117: * such as constant values and variable references where promotion would give no performance
118: * advantage. This method is always called at compile time.
119: *
120: * <p>Unlike the corresponding method on {@link Expression}, this method does not return anything:
121: * it can make internal changes to the pattern, but cannot return a different pattern. Only certain
122: * kinds of promotion are applicable within a pattern: specifically, promotions affecting local
123: * variable references within the pattern.
124: *
125: * @param offer details of the offer, for example the offer to move
126: * expressions that don't depend on the context to an outer level in
127: * the containing expression
128: * @throws net.sf.saxon.trans.XPathException
129: * if any error is detected
130: */
131:
132: public void promote(PromotionOffer offer) throws XPathException {
133: // default implementation does nothing
134: }
135:
136: /**
137: * Set the system ID where the pattern occurred
138: */
139:
140: public void setSystemId(String systemId) {
141: this .systemId = systemId;
142: }
143:
144: /**
145: * Set the line number where the pattern occurred
146: */
147:
148: public void setLineNumber(int lineNumber) {
149: this .lineNumber = lineNumber;
150: }
151:
152: /**
153: * Determine whether this Pattern matches the given Node. This is the main external interface
154: * for matching patterns: it sets current() to the node being tested
155: * @param node The NodeInfo representing the Element or other node to be tested against the Pattern
156: * @param context The dynamic context. Only relevant if the pattern
157: * uses variables, or contains calls on functions such as document() or key().
158: * @return true if the node matches the Pattern, false otherwise
159: */
160:
161: public abstract boolean matches(NodeInfo node, XPathContext context)
162: throws XPathException;
163:
164: /**
165: * Determine whether this Pattern matches the given Node. This is an internal interface used
166: * for matching sub-patterns; it does not alter the value of current(). The default implementation
167: * is identical to matches().
168: * @param node The NodeInfo representing the Element or other node to be tested against the Pattern
169: * @param context The dynamic context. Only relevant if the pattern
170: * uses variables, or contains calls on functions such as document() or key().
171: * @return true if the node matches the Pattern, false otherwise
172: */
173:
174: protected boolean internalMatches(NodeInfo node,
175: XPathContext context) throws XPathException {
176: return matches(node, context);
177: }
178:
179: /**
180: * Determine the types of nodes to which this pattern applies. Used for optimisation.
181: * For patterns that match nodes of several types, return Type.NODE
182: * @return the type of node matched by this pattern. e.g. Type.ELEMENT or Type.TEXT
183: */
184:
185: public int getNodeKind() {
186: return Type.NODE;
187: }
188:
189: /**
190: * Determine the name fingerprint of nodes to which this pattern applies. Used for
191: * optimisation.
192: * @return A fingerprint that the nodes must match, or -1 if it can match multiple fingerprints
193: */
194:
195: public int getFingerprint() {
196: return -1;
197: }
198:
199: /**
200: * Get a NodeTest that all the nodes matching this pattern must satisfy
201: */
202:
203: public abstract NodeTest getNodeTest();
204:
205: /**
206: * Determine the default priority to use if this pattern appears as a match pattern
207: * for a template with no explicit priority attribute.
208: */
209:
210: public double getDefaultPriority() {
211: return 0.5;
212: }
213:
214: /**
215: * Get the system id of the entity in which the pattern occurred
216: */
217:
218: public String getSystemId() {
219: return systemId;
220: }
221:
222: /**
223: * Get the line number on which the pattern was defined
224: */
225:
226: public int getLineNumber() {
227: return lineNumber;
228: }
229:
230: /**
231: * Get the column number (always -1)
232: */
233:
234: public int getColumnNumber() {
235: return -1;
236: }
237:
238: /**
239: * Get the public ID (always null)
240: */
241:
242: public String getPublicId() {
243: return null;
244: }
245:
246: /**
247: * Get the original pattern text
248: */
249:
250: public String toString() {
251: return originalText;
252: }
253:
254: }
255:
256: //
257: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
258: // you may not use this file except in compliance with the License. You may obtain a copy of the
259: // License at http://www.mozilla.org/MPL/
260: //
261: // Software distributed under the License is distributed on an "AS IS" basis,
262: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
263: // See the License for the specific language governing rights and limitations under the License.
264: //
265: // The Original Code is: all this file.
266: //
267: // The Initial Developer of the Original Code is Michael H. Kay.
268: //
269: // Contributor(s): Michael Kay
270: //
|