#include "../config/pathan_config.h" /* * Copyright (c) 2001, DecisionSoft Limited All rights reserved. * Please see LICENSE.TXT for more information. */ #include #include #include #include #include #include "../operators/TotalOrderComparison.hpp" #include #include #include #include #include #include #include #include #include const XMLCh FunctionMax::name[] = { XERCES_CPP_NAMESPACE_QUALIFIER chLatin_m, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_a, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_x, XERCES_CPP_NAMESPACE_QUALIFIER chNull }; /** * fn:max($arg as xdt:anyAtomicType*) as xdt:anyAtomicType? * fn:max($arg as xdt:anyAtomicType*, $collation as string) as xdt:anyAtomicType? **/ FunctionMax::FunctionMax(const VectorOfDataItems &args, XPath2MemoryManager* memMgr) : AggregateFunction(name,1, 2, "anyAtomicType*, string", args, memMgr) { } Sequence FunctionMax::collapseTreeInternal(DynamicContext* context, int flags) const { XPath2MemoryManager* memMgr = context->getMemoryManager(); Sequence sequence(memMgr); try { sequence = validateSequence(getParamNumber(1,context,DataItem::UNORDERED), context); } catch (IllegalArgumentException &e) { DSLthrow(IllegalArgumentException, X("FunctionMax::collapseTreeInternal"), X("Invalid argument to fn:max() function")); } // Return the empty sequence if the sequence is empty if(sequence.isEmpty()) { return Sequence(memMgr); } if(sequence.getLength()==1 && isNumericNaN(sequence.first())) return sequence; Collation* collation=NULL; if (getNumArgs()>1) { Sequence collArg = getParamNumber(2,context); const XMLCh* collName = ((const ATStringOrDerived*)collArg.first())->asString(context); try { DatatypeFactory::STR2AT::createAnyURI(memMgr, collName, context); } catch(XPath2ErrorException &e) { DSLthrow(FunctionException, X("FunctionMax::collapseTreeInternal"), X("Invalid collationURI")); } collation=context->getCollation(collName); if (collation==NULL) DSLthrow(FunctionException,X("FunctionMax::collapseTreeInternal"),X("Collation object is not available")); } else collation=context->getDefaultCollation(); if(collation==NULL) collation=context->getCollation(CodepointCollation::getCodepointCollationName()); Sequence::iterator i = sequence.begin(); Sequence maxItem(*i, memMgr); ++i; for (; i != sequence.end(); ++i) { if(((const AnyAtomicType*)*i)->getPrimitiveTypeIndex() == AnyAtomicType::STRING) { if(collation->compare((*i)->asString(context),maxItem.first()->asString(context))>0) { maxItem.clear(); maxItem.addItem(*i); } } else { const ATBooleanOrDerived* greater; VectorOfDataItems gtArgs = VectorOfDataItems(PathanAllocator(memMgr)); DataItemSequence seq1(*i, memMgr); gtArgs.push_back(&seq1); DataItemSequence seq2(maxItem, memMgr); gtArgs.push_back(&seq2); TotalOrderComparison gt(gtArgs, true, memMgr); try { greater = (const ATBooleanOrDerived*)gt.collapseTree(context).first(); } catch (IllegalArgumentException &e) { DSLthrow(IllegalArgumentException, X("FunctionMax::collapseTreeInternal"), X("Invalid argument to fn:max() function")); } catch (XPath2ErrorException &e) { DSLthrow(IllegalArgumentException, X("FunctionMax::collapseTreeInternal"), X("Invalid argument to fn:max() function")); } if(greater->isTrue()) { maxItem.clear(); maxItem.addItem(*i); } } } return maxItem; }