You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/kode/kwsdl/schema/parser.cpp

1096 lines
30 KiB

/*
This file is part of KDE Schema Parser
Copyright (c) 2005 Tobias Koenig <tokoe@kde.org>
based on wsdlpull parser by Vivek Krishna
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <tqdir.h>
#include <tqfile.h>
#include <tqurl.h>
#include "fileprovider.h"
#include "parser.h"
using namespace Schema;
const TQString soapEncUri = "http://schemas.xmlsoap.org/soap/encoding/";
const TQString wsdlUri = "http://schemas.xmlsoap.org/wsdl/";
Parser::Parser( const TQString &nameSpace )
: mNameSpace( nameSpace )
{
mElementQualified = false;
mAttributeQualified = false;
}
Parser::~Parser()
{
clear();
}
Types Parser::types() const
{
Types types;
SimpleType::List simpleTypes;
ComplexType::List complexTypes;
for ( int i = 0; i < numTypes(); i++ ) {
const XSDType *pType = type( i + XSDType::ANYURI + 1 );
if ( pType != 0 ) {
if ( pType->isSimple() ) {
const SimpleType *simpleType = static_cast<const SimpleType*>( pType );
SimpleType type = *simpleType;
type.setBaseTypeName( mTypesTable.typeName( type.baseType() ) );
type.setListTypeName( mTypesTable.typeName( type.listType() ) );
simpleTypes.append( type );
} else {
const ComplexType *complexType = static_cast<const ComplexType*>( pType );
ComplexType type = *complexType;
type.setBaseTypeName( mTypesTable.typeName( type.baseType() ) );
Schema::Element::List elements = type.elements();
Schema::Element::List::Iterator elemIt;
for ( elemIt = elements.begin(); elemIt != elements.end(); ++elemIt )
(*elemIt).setTypeName( mTypesTable.typeName( (*elemIt).type() ) );
type.setElements( elements );
Schema::Attribute::List attributes = type.attributes();
Schema::Attribute::List::Iterator attrIt;
for ( attrIt = attributes.begin(); attrIt != attributes.end(); ++attrIt )
(*attrIt).setTypeName( mTypesTable.typeName( (*attrIt).type() ) );
type.setAttributes( attributes );
complexTypes.append( type );
}
}
}
Element::List elements;
for ( uint i = 0; i < mElements.count(); ++i ) {
Element element = *mElements[ i ];
element.setTypeName( mTypesTable.typeName( element.type() ) );
elements.append( element );
}
types.setSimpleTypes( simpleTypes );
types.setComplexTypes( complexTypes );
types.setElements( elements );
return types;
}
void Parser::clear()
{
mTypesTable.clear();
mImportedSchemas.clear();
for ( uint i = 0; i < mElements.count(); ++i )
delete mElements[ i ];
for ( uint i = 0; i < mAttributes.count(); ++i )
delete mAttributes[ i ];
}
void Parser::setSchemaBaseUrl( const TQString &url )
{
mSchemaBaseUrl = url;
}
void Parser::parseNameSpace( const TQDomElement &element )
{
TQDomNamedNodeMap attributes = element.attributes();
for ( uint i = 0; i < attributes.count(); ++i ) {
TQDomNode node = attributes.item( i );
TQDomAttr attribute = node.toAttr();
if ( attribute.name().startsWith( "xmlns:" ) )
mNameSpaceMap.insert( attribute.value(), attribute.name().mid( 6 ) );
}
}
bool Parser::parseSchemaTag( const TQDomElement &root )
{
QualifiedName name = root.tagName();
if ( name.localName() != "schema" )
return false;
if ( root.hasAttribute( "targetNamespace" ) )
mNameSpace = root.attribute( "targetNamespace" );
if ( root.hasAttribute( "elementFormDefault" ) ) {
const TQString value = root.attribute( "elementFormDefault" );
if ( value == "unqualified" )
mElementQualified = false;
else if ( value == "qualified" )
mElementQualified = true;
}
mTypesTable.setTargetNamespace( mNameSpace );
/*
for (i = xParser->getNamespaceCount(xParser->getDepth()) - 1;
i > xParser->getNamespaceCount(xParser->getDepth() - 1) - 1; i--)
if (xParser->getNamespaceUri(i) == mNameSpace)
m_tnsPrefix = xParser->getNamespacePrefix(i);
*/
TQDomNode node = root.firstChild();
while ( !node.isNull() ) {
TQDomElement element = node.toElement();
if ( !element.isNull() ) {
QualifiedName name = element.tagName();
if ( name.localName() == "import" ) {
parseImport( element );
} else if ( name.localName() == "element" ) {
parseElement( element );
} else if ( name.localName() == "complexType" ) {
XSDType *type = parseComplexType( element );
mTypesTable.addType( type );
} else if ( name.localName() == "simpleType" ) {
XSDType *type = parseSimpleType( element );
mTypesTable.addType( type );
} else if ( name.localName() == "attribute" ) {
parseAttribute( element );
} else if ( name.localName() == "annotation" ) {
parseAnnotation( element );
} else if ( name.localName() == "import" ) {
// TODO
} else if ( name.localName() == "include" ) {
// TODO
}
}
node = node.nextSibling();
}
if ( shouldResolve() ) {
resolveForwardElementRefs();
resolveForwardAttributeRefs();
resolveForwardDerivations();
}
return true;
}
void Parser::parseImport( const TQDomElement &element )
{
TQString location = element.attribute( "schemaLocation" );
if ( !location.isEmpty() ) {
// don't import a schema twice
if ( mImportedSchemas.tqcontains( location ) )
return;
else
mImportedSchemas.append( location );
importSchema( location );
}
}
void Parser::parseAnnotation( const TQDomElement& )
{
}
void Parser::parseAnnotation( const TQDomElement &element, TQString &documentation )
{
TQDomNode node = element.firstChild();
while ( !node.isNull() ) {
TQDomElement childElement = node.toElement();
if ( !childElement.isNull() ) {
QualifiedName name = childElement.tagName();
if ( name.localName() == "documentation" )
documentation = childElement.text().stripWhiteSpace();
}
node = node.nextSibling();
}
}
void Parser::parseAnnotation( const TQDomElement &element, ComplexType *complexType )
{
TQDomNode node = element.firstChild();
while ( !node.isNull() ) {
TQDomElement childElement = node.toElement();
if ( !childElement.isNull() ) {
QualifiedName name = childElement.tagName();
if ( name.localName() == "documentation" )
complexType->setDocumentation( childElement.text().stripWhiteSpace() );
}
node = node.nextSibling();
}
}
void Parser::parseAnnotation( const TQDomElement &element, SimpleType *simpleType )
{
TQDomNode node = element.firstChild();
while ( !node.isNull() ) {
TQDomElement childElement = node.toElement();
if ( !childElement.isNull() ) {
QualifiedName name = childElement.tagName();
if ( name.localName() == "documentation" )
simpleType->setDocumentation( childElement.text().stripWhiteSpace() );
}
node = node.nextSibling();
}
}
XSDType *Parser::parseComplexType( const TQDomElement &element )
{
ComplexType *newType = new ComplexType( mNameSpace );
newType->setName( element.attribute( "name" ) );
if ( element.hasAttribute( "mixed" ) )
newType->setContentModel( newType->MIXED );
TQDomNode node = element.firstChild();
while ( !node.isNull() ) {
TQDomElement childElement = node.toElement();
if ( !childElement.isNull() ) {
QualifiedName name = childElement.tagName();
if ( name.localName() == "all" ) {
all( childElement, newType );
} else if ( name.localName() == "sequence" ) {
cs( childElement, newType );
} else if ( name.localName() == "choice" ) {
cs( childElement, newType );
} else if ( name.localName() == "attribute" ) {
addAttribute( childElement, newType );
} else if ( name.localName() == "anyAttribute" ) {
addAnyAttribute( childElement, newType );
} else if ( name.localName() == "complexContent" ) {
parseComplexContent( childElement, newType );
} else if ( name.localName() == "simpleContent" ) {
parseSimpleContent( childElement, newType );
} else if ( name.localName() == "annotation" ) {
parseAnnotation( childElement, newType );
}
}
node = node.nextSibling();
}
return newType;
}
void Parser::all( const TQDomElement &element, ComplexType * ct )
{
int min, max;
TQString tmp;
min = element.attribute( "minOccurs", "1" ).toInt();
max = element.attribute( "maxOccurs", "1" ).toInt();
ct->setCompositor( ct->ALL, true, min, max );
TQDomNode node = element.firstChild();
while ( !node.isNull() ) {
TQDomElement childElement = node.toElement();
if ( !childElement.isNull() ) {
QualifiedName name = childElement.tagName();
if ( name.localName() == "element" ) {
addElement( childElement, ct );
} else if ( name.localName() == "annotation" ) {
parseAnnotation( childElement, ct );
}
}
node = node.nextSibling();
}
/*
if (xParser->getName() == "all"
&& xParser->getEventType() == xParser->END_TAG)
ct->setCompositor(ct->ALL, false);
*/
return;
}
void Parser::cs( const TQDomElement &element, ComplexType *ct )
{
int min = 1, max = 1;
QualifiedName name = element.tagName();
if ( name.localName() == "choice" || name.localName() == "sequence" ) {
min = element.attribute( "minOccurs", "1" ).toInt();
TQString value = element.attribute( "maxOccurs", "1" );
if ( value == "unbounded" )
max = UNBOUNDED;
else
max = value.toInt();
if ( name.localName() == "choice" )
ct->setCompositor( ct->CHOICE, true, min, max );
else
ct->setCompositor( ct->SEQ, true, min, max );
TQDomNode node = element.firstChild();
while ( !node.isNull() ) {
TQDomElement childElement = node.toElement();
if ( !childElement.isNull() ) {
QualifiedName csName = childElement.tagName();
if ( csName.localName() == "element" )
addElement( childElement, ct );
else if ( csName.localName() == "any" )
addAny( childElement, ct );
else if ( csName.localName() == "choice" )
cs( childElement, ct );
else if ( csName.localName() == "sequence" )
cs( childElement, ct );
}
node = node.nextSibling();
}
if ( name.localName() == "choice")
ct->setCompositor( ct->CHOICE, false );
else
ct->setCompositor( ct->SEQ, false );
}
return;
}
void Parser::addElement( const TQDomElement &element, ComplexType *cType )
{
TQString name, fixedValue, defaultValue, documentation;
QualifiedName refName;
int type_id = 0, minOccurs = 1, maxOccurs = 1;
bool qualified = false, added = false, nill = false;
XSDType *elemType;
name = element.attribute( "name" );
QualifiedName typeName = element.attribute( "type" );
// typeName.setNamespace(xParser->getNamespace(typeName.getPrefix()));
type_id = typeId( typeName, true );
if ( element.hasAttribute( "form" ) ) {
if ( element.attribute( "form" ) == "qualified" )
qualified = true;
else if ( element.attribute( "form" ) == "unqualified" )
qualified = false;
}
if ( element.hasAttribute( "ref" ) ) {
refName = element.attribute( "ref" );
// refName.setNamespace(xParser->getNamespace(refName.getPrefix()));
Element *e = 0;
if ( refName.nameSpace() == mNameSpace )
e = this->element( elementId( refName ) );
if ( e == 0 ) {
added = true;
mForwardElementRef.append( refName );
} else {
name = e->name();
type_id = e->type();
qualified = e->isQualified();
defaultValue = e->defaultValue();
fixedValue = e->fixedValue();
}
}
minOccurs = element.attribute( "minOccurs", "1" ).toInt();
TQString value = element.attribute( "maxOccurs", "1" );
if ( value == "unbounded" )
maxOccurs = UNBOUNDED;
else
maxOccurs = value.toInt();
defaultValue = element.attribute( "default" );
fixedValue = element.attribute( "fixed" );
if ( element.hasAttribute( "nillable" ) )
nill = true;
TQDomNode node = element.firstChild();
while ( !node.isNull() ) {
TQDomElement childElement = node.toElement();
if ( !childElement.isNull() ) {
QualifiedName childName = childElement.tagName();
if ( childName.localName() == "complexType" ) {
elemType = parseComplexType( childElement );
// create an anonymous type
ComplexType *ct = (ComplexType *) elemType;
if ( ct->numElements() == 1
&& ct->elementType( 0 ) == XSDType::ANY
&& ct->elementName( 0 ) == "any" ) {
// if the complex type is <any> then we dont need a type for it.
// make the tqparent's type as XSDType::ANY
delete ct;
type_id = XSDType::ANY;
} else {
elemType->setName( name );
type_id = mTypesTable.addType( elemType );
}
} else if ( childName.localName() == "simpleType" ) {
elemType = parseSimpleType( childElement );
//create an anonymous type
type_id = mTypesTable.addType( elemType );
} else if ( childName.localName() == "annotation" ) {
parseAnnotation( childElement, documentation );
}
}
node = node.nextSibling();
}
if ( nill && type_id == 0 )
type_id = XSDType::ANYTYPE;
if ( !added ) {
cType->addElement( name, type_id, minOccurs, maxOccurs, qualified, defaultValue, fixedValue, documentation );
} else {
cType->addElementRef( refName, minOccurs, maxOccurs );
}
}
void Parser::addAny( const TQDomElement &element, ComplexType *cType )
{
TQString ns, any( "any" );
int type_id = XSDType::ANY, min = 1, max = 1;
ns = element.attribute( "namespace" );
min = element.attribute( "minOccurs", "1" ).toInt();
TQString value = element.attribute( "maxOccurs", "1" );
if ( value == "unbounded" )
max = UNBOUNDED;
else
max = value.toInt();
cType->addElement( any, type_id, min, max, false, ns );
}
void Parser::addAnyAttribute( const TQDomElement &element, ComplexType *cType )
{
TQString ns, anyAttribute( "anyAttribute" );
ns = element.attribute( "namespace" );
cType->addAttribute( anyAttribute, XSDType::ANY, false, ns );
}
void Parser::addAttribute( const TQDomElement &element, ComplexType *cType )
{
TQString name, fixedVal, defaultVal;
int type_id = 0;
bool qualified = false, use = false, added = false;
QualifiedName refAttribute;
name = element.attribute( "name" );
if ( element.hasAttribute( "type" ) ) {
QualifiedName typeName = element.attribute( "type" );
// typeName.setNamespace(xParser->getNamespace(typeName.getPrefix()));
type_id = typeId( typeName, true );
}
if ( element.hasAttribute( "form" ) ) {
if ( element.attribute( "form" ) == "qualified" )
qualified = true;
else if ( element.attribute( "form" ) == "unqualified" )
qualified = false;
}
if ( element.hasAttribute( "ref" ) ) {
refAttribute = element.attribute( "ref" );
// refAttribute.setNamespace(xParser->getNamespace(refAttribute.getPrefix()));
Attribute *attribute = 0;
if ( refAttribute.nameSpace() == mNameSpace )
attribute = this->attribute( attributeId( refAttribute ) );
if ( attribute == 0 ) {
added = true;
mForwardAttributeRef.append( refAttribute );
} else {
name = attribute->name();
type_id = attribute->type();
qualified = attribute->isQualified();
defaultVal = attribute->defaultValue();
fixedVal = attribute->fixedValue();
}
}
defaultVal = element.attribute( "default" );
fixedVal = element.attribute( "fixed" );
if ( element.hasAttribute( "use" ) ) {
if ( element.attribute( "use" ) == "optional" )
use = false;
else if ( element.attribute( "use" ) == "required" )
use = true;
}
TQDomNode node = element.firstChild();
while ( !node.isNull() ) {
TQDomElement childElement = node.toElement();
if ( !childElement.isNull() ) {
QualifiedName childName = childElement.tagName();
if ( childName.localName() == "simpleType" ) {
XSDType *elemType = parseSimpleType( childElement );
elemType->setName( name );
type_id = mTypesTable.addType( elemType );
} else if ( childName.localName() == "annotation" ) {
// TKO: we have to pass it to the element here...
parseAnnotation( childElement );
}
}
node = node.nextSibling();
}
if ( !added )
cType->addAttribute( name, type_id, qualified, defaultVal, fixedVal, use );
else
cType->addAttributeRef( refAttribute, qualified, use );
}
XSDType *Parser::parseSimpleType( const TQDomElement &element )
{
SimpleType *st = new SimpleType( mNameSpace );
int basetype_id = XSDType::INVALID;
st->setName( element.attribute( "name" ) );
TQDomNode node = element.firstChild();
while ( !node.isNull() ) {
TQDomElement childElement = node.toElement();
if ( !childElement.isNull() ) {
QualifiedName name = childElement.tagName();
if ( name.localName() == "restriction" ) {
st->setSubType( SimpleType::TypeRestriction );
QualifiedName typeName( childElement.attribute( "base" ) );
// typeName.setNamespace(xParser->getNamespace(typeName.getPrefix()));
st->setBaseType( basetype_id = typeId( typeName, true ) );
parseRestriction( childElement, st );
} else if ( name.localName() == "union" ) {
st->setSubType( SimpleType::TypeUnion );
qDebug( "simpletype::union not supported" );
} else if ( name.localName() == "list" ) {
st->setSubType( SimpleType::TypeList );
if ( childElement.hasAttribute( "itemType" ) ) {
QualifiedName typeName( childElement.attribute( "itemType" ) );
int type = typeId( typeName, true );
st->setListType( type );
} else {
// TODO: add support for anonymous types
}
} else if ( name.localName() == "annotation" ) {
parseAnnotation( childElement, st );
}
}
node = node.nextSibling();
}
return st;
}
void Parser::parseRestriction( const TQDomElement &element, SimpleType *st )
{
if ( st->baseType() == 0 )
qDebug( "<restriction>:unkown BaseType" );
TQDomNode node = element.firstChild();
while ( !node.isNull() ) {
TQDomElement childElement = node.toElement();
if ( !childElement.isNull() ) {
if ( !st->isValidFacet( childElement.tagName() ) ) {
qDebug( "<restriction>: %s is not a valid facet for the simple type", childElement.tagName().latin1() );
continue;
}
st->setFacetValue( childElement.attribute( "value" ) );
}
node = node.nextSibling();
}
}
void Parser::parseComplexContent( const TQDomElement &element, ComplexType *ct )
{
QualifiedName typeName;
if ( element.attribute( "mixed" ) == "true" ) {
qDebug( "<complexContent>: No support for mixed=true" );
return;
}
ct->setContentModel( ct->COMPLEX );
TQDomNode node = element.firstChild();
while ( !node.isNull() ) {
TQDomElement childElement = node.toElement();
if ( !childElement.isNull() ) {
QualifiedName name = childElement.tagName();
if ( name.localName() == "restriction" || name.localName() == "extension" ) {
typeName = childElement.attribute( "base" );
// typeName.setNamespace(xParser->getNamespace(typeName.getPrefix()));
ComplexType::Derivation type = ( name.localName() == "restriction" ? ComplexType::Restriction : ComplexType::Extension );
if ( this->type( typeName ) != 0 ) { // type already known
ct->setBaseType( typeId( typeName, true ), type, this->type( typeName ) );
} else {
ForwardDerivation entry;
entry.type = ct->qualifiedName();
entry.baseType = typeName;
entry.derivation = type;
mForwardDerivations.append( entry );
}
// if the base soapenc:Array, then read only the arrayType attribute and nothing else
if ( typeName.localName() == "Array" ) {
TQDomElement arrayElement = childElement.firstChild().toElement();
ct->setIsArray( true );
QualifiedName arrayType( arrayElement.attribute( "arrayType" ) );
// arrayType.setNamespace(xParser->getNamespace(arrayType.getPrefix()));
ct->addElement( "item", typeId( arrayType, true ), 0, UNBOUNDED );
} else {
TQDomNode childNode = childElement.firstChild();
while ( !childNode.isNull() ) {
TQDomElement ctElement = childNode.toElement();
if ( !ctElement.isNull() ) {
QualifiedName name = ctElement.tagName();
if ( name.localName() == "all" ) {
all( ctElement, ct );
} else if ( name.localName() == "sequence" ) {
cs( ctElement, ct );
} else if ( name.localName() == "choice" ) {
cs( ctElement, ct );
} else if ( name.localName() == "attribute" ) {
addAttribute( ctElement, ct );
} else if ( name.localName() == "anyAttribute" ) {
addAnyAttribute( ctElement, ct );
}
}
childNode = childNode.nextSibling();
}
}
}
}
node = node.nextSibling();
}
}
void Parser::parseSimpleContent( const TQDomElement &element, ComplexType *ct )
{
ct->setContentModel( ct->SIMPLE );
const TQDomElement childElement = element.firstChild().toElement();
QualifiedName name = childElement.tagName();
if ( name.localName() == "restriction" ) {
SimpleType *st = new SimpleType( mNameSpace );
if ( childElement.hasAttribute( "base" ) ) {
int basetype_id = 0;
QualifiedName typeName( childElement.attribute( "base" ) );
// typeName.setNamespace(xParser->getNamespace(typeName.getPrefix()));
st->setBaseType( basetype_id = typeId( typeName, true ) );
}
parseRestriction( childElement, st );
int typeId = mTypesTable.addType( st );
if ( typeId == 0 ) {
qDebug( "Could not add type in types table" );
return;
}
ct->setContentType( typeId );
} else if ( name.localName() == "extension" ) {
// This extension does not use the full model that can come in ComplexContent.
// It uses the simple model. No particle allowed, only attributes
if ( childElement.hasAttribute( "base" ) ) {
int basetype_id = 0;
QualifiedName typeName( childElement.attribute( "base" ) );
// typeName.setNamespace(xParser->getNamespace(typeName.getPrefix()));
ct->setContentType( basetype_id = typeId( typeName, true ) );
TQDomNode childNode = childElement.firstChild();
while ( !childNode.isNull() ) {
TQDomElement ctElement = childNode.toElement();
if ( !ctElement.isNull() ) {
QualifiedName name = ctElement.tagName();
if ( name.localName() == "attribute" )
addAttribute( ctElement, ct );
}
childNode = childNode.nextSibling();
}
}
}
}
bool Parser::isBasicType( int type ) const
{
if ( type > XSDType::ANYURI )
return false;
else
return true;
}
void Parser::parseElement( const TQDomElement &element )
{
ComplexType *ct = new ComplexType( mNameSpace );
addElement( element, ct );
ComplexType *elementType = (ComplexType*)type( ct->element( 0 )->name() );
if ( elementType ) {
elementType->setDocumentation( ct->element( 0 )->documentation() );
}
Element *elementPtr = new Element();
*elementPtr = (*ct->element( 0 ));
delete ct;
mElements.append( elementPtr );
}
void Parser::parseAttribute( const TQDomElement &element )
{
ComplexType *ct = new ComplexType( mNameSpace );
addAttribute( element, ct );
Attribute *attributePtr = new Attribute();
*attributePtr = (*ct->attribute( 0 ));
delete ct;
mAttributes.append( attributePtr );
}
int Parser::addExternalElement( const TQString &name, int localTypeId )
{
Element *element = new Element( name, localTypeId );
mElements.append( element );
return mElements.count() - 1;
}
int Parser::typeId( const QualifiedName &type, bool create )
{
QualifiedName typeName( type );
TQString typens = typeName.nameSpace();
if ( typens.isEmpty() )
typeName.setNameSpace( typens = mNameSpace );
if ( typens == mNameSpace || typens == SchemaUri ) {
return mTypesTable.typeId( typeName, create );
} else {
return mTypesTable.addExternalTypeId( typeName, 0 );
}
}
TQString Parser::typeName( int id ) const
{
return mTypesTable.typeName( id );
}
bool Parser::finalize()
{
if ( mTypesTable.detectUndefinedTypes() )
return false;
else
return true;
}
void Parser::resolveForwardElementRefs()
{
if ( mForwardElementRef.isEmpty() )
return;
QualifiedName::List::ConstIterator it;
for ( it = mForwardElementRef.begin(); it != mForwardElementRef.end(); ++it ) {
Element *e = element( elementId( *it ) );
if ( e )
mTypesTable.resolveForwardElementRefs( (*it).localName(), *e );
else
qDebug( "Could not resolve element reference %s ", (*it).localName().latin1() );
}
}
void Parser::resolveForwardAttributeRefs()
{
if ( mForwardAttributeRef.isEmpty() )
return;
QualifiedName::List::ConstIterator it;
for ( it = mForwardAttributeRef.begin(); it != mForwardAttributeRef.end(); ++it ) {
Attribute *a = attribute( attributeId( *it ) );
if ( a )
mTypesTable.resolveForwardAttributeRefs( (*it).localName(), *a );
else
qDebug( "Could not resolve attribute reference %s ", (*it).localName().latin1() );
}
}
void Parser::resolveForwardDerivations()
{
if ( mForwardDerivations.isEmpty() )
return;
int id;
ComplexType *type = 0;
TQValueList<ForwardDerivation>::ConstIterator it;
for ( it = mForwardDerivations.begin(); it != mForwardDerivations.end(); ++it ) {
if ( ( id = typeId( (*it).type, false ) ) == 0 )
continue;
else
type = (ComplexType*)mTypesTable.typePtr( id );
if ( type )
type->setBaseType( typeId( (*it).baseType, true ), (*it).derivation, this->type( (*it).baseType ) );
}
mForwardDerivations.clear();
}
int Parser::elementId( const QualifiedName &type )
{
QualifiedName typeName( type );
TQString typens = typeName.nameSpace();
if ( typens.isEmpty() )
typeName.setNameSpace( typens = mNameSpace );
int i = 0;
// check if it is a global element
for ( i = 0; i < (int)mElements.count(); i++ )
if ( mElements[ i ]->name() == typeName.localName() )
return i;
return -1;
}
int Parser::elementType( const QualifiedName &type )
{
int id = elementId( type );
if ( id == -1 )
return 0;
Element *e = element( id );
if ( e != 0 )
return e->type();
else
return 0;
}
Element *Parser::element( const QualifiedName &name ) const
{
QualifiedName elementName( name );
TQString typens = elementName.nameSpace();
if ( typens.isEmpty() )
elementName.setNameSpace( typens = mNameSpace );
if ( typens == mNameSpace || typens == SchemaUri ) {
int i = 0;
// check if it is a global element
for ( i = 0; i < (int)mElements.count(); i++ )
if ( mElements[ i ]->name() == elementName.localName() )
return mElements[ i ];
return 0;
}
return 0;
}
Element *Parser::element( int id ) const
{
if ( id >= 0 && id < (int)mElements.count() )
return mElements[ id ];
else
return 0;
}
Element::PtrList Parser::elements() const
{
return mElements;
}
int Parser::attributeId( const QualifiedName &type ) const
{
QualifiedName typeName( type );
TQString typens = typeName.nameSpace();
if ( typens.isEmpty() )
typeName.setNameSpace( typens = mNameSpace );
if ( typens != mNameSpace && typens != SchemaUri ) {
qDebug( "Namespace does not match" );
return -1;
}
// check if it is a global attribute
for ( int i = 0; i < (int)mAttributes.count(); i++ )
if ( mAttributes[ i ]->name() == typeName.localName() )
return i;
return -1;
}
int Parser::attributeType( const QualifiedName &type )
{
int attId = attributeId( type );
if ( attId == -1 )
return 0;
Attribute *a = attribute( attId );
if ( a != 0 )
return a->type();
else
return 0;
}
Attribute *Parser::attribute( int id ) const
{
if ( id >= 0 && id < (int)mAttributes.count() )
return mAttributes[ id ];
else
return 0;
}
Attribute *Parser::attribute( const QualifiedName &name ) const
{
int id = attributeId( name );
if ( id != -1 )
return mAttributes[ id ];
else
return 0;
}
TQString Parser::targetNamespace() const
{
return mNameSpace;
}
const XSDType *Parser::type( int id ) const
{
return (const XSDType *)mTypesTable.typePtr( id );
}
const XSDType *Parser::type( const QualifiedName &type )
{
int id;
if ( ( id = typeId( type, false ) ) == 0 )
return 0;
else
return (const XSDType *)mTypesTable.typePtr( id );
}
int Parser::numTypes() const
{
return mTypesTable.numTypes();
}
int Parser::numElements() const
{
return mElements.count();
}
int Parser::numAttributes() const
{
return mAttributes.count();
}
bool Parser::shouldResolve()
{
return true;
}
void Parser::importSchema( const TQString &location )
{
FileProvider provider;
TQString fileName;
TQString schemaLocation( location );
TQUrl url( location );
TQDir dir( location );
if ( (url.protocol().isEmpty() || url.protocol() == "file") && dir.isRelative() )
schemaLocation = mSchemaBaseUrl + "/" + location;
if ( provider.get( schemaLocation, fileName ) ) {
TQFile file( fileName );
if ( !file.open( IO_ReadOnly ) ) {
qDebug( "Unable to open file %s", file.name().latin1() );
return;
}
TQDomDocument doc( "kwsdl" );
TQString errorMsg;
int errorLine, errorColumn;
bool ok = doc.setContent( &file, true, &errorMsg, &errorLine, &errorColumn );
if ( !ok ) {
qDebug( "Error[%d:%d] %s", errorLine, errorColumn, errorMsg.latin1() );
return;
}
TQDomNodeList nodes = doc.elementsByTagName( "schema" );
if ( nodes.count() > 0 ) {
TQDomElement schemaElement = nodes.item( 0 ).toElement();
parseSchemaTag( schemaElement );
} else {
qDebug( "No schema tag found in schema file" );
}
file.close();
provider.cleanUp();
}
}