net.sf.saxon.functions.Minimax Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Saxon-HE Show documentation
Show all versions of Saxon-HE Show documentation
The XSLT and XQuery Processor
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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.functions;
import net.sf.saxon.expr.*;
import net.sf.saxon.expr.parser.ContextItemStaticInfo;
import net.sf.saxon.expr.parser.ExpressionVisitor;
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.om.Sequence;
import net.sf.saxon.om.SequenceIterator;
import net.sf.saxon.om.ZeroOrOne;
import net.sf.saxon.trace.ExpressionPresenter;
import net.sf.saxon.trans.Err;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.*;
import net.sf.saxon.value.*;
import java.util.Properties;
/**
* This class implements the min() and max() functions, with the collation argument already known.
*/
public abstract class Minimax extends CollatingFunctionFixed {
private PlainType argumentType = BuiltInAtomicType.ANY_ATOMIC;
private boolean ignoreNaN = false;
/**
* Method to be implemented in subclasses to indicate whether the function implements
* fn:min() or fn:max()
* @return true if this is the fn:max() function
*/
public abstract boolean isMaxFunction();
/**
* 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. This is the case for internally-generated min() and max()
* functions used to support general comparisons.
*
* @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 PlainType getArgumentType() {
return argumentType;
}
/**
* Static analysis: preallocate a comparer if possible
*/
@Override
public void supplyTypeInformation(ExpressionVisitor visitor, ContextItemStaticInfo contextItemType, Expression[] arguments) throws XPathException {
ItemType type = arguments[0].getItemType();
argumentType = type.getAtomizedItemType();
if (argumentType instanceof AtomicType) {
if (argumentType == BuiltInAtomicType.UNTYPED_ATOMIC) {
argumentType = BuiltInAtomicType.DOUBLE;
}
preAllocateComparer((AtomicType) argumentType, (AtomicType) argumentType, visitor.getStaticContext(), false);
}
}
/**
* Determine the cardinality of the function.
*/
public int getCardinality(Expression[] arguments) {
if (!Cardinality.allowsZero(arguments[0].getCardinality())) {
return StaticProperty.EXACTLY_ONE;
} else {
return StaticProperty.ALLOWS_ZERO_OR_ONE;
}
}
@Override
public Expression makeOptimizedFunctionCall(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo, Expression... arguments) throws XPathException {
// test for a singleton: this often happens after (A call(XPathContext context, Sequence[] arguments) throws XPathException {
return new ZeroOrOne(
minimax(arguments[0].iterate(), isMaxFunction(), getAtomicComparer(context), ignoreNaN, context));
}
@Override
public void exportAttributes(ExpressionPresenter out) {
super.exportAttributes(out);
if (ignoreNaN) {
out.emitAttribute("flags", "i");
}
}
@Override
public void importAttributes(Properties attributes) throws XPathException {
super.importAttributes(attributes);
String flags = attributes.getProperty("flags");
if (flags != null && flags.contains("i")) {
setIgnoreNaN(true);
}
}
/**
* Concrete subclass to define the fn:min() function
*/
public static class Min extends Minimax {
public boolean isMaxFunction() {
return false;
}
}
/**
* Concrete subclass to define the fn:max() function
*/
public static class Max extends Minimax {
public boolean isMaxFunction() {
return true;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy