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.
tdesdk/umbrello/umbrello/codegenerators/xmlschemawriter.cpp

810 lines
28 KiB

/***************************************************************************
copyright : (C) 2003 Brian Thomas brian.thomas@gsfc.nasa.gov
(C) 2004-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "xmlschemawriter.h"
#include <kdebug.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <tqfile.h>
#include <tqtextstream.h>
#include <tqregexp.h>
#include "../umldoc.h"
#include "../classifier.h"
#include "../operation.h"
#include "../umlnamespace.h"
// Constructor
XMLSchemaWriter::XMLSchemaWriter()
{
packageNamespaceTag = "tns";
packageNamespaceURI = "http://foo.example.com/";
schemaNamespaceTag = "xs";
schemaNamespaceURI = "http://www.w3.org/2001/XMLSchema";
}
// form of..."the Destructor"!!
XMLSchemaWriter::~XMLSchemaWriter() {
}
/**
* returns "XMLSchema"
*/
Uml::Programming_Language XMLSchemaWriter::getLanguage() {
return Uml::pl_XMLSchema;
}
// main method for invoking..
void XMLSchemaWriter::writeClass(UMLClassifier *c)
{
if (!c) {
kDebug()<<"Cannot write class of NULL classifier!\n";
return;
}
// find an appropriate name for our file
TQString fileName = findFileName(c,".xsd");
if (fileName.isEmpty()) {
emit codeGenerated(c, false);
return;
}
// check that we may open that file for writing
TQFile file;
if ( !openFile(file, fileName) ) {
emit codeGenerated(c, false);
return;
}
TQTextStream XMLschema(&file);
// set package namespace tag appropriately
if(!c->getPackage().isEmpty())
packageNamespaceTag = c->getPackage();
// START WRITING
// 0. FIRST THING: open the xml processing instruction. This MUST be
// the first thing in the file
XMLschema<<"<?xml version=\"1.0\"?>"<<m_endl;
// 1. create the header
TQString headerText = getHeadingFile(".xsd");
if(!headerText.isEmpty()) {
headerText.replace(TQRegExp("%filename%"),fileName);
headerText.replace(TQRegExp("%filepath%"),file.name());
}
if(!headerText.isEmpty())
XMLschema<<headerText<<m_endl;
// 2. Open schema element node with appropriate namespace decl
XMLschema<<"<"<<makeSchemaTag("schema");
// common namespaces we know will be in the file..
XMLschema<<" targetNamespace=\""<<packageNamespaceURI+packageNamespaceTag<<"\""<<m_endl;
XMLschema<<" xmlns:"<<schemaNamespaceTag<<"=\""<<schemaNamespaceURI<<"\"";
XMLschema<<" xmlns:"<<packageNamespaceTag<<"=\""<<packageNamespaceURI+packageNamespaceTag<<"\"";
XMLschema<<">"<<m_endl; // close opening declaration
m_indentLevel++;
// 3? IMPORT statements -- do we need to do anything here? I suppose if
// our document has more than one package, which is possible, we are missing
// the correct import statements. Leave that for later at this time.
/*
//only import classes in a different package as this class
UMLPackageList imports;
findObjectsRelated(c,imports);
for(UMLPackage *con = imports.first(); con ; con = imports.next())
if(con->getPackage() != c->getPackage())
XMLschema<<"import "<<con->getPackage()<<"."<<cleanName(con->getName())<<";"<<m_endl;
*/
// 4. BODY of the schema.
// start the writing by sending this classifier, the "root" for this particular
// schema, to writeClassifier method, which will subsequently call itself on all
// related classifiers and thus populate the schema.
writeClassifier(c, XMLschema);
// 5. What remains is to make the root node declaration
XMLschema<<m_endl;
writeElementDecl(getElementName(c), getElementTypeName(c), XMLschema);
// 6. Finished: now we may close schema decl
m_indentLevel--;
XMLschema<<getIndent()<<"</"<<makeSchemaTag("schema")<<">"<<m_endl; // finished.. close schema node
// bookeeping for code generation
emit codeGenerated(c, true);
// tidy up. no dangling open files please..
file.close();
// need to clear HERE, NOT in the destructor because we want each
// schema that we write to have all related classes.
writtenClassifiers.clear();
}
void XMLSchemaWriter::writeElementDecl( const TQString &elementName, const TQString &elementTypeName, TQTextStream &XMLschema)
{
if(forceDoc())
writeComment(elementName+" is the root element, declared here.", XMLschema);
XMLschema<<getIndent()<<"<"<<makeSchemaTag("element")
<<" name=\""<<elementName<<"\""
<<" type=\""<<makePackageTag(elementTypeName)<<"\""
<<"/>"<<m_endl;
}
void XMLSchemaWriter::writeClassifier (UMLClassifier *c, TQTextStream &XMLschema)
{
// NO doing this 2 or more times.
if(hasBeenWritten(c))
return;
XMLschema<<m_endl;
// write documentation for class, if any, first
if(forceDoc() || !c->getDoc().isEmpty())
writeComment(c->getDoc(),XMLschema);
if(c->getAbstract() || c->isInterface() )
writeAbstractClassifier(c,XMLschema); // if its an interface or abstract class
else
writeConcreteClassifier(c,XMLschema);
}
UMLAttributeList XMLSchemaWriter::findAttributes (UMLClassifier *c)
{
// sort attributes by Scope
UMLAttributeList attribs;
attribs.setAutoDelete(false);
if (!c->isInterface()) {
UMLAttributeList atl = c->getAttributeList();
for(UMLAttribute *at=atl.first(); at ; at=atl.next()) {
switch(at->getVisibility())
{
case Uml::Visibility::Public:
case Uml::Visibility::Protected:
attribs.append(at);
break;
case Uml::Visibility::Private:
// DO NOTHING! no way to print in the schema
break;
default:
break;
}
}
}
return attribs;
}
// We have to do 2 things with abstract classifiers (e.g. abstract classes and interfaces)
// which is to:
// 1) declare it as a complexType so it may be inherited (I can see an option here: to NOT write
// this complexType declaration IF the classifier itself isnt inherited by or is inheriting
// from anything because no other element will use this complexType).
// 2) Create a group so that elements, which obey the abstract class /interface may be placed in
// aggregation with other elements (again, and option here to NOT write the group if no other
// element use the interface in element aggregation)
//
void XMLSchemaWriter::writeAbstractClassifier (UMLClassifier *c, TQTextStream &XMLschema)
{
// preparations
UMLClassifierList subclasses = c->findSubClassConcepts(); // list of what inherits from us
UMLClassifierList superclasses = c->findSuperClassConcepts(); // list of what we inherit from
// write the main declaration
writeConcreteClassifier (c, XMLschema);
writeGroupClassifierDecl (c, subclasses, XMLschema);
markAsWritten(c);
// now go back and make sure all sub-classing nodes are declared
if(subclasses.count() > 0)
{
TQString elementName = getElementName(c);
UMLAttributeList attribs = findAttributes(c);
TQStringList attribGroups = findAttributeGroups(c);
writeAttributeGroupDecl(elementName, attribs, XMLschema);
// now write out inheriting classes, as needed
for(UMLClassifier * classifier = subclasses.first(); classifier; classifier = subclasses.next())
writeClassifier(classifier, XMLschema);
}
// write out any superclasses as needed
for(UMLClassifier *classifier = superclasses.first(); classifier; classifier = superclasses.next())
writeClassifier(classifier, XMLschema);
}
void XMLSchemaWriter::writeGroupClassifierDecl (UMLClassifier *c,
UMLClassifierList subclasses,
TQTextStream &XMLschema)
{
// name of class, subclassing classifiers
TQString elementTypeName = getElementGroupTypeName(c);
// start Writing node but only if it has subclasses? Nah..right now put in empty group
XMLschema<<getIndent()<<"<"<<makeSchemaTag("group")<<" name=\""<<elementTypeName<<"\">"<<m_endl;
m_indentLevel++;
XMLschema<<getIndent()<<"<"<<makeSchemaTag("choice")<<">"<<m_endl;
m_indentLevel++;
for(UMLClassifier *classifier = subclasses.first(); classifier; classifier = subclasses.next()) {
writeAssociationRoleDecl(classifier, "1", XMLschema);
}
m_indentLevel--;
XMLschema<<getIndent()<<"</"<<makeSchemaTag("choice")<<">"<<m_endl;
m_indentLevel--;
// finish node
XMLschema<<getIndent()<<"</"<<makeSchemaTag("group")<<">"<<m_endl;
}
void XMLSchemaWriter::writeComplexTypeClassifierDecl (UMLClassifier *c,
UMLAssociationList associations,
UMLAssociationList aggregations,
UMLAssociationList compositions,
UMLClassifierList superclasses,
TQTextStream &XMLschema)
{
// Preparations
//
// sort attributes by Scope
UMLAttributeList attribs = findAttributes(c);
TQStringList attribGroups = findAttributeGroups(c);
// test for relevant associations
bool hasAssociations = determineIfHasChildNodes(c);
bool hasSuperclass = superclasses.count()> 0;
bool hasAttributes = attribs.count() > 0 || attribGroups.count() > 0;
// START WRITING
// start body of element
TQString elementTypeName = getElementTypeName(c);
XMLschema<<getIndent()<<"<"<<makeSchemaTag("complexType")<<" name=\""<<elementTypeName<<"\"";
if(hasAssociations || hasAttributes || hasSuperclass)
{
XMLschema<<">"<<m_endl;
m_indentLevel++;
if(hasSuperclass)
{
TQString superClassName = getElementTypeName(superclasses.first());
XMLschema<<getIndent()<<"<"<<makeSchemaTag("complexContent")<<">"<<m_endl;
//PROBLEM: we only treat ONE superclass for inheritence.. bah.
m_indentLevel++;
XMLschema<<getIndent()<<"<"<<makeSchemaTag("extension")<<" base=\""<<makePackageTag(superClassName)
<<"\"";
if(hasAssociations || hasAttributes )
XMLschema<<">"<<m_endl;
else
XMLschema<<"/>"<<m_endl;
m_indentLevel++;
}
if(hasAssociations)
{
// Child Elements (from most associations)
//
bool didFirstOne = false;
didFirstOne = writeAssociationDecls(associations, true, didFirstOne, c->getID(), XMLschema);
didFirstOne = writeAssociationDecls(aggregations, false, didFirstOne, c->getID(), XMLschema);
didFirstOne = writeAssociationDecls(compositions, false, didFirstOne, c->getID(), XMLschema);
if (didFirstOne) {
m_indentLevel--;
XMLschema<<getIndent()<<"</"<<makeSchemaTag("sequence")<<">"<<m_endl;
}
}
// ATTRIBUTES
//
if(hasAttributes)
{
writeAttributeDecls(attribs, XMLschema);
for(uint i= 0; i < attribGroups.count(); i++)
XMLschema<<getIndent()<<"<"<<makeSchemaTag("attributeGroup")<<" ref=\""
<<makePackageTag(attribGroups[i])<<"\"/>"<<m_endl;
}
if(hasSuperclass)
{
m_indentLevel--;
if(hasAssociations || hasAttributes )
XMLschema<<getIndent()<<"</"<<makeSchemaTag("extension")<<">"<<m_endl;
m_indentLevel--;
XMLschema<<getIndent()<<"</"<<makeSchemaTag("complexContent")<<">"<<m_endl;
}
// close this element decl
m_indentLevel--;
XMLschema<<getIndent()<<"</"<<makeSchemaTag("complexType")<<">"<<m_endl;
} else
XMLschema<<"/>"<<m_endl; // empty node. just close this element decl
}
void XMLSchemaWriter::writeConcreteClassifier (UMLClassifier *c, TQTextStream &XMLschema)
{
// preparations.. gather information about this classifier
//
UMLClassifierList superclasses = c->findSuperClassConcepts(); // list of what inherits from us
UMLClassifierList subclasses = c->findSubClassConcepts(); // list of what we inherit from
UMLAssociationList aggregations = c->getAggregations();
UMLAssociationList compositions = c->getCompositions();
// BAD! only way to get "general" associations.
UMLAssociationList associations = c->getSpecificAssocs(Uml::at_Association);
// write the main declaration
writeComplexTypeClassifierDecl(c, associations, aggregations, compositions, superclasses, XMLschema);
markAsWritten(c);
// Now write out any child def's
writeChildObjsInAssociation(c, associations, XMLschema);
writeChildObjsInAssociation(c, aggregations, XMLschema);
writeChildObjsInAssociation(c, compositions, XMLschema);
// write out any superclasses as needed
for(UMLClassifier *classifier = superclasses.first(); classifier; classifier = superclasses.next())
writeClassifier(classifier, XMLschema);
// write out any subclasses as needed
for(UMLClassifier *classifier = subclasses.first(); classifier; classifier = subclasses.next())
writeClassifier(classifier, XMLschema);
}
// these exist for abstract classes only (which become xs:group nodes)
TQStringList XMLSchemaWriter::findAttributeGroups (UMLClassifier *c)
{
// we need to look for any class we inherit from. IF these
// have attributes, then we need to notice
TQStringList list;
UMLClassifierList superclasses = c->findSuperClassConcepts(); // list of what inherits from us
for(UMLClassifier *classifier = superclasses.first(); classifier; classifier = superclasses.next())
{
if(classifier->getAbstract())
{
// only classes have attributes..
if (!classifier->isInterface()) {
UMLAttributeList attribs = c->getAttributeList();
if (attribs.count() > 0)
list.append(getElementName(classifier)+"AttribGroupType");
}
}
}
return list;
}
bool XMLSchemaWriter::determineIfHasChildNodes( UMLClassifier *c)
{
UMLObjectList aggList = findChildObjsInAssociations (c, c->getAggregations());
UMLObjectList compList = findChildObjsInAssociations (c, c->getCompositions());
UMLAssociationList associations = c->getSpecificAssocs(Uml::at_Association); // BAD! only way to get "general" associations.
UMLObjectList assocList = findChildObjsInAssociations (c, associations);
return aggList.count() > 0 || compList.count() > 0 || assocList.count() > 0;
}
void XMLSchemaWriter::writeChildObjsInAssociation (UMLClassifier *c,
UMLAssociationList assoc,
TQTextStream &XMLschema)
{
UMLObjectList list = findChildObjsInAssociations (c, assoc);
for(UMLObject * obj = list.first(); obj; obj = list.next())
{
UMLClassifier * thisClassifier = dynamic_cast<UMLClassifier*>(obj);
if(thisClassifier)
writeClassifier(thisClassifier, XMLschema);
}
}
bool XMLSchemaWriter::hasBeenWritten(UMLClassifier *c) {
if (writtenClassifiers.contains(c))
return true;
else
return false;
}
void XMLSchemaWriter::markAsWritten(UMLClassifier *c) {
writtenClassifiers.append(c);
}
void XMLSchemaWriter::writeAttributeDecls(UMLAttributeList &attribs, TQTextStream &XMLschema )
{
UMLAttribute *at;
for(at=attribs.first(); at; at=attribs.next())
{
writeAttributeDecl(at,XMLschema);
}
}
void XMLSchemaWriter::writeAttributeDecl(UMLAttribute *attrib, TQTextStream &XMLschema )
{
TQString documentation = attrib->getDoc();
TQString typeName = fixTypeName(attrib->getTypeName());
bool isStatic = attrib->getStatic();
TQString initialValue = fixInitialStringDeclValue(attrib->getInitialValue(), typeName);
if(!documentation.isEmpty())
writeComment(documentation, XMLschema);
XMLschema<<getIndent()<<"<"<<makeSchemaTag("attribute")
<<" name=\""<<cleanName(attrib->getName())<<"\""
<<" type=\""<<typeName<<"\"";
// default value?
if(!initialValue.isEmpty())
{
// IF its static, then we use "fixed", otherwise, we use "default" decl.
// For the default decl, we _must_ use "optional" decl
if(isStatic)
XMLschema<<" use=\"required\" fixed=\""<<initialValue<<"\"";
else
XMLschema<<" use=\"optional\" default=\""<<initialValue<<"\"";
}
// finish decl
XMLschema<<"/>"<<m_endl;
}
void XMLSchemaWriter::writeAttributeGroupDecl (const TQString &elementName, UMLAttributeList &attribs, TQTextStream &XMLschema )
{
if (attribs.count()> 0) {
// write a little documentation
writeComment("attributes for element "+elementName,XMLschema);
// open attribute group
XMLschema<<getIndent()<<"<"<<makeSchemaTag("attributeGroup")<<" name=\""<<elementName+"AttribGroupType"<<"\">"<<m_endl;
m_indentLevel++;
for( UMLAttribute *at=attribs.first(); at; at=attribs.next())
{
writeAttributeDecl(at,XMLschema);
}
m_indentLevel--;
// close attrib group node
XMLschema<<getIndent()<<"</"<<makeSchemaTag("attributeGroup")<<">"<<m_endl;
}
}
void XMLSchemaWriter::writeComment( const TQString &comment, TQTextStream &XMLschema )
{
// in the case we have several line comment..
// NOTE: this part of the method has the problem of adopting UNIX newline,
// need to resolve for using with MAC/WinDoze eventually I assume
TQString indent = getIndent();
XMLschema<<indent<<"<!-- ";
if (comment.contains(TQRegExp("\n"))) {
XMLschema<<m_endl;
TQStringList lines = TQStringList::split( "\n", comment);
for(uint i= 0; i < lines.count(); i++)
XMLschema<<indent<<" "<<lines[i]<<m_endl;
XMLschema<<indent<<"-->"<<m_endl;
} else {
// this should be more fancy in the future, breaking it up into 80 char
// lines so that it doesn't look too bad
XMLschema<<comment<<" -->"<<m_endl;
}
}
// all that matters here is roleA, the role served by the children of this class
// in any composition or aggregation association. In full associations, I have only
// considered the case of "self" association, so it shouldn't matter if we use role A or
// B to find the child class as long as we don't use BOTH roles. I bet this will fail
// badly for someone using a plain association between 2 different classes. THAT should
// be done, but isnt yet (this is why I have left role b code in for now). -b.t.
bool XMLSchemaWriter::writeAssociationDecls(UMLAssociationList associations,
bool noRoleNameOK, bool didFirstOne, Uml::IDType id, TQTextStream &XMLschema)
{
if( !associations.isEmpty() )
{
bool printRoleA = false, printRoleB = false;
for(UMLAssociation *a = associations.first(); a; a = associations.next())
{
// it may seem counter intuitive, but you want to insert the role of the
// *other* class into *this* class.
if (a->getObjectId(Uml::A) == id && a->getVisibility(Uml::B) != Uml::Visibility::Private)
printRoleB = true;
if (a->getObjectId(Uml::B) == id && a->getVisibility(Uml::A) != Uml::Visibility::Private)
printRoleA = true;
// First: we insert documentaion for association IF it has either role
// AND some documentation (!)
if ((printRoleA || printRoleB) && !(a->getDoc().isEmpty()))
writeComment(a->getDoc(), XMLschema);
// opening for sequence
if(!didFirstOne && (printRoleA || printRoleB))
{
didFirstOne = true;
XMLschema<<getIndent()<<"<"<<makeSchemaTag("sequence")<<">"<<m_endl;
m_indentLevel++;
}
// print RoleB decl
/*
// As mentioned in the header comment for this method: this block of code is
// commented out for now as it will only be needed if/when plain associations
// between different classes are to be treated
if (printRoleB)
{
UMLClassifier *classifierB = dynamic_cast<UMLClassifier*>(a->getObjectB());
if (classifierB) {
// ONLY write out IF there is a rolename given
// otherwise its not meant to be declared
if (!a->getRoleNameB().isEmpty() || noRoleNameOK)
writeAssociationRoleDecl(classifierB, a->getMultiB(), XMLschema);
}
}
*/
// print RoleA decl
if (printRoleA)
{
UMLClassifier *classifierA = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A));
if (classifierA) {
// ONLY write out IF there is a rolename given
// otherwise its not meant to be declared
if (!a->getRoleName(Uml::A).isEmpty() || noRoleNameOK )
writeAssociationRoleDecl(classifierA, a->getMulti(Uml::A), XMLschema);
}
}
}
}
return didFirstOne;
}
UMLObjectList XMLSchemaWriter::findChildObjsInAssociations (UMLClassifier *c, UMLAssociationList associations)
{
Uml::IDType id = c->getID();
UMLObjectList list;
for(UMLAssociation *a = associations.first(); a; a = associations.next())
{
if (a->getObjectId(Uml::A) == id
&& a->getVisibility(Uml::B) != Uml::Visibility::Private
&& !a->getRoleName(Uml::B).isEmpty()
)
list.append(a->getObject(Uml::B));
if (a->getObjectId(Uml::B) == id
&& a->getVisibility(Uml::A) != Uml::Visibility::Private
&& !a->getRoleName(Uml::A).isEmpty()
)
list.append(a->getObject(Uml::A));
}
return list;
}
void XMLSchemaWriter::writeAssociationRoleDecl( UMLClassifier *c, const TQString &multi, TQTextStream &XMLschema)
{
bool isAbstract = c->getAbstract();
bool isInterface = c->isInterface();
TQString elementName = getElementName(c);
TQString doc = c->getDoc();
if (!doc.isEmpty())
writeComment(doc, XMLschema);
// Min/Max Occurs is based on whether it is this a single element
// or a List (maxoccurs>1). One day this will be done correctly with special
// multiplicity object that we don't have to figure out what it means via regex.
TQString minOccurs = "0";
TQString maxOccurs = "unbounded";
if (multi.isEmpty())
{
// in this case, association will only specify ONE element can exist
// as a child
minOccurs = "1";
maxOccurs = "1";
}
else
{
TQStringList values = TQStringList::split( TQRegExp("[^\\d{1,}|\\*]"), multi);
// could use some improvement here.. for sequences like "0..1,3..5,10" we
// don't capture the whole "richness" of the multi. Instead we translate it
// now to minOccurs="0" maxOccurs="10"
if (values.count() > 0)
{
// populate both with the actual value as long as our value isnt an asterix
// In that case, use special value (from above)
if(values[0].contains(TQRegExp("\\d{1,}")))
minOccurs = values[0]; // use first number in sequence
if(values[values.count()-1].contains(TQRegExp("\\d{1,}")))
maxOccurs = values[values.count()-1]; // use only last number in sequence
}
}
// Now declare the class in the association as an element or group.
//
// In a semi-arbitrary way, we have decided to make abstract classes into
// "groups" and concrete classes into "complexTypes".
//
// This is because about the only thing you can do with an abstract
// class (err. node) is inherit from it with a "concrete" element. Therefore,
// in this manner, we need a group node for abstract classes to lay out the child
// element choices so that the child, concrete class may be plugged into whatever spot
// it parent could go. The tradeoff is that "group" nodes may not be extended, so the
// choices that you lay out here are it (e.g. no more nodes may inherit" from this group)
//
// The flipside for concrete classes is that we want to use them as elements in our document.
// Unfortunately, about all you can do with complexTypes in terms of inheritance, is to
// use these as the basis for a new node type. This is NOT full inheritence because the new
// class (err. element node) wont be able to go into the document where it parent went without
// you heavily editing the schema.
//
// Therefore, IF a group is abstract, but has no inheriting sub-classes, there are no choices, and its nigh
// on pointless to declare it as a group, in this special case, abstract classes get declared
// as complexTypes.
//
// Of course, in OO methodology, you should be able to inherit from
// any class, but schema just don't allow use to have full inheritence using either groups
// or complexTypes. Thus we have taken a middle rode. If someone wants to key me into a
// better way to represent this, I'd be happy to listen. =b.t.
//
// UPDATE: partial solution to the above: as of 13-Mar-2003 we now write BOTH a complexType
// AND a group declaration for interfaces AND classes which are inherited from.
//
if ((isAbstract || isInterface ) && c->findSubClassConcepts().count() > 0)
XMLschema<<getIndent()<<"<"<<makeSchemaTag("group")
<<" ref=\""<<makePackageTag(getElementGroupTypeName(c))<<"\"";
else
XMLschema<<getIndent()<<"<"<<makeSchemaTag("element")
<<" name=\""<<getElementName(c)<<"\""
<<" type=\""<<makePackageTag(getElementTypeName(c))<<"\"";
// min/max occurs
if (minOccurs != "1")
XMLschema<<" minOccurs=\""<<minOccurs<<"\"";
if (maxOccurs != "1")
XMLschema<<" maxOccurs=\""<<maxOccurs<<"\"";
// tidy up the node
XMLschema<<"/>"<<m_endl;
}
// IF the type is "string" we need to declare it as
// the XMLSchema Object "String" (there is no string primative in XMLSchema).
// Same thing again for "bool" to "boolean"
TQString XMLSchemaWriter::fixTypeName(const TQString& string)
{
// string.replace(TQRegExp("^string$"),schemaNamespaceTag+":string");
// string.replace(TQRegExp("^bool$"),schemaNamespaceTag+":boolean");
return schemaNamespaceTag + ':' + string;
}
TQString XMLSchemaWriter::fixInitialStringDeclValue(TQString value, const TQString &type)
{
// check for strings only
if (!value.isEmpty() && type == "xs:string") {
if (!value.startsWith("\""))
value.remove(0,1);
if (!value.endsWith("\""))
value.remove(value.length(),1);
}
return value;
}
TQString XMLSchemaWriter::getElementName(UMLClassifier *c)
{
return cleanName(c->getName());
}
TQString XMLSchemaWriter::getElementTypeName(UMLClassifier *c)
{
TQString elementName = getElementName(c);
return elementName + "ComplexType";
}
TQString XMLSchemaWriter::getElementGroupTypeName(UMLClassifier *c)
{
TQString elementName = getElementName(c);
return elementName + "GroupType";
}
TQString XMLSchemaWriter::makePackageTag (TQString tagName) {
tagName.prepend( packageNamespaceTag + ':');
return tagName;
}
TQString XMLSchemaWriter::makeSchemaTag (TQString tagName) {
tagName.prepend( schemaNamespaceTag + ':');
return tagName;
}
const TQStringList XMLSchemaWriter::reservedKeywords() const {
static TQStringList keywords;
if (keywords.isEmpty()) {
keywords << "ATTLIST"
<< "CDATA"
<< "DOCTYPE"
<< "ELEMENT"
<< "ENTITIES"
<< "ENTITY"
<< "ID"
<< "IDREF"
<< "IDREFS"
<< "NMTOKEN"
<< "NMTOKENS"
<< "NOTATION"
<< "PUBLIC"
<< "SHORTREF"
<< "SYSTEM"
<< "USEMAP";
}
return keywords;
}
#include "xmlschemawriter.moc"