Package client.net.sf.saxon.ce.trans

Source Code of client.net.sf.saxon.ce.trans.RuleManager

package client.net.sf.saxon.ce.trans;

import client.net.sf.saxon.ce.expr.Expression;
import client.net.sf.saxon.ce.expr.Token;
import client.net.sf.saxon.ce.expr.XPathContext;
import client.net.sf.saxon.ce.expr.instruct.Template;
import client.net.sf.saxon.ce.om.NodeInfo;
import client.net.sf.saxon.ce.om.StructuredQName;
import client.net.sf.saxon.ce.pattern.*;
import client.net.sf.saxon.ce.style.StylesheetModule;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

/**
  * <B>RuleManager</B> maintains a set of template rules, one set for each mode
  * @version 10 December 1999: carved out of the old Controller class
  * @author Michael H. Kay
  */

public final class RuleManager  {

    private Mode unnamedMode;           // node handlers with default mode
    private HashMap<StructuredQName, Mode> modes;
                                        // tables of node handlers for non-default modes
    private Mode omniMode = null;       // node handlers that specify mode="all"
    private int recoveryPolicy;

    /**
    * create a RuleManager and initialise variables.
    */

    public RuleManager() {
        resetHandlers();
    }

    /**
     * Set the policy for handling recoverable errrors. Note that for some errors the decision can be
     * made at run-time, but for the "ambiguous template match" error, the decision is (since 9.2)
     * fixed at compile time.
     * @param policy the recovery policy to be used. The options are {@link client.net.sf.saxon.ce.Configuration#RECOVER_SILENTLY},
     * {@link client.net.sf.saxon.ce.Configuration#RECOVER_WITH_WARNINGS}, or {@link client.net.sf.saxon.ce.Configuration#DO_NOT_RECOVER}.
     * @since 9.2
     */

    public void setRecoveryPolicy(int policy) {
        recoveryPolicy = policy;
        unnamedMode.setRecoveryPolicy(policy);
    }

    /**
     * Get the policy for handling recoverable errors. Note that for some errors the decision can be
     * made at run-time, but for the "ambiguous template match" error, the decision is (since 9.2)
     * fixed at compile time.
     *
     * @return the current policy.
     * @since 9.2
     */

    public int getRecoveryPolicy() {
        return recoveryPolicy;
    }

    /**
    * Set up a new table of handlers.
    */

    public void resetHandlers() {
        unnamedMode = new Mode(Mode.UNNAMED_MODE, Mode.UNNAMED_MODE_NAME);
        unnamedMode.setRecoveryPolicy(recoveryPolicy);
        modes = new HashMap<StructuredQName, Mode>(5);
    }

    /**
     * Get the mode object for the unnamed mode
     */

    public Mode getUnnamedMode() {
        return unnamedMode;
    }

    /**
     * Get the Mode object for a named mode. If there is not one already registered.
     * a new Mode is created.
     * @param modeName The name of the mode. Supply null to get the default
     * mode or Mode.ALL_MODES to get the Mode object containing "mode=all" rules
     * @param createIfAbsent if true, then if the mode does not already exist it will be created.
     * If false, then if the mode does not already exist the method returns null.
     * @return the Mode with this name
     */

    public Mode getMode(StructuredQName modeName, boolean createIfAbsent) {
        if (modeName == null || modeName.equals(Mode.UNNAMED_MODE_NAME)) {
            return unnamedMode;
        }
        if (modeName.equals(Mode.ALL_MODES)) {
            if (omniMode==null) {
                omniMode = new Mode(Mode.NAMED_MODE, modeName);
                omniMode.setRecoveryPolicy(recoveryPolicy);
            }
            return omniMode;
        }
        //Integer modekey = new Integer(modeNameCode & 0xfffff);
        Mode m = modes.get(modeName);
        if (m == null && createIfAbsent) {
            m = new Mode(omniMode, modeName);
            m.setRecoveryPolicy(recoveryPolicy);
            modes.put(modeName, m);
            // when creating a specific mode, copy all the rules currently held
            // in the omniMode, as these apply to all modes
        }
        return m;
    }

    /**
     * Get all the modes in a given namespace
     * @param namespace the namespace URI
     * @return a list of modes whose names are in this namespace
     */

    public List<Mode> getModesInNamespace(String namespace) {
        List<Mode> result = new ArrayList<Mode>();
        for (StructuredQName name : modes.keySet()) {
            if (namespace.equals(name.getNamespaceURI())) {
                result.add(modes.get(name));
            }
        }
        return result;
    }

    /**
      * Register a template rule for a particular pattern. The priority of the rule
      * is the default priority for the pattern, which depends on the syntax of
      * the pattern suppllied.
      * @param pattern A match pattern
      * @param eh The Template to be used
      * @param mode The processing mode
      * @param module The stylesheet module containing the template rule
      */

//    public void setTemplateRule(Pattern pattern, Template eh, Mode mode, StylesheetModule module) {
//        // for a union pattern, register the parts separately (each with its own priority)
//        if (pattern instanceof UnionPattern) {
//            UnionPattern up = (UnionPattern)pattern;
//            Pattern p1 = up.getLHS();
//            Pattern p2 = up.getRHS();
//            setTemplateRule(p1, eh, mode, module);
//            setTemplateRule(p2, eh, mode, module);
//            return;
//        }
//
//        double priority = pattern.getDefaultPriority();
//        setTemplateRule(pattern, eh, mode, module, priority);
//    }


