BoolResult FunctionContains::boolResult(DynamicContext* context) const { Sequence str1 = getParamNumber(1,context)->toSequence(context); Sequence str2 = getParamNumber(2,context)->toSequence(context); Collation* collation = NULL; if(getNumArgs()>2) { Sequence collArg = getParamNumber(3,context)->toSequence(context); const XMLCh* collName = collArg.first()->asString(context); try { context->getItemFactory()->createAnyURI(collName, context); } catch(XPath2ErrorException &e) { XQThrow(FunctionException, X("FunctionContains::createSequence"), X("Invalid collationURI")); } collation=context->getCollation(collName, this); if(collation==NULL) XQThrow(FunctionException,X("FunctionContains::createSequence"),X("Collation object is not available")); } else collation=context->getCollation(CodepointCollation::getCodepointCollationName(), this); const XMLCh* container = XMLUni::fgZeroLenString; if(!str1.isEmpty()) container=str1.first()->asString(context); const XMLCh* pattern = XMLUni::fgZeroLenString; if(!str2.isEmpty()) pattern=str2.first()->asString(context); if(XMLString::stringLen(pattern)==0) return true; else if(XMLString::stringLen(container)==0) return false; return XMLString::patternMatch(container, pattern) > -1; }
Item::Ptr Multiply::execute(const AnyAtomicType::Ptr &atom1, const AnyAtomicType::Ptr &atom2, DynamicContext *context) const { if(atom1.isNull() || atom2.isNull()) return 0; // xs:double * xs:duration (only xdt:dayTimeDuration and xdt:yearMonthDuration) if(atom1->isNumericValue() && (atom2->getPrimitiveTypeIndex() == AnyAtomicType::DAY_TIME_DURATION || atom2->getPrimitiveTypeIndex() == AnyAtomicType::YEAR_MONTH_DURATION)) { return ((const ATDurationOrDerived*)atom2.get())->multiply((const Numeric*)atom1.get(), context); } // xs:duration * xs:double (only xdt:dayTimeDuration and xdt:yearMonthDuration) if(atom2->isNumericValue() && (atom1->getPrimitiveTypeIndex() == AnyAtomicType::DAY_TIME_DURATION || atom1->getPrimitiveTypeIndex() == AnyAtomicType::YEAR_MONTH_DURATION)) { return ((const ATDurationOrDerived*)atom1.get())->multiply((const Numeric*)atom2.get(), context); } // numeric * numeric if(atom1->isNumericValue()) { if(atom2->isNumericValue()) { return ((const Numeric*)atom1.get())->multiply((const Numeric*)atom2.get(), context); } else { XQThrow(XPath2ErrorException,X("Multiply::createSequence"), X("An attempt to multiply a non numeric type to a numeric type has occurred [err:XPTY0004]")); } } XQThrow(XPath2ErrorException,X("Multiply::createSequence"), X("The operator * has been called on invalid operand types [err:XPTY0004]")); }
Item::Ptr Divide::execute(const AnyAtomicType::Ptr &atom1, const AnyAtomicType::Ptr &atom2, DynamicContext *context) const { if(atom1 == NULLRCP || atom2 == NULLRCP) return 0; if(atom1->isNumericValue()) { if(atom2->isNumericValue()) { return (const Item::Ptr)((Numeric*)(const AnyAtomicType*)atom1)->divide((const Numeric::Ptr )atom2, context); } else { XQThrow(XPath2ErrorException,X("Divide::createSequence"), X("An attempt to divide a numeric type by a non-numeric type has occurred [err:XPTY0004]")); } } if(atom1->getPrimitiveTypeIndex() == AnyAtomicType::DAY_TIME_DURATION || atom1->getPrimitiveTypeIndex() == AnyAtomicType::YEAR_MONTH_DURATION) { const ATDurationOrDerived* duration = (const ATDurationOrDerived*)atom1.get(); if(atom2->isNumericValue()) { return (const Item::Ptr)duration->divide((const Numeric *)atom2.get(), context); } else if(atom2->getPrimitiveTypeIndex() == AnyAtomicType::DAY_TIME_DURATION || atom2->getPrimitiveTypeIndex() == AnyAtomicType::YEAR_MONTH_DURATION) { return (const Item::Ptr)duration->divide((const ATDurationOrDerived*)atom2.get(), context); } else { XQThrow(XPath2ErrorException,X("Divide::createSequence"), X("An attempt to divide an xs:duration by an invalid type has occured [err:XPTY0004]")); } } else { XQThrow(XPath2ErrorException,X("Divide::createSequence"), X("The operator div has been called on invalid operand types [err:XPTY0004]")); } return 0; }
Result XQNameExpression::createResult(DynamicContext* context, int flags) const { AnyAtomicType::Ptr itemName = getExpression()->createResult(context)->next(context); switch(itemName->getPrimitiveTypeIndex()) { case AnyAtomicType::QNAME: return (Item::Ptr)itemName; case AnyAtomicType::STRING: case AnyAtomicType::UNTYPED_ATOMIC: try { return (Item::Ptr)context->getItemFactory()->createDerivedFromAtomicType(AnyAtomicType::QNAME, itemName->asString(context), context); } catch(XQException &) { XQThrow(ASTException,X("XQNameExpression::NameExpressionResult::createResult"), X("The name expression cannot be converted to a xs:QName [err:XQDY0074]")); } default: break; } XMLBuffer buf; buf.set(X("The name expression must be a single xs:QName, xs:string or xs:untypedAtomic")); buf.append(X(" - found item of type ")); itemName->typeToBuffer(context, buf); buf.append(X(" [err:XPTY0004]")); XQThrow(XPath2TypeMatchException, X("XQNameExpression::NameExpressionResult::createResult"), buf.getRawBuffer()); }
ASTNode *XQNamespaceConstructor::staticTypingImpl(StaticContext *context) { _src.clear(); _src.add(m_name->getStaticAnalysis()); if(m_name->getStaticAnalysis().isUpdating()) { XQThrow(StaticErrorException,X("XQNamespaceConstructor::staticTyping"), X("It is a static error for the name expression of an namespace constructor " "to be an updating expression [err:XUST0001]")); } unsigned int i; for(i = 0; i < m_children->size(); ++i) { _src.add((*m_children)[i]->getStaticAnalysis()); if((*m_children)[i]->getStaticAnalysis().isUpdating()) { XQThrow(StaticErrorException,X("XQNamespaceConstructor::staticTyping"), X("It is a static error for the a value expression of an namespace constructor " "to be an updating expression [err:XUST0001]")); } } _src.getStaticType() = StaticType::NAMESPACE_TYPE; _src.creative(true); _src.setProperties(StaticAnalysis::DOCORDER | StaticAnalysis::GROUPED | StaticAnalysis::PEER | StaticAnalysis::SUBTREE | StaticAnalysis::SAMEDOC | StaticAnalysis::ONENODE); return this; }
ASTNode *UTransform::staticTypingImpl(StaticContext *context) { _src.clear(); // Add all the binding variables to the new scope VectorOfCopyBinding::iterator end = bindings_->end(); for(VectorOfCopyBinding::iterator it0 = bindings_->begin(); it0 != end; ++it0) { if((*it0)->expr_->getStaticAnalysis().isUpdating()) { XQThrow(StaticErrorException,X("UTransform::staticTyping"), X("It is a static error for the copy expression of a transform expression " "to be an updating expression [err:XUST0001]")); } } // Call staticTyping on the modify expression _src.add(modify_->getStaticAnalysis()); _src.updating(false); if(!modify_->getStaticAnalysis().isUpdating() && !modify_->getStaticAnalysis().isPossiblyUpdating()) XQThrow(StaticErrorException, X("UTransform::staticTyping"), X("The modify expression is not an updating expression [err:XUST0002]")); // Call staticResolution on the return expression _src.getStaticType() = return_->getStaticAnalysis().getStaticType(); _src.setProperties(return_->getStaticAnalysis().getProperties()); _src.add(return_->getStaticAnalysis()); if(return_->getStaticAnalysis().isUpdating()) { XQThrow(StaticErrorException,X("UTransform::staticTyping"), X("It is a static error for the return expression of a transform expression " "to be an updating expression [err:XUST0001]")); } VectorOfCopyBinding *newBindings = context == 0 ? 0 : new (context->getMemoryManager()) VectorOfCopyBinding(XQillaAllocator<CopyBinding*>(context->getMemoryManager())); VectorOfCopyBinding::reverse_iterator rend = bindings_->rend(); for(VectorOfCopyBinding::reverse_iterator it = bindings_->rbegin(); it != rend; ++it) { // Remove our binding variable from the StaticAnalysis data (removing it if it's not used) if(!_src.removeVariable((*it)->uri_, (*it)->name_)) { (*it)->qname_ = 0; } _src.add((*it)->expr_->getStaticAnalysis()); // Add the new VB at the front of the new Bindings // (If it's a let binding, and it's variable isn't used, don't add it - there's no point) if(newBindings && (*it)->qname_) { CopyBinding *newVB = new (context->getMemoryManager()) CopyBinding(context->getMemoryManager(), **it); newVB->setLocationInfo(*it); newBindings->insert(newBindings->begin(), newVB); } } // Overwrite our bindings with the new ones if(newBindings) bindings_ = newBindings; return this; }
ASTNode *XQIf::staticTypingImpl(StaticContext *context) { _src.clear(); if(_test->getStaticAnalysis().isUpdating()) { XQThrow(StaticErrorException,X("XQIf::staticTyping"), X("It is a static error for the conditional expression of an if expression " "to be an updating expression [err:XUST0001]")); } _src.add(_test->getStaticAnalysis()); _src.getStaticType() = _whenTrue->getStaticAnalysis().getStaticType(); _src.setProperties(_whenTrue->getStaticAnalysis().getProperties()); _src.add(_whenTrue->getStaticAnalysis()); if(_src.isUpdating()) { if(!_whenFalse->getStaticAnalysis().isUpdating() && !_whenFalse->getStaticAnalysis().isPossiblyUpdating()) XQThrow(StaticErrorException, X("XQIf::staticTyping"), X("Mixed updating and non-updating operands [err:XUST0001]")); } else { if(_whenFalse->getStaticAnalysis().isUpdating() && !_whenTrue->getStaticAnalysis().isPossiblyUpdating()) XQThrow(StaticErrorException, X("XQIf::staticTyping"), X("Mixed updating and non-updating operands [err:XUST0001]")); } _src.getStaticType() |= _whenFalse->getStaticAnalysis().getStaticType(); _src.setProperties(_src.getProperties() & _whenFalse->getStaticAnalysis().getProperties()); _src.add(_whenFalse->getStaticAnalysis()); return this; }
Sequence FunctionCompare::createSequence(DynamicContext* context, int flags) const { Sequence str1 = getParamNumber(1,context)->toSequence(context); Sequence str2 = getParamNumber(2,context)->toSequence(context); if(str1.isEmpty() || str2.isEmpty()) return Sequence(context->getMemoryManager()); Collation* collation = NULL; if(getNumArgs()>2) { Sequence collArg = getParamNumber(3,context)->toSequence(context); const XMLCh* collName = collArg.first()->asString(context); try { context->getItemFactory()->createAnyURI(collName, context); } catch(XPath2ErrorException &e) { XQThrow(FunctionException, X("FunctionCompare::createSequence"), X("Invalid argument to compare function")); } collation = context->getCollation(collName, this); if(collation == NULL) XQThrow(FunctionException,X("FunctionCompare::createSequence"),X("Collation object is not available")); } else collation = context->getDefaultCollation(this); if(collation == NULL) collation = context->getCollation(CodepointCollation::getCodepointCollationName(), this); const XMLCh* string1 = str1.first()->asString(context); const XMLCh* string2 = str2.first()->asString(context); Sequence result(context->getItemFactory()->createInteger(collation->compare(string1,string2), context), context->getMemoryManager()); return result; }
ASTNode *XQCastAs::staticTypingImpl(StaticContext *context) { _src.clear(); const SequenceType::ItemType *itemType = _exprType->getItemType(); if(itemType != NULL) { _src.getStaticType() = StaticType::create(_typeIndex); if(_exprType->getOccurrenceIndicator() == SequenceType::QUESTION_MARK) { _src.getStaticType().multiply(0, 1); } } _src.add(_expr->getStaticAnalysis()); if(_typeIndex == AnyAtomicType::QNAME && !_expr->getStaticAnalysis().getStaticType().containsType(StaticType::QNAME_TYPE) && (_exprType->getOccurrenceIndicator() == SequenceType::EXACTLY_ONE || _expr->getStaticAnalysis().getStaticType().containsType(StaticType::ITEM_TYPE))) { XQThrow(TypeErrorException,X("XQCastAs::staticTyping"), X("Only a subtype of xs:QName can be cast to a subtype of xs:QName [err:XPTY0004]")); } if(_typeIndex == AnyAtomicType::NOTATION && !_expr->getStaticAnalysis().getStaticType().containsType(StaticType::NOTATION_TYPE) && (_exprType->getOccurrenceIndicator() == SequenceType::EXACTLY_ONE || _expr->getStaticAnalysis().getStaticType().containsType(StaticType::ITEM_TYPE))) { XQThrow(TypeErrorException,X("XQCastAs::staticTyping"), X("Only a subtype of xs:NOTATION can be cast to a subtype of xs:NOTATION [err:XPTY0004]")); } return this; }
Sequence FunctionDocument::createSequence(DynamicContext* context, int flags) const { const XMLCh *baseURI; if(getNumArgs() == 2) { baseURI = ((Node*)getParamNumber(2, context)->next(context).get())->dmBaseURI(context).first()->asString(context); } else { baseURI = context->getBaseURI(); } Sequence result(context->getMemoryManager()); Result args = getParamNumber(1, context); Item::Ptr uriArg; while((uriArg = args->next(context)).notNull()) { const XMLCh *uri = uriArg->asString(context); if(!XPath2Utils::isValidURI(uri, context->getMemoryManager())) XQThrow(FunctionException, X("FunctionDocument::createSequence"), X("Invalid argument to fn:document function [err:FODC0005]")); try { XMLUri base(baseURI); XMLUri full(&base, uri); uri = context->getMemoryManager()->getPooledString(full.getUriText()); } catch(MalformedURLException &e){ XQThrow(FunctionException, X("FunctionDocument::createSequence"), X("Invalid argument to resolve-uri [err:FORG0002]")); } result.joinSequence(context->resolveDocument(uri, this, context->getProjection() ? queryPathTree_ : 0)); } return result; }
Item::Ptr XQCastAs::CastAsResult::getSingleResult(DynamicContext *context) const { // The semantics of the cast expression are as follows: // 1. Atomization is performed on the input expression. Result toBeCasted(_di->getExpression()->createResult(context)); const Item::Ptr first = toBeCasted->next(context); if(first == NULLRCP) { // 3. If the result of atomization is an empty sequence: // 1. If ? is specified after the target type, the result of the cast expression is an empty sequence. // 2. If ? is not specified after the target type, a type error is raised [err:XPTY0004]. if(_di->getSequenceType()->getOccurrenceIndicator() == SequenceType::EXACTLY_ONE) { XQThrow(TypeErrorException,X("XQCastAs::CastAsResult::getSingleResult"), X("The input to a non-optional cast as expression is an empty sequence [err:XPTY0004]")); } else { return 0; } } const Item::Ptr second = toBeCasted->next(context); // 2. If the result of atomization is a sequence of more than one atomic value, a type error is raised.[err:XPTY0004] if(second != NULLRCP) { XQThrow(TypeErrorException,X("XQCastAs::CastAsResult::getSingleResult"), X("The input to a cast as expression is more than one atomic value [err:XPTY0004]")); } // 4. If the result of atomization is a single atomic value, the result of the cast expression depends on the input type and the target type. // The normative definition of these rules is given in [XQuery 1.0 and XPath 2.0 Functions and Operators]. return _di->cast((const AnyAtomicType*)first.get(), context); }
EventGenerator::Ptr XQNamespaceConstructor::generateEvents(EventHandler *events, DynamicContext *context, bool preserveNS, bool preserveType) const { const XMLCh *nodeName = m_name->createResult(context)->next(context)->asString(context); if(*nodeName && !XMLChar1_0::isValidNCName(nodeName, XMLString::stringLen(nodeName))) XQThrow(ASTException,X("XQNamespaceConstructor::generateEvents"), X("The name for the namespace node must be either a zero-length string or a valid xs:NCName [err:XTDE0920]")); if(XPath2Utils::equals(nodeName, XMLUni::fgXMLNSString)) XQThrow(ASTException,X("XQNamespaceConstructor::generateEvents"), X("The name for the namespace node must not be \"xmlns\" [err:XTDE0920]")); XMLBuffer value; getStringValue(m_children, value, context); if(value.getLen() == 0) XQThrow(ASTException,X("XQNamespaceConstructor::generateEvents"), X("The value for the namespace node must not be empty [err:XTDE0930]")); if(XPath2Utils::equals(nodeName, XMLUni::fgXMLString) && !XPath2Utils::equals(value.getRawBuffer(), XMLUni::fgXMLURIName)) XQThrow(ASTException,X("XQNamespaceConstructor::generateEvents"), X("The name for the namespace node must not be \"xml\" when the value is not \"http://www.w3.org/XML/1998/namespace\" [err:XTDE0925]")); if(XPath2Utils::equals(value.getRawBuffer(), XMLUni::fgXMLURIName) && !XPath2Utils::equals(nodeName, XMLUni::fgXMLString)) XQThrow(ASTException,X("XQNamespaceConstructor::generateEvents"), X("The value for the namespace node must not be \"http://www.w3.org/XML/1998/namespace\" when the name is not \"xml\" [err:XTDE0925]")); events->namespaceEvent(nodeName, value.getRawBuffer()); return 0; }
Sequence FunctionLocalname::createSequence(DynamicContext* context, int flags) const { XPath2MemoryManager* memMgr = context->getMemoryManager(); Node::Ptr ctxNode; if(getNumArgs() == 1) { Sequence arg=getParamNumber(1,context)->toSequence(context); if(arg.isEmpty()) return Sequence(context->getItemFactory()->createString(XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString, context), memMgr); ctxNode=arg.first(); } else { const Item::Ptr item = context->getContextItem(); if(item==NULLRCP) XQThrow(FunctionException, X("FunctionLocalName::createSequence"),X("Undefined context item in fn:local-name [err:XPDY0002]")); if(!item->isNode()) XQThrow(FunctionException, X("FunctionLocalName::createSequence"),X("The context item is not a node [err:XPTY0004]")); ctxNode=item; } ATQNameOrDerived::Ptr name = ctxNode->dmNodeName(context); if(name.notNull()) return Sequence(context->getItemFactory()->createString(((const ATQNameOrDerived*)name.get())->getName(), context), memMgr); return Sequence(context->getItemFactory()->createString(XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString, context), memMgr); }
Item::Ptr PromoteAnyURIResult::next(DynamicContext *context) { Item::Ptr item = parent_->next(context); if(item.notNull()) { assert(item->isAtomicValue()); const AnyAtomicType *atomic = (const AnyAtomicType *)item.get(); // 4. For each item of type xs:anyURI in the atomic sequence that can be promoted to the expected atomic // type using URI promotion as described in B.1 Type Promotion, the promotion is done. if(atomic->getPrimitiveTypeIndex() == AnyAtomicType::ANY_URI) { try { item = atomic->castAs(AnyAtomicType::STRING, context); } catch (XPath2TypeCastException &e) { XQThrow(XPath2ErrorException, X("SequenceType::AtomicTypeConvertFunctionArgResult::next"), X("AnyURI type promotion failed (for promotable type)")); } catch (const XMLException& e) { XQThrow(XPath2ErrorException, X("SequenceType::AtomicTypeConvertFunctionArgResult::next"), X("AnyURI type promotion failed (for promotable type)")); } } } else { parent_ = 0; } return item; }
Item::Ptr PromoteNumericResult::next(DynamicContext *context) { Item::Ptr item = parent_->next(context); if(item.notNull()) { assert(item->isAtomicValue()); const AnyAtomicType *atomic = (const AnyAtomicType *)item.get(); // 3. For each numeric item in the atomic sequence that can be promoted to the expected atomic type using // the promotion rules in B.1 Type Promotion, the promotion is done. if(atomic->isNumericValue()) { try { const Numeric::Ptr promotedType = ((const Numeric*)atomic)-> promoteTypeIfApplicable(typeIndex_, context); if(promotedType.notNull()) { item = promotedType; } } catch (XPath2TypeCastException &e) { XQThrow(XPath2ErrorException, X("SequenceType::AtomicTypeConvertFunctionArgResult::next"), X("Numeric type promotion failed (for promotable type)")); } catch (const XMLException& e) { XQThrow(XPath2ErrorException, X("SequenceType::AtomicTypeConvertFunctionArgResult::next"), X("Numeric type promotion failed (for promotable type)")); } } } else { parent_ = 0; } return item; }
ASTNode *URename::staticTypingImpl(StaticContext *context) { _src.clear(); _src.add(target_->getStaticAnalysis()); if(target_->getStaticAnalysis().isUpdating()) { XQThrow(StaticErrorException,X("URename::staticTyping"), X("It is a static error for the target expression of a rename expression " "to be an updating expression [err:XUST0001]")); } if(!target_->getStaticAnalysis().getStaticType(). containsType(StaticType::ELEMENT_TYPE|StaticType::ATTRIBUTE_TYPE|StaticType::PI_TYPE)) { XQThrow(XPath2TypeMatchException,X("URename::staticTyping"), X("It is a type error for the target expression of a rename expression not to be a single element, " "attribute or processing instruction [err:XUTY0012]")); } _src.add(name_->getStaticAnalysis()); if(name_->getStaticAnalysis().isUpdating()) { XQThrow(StaticErrorException,X("URename::staticTyping"), X("It is a static error for the name expression of a rename expression " "to be an updating expression [err:XUST0001]")); } _src.updating(true); return this; }
ASTNode *Intersect::staticTypingImpl(StaticContext *context) { _src.clear(); _src.copy(_args[0]->getStaticAnalysis()); if(_args[0]->getStaticAnalysis().isUpdating()) { XQThrow(StaticErrorException,X("Intersect::staticTyping"), X("It is a static error for an operand of an operator " "to be an updating expression [err:XUST0001]")); } _src.add(_args[1]->getStaticAnalysis()); _src.getStaticType().typeNodeIntersect(_args[1]->getStaticAnalysis().getStaticType()); _src.getStaticType().multiply(0, 1); if(_args[1]->getStaticAnalysis().isUpdating()) { XQThrow(StaticErrorException,X("Intersect::staticTyping"), X("It is a static error for an operand of an operator " "to be an updating expression [err:XUST0001]")); } return this; }
PendingUpdateList UInsertAsLast::createUpdateList(DynamicContext *context) const { Node::Ptr node = (Node*)target_->createResult(context)->next(context).get(); if(node->dmNodeKind() != Node::element_string && node->dmNodeKind() != Node::document_string) XQThrow(XPath2TypeMatchException,X("UInsertAsLast::createUpdateList"), X("It is a type error for the target expression of an insert as last expression not to be a single element " "or document [err:XUTY0005]")); Sequence alist(context->getMemoryManager()); Sequence clist(context->getMemoryManager()); Result value = source_->createResult(context); Item::Ptr item; while((item = value->next(context)).notNull()) { if(((Node*)item.get())->dmNodeKind() == Node::attribute_string) { if(!clist.isEmpty()) XQThrow(ASTException,X("UInsertAsLast::createUpdateList"), X("Attribute nodes must occur before other nodes in the source expression for an insert as last expression [err:XUTY0004]")); // b. No attribute node in $alist may have a QName whose implied namespace binding conflicts with a namespace // binding in the "namespaces" property of $target [err:XUDY0023]. ATQNameOrDerived::Ptr qname = ((Node*)item.get())->dmNodeName(context); if(qname->getURI() != 0 && *(qname->getURI()) != 0) { ATAnyURIOrDerived::Ptr uri = FunctionNamespaceURIForPrefix::uriForPrefix(qname->getPrefix(), node, context, this); if(uri.notNull() && !XPath2Utils::equals(uri->asString(context), qname->getURI())) { XMLBuffer buf; buf.append(X("Implied namespace binding for the insert as last expression (\"")); buf.append(qname->getPrefix()); buf.append(X("\" -> \"")); buf.append(qname->getURI()); buf.append(X("\") conflicts with those already existing on the parent element of the target attribute [err:XUDY0023]")); XQThrow3(DynamicErrorException, X("UInsertInto::createUpdateList"), buf.getRawBuffer(), this); } } alist.addItem(item); } else clist.addItem(item); } PendingUpdateList result; if(!alist.isEmpty()) { // 3. If $alist is not empty and into is specified, the following checks are performed: // a. $target must be an element node [err:XUTY0022]. if(node->dmNodeKind() == Node::document_string) XQThrow(XPath2TypeMatchException,X("UInsertInto::createUpdateList"), X("It is a type error if an insert expression specifies the insertion of an attribute node into a document node [err:XUTY0022]")); result.addUpdate(PendingUpdate(PendingUpdate::INSERT_ATTRIBUTES, node, alist, this)); } if(!clist.isEmpty()) { result.addUpdate(PendingUpdate(PendingUpdate::INSERT_INTO_AS_LAST, node, clist, this)); } return result; }
PendingUpdateList UReplaceValueOf::createUpdateList(DynamicContext *context) const { Node::Ptr node = (Node*)target_->createResult(context)->next(context).get(); if(node->dmNodeKind() == Node::document_string) XQThrow(XPath2TypeMatchException,X("UReplaceValueOf::createUpdateList"), X("The target expression of a replace expression does not return a single " "node that is not a document node [err:XUTY0008]")); XMLBuffer buf; XQDOMConstructor::getStringValue(expr_, buf, context); // If $target is a comment node, and $string contains two adjacent hyphens or ends with a hyphen, a dynamic error is raised [err:XQDY0072]. if(node->dmNodeKind() == Node::comment_string) { bool foundOne = false; for(const XMLCh *str = buf.getRawBuffer(); *str; ++str) { if(*str == '-') { if(foundOne) { XQThrow(DynamicErrorException,X("UReplaceValueOf::createUpdateList"), X("The replace value of expression would result in a comment node whose content contains two adjacent hyphens [err:XQDY0072]")); } else foundOne = true; } else { foundOne = false; } } if(foundOne) { XQThrow(DynamicErrorException,X("UReplaceValueOf::createUpdateList"), X("The replace value of expression would result in a comment node whose content ends with a hyphen [err:XQDY0072]")); } } // If $target is a processing instruction node, and $string contains the substring "?>", a dynamic error is raised [err:XQDY0026]. else if(node->dmNodeKind() == Node::processing_instruction_string) { bool foundQuestion = false; for(const XMLCh *str = buf.getRawBuffer(); *str; ++str) { if(*str == '?') { foundQuestion = true; } else { if(foundQuestion && *str == '>') { XQThrow(DynamicErrorException,X("UReplaceValueOf::createUpdateList"), X("The replace value of expression would result in a processing instruction node whose content includes the string \"?>\" [err:XQDY0026]")); } foundQuestion = false; } } } Item::Ptr value = context->getItemFactory()->createString(buf.getRawBuffer(), context); if(node->dmNodeKind() == Node::element_string) { return PendingUpdate(PendingUpdate::REPLACE_ELEMENT_CONTENT, node, value, this); } else { return PendingUpdate(PendingUpdate::REPLACE_VALUE, node, value, this); } }
ASTNode* XQCastAs::staticResolution(StaticContext *context) { XPath2MemoryManager *mm = context->getMemoryManager(); _exprType->staticResolution(context); const SequenceType::ItemType *itemType = _exprType->getItemType(); if(itemType != NULL) { if((XPath2Utils::equals(itemType->getTypeURI(), XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA) && XPath2Utils::equals(itemType->getType()->getName(), szNOTATION)) || (XPath2Utils::equals(itemType->getTypeURI(), FunctionConstructor::XMLChXPath2DatatypesURI) && XPath2Utils::equals(itemType->getType()->getName(), AnyAtomicType::fgDT_ANYATOMICTYPE))) XQThrow(TypeErrorException,X("XQCastAs::CastAsResult::getSingleResult"), X("The target type of a cast expression must be an atomic type that is in the in-scope schema types and is not xs:NOTATION or xdt:anyAtomicType [err:XPST0080]")); } if(_exprType->getItemTestType() != SequenceType::ItemType::TEST_ATOMIC_TYPE) XQThrow(TypeErrorException,X("XQCastAs::staticResolution"),X("Cannot cast to a non atomic type")); _typeIndex = context->getItemFactory()-> getPrimitiveTypeIndex(_exprType->getTypeURI(), _exprType->getConstrainingType()->getName(), _isPrimitive); // If this is a cast to xs:QName or xs:NOTATION and the argument is a string literal // evaluate immediately, since they aren't allowed otherwise if((_typeIndex == AnyAtomicType::QNAME || _typeIndex == AnyAtomicType::NOTATION) && _expr->getType() == LITERAL && ((XQLiteral*)_expr)->getPrimitiveType() == AnyAtomicType::STRING) { AutoDelete<DynamicContext> dContext(context->createDynamicContext()); dContext->setMemoryManager(mm); AnyAtomicType::Ptr item = (AnyAtomicType*)_expr->createResult(dContext)->next(dContext).get(); try { if(_isPrimitive) { item = item->castAsNoCheck(_typeIndex, 0, 0, dContext); } else { item = item->castAsNoCheck(_typeIndex, _exprType->getTypeURI(), _exprType->getConstrainingType()->getName(), dContext); } } catch(XQException &e) { if(e.getXQueryLine() == 0) e.setXQueryPosition(this); throw; } return XQLiteral::create(item, dContext, mm, this)->staticResolution(context); } _expr = new (mm) XQAtomize(_expr, mm); _expr->setLocationInfo(this); _expr = _expr->staticResolution(context); return this; }
PendingUpdateList URename::createUpdateList(DynamicContext *context) const { Node::Ptr node = (Node*)target_->createResult(context)->next(context).get(); if(node->dmNodeKind() != Node::element_string && node->dmNodeKind() != Node::attribute_string && node->dmNodeKind() != Node::processing_instruction_string) XQThrow(XPath2TypeMatchException,X("URename::createUpdateList"), X("It is a type error for the target expression of a rename expression not to be a single element, " "attribute or processing instruction [err:XUTY0012]")); ATQNameOrDerived::Ptr qname = (ATQNameOrDerived*)name_->createResult(context)->next(context).get(); // 3. The following checks are performed for error conditions: // a. If $target is an element node, the "namespaces" property of $target must not include any namespace binding that conflicts // with the implied namespace binding of $QName [err:XUDY0023]. if(node->dmNodeKind() == Node::element_string) { ATAnyURIOrDerived::Ptr uri = FunctionNamespaceURIForPrefix::uriForPrefix(qname->getPrefix(), node, context, this); if(uri.notNull() && !XPath2Utils::equals(uri->asString(context), qname->getURI())) { XMLBuffer buf; buf.append(X("Implied namespace binding for the rename expression (\"")); buf.append(qname->getPrefix()); buf.append(X("\" -> \"")); buf.append(qname->getURI()); buf.append(X("\") conflicts with those already existing on the target element [err:XUDY0023]")); XQThrow3(DynamicErrorException, X("URename::createUpdateList"), buf.getRawBuffer(), this); } } // b. If $target is an attribute node that has a parent, the "namespaces" property of parent($target) must not include any // namespace binding that conflicts with the implied namespace binding of $QName [err:XUDY0023]. else if(node->dmNodeKind() == Node::attribute_string) { Node::Ptr parentNode = node->dmParent(context); if(parentNode.notNull() && qname->getURI() != 0 && *(qname->getURI()) != 0) { ATAnyURIOrDerived::Ptr uri = FunctionNamespaceURIForPrefix::uriForPrefix(qname->getPrefix(), parentNode, context, this); if(uri.notNull() && !XPath2Utils::equals(uri->asString(context), qname->getURI())) { XMLBuffer buf; buf.append(X("Implied namespace binding for the rename expression (\"")); buf.append(qname->getPrefix()); buf.append(X("\" -> \"")); buf.append(qname->getURI()); buf.append(X("\") conflicts with those already existing on the parent element of the target attribute [err:XUDY0023]")); XQThrow3(DynamicErrorException, X("URename::createUpdateList"), buf.getRawBuffer(), this); } } } // c. If $target is processing instruction node, $QName must not include a non-empty namespace prefix. [err:XUDY0025]. else if(node->dmNodeKind() == Node::processing_instruction_string && !XPath2Utils::equals(qname->getPrefix(), XMLUni::fgZeroLenString)) XQThrow(XPath2TypeMatchException,X("URename::createUpdateList"), X("The target of a rename expression is a processing instruction node, and the new name " "expression returned a QName with a non-empty namespace prefix [err:XUDY0025]")); return PendingUpdate(PendingUpdate::RENAME, node, qname, this); }
Sequence FunctionDocAvailable::createSequence(DynamicContext* context, int flags) const { Sequence uriArg = getParamNumber(1,context)->toSequence(context); if (uriArg.isEmpty()) { return Sequence(context->getMemoryManager()); } const XMLCh* uri = uriArg.first()->asString(context); // on Windows, we can have URIs using \ instead of /; let's normalize them XMLCh backSlash[]={ XERCES_CPP_NAMESPACE_QUALIFIER chBackSlash, XERCES_CPP_NAMESPACE_QUALIFIER chNull }; if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::findAny(uri,backSlash)) { XMLCh* newUri=XERCES_CPP_NAMESPACE_QUALIFIER XMLString::replicate(uri,context->getMemoryManager()); for(unsigned int i=0;i<XERCES_CPP_NAMESPACE_QUALIFIER XMLString::stringLen(newUri);i++) if(newUri[i]==XERCES_CPP_NAMESPACE_QUALIFIER chBackSlash) newUri[i]=XERCES_CPP_NAMESPACE_QUALIFIER chForwardSlash; uri=newUri; } if(!XPath2Utils::isValidURI(uri, context->getMemoryManager())) XQThrow(FunctionException, X("FunctionDocAvailable::createSequence"), X("Invalid argument to fn:doc-available function [err:FODC0005]")); bool bSuccess=false; try { bSuccess = !context->resolveDocument(uri, this).isEmpty(); } catch(...) { } return Sequence(context->getItemFactory()->createBoolean(bSuccess, context), context->getMemoryManager()); }
BoolResult FunctionDocAvailable::boolResult(DynamicContext* context) const { Sequence uriArg = getParamNumber(1,context)->toSequence(context); if (uriArg.isEmpty()) return false; const XMLCh* uri = uriArg.first()->asString(context); // on Windows, we can have URIs using \ instead of /; let's normalize them XMLCh backSlash[]={ chBackSlash, chNull }; if(XMLString::findAny(uri,backSlash)) { XMLCh* newUri=XMLString::replicate(uri,context->getMemoryManager()); for(unsigned int i=0;i<XMLString::stringLen(newUri);i++) if(newUri[i]==chBackSlash) newUri[i]=chForwardSlash; uri=newUri; } if(!XPath2Utils::isValidURI(uri, context->getMemoryManager())) XQThrow(FunctionException, X("FunctionDocAvailable::createSequence"), X("Invalid argument to fn:doc-available function [err:FODC0005]")); try { return !context->resolveDocument(uri, this).isEmpty(); } catch(...) { } return false; }
Item::Ptr DistinctValueResult::next(DynamicContext *context) { if(toDo_) { toDo_ = false; parent_ = fdv_->getParamNumber(1, context); Collation *collation; if(fdv_->getNumArgs() > 1) { const XMLCh* collName = fdv_->getParamNumber(2, context)->next(context)->asString(context); try { context->getItemFactory()->createAnyURI(collName, context); } catch(XPath2ErrorException &e) { XQThrow(FunctionException, X("FunctionDistinctValues::DistinctValueResult::next"), X("Invalid collationURI")); } collation = context->getCollation(collName, this); } else collation = context->getDefaultCollation(this); alreadySeen_ = new DistinctSet(dvCompare(collation, context)); } AnyAtomicType::Ptr item; while(true) { item = (const AnyAtomicType *)parent_->next(context).get(); if(item.isNull()) break; if(alreadySeen_->insert(item).second) return item; } parent_ = 0; return 0; }
Item::Ptr AtomizeResult::next(DynamicContext *context) { // for $item in (Expr) return // typeswitch ($item) // case $value as atomic value return $value // default $node return fn:data($node) Item::Ptr result = _sub->next(context); while(result.isNull()) { _sub = 0; result = _parent->next(context); if(result.isNull()) { _parent = 0; return 0; } if(result->isNode()) { _sub = ((Node*)result.get())->dmTypedValue(context); result = _sub->next(context); } else if(result->isFunction()) { XMLBuffer buf; buf.set(X("Sequence does not match type (xs:anyAtomicType | node())*")); buf.append(X(" - found item of type ")); result->typeToBuffer(context, buf); buf.append(X(" [err:XPTY0004]")); XQThrow(XPath2TypeMatchException, X("AtomizeResult::next"), buf.getRawBuffer()); } } return result; }
Sequence FunctionAdjustTimeToTimezone::createSequence(DynamicContext* context, int flags) const { XPath2MemoryManager* memMgr = context->getMemoryManager(); //If $srcval is the empty sequence, then the result is the empty sequence. Sequence op1 = getParamNumber(1, context)->toSequence(context); if (op1.isEmpty()) { return Sequence(memMgr); } const ATTimeOrDerived* time = (const ATTimeOrDerived*)(const Item*)op1.first(); //If $timezone is not specified, then $timezone is the value of the implicit timezone in the evaluation context. ATDurationOrDerived::Ptr timezoneAsDuration = 0; if (getNumArgs() > 1) { Sequence op2 = getParamNumber(2, context)->toSequence(context); if (op2.isEmpty()) { // unset the timezone return Sequence(time->setTimezone(0, context), memMgr); } else { timezoneAsDuration = (const ATDurationOrDerived::Ptr )op2.first(); Timezone::Ptr timezone = new Timezone(timezoneAsDuration, context); if(!timezoneAsDuration->equals(timezone->asDayTimeDuration(context), context)) { XQThrow(FunctionException, X("FunctionAdjustTimeToTimeZone::createSequence"),X("Invalid timezone value [err:FODT0003]")); } } } else { timezoneAsDuration = context->getImplicitTimezone(); } return Sequence(time->addTimezone(timezoneAsDuration, context), memMgr); }
TupleNode *ForTuple::staticResolution(StaticContext *context) { parent_ = parent_->staticResolution(context); varURI_ = context->getUriBoundToPrefix(XPath2NSUtils::getPrefix(varQName_, context->getMemoryManager()), this); varName_ = XPath2NSUtils::getLocalName(varQName_); if(posQName_ && *posQName_) { posURI_ = context->getUriBoundToPrefix(XPath2NSUtils::getPrefix(posQName_, context->getMemoryManager()), this); posName_ = XPath2NSUtils::getLocalName(posQName_); if(XPath2Utils::equals(posName_, varName_) && XPath2Utils::equals(posURI_, varURI_)) { XMLBuffer errMsg; errMsg.set(X("The positional variable with name {")); errMsg.append(posURI_); errMsg.append(X("}")); errMsg.append(posName_); errMsg.append(X(" conflicts with the iteration variable [err:XQST0089]")); XQThrow(StaticErrorException,X("ForTuple::staticResolution"), errMsg.getRawBuffer()); } } expr_ = expr_->staticResolution(context); return this; }
EventGenerator::Ptr XQAttributeConstructor::generateEvents(EventHandler *events, DynamicContext *context, bool preserveNS, bool preserveType) const { AnyAtomicType::Ptr itemName = m_name->createResult(context)->next(context); const ATQNameOrDerived* pQName = (const ATQNameOrDerived*)itemName.get(); const XMLCh *prefix = pQName->getPrefix(); const XMLCh *uri = pQName->getURI(); const XMLCh *name = pQName->getName(); if((uri==NULL && XPath2Utils::equals(name, XMLUni::fgXMLNSString)) || XPath2Utils::equals(uri, XMLUni::fgXMLNSURIName)) XQThrow(ASTException,X("DOM Constructor"),X("A computed attribute constructor cannot create a namespace declaration [err:XQDY0044]")); XMLBuffer value; getStringValue(m_children, value, context); const XMLCh *typeURI = SchemaSymbols::fgURI_SCHEMAFORSCHEMA; const XMLCh *typeName = ATUntypedAtomic::fgDT_UNTYPEDATOMIC; // check if it's xml:id static const XMLCh id[] = { 'i', 'd', 0 }; if(XPath2Utils::equals(name, id) && XPath2Utils::equals(uri, XMLUni::fgXMLURIName)) { // If the attribute name is xml:id, the string value and typed value of the attribute are further normalized by // discarding any leading and trailing space (#x20) characters, and by replacing sequences of space (#x20) characters // by a single space (#x20) character. XMLString::collapseWS(value.getRawBuffer(), context->getMemoryManager()); typeURI = SchemaSymbols::fgURI_SCHEMAFORSCHEMA; typeName = XMLUni::fgIDString; } events->attributeEvent(emptyToNull(prefix), emptyToNull(uri), name, value.getRawBuffer(), typeURI, typeName); return 0; }
ASTNode* XQFunctionCall::staticResolution(StaticContext *context) { if(uri_ == 0) { if(prefix_ == 0 || *prefix_ == 0) { uri_ = context->getDefaultFuncNS(); } else { uri_ = context->getUriBoundToPrefix(prefix_, this); } } ASTNode *result = context->lookUpFunction(uri_, name_, *args_, this); if(result == 0) { XMLBuffer buf; buf.set(X("A function called {")); buf.append(uri_); buf.append(X("}")); buf.append(name_); buf.append(X(" with ")); XPath2Utils::numToBuf(args_ ? (unsigned int)args_->size() : 0, buf); buf.append(X(" arguments is not defined [err:XPST0017]")); XQThrow(StaticErrorException, X("XQFunctionCall::staticResolution"), buf.getRawBuffer()); } // Our arguments don't belong to us anymore for(VectorOfASTNodes::iterator i = args_->begin(); i != args_->end(); ++i) { *i = 0; } // Release this object this->release(); return result->staticResolution(context); }
void XQGlobalVariable::staticTyping(StaticContext* context, StaticTyper *styper) { VariableTypeStore* varStore = context->getVariableTypeStore(); if(m_Value != NULL) { XQUserFunction::staticTypeFunctionCalls(m_Value, context, styper); m_Value = m_Value->staticTyping(context, styper); _src.copy(m_Value->getStaticAnalysis()); if(m_Value->getStaticAnalysis().isUpdating()) { XQThrow(StaticErrorException,X("XQGlobalVariable::staticTyping"), X("It is a static error for the initializing expression of a global variable " "to be an updating expression [err:XUST0001]")); } } if(m_Value == 0 || !required_) { if(m_Type != 0) { bool isPrimitive; m_Type->getStaticType(_src.getStaticType(), context, isPrimitive, m_Type); } else { _src.getStaticType() = StaticType(StaticType::ITEM_TYPE, 0, StaticType::UNLIMITED); } } varStore->declareGlobalVar(m_szURI, m_szLocalName, _src); }