zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #22627
[Merge] lp:~zorba-coders/zorba/bug-1181360 into lp:zorba
Luis Rodriguez Gonzalez has proposed merging lp:~zorba-coders/zorba/bug-1181360 into lp:zorba.
Requested reviews:
Luis Rodriguez Gonzalez (kuraru)
Cezar Andrei (cezar-andrei)
Related bugs:
Bug #1181360 in Zorba: "validation leaks exception"
https://bugs.launchpad.net/zorba/+bug/1181360
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/bug-1181360/+merge/166946
--
https://code.launchpad.net/~zorba-coders/zorba/bug-1181360/+merge/166946
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'src/diagnostics/diagnostic_en.xml'
--- src/diagnostics/diagnostic_en.xml 2013-05-24 22:52:47 +0000
+++ src/diagnostics/diagnostic_en.xml 2013-06-01 18:12:28 +0000
@@ -3676,6 +3676,10 @@
<entry key="DocNodeMultipleElements">
<value>document node has more than one element</value>
</entry>
+
+ <entry key="DocNodeNoElements">
+ <value>document node doesn't contain any elements, must contain exactly one element</value>
+ </entry>
<entry key="EBVNotDefSeq_5">
<value>effective boolean value not defined for sequence of more than one item that starts with "$5"</value>
=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
--- src/diagnostics/pregenerated/dict_en.cpp 2013-05-24 22:52:47 +0000
+++ src/diagnostics/pregenerated/dict_en.cpp 2013-06-01 18:12:28 +0000
@@ -610,6 +610,7 @@
{ "~DivisionNoINF", "division can not have +-INF dividend" },
{ "~DivisionNoNaN", "division can not involve NaN" },
{ "~DocNodeMultipleElements", "document node has more than one element" },
+ { "~DocNodeNoElements", "document node doesn't contain any elements, must contain exactly one element" },
{ "~EBVNotDefSeq_5", "effective boolean value not defined for sequence of more than one item that starts with \"$5\"" },
{ "~EffectiveBooleanValue", "effective boolean value" },
{ "~ElementName", "element name" },
=== modified file 'src/diagnostics/pregenerated/dict_zed_keys.h'
--- src/diagnostics/pregenerated/dict_zed_keys.h 2013-05-16 22:26:07 +0000
+++ src/diagnostics/pregenerated/dict_zed_keys.h 2013-06-01 18:12:28 +0000
@@ -223,6 +223,7 @@
#define ZED_DivisionNoINF "~DivisionNoINF"
#define ZED_DivisionNoNaN "~DivisionNoNaN"
#define ZED_DocNodeMultipleElements "~DocNodeMultipleElements"
+#define ZED_DocNodeNoElements "~DocNodeNoElements"
#define ZED_EBVNotDefSeq_5 "~EBVNotDefSeq_5"
#define ZED_EffectiveBooleanValue "~EffectiveBooleanValue"
#define ZED_ElementName "~ElementName"
=== modified file 'src/types/schema/SchemaValidatorFilter.cpp'
--- src/types/schema/SchemaValidatorFilter.cpp 2013-04-24 21:40:21 +0000
+++ src/types/schema/SchemaValidatorFilter.cpp 2013-06-01 18:12:28 +0000
@@ -1077,6 +1077,7 @@
else
{
const ElemStack::StackElem* topElem = fElemStack.topElement();
+
DatatypeValidator *currentDV = 0;
if(topElem->fThisElement->isDeclared() ||
theXsiType // this is when there is no schema import but xsiType is used
=== added file 'src/types/schema/validate.cpp'
--- src/types/schema/validate.cpp 1970-01-01 00:00:00 +0000
+++ src/types/schema/validate.cpp 2013-06-01 18:12:28 +0000
@@ -0,0 +1,896 @@
+/*
+* Copyright 2006-2008 The FLWOR Foundation.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+#include "stdafx.h"
+
+#include "validate.h"
+
+#include "diagnostics/xquery_diagnostics.h"
+
+#include "system/globalenv.h"
+
+#include "types/casting.h"
+#include "types/typeops.h"
+
+#ifndef ZORBA_NO_XMLSCHEMA
+
+#include "types/schema/schema.h"
+#include "types/schema/SchemaValidatorFilter.h"
+#include "types/schema/EventSchemaValidator.h"
+#include "types/schema/StrX.h"
+#include "types/schema/revalidateUtils.h"
+
+#include "zorbatypes/duration.h"
+#include "zorbatypes/datetime.h"
+
+#endif
+
+#include "api/unmarshaller.h"
+
+#include "compiler/parser/query_loc.h"
+
+#include "store/api/copymode.h"
+#include "store/api/item.h"
+#include "store/api/item_factory.h"
+#include "store/api/iterator.h"
+#include "store/api/store.h"
+
+#include "context/dynamic_context.h"
+#include "context/static_context.h"
+#include "context/namespace_context.h"
+
+#include "diagnostics/assert.h"
+#include "zorba/store_consts.h"
+
+//using namespace std;
+
+namespace zorba
+{
+
+
+bool Validator::effectiveValidationValue(
+ store::Item_t& result,
+ const store::Item_t& sourceNode,
+ const store::Item_t& typeName,
+ TypeManager* typeManager,
+ ParseConstants::validation_mode_t validationMode,
+ const static_context* sctx,
+ const QueryLoc& loc)
+{
+ //cout << "Starting Validation typeManager: " << typeManager <<
+ //endl; cout.flush();
+ try
+ {
+ return realValidationValue(result, sourceNode, typeName,
+ typeManager, validationMode, sctx, loc);
+ }
+ catch (ZorbaException& e)
+ {
+ set_source( e, loc );
+
+ if ( sourceNode->isNode() &&
+ sourceNode->getNodeKind() == store::StoreConsts::documentNode )
+ {
+ zstring baseUri;
+ sourceNode->getDocumentURI(baseUri);
+
+ //e.theDescription += " while validating document '" + baseUri + "'";
+ }
+ throw;
+ }
+}
+
+
+bool Validator::realValidationValue(
+ store::Item_t& result,
+ const store::Item_t& sourceNode,
+ const store::Item_t& typeName,
+ TypeManager* typeManager,
+ ParseConstants::validation_mode_t validationMode,
+ const static_context* sctx,
+ const QueryLoc& loc)
+{
+ xqtref_t type;
+
+ if (!sourceNode->isNode() ||
+ !(sourceNode->getNodeKind()==store::StoreConsts::documentNode ||
+ sourceNode->getNodeKind()==store::StoreConsts::elementNode
+ ) )
+ {
+ throw XQUERY_EXCEPTION( err::XQTY0030, ERROR_LOC( loc ) );
+ }
+
+ // verify number of child elements when source is a document node
+ if (sourceNode->getNodeKind() == store::StoreConsts::documentNode)
+ {
+ //don't allow more than one child element in documents
+ store::Iterator_t child_it;
+ child_it = sourceNode->getChildren();
+ store::Item_t child;
+ int nr_child_elements = 0;
+ while ( child_it->next(child) )
+ {
+ if ( child->isNode() &&
+ child->getNodeKind() == store::StoreConsts::elementNode)
+ {
+ if (nr_child_elements)
+ {
+ throw XQUERY_EXCEPTION(
+ err::XQDY0061,
+ ERROR_PARAMS( ZED( DocNodeMultipleElements ) ),
+ ERROR_LOC( loc )
+ );
+ }
+ nr_child_elements++;
+ }
+ }
+ // if nr_child_elements == 0 thow an error since it means there isn't any child element
+ if(nr_child_elements == 0)
+ {
+ throw XQUERY_EXCEPTION(
+ err::XQDY0061,
+ ERROR_PARAMS( ZED( DocNodeNoElements ) ),
+ ERROR_LOC( loc )
+ );
+ }
+ }
+
+ Schema* schema = typeManager->getSchema();
+
+ if ( !schema )
+ {
+ //cout << "No schema: isNode() " << sourceNode->isNode() << " nodeKind: "<<
+ // sourceNode->getNodeKind() << endl;
+
+ if ( validationMode == ParseConstants::val_dtd_lax)
+ {
+ // when dtd validation enabled avoid using schema object
+ result = sourceNode;
+ return true;
+ }
+ else
+ {
+ // if we got here it basicaly means that there was no import but
+ // validation is used so we need to set up schema in the typeManager anyway
+ // validation has to work for xsiType and built-in types
+
+ TypeManagerImpl* typeManagerImpl = static_cast<TypeManagerImpl*>(typeManager);
+ typeManagerImpl->initializeSchema();
+ schema = typeManager->getSchema();
+ }
+ }
+ else if (validationMode == ParseConstants::val_dtd_lax && !schema->hasXSD())
+ {
+ // when dtd validation enabled avoid using schema object
+ result = sourceNode;
+ return true;
+ }
+
+#ifndef ZORBA_NO_XMLSCHEMA
+
+ EventSchemaValidator schemaValidator =
+ EventSchemaValidator(typeManager,
+ schema->getGrammarPool(),
+ validationMode == ParseConstants::val_lax,
+ loc);
+
+ switch (sourceNode->getNodeKind())
+ {
+ case store::StoreConsts::documentNode:
+ {
+ //cout << "Validate document" << "\n"; cout.flush();
+
+ if ( validationMode == ParseConstants::val_typename )
+ {
+ //cout << "Validate type: " << typeName->getLocalName()
+ // << " @ " << typeName->getNamespace() << "\n"; cout.flush();
+ schemaValidator.startType(typeName);
+ }
+ else
+ {
+ schemaValidator.startDoc();
+
+ store::Iterator_t children = sourceNode->getChildren();
+ store::Item_t child;
+ while ( children->next(child) )
+ {
+ // ask for the type of the element. We don't really need this type here,
+ // but a side-effect of this call is to add the type to the cache.
+ if ( child->isNode() &&
+ child->getNodeKind()==store::StoreConsts::elementNode )
+ {
+ bool nillable;
+ typeManager->getSchema()->
+ createXQTypeFromGlobalElementDecl(typeManager,
+ child->getNodeName(),
+ false,
+ nillable,
+ loc);
+ break;
+ }
+ }
+ }
+
+ zstring docBaseUri;
+ zstring docUri;
+ sourceNode->getBaseURI(docBaseUri);
+ sourceNode->getDocumentURI(docUri);
+
+ store::Item_t newDoc;
+ GENV_ITEMFACTORY->createDocumentNode(newDoc, docBaseUri, docUri);
+
+ processChildren(sctx,
+ typeManager,
+ schemaValidator,
+ newDoc,
+ sourceNode->getChildren(),
+ loc);
+
+ if ( validationMode == ParseConstants::val_typename )
+ {
+ schemaValidator.endType();
+ //cout << "End Validate type: " << typeName->getLocalName()
+ // << " @ " << typeName->getNamespace() << "\n";
+ //cout.flush();
+ }
+ else
+ {
+ schemaValidator.endDoc();
+ }
+
+ //cout << "End Validate doc" << "\n"; cout.flush();
+
+ result = newDoc;
+ result->markValidated();
+ return true;
+ }
+ case store::StoreConsts::elementNode:
+ {
+ if ( validationMode == ParseConstants::val_typename )
+ {
+ //cout << "Validate type: " << typeName->getLocalName() <<" @ "
+ // << typeName->getNamespace() << "\n"; cout.flush();
+
+ schemaValidator.startType(typeName);
+ }
+ else
+ {
+ //cout << "Validate element" << "\n"; cout.flush();
+ schemaValidator.startDoc();
+
+ // ask for the type of the element. We don't really need this type here,
+ // but a side-effect of this call is to add the type to the cache.
+ bool nillable;
+ typeManager->getSchema()->
+ createXQTypeFromGlobalElementDecl(typeManager,
+ sourceNode->getNodeName(),
+ false,
+ nillable,
+ loc);
+ }
+
+ store::Item_t newElem = processElement(sctx,
+ typeManager,
+ schemaValidator,
+ NULL,
+ sourceNode,
+ loc);
+
+ if ( validationMode == ParseConstants::val_typename )
+ {
+ schemaValidator.endType();
+ //cout << "End Validate type: " << typeName->getLocalName()
+ // <<" @ "<< typeName->getNamespace() << "\n";cout.flush();
+ }
+ else
+ {
+ schemaValidator.endDoc();
+ //cout << "End Validate elem" << "\n"; cout.flush();
+ }
+
+ result = newElem;
+ result->markValidated();
+ return true;
+ }
+ default:
+ {
+ throw XQUERY_EXCEPTION( err::XQTY0030, ERROR_LOC( loc ) );
+ }
+ }
+#endif // ZORBA_NO_XMLSCHEMA
+}
+
+
+#ifndef ZORBA_NO_XMLSCHEMA
+
+
+store::Item_t Validator::processElement(
+ const static_context* sctx,
+ TypeManager* typeManager,
+ EventSchemaValidator& schemaValidator,
+ store::Item* parent,
+ const store::Item_t& element,
+ const QueryLoc& loc)
+{
+ ZORBA_ASSERT(element->isNode());
+ ZORBA_ASSERT(element->getNodeKind() == store::StoreConsts::elementNode);
+
+
+ store::Item_t nodeName = element->getNodeName();
+ zstring baseUri;
+ element->getBaseURI(baseUri);
+
+ schemaValidator.startElem(nodeName);
+
+ // namespace declarations must go first
+ processNamespaces( schemaValidator, element);
+
+ // since the type of an element is determined only after the validator
+ // receives all of it's attributes, and an attribute node needs it's parent
+ // when created we need to go through the attributes twice: once for
+ // validation and once for creation
+ validateAttributes(schemaValidator, element->getAttributes());
+
+ // not required since getTypeQName will trigger processElement in validator
+ //schemaValidator.endAttrs();
+
+ store::Item_t typeName = schemaValidator.getTypeQName();
+
+ bool isSubstitutionGroup = false;
+ if ( schemaValidator.getSubstitutedElemQName() )
+ isSubstitutionGroup = true;
+
+ store::Item_t newElem;
+
+ store::NsBindings bindings;
+ element->getNamespaceBindings(bindings);
+
+ bool haveTypedValue = true;
+ bool haveEmptyValue = false;
+
+ if ( typeName!=NULL && typeManager!=NULL )
+ {
+ xqtref_t schemaType = typeManager->create_named_type(typeName,
+ TypeConstants::QUANT_ONE,
+ loc);
+
+ if ( schemaType!=NULL )
+ {
+ haveTypedValue = typeHasValue(schemaType);
+ haveEmptyValue = typeHasEmptyValue(schemaType);
+ }
+ }
+
+ store::Item_t elemName = element->getNodeName();
+ GENV_ITEMFACTORY->createElementNode(newElem, parent, elemName,
+ typeName, haveTypedValue, haveEmptyValue,
+ bindings, baseUri, isSubstitutionGroup);
+
+ processAttributes(sctx,
+ typeManager,
+ schemaValidator,
+ (store::Item *)newElem,
+ element->getAttributes(),
+ loc);
+
+ processChildren(sctx,
+ typeManager,
+ schemaValidator,
+ (store::Item *)newElem,
+ element->getChildren(),
+ loc);
+
+ schemaValidator.endElem(nodeName);
+
+ return newElem;
+}
+
+
+void Validator::validateAttributes(
+ EventSchemaValidator& schemaValidator,
+ store::Iterator_t attributes)
+{
+ store::Item_t attribute;
+
+ while ( attributes->next(attribute) )
+ {
+ ZORBA_ASSERT(attribute->isNode());
+ ZORBA_ASSERT(attribute->getNodeKind() == store::StoreConsts::attributeNode);
+
+ //cout << " v - attr: " << attribute->getNodeName()->getLocalName() << ":" <<
+ // attribute->getStringValue() << "\n"; cout.flush();
+
+ store::Item_t attName = attribute->getNodeName();
+ schemaValidator.attr(attName, attribute->getStringValue());
+ }
+}
+
+
+void Validator::processAttributes(
+ const static_context* sctx,
+ TypeManager* typeManager,
+ EventSchemaValidator& schemaValidator,
+ store::Item* parent,
+ store::Iterator_t attributes,
+ const QueryLoc& loc)
+{
+ std::list<AttributeValidationInfo*>* attList =
+ schemaValidator.getAttributeList();
+ std::list<AttributeValidationInfo*>::iterator curAtt;
+
+ for( curAtt = attList->begin(); curAtt != attList->end(); ++curAtt )
+ {
+ AttributeValidationInfo* att = *curAtt;
+ //cout << " v proccessATT2: " << att->theLocalName << " T: " <<
+ // att->theTypeName << "\n";
+
+ store::Item_t attQName;
+ GENV_ITEMFACTORY->createQName(attQName,
+ att->theUri,
+ att->thePrefix,
+ att->theLocalName);
+
+ zstring typePrefix;
+
+ // hack around typeManager bug for comparing QNames
+ if (att->theTypeURI == Schema::XSD_NAMESPACE)
+ typePrefix = "xs";
+ else
+ typePrefix = "";
+
+ store::Item_t typeQName;
+ GENV_ITEMFACTORY->createQName(typeQName,
+ att->theTypeURI,
+ typePrefix,
+ att->theTypeName);
+
+ store::NsBindings bindings;
+ parent->getNamespaceBindings(bindings);
+
+ std::vector<store::Item_t> typedValues;
+ processTextValue(sctx,
+ typeManager,
+ bindings,
+ typeQName,
+ att->theValue,
+ typedValues,
+ loc);
+
+ store::Item_t validatedAttNode;
+ if ( typedValues.size()==1 ) // hack around serialization bug
+ GENV_ITEMFACTORY->createAttributeNode(validatedAttNode,
+ parent,
+ attQName,
+ typeQName,
+ typedValues[0]);
+ else
+ GENV_ITEMFACTORY->createAttributeNode(validatedAttNode,
+ parent,
+ attQName,
+ typeQName,
+ typedValues);
+ }
+}
+
+
+void Validator::processChildren(
+ const static_context* sctx,
+ TypeManager* typeManager,
+ EventSchemaValidator& schemaValidator,
+ store::Item* parent,
+ store::Iterator_t children,
+ const QueryLoc& loc)
+{
+ store::Item_t child;
+ bool inTextContent = false;
+ bool hasChildrenElements = false;
+ zstring textNodeValue = zstring("");
+ std::vector<store::Item*> textContent;
+
+ while ( children->next(child) )
+ {
+ if ( child->isNode() )
+ {
+ //cout << " > child: " << (long)child->getNodeKind() << " " <<
+ // //(child->getType() != NULL ? child->getType()->getLocalName() : "type_NULL" ) <<
+ // "\n"; cout.flush();
+
+ switch ( child->getNodeKind() )
+ {
+ case store::StoreConsts::elementNode:
+ if (inTextContent)
+ {
+ hasChildrenElements = true;
+ processTextContent(sctx, typeManager, schemaValidator, parent,
+ hasChildrenElements, textNodeValue, textContent, loc);
+ textNodeValue = "";
+ inTextContent = false;
+ textContent.clear();
+ }
+ processElement(sctx, typeManager, schemaValidator, parent, child, loc);
+ break;
+
+ case store::StoreConsts::attributeNode:
+ ZORBA_ASSERT(false);
+ break;
+
+ case store::StoreConsts::documentNode:
+ ZORBA_ASSERT(false);
+ break;
+
+ case store::StoreConsts::textNode:
+ {
+ // keep on adding the text
+ inTextContent = true;
+ zstring childStringValue;
+ child->getStringValue2(childStringValue);
+ textNodeValue += childStringValue;
+ textContent.push_back(child.getp());
+ }
+ break;
+
+ case store::StoreConsts::piNode:
+ {
+ //cout << " - pi: " << child->getStringValue() << "\n";cout.flush();
+ if ( inTextContent )
+ {
+ textContent.push_back(child.getp());
+ }
+ else
+ {
+ store::Item_t piNode;
+ zstring piTarget =child->getTarget();
+ zstring childStringValue;
+ child->getStringValue2(childStringValue);
+ zstring childBaseUri;
+ child->getBaseURI(childBaseUri);
+
+ GENV_ITEMFACTORY->createPiNode(piNode, parent, piTarget,
+ childStringValue, childBaseUri);
+ }
+ }
+ break;
+
+ case store::StoreConsts::commentNode:
+ {
+ //cout << " - comment: " << child->getStringValue() <<
+ // "\n"; cout.flush();
+ if ( inTextContent )
+ {
+ textContent.push_back(child.getp());
+ }
+ else
+ {
+ store::Item_t commentNode;
+ zstring childStringValue;
+ child->getStringValue2(childStringValue);
+ GENV_ITEMFACTORY->createCommentNode(commentNode, parent, childStringValue);
+ }
+ }
+ break;
+
+ case store::StoreConsts::anyNode:
+ //cout << " - any: " << child->getStringValue() <<"\n";cout.flush();
+ ZORBA_ASSERT(false);
+ break;
+
+ default:
+ ZORBA_ASSERT(false);
+ }
+ }
+ }
+
+ if (inTextContent)
+ {
+ processTextContent(sctx, typeManager, schemaValidator, parent,
+ hasChildrenElements, textNodeValue, textContent, loc);
+ textNodeValue = "";
+ inTextContent = false;
+ }
+}
+
+void Validator::processTextContent(
+ const static_context* sctx,
+ TypeManager* typeManager,
+ EventSchemaValidator& schemaValidator,
+ store::Item* parent,
+ bool hasChildrenElements,
+ zstring& textNodeValue,
+ std::vector<store::Item*>& textContent,
+ const QueryLoc& loc)
+{
+ for ( std::size_t i = 0; i<textContent.size(); i++)
+ {
+ store::Item* child = textContent[i];
+ switch ( child->getNodeKind() )
+ {
+ case store::StoreConsts::textNode:
+ {
+ if (hasChildrenElements)
+ {
+ zstring childStringValue;
+ child->getStringValue2(childStringValue);
+ finishTextNode(sctx, typeManager, schemaValidator, parent,
+ childStringValue, loc);
+ }
+ }
+ break;
+
+ case store::StoreConsts::piNode:
+ {
+ store::Item_t piNode;
+ zstring piTarget =child->getTarget();
+ zstring childStringValue;
+ child->getStringValue2(childStringValue);
+ zstring childBaseUri;
+ child->getBaseURI(childBaseUri);
+
+ GENV_ITEMFACTORY->createPiNode(piNode, parent, piTarget,
+ childStringValue, childBaseUri);
+ }
+ break;
+
+ case store::StoreConsts::commentNode:
+ {
+ store::Item_t commentNode;
+ zstring childStringValue;
+ child->getStringValue2(childStringValue);
+ GENV_ITEMFACTORY->createCommentNode(commentNode, parent, childStringValue);
+ }
+ break;
+
+ case store::StoreConsts::elementNode:
+ case store::StoreConsts::attributeNode:
+ case store::StoreConsts::documentNode:
+ case store::StoreConsts::anyNode:
+ //cout << " - any: " << child->getStringValue() <<"\n";cout.flush();
+ ZORBA_ASSERT(false);
+ break;
+
+ default:
+ ZORBA_ASSERT(false);
+ }
+ }
+
+ if (!hasChildrenElements)
+ {
+ finishTextNode(sctx, typeManager, schemaValidator, parent,
+ textNodeValue, loc);
+ }
+}
+
+void Validator::finishTextNode(
+ const static_context* sctx,
+ TypeManager* typeManager,
+ EventSchemaValidator& schemaValidator,
+ store::Item* parent,
+ zstring& textNodeValue,
+ const QueryLoc& loc)
+{
+ schemaValidator.text(textNodeValue);
+
+ store::Item_t typeQName = schemaValidator.getTypeQName();
+
+ store::Item_t validatedTextNode;
+
+ TypeIdentifier_t typeIdentifier =
+ TypeIdentifier::createNamedType(
+ Unmarshaller::newString( typeQName->getNamespace() ),
+ Unmarshaller::newString( typeQName->getLocalName() )
+ );
+
+ //xqType is NULL, create_type can't find it
+ xqtref_t xqType = typeManager->create_type(*typeIdentifier);
+
+#if 0 // enable this to debug children values
+ if ( typeQName.getp() && xqType.getp() )
+ {
+ cout << " - text: '" << textNodeValue << "' T: " <<
+ typeQName->getLocalName() << "\n"; cout.flush();
+ cout << " xqT: " << xqType->toString() << " content_kind: " <<
+ (long)xqType->contentKind() << " tKind:" << (long)xqType->type_kind() << " \n";
+ cout.flush();
+ }
+ else
+ cout << " - text2: '" << textNodeValue << "' tQN: " <<
+ (typeQName ? typeQName->getStringValue() : "NULL") <<
+ " xqT:" << ( xqType.getp() ? xqType.getp()->toString() : "NULL" )
+ << "\n"; cout.flush();
+#endif
+
+ if ( xqType != NULL &&
+ xqType->contentKind() == XQType::SIMPLE_CONTENT_KIND )
+ {
+ store::NsBindings nsBindings;
+ parent->getNamespaceBindings(nsBindings);
+ std::vector<store::Item_t> typedValues;
+
+ processTextValue(sctx,
+ typeManager,
+ nsBindings,
+ typeQName,
+ textNodeValue,
+ typedValues,
+ loc);
+
+ if ( typedValues.size() == 1 ) // hack around serialization bug
+ GENV_ITEMFACTORY->createTextNode(validatedTextNode, parent,
+ typedValues[0]);
+ else
+ GENV_ITEMFACTORY->createTextNode(validatedTextNode, parent,
+ typedValues);
+ }
+ else if ( xqType!=NULL &&
+ (xqType->contentKind()==XQType::ELEMENT_ONLY_CONTENT_KIND ||
+ xqType->contentKind()==XQType::EMPTY_CONTENT_KIND ))
+ {
+ // if text not valid the schemaValidator should have already
+ // thrown an error
+
+ // XQ XP Datamodel Spec: http://www.w3.org/TR/xpath-datamodel/
+ // section 6.7.4 Construction from a PSVI
+ if ( !utf8::is_space(textNodeValue) )
+ {
+ zstring empty;
+ GENV_ITEMFACTORY->createTextNode(validatedTextNode,
+ parent,
+ empty);
+ //cout << " -- create empty text : ElementOnly || Empty" << endl;
+ }
+ else
+ {
+ //cout << " -- skip this text: (ElemOnly || Empty) && whitespace" << endl;
+ }
+ }
+ else
+ //if ( xqType!=NULL &&
+ // xqType->content_kind()==XQType::MIXED_CONTENT_KIND )
+ {
+ // if text not valid the schemaValidator should have already
+ // thrown an error
+ GENV_ITEMFACTORY->createTextNode(validatedTextNode,
+ parent,
+ textNodeValue);
+ //cout << " -- create empty text: Mixed" << endl;
+ }
+}
+
+
+
+void Validator::processNamespaces (
+ EventSchemaValidator& schemaValidator,
+ const store::Item_t& item)
+{
+ store::NsBindings bindings;
+ item->getNamespaceBindings(bindings,
+ store::StoreConsts::ONLY_LOCAL_NAMESPACES);
+
+ for (unsigned long i = 0; i < bindings.size(); i++)
+ {
+ schemaValidator.ns(bindings[i].first, bindings[i].second);
+ }
+}
+
+
+void Validator::processTextValue(
+ const static_context* sctx,
+ TypeManager* typeManager,
+ store::NsBindings& bindings,
+ const store::Item_t& typeQName,
+ zstring& textValue,
+ std::vector<store::Item_t>& resultList,
+ const QueryLoc& loc)
+{
+ xqtref_t type = typeManager->create_named_type(typeQName.getp(),
+ TypeConstants::QUANT_ONE,
+ loc);
+
+ //cout << " - processTextValue: " << typeQName->getPrefix()
+ // << ":" << typeQName->getLocalName() << "@"
+ // << typeQName->getNamespace() ; cout.flush();
+ //cout << " type: " << (type==NULL ? "NULL" : type->toString()) << "\n"; cout.flush();
+
+ // TODO: we probably need the ns bindings from the static context
+ // surrounding the original validate_expr, not planState.sctx()
+ namespace_context nsCtx = namespace_context(sctx, bindings);
+
+ store::Item_t result;
+ if (type != NULL)
+ {
+ if ( type->type_kind() == XQType::USER_DEFINED_KIND )
+ {
+ const UserDefinedXQType udt = static_cast<const UserDefinedXQType&>(*type);
+
+ if ( udt.isList() || udt.isUnion() )
+ {
+ typeManager->getSchema()->parseUserSimpleTypes(textValue, type,
+ resultList, loc, false);
+ }
+ else if (udt.isAtomicAny())
+ {
+ bool res = typeManager->getSchema()->
+ parseUserAtomicTypes(textValue, type.getp(), result, &nsCtx, loc,
+ false);
+
+ ZORBA_ASSERT(res);
+ resultList.push_back(result);
+ }
+ else if (udt.isComplex() &&
+ udt.contentKind() == XQType::SIMPLE_CONTENT_KIND)
+ {
+ try
+ {
+ // if complex type with simple content parse text by the base
+ // type which has to be simple
+ xqtref_t baseType = udt.getBaseType();
+
+ while ( baseType->type_kind() == XQType::USER_DEFINED_KIND &&
+ static_cast<const UserDefinedXQType&>(*baseType).isComplex() )
+ {
+ const UserDefinedXQType udBaseType =
+ static_cast<const UserDefinedXQType&>(*baseType);
+
+ baseType = udBaseType.getBaseType();
+ }
+
+ bool res = typeManager->getSchema()->
+ parseUserSimpleTypes(textValue, baseType, resultList, loc, false);
+
+ // if this assert fails it means the validator and zorba casting code
+ // don't follow the same rules
+ ZORBA_ASSERT(res);
+ }
+ catch(ZorbaException const& /*err*/)
+ {
+ // do nothing here, the validator will throw the right error at end
+ // elemet event call
+ //std::cout << "validate.cpp: processTextValue1 '" << textValue << "' err:" << err.toString() << std::endl; std::cout.flush();
+ }
+ }
+ }
+ else if (type->type_kind() == XQType::ATOMIC_TYPE_KIND)
+ {
+ try
+ {
+ bool res = GenericCast::castStringToAtomic(result, textValue, type.getp(),
+ typeManager, &nsCtx, loc);
+ ZORBA_ASSERT(res);
+ resultList.push_back(result);
+ }
+ catch(ZorbaException const& /*err*/)
+ {
+ // do nothing here, the validator will throw the right error at end
+ // elemet event call
+ //std::cout << "validate.cpp: processTextValue2 '" << textValue
+ // << "' err:" << err.toString() << std::endl; std::cout.flush();
+ }
+ }
+ else
+ {
+ if ( GENV_ITEMFACTORY->createUntypedAtomic( result, textValue) )
+ resultList.push_back(result);
+ }
+ }
+ else
+ {
+ if ( GENV_ITEMFACTORY->createUntypedAtomic( result, textValue) )
+ resultList.push_back(result);
+ }
+}
+
+} // namespace zorba
+
+#endif // ifndef ZORBA_NO_XMLSCHEMA
+/* vim:set et sw=2 ts=2: */
=== removed file 'src/types/schema/validate.cpp'
--- src/types/schema/validate.cpp 2013-05-21 21:44:25 +0000
+++ src/types/schema/validate.cpp 1970-01-01 00:00:00 +0000
@@ -1,887 +0,0 @@
-/*
-* Copyright 2006-2008 The FLWOR Foundation.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-#include "stdafx.h"
-
-#include "validate.h"
-
-#include "diagnostics/xquery_diagnostics.h"
-
-#include "system/globalenv.h"
-
-#include "types/casting.h"
-#include "types/typeops.h"
-
-#ifndef ZORBA_NO_XMLSCHEMA
-
-#include "types/schema/schema.h"
-#include "types/schema/SchemaValidatorFilter.h"
-#include "types/schema/EventSchemaValidator.h"
-#include "types/schema/StrX.h"
-#include "types/schema/revalidateUtils.h"
-
-#include "zorbatypes/duration.h"
-#include "zorbatypes/datetime.h"
-
-#endif
-
-#include "api/unmarshaller.h"
-
-#include "compiler/parser/query_loc.h"
-
-#include "store/api/copymode.h"
-#include "store/api/item.h"
-#include "store/api/item_factory.h"
-#include "store/api/iterator.h"
-#include "store/api/store.h"
-
-#include "context/dynamic_context.h"
-#include "context/static_context.h"
-#include "context/namespace_context.h"
-
-#include "diagnostics/assert.h"
-#include "zorba/store_consts.h"
-
-//using namespace std;
-
-namespace zorba
-{
-
-
-bool Validator::effectiveValidationValue(
- store::Item_t& result,
- const store::Item_t& sourceNode,
- const store::Item_t& typeName,
- TypeManager* typeManager,
- ParseConstants::validation_mode_t validationMode,
- const static_context* sctx,
- const QueryLoc& loc)
-{
- //cout << "Starting Validation typeManager: " << typeManager <<
- //endl; cout.flush();
- try
- {
- return realValidationValue(result, sourceNode, typeName,
- typeManager, validationMode, sctx, loc);
- }
- catch (ZorbaException& e)
- {
- set_source( e, loc );
-
- if ( sourceNode->isNode() &&
- sourceNode->getNodeKind() == store::StoreConsts::documentNode )
- {
- zstring baseUri;
- sourceNode->getDocumentURI(baseUri);
-
- //e.theDescription += " while validating document '" + baseUri + "'";
- }
- throw;
- }
-}
-
-
-bool Validator::realValidationValue(
- store::Item_t& result,
- const store::Item_t& sourceNode,
- const store::Item_t& typeName,
- TypeManager* typeManager,
- ParseConstants::validation_mode_t validationMode,
- const static_context* sctx,
- const QueryLoc& loc)
-{
- xqtref_t type;
-
- if (!sourceNode->isNode() ||
- !(sourceNode->getNodeKind()==store::StoreConsts::documentNode ||
- sourceNode->getNodeKind()==store::StoreConsts::elementNode
- ) )
- {
- throw XQUERY_EXCEPTION( err::XQTY0030, ERROR_LOC( loc ) );
- }
-
- // verify number of child elements when source is a document node
- if (sourceNode->getNodeKind() == store::StoreConsts::documentNode)
- {
- //don't allow more than one child element in documents
- store::Iterator_t child_it;
- child_it = sourceNode->getChildren();
- store::Item_t child;
- int nr_child_elements = 0;
- while ( child_it->next(child) )
- {
- if ( child->isNode() &&
- child->getNodeKind() == store::StoreConsts::elementNode)
- {
- if (nr_child_elements)
- {
- throw XQUERY_EXCEPTION(
- err::XQDY0061,
- ERROR_PARAMS( ZED( DocNodeMultipleElements ) ),
- ERROR_LOC( loc )
- );
- }
- nr_child_elements++;
- }
- }
- }
-
- Schema* schema = typeManager->getSchema();
-
- if ( !schema )
- {
- //cout << "No schema: isNode() " << sourceNode->isNode() << " nodeKind: "<<
- // sourceNode->getNodeKind() << endl;
-
- if ( validationMode == ParseConstants::val_dtd_lax)
- {
- // when dtd validation enabled avoid using schema object
- result = sourceNode;
- return true;
- }
- else
- {
- // if we got here it basicaly means that there was no import but
- // validation is used so we need to set up schema in the typeManager anyway
- // validation has to work for xsiType and built-in types
-
- TypeManagerImpl* typeManagerImpl = static_cast<TypeManagerImpl*>(typeManager);
- typeManagerImpl->initializeSchema();
- schema = typeManager->getSchema();
- }
- }
- else if (validationMode == ParseConstants::val_dtd_lax && !schema->hasXSD())
- {
- // when dtd validation enabled avoid using schema object
- result = sourceNode;
- return true;
- }
-
-#ifndef ZORBA_NO_XMLSCHEMA
-
- EventSchemaValidator schemaValidator =
- EventSchemaValidator(typeManager,
- schema->getGrammarPool(),
- validationMode == ParseConstants::val_lax,
- loc);
-
- switch (sourceNode->getNodeKind())
- {
- case store::StoreConsts::documentNode:
- {
- //cout << "Validate document" << "\n"; cout.flush();
-
- if ( validationMode == ParseConstants::val_typename )
- {
- //cout << "Validate type: " << typeName->getLocalName()
- // << " @ " << typeName->getNamespace() << "\n"; cout.flush();
- schemaValidator.startType(typeName);
- }
- else
- {
- schemaValidator.startDoc();
-
- store::Iterator_t children = sourceNode->getChildren();
- store::Item_t child;
- while ( children->next(child) )
- {
- // ask for the type of the element. We don't really need this type here,
- // but a side-effect of this call is to add the type to the cache.
- if ( child->isNode() &&
- child->getNodeKind()==store::StoreConsts::elementNode )
- {
- bool nillable;
- typeManager->getSchema()->
- createXQTypeFromGlobalElementDecl(typeManager,
- child->getNodeName(),
- false,
- nillable,
- loc);
- break;
- }
- }
- }
-
- zstring docBaseUri;
- zstring docUri;
- sourceNode->getBaseURI(docBaseUri);
- sourceNode->getDocumentURI(docUri);
-
- store::Item_t newDoc;
- GENV_ITEMFACTORY->createDocumentNode(newDoc, docBaseUri, docUri);
-
- processChildren(sctx,
- typeManager,
- schemaValidator,
- newDoc,
- sourceNode->getChildren(),
- loc);
-
- if ( validationMode == ParseConstants::val_typename )
- {
- schemaValidator.endType();
- //cout << "End Validate type: " << typeName->getLocalName()
- // << " @ " << typeName->getNamespace() << "\n";
- //cout.flush();
- }
- else
- {
- schemaValidator.endDoc();
- }
-
- //cout << "End Validate doc" << "\n"; cout.flush();
-
- result = newDoc;
- result->markValidated();
- return true;
- }
- case store::StoreConsts::elementNode:
- {
- if ( validationMode == ParseConstants::val_typename )
- {
- //cout << "Validate type: " << typeName->getLocalName() <<" @ "
- // << typeName->getNamespace() << "\n"; cout.flush();
-
- schemaValidator.startType(typeName);
- }
- else
- {
- //cout << "Validate element" << "\n"; cout.flush();
- schemaValidator.startDoc();
-
- // ask for the type of the element. We don't really need this type here,
- // but a side-effect of this call is to add the type to the cache.
- bool nillable;
- typeManager->getSchema()->
- createXQTypeFromGlobalElementDecl(typeManager,
- sourceNode->getNodeName(),
- false,
- nillable,
- loc);
- }
-
- store::Item_t newElem = processElement(sctx,
- typeManager,
- schemaValidator,
- NULL,
- sourceNode,
- loc);
-
- if ( validationMode == ParseConstants::val_typename )
- {
- schemaValidator.endType();
- //cout << "End Validate type: " << typeName->getLocalName()
- // <<" @ "<< typeName->getNamespace() << "\n";cout.flush();
- }
- else
- {
- schemaValidator.endDoc();
- //cout << "End Validate elem" << "\n"; cout.flush();
- }
-
- result = newElem;
- result->markValidated();
- return true;
- }
- default:
- {
- throw XQUERY_EXCEPTION( err::XQTY0030, ERROR_LOC( loc ) );
- }
- }
-#endif // ZORBA_NO_XMLSCHEMA
-}
-
-
-#ifndef ZORBA_NO_XMLSCHEMA
-
-
-store::Item_t Validator::processElement(
- const static_context* sctx,
- TypeManager* typeManager,
- EventSchemaValidator& schemaValidator,
- store::Item* parent,
- const store::Item_t& element,
- const QueryLoc& loc)
-{
- ZORBA_ASSERT(element->isNode());
- ZORBA_ASSERT(element->getNodeKind() == store::StoreConsts::elementNode);
-
-
- store::Item_t nodeName = element->getNodeName();
- zstring baseUri;
- element->getBaseURI(baseUri);
-
- schemaValidator.startElem(nodeName);
-
- // namespace declarations must go first
- processNamespaces( schemaValidator, element);
-
- // since the type of an element is determined only after the validator
- // receives all of it's attributes, and an attribute node needs it's parent
- // when created we need to go through the attributes twice: once for
- // validation and once for creation
- validateAttributes(schemaValidator, element->getAttributes());
-
- // not required since getTypeQName will trigger processElement in validator
- //schemaValidator.endAttrs();
-
- store::Item_t typeName = schemaValidator.getTypeQName();
-
- bool isSubstitutionGroup = false;
- if ( schemaValidator.getSubstitutedElemQName() )
- isSubstitutionGroup = true;
-
- store::Item_t newElem;
-
- store::NsBindings bindings;
- element->getNamespaceBindings(bindings);
-
- bool haveTypedValue = true;
- bool haveEmptyValue = false;
-
- if ( typeName!=NULL && typeManager!=NULL )
- {
- xqtref_t schemaType = typeManager->create_named_type(typeName,
- TypeConstants::QUANT_ONE,
- loc);
-
- if ( schemaType!=NULL )
- {
- haveTypedValue = typeHasValue(schemaType);
- haveEmptyValue = typeHasEmptyValue(schemaType);
- }
- }
-
- store::Item_t elemName = element->getNodeName();
- GENV_ITEMFACTORY->createElementNode(newElem, parent, elemName,
- typeName, haveTypedValue, haveEmptyValue,
- bindings, baseUri, isSubstitutionGroup);
-
- processAttributes(sctx,
- typeManager,
- schemaValidator,
- (store::Item *)newElem,
- element->getAttributes(),
- loc);
-
- processChildren(sctx,
- typeManager,
- schemaValidator,
- (store::Item *)newElem,
- element->getChildren(),
- loc);
-
- schemaValidator.endElem(nodeName);
-
- return newElem;
-}
-
-
-void Validator::validateAttributes(
- EventSchemaValidator& schemaValidator,
- store::Iterator_t attributes)
-{
- store::Item_t attribute;
-
- while ( attributes->next(attribute) )
- {
- ZORBA_ASSERT(attribute->isNode());
- ZORBA_ASSERT(attribute->getNodeKind() == store::StoreConsts::attributeNode);
-
- //cout << " v - attr: " << attribute->getNodeName()->getLocalName() << ":" <<
- // attribute->getStringValue() << "\n"; cout.flush();
-
- store::Item_t attName = attribute->getNodeName();
- schemaValidator.attr(attName, attribute->getStringValue());
- }
-}
-
-
-void Validator::processAttributes(
- const static_context* sctx,
- TypeManager* typeManager,
- EventSchemaValidator& schemaValidator,
- store::Item* parent,
- store::Iterator_t attributes,
- const QueryLoc& loc)
-{
- std::list<AttributeValidationInfo*>* attList =
- schemaValidator.getAttributeList();
- std::list<AttributeValidationInfo*>::iterator curAtt;
-
- for( curAtt = attList->begin(); curAtt != attList->end(); ++curAtt )
- {
- AttributeValidationInfo* att = *curAtt;
- //cout << " v proccessATT2: " << att->theLocalName << " T: " <<
- // att->theTypeName << "\n";
-
- store::Item_t attQName;
- GENV_ITEMFACTORY->createQName(attQName,
- att->theUri,
- att->thePrefix,
- att->theLocalName);
-
- zstring typePrefix;
-
- // hack around typeManager bug for comparing QNames
- if (att->theTypeURI == Schema::XSD_NAMESPACE)
- typePrefix = "xs";
- else
- typePrefix = "";
-
- store::Item_t typeQName;
- GENV_ITEMFACTORY->createQName(typeQName,
- att->theTypeURI,
- typePrefix,
- att->theTypeName);
-
- store::NsBindings bindings;
- parent->getNamespaceBindings(bindings);
-
- std::vector<store::Item_t> typedValues;
- processTextValue(sctx,
- typeManager,
- bindings,
- typeQName,
- att->theValue,
- typedValues,
- loc);
-
- store::Item_t validatedAttNode;
- if ( typedValues.size()==1 ) // hack around serialization bug
- GENV_ITEMFACTORY->createAttributeNode(validatedAttNode,
- parent,
- attQName,
- typeQName,
- typedValues[0]);
- else
- GENV_ITEMFACTORY->createAttributeNode(validatedAttNode,
- parent,
- attQName,
- typeQName,
- typedValues);
- }
-}
-
-
-void Validator::processChildren(
- const static_context* sctx,
- TypeManager* typeManager,
- EventSchemaValidator& schemaValidator,
- store::Item* parent,
- store::Iterator_t children,
- const QueryLoc& loc)
-{
- store::Item_t child;
- bool inTextContent = false;
- bool hasChildrenElements = false;
- zstring textNodeValue = zstring("");
- std::vector<store::Item*> textContent;
-
- while ( children->next(child) )
- {
- if ( child->isNode() )
- {
- //cout << " > child: " << (long)child->getNodeKind() << " " <<
- // //(child->getType() != NULL ? child->getType()->getLocalName() : "type_NULL" ) <<
- // "\n"; cout.flush();
-
- switch ( child->getNodeKind() )
- {
- case store::StoreConsts::elementNode:
- if (inTextContent)
- {
- hasChildrenElements = true;
- processTextContent(sctx, typeManager, schemaValidator, parent,
- hasChildrenElements, textNodeValue, textContent, loc);
- textNodeValue = "";
- inTextContent = false;
- textContent.clear();
- }
- processElement(sctx, typeManager, schemaValidator, parent, child, loc);
- break;
-
- case store::StoreConsts::attributeNode:
- ZORBA_ASSERT(false);
- break;
-
- case store::StoreConsts::documentNode:
- ZORBA_ASSERT(false);
- break;
-
- case store::StoreConsts::textNode:
- {
- // keep on adding the text
- inTextContent = true;
- zstring childStringValue;
- child->getStringValue2(childStringValue);
- textNodeValue += childStringValue;
- textContent.push_back(child.getp());
- }
- break;
-
- case store::StoreConsts::piNode:
- {
- //cout << " - pi: " << child->getStringValue() << "\n";cout.flush();
- if ( inTextContent )
- {
- textContent.push_back(child.getp());
- }
- else
- {
- store::Item_t piNode;
- zstring piTarget =child->getTarget();
- zstring childStringValue;
- child->getStringValue2(childStringValue);
- zstring childBaseUri;
- child->getBaseURI(childBaseUri);
-
- GENV_ITEMFACTORY->createPiNode(piNode, parent, piTarget,
- childStringValue, childBaseUri);
- }
- }
- break;
-
- case store::StoreConsts::commentNode:
- {
- //cout << " - comment: " << child->getStringValue() <<
- // "\n"; cout.flush();
- if ( inTextContent )
- {
- textContent.push_back(child.getp());
- }
- else
- {
- store::Item_t commentNode;
- zstring childStringValue;
- child->getStringValue2(childStringValue);
- GENV_ITEMFACTORY->createCommentNode(commentNode, parent, childStringValue);
- }
- }
- break;
-
- case store::StoreConsts::anyNode:
- //cout << " - any: " << child->getStringValue() <<"\n";cout.flush();
- ZORBA_ASSERT(false);
- break;
-
- default:
- ZORBA_ASSERT(false);
- }
- }
- }
-
- if (inTextContent)
- {
- processTextContent(sctx, typeManager, schemaValidator, parent,
- hasChildrenElements, textNodeValue, textContent, loc);
- textNodeValue = "";
- inTextContent = false;
- }
-}
-
-void Validator::processTextContent(
- const static_context* sctx,
- TypeManager* typeManager,
- EventSchemaValidator& schemaValidator,
- store::Item* parent,
- bool hasChildrenElements,
- zstring& textNodeValue,
- std::vector<store::Item*>& textContent,
- const QueryLoc& loc)
-{
- for ( std::size_t i = 0; i<textContent.size(); i++)
- {
- store::Item* child = textContent[i];
- switch ( child->getNodeKind() )
- {
- case store::StoreConsts::textNode:
- {
- if (hasChildrenElements)
- {
- zstring childStringValue;
- child->getStringValue2(childStringValue);
- finishTextNode(sctx, typeManager, schemaValidator, parent,
- childStringValue, loc);
- }
- }
- break;
-
- case store::StoreConsts::piNode:
- {
- store::Item_t piNode;
- zstring piTarget =child->getTarget();
- zstring childStringValue;
- child->getStringValue2(childStringValue);
- zstring childBaseUri;
- child->getBaseURI(childBaseUri);
-
- GENV_ITEMFACTORY->createPiNode(piNode, parent, piTarget,
- childStringValue, childBaseUri);
- }
- break;
-
- case store::StoreConsts::commentNode:
- {
- store::Item_t commentNode;
- zstring childStringValue;
- child->getStringValue2(childStringValue);
- GENV_ITEMFACTORY->createCommentNode(commentNode, parent, childStringValue);
- }
- break;
-
- case store::StoreConsts::elementNode:
- case store::StoreConsts::attributeNode:
- case store::StoreConsts::documentNode:
- case store::StoreConsts::anyNode:
- //cout << " - any: " << child->getStringValue() <<"\n";cout.flush();
- ZORBA_ASSERT(false);
- break;
-
- default:
- ZORBA_ASSERT(false);
- }
- }
-
- if (!hasChildrenElements)
- {
- finishTextNode(sctx, typeManager, schemaValidator, parent,
- textNodeValue, loc);
- }
-}
-
-void Validator::finishTextNode(
- const static_context* sctx,
- TypeManager* typeManager,
- EventSchemaValidator& schemaValidator,
- store::Item* parent,
- zstring& textNodeValue,
- const QueryLoc& loc)
-{
- schemaValidator.text(textNodeValue);
-
- store::Item_t typeQName = schemaValidator.getTypeQName();
-
- store::Item_t validatedTextNode;
-
- TypeIdentifier_t typeIdentifier =
- TypeIdentifier::createNamedType(
- Unmarshaller::newString( typeQName->getNamespace() ),
- Unmarshaller::newString( typeQName->getLocalName() )
- );
-
- //xqType is NULL, create_type can't find it
- xqtref_t xqType = typeManager->create_type(*typeIdentifier);
-
-#if 0 // enable this to debug children values
- if ( typeQName.getp() && xqType.getp() )
- {
- cout << " - text: '" << textNodeValue << "' T: " <<
- typeQName->getLocalName() << "\n"; cout.flush();
- cout << " xqT: " << xqType->toString() << " content_kind: " <<
- (long)xqType->contentKind() << " tKind:" << (long)xqType->type_kind() << " \n";
- cout.flush();
- }
- else
- cout << " - text2: '" << textNodeValue << "' tQN: " <<
- (typeQName ? typeQName->getStringValue() : "NULL") <<
- " xqT:" << ( xqType.getp() ? xqType.getp()->toString() : "NULL" )
- << "\n"; cout.flush();
-#endif
-
- if ( xqType != NULL &&
- xqType->contentKind() == XQType::SIMPLE_CONTENT_KIND )
- {
- store::NsBindings nsBindings;
- parent->getNamespaceBindings(nsBindings);
- std::vector<store::Item_t> typedValues;
-
- processTextValue(sctx,
- typeManager,
- nsBindings,
- typeQName,
- textNodeValue,
- typedValues,
- loc);
-
- if ( typedValues.size() == 1 ) // hack around serialization bug
- GENV_ITEMFACTORY->createTextNode(validatedTextNode, parent,
- typedValues[0]);
- else
- GENV_ITEMFACTORY->createTextNode(validatedTextNode, parent,
- typedValues);
- }
- else if ( xqType!=NULL &&
- (xqType->contentKind()==XQType::ELEMENT_ONLY_CONTENT_KIND ||
- xqType->contentKind()==XQType::EMPTY_CONTENT_KIND ))
- {
- // if text not valid the schemaValidator should have already
- // thrown an error
-
- // XQ XP Datamodel Spec: http://www.w3.org/TR/xpath-datamodel/
- // section 6.7.4 Construction from a PSVI
- if ( !utf8::is_space(textNodeValue) )
- {
- zstring empty;
- GENV_ITEMFACTORY->createTextNode(validatedTextNode,
- parent,
- empty);
- //cout << " -- create empty text : ElementOnly || Empty" << endl;
- }
- else
- {
- //cout << " -- skip this text: (ElemOnly || Empty) && whitespace" << endl;
- }
- }
- else
- //if ( xqType!=NULL &&
- // xqType->content_kind()==XQType::MIXED_CONTENT_KIND )
- {
- // if text not valid the schemaValidator should have already
- // thrown an error
- GENV_ITEMFACTORY->createTextNode(validatedTextNode,
- parent,
- textNodeValue);
- //cout << " -- create empty text: Mixed" << endl;
- }
-}
-
-
-
-void Validator::processNamespaces (
- EventSchemaValidator& schemaValidator,
- const store::Item_t& item)
-{
- store::NsBindings bindings;
- item->getNamespaceBindings(bindings,
- store::StoreConsts::ONLY_LOCAL_NAMESPACES);
-
- for (unsigned long i = 0; i < bindings.size(); i++)
- {
- schemaValidator.ns(bindings[i].first, bindings[i].second);
- }
-}
-
-
-void Validator::processTextValue(
- const static_context* sctx,
- TypeManager* typeManager,
- store::NsBindings& bindings,
- const store::Item_t& typeQName,
- zstring& textValue,
- std::vector<store::Item_t>& resultList,
- const QueryLoc& loc)
-{
- xqtref_t type = typeManager->create_named_type(typeQName.getp(),
- TypeConstants::QUANT_ONE,
- loc);
-
- //cout << " - processTextValue: " << typeQName->getPrefix()
- // << ":" << typeQName->getLocalName() << "@"
- // << typeQName->getNamespace() ; cout.flush();
- //cout << " type: " << (type==NULL ? "NULL" : type->toString()) << "\n"; cout.flush();
-
- // TODO: we probably need the ns bindings from the static context
- // surrounding the original validate_expr, not planState.sctx()
- namespace_context nsCtx = namespace_context(sctx, bindings);
-
- store::Item_t result;
- if (type != NULL)
- {
- if ( type->type_kind() == XQType::USER_DEFINED_KIND )
- {
- const UserDefinedXQType udt = static_cast<const UserDefinedXQType&>(*type);
-
- if ( udt.isList() || udt.isUnion() )
- {
- typeManager->getSchema()->parseUserSimpleTypes(textValue, type,
- resultList, loc, false);
- }
- else if (udt.isAtomicAny())
- {
- bool res = typeManager->getSchema()->
- parseUserAtomicTypes(textValue, type.getp(), result, &nsCtx, loc,
- false);
-
- ZORBA_ASSERT(res);
- resultList.push_back(result);
- }
- else if (udt.isComplex() &&
- udt.contentKind() == XQType::SIMPLE_CONTENT_KIND)
- {
- try
- {
- // if complex type with simple content parse text by the base
- // type which has to be simple
- xqtref_t baseType = udt.getBaseType();
-
- while ( baseType->type_kind() == XQType::USER_DEFINED_KIND &&
- static_cast<const UserDefinedXQType&>(*baseType).isComplex() )
- {
- const UserDefinedXQType udBaseType =
- static_cast<const UserDefinedXQType&>(*baseType);
-
- baseType = udBaseType.getBaseType();
- }
-
- bool res = typeManager->getSchema()->
- parseUserSimpleTypes(textValue, baseType, resultList, loc, false);
-
- // if this assert fails it means the validator and zorba casting code
- // don't follow the same rules
- ZORBA_ASSERT(res);
- }
- catch(ZorbaException const& /*err*/)
- {
- // do nothing here, the validator will throw the right error at end
- // elemet event call
- //std::cout << "validate.cpp: processTextValue1 '" << textValue << "' err:" << err.toString() << std::endl; std::cout.flush();
- }
- }
- }
- else if (type->type_kind() == XQType::ATOMIC_TYPE_KIND)
- {
- try
- {
- bool res = GenericCast::castStringToAtomic(result, textValue, type.getp(),
- typeManager, &nsCtx, loc);
- ZORBA_ASSERT(res);
- resultList.push_back(result);
- }
- catch(ZorbaException const& /*err*/)
- {
- // do nothing here, the validator will throw the right error at end
- // elemet event call
- //std::cout << "validate.cpp: processTextValue2 '" << textValue
- // << "' err:" << err.toString() << std::endl; std::cout.flush();
- }
- }
- else
- {
- if ( GENV_ITEMFACTORY->createUntypedAtomic( result, textValue) )
- resultList.push_back(result);
- }
- }
- else
- {
- if ( GENV_ITEMFACTORY->createUntypedAtomic( result, textValue) )
- resultList.push_back(result);
- }
-}
-
-} // namespace zorba
-
-#endif // ifndef ZORBA_NO_XMLSCHEMA
-/* vim:set et sw=2 ts=2: */
Follow ups