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; }
Numeric::Ptr NumericFunction::getNumericParam(unsigned int number, DynamicContext *context, int flags) const { Result arg = XQFunction::getParamNumber(number, context, flags); Item::Ptr item = arg->next(context); if(item.isNull()) { return 0; } else if(item->isAtomicValue() && ((const AnyAtomicType *)item.get())->isNumericValue()) { return (const Numeric *)item.get(); } else { XQThrow(FunctionException,X("NumericFunction::getParamNumber"), X("Non-numeric argument in numeric function [err:XPTY0004]")); } }
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); }
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; }
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; }
Item::Ptr PromoteUntypedResult::next(DynamicContext *context) { Item::Ptr item = parent_->next(context); if(item.notNull()) { assert(item->isAtomicValue()); const AnyAtomicType *atomic = (const AnyAtomicType *)item.get(); // 2. Each item in the atomic sequence that is of type xdt:untypedAtomic is cast to the expected atomic // type. For built-in functions where the expected type is specified as numeric, arguments of type // xdt:untypedAtomic are cast to xs:double. if(atomic->getPrimitiveTypeIndex() == AnyAtomicType::UNTYPED_ATOMIC) { try { if(isPrimitive_) { item = atomic->castAs(typeIndex_, 0, 0, context); } else { item = atomic->castAs(typeIndex_, uri_, name_, context); } } catch(XPath2TypeCastException &e) { if(e.getXQueryLine() == 0) e.setXQueryPosition(this); throw; } } } else { parent_ = 0; } return item; }
Item::Ptr UTransform::TransformResult::next(DynamicContext *context) { context->testInterrupt(); AutoVariableStoreReset reset(context, &scope_); if(toDo_) { toDo_ = false; NodeSet copiedNodes = NodeSet(nodecompare(context)); VectorOfCopyBinding::const_iterator end = transform_->getBindings()->end(); for(VectorOfCopyBinding::const_iterator it = transform_->getBindings()->begin(); it != end; ++it) { if((*it)->qname_ == 0) continue; Sequence values = (*it)->expr_->createResult(context)->toSequence(context); // Keep a record of the nodes that have been copied Result valIt = values; Item::Ptr val; while((val = valIt->next(context)).notNull()) { copiedNodes.insert((Node*)val.get()); } scope_.setVar((*it)->uri_, (*it)->name_, values); } // Get the pending update list PendingUpdateList pul = transform_->getModifyExpr()->createUpdateList(context); // Check that the targets of the pending updates are copied nodes for(PendingUpdateList::const_iterator i = pul.begin(); i != pul.end(); ++i) { Node::Ptr target = i->getTarget(); while(copiedNodes.find(target) == copiedNodes.end()) { target = target->dmParent(context); if(target.isNull()) { XQThrow3(StaticErrorException,X("UTransform::staticTyping"), X("The target node of an update expression in the transform expression is not a node from the copy clauses [err:XUDY0014]"), &(*i)); } } } // Apply the updates AutoDelete<UpdateFactory> ufactory(context->createUpdateFactory()); ufactory->applyUpdates(pul, context, transform_->getRevalidationMode()); // Execute the return expression result_ = transform_->getReturnExpr()->createResult(context); } Item::Ptr result = result_->next(context); if(result.isNull()) { result_ = 0; return 0; } return result; }
EventGenerator::Ptr XQCopy::generateEventsImpl(const Item::Ptr &toBeCopied, EventHandler *events, DynamicContext *context, bool preserveNS, bool preserveType) const { if(!toBeCopied->isNode()) { toBeCopied->generateEvents(events, context, preserveNS, preserveType); return 0; } Node *node = (Node*)toBeCopied.get(); if(node->dmNodeKind() == Node::element_string) { NoInheritFilter niFilter(events, context->getMemoryManager()); if(!inheritNamespaces_) events = &niFilter; AnyAtomicType::Ptr itemName = node->dmNodeName(context); const ATQNameOrDerived *pQName = (const ATQNameOrDerived*)itemName.get(); const XMLCh *prefix = emptyToNull(pQName->getPrefix()); const XMLCh *uri = emptyToNull(pQName->getURI()); const XMLCh *localname = pQName->getName(); events->startElementEvent(prefix, uri, localname); ElemConstructFilter elemFilter(events, this, context->getMemoryManager()); if(copyNamespaces_) { Result nsnodes = node->dmNamespaceNodes(context, this); Item::Ptr ns; while((ns = nsnodes->next(context)).notNull()) { ns->generateEvents(&elemFilter, context, preserveNS, preserveType); } } for(VectorOfASTNodes::const_iterator itCont = children_.begin(); itCont != children_.end (); ++itCont) { (*itCont)->generateAndTailCall(&elemFilter, context, preserveNS, preserveType); } // TBD validation and type - jpcs const XMLCh *typeURI = SchemaSymbols::fgURI_SCHEMAFORSCHEMA; const XMLCh *typeName = DocumentCache::g_szUntyped; events->endElementEvent(prefix, uri, localname, typeURI, typeName); } else if(node->dmNodeKind() == Node::document_string) { events->startDocumentEvent(0, 0); DocConstructFilter filter(events, this); for(VectorOfASTNodes::const_iterator itCont = children_.begin(); itCont != children_.end (); ++itCont) { (*itCont)->generateAndTailCall(&filter, context, preserveNS, preserveType); } events->endDocumentEvent(); } else { node->generateEvents(events, context, preserveNS, preserveType); } return 0; }
Sequence FunctionMinutesFromDateTime::createSequence(DynamicContext* context, int flags) const { XPath2MemoryManager* memMgr = context->getMemoryManager(); Item::Ptr arg = getParamNumber(1, context)->next(context); if(arg.isNull()) return Sequence(memMgr); return Sequence(((const ATDateTimeOrDerived*)arg.get())->getMinutes(context), memMgr); }
Sequence FunctionName::createSequence(DynamicContext* context, int flags) const { XPath2MemoryManager* mm = context->getMemoryManager(); Item::Ptr arg = getParamNumber(1,context)->next(context); if(arg.isNull()) return Sequence(context->getItemFactory()->createString(XMLUni::fgZeroLenString, context), mm); return Sequence(FunctionString::string_item(((Node*)arg.get())->dmNodeName(context), context), mm); }
PendingUpdateList UDelete::createUpdateList(DynamicContext *context) const { PendingUpdateList pul; Result targets = expr_->createResult(context); Item::Ptr item; while((item = targets->next(context)).notNull()) { pul.addUpdate(PendingUpdate(PendingUpdate::PUDELETE, (Node*)item.get(), this)); } return pul; }
bool SequenceType::ItemType::matchesNameType(const Item::Ptr &toBeTested, const DynamicContext* context) const { // Check name constraint if(m_pName) { if(toBeTested->isNode()) { ATQNameOrDerived::Ptr name = ((const Node*)(const Item*)toBeTested)->dmNodeName(context); if(name.isNull()) return false; // Match node name if(!(XPath2Utils::equals(m_pName->getName(), ((const ATQNameOrDerived*)name.get())->getName()))) return false; // Match node uri if(!(XPath2Utils::equals(m_NameURI, ((const ATQNameOrDerived*)name.get())->getURI()))) return false; } else return false; } //A named atomic type matches a value if the dynamic type of the //value is the same as the named atomic type or is derived from the //named atomic type by restriction. For example, the ItemType //xs:decimal matches the value 12.34 (a decimal literal); it also //matches a value whose dynamic type is shoesize, if shoesize is an //atomic type derived from xs:decimal. if(m_pType) { if(toBeTested->isAtomicValue()) { return ((AnyAtomicType*)toBeTested.get())->isInstanceOfType(m_TypeURI, m_pType->getName(), context); } else if (toBeTested->isNode()) { return ((Node*)toBeTested.get())->hasInstanceOfType(m_TypeURI, m_pType->getName(), context); } return false; } return true; }
bool SequenceType::ItemType::matches(const Item::Ptr &toBeTested, DynamicContext* context) const { if(toBeTested->isNode()) return matches((const Node::Ptr)toBeTested, context); switch(m_nTestType) { case TEST_ELEMENT: case TEST_ATTRIBUTE: case TEST_SCHEMA_ELEMENT: case TEST_SCHEMA_ATTRIBUTE: case TEST_NODE: case TEST_PI: case TEST_COMMENT: case TEST_TEXT: case TEST_DOCUMENT: case TEST_SCHEMA_DOCUMENT: { return false; } case TEST_ANYTHING: { return true; } case TEST_ATOMIC_TYPE: { if(!toBeTested->isAtomicValue()) return false; return matchesNameType(toBeTested, context); } case TEST_FUNCTION: { if(!toBeTested->isFunction()) return false; if(returnType_ == 0) return true; FunctionRef *func = (FunctionRef*)toBeTested.get(); if(func->getNumArgs() != argTypes_->size()) return false; return true; } } return true; }
Item::Ptr next(DynamicContext *context) { Item::Ptr result; while((result = stepResult_->next(context)).isNull()) { context->testInterrupt(); Item::Ptr item = parent_->next(context); if(item.isNull()) { return 0; } if(!item->isNode()) { XQThrow(TypeErrorException,X("StepResult::next"), X("An attempt was made to perform an axis step when the Context Item was not a node [err:XPTY0020]")); } stepResult_ = ((Node*)item.get())->getAxisResult(step_->getAxis(), step_->getNodeTest(), context, this); } return result; }
bool XQLiteral::isDateOrTimeAndHasNoTimezone(StaticContext *context) const { switch(primitiveType_) { case AnyAtomicType::DATE: case AnyAtomicType::DATE_TIME: case AnyAtomicType::TIME: case AnyAtomicType::G_DAY: case AnyAtomicType::G_MONTH: case AnyAtomicType::G_MONTH_DAY: case AnyAtomicType::G_YEAR: case AnyAtomicType::G_YEAR_MONTH: { if(context == 0) return true; AutoDelete<DynamicContext> dContext(context->createDynamicContext()); dContext->setMemoryManager(context->getMemoryManager()); Item::Ptr item = dContext->getItemFactory()->createDerivedFromAtomicType(primitiveType_, typeURI_, typeName_, value_, dContext); return !((const DateOrTimeType*)item.get())->hasTimezone(); } default: break; } return false; }