package client.net.sf.saxon.ce.expr.instruct; import client.net.sf.saxon.ce.expr.*; import client.net.sf.saxon.ce.lib.StandardErrorListener; import client.net.sf.saxon.ce.om.StandardNames; import client.net.sf.saxon.ce.om.ValueRepresentation; import client.net.sf.saxon.ce.trans.XPathException; import client.net.sf.saxon.ce.type.AnyItemType; import client.net.sf.saxon.ce.type.ItemType; import client.net.sf.saxon.ce.type.TypeHierarchy; import com.google.gwt.user.client.Window; import java.util.ArrayList; import java.util.Iterator; import java.util.logging.Logger; import java.util.logging.Level; /** * An xsl:message element in the stylesheet. */ public class Message extends Instruction { private Expression terminate; private Expression select; private static Logger logger = Logger.getLogger("Message"); /** * Create an xsl:message instruction * @param select the expression that constructs the message (composite of the select attribute * and the contained sequence constructor) * @param terminate expression that calculates terminate = yes or no. */ public Message(Expression select, Expression terminate) { this.terminate = terminate; this.select = select; adoptChildExpression(terminate); adoptChildExpression(select); } /** * Simplify an expression. This performs any static optimization (by rewriting the expression * as a different expression). The default implementation does nothing. * @return the simplified expression * @throws client.net.sf.saxon.ce.trans.XPathException * if an error is discovered during expression rewriting * @param visitor an expression visitor */ public Expression simplify(ExpressionVisitor visitor) throws XPathException { select = visitor.simplify(select); terminate = visitor.simplify(terminate); return this; } public Expression typeCheck(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException { select = visitor.typeCheck(select, contextItemType); adoptChildExpression(select); if (terminate != null) { terminate = visitor.typeCheck(terminate, contextItemType); adoptChildExpression(terminate); } return this; } public Expression optimize(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException { select = visitor.optimize(select, contextItemType); adoptChildExpression(select); if (terminate != null) { terminate = visitor.optimize(terminate, contextItemType); adoptChildExpression(terminate); } return this; } /** * Get the name of this instruction for diagnostic and tracing purposes */ public int getInstructionNameCode() { return StandardNames.XSL_MESSAGE; } /** * Get the item type. To avoid spurious compile-time type errors, we falsely declare that the * instruction can return anything * @param th the type hierarchy cache * @return AnyItemType */ public ItemType getItemType(TypeHierarchy th) { return AnyItemType.getInstance(); } /** * Get the static cardinality. To avoid spurious compile-time type errors, we falsely declare that the * instruction returns zero or one items - this is always acceptable * @return zero or one */ public int getCardinality() { return StaticProperty.ALLOWS_ZERO_OR_ONE; } /** * Determine whether this instruction creates new nodes. * This implementation returns true. */ public final boolean createsNewNodes() { return true; } /** * Handle promotion offers, that is, non-local tree rewrites. * @param offer The type of rewrite being offered * @throws XPathException */ protected void promoteInst(PromotionOffer offer) throws XPathException { if (select != null) { select = doPromotion(select, offer); } if (terminate != null) { terminate = doPromotion(terminate, offer); } } /** * Get all the XPath expressions associated with this instruction * (in XSLT terms, the expression present on attributes of the instruction, * as distinct from the child instructions in a sequence construction) */ public Iterator<Expression> iterateSubExpressions() { ArrayList list = new ArrayList(2); if (select != null) { list.add(select); } if (terminate != null) { list.add(terminate); } return list.iterator(); } /** * Replace one subexpression by a replacement subexpression * @param original the original subexpression * @param replacement the replacement subexpression * @return true if the original subexpression is found */ public boolean replaceSubExpression(Expression original, Expression replacement) { boolean found = false; if (select == original) { select = replacement; found = true; } if (terminate == original) { terminate = replacement; found = true; } return found; } public TailCall processLeavingTail(XPathContext context) throws XPathException { ValueRepresentation content = ExpressionTool.evaluate(select, ExpressionTool.ITERATE_AND_MATERIALIZE, context, 1); String message = content.getStringValue(); boolean abort = false; if (terminate != null) { String term = terminate.evaluateAsString(context).toString(); if (term.equals("no")) { // no action } else if (term.equals("yes")) { abort = true; } else { XPathException e = new XPathException("The terminate attribute of xsl:message must be 'yes' or 'no'"); e.setXPathContext(context); e.setErrorCode("XTDE0030"); throw e; } } logger.log(Level.INFO, message); if (abort) { throw new TerminationException( "Processing terminated by xsl:message in " + StandardErrorListener.abbreviatePath(getSystemId())); } return null; } } // 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.