001: package net.sf.saxon.instruct;
002:
003: import net.sf.saxon.Controller;
004: import net.sf.saxon.event.Emitter;
005: import net.sf.saxon.event.TreeReceiver;
006: import net.sf.saxon.expr.*;
007: import net.sf.saxon.om.*;
008: import net.sf.saxon.pattern.NoNodeTest;
009: import net.sf.saxon.style.StandardNames;
010: import net.sf.saxon.trans.DynamicError;
011: import net.sf.saxon.trans.XPathException;
012: import net.sf.saxon.type.ItemType;
013: import net.sf.saxon.type.TypeHierarchy;
014:
015: import javax.xml.transform.OutputKeys;
016: import java.io.OutputStreamWriter;
017: import java.io.PrintStream;
018: import java.util.ArrayList;
019: import java.util.Iterator;
020: import java.util.Properties;
021:
022: /**
023: * An xsl:message element in the stylesheet.
024: */
025:
026: public class Message extends Instruction {
027:
028: // TODO: JAXP 1.3 specifies that xsl:message output is written to the ErrorListener
029:
030: private Expression terminate;
031: private Expression select;
032:
033: public Message(Expression select, Expression terminate) {
034: this .terminate = terminate;
035: this .select = select;
036: adoptChildExpression(terminate);
037: adoptChildExpression(select);
038: }
039:
040: /**
041: * Simplify an expression. This performs any static optimization (by rewriting the expression
042: * as a different expression). The default implementation does nothing.
043: * @return the simplified expression
044: * @throws net.sf.saxon.trans.XPathException
045: * if an error is discovered during expression rewriting
046: */
047:
048: public Expression simplify(StaticContext env) throws XPathException {
049: select = select.simplify(env);
050: if (terminate != null) {
051: terminate = terminate.simplify(env);
052: }
053: return this ;
054: }
055:
056: public Expression typeCheck(StaticContext env,
057: ItemType contextItemType) throws XPathException {
058: select = select.typeCheck(env, contextItemType);
059: adoptChildExpression(select);
060: if (terminate != null) {
061: terminate = terminate.typeCheck(env, contextItemType);
062: adoptChildExpression(terminate);
063: }
064: return this ;
065: }
066:
067: public Expression optimize(Optimizer opt, StaticContext env,
068: ItemType contextItemType) throws XPathException {
069: select = select.optimize(opt, env, contextItemType);
070: adoptChildExpression(select);
071: if (terminate != null) {
072: terminate = terminate.optimize(opt, env, contextItemType);
073: adoptChildExpression(terminate);
074: }
075: return this ;
076: }
077:
078: /**
079: * Get the name of this instruction for diagnostic and tracing purposes
080: */
081:
082: public int getInstructionNameCode() {
083: return StandardNames.XSL_MESSAGE;
084: }
085:
086: public ItemType getItemType(TypeHierarchy th) {
087: return NoNodeTest.getInstance();
088: }
089:
090: public int getCardinality() {
091: return StaticProperty.EMPTY;
092: }
093:
094: /**
095: * Determine whether this instruction creates new nodes.
096: * This implementation returns true.
097: */
098:
099: public final boolean createsNewNodes() {
100: return true;
101: }
102:
103: /**
104: * Handle promotion offers, that is, non-local tree rewrites.
105: * @param offer The type of rewrite being offered
106: * @throws XPathException
107: */
108:
109: protected void promoteInst(PromotionOffer offer)
110: throws XPathException {
111: if (select != null) {
112: select = doPromotion(select, offer);
113: }
114: if (terminate != null) {
115: terminate = doPromotion(terminate, offer);
116: }
117: }
118:
119: /**
120: * Get all the XPath expressions associated with this instruction
121: * (in XSLT terms, the expression present on attributes of the instruction,
122: * as distinct from the child instructions in a sequence construction)
123: */
124:
125: public Iterator iterateSubExpressions() {
126: ArrayList list = new ArrayList(2);
127: if (select != null) {
128: list.add(select);
129: }
130: if (terminate != null) {
131: list.add(terminate);
132: }
133: return list.iterator();
134: }
135:
136: public TailCall processLeavingTail(XPathContext context)
137: throws XPathException {
138: Controller controller = context.getController();
139: Emitter emitter = controller.getMessageEmitter();
140: if (emitter == null) {
141: emitter = controller.makeMessageEmitter();
142: }
143: if (emitter.getWriter() == null) {
144: emitter.setWriter(new OutputStreamWriter(System.err));
145: }
146:
147: TreeReceiver rec = new TreeReceiver(emitter);
148:
149: XPathContext c2 = context.newMinorContext();
150: c2.setOrigin(this );
151: Properties props = new Properties();
152: props.put(OutputKeys.OMIT_XML_DECLARATION, "yes");
153: emitter.setOutputProperties(props);
154: c2.changeOutputDestination(props, rec, false,
155: Validation.PRESERVE, null);
156:
157: if (select != null) {
158: SequenceIterator iter = select.iterate(c2);
159: while (true) {
160: Item item = iter.next();
161: if (item == null) {
162: break;
163: }
164: rec.append(item, locationId, NodeInfo.ALL_NAMESPACES);
165: }
166: }
167: rec.close();
168:
169: if (terminate != null) {
170: String term = terminate.evaluateAsString(context);
171: if (term.equals("no")) {
172: // no action
173: } else if (term.equals("yes")) {
174: throw new TerminationException(
175: "Processing terminated by xsl:message at line "
176: + getLineNumber());
177: } else {
178: DynamicError e = new DynamicError(
179: "The terminate attribute of xsl:message must be 'yes' or 'no'");
180: e.setXPathContext(context);
181: e.setErrorCode("XTDE0030");
182: throw e;
183: }
184: }
185: return null;
186: }
187:
188: /**
189: * Diagnostic print of expression structure. The expression is written to the System.err
190: * output stream
191: *
192: * @param level indentation level for this expression
193: * @param out
194: */
195:
196: public void display(int level, NamePool pool, PrintStream out) {
197: out.println(ExpressionTool.indent(level) + "message");
198: }
199: }
200: //
201: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
202: // you may not use this file except in compliance with the License. You may obtain a copy of the
203: // License at http://www.mozilla.org/MPL/
204: //
205: // Software distributed under the License is distributed on an "AS IS" basis,
206: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
207: // See the License for the specific language governing rights and limitations under the License.
208: //
209: // The Original Code is: all this file.
210: //
211: // The Initial Developer of the Original Code is Michael H. Kay.
212: //
213: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
214: //
215: // Contributor(s): none.
216: //
|