static KODE::Code createRangeCheckCode( const XSD::SimpleType *type, const QString &variableName, KODE::Class &parentClass ) { KODE::Code code; code += "bool rangeOk = true;"; code.newLine(); // TODO /* WhiteSpaceType facetWhiteSpace() const; int facetTotalDigits() const; int facetFractionDigits() const; */ if ( type->facetType() & XSD::SimpleType::MININC ) code += "rangeOk = rangeOk && (" + variableName + " >= " + QString::number( type->facetMinimumInclusive() ) + ");"; if ( type->facetType() & XSD::SimpleType::MINEX ) code += "rangeOk = rangeOk && (" + variableName + " > " + QString::number( type->facetMinimumExclusive() ) + ");"; if ( type->facetType() & XSD::SimpleType::MAXINC ) code += "rangeOk = rangeOk && (" + variableName + " <= " + QString::number( type->facetMaximumInclusive() ) + ");"; if ( type->facetType() & XSD::SimpleType::MINEX ) code += "rangeOk = rangeOk && (" + variableName + " < " + QString::number( type->facetMaximumExclusive() ) + ");"; if ( type->facetType() & XSD::SimpleType::LENGTH ) code += "rangeOk = rangeOk && (" + variableName + ".length() == " + QString::number( type->facetLength() ) + ");"; if ( type->facetType() & XSD::SimpleType::MINLEN ) code += "rangeOk = rangeOk && (" + variableName + ".length() >= " + QString::number( type->facetMinimumLength() ) + ");"; if ( type->facetType() & XSD::SimpleType::MAXLEN ) code += "rangeOk = rangeOk && (" + variableName + ".length() <= " + QString::number( type->facetMaximumLength() ) + ");"; if ( type->facetType() & XSD::SimpleType::PATTERN ) { code += "QRegExp exp( \"" + type->facetPattern() + "\" );"; code += "rangeOk = rangeOk && exp.exactMatch( " + variableName + " );"; parentClass.addInclude( "QRegExp" ); } return code; }
void Converter::convertComplexType(const XSD::ComplexType *type) { // An empty type is still useful, in document mode: it serializes the element name //if ( type->isEmpty() ) // return; // Skip the Array types we added in Parser::init... if (NSManager::soapEncNamespaces().contains(type->nameSpace())) { return; } const QString className(mTypeMap.localType(type->qualifiedName())); KODE::Class newClass; newClass.setNamespaceAndName(className); if (!Settings::self()->exportDeclaration().isEmpty()) { newClass.setExportDeclaration(Settings::self()->exportDeclaration()); } newClass.setUseSharedData(true, QLatin1String("d_ptr") /*avoid clash with possible d() method */); const bool doDebug = (qgetenv("KDSOAP_TYPE_DEBUG").toInt()); if (doDebug) { qDebug() << "Generating complex type" << className; } // 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. * * In fact, let's do the same with string */ if (type->baseTypeName().localName() == QLatin1String("Array")) { // this is handled in the attribute section } else { const QName baseName = type->baseTypeName(); const QString typeName = mTypeMap.localType(baseName); const QString inputTypeName = mTypeMap.localInputType(baseName, QName()); // include header newClass.addIncludes(QStringList(), mTypeMap.forwardDeclarations(baseName)); newClass.addHeaderIncludes(mTypeMap.headerIncludes(baseName)); if (mTypeMap.isComplexType(baseName)) { newClass.addBaseClass(typeName); } else { const QString variableName = generateMemberVariable("value", typeName, inputTypeName, newClass, XSD::Attribute::Required, false, false); // convenience constructor KODE::Function conctor(upperlize(newClass.name())); conctor.addArgument(inputTypeName + QLatin1String(" value")); conctor.setBody(variableName + QLatin1String(" = value;")); // type operator KODE::Function op(QLatin1String("operator ") + typeName); op.setBody(QLatin1String("return ") + variableName + QLatin1Char(';')); op.setConst(true); newClass.addFunction(conctor); newClass.addFunction(op); } } } if (!type->documentation().isEmpty()) { newClass.setDocs(type->documentation().simplified()); } QVector<QString> seenElements; // elements in the complex type const XSD::Element::List elements = type->elements(); Q_FOREACH (const XSD::Element &elemIt, elements) { if (elemIt.type().isEmpty()) { qDebug() << "ERROR: Element from" << *type << "with no type:" << elemIt << "(skipping)"; Q_ASSERT(false); continue; } // When having <choice> // <sequence>A,B(opt)</sequence> // B // <sequence>C,B(opt)</sequence> // </choice> // we don't want to emit setB() three times, that's not valid C++ // (testcase in wsdl_document.wsdl TestRepeatedChildren) if (seenElements.contains(elemIt.name())) { continue; } seenElements.append(elemIt.name()); QString typeName = mTypeMap.localType(elemIt.type()); Q_ASSERT(!typeName.isEmpty()); if (typeName != QLatin1String("void")) { // void means empty element, probably just here for later extensions (testcase: SetPasswordResult in salesforce) QString inputTypeName = mTypeMap.localInputType(elemIt.type(), QName()); bool isList = false; if (elemIt.maxOccurs() > 1 || elemIt.compositor().maxOccurs() > 1) { QString itemType = mTypeMap.isPolymorphic(elemIt.type()) ? pointerStorageType(typeName) : typeName; typeName = listTypeFor(itemType, newClass); inputTypeName = QLatin1String("const ") + typeName + QLatin1String("&"); isList = true; } if (type->isArray()) { QString arrayTypeName = mTypeMap.localType(type->arrayType()); Q_ASSERT(!arrayTypeName.isEmpty()); if (mTypeMap.isPolymorphic(type->arrayType())) { arrayTypeName = pointerStorageType(arrayTypeName); } //qDebug() << "array of" << attribute.arrayType() << "->" << arrayTypeName; typeName = listTypeFor(arrayTypeName, newClass); if (!mTypeMap.isBasicType(type->arrayType())) { newClass.addInclude(QString(), arrayTypeName); // add forward declaration } newClass.addHeaderIncludes(QStringList() << QLatin1String("QtCore/QList")); inputTypeName = QLatin1String("const ") + typeName + QLatin1Char('&'); isList = true; } XSD::Attribute::AttributeUse use = isElementOptional(elemIt) ? XSD::Attribute::Optional : XSD::Attribute::Required; const bool polymorphic = isElementPolymorphic(elemIt, mTypeMap, isList); const bool usePointer = usePointerForElement(elemIt, newClass, mTypeMap, isList); generateMemberVariable(KODE::Style::makeIdentifier(elemIt.name()), typeName, inputTypeName, newClass, use, usePointer, polymorphic); } // include header newClass.addIncludes(QStringList(), mTypeMap.forwardDeclarations(elemIt.type())); newClass.addHeaderIncludes(mTypeMap.headerIncludes(elemIt.type())); if (elemIt.maxOccurs() > 1 || elemIt.compositor().maxOccurs() > 1) { newClass.addHeaderIncludes(QStringList() << QLatin1String("QtCore/QList")); } } // attributes in the complex type XSD::Attribute::List attributes = type->attributes(); Q_FOREACH (const XSD::Attribute &attribute, attributes) { QString typeName, inputTypeName; typeName = mTypeMap.localType(attribute.type()); if (typeName.isEmpty()) { qDebug() << "ERROR: attribute with unknown type:" << attribute.name() << attribute.type() << "in" << typeName; } inputTypeName = mTypeMap.localInputType(attribute.type(), QName()); //qDebug() << "Attribute" << attribute.name(); generateMemberVariable(KODE::Style::makeIdentifier(attribute.name()), typeName, inputTypeName, newClass, attribute.attributeUse(), false, false); // include header newClass.addIncludes(QStringList(), mTypeMap.forwardDeclarations(attribute.type())); newClass.addHeaderIncludes(mTypeMap.headerIncludes(attribute.type())); }