void ComplexBaseInputField::xmlData( QDomDocument &document, QDomElement &parent ) { QDomElement element = document.createElement( mName ); XSD::Element::List elements = mType->elements(); XSD::Element::List::ConstIterator elemIt; for ( elemIt = elements.constBegin(); elemIt != elements.constEnd(); ++elemIt ) { InputField *field = childField( (*elemIt).name() ); if ( !field ) { qDebug( "ComplexBaseInputField: No child found" ); } else { field->xmlData( document, element ); } } XSD::Attribute::List attributes = mType->attributes(); XSD::Attribute::List::ConstIterator attrIt; for ( attrIt = attributes.constBegin(); attrIt != attributes.constEnd(); ++attrIt ) { InputField *field = childField( (*attrIt).name() ); if ( !field ) { qDebug( "ComplexBaseInputField: No child found" ); } else { element.setAttribute( field->name(), field->data() ); } } parent.appendChild( element ); }
ComplexBaseInputField::ComplexBaseInputField( const QString &name, const XSD::ComplexType *type ) : ComplexInputField( name, type ) { XSD::Element::List elements = type->elements(); XSD::Element::List::ConstIterator elemIt; for ( elemIt = elements.constBegin(); elemIt != elements.constEnd(); ++elemIt ) { bool isList = ((*elemIt).maxOccurs() == XSD::Parser::UNBOUNDED); InputField *field = InputFieldFactory::self()->createField( (*elemIt).name(), (*elemIt).type().qname(), isList ); if ( !field ) { qDebug( "ComplexBaseInputField: Unable to create field of type %s", qPrintable( type->baseTypeName().qname() ) ); } else { appendChild( field ); } } XSD::Attribute::List attributes = type->attributes(); XSD::Attribute::List::ConstIterator attrIt; for ( attrIt = attributes.constBegin(); attrIt != attributes.constEnd(); ++attrIt ) { InputField *field = InputFieldFactory::self()->createField( (*attrIt).name(), (*attrIt).type().qname() ); if ( !field ) { qDebug( "ComplexBaseInputField: Unable to create field of type %s", qPrintable( type->baseTypeName().qname() ) ); } else { appendChild( field ); } } }
void Converter::convertComplexType( const XSD::ComplexType *type ) { const QString typeName( mTypeMap.localType( type->qualifiedName() ) ); KODE::Class newClass( typeName ); newClass.addInclude( QString(), "Serializer" ); KODE::Code ctorBody; KODE::Code dtorBody; // subclass handling if ( !type->baseTypeName().isEmpty() ) { // this class extends something /** * A class can't subclass basic type (e.g. int, unsigned char), so we * add setValue() and value() methods to access the base type. */ if ( mTypeMap.isBasicType( type->baseTypeName() ) ) { const QName baseName = type->baseTypeName(); const QString typeName = mTypeMap.localType( baseName ); // include header newClass.addIncludes( QStringList(), mTypeMap.forwardDeclarations( baseName ) ); // member variables KODE::MemberVariable variable( "value", typeName + '*' ); newClass.addMemberVariable( variable ); ctorBody += variable.name() + " = 0;"; dtorBody += "delete " + variable.name() + "; " + variable.name() + " = 0;"; // setter method KODE::Function setter( "setValue", "void" ); setter.addArgument( typeName + " *value" ); setter.setBody( variable.name() + " = value;" ); // getter method KODE::Function getter( "value", typeName + '*' ); getter.setBody( "return " + variable.name() + ';' ); getter.setConst( true ); // convenience constructor KODE::Function conctor( upperlize( newClass.name() ) ); conctor.addArgument( typeName + " *value" ); conctor.setBody( variable.name() + " = value;" ); if ( typeName == "QString" ) { KODE::Function charctor( upperlize( newClass.name() ) ); charctor.addArgument( "const char *charValue" ); charctor.setBody( variable.name() + " = new QString( charValue );" ); newClass.addFunction( charctor ); } // type operator KODE::Function op( "operator const " + typeName + '*' ); op.setBody( "return " + variable.name() + ';' ); op.setConst( true ); newClass.addFunction( conctor ); newClass.addFunction( op ); newClass.addFunction( setter ); newClass.addFunction( getter ); } else if ( type->baseTypeName().localName() == "Array" ) { // handle soap array // this is handled in the attribute section } else { if ( type->baseTypeName() != XmlAnyType ) { QString baseName = mTypeMap.localType( type->baseTypeName() ); newClass.addBaseClass( KODE::Class( baseName ) ); } } } if ( !type->documentation().isEmpty() ) newClass.setDocs( type->documentation().simplified() ); // elements XSD::Element::List elements = type->elements(); XSD::Element::List::ConstIterator elemIt; for ( elemIt = elements.constBegin(); elemIt != elements.constEnd(); ++elemIt ) { QString typeName = mTypeMap.localType( (*elemIt).type() ); if ( (*elemIt).maxOccurs() > 1 ) typeName = "QList<" + typeName + "*>"; // member variables KODE::MemberVariable variable( (*elemIt).name(), typeName + '*' ); newClass.addMemberVariable( variable ); ctorBody += variable.name() + " = 0;"; if ( (*elemIt).maxOccurs() > 1 ) { dtorBody += "qDeleteAll( *" + variable.name() + " );"; dtorBody += variable.name() + "->clear();"; } dtorBody += "delete " + variable.name() + "; " + variable.name() + " = 0;"; QString upperName = upperlize( (*elemIt).name() ); QString lowerName = lowerlize( (*elemIt).name() ); // setter method KODE::Function setter( "set" + upperName, "void" ); setter.addArgument( typeName + " *" + mNameMapper.escape( lowerName ) ); setter.setBody( variable.name() + " = " + mNameMapper.escape( lowerName ) + ';' ); // getter method KODE::Function getter( mNameMapper.escape( lowerName ), typeName + '*' ); getter.setBody( "return " + variable.name() + ';' ); getter.setConst( true ); newClass.addFunction( setter ); newClass.addFunction( getter ); // include header newClass.addIncludes( QStringList(), mTypeMap.forwardDeclarations( (*elemIt).type() ) ); if ( (*elemIt).maxOccurs() > 1 ) newClass.addHeaderIncludes( QStringList( "QList" ) ); } // attributes XSD::Attribute::List attributes = type->attributes(); XSD::Attribute::List::ConstIterator attrIt; for ( attrIt = attributes.constBegin(); attrIt != attributes.constEnd(); ++attrIt ) { QString typeName; bool isArray = !(*attrIt).arrayType().isEmpty(); if ( isArray ) typeName = "QList<" + mTypeMap.localType( (*attrIt).arrayType() ) + "*>"; else typeName = mTypeMap.localType( (*attrIt).type() ); // member variables KODE::MemberVariable variable( (*attrIt).name(), typeName + '*' ); newClass.addMemberVariable( variable ); ctorBody += variable.name() + " = 0;"; if ( isArray ) { dtorBody += "qDeleteAll( *" + variable.name() + " );"; dtorBody += variable.name() + "->clear();"; } dtorBody += "delete " + variable.name() + "; " + variable.name() + " = 0;"; QString upperName = upperlize( (*attrIt).name() ); QString lowerName = lowerlize( (*attrIt).name() ); // setter method KODE::Function setter( "set" + upperName, "void" ); setter.addArgument( typeName + " *" + mNameMapper.escape( lowerName ) ); setter.setBody( variable.name() + " = " + mNameMapper.escape( lowerName ) + ';' ); // getter method KODE::Function getter( mNameMapper.escape( lowerName ), typeName + '*' ); getter.setBody( "return " + variable.name() + ';' ); getter.setConst( true ); newClass.addFunction( setter ); newClass.addFunction( getter ); // include header newClass.addIncludes( QStringList(), mTypeMap.forwardDeclarations( (*attrIt).type() ) ); if ( isArray ) newClass.addHeaderIncludes( QStringList( "QList" ) ); } createComplexTypeSerializer( type ); KODE::Function ctor( upperlize( newClass.name() ) ); ctor.setBody( ctorBody ); newClass.addFunction( ctor ); KODE::Function dtor( '~' + upperlize( newClass.name() ) ); dtor.setBody( dtorBody ); newClass.addFunction( dtor ); mClasses.append( newClass ); }
void Converter::createComplexTypeSerializer( const XSD::ComplexType *type ) { const QString typeName = mTypeMap.localType( type->qualifiedName() ); const QString baseType = mTypeMap.localType( type->baseTypeName() ); KODE::Function marshal( "marshal", "void" ); marshal.setStatic( true ); marshal.addArgument( "QDomDocument &doc" ); marshal.addArgument( "QDomElement &parent" ); marshal.addArgument( "const QString &name" ); marshal.addArgument( "const " + typeName + " *value" ); marshal.addArgument( "bool noNamespace" ); KODE::Function demarshal( "demarshal", "void" ); demarshal.setStatic( true ); demarshal.addArgument( "const QDomElement &parent" ); demarshal.addArgument( typeName + " *value" ); KODE::Code marshalCode, demarshalCode, demarshalStartCode, demarshalFinalCode; marshalCode += "if ( !value )"; marshalCode.indent(); marshalCode += "return;"; marshalCode.unindent(); marshalCode.newLine(); demarshalStartCode += "if ( !value )"; demarshalStartCode.indent(); demarshalStartCode += "return;"; demarshalStartCode.unindent(); demarshalStartCode.newLine(); // include header mSerializer.addIncludes( QStringList(), mTypeMap.forwardDeclarations( type->qualifiedName() ) ); marshalCode += "QDomElement parentElement;"; marshalCode += "if ( !name.isEmpty() ) {"; marshalCode.indent(); const QString typePrefix = mNSManager.prefix( type->qualifiedName().nameSpace() ); marshalCode += "QDomElement root = doc.createElement( noNamespace ? name : \"" + typePrefix + ":\" + name );"; marshalCode += "root.setAttribute( \"" + mNSManager.schemaInstancePrefix() + ":type\", \"" + typePrefix + ":" + typeName + "\" );"; marshalCode += "parent.appendChild( root );"; marshalCode += "parentElement = root;"; marshalCode.unindent(); marshalCode += "} else {"; marshalCode.indent(); marshalCode += "parentElement = parent;"; marshalCode.unindent(); marshalCode += '}'; marshalCode.newLine(); // handle marshalling of base types if ( type->baseTypeName() != XmlAnyType && !type->baseTypeName().isEmpty() && !type->isArray() ) { marshalCode += "// marshall base type"; marshalCode += "Serializer::marshal( doc, parentElement, QString(), (" + baseType + "*)value, noNamespace );"; } // handle demarshalling of base types if ( type->baseTypeName() != XmlAnyType && !type->baseTypeName().isEmpty() && !type->isArray() ) { demarshalCode += "// demarshall base type"; demarshalCode += "Serializer::demarshal( parent, (" + baseType + "*)value );"; demarshalCode.newLine(); } demarshalCode += "QDomNode node = parent.firstChild();"; demarshalCode += "while ( !node.isNull() ) {"; demarshalCode.indent(); demarshalCode += "QDomElement element = node.toElement();"; demarshalCode += "if ( !element.isNull() ) {"; demarshalCode.indent(); // elements XSD::Element::List elements = type->elements(); XSD::Element::List::ConstIterator elemIt; for ( elemIt = elements.constBegin(); elemIt != elements.constEnd(); ++elemIt ) { const QString typeName = mTypeMap.localType( (*elemIt).type() ); QString upperName = upperlize( (*elemIt).name() ); QString lowerName = lowerlize( (*elemIt).name() ); KODE::Function setter( "set" + upperName, "void" ); KODE::Function getter( mNameMapper.escape( lowerName ), typeName + '*' ); if ( (*elemIt).maxOccurs() > 1 ) { const QString typePrefix = mNSManager.prefix( (*elemIt).type().nameSpace() ); marshalCode += '{'; marshalCode.indent(); marshalCode += "const QList<" + typeName + "*> *list = value->" + mNameMapper.escape( lowerName ) + "();"; marshalCode.newLine(); marshalCode += "QList<" + typeName + "*>::ConstIterator it;"; marshalCode += "for ( it = list->begin(); it != list->end(); ++it ) {"; marshalCode.indent(); marshalCode += "Serializer::marshal( doc, parentElement, \"" + typePrefix + ":" + (*elemIt).name() + "\", *it, false );"; marshalCode.unindent(); marshalCode += '}'; marshalCode.unindent(); marshalCode += '}'; const QString listName = mNameMapper.escape( lowerName ) + "List"; demarshalStartCode += "QList<" + typeName + "*> *" + listName + " = new QList<" + typeName + "*>();"; demarshalCode += "if ( element.tagName() == \"" + (*elemIt).name() + "\" ) {"; demarshalCode.indent(); demarshalCode += typeName + " *item = new " + typeName + "();"; demarshalCode += "Serializer::demarshal( element, item );"; demarshalCode += listName + "->append( item );"; demarshalCode.unindent(); demarshalCode += '}'; demarshalFinalCode += "value->" + setter.name() + "( " + listName + " );"; } else { marshalCode += "Serializer::marshal( doc, parentElement, \"" + (*elemIt).name() + "\", value->" + getter.name() + "(), false );"; demarshalCode += "if ( element.tagName() == \"" + (*elemIt).name() + "\" ) {"; demarshalCode.indent(); demarshalCode += typeName + " *item = new " + typeName + "();"; demarshalCode += "Serializer::demarshal( element, item );"; demarshalCode += "value->" + setter.name() + "( item );"; demarshalCode.unindent(); demarshalCode += '}'; } } // attributes XSD::Attribute::List attributes = type->attributes(); XSD::Attribute::List::ConstIterator attrIt; for ( attrIt = attributes.constBegin(); attrIt != attributes.constEnd(); ++attrIt ) { QString upperName = upperlize( (*attrIt).name() ); QString lowerName = lowerlize( (*attrIt).name() ); KODE::Function setter( "set" + upperName, "void" ); bool isArray = !(*attrIt).arrayType().isEmpty(); if ( isArray ) { const QString typeName = mTypeMap.localType( (*attrIt).arrayType() ); const QString typePrefix = mNSManager.prefix( (*attrIt).arrayType().nameSpace() ); marshalCode += '{'; marshalCode.indent(); marshalCode += "const QList<" + typeName + "*> *list = value->" + mNameMapper.escape( lowerName ) + "();"; marshalCode.newLine(); marshalCode += "QDomElement element = doc.createElement( noNamespace ? name : \"" + typePrefix + ":\" + name );"; marshalCode += "element.setAttribute( \"" + mNSManager.schemaInstancePrefix() + ":type\", \"" + mNSManager.soapEncPrefix() + ":Array\" );"; marshalCode += "element.setAttribute( \"" + mNSManager.soapEncPrefix() + ":arrayType\", \"" + typePrefix + ":" + typeName + "[\" + QString::number( list->count() ) + \"]\" );"; marshalCode += "parentElement.appendChild( element );"; marshalCode.newLine(); marshalCode += "QList<" + typeName + "*>::ConstIterator it;"; marshalCode += "for ( it = list->begin(); it != list->end(); ++it ) {"; marshalCode.indent(); marshalCode += "Serializer::marshal( doc, element, \"item\", *it, false );"; marshalCode.unindent(); marshalCode += '}'; marshalCode.unindent(); marshalCode += '}'; const QString listName = mNameMapper.escape( lowerName ) + "List"; // TODO: prepend the code somehow demarshalStartCode += "QList<" + typeName + "*> *" + listName + " = new QList<" + typeName + "*>();"; demarshalCode.indent(); demarshalCode += typeName + " *item = new " + typeName + "();"; demarshalCode += "Serializer::demarshal( element, item );"; demarshalCode += listName + "->append( item );"; demarshalCode.unindent(); demarshalFinalCode += "value->" + setter.name() + "( " + listName + " );"; } else { const QString typeName = mTypeMap.localType( (*attrIt).type() ); marshalCode += "parentElement.setAttribute( \"" + (*attrIt).name() + "\", " "Serializer::marshalValue( value->" + mNameMapper.escape( lowerName ) + "() ) );"; marshalCode.newLine(); demarshalCode += "if ( element.hasAttribute( \"" + (*attrIt).name() + "\" ) ) {"; demarshalCode.indent(); demarshalCode += typeName + " *item = new " + typeName + "();"; demarshalCode += "Serializer::demarshalValue( element.attribute( \"" + (*attrIt).name() + "\" ), item );"; demarshalCode += "value->" + setter.name() + "( item );"; demarshalCode.unindent(); demarshalCode += '}'; } } demarshalCode.unindent(); demarshalCode += '}'; demarshalCode += "node = node.nextSibling();"; demarshalCode.unindent(); demarshalCode += '}'; demarshalCode.newLine(); demarshalCode += demarshalFinalCode; demarshalStartCode.newLine(); demarshalStartCode += demarshalCode; marshal.setBody( marshalCode ); mSerializer.addFunction( marshal ); demarshal.setBody( demarshalStartCode ); mSerializer.addFunction( demarshal ); }
void TypeMap::addSchemaTypes( const XSD::Types &types, const QString& ns ) { Q_ASSERT( mNSManager ); XSD::SimpleType::List simpleTypes = types.simpleTypes(); XSD::SimpleType::List::ConstIterator simpleIt; for ( simpleIt = simpleTypes.constBegin(); simpleIt != simpleTypes.constEnd(); ++simpleIt ) { Entry entry; entry.basicType = false; entry.builtinType = false; entry.nameSpace = (*simpleIt).nameSpace(); entry.typeName = (*simpleIt).name(); entry.localType = prefixNamespace( mNSManager->prefix( entry.nameSpace ).toUpper() + "__" + adaptLocalTypeName( (*simpleIt).name() ), ns ); entry.baseType = (*simpleIt).baseTypeName(); //qDebug() << entry.baseType.nameSpace() << entry.baseType.localName() << entry.baseType; //entry.headers << (*simpleIt).name().toLower() + ".h"; entry.forwardDeclarations << entry.localType; mTypeMap.append( entry ); } foreach ( const XSD::ComplexType &complex, types.complexTypes() ) { Entry entry; entry.basicType = false; entry.builtinType = false; entry.complexType = true; entry.nameSpace = complex.nameSpace(); entry.typeName = complex.name(); entry.isPolymorphic = complex.isPolymorphicBaseClass(); //qDebug() << "TypeMap: adding complex type" << entry.nameSpace << entry.typeName << "derived types:" << complex.derivedTypes(); // Keep empty complex types, useful for document mode. /*if ( (*complexIt).isEmpty() ) entry.localType = "void"; else*/ { entry.localType = prefixNamespace( mNSManager->prefix( entry.nameSpace ).toUpper() + "__" + adaptLocalTypeName( complex.name() ), ns ); if (complex.isConflicting()) { entry.localType += complex.isAnonymous() ? "Element" : "Type"; } //entry.headers << (*complexIt).name().toLower() + ".h"; entry.forwardDeclarations << entry.localType; } mTypeMap.append( entry ); } XSD::Attribute::List attributes = types.attributes(); XSD::Attribute::List::ConstIterator attrIt; for ( attrIt = attributes.constBegin(); attrIt != attributes.constEnd(); ++attrIt ) { if ( (*attrIt).nameSpace() == "http://www.w3.org/2003/05/soap-encoding" ) // e.g. soap-enc:arrayType continue; Entry entry; entry.basicType = false; entry.builtinType = false; entry.nameSpace = (*attrIt).nameSpace(); entry.typeName = (*attrIt).name(); entry.localType = prefixNamespace( mNSManager->prefix( entry.nameSpace ).toUpper() + "__" + adaptLocalTypeName( (*attrIt).name() + "Attribute" ), ns ); entry.headers << (*attrIt).name().toLower() + "attribute.h"; entry.forwardDeclarations << entry.localType; mAttributeMap.append( entry ); } const XSD::Element::List elements = types.elements(); Q_FOREACH( const XSD::Element& elemIt, elements ) { Entry entry; entry.nameSpace = elemIt.nameSpace(); entry.typeName = elemIt.name(); QName type = elemIt.type(); if ( type.isEmpty() ) { qDebug() << "ERROR: element without type" << elemIt.nameSpace() << elemIt.name(); } // Resolve to localType(type) QList<Entry>::ConstIterator it = typeEntry(type); if ( it == mTypeMap.constEnd() ) { qDebug() << "ERROR: basic type not found:" << type; Q_ASSERT(0); continue; } const QString resolvedType = (*it).localType; Q_ASSERT( !resolvedType.isEmpty() ); entry.localType = resolvedType; entry.basicType = (*it).basicType; entry.builtinType = (*it).builtinType; entry.complexType = (*it).complexType; entry.baseType = type; if ( !entry.basicType ) entry.forwardDeclarations << entry.localType; // The "FooElement" type isn't necessary, we just point to the resolved type // directly, this is much simpler. /*} else { entry.localType = mNSManager->prefix( entry.nameSpace ).toUpper() + "__" + adaptLocalTypeName( elemIt.name() + "Element" ); }*/ //qDebug() << "Adding TypeMap entry for element" << entry.typeName << resolvedType; mElementMap.append( entry ); }