IndependentContext.java :  » XML » XPath-Saxon » net » sf » saxon » trans » Java Open Source

Java Open Source » XML » XPath Saxon 
XPath Saxon » net » sf » saxon » trans » IndependentContext.java
package net.sf.saxon.trans;
import net.sf.saxon.Configuration;
import net.sf.saxon.sort.IntHashMap;
import net.sf.saxon.value.QNameValue;
import net.sf.saxon.expr.*;
import net.sf.saxon.functions.ConstructorFunctionLibrary;
import net.sf.saxon.functions.FunctionLibrary;
import net.sf.saxon.functions.FunctionLibraryList;
import net.sf.saxon.functions.SystemFunctionLibrary;
import net.sf.saxon.instruct.LocationMap;
import net.sf.saxon.instruct.SlotManager;
import net.sf.saxon.om.*;
import net.sf.saxon.type.AtomicType;
import net.sf.saxon.type.Type;

import javax.xml.transform.SourceLocator;
import java.io.Serializable;
import java.util.*;

/**
* An IndependentContext provides a context for parsing an expression or pattern appearing
* in a context other than a stylesheet.
 *
 * This class was formerly named StandaloneContext. It has forked from that class, so that
 * StandaloneContext could be changed to meet the demands of the JAXP 1.3 XPath API.
*/

public class IndependentContext implements StaticContext, NamespaceResolver, Serializable {

  private NamePool namePool;
  private HashMap namespaces = new HashMap(10);
  private HashMap collations = new HashMap(10);
  private IntHashMap variables = new IntHashMap(20);
    private SlotManager stackFrameMap;
  private String defaultCollationName = null;
    private String baseURI = null;
    private Configuration config;
    private LocationMap locationMap = new LocationMap();
    private FunctionLibrary functionLibrary;
    private String defaultFunctionNamespace = NamespaceConstant.FN;
    //private StaticContext schemaImporter = null;
    private NamespaceResolver externalResolver = null;
    private Set importedSchemaNamespaces = Collections.EMPTY_SET;

    public IndependentContext() {
        this(new Configuration());
    }

    /**
  * Create an IndependentContext using a specific Configuration
  */

  public IndependentContext(Configuration config) {
        this.config = config;
    namePool = config.getNamePool();
        stackFrameMap = config.makeSlotManager();
    clearNamespaces();

        // Set up a default function library. This can be overridden using setFunctionLibrary()

        FunctionLibraryList lib = new FunctionLibraryList();
        lib.addFunctionLibrary(new SystemFunctionLibrary(SystemFunctionLibrary.XPATH_ONLY));
        lib.addFunctionLibrary(getConfiguration().getVendorFunctionLibrary());
        lib.addFunctionLibrary(new ConstructorFunctionLibrary(getConfiguration()));
        if (config.isAllowExternalFunctions()) {
            lib.addFunctionLibrary(config.getExtensionBinder());
        }
        functionLibrary = lib;
    }

    /**
     * Create a copy of this IndependentContext. All aspects of the context are copied
     * except for declared variables.
     */

    public IndependentContext copy() {
        IndependentContext ic = new IndependentContext(config);
        ic.namespaces = new HashMap(namespaces);
        ic.collations = new HashMap(collations);
        ic.variables = new IntHashMap(10);
        ic.defaultCollationName = defaultCollationName;
        ic.baseURI = baseURI;
        ic.locationMap = locationMap;
        ic.functionLibrary = functionLibrary;
        ic.defaultFunctionNamespace = defaultFunctionNamespace;
        ic.importedSchemaNamespaces = importedSchemaNamespaces;
        ic.externalResolver = externalResolver;
        return ic;
    }

    /**
     * Get the system configuration
     */

    public Configuration getConfiguration() {
        return config;
    }

    /**
     * Construct a dynamic context for early evaluation of constant subexpressions
     */

    public XPathContext makeEarlyEvaluationContext() {
        return new EarlyEvaluationContext(this);
    }


