001: package net.sf.saxon.style;
002:
003: import net.sf.saxon.expr.Expression;
004: import net.sf.saxon.functions.ExecutableFunctionLibrary;
005: import net.sf.saxon.instruct.Executable;
006: import net.sf.saxon.om.AttributeCollection;
007: import net.sf.saxon.om.NamePool;
008: import net.sf.saxon.query.ModuleURIResolver;
009: import net.sf.saxon.query.QueryReader;
010: import net.sf.saxon.query.StaticQueryContext;
011: import net.sf.saxon.query.XQueryFunction;
012: import net.sf.saxon.trans.StaticError;
013: import net.sf.saxon.trans.XPathException;
014:
015: import javax.xml.transform.stream.StreamSource;
016: import java.util.Iterator;
017:
018: /**
019: * The class implements a saxon:import-query declaration in a stylesheet. This
020: * declaration imports an XQuery library module and adds the functions defined
021: * in that module to the static context, making them available for calling from
022: * XPath expressions in the stylesheet.
023: */
024:
025: public class SaxonImportQuery extends StyleElement {
026:
027: private String href;
028: private String moduleURI;
029:
030: /**
031: * The importModule() method is called very early, before preparing the attributes,
032: * to make sure that all functions in the imported modules are available in the static
033: * context.
034: * @throws XPathException
035: */
036:
037: public void importModule() throws XPathException {
038: prepareAttributes();
039: loadLibraryModule();
040: }
041:
042: public void prepareAttributes() throws XPathException {
043:
044: // Avoid reporting errors twice
045: if (href != null || moduleURI != null) {
046: return;
047: }
048:
049: AttributeCollection atts = getAttributeList();
050:
051: for (int a = 0; a < atts.getLength(); a++) {
052: int nc = atts.getNameCode(a);
053: String f = getNamePool().getClarkName(nc);
054: if (f == StandardNames.HREF) {
055: href = atts.getValue(a).trim();
056: } else if (f == StandardNames.NAMESPACE) {
057: moduleURI = atts.getValue(a).trim();
058: } else {
059: checkUnknownAttribute(nc);
060: moduleURI = ""; // for error recovery path
061: }
062: }
063:
064: if (href == null && moduleURI == null) {
065: compileError("At least one of href or namespace must be specified");
066: moduleURI = ""; // for error recovery path
067: }
068: }
069:
070: public void validate() throws XPathException {
071: checkEmpty();
072: checkTopLevel(null);
073: }
074:
075: private void loadLibraryModule() throws XPathException {
076:
077: if (href == null && moduleURI == null) {
078: // error already reported
079: return;
080: }
081:
082: try {
083: XSLStylesheet top = getPrincipalStylesheet();
084: getExecutable().setFunctionLibrary(
085: new ExecutableFunctionLibrary(getConfiguration()));
086: // this is not actually used, but is needed to keep the XQuery processor happy
087: StaticQueryContext importedModule = loadModule();
088:
089: // Do the importing
090:
091: short ns = importedModule.getModuleNamespaceCode();
092: NamePool pool = getTargetNamePool();
093: Iterator it = importedModule.getGlobalFunctionLibrary()
094: .getFunctionDefinitions();
095: while (it.hasNext()) {
096: XQueryFunction def = (XQueryFunction) it.next();
097: // don't import functions transitively
098: if (pool.getURICode(def.getFunctionFingerprint()) == ns) {
099: top.declareXQueryFunction(def);
100: }
101: // Note, we are not importing global variables at present
102: }
103: } catch (XPathException err) {
104: compileError(err);
105: }
106: }
107:
108: /**
109: * Load a query module
110: */
111:
112: private StaticQueryContext loadModule() throws XPathException {
113: // Call the module URI resolver to find the module or modules
114:
115: ModuleURIResolver resolver = getConfiguration()
116: .getModuleURIResolver();
117: if (resolver == null) {
118: resolver = getConfiguration()
119: .getStandardModuleURIResolver();
120: }
121:
122: String[] hints = { href };
123: StreamSource[] sources;
124: try {
125: sources = resolver.resolve(moduleURI, getBaseURI(), hints);
126: if (sources == null) {
127: resolver = getConfiguration()
128: .getStandardModuleURIResolver();
129: sources = resolver.resolve(moduleURI, getBaseURI(),
130: hints);
131: }
132: } catch (XPathException e) {
133: throw StaticError.makeStaticError(e);
134: }
135:
136: if (sources.length != 1) {
137: StaticError err = new StaticError(
138: "Query module resolver must return a single module");
139: throw err;
140: }
141:
142: StreamSource ss = sources[0];
143: String baseURI = ss.getSystemId();
144: if (baseURI == null) {
145: ss.setSystemId(hints[0]);
146: }
147: String queryText = QueryReader.readSourceQuery(ss,
148: getConfiguration().getNameChecker());
149: StaticQueryContext sqc = StaticQueryContext
150: .makeStaticQueryContext(baseURI, getExecutable(), null,
151: queryText, moduleURI);
152: getExecutable().fixupQueryModules(sqc);
153: return sqc;
154:
155: }
156:
157: public Expression compile(Executable exec) throws XPathException {
158: exec
159: .setReasonUnableToCompile("Cannot compile a stylesheet that imports an XQuery library module");
160: return null;
161: }
162: }
163:
164: //
165: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
166: // you may not use this file except in compliance with the License. You may obtain a copy of the
167: // License at http://www.mozilla.org/MPL/
168: //
169: // Software distributed under the License is distributed on an "AS IS" basis,
170: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
171: // See the License for the specific language governing rights and limitations under the License.
172: //
173: // The Original Code is: all this file.
174: //
175: // The Initial Developer of the Original Code is Michael H. Kay.
176: //
177: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
178: //
179: // Contributor(s): none.
180: //
|