1 /*
2     SPDX-License-Identifier: GPL-2.0-or-later
3     SPDX-FileCopyrightText: 2002-2021 Umbrello UML Modeller Authors <umbrello-devel@kde.org>
4 */
5 
6 // own header
7 #include "umlobject.h"
8 
9 // app includes
10 #include "classpropertiesdialog.h"
11 #include "debug_utils.h"
12 #include "enumliteral.h"
13 #include "uniqueid.h"
14 #include "uml.h"
15 #include "umldoc.h"
16 #include "umllistview.h"
17 #include "umlobjectprivate.h"
18 #include "models/objectsmodel.h"
19 #include "package.h"
20 #include "folder.h"
21 #include "stereotype.h"
22 #include "object_factory.h"
23 #include "model_utils.h"
24 #include "import_utils.h"
25 #include "docwindow.h"
26 #include "cmds.h"
27 
28 // kde includes
29 #include <KLocalizedString>
30 
31 // qt includes
32 #include <QApplication>
33 #include <QPointer>
34 
35 using namespace Uml;
36 
DEBUG_REGISTER_DISABLED(UMLObject)37 DEBUG_REGISTER_DISABLED(UMLObject)
38 
39 /**
40  * Creates a UMLObject.
41  * @param other object to created from
42  */
43 UMLObject::UMLObject(const UMLObject &other)
44   : QObject(other.umlParent()),
45     m_d(new UMLObjectPrivate)
46 {
47     other.copyInto(this);
48     UMLApp::app()->document()->objectsModel()->add(this);
49 }
50 
51 /**
52  * Creates a UMLObject.
53  * @param parent   The parent of the object.
54  * @param name     The name of the object.
55  * @param id       The ID of the object (optional.) If omitted
56  *                 then a new ID will be assigned internally.
57  */
UMLObject(UMLObject * parent,const QString & name,ID::Type id)58 UMLObject::UMLObject(UMLObject* parent, const QString& name, ID::Type id)
59   : QObject(parent),
60     m_nId(id),
61     m_name(name),
62     m_d(new UMLObjectPrivate)
63 {
64     init();
65     if (id == Uml::ID::None)
66         m_nId = UniqueID::gen();
67     UMLApp::app()->document()->objectsModel()->add(this);
68 }
69 
70 /**
71  * Creates a UMLObject.
72  * @param name     The name of the object.
73  * @param id       The ID of the object (optional.) If omitted
74  *                 then a new ID will be assigned internally.
75  */
UMLObject(const QString & name,ID::Type id)76 UMLObject::UMLObject(const QString& name, ID::Type id)
77   : QObject(0),
78     m_nId(id),
79     m_name(name),
80     m_d(new UMLObjectPrivate)
81 {
82     init();
83     if (id == Uml::ID::None)
84         m_nId = UniqueID::gen();
85     UMLApp::app()->document()->objectsModel()->add(this);
86 }
87 
88 /**
89  * Creates a UMLObject.
90  * @param   parent   The parent of the object.
91  */
UMLObject(UMLObject * parent)92 UMLObject::UMLObject(UMLObject * parent)
93   : QObject(parent),
94     m_nId(Uml::ID::None),
95     m_name(QString()),
96     m_d(new UMLObjectPrivate)
97 {
98     init();
99     UMLApp::app()->document()->objectsModel()->add(this);
100 }
101 
102 /**
103  * Standard destructor.
104  */
~UMLObject()105 UMLObject::~UMLObject()
106 {
107     // unref stereotype
108     setUMLStereotype(0);
109     if (m_pSecondary && m_pSecondary->baseType() == ot_Stereotype) {
110         UMLStereotype* stereotype = m_pSecondary->asUMLStereotype();
111         if (stereotype)
112             stereotype->decrRefCount();
113     }
114     UMLApp::app()->document()->objectsModel()->remove(this);
115     delete m_d;
116 }
117 
118 /**
119  * Initializes key variables of the class.
120  */
init()121 void UMLObject::init()
122 {
123     setObjectName(QLatin1String("UMLObject"));
124     m_BaseType = ot_UMLObject;
125     m_visibility = Uml::Visibility::Public;
126     m_pStereotype = 0;
127     m_Doc.clear();
128     m_bAbstract = false;
129     m_bStatic = false;
130     m_bCreationWasSignalled = false;
131     m_pSecondary = 0;
132 }
133 
134 /**
135  * Display the properties configuration dialog for the object.
136  *
137  * @param parent    The parent widget.
138  * @return  True for success of this operation.
139  */
showPropertiesDialog(QWidget * parent)140 bool UMLObject::showPropertiesDialog(QWidget *parent)
141 {
142     DocWindow *docwindow = UMLApp::app()->docWindow();
143     docwindow->updateDocumentation(false);
144     QPointer<ClassPropertiesDialog> dlg = new ClassPropertiesDialog(parent, this, false);
145     bool modified = false;
146     if (dlg->exec()) {
147         docwindow->showDocumentation(this, true);
148         UMLApp::app()->document()->setModified(true);
149         modified = true;
150     }
151     dlg->close();
152     delete dlg;
153     return modified;
154 }
155 
156 /**
157  * This should be reimplemented by subclasses if they wish to
158  * accept certain types of associations. Note that this only
159  * tells if this UMLObject can accept the association
160  * type. When creating an association another check is made to
161  * see if the association is valid. For example a UMLClass
162  * (UMLClassifier) can accept generalizations and should
163  * return true. If while creating a generalization the
164  * superclass is already subclassed from this, the association
165  * is not valid and will not be created.  The default accepts
166  * nothing (returns false)
167  */
acceptAssociationType(Uml::AssociationType::Enum type) const168 bool UMLObject::acceptAssociationType(Uml::AssociationType::Enum type) const
169 {
170     Q_UNUSED(type);
171     // A UMLObject accepts nothing. This should be reimplemented by the subclasses
172     return false;
173 }
174 
175 /**
176  * Assigns a new Id to the object
177  */
setID(ID::Type NewID)178 void UMLObject::setID(ID::Type NewID)
179 {
180     m_nId = NewID;
181     emitModified();
182 }
183 
184 /**
185  * Set the UMLObject's name
186  */
setName(const QString & strName)187 void UMLObject::setName(const QString &strName)
188 {
189     if (name() != strName) {
190         UMLApp::app()->executeCommand(new Uml::CmdRenameUMLObject(this, strName));
191     }
192 }
193 
194 /**
195  * Method used by setName: it is called by  cmdSetName, Don't use it!
196  */
setNameCmd(const QString & strName)197 void UMLObject::setNameCmd(const QString &strName)
198 {
199     m_name = strName;
200     emitModified();
201 }
202 
203 /**
204  * Returns a copy of m_name
205  */
name() const206 QString UMLObject::name() const
207 {
208     return m_name;
209 }
210 
211 /**
212  * Returns the fully qualified name, i.e. all package prefixes and then m_name.
213  *
214  * @param separator  The separator string to use (optional.)
215  *                   If not given then the separator is chosen according
216  *                   to the currently selected active programming language
217  *                   of import and code generation.
218  * @param includeRoot  Whether to prefix the root folder name to the FQN.
219  *                     See UMLDoc::getRootFolder(). Default: false.
220  * @return  The fully qualified name of this UMLObject.
221  */
fullyQualifiedName(const QString & separator,bool includeRoot) const222 QString UMLObject::fullyQualifiedName(const QString& separator,
223         bool includeRoot /* = false */) const
224 {
225     QString fqn;
226     UMLPackage *parent = umlPackage();
227     if (parent && parent != this) {
228         bool skipPackage = false;
229         if (!includeRoot) {
230             UMLDoc *umldoc = UMLApp::app()->document();
231             if ((umldoc->rootFolderType(parent) != Uml::ModelType::N_MODELTYPES) ||
232                     (parent == umldoc->datatypeFolder()))
233                 skipPackage = true;
234         }
235         if (!skipPackage) {
236             QString tempSeparator = separator;
237             if (tempSeparator.isEmpty())
238                 tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
239             fqn = parent->fullyQualifiedName(tempSeparator, includeRoot);
240             fqn.append(tempSeparator);
241         }
242     }
243     fqn.append(m_name);
244     return fqn;
245 }
246 
247 /**
248  * Overloaded '==' operator
249  */
operator ==(const UMLObject & rhs) const250 bool UMLObject::operator==(const UMLObject & rhs) const
251 {
252     if (this == &rhs)
253         return true;
254 
255     //don't compare IDs, these are program specific and
256     //don't mean the objects are the same
257     //***** CHECK: Who put in this comment? What was the reason?
258     //***** Currently some operator== in umbrello compare the IDs
259     //***** while others don't.
260 
261     if (m_name != rhs.m_name)
262         return false;
263 
264     // Packages create different namespaces, therefore they should be
265     // part of the equality test.
266     if (umlParent() != rhs.umlParent())
267         return false;
268 
269     // Making the type part of an object's identity has its problems:
270     // Not all programming languages support declarations of the same
271     // name but different type.
272     // In such cases, the code generator is responsible for generating
273     // the appropriate error message.
274     if (m_BaseType != rhs.m_BaseType)
275         return false;
276 
277     // The documentation should not be part of the equality test.
278     // If two objects are the same but differ only in their documentation,
279     // what does that mean?
280     //if(m_Doc != rhs.m_Doc)
281     //  return false;
282 
283     // The visibility should not be part of the equality test.
284     // What does it mean if two objects are the same but differ in their
285     // visibility? - I'm not aware of any programming language that would
286     // support that.
287     //if(m_visibility != rhs.m_visibility)
288     //  return false;
289 
290     // See comments above
291     //if(m_pStereotype != rhs.m_pStereotype)
292     //  return false;
293 
294     // See comments above
295     //if(m_bAbstract != rhs.m_bAbstract)
296     //  return false;
297 
298     // See comments above
299     //if(m_bStatic != rhs.m_bStatic)
300     //  return false;
301 
302     return true;
303 }
304 
305 /**
306  * Copy the internal presentation of this object into the new
307  * object.
308  */
copyInto(UMLObject * lhs) const309 void UMLObject::copyInto(UMLObject *lhs) const
310 {
311     // Data members with copy constructor
312     lhs->m_Doc = m_Doc;
313     lhs->m_pStereotype = m_pStereotype;
314     if (lhs->m_pStereotype)
315         lhs->m_pStereotype->incrRefCount();
316     lhs->m_bAbstract = m_bAbstract;
317     lhs->m_bStatic = m_bStatic;
318     lhs->m_BaseType = m_BaseType;
319     lhs->m_visibility = m_visibility;
320     lhs->setUMLParent(umlParent());
321 
322     // We don't want the same name existing twice.
323     lhs->m_name = Model_Utils::uniqObjectName(m_BaseType, umlPackage(), m_name);
324 
325     // Create a new ID.
326     lhs->m_nId = UniqueID::gen();
327 
328     // Hope that the parent from QObject is okay.
329     if (lhs->umlParent() != umlParent())
330         uDebug() << "copyInto has a wrong parent";
331 }
332 
clone() const333 UMLObject *UMLObject::clone() const
334 {
335     UMLObject *clone = new UMLObject;
336     UMLObject::copyInto(clone);
337     return clone;
338 }
339 
340 /**
341  * Returns the abstract state of the object.
342  */
isAbstract() const343 bool UMLObject::isAbstract() const
344 {
345     return m_bAbstract;
346 }
347 
348 /**
349  * Sets the paste state of the object.
350  */
setAbstract(bool bAbstract)351 void UMLObject::setAbstract(bool bAbstract)
352 {
353     m_bAbstract = bAbstract;
354     emitModified();
355 }
356 
357 /**
358  * Returns true if this UMLObject has classifier scope,
359  * otherwise false (the default).
360  */
isStatic() const361 bool UMLObject::isStatic() const
362 {
363     return m_bStatic;
364 }
365 
366 /**
367  * Sets the value for m_bStatic.
368  */
setStatic(bool bStatic)369 void UMLObject::setStatic(bool bStatic)
370 {
371     m_bStatic = bStatic;
372     emitModified();
373 }
374 
375 /**
376  * Forces the emission of the modified signal.  Useful when
377  * updating several attributes at a time: you can block the
378  * signals, update all atts, and then force the signal.
379  */
emitModified()380 void UMLObject::emitModified()
381 {
382     UMLDoc *umldoc = UMLApp::app()->document();
383     if (!umldoc->loading() && !umldoc->closing())
384         emit modified();
385 }
386 
387 /**
388  * Returns the type of the object.
389  *
390  * @return  Returns the type of the object.
391  */
baseType() const392 UMLObject::ObjectType UMLObject::baseType() const
393 {
394     return m_BaseType;
395 }
396 
397 /**
398  * @return The type used for rtti as string.
399  */
baseTypeStr() const400 QLatin1String UMLObject::baseTypeStr() const
401 {
402     return QLatin1String(ENUM_NAME(UMLObject, ObjectType, m_BaseType));
403 }
404 
405 /**
406  * Set the type of the object.
407  *
408  * @param ot The ObjectType to set.
409  */
setBaseType(ObjectType ot)410 void UMLObject::setBaseType(ObjectType ot)
411 {
412     m_BaseType = ot;
413 }
414 
415 /**
416  * Returns the ID of the object.
417  *
418  * @return  Returns the ID of the object.
419  */
id() const420 ID::Type UMLObject::id() const
421 {
422     return m_nId;
423 }
424 
425 /**
426  * Returns the documentation for the object.
427  *
428  * @return  Returns the documentation for the object.
429  */
doc() const430 QString UMLObject::doc() const
431 {
432     return m_Doc;
433 }
434 
435 /**
436  * Returns state of documentation for the object.
437  *
438  * @return false if documentation is empty
439  */
hasDoc() const440 bool UMLObject::hasDoc() const
441 {
442     return !m_Doc.isEmpty();
443 }
444 
445 /**
446  * Sets the documentation for the object.
447  *
448  * @param d The documentation for the object.
449  */
setDoc(const QString & d)450 void UMLObject::setDoc(const QString &d)
451 {
452     m_Doc = d;
453     //emit modified();  No, this is done centrally at DocWindow::updateDocumentation()
454 }
455 
456 /**
457  * Returns the visibility of the object.
458  *
459  * @return  Returns the visibility of the object.
460  */
visibility() const461 Visibility::Enum UMLObject::visibility() const
462 {
463     return m_visibility;
464 }
465 
466 /**
467  * Sets the visibility of the object.
468  *
469  * @param visibility  The visibility of the object.
470  */
setVisibility(Visibility::Enum visibility)471 void UMLObject::setVisibility(Visibility::Enum visibility)
472 {
473     if (m_visibility != visibility) {
474         UMLApp::app()->executeCommand(new CmdSetVisibility(this, visibility));
475     }
476 }
477 
478 /**
479  * Method used by setVisibility: it is called by  cmdSetVisibility, Don't use it!
480  */
setVisibilityCmd(Visibility::Enum visibility)481 void UMLObject::setVisibilityCmd(Visibility::Enum visibility)
482 {
483     m_visibility = visibility;
484     emitModified();
485 }
486 
487 /**
488  * Sets the class' UMLStereotype. Adjusts the reference counts
489  * at the previously set stereotype and at the new stereotype.
490  * If the previously set UMLStereotype's reference count drops
491  * to zero then the UMLStereotype is removed at the UMLDoc and
492  * it is then physically deleted.
493  *
494  * @param stereo Sets the classes UMLStereotype.
495  */
setUMLStereotype(UMLStereotype * stereo)496 void UMLObject::setUMLStereotype(UMLStereotype *stereo)
497 {
498     if (stereo == m_pStereotype)
499         return;
500     if (stereo) {
501         stereo->incrRefCount();
502     }
503     if (m_pStereotype) {
504         m_pStereotype->decrRefCount();
505         if (m_pStereotype->refCount() == 0) {
506             UMLDoc *pDoc = UMLApp::app()->document();
507             pDoc->removeStereotype(m_pStereotype);
508             delete m_pStereotype;
509         }
510     }
511     m_pStereotype = stereo;
512     // TODO: don't emit modified() if predefined folder
513     if (!UMLApp::shuttingDown())
514         emitModified();
515 }
516 
517 /**
518  * Sets the classes stereotype name.
519  * Internally uses setUMLStereotype().
520  *
521  * @param name     Sets the classes stereotype name.
522  */
setStereotype(const QString & name)523 void UMLObject::setStereotype(const QString &name)
524 {
525     if (name != stereotype()) {
526         UMLApp::app()->executeCommand(new CmdSetStereotype(this, name));
527     }
528 }
529 
setStereotypeCmd(const QString & name)530 void UMLObject::setStereotypeCmd(const QString& name)
531 {
532     if (name.isEmpty()) {
533         setUMLStereotype(0);
534         return;
535     }
536     UMLDoc *pDoc = UMLApp::app()->document();
537     UMLStereotype *s = pDoc->findOrCreateStereotype(name);
538     setUMLStereotype(s);
539 }
540 
541 /**
542  * Returns the classes UMLStereotype object.
543  *
544  * @return   Returns the classes UMLStereotype object.
545  */
umlStereotype() const546 UMLStereotype * UMLObject::umlStereotype() const
547 {
548     return m_pStereotype;
549 }
550 
551 /**
552  * Returns the stereotype.
553  */
stereotype(bool includeAdornments) const554 QString UMLObject::stereotype(bool includeAdornments /* = false */) const
555 {
556     if (m_pStereotype == 0)
557         return QString();
558     return m_pStereotype->name(includeAdornments);
559 }
560 
561 /**
562  * Returns the concrete values of stereotype attributes.
563  */
tags()564 QStringList & UMLObject::tags()
565 {
566     return m_TaggedValues;
567 }
568 
569 /**
570  * Return the package(s) in which this UMLObject is contained
571  * as a text.
572  *
573  * @param separator Separator string for joining together the
574  *                  individual package prefixes (optional.)
575  *                  If no separator is given then the separator
576  *                  of the currently selected language is used.
577  * @param includeRoot  Whether to prefix the root folder name.
578  *                     Default: false.
579  * @return  The UMLObject's enclosing package(s) as a text.
580  */
package(const QString & separator,bool includeRoot) const581 QString UMLObject::package(const QString& separator, bool includeRoot) const
582 {
583     QString tempSeparator = separator;
584     if (tempSeparator.isEmpty())
585         tempSeparator = UMLApp::app()->activeLanguageScopeSeparator();
586     QString fqn = fullyQualifiedName(tempSeparator, includeRoot);
587     if (!fqn.contains(tempSeparator))
588         return QString();
589     QString scope = fqn.left(fqn.length() - tempSeparator.length() - m_name.length());
590     return scope;
591 }
592 
593 /**
594  * Return a list of the packages in which this class is embedded.
595  * The outermost package is first in the list.
596  *
597  * @param includeRoot  Whether to prefix the root folder name.
598  *                     Default: false.
599  * @return  UMLPackageList of the containing packages.
600  */
packages(bool includeRoot) const601 UMLPackageList UMLObject::packages(bool includeRoot) const
602 {
603     UMLPackageList pkgList;
604     UMLPackage* pkg = umlPackage();
605     while (pkg != 0) {
606         pkgList.prepend(pkg);
607         pkg = pkg->umlPackage();
608     }
609     if (!includeRoot)
610         pkgList.removeFirst();
611     return pkgList;
612 }
613 
614 /**
615  * Sets the UMLPackage in which this class is located.
616  *
617  * @param pPkg   Pointer to the class' UMLPackage.
618  */
setUMLPackage(UMLPackage * pPkg)619 bool UMLObject::setUMLPackage(UMLPackage *pPkg)
620 {
621     if (pPkg == this) {
622         uDebug() << "setting parent to myself is not allowed";
623         return false;
624     }
625 
626     if (pPkg == 0) {
627         // Allow setting to NULL for stereotypes
628         setParent(pPkg);
629         return true;
630     }
631 
632     if (pPkg->umlPackage() == this) {
633         uDebug() << "setting parent to an object of which I'm already the parent is not allowed";
634         return false;
635     }
636 
637     setParent(pPkg);
638     emitModified();
639     return true;
640 }
641 
642 /**
643  * Returns the UMLPackage that this class is located in.
644  *
645  * This method is a shortcut for calling umlParent()->asUMLPackage().
646  *
647  * @return  Pointer to the UMLPackage of this class.
648  */
umlPackage() const649 UMLPackage* UMLObject::umlPackage() const
650 {
651     return dynamic_cast<UMLPackage *>(parent());
652 }
653 
654 /**
655  * Set UML model parent.
656  *
657  * @param parent object to set as parent
658  *
659  * TODO prevent setting parent to myself
660  */
setUMLParent(UMLObject * parent)661 void UMLObject::setUMLParent(UMLObject *parent)
662 {
663     setParent(parent);
664 }
665 
666 /**
667  * Return UML model parent.
668  *
669  * Model classes of type UMLClassifierListItem and below
670  * uses QObject::parent to hold the model parent
671  *
672  * @return parent of uml object
673  */
umlParent() const674 UMLObject *UMLObject::umlParent() const
675 {
676     return dynamic_cast<UMLObject *>(parent());
677 }
678 
679 /**
680  * Return secondary ID. Required by resolveRef().
681  */
secondaryId() const682 QString UMLObject::secondaryId() const
683 {
684     return m_SecondaryId;
685 }
686 
687 /**
688  * Set the secondary ID.
689  * Currently only required by petalTree2Uml(); all other setting of the
690  * m_SecondaryID is internal to the UMLObject class hierarchy.
691  */
setSecondaryId(const QString & id)692 void UMLObject::setSecondaryId(const QString& id)
693 {
694     m_SecondaryId = id;
695 }
696 
697 /**
698  * Return secondary ID fallback.
699  * Required by resolveRef() for imported model files.
700  */
secondaryFallback() const701 QString UMLObject::secondaryFallback() const
702 {
703     return m_SecondaryFallback;
704 }
705 
706 /**
707  * Set the secondary ID fallback.
708  * Currently only used by petalTree2Uml().
709  */
setSecondaryFallback(const QString & id)710 void UMLObject::setSecondaryFallback(const QString& id)
711 {
712     m_SecondaryFallback = id;
713 }
714 
715 /**
716  * Calls UMLDoc::signalUMLObjectCreated() if m_BaseType affords
717  * doing so.
718  */
maybeSignalObjectCreated()719 void UMLObject::maybeSignalObjectCreated()
720 {
721     if (!m_bCreationWasSignalled &&
722             m_BaseType != ot_Stereotype &&
723             m_BaseType != ot_Association &&
724             m_BaseType != ot_Role) {
725         m_bCreationWasSignalled = true;
726         UMLDoc* umldoc = UMLApp::app()->document();
727         umldoc->signalUMLObjectCreated(this);
728     }
729 }
730 
731 /**
732  * Resolve referenced objects (if any.)
733  * Needs to be called after all UML objects are loaded from file.
734  * This needs to be done after all model objects are loaded because
735  * some of the xmi.id's might be forward references, i.e. they may
736  * identify model objects which were not yet loaded at the point of
737  * reference.
738  * The default implementation attempts resolution of the m_SecondaryId.
739  *
740  * @return   True for success.
741  */
resolveRef()742 bool UMLObject::resolveRef()
743 {
744     if (m_pSecondary || (m_SecondaryId.isEmpty() && m_SecondaryFallback.isEmpty())) {
745         maybeSignalObjectCreated();
746         return true;
747     }
748 #ifdef VERBOSE_DEBUGGING
749     uDebug() << m_name << ": m_SecondaryId is " << m_SecondaryId;
750 #endif
751     UMLDoc *pDoc = UMLApp::app()->document();
752     // In the new, XMI standard compliant save format,
753     // the type is the xmi.id of a UMLClassifier.
754     if (! m_SecondaryId.isEmpty()) {
755         m_pSecondary = pDoc->findObjectById(Uml::ID::fromString(m_SecondaryId));
756         if (m_pSecondary != 0) {
757             if (m_pSecondary->baseType() == ot_Stereotype) {
758                 if (m_pStereotype)
759                     m_pStereotype->decrRefCount();
760                 m_pStereotype = m_pSecondary->asUMLStereotype();
761                 m_pStereotype->incrRefCount();
762                 m_pSecondary = 0;
763             }
764             m_SecondaryId = QString();
765             maybeSignalObjectCreated();
766             return true;
767         }
768         if (m_SecondaryFallback.isEmpty()) {
769             uDebug() << "object with xmi.id=" << m_SecondaryId << " not found, setting to undef";
770             UMLFolder *datatypes = pDoc->datatypeFolder();
771             m_pSecondary = Object_Factory::createUMLObject(ot_Datatype, QLatin1String("undef"), datatypes, false);
772             return true;
773         }
774     }
775     if (m_SecondaryFallback.isEmpty()) {
776         uError() << m_name << ": cannot find type with id " << m_SecondaryId;
777         return false;
778     }
779 #ifdef VERBOSE_DEBUGGING
780     uDebug() << m_name << ": could not resolve secondary ID " << m_SecondaryId
781              << ", using secondary fallback " << m_SecondaryFallback;
782 #endif
783     m_SecondaryId = m_SecondaryFallback;
784     // Assume we're dealing with the older Umbrello format where
785     // the type name was saved in the "type" attribute rather
786     // than the xmi.id of the model object of the attribute type.
787     m_pSecondary = pDoc->findUMLObject(m_SecondaryId, ot_UMLObject, this);
788     if (m_pSecondary) {
789         m_SecondaryId = QString();
790         maybeSignalObjectCreated();
791         return true;
792     }
793     // Work around Object_Factory::createUMLObject()'s incapability
794     // of on-the-fly scope creation:
795     if (m_SecondaryId.contains(QLatin1String("::"))) {
796         // TODO: Merge Import_Utils::createUMLObject() into Object_Factory::createUMLObject()
797         m_pSecondary = Import_Utils::createUMLObject(ot_UMLObject, m_SecondaryId, umlPackage());
798         if (m_pSecondary) {
799             if (Import_Utils::newUMLObjectWasCreated()) {
800                 maybeSignalObjectCreated();
801                 qApp->processEvents();
802                 uDebug() << "Import_Utils::createUMLObject() created a new type for "
803                          << m_SecondaryId;
804             } else {
805                 uDebug() << "Import_Utils::createUMLObject() returned an existing type for "
806                          << m_SecondaryId;
807             }
808             m_SecondaryId = QString();
809             return true;
810         }
811         uError() << "Import_Utils::createUMLObject() failed to create a new type for "
812                  << m_SecondaryId;
813         return false;
814     }
815     uDebug() << "Creating new type for " << m_SecondaryId;
816     // This is very C++ specific - we rely on  some '*' or
817     // '&' to decide it's a ref type. Plus, we don't recognize
818     // typedefs of ref types.
819     bool isReferenceType = (m_SecondaryId.contains(QLatin1Char('*')) ||
820                             m_SecondaryId.contains(QLatin1Char('&')));
821     ObjectType ot = ot_Class;
822     if (isReferenceType) {
823         ot = ot_Datatype;
824     } else {
825         if (Model_Utils::isCommonDataType(m_SecondaryId))
826             ot = ot_Datatype;
827     }
828     m_pSecondary = Object_Factory::createUMLObject(ot, m_SecondaryId, 0);
829     if (m_pSecondary == 0)
830         return false;
831     m_SecondaryId = QString();
832     maybeSignalObjectCreated();
833     //qApp->processEvents();
834     return true;
835 }
836 
saveToXMI1(QXmlStreamWriter & writer)837 void UMLObject::saveToXMI1(QXmlStreamWriter& writer)
838 {
839     Q_UNUSED(writer);
840 }
841 
842 /**
843  * Auxiliary to saveToXMI1.
844  * Create an XML element with the given tag, and save the XMI attributes
845  * that are common to all child classes to the newly created element.
846  * This method does not need to be overridden by child classes.
847  * It is public because UMLOperation::saveToXMI1 invokes it for its
848  * <UML:Parameter>s (cannot be done with protected access).
849  */
save1(const QString & tag,QXmlStreamWriter & writer)850 void UMLObject::save1(const QString& tag, QXmlStreamWriter& writer)
851 {
852     m_d->isSaved = true;
853     /*
854       Call as the first action of saveToXMI1() in child class:
855       This creates the XML element with which to work.
856     */
857     writer.writeStartElement(tag);
858     writer.writeAttribute(QLatin1String("isSpecification"), QLatin1String("false"));
859     if (m_BaseType != ot_Association &&
860         m_BaseType != ot_Role &&
861         m_BaseType != ot_Attribute &&
862         m_BaseType != ot_Instance) {
863         writer.writeAttribute(QLatin1String("isLeaf"), QLatin1String("false"));
864         writer.writeAttribute(QLatin1String("isRoot"), QLatin1String("false"));
865         if (m_bAbstract)
866             writer.writeAttribute(QLatin1String("isAbstract"), QLatin1String("true"));
867         else
868             writer.writeAttribute(QLatin1String("isAbstract"), QLatin1String("false"));
869     }
870     writer.writeAttribute(QLatin1String("xmi.id"), Uml::ID::toString(m_nId));
871     writer.writeAttribute(QLatin1String("name"), m_name);
872     if (m_BaseType != ot_Operation &&
873         m_BaseType != ot_Role &&
874         m_BaseType != ot_Attribute) {
875         Uml::ID::Type nmSpc;
876         if (umlPackage())
877             nmSpc = umlPackage()->id();
878         else
879             nmSpc = UMLApp::app()->document()->modelID();
880         writer.writeAttribute(QLatin1String("namespace"), Uml::ID::toString(nmSpc));
881     }
882     if (! m_Doc.isEmpty())
883         writer.writeAttribute(QLatin1String("comment"), m_Doc);    //CHECK: uml13.dtd compliance
884 #ifdef XMI_FLAT_PACKAGES
885     if (umlParent()->asUMLPackage())             //FIXME: uml13.dtd compliance
886         writer.writeAttribute(QLatin1String("package"), umlParent()->asUMLPackage()->ID());
887 #endif
888     QString visibility = Uml::Visibility::toString(m_visibility, false);
889     writer.writeAttribute(QLatin1String("visibility"), visibility);
890     if (m_pStereotype != 0)
891         writer.writeAttribute(QLatin1String("stereotype"), Uml::ID::toString(m_pStereotype->id()));
892     if (m_bStatic)
893         writer.writeAttribute(QLatin1String("ownerScope"), QLatin1String("classifier"));
894     /* else
895         writer.writeAttribute("ownerScope", "instance");
896      *** ownerScope defaults to instance if not set **********/
897 }
898 
899 /**
900  * Auxiliary to saveToXMI1.
901  * Save possible stereotype tagged values stored in m_TaggedValues
902  * and write the XML end element created in save1().
903  */
save1end(QXmlStreamWriter & writer)904 void UMLObject::save1end(QXmlStreamWriter& writer)
905 {
906     // Save optional stereotype attributes
907     if (m_TaggedValues.count()) {
908         if (m_pStereotype == 0) {
909             uError() << m_name << " TaggedValues are set but pStereotype is null : clearing TaggedValues";
910             m_TaggedValues.clear();
911             return;
912         }
913         writer.writeStartElement(QLatin1String("UML:ModelElement.taggedValues"));
914         writer.writeAttribute(QLatin1String("stereotype"), Uml::ID::toString(m_pStereotype->id()));
915         const UMLStereotype::AttributeDefs& attrDefs = m_pStereotype->getAttributeDefs();
916         for (int i = 0; i < m_TaggedValues.count(); i++) {
917             if (i >= attrDefs.count()) {
918                 uError() << m_name << ": stereotype " << m_pStereotype->name() << " defines "
919                          << attrDefs.count() << " attributes; ignoring excess TaggedValues";
920                 break;
921             }
922             const QString& tv = m_TaggedValues.at(i);
923             writer.writeStartElement(QLatin1String("UML:TaggedValue"));
924             writer.writeAttribute(QLatin1String("tag"), attrDefs[i].name);
925             writer.writeAttribute(QLatin1String("value"), tv);
926             writer.writeEndElement();            // UML:TaggedValue
927         }
928         writer.writeEndElement();            // UML:ModelElement.taggedValues
929     }
930     writer.writeEndElement();
931 }
932 
933 /**
934  * Auxiliary to loadFromXMI.
935  * This method is usually overridden by child classes.
936  * It is responsible for loading the specific XMI structure
937  * of the child class.
938  */
load1(QDomElement &)939 bool UMLObject::load1(QDomElement&)
940 {
941     // This body is not usually executed because child classes
942     // overwrite the load method.
943     return true;
944 }
945 
946 /**
947  * Analyzes the given QDomElement for a reference to a stereotype.
948  *
949  * @param element   QDomElement to analyze.
950  * @return          True if a stereotype reference was found, else false.
951  */
loadStereotype(QDomElement & element)952 bool UMLObject::loadStereotype(QDomElement & element)
953 {
954     QString tag = element.tagName();
955     if (!UMLDoc::tagEq(tag, QLatin1String("stereotype")))
956         return false;
957     QString stereo = element.attribute(QLatin1String("xmi.value"));
958     if (stereo.isEmpty() && element.hasChildNodes()) {
959         /* like so:
960          <UML:ModelElement.stereotype>
961            <UML:Stereotype xmi.idref = '07CD'/>
962          </UML:ModelElement.stereotype>
963          */
964         QDomNode stereoNode = element.firstChild();
965         QDomElement stereoElem = stereoNode.toElement();
966         tag = stereoElem.tagName();
967         if (UMLDoc::tagEq(tag, QLatin1String("Stereotype"))) {
968             stereo = stereoElem.attribute(QLatin1String("xmi.idref"));
969         }
970     }
971     if (stereo.isEmpty())
972         return false;
973     Uml::ID::Type stereoID = Uml::ID::fromString(stereo);
974     UMLDoc *pDoc = UMLApp::app()->document();
975     if (m_pStereotype)
976         m_pStereotype->decrRefCount();
977     m_pStereotype = pDoc->findStereotypeById(stereoID);
978     if (m_pStereotype)
979         m_pStereotype->incrRefCount();
980     else
981         m_SecondaryId = stereo;  // leave it to resolveRef()
982     return true;
983 }
984 
985 /**
986  * This method loads the generic parts of the XMI common to most model
987  * classes.  It is not usually reimplemented by child classes.
988  * Instead, it invokes the load() method which implements the loading
989  * of the specifics of each child class.
990  *
991  * @param element   The QDomElement from which to load.
992  */
loadFromXMI1(QDomElement & element)993 bool UMLObject::loadFromXMI1(QDomElement & element)
994 {
995     UMLDoc* umldoc = UMLApp::app()->document();
996     if (umldoc == 0) {
997         uError() << "umldoc is NULL";
998         return false;
999     }
1000     // Read the name first so that if we encounter a problem, the error
1001     // message can say the name.
1002     m_name = element.attribute(QLatin1String("name"));
1003     QString id = Model_Utils::getXmiId(element);
1004     if (id.isEmpty() || id == QLatin1String("-1")) {
1005         // Before version 1.4, Umbrello did not save the xmi.id of UMLRole objects.
1006         // Some tools (such as Embarcadero's) do not have an xmi.id on all attributes.
1007         m_nId = UniqueID::gen();
1008         uWarning() << m_name << ": xmi.id not present, generating a new one";
1009     } else {
1010         Uml::ID::Type nId = Uml::ID::fromString(id);
1011         if (m_BaseType == ot_Role) {
1012             // Some older Umbrello versions had a problem with xmi.id's
1013             // of other objects being reused for the UMLRole, see e.g.
1014             // attachment 21179 at https://bugs.kde.org/147988 .
1015             // If the xmi.id is already being used then we generate a new one.
1016             UMLObject *o = umldoc->findObjectById(nId);
1017             if (o) {
1018                 uError() << "loadFromXMI1(UMLRole): id " << id
1019                          << " is already in use!!! Please fix your XMI file.";
1020             }
1021         }
1022         m_nId = nId;
1023     }
1024 
1025     if (element.hasAttribute(QLatin1String("documentation")))  // for bkwd compat.
1026         m_Doc = element.attribute(QLatin1String("documentation"));
1027     else
1028         m_Doc = element.attribute(QLatin1String("comment"));    //CHECK: need a UML:Comment?
1029 
1030     m_visibility = Uml::Visibility::Public;
1031     if (element.hasAttribute(QLatin1String("scope"))) {        // for bkwd compat.
1032         QString scope = element.attribute(QLatin1String("scope"));
1033         if (scope == QLatin1String("instance_level"))         // nsuml compat.
1034             m_bStatic = false;
1035         else if (scope == QLatin1String("classifier_level"))  // nsuml compat.
1036             m_bStatic = true;
1037         else {
1038             int nScope = scope.toInt();
1039             switch (nScope) {
1040             case 200:
1041                 m_visibility = Uml::Visibility::Public;
1042                 break;
1043             case 201:
1044                 m_visibility = Uml::Visibility::Private;
1045                 break;
1046             case 202:
1047                 m_visibility = Uml::Visibility::Protected;
1048                 break;
1049             default:
1050                 uError() << m_name << ": illegal scope " << nScope;
1051             }
1052         }
1053     } else {
1054         QString visibility = element.attribute(QLatin1String("visibility"), QLatin1String("public"));
1055         if (visibility == QLatin1String("private")
1056                 || visibility == QLatin1String("private_vis"))    // for compatibility with other programs
1057             m_visibility = Uml::Visibility::Private;
1058         else if (visibility == QLatin1String("protected")
1059                  || visibility == QLatin1String("protected_vis"))  // for compatibility with other programs
1060             m_visibility = Uml::Visibility::Protected;
1061         else if (visibility == QLatin1String("implementation"))
1062             m_visibility = Uml::Visibility::Implementation;
1063     }
1064 
1065     QString stereo = element.attribute(QLatin1String("stereotype"));
1066     if (!stereo.isEmpty()) {
1067         Uml::ID::Type stereoID = Uml::ID::fromString(stereo);
1068         if (m_pStereotype)
1069             m_pStereotype->decrRefCount();
1070         m_pStereotype = umldoc->findStereotypeById(stereoID);
1071         if (m_pStereotype) {
1072             m_pStereotype->incrRefCount();
1073         } else {
1074             uDebug() << m_name << ": UMLStereotype " << Uml::ID::toString(stereoID)
1075                      << " not found, creating now.";
1076             setStereotypeCmd(stereo);
1077         }
1078     }
1079 
1080     if (element.hasAttribute(QLatin1String("abstract"))) {      // for bkwd compat.
1081         QString abstract = element.attribute(QLatin1String("abstract"), QLatin1String("0"));
1082         m_bAbstract = (bool)abstract.toInt();
1083     } else {
1084         QString isAbstract = element.attribute(QLatin1String("isAbstract"), QLatin1String("false"));
1085         m_bAbstract = (isAbstract == QLatin1String("true"));
1086     }
1087 
1088     if (element.hasAttribute(QLatin1String("static"))) {        // for bkwd compat.
1089         QString staticScope = element.attribute(QLatin1String("static"), QLatin1String("0"));
1090         m_bStatic = (bool)staticScope.toInt();
1091     } else {
1092         QString ownerScope = element.attribute(QLatin1String("ownerScope"), QLatin1String("instance"));
1093         m_bStatic = (ownerScope == QLatin1String("classifier"));
1094     }
1095 
1096     // If the node has child nodes, check whether attributes can be
1097     // extracted from them.
1098     if (element.hasChildNodes()) {
1099         QDomNode node = element.firstChild();
1100         if (node.isComment())
1101             node = node.nextSibling();
1102         QDomElement elem = node.toElement();
1103         while (!elem.isNull()) {
1104             QString tag = elem.tagName();
1105             if (UMLDoc::tagEq(tag, QLatin1String("ModelElement.taggedValues"))) {
1106                 QDomNode tvNode = elem.firstChild();
1107                 QDomElement tvElem = tvNode.toElement();
1108                 while (!tvElem.isNull()) {
1109                     tag = tvElem.tagName();
1110                     if (UMLDoc::tagEq(tag, QLatin1String("TaggedValue"))) {
1111                         QString value = tvElem.attribute(QLatin1String("value"));
1112                         m_TaggedValues.append(value);
1113                         uDebug() << "loadFromXMI1(" << m_name
1114                                  << "): Loaded " << tag << " value " << value;
1115                     } else {
1116                         uDebug() << "loadFromXMI1(" << m_name
1117                                  << "): Unknown ModelElement.taggedValues child " << tag;
1118                     }
1119                     tvNode = tvNode.nextSibling();
1120                     tvElem = tvNode.toElement();
1121                 }
1122             } else if (UMLDoc::tagEq(tag, QLatin1String("name"))) {
1123                 m_name = elem.attribute(QLatin1String("xmi.value"));
1124                 if (m_name.isEmpty())
1125                     m_name = elem.text();
1126             } else if (UMLDoc::tagEq(tag, QLatin1String("visibility"))) {
1127                 QString vis = elem.attribute(QLatin1String("xmi.value"));
1128                 if (vis.isEmpty())
1129                     vis = elem.text();
1130                 if (vis == QLatin1String("private") || vis == QLatin1String("private_vis"))
1131                     m_visibility = Uml::Visibility::Private;
1132                 else if (vis == QLatin1String("protected") || vis == QLatin1String("protected_vis"))
1133                     m_visibility = Uml::Visibility::Protected;
1134                 else if (vis == QLatin1String("implementation"))
1135                     m_visibility = Uml::Visibility::Implementation;
1136             } else if (UMLDoc::tagEq(tag, QLatin1String("isAbstract"))) {
1137                 QString isAbstract = elem.attribute(QLatin1String("xmi.value"));
1138                 if (isAbstract.isEmpty())
1139                     isAbstract = elem.text();
1140                 m_bAbstract = (isAbstract == QLatin1String("true"));
1141             } else if (UMLDoc::tagEq(tag, QLatin1String("ownerScope"))) {
1142                 QString ownerScope = elem.attribute(QLatin1String("xmi.value"));
1143                 if (ownerScope.isEmpty())
1144                     ownerScope = elem.text();
1145                 m_bStatic = (ownerScope == QLatin1String("classifier"));
1146             } else {
1147                 loadStereotype(elem);
1148             }
1149             node = node.nextSibling();
1150             if (node.isComment())
1151                 node = node.nextSibling();
1152             elem = node.toElement();
1153         }
1154     }
1155 
1156     // Operations, attributes, enum literals, templates, stereotypes,
1157     // and association role objects get added and signaled elsewhere.
1158     if (m_BaseType != ot_Operation && m_BaseType != ot_Attribute &&
1159         m_BaseType != ot_EnumLiteral && m_BaseType != ot_EntityAttribute &&
1160         m_BaseType != ot_Template && m_BaseType != ot_Stereotype &&
1161         m_BaseType != ot_Role && m_BaseType != ot_UniqueConstraint &&
1162         m_BaseType != ot_ForeignKeyConstraint && m_BaseType != ot_CheckConstraint &&
1163         m_BaseType != ot_InstanceAttribute ) {
1164         if (umlPackage()) {
1165             umlPackage()->addObject(this);
1166         } else if (umldoc->rootFolderType(this) == Uml::ModelType::N_MODELTYPES) {
1167             // umlPackage() is not set on the root folders.
1168             uDebug() << m_name << ": umlPackage() is not set";
1169         }
1170     }
1171     return load1(element);
1172 }
1173 
1174 /**
1175  * Helper function for debug output.
1176  * Returns the given enum value as string.
1177  * @param ot   ObjectType of which a string representation is wanted
1178  * @return   the ObjectType as string
1179  */
toString(ObjectType ot)1180 QString UMLObject::toString(ObjectType ot)
1181 {
1182     return QLatin1String(ENUM_NAME(UMLObject, ObjectType, ot));
1183 }
1184 
1185 /**
1186  * Returns the given object type value as localized string.
1187  * @param t   ObjectType of which a string representation is wanted
1188  * @return   the ObjectType as localized string
1189  */
toI18nString(ObjectType t)1190 QString UMLObject::toI18nString(ObjectType t)
1191 {
1192     QString name;
1193 
1194     switch (t) {
1195     case UMLObject::ot_Actor:
1196         name = i18n("Actor &name:");
1197         break;
1198     case  UMLObject::ot_Artifact:
1199         name = i18n("Artifact &name:");
1200         break;
1201     case UMLObject::ot_Association:
1202         name = i18n("Association &name:");
1203         break;
1204     case UMLObject::ot_Class:
1205         name = i18n("Class &name:");
1206         break;
1207     case  UMLObject::ot_Component:
1208         name = i18n("Component &name:");
1209         break;
1210     case  UMLObject::ot_Datatype:
1211         name = i18n("Datatype &name:");
1212         break;
1213     case  UMLObject::ot_Entity:
1214         name = i18n("Entity &name:");
1215         break;
1216     case  UMLObject::ot_Enum:
1217         name = i18n("Enum &name:");
1218         break;
1219     case  UMLObject::ot_Folder:
1220         name = i18n("Folder &name:");
1221         break;
1222     case  UMLObject::ot_Interface:
1223         name = i18n("Interface &name:");
1224         break;
1225     case  UMLObject::ot_Node:
1226         name = i18n("Node &name:");
1227         break;
1228     case  UMLObject::ot_Package:
1229         name = i18n("Package &name:");
1230         break;
1231     case  UMLObject::ot_Port:
1232         name = i18n("Port &name:");
1233         break;
1234     case  UMLObject::ot_Stereotype:
1235         name = i18n("Stereotype &name:");
1236         break;
1237     case  UMLObject::ot_UseCase:
1238         name = i18n("Use case &name:");
1239         break;
1240     case UMLObject::ot_Instance:
1241         name = i18n("Instance name:");
1242         break;
1243 
1244     default:
1245         name = QLatin1String("<unknown> &name:");
1246         uWarning() << "UMLObject::toI18nString unknown object type " << toString(t);
1247         break;
1248     }
1249     return name;
1250 }
1251 
1252 /**
1253  * Returns the given object type value as icon type.
1254  * @param t  ObjectType of which an icon type is wanted
1255  * @return   the ObjectType as icon type
1256  */
toIcon(ObjectType t)1257 Icon_Utils::IconType UMLObject::toIcon(ObjectType t)
1258 {
1259     Icon_Utils::IconType icon;
1260 
1261     switch (t) {
1262     case UMLObject::ot_Actor:
1263         icon = Icon_Utils::it_Actor;
1264         break;
1265     case  UMLObject::ot_Artifact:
1266         icon = Icon_Utils::it_Artifact;
1267         break;
1268     case UMLObject::ot_Association:
1269         icon = Icon_Utils::it_Association;
1270         break;
1271     case UMLObject::ot_Class:
1272         icon = Icon_Utils::it_Class;
1273         break;
1274     case  UMLObject::ot_Component:
1275         icon = Icon_Utils::it_Component;
1276         break;
1277     case  UMLObject::ot_Datatype:
1278         icon = Icon_Utils::it_Datatype;
1279         break;
1280     case  UMLObject::ot_Entity:
1281         icon = Icon_Utils::it_Entity;
1282         break;
1283     case  UMLObject::ot_Enum:
1284         icon = Icon_Utils::it_Enum;
1285         break;
1286     case  UMLObject::ot_Folder:
1287         icon = Icon_Utils::it_Folder;
1288         break;
1289     case UMLObject::ot_Instance:
1290         icon = Icon_Utils::it_Instance;
1291         break;
1292     case  UMLObject::ot_Interface:
1293         icon = Icon_Utils::it_Interface;
1294         break;
1295     case  UMLObject::ot_Node:
1296         icon = Icon_Utils::it_Node;
1297         break;
1298     case  UMLObject::ot_Package:
1299         icon = Icon_Utils::it_Package;
1300         break;
1301     case  UMLObject::ot_Port:
1302         icon = Icon_Utils::it_Port;
1303         break;
1304     case  UMLObject::ot_EnumLiteral:
1305         icon = Icon_Utils::it_Enum_Literal;
1306         break;
1307     case  UMLObject::ot_Attribute:
1308     case  UMLObject::ot_InstanceAttribute:
1309         icon = Icon_Utils::it_Public_Attribute;
1310         break;
1311     case  UMLObject::ot_Operation:
1312         icon = Icon_Utils::it_Public_Method;
1313         break;
1314     case  UMLObject::ot_Template:
1315         icon = Icon_Utils::it_Template;
1316         break;
1317     case  UMLObject::ot_Category:
1318         icon = Icon_Utils::it_Category;
1319         break;
1320     case  UMLObject::ot_EntityAttribute:
1321         icon = Icon_Utils::it_Entity_Attribute;
1322         break;
1323     case  UMLObject::ot_UniqueConstraint:
1324         icon = Icon_Utils::it_Unique_Constraint;
1325         break;
1326     case  UMLObject::ot_ForeignKeyConstraint:
1327         icon = Icon_Utils::it_ForeignKey_Constraint;
1328         break;
1329     case  UMLObject::ot_CheckConstraint:
1330         icon = Icon_Utils::it_Check_Constraint;
1331         break;
1332     case  UMLObject::ot_UseCase:
1333         icon = Icon_Utils::it_UseCase;
1334         break;
1335 
1336     default:
1337         icon = Icon_Utils::it_Home;
1338         uWarning() << "UMLObject::toIcon unknown object type " << toString(t);
1339         break;
1340     }
1341     return icon;
1342 }
1343 
1344 /**
1345  * Print UML Object to debug output stream, so it can be used like
1346  *   uDebug() << "This object shouldn't be here: " << illegalObject;
1347  */
operator <<(QDebug out,const UMLObject & obj)1348 QDebug operator<<(QDebug out, const UMLObject& obj)
1349 {
1350     out.nospace() << "UMLObject: name= " << obj.name()
1351         << ", type= " << UMLObject::toString(obj.m_BaseType);
1352     return out.space();
1353 }
1354 
1355 //only required for getting types
1356 #include "actor.h"
1357 #include "artifact.h"
1358 #include "association.h"
1359 #include "attribute.h"
1360 #include "umlcanvasobject.h"
1361 #include "category.h"
1362 #include "checkconstraint.h"
1363 #include "classifier.h"
1364 #include "component.h"
1365 #include "datatype.h"
1366 #include "entity.h"
1367 #include "entityattribute.h"
1368 #include "entityconstraint.h"
1369 #include "enum.h"
1370 #include "foreignkeyconstraint.h"
1371 #include "instance.h"
1372 #include "instanceattribute.h"
1373 #include "node.h"
1374 #include "operation.h"
1375 #include "port.h"
1376 #include "umlrole.h"
1377 #include "template.h"
1378 #include "uniqueconstraint.h"
1379 #include "usecase.h"
1380 
1381 
asUMLActor()1382 UMLActor                * UMLObject::asUMLActor()                { return dynamic_cast<UMLActor*>(this); }
asUMLArtifact()1383 UMLArtifact             * UMLObject::asUMLArtifact()             { return dynamic_cast<UMLArtifact*>(this); }
asUMLAssociation()1384 UMLAssociation          * UMLObject::asUMLAssociation()          { return dynamic_cast<UMLAssociation*>(this); }
asUMLAttribute()1385 UMLAttribute            * UMLObject::asUMLAttribute()            { return dynamic_cast<UMLAttribute*>(this); }
asUMLCanvasObject()1386 UMLCanvasObject         * UMLObject::asUMLCanvasObject()         { return dynamic_cast<UMLCanvasObject*>(this); }
asUMLCategory()1387 UMLCategory             * UMLObject::asUMLCategory()             { return dynamic_cast<UMLCategory*>(this); }
asUMLCheckConstraint()1388 UMLCheckConstraint      * UMLObject::asUMLCheckConstraint()      { return dynamic_cast<UMLCheckConstraint*>(this); }
asUMLClassifier()1389 UMLClassifier           * UMLObject::asUMLClassifier()           { return dynamic_cast<UMLClassifier*>(this); }
asUMLClassifierListItem()1390 UMLClassifierListItem   * UMLObject::asUMLClassifierListItem()   { return dynamic_cast<UMLClassifierListItem*>(this); }
asUMLComponent()1391 UMLComponent            * UMLObject::asUMLComponent()            { return dynamic_cast<UMLComponent*>(this); }
asUMLDatatype()1392 UMLDatatype             * UMLObject::asUMLDatatype()             { return dynamic_cast<UMLDatatype*>(this); }
asUMLEntity()1393 UMLEntity               * UMLObject::asUMLEntity()               { return dynamic_cast<UMLEntity*>(this); }
asUMLEntityAttribute()1394 UMLEntityAttribute      * UMLObject::asUMLEntityAttribute()      { return dynamic_cast<UMLEntityAttribute*>(this); }
asUMLEntityConstraint()1395 UMLEntityConstraint     * UMLObject::asUMLEntityConstraint()     { return dynamic_cast<UMLEntityConstraint*>(this); }
asUMLEnum()1396 UMLEnum                 * UMLObject::asUMLEnum()                 { return dynamic_cast<UMLEnum*>(this); }
asUMLEnumLiteral()1397 UMLEnumLiteral          * UMLObject::asUMLEnumLiteral()          { return dynamic_cast<UMLEnumLiteral*>(this); }
asUMLFolder()1398 UMLFolder               * UMLObject::asUMLFolder()               { return dynamic_cast<UMLFolder*>(this); }
asUMLForeignKeyConstraint()1399 UMLForeignKeyConstraint * UMLObject::asUMLForeignKeyConstraint() { return dynamic_cast<UMLForeignKeyConstraint*>(this); }
asUMLInstance()1400 UMLInstance             * UMLObject::asUMLInstance()             { return dynamic_cast<UMLInstance*>(this); }
asUMLInstanceAttribute()1401 UMLInstanceAttribute    * UMLObject::asUMLInstanceAttribute()    { return dynamic_cast<UMLInstanceAttribute*>(this); }
asUMLNode()1402 UMLNode                 * UMLObject::asUMLNode()                 { return dynamic_cast<UMLNode*>(this); }
asUMLObject()1403 UMLObject               * UMLObject::asUMLObject()               { return dynamic_cast<UMLObject*>(this); }
asUMLOperation()1404 UMLOperation            * UMLObject::asUMLOperation()            { return dynamic_cast<UMLOperation*>(this); }
asUMLPackage()1405 UMLPackage              * UMLObject::asUMLPackage()              { return dynamic_cast<UMLPackage*>(this); }
asUMLPort()1406 UMLPort                 * UMLObject::asUMLPort()                 { return dynamic_cast<UMLPort*>(this); }
asUMLRole()1407 UMLRole                 * UMLObject::asUMLRole()                 { return dynamic_cast<UMLRole*>(this); }
asUMLStereotype()1408 UMLStereotype           * UMLObject::asUMLStereotype()           { return dynamic_cast<UMLStereotype*>(this); }
asUMLTemplate()1409 UMLTemplate             * UMLObject::asUMLTemplate()             { return dynamic_cast<UMLTemplate*>(this); }
asUMLUniqueConstraint()1410 UMLUniqueConstraint     * UMLObject::asUMLUniqueConstraint()     { return dynamic_cast<UMLUniqueConstraint*>(this); }
asUMLUseCase()1411 UMLUseCase              * UMLObject::asUMLUseCase()              { return dynamic_cast<UMLUseCase*>(this); }
1412 
1413