001: package net.sf.saxon.instruct;
002:
003: import net.sf.saxon.Controller;
004: import net.sf.saxon.event.Receiver;
005: import net.sf.saxon.event.SequenceReceiver;
006: import net.sf.saxon.expr.Expression;
007: import net.sf.saxon.expr.ExpressionTool;
008: import net.sf.saxon.expr.StaticContext;
009: import net.sf.saxon.expr.XPathContext;
010: import net.sf.saxon.om.*;
011: import net.sf.saxon.pattern.NodeKindTest;
012: import net.sf.saxon.pull.UnconstructedDocument;
013: import net.sf.saxon.style.StandardNames;
014: import net.sf.saxon.tinytree.TinyBuilder;
015: import net.sf.saxon.trans.DynamicError;
016: import net.sf.saxon.trans.XPathException;
017: import net.sf.saxon.type.ItemType;
018: import net.sf.saxon.type.TypeHierarchy;
019: import net.sf.saxon.value.TextFragmentValue;
020:
021: import java.io.PrintStream;
022:
023: /**
024: * An instruction to create a document node. This doesn't correspond directly
025: * to any XSLT instruction. It is used to support the document node constructor
026: * expression in XQuery, and is used as a sub-instruction within an xsl:variable
027: * that constructs a temporary tree.
028: *
029: * <p>Conceptually it represents an XSLT instruction xsl:document-node,
030: * with no attributes, whose content is a complex content constructor for the
031: * children of the document node.</p>
032: */
033:
034: public class DocumentInstr extends ParentNodeConstructor {
035:
036: private static final int[] treeSizeParameters = { 50, 10, 5, 200 };
037: // estimated size of a temporary tree: {nodes, attributes, namespaces, characters}
038:
039: private boolean textOnly;
040: private String constantText;
041: private String baseURI;
042:
043: public DocumentInstr(boolean textOnly, String constantText,
044: String baseURI) {
045: this .textOnly = textOnly;
046: this .constantText = constantText;
047: this .baseURI = baseURI;
048: }
049:
050: /**
051: * An implementation of Expression must provide at least one of the methods evaluateItem(), iterate(), or process().
052: * This method indicates which of these methods is prefered. For instructions this is the process() method.
053: */
054:
055: public int getImplementationMethod() {
056: return Expression.EVALUATE_METHOD;
057: }
058:
059: /**
060: * Set the validation action
061: */
062:
063: public void setValidationAction(int action) {
064: validation = action;
065: }
066:
067: /**
068: * Simplify an expression. This performs any static optimization (by rewriting the expression
069: * as a different expression). The default implementation does nothing.
070: *
071: * @return the simplified expression
072: * @throws net.sf.saxon.trans.XPathException
073: * if an error is discovered during expression rewriting
074: */
075:
076: public Expression simplify(StaticContext env) throws XPathException {
077: setLazyConstruction(env.getConfiguration()
078: .isLazyConstructionMode());
079: return super .simplify(env);
080: }
081:
082: public Expression typeCheck(StaticContext env,
083: ItemType contextItemType) throws XPathException {
084: Expression res = super .typeCheck(env, contextItemType);
085: //verifyLazyConstruction();
086: return res;
087: }
088:
089: public ItemType getItemType(TypeHierarchy th) {
090: return NodeKindTest.DOCUMENT;
091: }
092:
093: public TailCall processLeavingTail(XPathContext context)
094: throws XPathException {
095: Item item = evaluateItem(context);
096: if (item != null) {
097: SequenceReceiver out = context.getReceiver();
098: out.append(item, locationId, NodeInfo.ALL_NAMESPACES);
099: }
100: return null;
101: }
102:
103: /**
104: * Evaluate as an expression.
105: */
106:
107: public Item evaluateItem(XPathContext context)
108: throws XPathException {
109: if (isLazyConstruction()) {
110: return new UnconstructedDocument(this , context);
111: } else {
112: Controller controller = context.getController();
113: DocumentInfo root;
114: if (textOnly) {
115: CharSequence textValue;
116: if (constantText != null) {
117: textValue = constantText;
118: } else {
119: FastStringBuffer sb = new FastStringBuffer(100);
120: SequenceIterator iter = content.iterate(context);
121: if (iter instanceof AtomizableIterator) {
122: ((AtomizableIterator) iter)
123: .setIsAtomizing(true);
124: }
125: while (true) {
126: Item item = iter.next();
127: if (item == null)
128: break;
129: sb.append(item.getStringValueCS());
130: }
131: textValue = sb.condense();
132: }
133: root = new TextFragmentValue(textValue, baseURI);
134: ((TextFragmentValue) root).setConfiguration(controller
135: .getConfiguration());
136: } else {
137: try {
138: XPathContext c2 = context.newMinorContext();
139: c2.setOrigin(this );
140:
141: TinyBuilder builder = new TinyBuilder();
142: builder.setSizeParameters(treeSizeParameters);
143: builder.setLineNumbering(controller
144: .getConfiguration().isLineNumbering());
145:
146: Receiver receiver = builder;
147: receiver.setSystemId(baseURI);
148: receiver.setPipelineConfiguration(controller
149: .makePipelineConfiguration());
150:
151: c2.changeOutputDestination(null, receiver, false,
152: validation, getSchemaType());
153: Receiver out = c2.getReceiver();
154: out.open();
155: out.startDocument(0);
156:
157: content.process(c2);
158:
159: out.endDocument();
160: out.close();
161:
162: root = (DocumentInfo) builder.getCurrentRoot();
163: } catch (XPathException e) {
164: if (e.getLocator() == null) {
165: e.setLocator(this );
166: }
167: if (e instanceof DynamicError
168: && ((DynamicError) e).getXPathContext() == null) {
169: ((DynamicError) e).setXPathContext(context);
170: }
171: throw e;
172: }
173: }
174: return root;
175: }
176: }
177:
178: /**
179: * Get the name of this instruction for diagnostic and tracing purposes
180: * (the string "document-constructor")
181: */
182:
183: public int getInstructionNameCode() {
184: return StandardNames.XSL_DOCUMENT;
185: }
186:
187: /**
188: * Display this instruction as an expression, for diagnostics
189: */
190:
191: public void display(int level, NamePool pool, PrintStream out) {
192: out.println(ExpressionTool.indent(level)
193: + "document-constructor");
194: content.display(level + 1, pool, out);
195: }
196: }
197:
198: //
199: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
200: // you may not use this file except in compliance with the License. You may obtain a copy of the
201: // License at http://www.mozilla.org/MPL/
202: //
203: // Software distributed under the License is distributed on an "AS IS" basis,
204: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
205: // See the License for the specific language governing rights and limitations under the License.
206: //
207: // The Original Code is: all this file.
208: //
209: // The Initial Developer of the Original Code is Michael H. Kay.
210: //
211: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
212: //
213: // Contributor(s): none.
214: //
|