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

net.sf.saxon.functions.Minimax Maven / Gradle / Ivy

There is a newer version: 10.5
Show newest version
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2013 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.functions;




import net.sf.saxon.expr.*;
import net.sf.saxon.expr.parser.ExpressionTool;
import net.sf.saxon.expr.parser.ExpressionVisitor;
import net.sf.saxon.expr.parser.Optimizer;
import net.sf.saxon.expr.sort.AtomicComparer;
import net.sf.saxon.expr.sort.DescendingComparer;
import net.sf.saxon.expr.sort.GenericAtomicComparer;
import net.sf.saxon.lib.ConversionRules;
import net.sf.saxon.lib.StringCollator;
import net.sf.saxon.om.SequenceIterator;
import net.sf.saxon.om.StandardNames;
import net.sf.saxon.trans.Err;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.*;
import net.sf.saxon.value.*;


/**
 * This class implements the min() and max() functions
 */

public abstract class Minimax extends CollatingFunction {

    public static final int MIN = 2;
    public static final int MAX = 3;

    private BuiltInAtomicType argumentType = BuiltInAtomicType.ANY_ATOMIC;
    private boolean ignoreNaN = false;

    /**
     * Get the argument position (0-based) containing the collation name
     * @return the position of the argument containing the collation URI
     */
    @Override
    protected int getCollationArgument() {
        return 1;
    }

    /**
     * Indicate whether NaN values should be ignored. For the external min() and max() function, a
     * NaN value in the input causes the result to be NaN. Internally, however, min() and max() are also
     * used in such a way that NaN values should be ignored.
     *
     * @param ignore true if NaN values are to be ignored when computing the min or max.
     */

    public void setIgnoreNaN(boolean ignore) {
        ignoreNaN = ignore;
    }

    /**
     * Test whether NaN values are to be ignored
     *
     * @return true if NaN values are to be ignored. This is the case for internally-generated min() and max()
     *         functions used to support general comparisons
     */

    public boolean isIgnoreNaN() {
        return ignoreNaN;
    }



    public AtomicComparer getComparer() {
        return getPreAllocatedAtomicComparer();
    }

    public BuiltInAtomicType getArgumentType() {
        return argumentType;
    }

    /**
     * Get implementation method
     *
     * @return a value that indicates this function is capable of being streamed
     */

    public int getImplementationMethod() {
        return super.getImplementationMethod() | ITEM_FEED_METHOD;
    }

    /**
     * Static analysis: prevent sorting of the argument and preallocate a comparer if possible
     */

    public void checkArguments(/*@NotNull*/ ExpressionVisitor visitor) throws XPathException {
        super.checkArguments(visitor);
        Optimizer opt = visitor.getConfiguration().obtainOptimizer();
        argument[0] = ExpressionTool.unsorted(opt, argument[0], false);
        TypeHierarchy th = visitor.getConfiguration().getTypeHierarchy();
        ItemType type = argument[0].getItemType(th);
        if (type instanceof AtomicType) {
            if (type == BuiltInAtomicType.UNTYPED_ATOMIC) {
                type = BuiltInAtomicType.DOUBLE;
            }
            preAllocateComparer((AtomicType)type, (AtomicType)type, visitor.getStaticContext(), false);
        }
    }

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

    public int computeCardinality() {
        int c = super.computeCardinality();
        if (!Cardinality.allowsZero(argument[0].getCardinality())) {
            c = StaticProperty.EXACTLY_ONE;
        }
        return c;
    }


    /**
     * Type-check the expression
     */

    /*@NotNull*/
    public Expression typeCheck(ExpressionVisitor visitor, ExpressionVisitor.ContextItemType contextItemType) throws XPathException {
        Expression e2 = super.typeCheck(visitor, contextItemType);
        if (e2 != this) {
            return e2;
        }
        TypeHierarchy th = visitor.getConfiguration().getTypeHierarchy();
        StaticContext env = visitor.getStaticContext();
        if(Literal.isEmptySequence(argument[0])){
            return argument[0];
        }
        argumentType = (BuiltInAtomicType) argument[0].getItemType(th).getPrimitiveItemType();

        PlainType t0 = (PlainType) argument[0].getItemType(th);

        if (t0.isExternalType()) {
            XPathException err = new XPathException("Cannot perform computation involving external objects");
            err.setIsTypeError(true);
            err.setErrorCode("XPTY0004");
            err.setLocator(this);
            throw err;
        }

        BuiltInAtomicType p0 = (BuiltInAtomicType) t0.getPrimitiveItemType();
        if (p0.equals(BuiltInAtomicType.UNTYPED_ATOMIC)) {
            p0 = BuiltInAtomicType.DOUBLE;
        }

        //needsRuntimeCheck = p0.equals(BuiltInAtomicType.ANY_ATOMIC);

//        if (comparer == null) {
//            StringCollator comp = getDefaultCollation();
//            if (comp != null) {
//                comparer = GenericAtomicComparer.makeAtomicComparer(
//                        p0, p0, comp, env.getConfiguration().getConversionContext());
//            }
//        }

        return this;
    }

    /**
     * Perform optimisation of an expression and its subexpressions.
     * 

*

This method is called after all references to functions and variables have been resolved * to the declaration of the function or variable, and after all type checking has been done.

* * @param visitor an expression visitor * @param contextItemType the static type of "." at the point where this expression is invoked. * The parameter is set to null if it is known statically that the context item will be undefined. * If the type of the context item is not known statically, the argument is set to * {@link net.sf.saxon.type.Type#ITEM_TYPE} * @return the original expression, rewritten if appropriate to optimize execution * @throws XPathException if an error is discovered during this phase * (typically a type error) */ /*@NotNull*/ public Expression optimize(/*@NotNull*/ ExpressionVisitor visitor, ExpressionVisitor.ContextItemType contextItemType) throws XPathException { TypeHierarchy th = visitor.getConfiguration().getTypeHierarchy(); Expression e = super.optimize(visitor, contextItemType); if (e != this) { return e; } if (getNumberOfArguments() == 1) { // test for a singleton: this often happens after (A




© 2015 - 2024 Weber Informatics LLC | Privacy Policy