QString TypeMapper::type( const QString &typeName ) const { // check basic types QMap<QString, TypeInfo>::ConstIterator it = mMap.find( typeName ); if ( it != mMap.end() ) return it.data().type; Schema::SimpleType::List simpleTypes = mTypes.simpleTypes(); Schema::SimpleType::List::ConstIterator simpleIt; for ( simpleIt = simpleTypes.begin(); simpleIt != simpleTypes.end(); ++simpleIt ) { if ( (*simpleIt).name() == typeName ) { return type( &(*simpleIt) ); } } Schema::ComplexType::List complexTypes = mTypes.complexTypes(); Schema::ComplexType::List::ConstIterator complexIt; for ( complexIt = complexTypes.begin(); complexIt != complexTypes.end(); ++complexIt ) { if ( (*complexIt).name() == typeName ) { return type( &(*complexIt) ); } } Schema::Element::List elements = mTypes.elements(); Schema::Element::List::ConstIterator elemIt; for ( elemIt = elements.begin(); elemIt != elements.end(); ++elemIt ) { if ( (*elemIt).name() == typeName ) { return type( &(*elemIt) ); } } return QString(); }
void Converter::createComplexTypeSerializer( const Schema::ComplexType *type ) { const QString typeName = mTypeMapper.type( type ); 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" ); KODE::Function demarshal( "demarshal", "void" ); demarshal.setStatic( true ); demarshal.addArgument( "const QDomElement &parent" ); demarshal.addArgument( typeName + "* value" ); KODE::Code marshalCode, demarshalCode, demarshalFinalCode; // include header QMap<QString, QString> headerDec = mTypeMapper.headerDec( type->name() ); QMap<QString, QString>::ConstIterator it; for ( it = headerDec.begin(); it != headerDec.end(); ++it ) { if ( !it.key().isEmpty() ) mSerializer.addInclude( it.key(), it.data() ); if ( it.data().isEmpty() ) mSerializer.addHeaderInclude( it.key() ); } marshalCode += "QDomElement root = doc.createElement( name );"; marshalCode += "root.setAttribute( \"xsi:type\", \"ns1:" + typeName + "\" );"; marshalCode += "parent.appendChild( root );"; demarshalCode += "QDomNode node = parent.firstChild();"; demarshalCode += "while ( !node.isNull() ) {"; demarshalCode.indent(); demarshalCode += "QDomElement element = node.toElement();"; demarshalCode += "if ( !element.isNull() ) {"; demarshalCode.indent(); // elements Schema::Element::List elements = type->elements(); Schema::Element::List::ConstIterator elemIt; for ( elemIt = elements.begin(); elemIt != elements.end(); ++elemIt ) { const QString typeName = mTypeMapper.type( &*elemIt ); QString upperName = (*elemIt).name(); QString lowerName = (*elemIt).name(); upperName[ 0 ] = upperName[ 0 ].upper(); lowerName[ 0 ] = lowerName[ 0 ].lower(); KODE::Function setter( "set" + upperName, "void" ); KODE::Function getter( mNameMapper.escape( lowerName ), typeName + "*" ); if ( (*elemIt).maxOccurs() > 1 ) { marshalCode += "if ( value->" + mNameMapper.escape( lowerName ) + "() ) {"; marshalCode.indent(); marshalCode += "const QPtrList<" + typeName + ">* list = value->" + mNameMapper.escape( lowerName ) + "();"; marshalCode.newLine(); marshalCode += "QDomElement element = doc.createElement( name );"; // no idea about the namespaces here... marshalCode += "element.setAttribute( \"xmlns:ns1\", \"http://schemas.xmlsoap.org/soap/encoding/\" );"; marshalCode += "element.setAttribute( \"xsi:type\", \"ns1:Array\" );"; marshalCode += "element.setAttribute( \"ns1:arrayType\", \"ns1:" + typeName + "[\" + QString::number( list->count() ) + \"]\" );"; marshalCode += "parent.appendChild( element );"; marshalCode.newLine(); marshalCode += "QPtrListIterator<" + typeName + "> it( *list );"; marshalCode += "while ( it.current() != 0 ) {"; marshalCode.indent(); marshalCode += "Serializer::marshal( doc, element, \"item\", it.current() );"; marshalCode += "++it;"; marshalCode.unindent(); marshalCode += "}"; marshalCode.unindent(); marshalCode += "}"; const QString listName = mNameMapper.escape( lowerName ) + "List"; // TODO: prepend the code somehow KODE::Code code; code += "QPtrList<" + typeName + ">* " + listName + " = new QPtrList<" + typeName + ">();"; code += listName + "->setAutoDelete( true );"; code += demarshalCode; demarshalCode = code; demarshalCode += "if ( element.tagName() == \"item\" ) {"; 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 += "if ( value->" + getter.name() + "() ) {"; marshalCode.indent(); marshalCode += "Serializer::marshal( doc, root, \"" + (*elemIt).name() + "\", value->" + getter.name() + "() );"; marshalCode.unindent(); marshalCode += "}"; 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 Schema::Attribute::List attributes = type->attributes(); Schema::Attribute::List::ConstIterator attrIt; for ( attrIt = attributes.begin(); attrIt != attributes.end(); ++attrIt ) { const QString typeName = mTypeMapper.type( &*attrIt ); QString upperName = (*attrIt).name(); QString lowerName = (*attrIt).name(); upperName[ 0 ] = upperName[ 0 ].upper(); lowerName[ 0 ] = lowerName[ 0 ].lower(); KODE::Function setter( "set" + upperName, "void" ); KODE::Function getter( mNameMapper.escape( lowerName ), typeName + "*" ); marshalCode += "if ( value->" + mNameMapper.escape( lowerName ) + "() )"; marshalCode.indent(); marshalCode += "parent.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; marshal.setBody( marshalCode ); mSerializer.addFunction( marshal ); demarshal.setBody( demarshalCode ); mSerializer.addFunction( demarshal ); }
void Converter::convertComplexType( const Schema::ComplexType *type ) { KODE::Class newClass( type->name() ); newClass.addInclude( "serializer.h" ); KODE::Code ctorCode, dtorCode; if ( type->baseType() != Schema::XSDType::ANYTYPE && !type->isArray() ) { QString baseName = mTypeMapper.type( type->baseTypeName() ); newClass.addBaseClass( KODE::Class( baseName ) ); newClass.addHeaderIncludes( mTypeMapper.header( type->baseTypeName() ) ); } if ( !type->documentation().isEmpty() ) newClass.setDocs( type->documentation().simplifyWhiteSpace() ); // elements Schema::Element::List elements = type->elements(); Schema::Element::List::ConstIterator elemIt; for ( elemIt = elements.begin(); elemIt != elements.end(); ++elemIt ) { QString typeName = mTypeMapper.type( &*elemIt ); if ( (*elemIt).maxOccurs() > 1 ) typeName = "QPtrList<" + typeName + ">"; // member variables KODE::MemberVariable variable( (*elemIt).name(), typeName + "*" ); newClass.addMemberVariable( variable ); ctorCode += variable.name() + " = 0;"; dtorCode += "delete " + variable.name() + ";"; dtorCode += variable.name() + " = 0;"; QString upperName = (*elemIt).name(); QString lowerName = (*elemIt).name(); upperName[ 0 ] = upperName[ 0 ].upper(); lowerName[ 0 ] = lowerName[ 0 ].lower(); // setter method KODE::Function setter( "set" + upperName, "void" ); setter.addArgument( mTypeMapper.argument( mNameMapper.escape( lowerName ), &*elemIt ) ); 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 QMap<QString, QString> headerDec = mTypeMapper.headerDec( &*elemIt); QMap<QString, QString>::ConstIterator it; for ( it = headerDec.begin(); it != headerDec.end(); ++it ) { if ( !it.key().isEmpty() ) newClass.addInclude( it.key(), it.data() ); if ( it.data().isEmpty() ) newClass.addHeaderInclude( it.key() ); } } // attributes Schema::Attribute::List attributes = type->attributes(); Schema::Attribute::List::ConstIterator attrIt; for ( attrIt = attributes.begin(); attrIt != attributes.end(); ++attrIt ) { const QString typeName = mTypeMapper.type( &*attrIt ); // member variables KODE::MemberVariable variable( (*attrIt).name(), typeName + "*" ); newClass.addMemberVariable( variable ); ctorCode += variable.name() + " = 0;"; dtorCode += "delete " + variable.name() + ";"; dtorCode += variable.name() + " = 0;"; QString upperName = (*attrIt).name(); QString lowerName = (*attrIt).name(); upperName[ 0 ] = upperName[ 0 ].upper(); lowerName[ 0 ] = lowerName[ 0 ].lower(); // setter method KODE::Function setter( "set" + upperName, "void" ); setter.addArgument( mTypeMapper.argument( mNameMapper.escape( lowerName ), &*attrIt ) ); 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 QMap<QString, QString> headerDec = mTypeMapper.headerDec( &*attrIt); QMap<QString, QString>::ConstIterator it; for ( it = headerDec.begin(); it != headerDec.end(); ++it ) { if ( !it.key().isEmpty() ) newClass.addInclude( it.key(), it.data() ); if ( it.data().isEmpty() ) newClass.addHeaderInclude( it.key() ); } } createComplexTypeSerializer( type ); KODE::Function ctor( capitalize( newClass.name() ) ); KODE::Function dtor( "~" + capitalize( newClass.name() ) ); ctor.setBody( ctorCode ); dtor.setBody( dtorCode ); newClass.addFunction( ctor ); newClass.addFunction( dtor ); mClasses.append( newClass ); }