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.
754 lines
26 KiB
754 lines
26 KiB
/***************************************************************************
|
|
* *
|
|
* 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 <tqregexp.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 TQString &name, Uml::IDType id)
|
|
: TQObject(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 TQString &name, Uml::IDType id)
|
|
: TQObject(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)
|
|
: TQObject(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((TQWidget*)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 TQString &strName) {
|
|
m_Name = strName;
|
|
emitModified();
|
|
}
|
|
|
|
TQString UMLObject::getName() const {
|
|
return m_Name;
|
|
}
|
|
|
|
TQString UMLObject::getFullyQualifiedName(const TQString& separator,
|
|
bool includeRoot /* = false */) const {
|
|
TQString 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) {
|
|
TQString 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 TQObject 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 TQString &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;
|
|
}
|
|
|
|
TQString 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 TQString &_name) {
|
|
if (_name.isEmpty()) {
|
|
setUMLStereotype(NULL);
|
|
return;
|
|
}
|
|
UMLDoc *pDoc = UMLApp::app()->getDocument();
|
|
UMLStereotype *s = pDoc->findOrCreateStereotype(_name);
|
|
setUMLStereotype(s);
|
|
}
|
|
|
|
void UMLObject::setPackage(const TQString &_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;
|
|
}
|
|
|
|
TQString UMLObject::getStereotype(bool includeAdornments /* = false */) const {
|
|
if (m_pStereotype == NULL)
|
|
return "";
|
|
TQString name = m_pStereotype->getName();
|
|
if (includeAdornments)
|
|
name = TQString::fromUtf8("«") + name + TQString::fromUtf8("»");
|
|
return name;
|
|
}
|
|
|
|
TQString UMLObject::getPackage(const TQString& separator, bool includeRoot) {
|
|
TQString tempSeparator = separator;
|
|
if (tempSeparator.isEmpty())
|
|
tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
|
|
TQString fqn = getFullyQualifiedName(tempSeparator, includeRoot);
|
|
if (!fqn.contains(tempSeparator))
|
|
return "";
|
|
TQString 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;
|
|
}
|
|
|
|
TQString UMLObject::getSecondaryId() const {
|
|
return m_SecondaryId;
|
|
}
|
|
|
|
void UMLObject::setSecondaryId(const TQString& id) {
|
|
m_SecondaryId = id;
|
|
}
|
|
|
|
TQString UMLObject::getSecondaryFallback() const {
|
|
return m_SecondaryFallback;
|
|
}
|
|
|
|
void UMLObject::setSecondaryFallback(const TQString& 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;
|
|
}
|
|
|
|
TQDomElement UMLObject::save( const TQString &tag, TQDomDocument & qDoc ) {
|
|
/*
|
|
Call as the first action of saveToXMI() in child class:
|
|
This creates the TQDomElement with which to work.
|
|
*/
|
|
TQDomElement 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
|
|
TQString 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( TQDomElement& ) {
|
|
// This body is not usually executed because child classes
|
|
// overwrite the load method.
|
|
return true;
|
|
}
|
|
|
|
bool UMLObject::loadStereotype(TQDomElement & element) {
|
|
TQString tag = element.tagName();
|
|
if (!Uml::tagEq(tag, "stereotype"))
|
|
return false;
|
|
TQString stereo = element.attribute("xmi.value", "");
|
|
if (stereo.isEmpty() && element.hasChildNodes()) {
|
|
/* like so:
|
|
<UML:ModelElement.stereotype>
|
|
<UML:Stereotype xmi.idref = '07CD'/>
|
|
</UML:ModelElement.stereotype>
|
|
*/
|
|
TQDomNode stereoNode = element.firstChild();
|
|
TQDomElement 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( TQDomElement & 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", "" );
|
|
TQString 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.
|
|
TQString 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 {
|
|
TQString 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;
|
|
}
|
|
|
|
TQString 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.
|
|
TQString abstract = element.attribute( "abstract", "0" );
|
|
m_bAbstract = (bool)abstract.toInt();
|
|
} else {
|
|
TQString isAbstract = element.attribute( "isAbstract", "false" );
|
|
m_bAbstract = (isAbstract == "true");
|
|
}
|
|
|
|
if( element.hasAttribute("static") ) { // for bkwd compat.
|
|
TQString staticScope = element.attribute( "static", "0" );
|
|
m_bStatic = (bool)staticScope.toInt();
|
|
} else {
|
|
TQString 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()) {
|
|
TQDomNode node = element.firstChild();
|
|
if (node.isComment())
|
|
node = node.nextSibling();
|
|
TQDomElement elem = node.toElement();
|
|
while( !elem.isNull() ) {
|
|
TQString 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")) {
|
|
TQString 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")) {
|
|
TQString isAbstract = elem.attribute("xmi.value", "");
|
|
if (isAbstract.isEmpty())
|
|
isAbstract = elem.text();
|
|
m_bAbstract = (isAbstract == "true");
|
|
} else if (Uml::tagEq(tag, "ownerScope")) {
|
|
TQString 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"
|