    public LocationMap getLocationMap() {
        return locationMap;
    }

    public void setLocationMap(LocationMap locationMap) {
        this.locationMap = locationMap;
    }

  /**
  * Declare a namespace whose prefix can be used in expressions
  * @param prefix The namespace prefix. Must not be null. Must not be the empty string
  * ("") - unqualified names in an XPath expression always refer to the null namespace.
  * @param uri The namespace URI. Must not be null.
  */

  public void declareNamespace(String prefix, String uri) {
      if (prefix==null) {
          throw new NullPointerException("Null prefix supplied to declareNamespace()");
      }
      if (uri==null) {
          throw new NullPointerException("Null namespace URI supplied to declareNamespace()");
      }
    namespaces.put(prefix, uri);
    namePool.allocateNamespaceCode(prefix, uri);
  }

  /**
  * Clear all the declared namespaces, except for the standard ones (xml, xslt, saxon, xdt)
  */

  public void clearNamespaces() {
      namespaces.clear();
    declareNamespace("xml", NamespaceConstant.XML);
    declareNamespace("xsl", NamespaceConstant.XSLT);
    declareNamespace("saxon", NamespaceConstant.SAXON);
    declareNamespace("xs", NamespaceConstant.SCHEMA);
    declareNamespace("xdt", NamespaceConstant.XDT);
        declareNamespace("", "");
  }

  /**
  * Clear all the declared namespaces, including the standard ones (xml, xslt, saxon).
     * Leave only the XML namespace and the default namespace (xmlns="")
  */

  public void clearAllNamespaces() {
      namespaces.clear();
    declareNamespace("xml", NamespaceConstant.XML);
    declareNamespace("", "");
  }

  /**
  * Set all the declared namespaces to be the namespaces that are in-scope for a given node.
  * In addition, the standard namespaces (xml, xslt, saxon) are declared.
  * @param node The node whose in-scope namespaces are to be used as the context namespaces.
  * If the node is an attribute, text node, etc, then the namespaces of its parent element are used.
  */

  public void setNamespaces(NodeInfo node) {
      namespaces.clear();
        int kind = node.getNodeKind();
        if (kind == Type.ATTRIBUTE || kind == Type.TEXT ||
                kind == Type.COMMENT || kind == Type.PROCESSING_INSTRUCTION ||
                kind == Type.NAMESPACE) {
            node = node.getParent();
        }
        if (node == null) {
            return;
        }

      AxisIterator iter = node.iterateAxis(Axis.NAMESPACE);
      while (true) {
          NodeInfo ns = (NodeInfo)iter.next();
            if (ns == null) {
                return;
            }
          declareNamespace(ns.getLocalPart(), ns.getStringValue());
      }
  }

    /**
     * Set an external namespace resolver. If this is set, then all resolution of namespace
     * prefixes is delegated to the external namespace resolver, and namespaces declared
     * individually on this IndependentContext object are ignored.
     */

    public void setNamespaceResolver(NamespaceResolver resolver) {
        this.externalResolver = resolver;
    }

    /**
     * Set the base URI in the static context
     */

    public void setBaseURI(String baseURI) {
        this.baseURI = baseURI;
    }

    /**
    * Declare a named collation
    * @param name The name of the collation (technically, a URI)
    * @param comparator The Java Comparator used to implement the collating sequence
    * @param isDefault True if this is to be used as the default collation
    */

    public void declareCollation(String name, Comparator comparator, boolean isDefault) {
        collations.put(name, comparator);
        if (isDefault) {
            defaultCollationName = name;
        }
    }

    /**
     * Get the stack frame map containing the slot number allocations for the variables declared
     * in this static context
     */

    public SlotManager getStackFrameMap() {
        return stackFrameMap;
    }

    /**
    * Declare a variable. A variable must be declared before an expression referring
    * to it is compiled. The initial value of the variable will be the empty sequence
     * @param qname The name of the variable
    */

