umbrello API Documentation

umlcanvasobject.cpp

00001 /***************************************************************************
00002  *                                                                         *
00003  *   This program is free software; you can redistribute it and/or modify  *
00004  *   it under the terms of the GNU General Public License as published by  *
00005  *   the Free Software Foundation; either version 2 of the License, or     *
00006  *   (at your option) any later version.                                   *
00007  *                                                                         *
00008  *   copyright (C) 2003-2007                                               *
00009  *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
00010  ***************************************************************************/
00011 
00012 // own header
00013 #include "umlcanvasobject.h"
00014 
00015 // qt/kde includes
00016 #include <kdebug.h>
00017 #include <klocale.h>
00018 
00019 // local includes
00020 #include "uml.h"
00021 #include "umldoc.h"
00022 #include "classifier.h"
00023 #include "association.h"
00024 #include "attribute.h"
00025 #include "operation.h"
00026 #include "template.h"
00027 #include "stereotype.h"
00028 #include "clipboard/idchangelog.h"
00029 
00030 UMLCanvasObject::UMLCanvasObject(const QString & name, Uml::IDType id)
00031         : UMLObject(name, id)
00032 {
00033     init();
00034 }
00035 
00036 UMLCanvasObject::~UMLCanvasObject() {
00037     //removeAllAssociations();
00038     /* No! This is way too late to do that.
00039       It should have been called explicitly before destructing the
00040       UMLCanvasObject.
00041       Here is an example crash that happens if we rely on
00042       removeAllAssociations() at this point:
00043 #4  0x415aac7f in __dynamic_cast () from /usr/lib/libstdc++.so.5
00044 #5  0x081acdbd in UMLCanvasObject::removeAllAssociations() (this=0x89e5b08)
00045     at umlcanvasobject.cpp:83
00046 #6  0x081ac9fa in ~UMLCanvasObject (this=0x89e5b08) at umlcanvasobject.cpp:29
00047 #7  0x08193ffc in ~UMLPackage (this=0x89e5b08) at package.cpp:35
00048 #8  0x0813cbf6 in ~UMLClassifier (this=0x89e5b08) at classifier.cpp:40
00049 #9  0x081af3a6 in UMLDoc::closeDocument() (this=0x8468b10) at umldoc.cpp:284
00050      */
00051     if (associations())
00052         kDebug() << "UMLCanvasObject destructor: FIXME: there are still associations()" << endl;
00053 }
00054 
00055 UMLAssociationList UMLCanvasObject::getSpecificAssocs(Uml::Association_Type assocType) {
00056     UMLAssociationList list;
00057     UMLObject *o;
00058     for (UMLObjectListIt oit(m_List); (o = oit.current()) != NULL; ++oit) {
00059         if (o->getBaseType() != Uml::ot_Association)
00060             continue;
00061         UMLAssociation *a = static_cast<UMLAssociation*>(o);
00062         if (a->getAssocType() == assocType)
00063             list.append(a);
00064     }
00065     return list;
00066 }
00067 
00068 bool UMLCanvasObject::addAssociationEnd(UMLAssociation* assoc) {
00069     // add association only if not already present in list
00070     if(!hasAssociation(assoc))
00071     {
00072         m_List.append( assoc );
00073 
00074         // Don't emit signals during load from XMI
00075         UMLObject::emitModified();
00076         emit sigAssociationEndAdded(assoc);
00077         return true;
00078     }
00079     return false;
00080 }
00081 
00082 bool UMLCanvasObject::hasAssociation(UMLAssociation* assoc) {
00083     if(m_List.containsRef(assoc) > 0)
00084         return true;
00085     return false;
00086 }
00087 
00088 int UMLCanvasObject::removeAssociationEnd(UMLAssociation * assoc) {
00089     if(!hasAssociation(assoc) || !m_List.remove(assoc)) {
00090         kWarning() << "UMLCanvasObject::removeAssociation: "
00091             << "can't find given assoc in list" << endl;
00092         return -1;
00093     }
00094     UMLObject::emitModified();
00095     emit sigAssociationEndRemoved(assoc);
00096     return m_List.count();
00097 }
00098 
00099 void UMLCanvasObject::removeAllAssociationEnds() {
00100     UMLObject *o;
00101     for (UMLObjectListIt oit(m_List); (o = oit.current()) != NULL; ) {
00102         if (o->getBaseType() != Uml::ot_Association) {
00103             ++oit;
00104             continue;
00105         }
00106         UMLAssociation *assoc = static_cast<UMLAssociation*>(o);
00107         //umldoc->slotRemoveUMLObject(assoc);
00108         UMLObject* objA = assoc->getObject(Uml::A);
00109         UMLObject* objB = assoc->getObject(Uml::B);
00110         UMLCanvasObject *roleAObj = dynamic_cast<UMLCanvasObject*>(objA);
00111         if (roleAObj) {
00112             roleAObj->removeAssociationEnd(assoc);
00113         } else if (objA)
00114             kDebug() << "UMLCanvasObject::removeAllAssociations(" << m_Name
00115                 << "): objA " << objA->getName() << " is not a UMLCanvasObject"
00116                 << endl;
00117         else
00118             kDebug() << "UMLCanvasObject::removeAllAssociations(" << m_Name
00119                 << "): objA is NULL" << endl;
00120         UMLCanvasObject *roleBObj = dynamic_cast<UMLCanvasObject*>(objB);
00121         if (roleBObj) {
00122             roleBObj->removeAssociationEnd(assoc);
00123         } else if (objB)
00124             kDebug() << "UMLCanvasObject::removeAllAssociations(" << m_Name
00125                 << "): objB " << objB->getName() << " is not a UMLCanvasObject"
00126                 << endl;
00127         else
00128             kDebug() << "UMLCanvasObject::removeAllAssociations(" << m_Name
00129                 << "): objB is NULL" << endl;
00130         m_List.remove(assoc);
00131     }
00132 }
00133 
00134 void UMLCanvasObject::removeAllChildObjects() {
00135     removeAllAssociationEnds();
00136     m_List.setAutoDelete(true);
00137     m_List.clear();
00138     m_List.setAutoDelete(false);
00139 }
00140 
00141 QString UMLCanvasObject::uniqChildName( const Uml::Object_Type type,
00142                                         const QString &prefix /* = QString() */ ) {
00143     QString currentName = prefix;
00144     if (currentName.isEmpty()) {
00145         switch (type) {
00146             case Uml::ot_Association:
00147                 currentName = i18n("new_association");
00148                 break;
00149             case Uml::ot_Attribute:
00150                 currentName = i18n("new_attribute");
00151                 break;
00152             case Uml::ot_Template:
00153                 currentName = i18n("new_template");
00154                 break;
00155             case Uml::ot_Operation:
00156                 currentName = i18n("new_operation");
00157                 break;
00158             case Uml::ot_EnumLiteral:
00159                 currentName = i18n("new_literal");
00160                 break;
00161             case Uml::ot_EntityAttribute:
00162                 currentName = i18n("new_field");
00163                 break;
00164             default:
00165                 kWarning() << "uniqChildName() called for unknown child type " << type << endl;
00166                 return "ERROR_in_UMLCanvasObject_uniqChildName";
00167         }
00168     }
00169 
00170     QString name = currentName;
00171     for (int number = 1; findChildObject(name); ++number) {
00172         name = currentName + '_' + QString::number(number);
00173     }
00174     return name;
00175 }
00176 
00177 UMLObject * UMLCanvasObject::findChildObject(const QString &n, Uml::Object_Type t) {
00178     const bool caseSensitive = UMLApp::app()->activeLanguageIsCaseSensitive();
00179     UMLObject *obj;
00180     for (UMLObjectListIt oit(m_List); (obj = oit.current()) != NULL; ++oit) {
00181         if (t != Uml::ot_UMLObject && obj->getBaseType() != t)
00182             continue;
00183         if (caseSensitive) {
00184             if (obj->getName() == n)
00185                 return obj;
00186         } else if (obj->getName().lower() == n.lower()) {
00187             return obj;
00188         }
00189     }
00190     return NULL;
00191 }
00192 
00193 UMLObject* UMLCanvasObject::findChildObjectById(Uml::IDType id, bool /* considerAncestors */) {
00194     UMLObject *o;
00195     for (UMLObjectListIt oit(m_List); (o = oit.current()) != NULL; ++oit) {
00196         if (o->getID() == id)
00197             return o;
00198     }
00199     return 0;
00200 }
00201 
00202 void UMLCanvasObject::init() {
00203     m_List.setAutoDelete(false);
00204 }
00205 
00206 bool UMLCanvasObject::operator==(UMLCanvasObject& rhs) {
00207     if (this == &rhs) {
00208         return true;
00209     }
00210     if ( !UMLObject::operator==(rhs) ) {
00211         return false;
00212     }
00213     if ( m_List.count() != rhs.m_List.count() ) {
00214         return false;
00215     }
00216     if ( &m_List != &(rhs.m_List) ) {
00217         return false;
00218     }
00219     return true;
00220 }
00221 
00222 void UMLCanvasObject::copyInto(UMLCanvasObject *rhs) const
00223 {
00224     UMLObject::copyInto(rhs);
00225 
00226     // TODO Associations are not copied at the moment. This because
00227     // the duplicate function (on umlwidgets) do not copy the associations.
00228     //
00229     //rhs->m_List = m_List;
00230 }
00231 
00232 int UMLCanvasObject::associations() {
00233     int count = 0;
00234     UMLObject *obj;
00235     for (UMLObjectListIt oit(m_List); (obj = oit.current()) != NULL; ++oit) {
00236         if (obj->getBaseType() == Uml::ot_Association)
00237             count++;
00238     }
00239     return count;
00240 }
00241 
00242 UMLAssociationList UMLCanvasObject::getAssociations() {
00243     UMLAssociationList assocs;
00244     UMLObject *o;
00245     for (UMLObjectListIt oit(m_List); (o = oit.current()) != NULL; ++oit) {
00246         if (o->getBaseType() != Uml::ot_Association)
00247             continue;
00248         UMLAssociation *assoc = static_cast<UMLAssociation*>(o);
00249         assocs.append(assoc);
00250     }
00251     return assocs;
00252 }
00253 
00254 UMLClassifierList UMLCanvasObject::getSuperClasses() {
00255     UMLClassifierList list;
00256     UMLAssociationList assocs = getAssociations();
00257     for (UMLAssociation* a = assocs.first(); a; a = assocs.next()) {
00258         if ((a->getAssocType() != Uml::at_Generalization &&
00259              a->getAssocType() != Uml::at_Realization) ||
00260                 a->getObjectId(Uml::A) != getID() )
00261             continue;
00262         UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::B));
00263         if (c)
00264             list.append(c);
00265         else
00266             kDebug() << "UMLCanvasObject::getSuperClasses(" << m_Name
00267             << "): generalization's other end is not a "
00268             << "UMLClassifier (id= " << ID2STR(a->getObjectId(Uml::B)) << ")"
00269             << endl;
00270     }
00271     return list;
00272 }
00273 
00274 UMLClassifierList UMLCanvasObject::getSubClasses() {
00275     UMLClassifierList list;
00276     UMLAssociationList assocs = getAssociations();
00277     for (UMLAssociation* a = assocs.first(); a; a = assocs.next()) {
00278         if ((a->getAssocType() != Uml::at_Generalization &&
00279              a->getAssocType() != Uml::at_Realization) ||
00280                 a->getObjectId(Uml::B) != getID() )
00281             continue;
00282         UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A));
00283         if (c)
00284             list.append(c);
00285         else
00286             kDebug() << "UMLCanvasObject::getSubClasses: specialization's"
00287             << " other end is not a UMLClassifier"
00288             << " (id=" << ID2STR(a->getObjectId(Uml::A)) << ")" << endl;
00289     }
00290     return list;
00291 }
00292 
00293 UMLAssociationList UMLCanvasObject::getRealizations() {
00294     return getSpecificAssocs(Uml::at_Realization);
00295 }
00296 
00297 UMLAssociationList UMLCanvasObject::getAggregations() {
00298     return getSpecificAssocs(Uml::at_Aggregation);
00299 }
00300 
00301 UMLAssociationList UMLCanvasObject::getCompositions() {
00302     return getSpecificAssocs(Uml::at_Composition);
00303 }
00304 
00305 UMLAssociationList UMLCanvasObject::getRelationships() {
00306     return getSpecificAssocs(Uml::at_Relationship);
00307 }
00308 
00309 bool UMLCanvasObject::resolveRef() {
00310     bool overallSuccess = UMLObject::resolveRef();
00311     for (UMLObjectListIt ait(m_List); ait.current(); ++ait) {
00312         UMLObject *obj = ait.current();
00313         if (! obj->resolveRef()) {
00314             m_List.remove(obj);
00315             overallSuccess = false;
00316         }
00317     }
00318     return overallSuccess;
00319 }
00320 
00321 #include "umlcanvasobject.moc"
00322 
KDE Logo
This file is part of the documentation for umbrello Version 3.1.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Jun 26 08:08:00 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003