• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

umbrello/umbrello

  • sources
  • kde-4.12
  • kdesdk
  • umbrello
  • umbrello
umlrole.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * This program is free software; you can redistribute it and/or modify *
3  * it under the terms of the GNU General Public License as published by *
4  * the Free Software Foundation; either version 2 of the License, or *
5  * (at your option) any later version. *
6  * *
7  * copyright (C) 2003-2013 *
8  * Umbrello UML Modeller Authors <umbrello-devel@kde.org> *
9  ***************************************************************************/
10 
11 // own header
12 #include "umlrole.h"
13 
14 // local includes
15 #include "association.h"
16 #include "debug_utils.h"
17 #include "umldoc.h"
18 #include "uml.h"
19 
20 // qt includes
21 #include <QRegExp>
22 
30 UMLRole::UMLRole(UMLAssociation * parent, UMLObject * parentObj, Uml::RoleType::Enum role)
31  : UMLObject(const_cast<UMLAssociation*>(parent)),
32  m_pAssoc(parent),
33  m_role(role),
34  m_Multi(QString()),
35  m_Changeability(Uml::Changeability::Changeable)
36 {
37  m_BaseType = UMLObject::ot_Role;
38  m_name.clear();
39  m_pSecondary = parentObj;
40 
41  // connect this up to parent
42  connect(this, SIGNAL(modified()), parent, SIGNAL(modified()));
43 }
44 
48 UMLRole::~UMLRole()
49 {
50 }
51 
55 bool UMLRole::operator==(const UMLRole &rhs) const
56 {
57  if (this == &rhs) {
58  return true;
59  }
60  return (UMLObject::operator==(rhs) &&
61  m_Changeability == rhs.m_Changeability &&
62  m_Multi == rhs.m_Multi &&
63  m_name == rhs.m_name
64  );
65 }
66 
67 UMLAssociation * UMLRole::parentAssociation() const
68 {
69  return m_pAssoc;
70 }
71 
76 UMLObject* UMLRole::object() const
77 {
78  return m_pSecondary;
79 }
80 
86 Uml::Changeability::Enum UMLRole::changeability() const
87 {
88  return m_Changeability;
89 }
90 
96 QString UMLRole::multiplicity() const
97 {
98  return m_Multi;
99 }
100 
106 void UMLRole::setObject(UMLObject *obj)
107 {
108  // because we will get the id of this role from the parent
109  // object, we CANT allow UMLRoles to take other UMLRoles as
110  // parent objects. In fact, there is probably good reason
111  // to only take UMLClassifiers here, but I'll leave it more open
112  // for the time being. -b.t.
113  if (obj && dynamic_cast<UMLRole*>(obj)) {
114  uError() << "UMLRole(" << Uml::ID::toString(m_nId) << ") cannot setObject() to another UMLRole("
115  << Uml::ID::toString(obj->id()) << ")";
116  return;
117  }
118 
119  m_pSecondary = obj;
120  UMLObject::emitModified();
121 }
122 
128 void UMLRole::setChangeability(Uml::Changeability::Enum value)
129 {
130  m_Changeability = value;
131  UMLObject::emitModified();
132 }
133 
139 void UMLRole::setMultiplicity(const QString &multi)
140 {
141  m_Multi = multi;
142  UMLObject::emitModified();
143 }
144 
152 Uml::RoleType::Enum UMLRole::role() const
153 {
154  return m_role;
155 }
156 
160 void UMLRole::saveToXMI(QDomDocument & qDoc, QDomElement & qElement)
161 {
162  QDomElement roleElement = UMLObject::save("UML:AssociationEnd", qDoc);
163  if (m_pSecondary)
164  roleElement.setAttribute("type", Uml::ID::toString(m_pSecondary->id()));
165  else
166  uError() << "id " << Uml::ID::toString(m_nId) << ": m_pSecondary is NULL";
167  if (!m_Multi.isEmpty())
168  roleElement.setAttribute("multiplicity", m_Multi);
169  if (m_role == Uml::RoleType::A) { // role aggregation based on parent type
170  // role A
171  switch (m_pAssoc->getAssocType()) {
172  case Uml::AssociationType::Composition:
173  roleElement.setAttribute("aggregation", "composite");
174  break;
175  case Uml::AssociationType::Aggregation:
176  roleElement.setAttribute("aggregation", "aggregate");
177  break;
178  default:
179  roleElement.setAttribute("aggregation", "none");
180  break;
181  }
182  if (m_pAssoc->getAssocType() == Uml::AssociationType::UniAssociation) {
183  // Normally the isNavigable attribute is "true".
184  // We set it to false on role A to indicate that
185  // role B gets an explicit arrowhead.
186  roleElement.setAttribute("isNavigable", "false");
187  } else {
188  roleElement.setAttribute("isNavigable", "true");
189  }
190  } else {
191  roleElement.setAttribute("aggregation", "none");
192  roleElement.setAttribute("isNavigable", "true");
193  //FIXME obviously this isn't standard XMI
194  if (m_pAssoc->getAssocType() == Uml::AssociationType::Relationship) {
195  roleElement.setAttribute("relationship", "true");
196  }
197  }
198 
199  roleElement.setAttribute("visibility", Uml::Visibility::toString(visibility(), false));
200 
201  switch (m_Changeability) {
202  case Uml::Changeability::Frozen:
203  roleElement.setAttribute("changeability", "frozen");
204  break;
205  case Uml::Changeability::AddOnly:
206  roleElement.setAttribute("changeability", "addOnly");
207  break;
208  case Uml::Changeability::Changeable:
209  roleElement.setAttribute("changeability", "changeable");
210  break;
211  }
212  qElement.appendChild(roleElement);
213 }
214 
219 bool UMLRole::load(QDomElement & element)
220 {
221  UMLDoc * doc = UMLApp::app()->document();
222  QString type = element.attribute("type", "");
223  if (!type.isEmpty()) {
224  if (!m_SecondaryId.isEmpty())
225  uWarning() << "overwriting old m_SecondaryId \"" << m_SecondaryId
226  << " with new value \"" << type << "\"";
227  m_SecondaryId = type;
228  }
229  // Inspect child nodes - for multiplicity (and type if not set above.)
230  for (QDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling()) {
231  if (node.isComment())
232  continue;
233  QDomElement tempElement = node.toElement();
234  QString tag = tempElement.tagName();
235  if (UMLDoc::tagEq(tag, "name")) {
236  m_name = tempElement.text();
237  } else if (UMLDoc::tagEq(tag, "AssociationEnd.multiplicity")) {
245  QDomNode n = tempElement.firstChild();
246  if (node.isNull() || tempElement.isNull() || n.isNull() ||
247  n.toElement().isNull()) {
248  m_Multi = tempElement.text().trimmed();
249  continue;
250  }
251  tempElement = n.toElement();
252  tag = tempElement.tagName();
253  if (!UMLDoc::tagEq(tag, "Multiplicity")) {
254  m_Multi = tempElement.text().trimmed();
255  continue;
256  }
257  n = tempElement.firstChild();
258  tempElement = n.toElement();
259  tag = tempElement.tagName();
260  if (!UMLDoc::tagEq(tag, "Multiplicity.range")) {
261  m_Multi = tempElement.text().trimmed();
262  continue;
263  }
264  n = tempElement.firstChild();
265  tempElement = n.toElement();
266  tag = tempElement.tagName();
267  if (!UMLDoc::tagEq(tag, "MultiplicityRange")) {
268  m_Multi = tempElement.text().trimmed();
269  continue;
270  }
271  QString multiUpper;
272  if (tempElement.hasAttribute("lower")) {
273  m_Multi = tempElement.attribute("lower", "");
274  multiUpper = tempElement.attribute("upper", "");
275  if (!multiUpper.isEmpty()) {
276  if (!m_Multi.isEmpty())
277  m_Multi.append("..");
278  m_Multi.append(multiUpper);
279  }
280  continue;
281  }
282  n = tempElement.firstChild();
283  while (!n.isNull()) {
284  tempElement = n.toElement();
285  tag = tempElement.tagName();
286  if (UMLDoc::tagEq(tag, "MultiplicityRange.lower")) {
287  m_Multi = tempElement.text();
288  } else if (UMLDoc::tagEq(tag, "MultiplicityRange.upper")) {
289  multiUpper = tempElement.text();
290  }
291  n = n.nextSibling();
292  }
293  if (!multiUpper.isEmpty()) {
294  if (!m_Multi.isEmpty())
295  m_Multi.append("..");
296  m_Multi.append(multiUpper);
297  }
298  } else if (m_SecondaryId.isEmpty() &&
299  (UMLDoc::tagEq(tag, "type") ||
300  UMLDoc::tagEq(tag, "participant"))) {
301  m_SecondaryId = tempElement.attribute("xmi.id", "");
302  if (m_SecondaryId.isEmpty())
303  m_SecondaryId = tempElement.attribute("xmi.idref", "");
304  if (m_SecondaryId.isEmpty()) {
305  QDomNode inner = tempElement.firstChild();
306  QDomElement innerElem = inner.toElement();
307  m_SecondaryId = innerElem.attribute("xmi.id", "");
308  if (m_SecondaryId.isEmpty())
309  m_SecondaryId = innerElem.attribute("xmi.idref", "");
310  }
311  }
312  }
313  if (!m_Multi.isEmpty())
314  uDebug() << name() << ": m_Multi is " << m_Multi;
315  if (m_SecondaryId.isEmpty()) {
316  uError() << name() << ": type not given or illegal";
317  return false;
318  }
319  UMLObject * obj;
320  obj = doc->findObjectById(Uml::ID::fromString(m_SecondaryId));
321  if (obj) {
322  m_pSecondary = obj;
323  m_SecondaryId = "";
324  }
325 
326  // block signals to prevent needless updating
327  blockSignals(true);
328  // Here comes the handling of the association type.
329  // This is open for discussion - I'm pretty sure there are better ways..
330 
331  // Yeah, for one, setting the *parent* object parameters from here is sucky
332  // as hell. Why are we using roleA to store what is essentially a parent (association)
333  // parameter, eh? The UML13.dtd is pretty silly, but since that is what
334  // is driving us to that point, we have to go with it. Some analysis of
335  // the component roles/linked items needs to be done in order to get things
336  // right. *sigh* -b.t.
337 
338  // Setting association type from the role (A)
339  // Determination of the "aggregation" attribute used to be done only
340  // when (m_role == Uml::RoleType::A) but some XMI writers (e.g. StarUML) place
341  // the aggregation attribute at role B.
342  // The role end with the aggregation unequal to "none" wins.
343  QString aggregation = element.attribute("aggregation", "none");
344  if (aggregation == "composite")
345  m_pAssoc->setAssociationType(Uml::AssociationType::Composition);
346  else if (aggregation == "shared" // UML1.3
347  || aggregation == "aggregate") // UML1.4
348  m_pAssoc->setAssociationType(Uml::AssociationType::Aggregation);
349 
350  if (!element.hasAttribute("isNavigable")) {
351  // Backward compatibility mode: In Umbrello version 1.3.x the
352  // logic for saving the isNavigable flag was wrong.
353  // May happen on loading role A.
354  m_pAssoc->setOldLoadMode(true);
355  } else if (m_pAssoc->getOldLoadMode() == true) {
356  // Here is the original logic:
357  // "Role B:
358  // If isNavigable is not given, we make no change to the
359  // association type.
360  // If isNavigable is given, and is "true", then we assume that
361  // the association's other end (role A) is not navigable, and
362  // therefore we change the association type to UniAssociation.
363  // The case that isNavigable is given as "false" is ignored.
364  // Combined with the association type logic for role A, this
365  // allows us to support at_Association and at_UniAssociation."
366  if (element.attribute("isNavigable") == "true")
367  m_pAssoc->setAssociationType(Uml::AssociationType::UniAssociation);
368  } else if (element.attribute("isNavigable") == "false") {
369  m_pAssoc->setAssociationType(Uml::AssociationType::UniAssociation);
370  }
371 
372  //FIXME not standard XMI
373  if (element.hasAttribute("relationship")) {
374  if (element.attribute("relationship") == "true") {
375  m_pAssoc->setAssociationType(Uml::AssociationType::Relationship);
376  }
377  }
378 
379  if (m_Multi.isEmpty())
380  m_Multi = element.attribute("multiplicity", "");
381 
382  // Changeability defaults to Changeable if it cant set it here..
383  m_Changeability = Uml::Changeability::Changeable;
384  QString changeability = element.attribute("changeability", "");
385  if (changeability.isEmpty())
386  element.attribute("changeable", ""); // for backward compatibility
387  if (changeability == "frozen")
388  m_Changeability = Uml::Changeability::Frozen;
389  else if (changeability == "addOnly")
390  m_Changeability = Uml::Changeability::AddOnly;
391 
392  // finished config, now unblock
393  blockSignals(false);
394  return true;
395 }
396 
397 #include "umlrole.moc"
Uml::AssociationType::Aggregation
Definition: basictypes.h:101
UMLAssociation::getOldLoadMode
bool getOldLoadMode() const
Return the backward compatibility flag for loading files.
Definition: association.cpp:580
UMLRole::multiplicity
QString multiplicity() const
Returns the multiplicity assigned to the role.
Definition: umlrole.cpp:96
UMLRole::~UMLRole
virtual ~UMLRole()
Standard destructor.
Definition: umlrole.cpp:48
association.h
UMLAssociation::setAssociationType
void setAssociationType(Uml::AssociationType::Enum assocType)
Sets the assocType of the UMLAssociation.
Definition: association.cpp:589
Uml::RoleType::A
Definition: basictypes.h:209
UMLObject::ot_Role
Definition: umlobject.h:66
UMLObject::visibility
Uml::Visibility::Enum visibility() const
Returns the visibility of the object.
Definition: umlobject.cpp:435
Uml::AssociationType::UniAssociation
Definition: basictypes.h:112
UMLRole::parentAssociation
UMLAssociation * parentAssociation() const
Definition: umlrole.cpp:67
UMLDoc::tagEq
static bool tagEq(const QString &tag, const QString &pattern)
Function for comparing tags in XMI files.
Definition: umldoc.cpp:3030
umlrole.h
UMLRole::setObject
void setObject(UMLObject *obj)
Sets the UMLObject playing the role in the association.
Definition: umlrole.cpp:106
UMLRole::UMLRole
UMLRole(UMLAssociation *parent, UMLObject *parentUMLObject, Uml::RoleType::Enum role)
Sets up an association.
Definition: umlrole.cpp:30
UMLRole::operator==
bool operator==(const UMLRole &rhs) const
Overloaded '==' operator.
Definition: umlrole.cpp:55
UMLApp::app
static UMLApp * app()
Get the last created instance of this class.
Definition: uml.cpp:206
Uml::Changeability::Changeable
Definition: basictypes.h:176
uWarning
#define uWarning()
Definition: debug_utils.h:97
UMLApp::document
UMLDoc * document() const
Returns a pointer to the current document connected to the KMainWindow instance.
Definition: uml.cpp:872
debug_utils.h
UMLObject
This class is the non-graphical version of UMLWidget.
Definition: umlobject.h:41
UMLAssociation
This class contains the non-graphic representation of an association.
Definition: association.h:32
UMLRole::setChangeability
void setChangeability(Uml::Changeability::Enum value)
Sets the changeability of the role.
Definition: umlrole.cpp:128
Uml::RoleType::Enum
Enum
Definition: basictypes.h:208
Uml::Changeability::AddOnly
Definition: basictypes.h:178
UMLAssociation::getAssocType
Uml::AssociationType::Enum getAssocType() const
Returns the AssociationType::Enum of the UMLAssociation.
Definition: association.cpp:103
UMLAssociation::setOldLoadMode
void setOldLoadMode(bool value=true)
Set the attribute m_bOldLoadMode.
Definition: association.cpp:572
uDebug
#define uDebug()
Definition: debug_utils.h:95
Uml::Visibility::toString
QString toString(Enum item, bool mnemonic)
Convert Visibility item into QString representation.
Definition: basictypes.cpp:99
UMLRole::object
UMLObject * object() const
Returns the UMLObject assigned to the role.
Definition: umlrole.cpp:76
UMLObject::emitModified
void emitModified()
Forces the emission of the modified signal.
Definition: umlobject.cpp:354
Uml::Changeability::Frozen
Definition: basictypes.h:177
Uml::AssociationType::Composition
Definition: basictypes.h:110
Uml::Changeability::Enum
Enum
Definition: basictypes.h:175
UMLObject::m_BaseType
ObjectType m_BaseType
objects type
Definition: umlobject.h:176
Uml::ID::toString
QString toString(const ID::Type &id)
Definition: basictypes.cpp:1048
UMLDoc::findObjectById
UMLObject * findObjectById(Uml::ID::Type id)
Used to find a reference to a UMLObject by its ID.
Definition: umldoc.cpp:766
UMLObject::m_name
QString m_name
objects name
Definition: umlobject.h:175
UMLObject::save
QDomElement save(const QString &tag, QDomDocument &qDoc)
Auxiliary to saveToXMI.
Definition: umlobject.cpp:808
umldoc.h
UMLRole
This class contains the non-graphic representation of an association role.
Definition: umlrole.h:24
UMLRole::setMultiplicity
void setMultiplicity(const QString &multi)
Sets the multiplicity of the role.
Definition: umlrole.cpp:139
UMLRole::role
Uml::RoleType::Enum role() const
Get the 'id' of the role (NOT the parent object).
Definition: umlrole.cpp:152
uError
#define uError()
Definition: debug_utils.h:96
UMLRole::changeability
Uml::Changeability::Enum changeability() const
Returns the Changeablity of the role.
Definition: umlrole.cpp:86
Uml::AssociationType::Relationship
Definition: basictypes.h:119
UMLObject::name
QString name() const
Returns a copy of m_name.
Definition: umlobject.cpp:185
UMLRole::saveToXMI
void saveToXMI(QDomDocument &qDoc, QDomElement &qElement)
Creates the XMI element.
Definition: umlrole.cpp:160
UMLObject::m_SecondaryId
QString m_SecondaryId
xmi.id of the secondary object for intermediate use during loading.
Definition: umlobject.h:186
Uml::ID::fromString
ID::Type fromString(const QString &id)
Definition: basictypes.cpp:1053
UMLRole::load
bool load(QDomElement &element)
Loads the XMI element.
Definition: umlrole.cpp:219
UMLObject::modified
void modified()
UMLObject::m_nId
Uml::ID::Type m_nId
object's id
Definition: umlobject.h:171
UMLObject::m_pSecondary
UMLObject * m_pSecondary
pointer to an associated object Only a few of the classes inheriting from UMLObject use this...
Definition: umlobject.h:182
uml.h
UMLObject::doc
QString doc() const
Returns the documentation for the object.
Definition: umlobject.cpp:404
UMLDoc
UMLDoc provides a document object for a document-view model.
Definition: umldoc.h:63
UMLObject::id
virtual Uml::ID::Type id() const
Returns the ID of the object.
Definition: umlobject.cpp:394
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:06:00 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

umbrello/umbrello

Skip menu "umbrello/umbrello"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • okteta
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal