001: package net.sf.saxon.trans;
002:
003: import net.sf.saxon.expr.XPathContext;
004: import net.sf.saxon.instruct.Template;
005: import net.sf.saxon.om.NodeInfo;
006: import net.sf.saxon.pattern.Pattern;
007: import net.sf.saxon.pattern.UnionPattern;
008:
009: import java.io.Serializable;
010: import java.util.HashMap;
011: import java.util.Iterator;
012:
013: /**
014: * <B>RuleManager</B> maintains a set of template rules, one set for each mode
015: * @version 10 December 1999: carved out of the old Controller class
016: * @author Michael H. Kay
017: */
018:
019: public class RuleManager implements Serializable {
020:
021: private Mode defaultMode; // node handlers with default mode
022: private HashMap modes; // tables of node handlers for non-default modes
023: private Mode omniMode = null; // node handlers that specify mode="all"
024:
025: /**
026: * create a RuleManager and initialise variables.
027: */
028:
029: public RuleManager() {
030: resetHandlers();
031: }
032:
033: /**
034: * Set up a new table of handlers.
035: */
036:
037: public void resetHandlers() {
038: defaultMode = new Mode(Mode.DEFAULT_MODE);
039: modes = new HashMap(5);
040: }
041:
042: /**
043: * Get the Mode object for a named mode. If there is not one already registered.
044: * a new Mode is created.
045: * @param modeNameCode The name code of the mode. Supply Mode.DEFAULT_MODE to get the default
046: * mode or Mode.ALL_MODES to get the Mode object containing "mode=all" rules
047: * @return the Mode with this name
048: */
049:
050: public Mode getMode(int modeNameCode) {
051: if (modeNameCode == Mode.DEFAULT_MODE) {
052: return defaultMode;
053: }
054: if (modeNameCode == Mode.ALL_MODES) {
055: if (omniMode == null) {
056: omniMode = new Mode(Mode.NAMED_MODE);
057: }
058: return omniMode;
059: }
060: Integer modekey = new Integer(modeNameCode & 0xfffff);
061: Mode m = (Mode) modes.get(modekey);
062: if (m == null) {
063: m = new Mode(omniMode);
064: modes.put(modekey, m);
065: // when creating a specific mode, copy all the rules currently held
066: // in the omniMode, as these apply to all modes
067: }
068: return m;
069: }
070:
071: /**
072: * Register a handler for a particular pattern. The priority of the rule
073: * is the default priority for the pattern, which depends on the syntax of
074: * the pattern suppllied.
075: * @param pattern A match pattern
076: * @param eh The ElementHandler to be used
077: * @param mode The processing mode
078: * @param precedence The import precedence (use 0 by default)
079: */
080:
081: public void setHandler(Pattern pattern, Template eh, Mode mode,
082: int precedence) {
083: // for a union pattern, register the parts separately (each with its own priority)
084: if (pattern instanceof UnionPattern) {
085: UnionPattern up = (UnionPattern) pattern;
086: Pattern p1 = up.getLHS();
087: Pattern p2 = up.getRHS();
088: setHandler(p1, eh, mode, precedence);
089: setHandler(p2, eh, mode, precedence);
090: return;
091: }
092:
093: double priority = pattern.getDefaultPriority();
094: setHandler(pattern, eh, mode, precedence, priority);
095: }
096:
097: /**
098: * Register a handler for a particular pattern.
099: * @param pattern Must be a valid Pattern.
100: * @param eh The Template to be used
101: * @param mode The processing mode to which this element handler applies
102: * @param precedence The import precedence of this rule
103: * @param priority The priority of the rule: if an element matches several patterns, the
104: * one with highest priority is used
105: * @see Pattern
106: */
107:
108: public void setHandler(Pattern pattern, Template eh, Mode mode,
109: int precedence, double priority) {
110:
111: // for a union pattern, register the parts separately
112: if (pattern instanceof UnionPattern) {
113: UnionPattern up = (UnionPattern) pattern;
114: Pattern p1 = up.getLHS();
115: Pattern p2 = up.getRHS();
116: setHandler(p1, eh, mode, precedence, priority);
117: setHandler(p2, eh, mode, precedence, priority);
118: return;
119: }
120: mode.addRule(pattern, eh, precedence, priority);
121:
122: // if adding a rule to the omniMode (mode='all') add it to all
123: // the other modes as well
124: if (mode == omniMode) {
125: defaultMode.addRule(pattern, eh, precedence, priority);
126: Iterator iter = modes.values().iterator();
127: while (iter.hasNext()) {
128: Mode m = (Mode) iter.next();
129: m.addRule(pattern, eh, precedence, priority);
130: }
131: }
132: }
133:
134: /**
135: * Find the template rule registered for a particular node in a specific mode.
136: * @param node The NodeInfo for the relevant node
137: * @param mode The processing mode
138: * @param c The controller for this transformation
139: * @return The template rule that will process this node
140: * Returns null if there is no specific handler registered.
141: */
142:
143: public Template getTemplateRule(NodeInfo node, Mode mode,
144: XPathContext c) throws XPathException {
145:
146: if (mode == null) {
147: mode = defaultMode;
148: }
149:
150: return (Template) mode.getRule(node, c);
151: }
152:
153: /**
154: * Get a template rule whose import precedence is in a particular range. This is used to support
155: * the xsl:apply-imports function
156: * @param node The node to be matched
157: * @param mode The mode for which a rule is required
158: * @param min The minimum import precedence that the rule must have
159: * @param max The maximum import precedence that the rule must have
160: * @param c The Controller for the transformation
161: * @return The template rule to be invoked
162: * @throws XPathException
163: */
164:
165: public Template getTemplateRule(NodeInfo node, Mode mode, int min,
166: int max, XPathContext c) throws XPathException {
167: if (mode == null) {
168: mode = defaultMode;
169: }
170: return (Template) mode.getRule(node, min, max, c);
171: }
172:
173: /**
174: * Get the next-match handler after the current one
175: * @param node The node to be matched
176: * @param mode The processing mode
177: * @param currentHandler The current template rule
178: * @param c The dynamic context for the transformation
179: * @return The template rule to be executed
180: * @throws XPathException
181: */
182:
183: public Template getNextMatchHandler(NodeInfo node, Mode mode,
184: Template currentHandler, XPathContext c)
185: throws XPathException {
186: if (mode == null) {
187: mode = defaultMode;
188: }
189: return (Template) mode
190: .getNextMatchRule(node, currentHandler, c);
191: }
192: }
193:
194: //
195: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
196: // you may not use this file except in compliance with the License. You may obtain a copy of the
197: // License at http://www.mozilla.org/MPL/
198: //
199: // Software distributed under the License is distributed on an "AS IS" basis,
200: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
201: // See the License for the specific language governing rights and limitations under the License.
202: //
203: // The Original Code is: all this file.
204: //
205: // The Initial Developer of the Original Code is Michael H. Kay.
206: //
207: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
208: //
209: // Contributor(s): none.
210: //
|