    public Variable declareVariable(QNameValue qname) {
        Variable var = Variable.make(qname, getConfiguration());
        var.setXPathValue(null);
        int fingerprint = qname.allocateNameCode(getNamePool()) & 0xfffff;
        variables.put(fingerprint, var);
        stackFrameMap.allocateSlotNumber(fingerprint);
        return var;
    }

    /**
    * Declare a variable. A variable may be declared before an expression referring
    * to it is compiled. Alternatively, a JAXP XPathVariableResolver may be supplied
     * to perform the resolution. A variable that has been explicitly declared is
     * used in preference.
     * @param qname Lexical QName identifying the variable. The namespace prefix, if
     * any, must have been declared before this method is called, or must be resolvable
     * using the namespace context.
    */

    public Variable declareVariable(String qname) throws XPathException {
        String prefix;
        String localName;
        final NameChecker checker = getConfiguration().getNameChecker();
        try {
            String[] parts = checker.getQNameParts(qname);
            prefix = parts[0];
            localName = parts[1];
        } catch (QNameException err) {
            throw new StaticError("Invalid QName for variable: " + qname);
        }
        String uri = "";
        if (!("".equals(prefix))) {
            uri = getURIForPrefix(prefix);
        }
        QNameValue q = new QNameValue(prefix, uri, localName, checker);
        Variable var = Variable.make(q, getConfiguration());
        int fingerprint = namePool.allocate(prefix, uri, localName) & 0xfffff;
        variables.put(fingerprint, var);
        stackFrameMap.allocateSlotNumber(fingerprint);
        return var;
    }


    /**
    * Get the NamePool used for compiling expressions
    */

    public NamePool getNamePool() {
        return namePool;
    }

    /**
    * Issue a compile-time warning. This method is used during XPath expression compilation to
    * output warning conditions. The default implementation writes the message to System.err. To
    * change the destination of messages, create a subclass of StandaloneContext that overrides
    * this method.
    */

    public void issueWarning(String s, SourceLocator locator) {
        System.err.println(s);
    }

    /**
    * Get the system ID of the container of the expression. Used to construct error messages.
    * @return "" always
    */

    public String getSystemId() {
        return "";
    }

    /**
    * Get the Base URI of the stylesheet element, for resolving any relative URI's used
    * in the expression.
    * Used by the document() function, resolve-uri(), etc.
    * @return "" if no base URI has been set
    */

    public String getBaseURI() {
        return baseURI==null ? "" : baseURI;
    }

    /**
    * Get the line number of the expression within that container.
    * Used to construct error messages.
    * @return -1 always
    */

    public int getLineNumber() {
        return -1;
    }

    /**
     * Get the URI for a prefix, using the declared namespaces as
     * the context for namespace resolution. The default namespace is NOT used
     * when the prefix is empty.
     * This method is provided for use by the XPath parser.
     * @param prefix The prefix
     * @throws net.sf.saxon.trans.XPathException if the prefix is not declared
    */

    public String getURIForPrefix(String prefix) throws XPathException {
        String uri = getURIForPrefix(prefix, false);
      if (uri==null) {
        throw new StaticError("Prefix " + prefix + " has not been declared");
      }
      return uri;
    }

    public NamespaceResolver getNamespaceResolver() {
        if (externalResolver != null) {
            return externalResolver;
        } else {
            return this;
        }
    }

    /**
     * Get the namespace URI corresponding to a given prefix. Return null
     * if the prefix is not in scope.
     * @param prefix the namespace prefix
     * @param useDefault true if the default namespace is to be used when the
     * prefix is ""
     * @return the uri for the namespace, or null if the prefix is not in scope.
     * Return "" if the prefix maps to the null namespace.
     */

    public String getURIForPrefix(String prefix, boolean useDefault) {
        if (externalResolver != null) {
            return externalResolver.getURIForPrefix(prefix, useDefault);
        }
        if (prefix.equals("") && !useDefault) {
            return "";
        } else {
          return (String)namespaces.get(prefix);
        }
    }

