summaryrefslogtreecommitdiffstats
path: root/umbrello/umbrello/umlobject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'umbrello/umbrello/umlobject.cpp')
-rw-r--r--umbrello/umbrello/umlobject.cpp753
1 files changed, 753 insertions, 0 deletions
diff --git a/umbrello/umbrello/umlobject.cpp b/umbrello/umbrello/umlobject.cpp
new file mode 100644
index 00000000..e28ed7da
--- /dev/null
+++ b/umbrello/umbrello/umlobject.cpp
@@ -0,0 +1,753 @@
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ * copyright (C) 2002-2006 *
+ * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
+ ***************************************************************************/
+
+// own header
+#include "umlobject.h"
+// qt/kde includes
+#include <qregexp.h>
+#include <kdebug.h>
+#include <kapplication.h>
+// app includes
+#include "uniqueid.h"
+#include "uml.h"
+#include "umldoc.h"
+#include "umllistview.h"
+#include "umllistviewitem.h"
+#include "package.h"
+#include "folder.h"
+#include "stereotype.h"
+#include "object_factory.h"
+#include "model_utils.h"
+#include "codeimport/import_utils.h"
+#include "docwindow.h"
+#include "dialogs/classpropdlg.h"
+
+UMLObject::UMLObject(const UMLObject * parent, const QString &name, Uml::IDType id)
+ : QObject(const_cast<UMLObject*>(parent), "UMLObject" ) {
+ init();
+ if (id == Uml::id_None)
+ m_nId = UniqueID::gen();
+ else
+ m_nId = id;
+ m_Name = name;
+}
+
+UMLObject::UMLObject(const QString &name, Uml::IDType id)
+ : QObject(UMLApp::app()->getDocument()) {
+ init();
+ if (id == Uml::id_None)
+ m_nId = UniqueID::gen();
+ else
+ m_nId = id;
+ m_Name = name;
+}
+
+UMLObject::UMLObject(const UMLObject * parent)
+ : QObject(const_cast<UMLObject*>(parent)) {
+ init();
+}
+
+UMLObject::~UMLObject() {
+}
+
+void UMLObject::init() {
+ m_BaseType = Uml::ot_UMLObject;
+ m_nId = Uml::id_None;
+ m_pUMLPackage = NULL;
+ m_Name = "";
+ m_Vis = Uml::Visibility::Public;
+ m_pStereotype = NULL;
+ m_Doc = "";
+ m_bAbstract = false;
+ m_bStatic = false;
+ m_bInPaste = false;
+ m_bCreationWasSignalled = false;
+ m_pSecondary = NULL;
+}
+
+bool UMLObject::showProperties(int page, bool assoc) {
+ DocWindow *docwindow = UMLApp::app()->getDocWindow();
+ docwindow->updateDocumentation(false);
+ ClassPropDlg* dlg = new ClassPropDlg((QWidget*)UMLApp::app(), this, page, assoc);
+ bool modified = false;
+ if (dlg->exec()) {
+ docwindow->showDocumentation(this, true);
+ UMLApp::app()->getDocument()->setModified(true);
+ modified = true;
+ }
+ dlg->close(true); //wipe from memory
+ return modified;
+}
+
+bool UMLObject::acceptAssociationType(Uml::Association_Type)
+{// A UMLObject accepts nothing. This should be reimplemented by the subclasses
+ return false;
+}
+
+void UMLObject::setID(Uml::IDType NewID) {
+ m_nId = NewID;
+ emitModified();
+}
+
+void UMLObject::setName(const QString &strName) {
+ m_Name = strName;
+ emitModified();
+}
+
+QString UMLObject::getName() const {
+ return m_Name;
+}
+
+QString UMLObject::getFullyQualifiedName(const QString& separator,
+ bool includeRoot /* = false */) const {
+ QString fqn;
+ if (m_pUMLPackage) {
+ bool skipPackage = false;
+ if (!includeRoot) {
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ if (umldoc->rootFolderType(m_pUMLPackage) != Uml::N_MODELTYPES ||
+ m_pUMLPackage == umldoc->getDatatypeFolder())
+ skipPackage = true;
+ }
+ if (!skipPackage) {
+ QString tempSeparator = separator;
+ if (tempSeparator.isEmpty())
+ tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
+ fqn = m_pUMLPackage->getFullyQualifiedName(tempSeparator, includeRoot);
+ fqn.append(tempSeparator);
+ }
+ }
+ fqn.append(m_Name);
+ return fqn;
+}
+
+bool UMLObject::operator==(UMLObject & rhs ) {
+ if( this == &rhs )
+ return true;
+
+ //don't compare IDs, these are program specific and
+ //don't mean the objects are the same
+ //***** CHECK: Who put in this comment? What was the reason?
+ //***** Currently some operator== in umbrello compare the IDs
+ //***** while others don't.
+
+ if( m_Name != rhs.m_Name )
+ return false;
+
+ // Packages create different namespaces, therefore they should be
+ // part of the equality test.
+ if( m_pUMLPackage != rhs.m_pUMLPackage )
+ return false;
+
+ // Making the type part of an object's identity has its problems:
+ // Not all programming languages support declarations of the same
+ // name but different type.
+ // In such cases, the code generator is responsible for generating
+ // the appropriate error message.
+ if( m_BaseType != rhs.m_BaseType )
+ return false;
+
+ // The documentation should not be part of the equality test.
+ // If two objects are the same but differ only in their documentation,
+ // what does that mean?
+ //if( m_Doc != rhs.m_Doc )
+ // return false;
+
+ // The scope should not be part of the equality test.
+ // What does it mean if two objects are the same but differ in their
+ // scope? - I'm not aware of any programming language that would
+ // support that.
+ //if( m_Vis != rhs.m_Vis )
+ // return false;
+
+ // See comments above
+ //if( m_pStereotype != rhs.m_pStereotype )
+ // return false;
+
+ // See comments above
+ //if( m_bAbstract != rhs.m_bAbstract )
+ // return false;
+
+ // See comments above
+ //if( m_bStatic != rhs.m_bStatic )
+ // return false;
+
+ return true;
+}
+
+void UMLObject::copyInto(UMLObject *rhs) const
+{
+ // Data members with copy constructor
+ rhs->m_Doc = m_Doc;
+ rhs->m_pStereotype = m_pStereotype;
+ rhs->m_bAbstract = m_bAbstract;
+ rhs->m_bStatic = m_bStatic;
+ rhs->m_BaseType = m_BaseType;
+ rhs->m_Vis = m_Vis;
+ rhs->m_pUMLPackage = m_pUMLPackage;
+
+ // We don't want the same name existing twice.
+ rhs->m_Name = Model_Utils::uniqObjectName(m_BaseType, m_pUMLPackage, m_Name);
+
+ // Create a new ID.
+ rhs->m_nId = UniqueID::gen();
+
+ // Hope that the parent from QObject is okay.
+ if (rhs->parent() != parent())
+ kDebug() << "copyInto has a wrong parent" << endl;
+}
+
+
+bool UMLObject::getAbstract() const{
+ return m_bAbstract;
+}
+
+void UMLObject::setAbstract(bool bAbstract) {
+ m_bAbstract = bAbstract;
+ emitModified();
+}
+
+void UMLObject::setInPaste(bool bInPaste /* =true */) {
+ m_bInPaste = bInPaste;
+}
+
+/** Returns true if this UMLObject has classifier scope, otherwise false (the default). */
+bool UMLObject::getStatic() const
+{
+ return m_bStatic;
+}
+/** Sets the value for m_bStatic. */
+void UMLObject::setStatic(bool bStatic)
+{
+ m_bStatic = bStatic;
+ emitModified();
+}
+
+void UMLObject::emitModified()
+{
+ UMLDoc *umldoc = UMLApp::app()->getDocument();
+ if (! umldoc->loading())
+ emit modified();
+}
+
+void UMLObject::setDoc(const QString &d) {
+ m_Doc = d;
+ //emit modified(); No, this is done centrally at DocWindow::updateDocumentation()
+}
+
+Uml::Object_Type UMLObject::getBaseType() const {
+ return m_BaseType;
+}
+
+void UMLObject::setBaseType(Uml::Object_Type ot) {
+ m_BaseType = ot;
+}
+
+Uml::IDType UMLObject::getID() const {
+ return m_nId;
+}
+
+QString UMLObject::getDoc() const {
+ return m_Doc;
+}
+
+Uml::Visibility UMLObject::getVisibility() const {
+ return m_Vis;
+}
+
+void UMLObject::setVisibility(Uml::Visibility s) {
+ m_Vis = s;
+ emitModified();
+}
+
+void UMLObject::setUMLStereotype(UMLStereotype *stereo) {
+ if (stereo == m_pStereotype)
+ return;
+ if (stereo) {
+ stereo->incrRefCount();
+ }
+ if (m_pStereotype) {
+ m_pStereotype->decrRefCount();
+ if (m_pStereotype->refCount() == 0) {
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ pDoc->removeStereotype(m_pStereotype);
+ delete m_pStereotype;
+ }
+ }
+ m_pStereotype = stereo;
+ // TODO: don't emit modified() if predefined folder
+ emitModified();
+}
+
+void UMLObject::setStereotype(const QString &_name) {
+ if (_name.isEmpty()) {
+ setUMLStereotype(NULL);
+ return;
+ }
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ UMLStereotype *s = pDoc->findOrCreateStereotype(_name);
+ setUMLStereotype(s);
+}
+
+void UMLObject::setPackage(const QString &_name) {
+ UMLObject *pkgObj = NULL;
+ if (!_name.isEmpty()) {
+ UMLDoc* umldoc = UMLApp::app()->getDocument();
+ pkgObj = umldoc->findUMLObject(_name);
+ if (pkgObj == NULL) {
+ kDebug() << "UMLObject::setPackage: creating UMLPackage "
+ << _name << " for " << m_Name << endl;
+ pkgObj = Import_Utils::createUMLObject(Uml::ot_Package, _name);
+ } else {
+ const Uml::Object_Type ot = pkgObj->getBaseType();
+ if (ot != Uml::ot_Package && ot != Uml::ot_Folder && ot != Uml::ot_Component) {
+ kError() << "UMLObject::setPackage(" << m_Name << "): "
+ << "existing " << _name << " is not a container" << endl;
+ // This should not happen - if it does, there may be further problems.
+ // A container name should not overlap with another name in the same scope.
+ pkgObj = Import_Utils::createUMLObject(Uml::ot_Package, _name);
+ }
+ }
+ }
+ setUMLPackage( static_cast<UMLPackage *>(pkgObj) );
+}
+
+void UMLObject::setUMLPackage(UMLPackage* pPkg) {
+ m_pUMLPackage = pPkg;
+ emitModified();
+}
+
+const UMLStereotype * UMLObject::getUMLStereotype() {
+ return m_pStereotype;
+}
+
+QString UMLObject::getStereotype(bool includeAdornments /* = false */) const {
+ if (m_pStereotype == NULL)
+ return "";
+ QString name = m_pStereotype->getName();
+ if (includeAdornments)
+ name = QString::fromUtf8("«") + name + QString::fromUtf8("»");
+ return name;
+}
+
+QString UMLObject::getPackage(const QString& separator, bool includeRoot) {
+ QString tempSeparator = separator;
+ if (tempSeparator.isEmpty())
+ tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
+ QString fqn = getFullyQualifiedName(tempSeparator, includeRoot);
+ if (!fqn.contains(tempSeparator))
+ return "";
+ QString scope = fqn.left(fqn.length() - tempSeparator.length() - m_Name.length());
+ return scope;
+}
+
+UMLPackageList UMLObject::getPackages(bool includeRoot) const {
+ UMLPackageList pkgList;
+ UMLPackage* pkg = m_pUMLPackage;
+ while (pkg != NULL) {
+ pkgList.prepend(pkg);
+ pkg = pkg->getUMLPackage();
+ }
+ if (!includeRoot)
+ pkgList.removeFirst();
+ return pkgList;
+}
+
+UMLPackage* UMLObject::getUMLPackage() {
+ return m_pUMLPackage;
+}
+
+QString UMLObject::getSecondaryId() const {
+ return m_SecondaryId;
+}
+
+void UMLObject::setSecondaryId(const QString& id) {
+ m_SecondaryId = id;
+}
+
+QString UMLObject::getSecondaryFallback() const {
+ return m_SecondaryFallback;
+}
+
+void UMLObject::setSecondaryFallback(const QString& id) {
+ m_SecondaryFallback = id;
+}
+
+void UMLObject::maybeSignalObjectCreated() {
+ if (!m_bCreationWasSignalled &&
+ m_BaseType != Uml::ot_Stereotype &&
+ m_BaseType != Uml::ot_Association &&
+ m_BaseType != Uml::ot_Role) {
+ m_bCreationWasSignalled = true;
+ UMLDoc* umldoc = UMLApp::app()->getDocument();
+ umldoc->signalUMLObjectCreated(this);
+ }
+}
+
+bool UMLObject::resolveRef() {
+ if (m_pSecondary || (m_SecondaryId.isEmpty() && m_SecondaryFallback.isEmpty())) {
+ maybeSignalObjectCreated();
+ return true;
+ }
+#ifdef VERBOSE_DEBUGGING
+ kDebug() << "UMLObject::resolveRef(" << m_Name << "): m_SecondaryId is "
+ << m_SecondaryId << endl;
+#endif
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ // In the new, XMI standard compliant save format,
+ // the type is the xmi.id of a UMLClassifier.
+ if (! m_SecondaryId.isEmpty()) {
+ m_pSecondary = pDoc->findObjectById(STR2ID(m_SecondaryId));
+ if (m_pSecondary != NULL) {
+ if (m_pSecondary->getBaseType() == Uml::ot_Stereotype) {
+ m_pStereotype = static_cast<UMLStereotype*>(m_pSecondary);
+ m_pStereotype->incrRefCount();
+ m_pSecondary = NULL;
+ }
+ m_SecondaryId = "";
+ maybeSignalObjectCreated();
+ return true;
+ }
+ if (m_SecondaryFallback.isEmpty()) {
+ kDebug() << "UMLObject::resolveRef: object with xmi.id=" << m_SecondaryId
+ << " not found, setting to undef" << endl;
+ UMLFolder *datatypes = pDoc->getDatatypeFolder();
+ m_pSecondary = Object_Factory::createUMLObject(Uml::ot_Datatype, "undef", datatypes, false);
+ return true;
+ }
+ }
+ if (m_SecondaryFallback.isEmpty()) {
+ kError() << "UMLObject::resolveRef(" << m_Name
+ << "): cannot find type with id "
+ << m_SecondaryId << endl;
+ return false;
+ }
+#ifdef VERBOSE_DEBUGGING
+ kDebug() << "UMLObject::resolveRef(" << m_Name
+ << "): could not resolve secondary ID " << m_SecondaryId
+ << ", using secondary fallback " << m_SecondaryFallback
+ << endl;
+#endif
+ m_SecondaryId = m_SecondaryFallback;
+ // Assume we're dealing with the older Umbrello format where
+ // the type name was saved in the "type" attribute rather
+ // than the xmi.id of the model object of the attribute type.
+ m_pSecondary = pDoc->findUMLObject( m_SecondaryId, Uml::ot_UMLObject, this );
+ if (m_pSecondary) {
+ m_SecondaryId = "";
+ maybeSignalObjectCreated();
+ return true;
+ }
+ // Work around Object_Factory::createUMLObject()'s incapability
+ // of on-the-fly scope creation:
+ if (m_SecondaryId.contains("::")) {
+ // TODO: Merge Import_Utils::createUMLObject() into Object_Factory::createUMLObject()
+ m_pSecondary = Import_Utils::createUMLObject(Uml::ot_UMLObject, m_SecondaryId, m_pUMLPackage);
+ if (m_pSecondary) {
+ if (Import_Utils::newUMLObjectWasCreated()) {
+ maybeSignalObjectCreated();
+ kapp->processEvents();
+ kDebug() << "UMLObject::resolveRef: Import_Utils::createUMLObject() "
+ << "created a new type for " << m_SecondaryId << endl;
+ } else {
+ kDebug() << "UMLObject::resolveRef: Import_Utils::createUMLObject() "
+ << "returned an existing type for " << m_SecondaryId << endl;
+ }
+ m_SecondaryId = "";
+ return true;
+ }
+ kError() << "UMLObject::resolveRef: Import_Utils::createUMLObject() "
+ << "failed to create a new type for " << m_SecondaryId << endl;
+ return false;
+ }
+ kDebug() << "UMLObject::resolveRef: Creating new type for " << m_SecondaryId << endl;
+ // This is very C++ specific - we rely on some '*' or
+ // '&' to decide it's a ref type. Plus, we don't recognize
+ // typedefs of ref types.
+ bool isReferenceType = ( m_SecondaryId.contains('*') ||
+ m_SecondaryId.contains('&') );
+ Uml::Object_Type ot = Uml::ot_Class;
+ if (isReferenceType) {
+ ot = Uml::ot_Datatype;
+ } else {
+ if (Model_Utils::isCommonDataType(m_SecondaryId))
+ ot = Uml::ot_Datatype;
+ }
+ m_pSecondary = Object_Factory::createUMLObject(ot, m_SecondaryId, NULL);
+ if (m_pSecondary == NULL)
+ return false;
+ m_SecondaryId = "";
+ maybeSignalObjectCreated();
+ //kapp->processEvents();
+ return true;
+}
+
+QDomElement UMLObject::save( const QString &tag, QDomDocument & qDoc ) {
+ /*
+ Call as the first action of saveToXMI() in child class:
+ This creates the QDomElement with which to work.
+ */
+ QDomElement qElement = qDoc.createElement(tag);
+ qElement.setAttribute( "isSpecification", "false" );
+ if (m_BaseType != Uml::ot_Association &&
+ m_BaseType != Uml::ot_Role &&
+ m_BaseType != Uml::ot_Attribute) {
+ qElement.setAttribute( "isLeaf", "false" );
+ qElement.setAttribute( "isRoot", "false" );
+ if (m_bAbstract)
+ qElement.setAttribute( "isAbstract", "true" );
+ else
+ qElement.setAttribute( "isAbstract", "false" );
+ }
+ qElement.setAttribute( "xmi.id", ID2STR(m_nId) );
+ qElement.setAttribute( "name", m_Name );
+ if (m_BaseType != Uml::ot_Operation &&
+ m_BaseType != Uml::ot_Role &&
+ m_BaseType != Uml::ot_Attribute) {
+ Uml::IDType nmSpc;
+ if (m_pUMLPackage)
+ nmSpc = m_pUMLPackage->getID();
+ else
+ nmSpc = UMLApp::app()->getDocument()->getModelID();
+ qElement.setAttribute( "namespace", ID2STR(nmSpc) );
+ }
+ if (! m_Doc.isEmpty())
+ qElement.setAttribute( "comment", m_Doc ); //CHECK: uml13.dtd compliance
+#ifdef XMI_FLAT_PACKAGES
+ if (m_pUMLPackage) //FIXME: uml13.dtd compliance
+ qElement.setAttribute( "package", m_pUMLPackage->getID() );
+#endif
+ QString visibility = m_Vis.toString(false);
+ qElement.setAttribute( "visibility", visibility);
+ if (m_pStereotype != NULL)
+ qElement.setAttribute( "stereotype", ID2STR(m_pStereotype->getID()) );
+ if (m_bStatic)
+ qElement.setAttribute( "ownerScope", "classifier" );
+ /* else
+ qElement.setAttribute( "ownerScope", "instance" );
+ *** ownerScope defaults to instance if not set **********/
+ return qElement;
+}
+
+bool UMLObject::load( QDomElement& ) {
+ // This body is not usually executed because child classes
+ // overwrite the load method.
+ return true;
+}
+
+bool UMLObject::loadStereotype(QDomElement & element) {
+ QString tag = element.tagName();
+ if (!Uml::tagEq(tag, "stereotype"))
+ return false;
+ QString stereo = element.attribute("xmi.value", "");
+ if (stereo.isEmpty() && element.hasChildNodes()) {
+ /* like so:
+ <UML:ModelElement.stereotype>
+ <UML:Stereotype xmi.idref = '07CD'/>
+ </UML:ModelElement.stereotype>
+ */
+ QDomNode stereoNode = element.firstChild();
+ QDomElement stereoElem = stereoNode.toElement();
+ tag = stereoElem.tagName();
+ if (Uml::tagEq(tag, "Stereotype")) {
+ stereo = stereoElem.attribute("xmi.idref", "");
+ }
+ }
+ if (stereo.isEmpty())
+ return false;
+ Uml::IDType stereoID = STR2ID(stereo);
+ UMLDoc *pDoc = UMLApp::app()->getDocument();
+ m_pStereotype = pDoc->findStereotypeById(stereoID);
+ if (m_pStereotype)
+ m_pStereotype->incrRefCount();
+ else
+ m_SecondaryId = stereo; // leave it to resolveRef()
+ return true;
+}
+
+bool UMLObject::loadFromXMI( QDomElement & element) {
+ UMLDoc* umldoc = UMLApp::app()->getDocument();
+ if (umldoc == NULL) {
+ kError() << "UMLObject::loadFromXMI: umldoc is NULL" << endl;
+ return false;
+ }
+ // Read the name first so that if we encounter a problem, the error
+ // message can say the name.
+ m_Name = element.attribute( "name", "" );
+ QString id = element.attribute( "xmi.id", "" );
+ if (id.isEmpty() || id == "-1") {
+ if (m_BaseType == Uml::ot_Role) {
+ // Before version 1.4, Umbrello did not save the xmi.id
+ // of UMLRole objects.
+ m_nId = UniqueID::gen();
+ } else {
+ kError() << "UMLObject::loadFromXMI(" << m_Name
+ << "): nonexistent or illegal xmi.id" << endl;
+ return false;
+ }
+ } else {
+ m_nId = STR2ID(id);
+ if (m_BaseType == Uml::ot_Role) {
+ // Some older Umbrello versions had a problem with xmi.id's
+ // of other objects being reused for the UMLRole, see e.g.
+ // attachment 21179 at http://bugs.kde.org/147988 .
+ // If the xmi.id is already being used then we generate a new one.
+ UMLObject *o = umldoc->findObjectById(m_nId);
+ if (o) {
+ kDebug() << "loadFromXMI(UMLRole): id " << id
+ << " is already in use, generating a new one." << endl;
+ m_nId = UniqueID::gen();
+ }
+ }
+ }
+
+ if (element.hasAttribute("documentation")) // for bkwd compat.
+ m_Doc = element.attribute( "documentation", "" );
+ else
+ m_Doc = element.attribute( "comment", "" ); //CHECK: need a UML:Comment?
+
+ m_Vis = Uml::Visibility::Public;
+ if (element.hasAttribute("scope")) { // for bkwd compat.
+ QString scope = element.attribute( "scope", "" );
+ if (scope == "instance_level") // nsuml compat.
+ m_bStatic = false;
+ else if (scope == "classifier_level") // nsuml compat.
+ m_bStatic = true;
+ else {
+ int nScope = scope.toInt();
+ if (nScope >= Uml::Visibility::Public && nScope <= Uml::Visibility::Protected)
+ m_Vis = (Uml::Visibility::Value)nScope;
+ else
+ kError() << "UMLObject::loadFromXMI(" << m_Name
+ << "): illegal scope" << endl; // soft error
+ }
+ } else {
+ QString visibility = element.attribute( "visibility", "public" );
+ if (visibility == "private"
+ || visibility == "private_vis") // for compatibility with other programs
+ m_Vis = Uml::Visibility::Private;
+ else if (visibility == "protected"
+ || visibility == "protected_vis") // for compatibility with other programs
+ m_Vis = Uml::Visibility::Protected;
+ else if (visibility == "implementation")
+ m_Vis = Uml::Visibility::Implementation;
+ }
+
+ QString stereo = element.attribute( "stereotype", "" );
+ if (!stereo.isEmpty()) {
+ Uml::IDType stereoID = STR2ID(stereo);
+ m_pStereotype = umldoc->findStereotypeById(stereoID);
+ if (m_pStereotype) {
+ m_pStereotype->incrRefCount();
+ } else {
+ kDebug() << "UMLObject::loadFromXMI(" << m_Name << "): "
+ << "UMLStereotype " << ID2STR(stereoID)
+ << " not found, creating now." << endl;
+ setStereotype(stereo);
+ }
+ }
+
+ if( element.hasAttribute("abstract") ) { // for bkwd compat.
+ QString abstract = element.attribute( "abstract", "0" );
+ m_bAbstract = (bool)abstract.toInt();
+ } else {
+ QString isAbstract = element.attribute( "isAbstract", "false" );
+ m_bAbstract = (isAbstract == "true");
+ }
+
+ if( element.hasAttribute("static") ) { // for bkwd compat.
+ QString staticScope = element.attribute( "static", "0" );
+ m_bStatic = (bool)staticScope.toInt();
+ } else {
+ QString ownerScope = element.attribute( "ownerScope", "instance" );
+ m_bStatic = (ownerScope == "classifier");
+ }
+
+ // If the node has child nodes, check whether attributes can be
+ // extracted from them.
+ if (element.hasChildNodes()) {
+ QDomNode node = element.firstChild();
+ if (node.isComment())
+ node = node.nextSibling();
+ QDomElement elem = node.toElement();
+ while( !elem.isNull() ) {
+ QString tag = elem.tagName();
+ if (Uml::tagEq(tag, "name")) {
+ m_Name = elem.attribute("xmi.value", "");
+ if (m_Name.isEmpty())
+ m_Name = elem.text();
+ } else if (Uml::tagEq(tag, "visibility")) {
+ QString vis = elem.attribute("xmi.value", "");
+ if (vis.isEmpty())
+ vis = elem.text();
+ if (vis == "private" || vis == "private_vis")
+ m_Vis = Uml::Visibility::Private;
+ else if (vis == "protected" || vis == "protected_vis")
+ m_Vis = Uml::Visibility::Protected;
+ else if (vis == "implementation")
+ m_Vis = Uml::Visibility::Implementation;
+ } else if (Uml::tagEq(tag, "isAbstract")) {
+ QString isAbstract = elem.attribute("xmi.value", "");
+ if (isAbstract.isEmpty())
+ isAbstract = elem.text();
+ m_bAbstract = (isAbstract == "true");
+ } else if (Uml::tagEq(tag, "ownerScope")) {
+ QString ownerScope = elem.attribute("xmi.value", "");
+ if (ownerScope.isEmpty())
+ ownerScope = elem.text();
+ m_bStatic = (ownerScope == "classifier");
+ } else {
+ loadStereotype(elem);
+ }
+ node = node.nextSibling();
+ if (node.isComment())
+ node = node.nextSibling();
+ elem = node.toElement();
+ }
+ }
+
+ // Operations, attributes, enum literals, templates, stereotypes,
+ // and association role objects get added and signaled elsewhere.
+ if (m_BaseType != Uml::ot_Operation && m_BaseType != Uml::ot_Attribute &&
+ m_BaseType != Uml::ot_EnumLiteral && m_BaseType != Uml::ot_EntityAttribute &&
+ m_BaseType != Uml::ot_Template && m_BaseType != Uml::ot_Stereotype &&
+ m_BaseType != Uml::ot_Role) {
+ if (m_bInPaste) {
+ m_pUMLPackage = NULL; // forget any old parent
+ UMLListView *listView = UMLApp::app()->getListView();
+ UMLListViewItem *parentItem = (UMLListViewItem*)listView->currentItem();
+ if (parentItem) {
+ Uml::ListView_Type lvt = parentItem->getType();
+ if (Model_Utils::typeIsContainer(lvt) ||
+ lvt == Uml::lvt_Class ||
+ lvt == Uml::lvt_Interface) {
+ UMLObject *o = parentItem->getUMLObject();
+ m_pUMLPackage = static_cast<UMLPackage*>( o );
+ }
+ }
+ }
+ if (m_pUMLPackage) {
+ m_pUMLPackage->addObject(this);
+ } else if (umldoc->rootFolderType(this) == Uml::N_MODELTYPES) {
+ // m_pUMLPackage is not set on the root folders.
+ kDebug() << "UMLObject::loadFromXMI(" << m_Name << "): m_pUMLPackage is not set"
+ << endl;
+ }
+ }
+ return load(element);
+}
+
+kdbgstream& operator<< (kdbgstream& s, const UMLObject& a) {
+ s << a.getName();
+ return s;
+}
+
+#include "umlobject.moc"