示例#1
0
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 );
}
示例#2
0
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 );
    }
  }
}
示例#3
0
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 );
}
示例#4
0
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 );
}
示例#5
0
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 );
  }