All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.expr.TryCatch Maven / Gradle / Ivy

There is a newer version: 12.5
Show newest version
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2015 Saxonica Limited.
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package net.sf.saxon.expr;

import net.sf.saxon.expr.parser.*;
import net.sf.saxon.lib.NamespaceConstant;
import net.sf.saxon.om.Item;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.SequenceIterator;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.pattern.QNameTest;
import net.sf.saxon.trace.ExpressionPresenter;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.ItemType;
import net.sf.saxon.type.Type;
import net.sf.saxon.value.Cardinality;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * This class implements a try/catch expression. It consists of a try expression, and a sequence of Nametest/Catch
 * expression pairs. If the try expression succeeds, its result is returned; otherwise the error code of the
 * exception is matched against each of the Nametests in turn, and the first matching catch expression is
 * evaluated.
 */

public class TryCatch extends Expression {

    private Operand tryOp;
    private List catchClauses = new ArrayList();

    public TryCatch(Expression tryExpr) {
        this.tryOp = new Operand(this, tryExpr, OperandRole.SAME_FOCUS_ACTION);
    }

    public void addCatchExpression(QNameTest test, Expression catchExpr) {
        CatchClause clause = new CatchClause();
        clause.catchOp = new Operand(this, catchExpr, OperandRole.SAME_FOCUS_ACTION);
        clause.nameTest = test;
        catchClauses.add(clause);
    }

    /**
     * Get the "try" expression
     *
     * @return the primary expression to be evaluated
     */
    public Expression getTryExpr() {
        return tryOp.getChildExpression();
    }


    /**
     * Get the list of catch clauses
     *
     * @return the list of catch clauses
     */
    public List getCatchClauses() {
        return catchClauses;
    }

    /**
     * Determine the cardinality of the function.
     */

    public int computeCardinality() {
        int card = getTryExpr().getCardinality();
        for (CatchClause catchClause : catchClauses) {
            card = Cardinality.union(card, catchClause.catchOp.getChildExpression().getCardinality());
        }
        return card;
    }

    /**
     * Determine the item type of the value returned by the function
     */

    /*@NotNull*/
    public ItemType getItemType() {
        ItemType type = getTryExpr().getItemType();
        for (CatchClause catchClause : catchClauses) {
            type = Type.getCommonSuperType(type, catchClause.catchOp.getChildExpression().getItemType());
        }
        return type;
    }

    /**
     * Get the immediate sub-expressions of this expression, with information about the relationship
     * of each expression to its parent expression. Default implementation
     * returns a zero-length array, appropriate for an expression that has no
     * sub-expressions.
     *
     * @return an iterator containing the sub-expressions of this expression
     */
    @Override
    public Iterable operands() {
        List list = new ArrayList();
        list.add(tryOp);
        for (CatchClause cc : catchClauses) {
            list.add(cc.catchOp);
        }
        return list;
    }

    /**
     * Offer promotion for this subexpression. The offer will be accepted if the subexpression
     * is not dependent on the factors (e.g. the context item) identified in the PromotionOffer.
     * By default the offer is not accepted - this is appropriate in the case of simple expressions
     * such as constant values and variable references where promotion would give no performance
     * advantage. This method is always called at compile time.
     * 

*

This method must be overridden for any Expression that has subexpressions.

* * * @param offer details of the offer, for example the offer to move * expressions that don't depend on the context to an outer level in * the containing expression * @return if the offer is not accepted, return this expression unchanged. * Otherwise return the result of rewriting the expression to promote * this subexpression * @throws net.sf.saxon.trans.XPathException * if any error is detected */ public Expression promote(PromotionOffer offer) throws XPathException { if (offer.action != PromotionOffer.EXTRACT_GLOBAL_VARIABLES && offer.action != PromotionOffer.FOCUS_INDEPENDENT) { Expression exp = offer.accept(this); if (exp != null) { return exp; } else { //tryOp.setChildExpression(doPromotion(tryOp.getChildExpression(), offer)); for (CatchClause clause : catchClauses) { clause.catchOp.setChildExpression(doPromotion(clause.catchOp.getChildExpression(), offer)); } return this; } } else { return this; } } @Override public Expression optimize(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException { optimizeChildren(visitor, contextInfo); Expression e = getParentExpression(); while (e != null) { if (e instanceof LetExpression && ExpressionTool.dependsOnVariable(getTryExpr(), new Binding[]{(LetExpression)e})) { ((LetExpression)e).setNeedsEagerEvaluation(true); } e = e.getParentExpression(); } return this; } /** * An implementation of Expression must provide at least one of the methods evaluateItem(), iterate(), or process(). * This method indicates which of these methods is provided directly. The other methods will always be available * indirectly, using an implementation that relies on one of the other methods. * * @return the implementation method, for example {@link #ITERATE_METHOD} or {@link #EVALUATE_METHOD} or * {@link #PROCESS_METHOD} */ @Override public int getImplementationMethod() { return ITERATE_METHOD; } /** * Is this expression the same as another expression? * * @param other the expression to be compared with this one * @return true if the two expressions are statically equivalent */ @Override public boolean equals(Object other) { return other instanceof TryCatch && ((TryCatch)other).tryOp.getChildExpression().equals(tryOp.getChildExpression()) && ((TryCatch)other).catchClauses.equals(catchClauses); } /** * Hashcode supporting equals() */ public int hashCode() { int h = 0x836b12a0; for (int i = 0; i < catchClauses.size(); i++) { h ^= catchClauses.get(i).hashCode()<




© 2015 - 2025 Weber Informatics LLC | Privacy Policy