    /**
     * Get an iterator over all the prefixes declared in this namespace context. This will include
     * the default namespace (prefix="") and the XML namespace where appropriate
     */

    public Iterator iteratePrefixes() {
        if (externalResolver != null) {
            return externalResolver.iteratePrefixes();
        } else {
            return namespaces.keySet().iterator();
        }
    }

    /**
    * Bind a variable used in an XPath Expression to the XSLVariable element in which it is declared.
    * This method is provided for use by the XPath parser, and it should not be called by the user of
    * the API, or overridden, unless variables are to be declared using a mechanism other than the
    * declareVariable method of this class.
    */

    public VariableReference bindVariable(int fingerprint) throws StaticError {
        Variable var = (Variable)variables.get(fingerprint);
        if (var==null) {
            throw new StaticError("Undeclared variable in a standalone expression");
        } else {
            return new VariableReference(var);
        }
    }

    /**
     * Get the function library containing all the in-scope functions available in this static
     * context
     */

    public FunctionLibrary getFunctionLibrary() {
        return functionLibrary;
    }

    /**
     * Set the function library to be used
     */

    public void setFunctionLibrary(FunctionLibrary lib) {
        functionLibrary = lib;
    }

    /**
    * Get a named collation.
    * @return the collation identified by the given name, as set previously using declareCollation.
    * Return null if no collation with this name is found.
    */

    public Comparator getCollation(String name) {
        Configuration config = getConfiguration();
        return config.getCollationURIResolver().resolve(name, getBaseURI(), config);
    }

    /**
    * Get the name of the default collation.
    * @return the name of the default collation; or the name of the codepoint collation
    * if no default collation has been defined
    */

    public String getDefaultCollationName() {
        if (defaultCollationName != null) {
            return defaultCollationName;
        } else {
            return NamespaceConstant.CODEPOINT_COLLATION_URI;
        }
    }

    /**
    * Get the default XPath namespace, as a namespace code that can be looked up in the NamePool
    */

    public short getDefaultElementNamespace() {
        return NamespaceConstant.NULL_CODE;
    }

    /**
     * Set the default function namespace
     */

    public void setDefaultFunctionNamespace(String uri) {
        defaultFunctionNamespace = uri;
    }

    /**
     * Get the default function namespace
     */

    public String getDefaultFunctionNamespace() {
        return defaultFunctionNamespace;
    }

    /**
     * Determine whether Backwards Compatible Mode is used
     * @return false; XPath 1.0 compatibility mode is not supported in the standalone
     * XPath API
     */

    public boolean isInBackwardsCompatibleMode() {
        return false;
    }

    public boolean isImportedSchema(String namespace) {
        return importedSchemaNamespaces.contains(namespace);
    }

    /**
     * Determine whether a built-in type is available in this context. This method caters for differences
     * between host languages as to which set of types are built in.
     *
     * @param type the supposedly built-in type. This will always be a type in the
     *             XS or XDT namespace.
     * @return true if this type can be used in this static context
     */

    public boolean isAllowedBuiltInType(AtomicType type) {
        return true;
    }

    /**
     * Get the set of imported schemas
     *
     * @return a Set, the set of URIs representing the names of imported schemas
     */

    public Set getImportedSchemaNamespaces() {
        return importedSchemaNamespaces;
    }

    public void setImportedSchemaNamespaces(Set namespaces) {
        importedSchemaNamespaces = namespaces;
    }

//    public void setSchemaImporter(StaticContext importer) {
//        schemaImporter = importer;
//    }

}

//
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
// you may not use this file except in compliance with the License. You may obtain a copy of the
// License at http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
// See the License for the specific language governing rights and limitations under the License.
//
// The Original Code is: all this file.
//
// The Initial Developer of the Original Code is Michael H. Kay
//
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
//
// Contributor(s): none.
//
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.