    /**
      * Register a template for a particular pattern.
      * @param pattern Must be a valid Pattern.
      * @param eh The Template to be used
      * @param mode The processing mode to which this template applies
      * @param module The stylesheet module containing the template rule
      * @param priority The priority of the rule: if an element matches several patterns, the
      * one with highest priority is used
      * @see Pattern
      */

    public void setTemplateRule(Pattern pattern, Template eh, Mode mode, StylesheetModule module,
        double priority, boolean ixslPreventDefault, String ixslEventProperty) {

        // for a union pattern, register the parts separately
        // Note: technically this is only necessary if using default priorities and if the priorities
        // of the two halves are different. However, splitting increases the chance that the pattern
        // can be matched by hashing on the element name, so we do it always
        if (pattern instanceof UnionPattern) {
            UnionPattern up = (UnionPattern)pattern;
            Pattern p1 = up.getLHS();
            Pattern p2 = up.getRHS();
            Expression currentSetter = up.getVariableBindingExpression();
            if (currentSetter != null) {
                p1.setVariableBindingExpression(currentSetter);
                p2.setVariableBindingExpression(currentSetter);
            }
            setTemplateRule(p1, eh, mode, module, priority, ixslPreventDefault, ixslEventProperty);
            setTemplateRule(p2, eh, mode, module, priority, ixslPreventDefault, ixslEventProperty);
            return;
        }
        // some union patterns end up as a CombinedNodeTest. Need to split these.
        // (Same reasoning as above)
        if (pattern instanceof NodeTestPattern &&
                pattern.getNodeTest() instanceof CombinedNodeTest &&
                ((CombinedNodeTest)pattern.getNodeTest()).getOperator() == Token.UNION) {
            CombinedNodeTest cnt = (CombinedNodeTest)pattern.getNodeTest();
            NodeTest[] nt = cnt.getComponentNodeTests();
            setTemplateRule(new NodeTestPattern(nt[0]), eh, mode, module,
                priority, ixslPreventDefault, ixslEventProperty);
            setTemplateRule(new NodeTestPattern(nt[1]), eh, mode, module,
                priority, ixslPreventDefault, ixslEventProperty);
            return;
        }
        if (Double.isNaN(priority)) {
            priority = pattern.getDefaultPriority();
        }

        mode.addRule(pattern, eh, module, priority, true, ixslPreventDefault, ixslEventProperty);

        // if adding a rule to the omniMode (mode='all') add it to all
        // the other modes as well

        if (mode==omniMode) {
            unnamedMode.addRule(pattern, eh, module, priority, false, ixslPreventDefault, ixslEventProperty);
            Iterator<Mode> iter = modes.values().iterator();
            while (iter.hasNext()) {
                Mode m = iter.next();
                m.addRule(pattern, eh, module, priority, false, ixslPreventDefault, ixslEventProperty);
            }
        }
    }

     /**
      * Find the template rule registered for a particular node in a specific mode.
      * @param node The NodeInfo for the relevant node
      * @param mode The processing mode
      * @param c The controller for this transformation
      * @return The template rule that will process this node
      * Returns null if there is no specific handler registered.
      */

    public Rule getTemplateRule (NodeInfo node, Mode mode, XPathContext c) throws XPathException {

        if (mode==null) {
            mode = unnamedMode;
        }

        return mode.getRule(node, c);
    }

    /**
     * Get a template rule whose import precedence is in a particular range. This is used to support
     * the xsl:apply-imports function
     * @param node The node to be matched
     * @param mode The mode for which a rule is required
     * @param min  The minimum import precedence that the rule must have
     * @param max  The maximum import precedence that the rule must have
     * @param c    The Controller for the transformation
     * @return     The template rule to be invoked
     * @throws XPathException
     */

    public Rule getTemplateRule (NodeInfo node, Mode mode, int min, int max, XPathContext c)
    throws XPathException {
        if (mode==null) {
            mode = unnamedMode;
        }
        return mode.getRule(node, min, max, c);
    }

    /**
     * Get the next-match handler after the current one
     * @param node  The node to be matched
     * @param mode  The processing mode
     * @param currentRule The current template rule
     * @param c     The dynamic context for the transformation
     * @return      The template rule to be executed
     * @throws XPathException
     */

    public Rule getNextMatchHandler(NodeInfo node, Mode mode, Rule currentRule, XPathContext c)
    throws XPathException {
        if (mode==null) {
            mode = unnamedMode;
        }
        return mode.getNextMatchRule(node, currentRule, c);
    }

    /**
     * Allocate rankings to the rules within each mode. This method must be called when all
     * the rules in each mode are known
     */

    public void computeRankings() throws XPathException {
        unnamedMode.computeRankings();
        Iterator<Mode> iter = modes.values().iterator();
        while (iter.hasNext()) {
            Mode mode = iter.next();
            mode.computeRankings();
        }
    }

}

// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.
TOP

Related Classes of client.net.sf.saxon.ce.trans.RuleManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.