bool UMLClipboard::pasteChildren(UMLListViewItem *parent, IDChangeLog *chgLog) { if (!parent) { kWarning() << "Paste Children Error, parent missing" << endl; return false; } UMLDoc *doc = UMLApp::app()->getDocument(); UMLListView *listView = UMLApp::app()->getListView(); UMLListViewItem *childItem = static_cast<UMLListViewItem*>(parent->firstChild()); while (childItem) { Uml::IDType oldID = childItem->getID(); Uml::IDType newID = chgLog->findNewID(oldID); UMLListViewItem *shouldNotExist = listView->findItem(newID); if (shouldNotExist) { kError() << "UMLClipboard::pasteChildren: new list view item " << ID2STR(newID) << " already exists (internal error)" << endl; childItem = static_cast<UMLListViewItem*>(childItem->nextSibling()); continue; } UMLObject *newObj = doc->findObjectById(newID); if (newObj) { kDebug() << "UMLClipboard::pasteChildren: adjusting lvitem(" << ID2STR(oldID) << ") to new UMLObject(" << ID2STR(newID) << ")" << endl; childItem->setUMLObject(newObj); childItem->setText(newObj->getName()); } else { kDebug() << "UMLClipboard::pasteChildren: no UMLObject found for lvitem " << ID2STR(newID) << endl; } childItem = static_cast<UMLListViewItem*>(childItem->nextSibling()); } return true; }
UMLObject* CmdBaseObjectCommand::object() { UMLDoc *doc = UMLApp::app()->document(); UMLObject *umlObject = doc->findObjectById(m_objectId); if (!umlObject) umlObject = m_object; return umlObject; }
/** * This method loads the generic parts of the XMI common to most model * classes. It is not usually reimplemented by child classes. * Instead, it invokes the load() method which implements the loading * of the specifics of each child class. * * @param element The QDomElement from which to load. */ bool UMLObject::loadFromXMI(QDomElement & element) { UMLDoc* umldoc = UMLApp::app()->document(); if (umldoc == 0) { uError() << "umldoc is NULL"; return false; } // Read the name first so that if we encounter a problem, the error // message can say the name. m_name = element.attribute(QLatin1String("name")); QString id = Model_Utils::getXmiId(element); if (id.isEmpty() || id == QLatin1String("-1")) { // Before version 1.4, Umbrello did not save the xmi.id of UMLRole objects. // Some tools (such as Embarcadero's) do not have an xmi.id on all attributes. m_nId = UniqueID::gen(); uWarning() << m_name << ": xmi.id not present, generating a new one"; } else { Uml::ID::Type nId = Uml::ID::fromString(id); if (m_BaseType == 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(nId); if (o) { uError() << "loadFromXMI(UMLRole): id " << id << " is already in use!!! Please fix your XMI file."; } } m_nId = nId; } if (element.hasAttribute(QLatin1String("documentation"))) // for bkwd compat. m_Doc = element.attribute(QLatin1String("documentation")); else m_Doc = element.attribute(QLatin1String("comment")); //CHECK: need a UML:Comment? m_visibility = Uml::Visibility::Public; if (element.hasAttribute(QLatin1String("scope"))) { // for bkwd compat. QString scope = element.attribute(QLatin1String("scope")); if (scope == QLatin1String("instance_level")) // nsuml compat. m_bStatic = false; else if (scope == QLatin1String("classifier_level")) // nsuml compat. m_bStatic = true; else { int nScope = scope.toInt(); switch (nScope) { case 200: m_visibility = Uml::Visibility::Public; break; case 201: m_visibility = Uml::Visibility::Private; break; case 202: m_visibility = Uml::Visibility::Protected; break; default: uError() << m_name << ": illegal scope " << nScope; } } } else { QString visibility = element.attribute(QLatin1String("visibility"), QLatin1String("public")); if (visibility == QLatin1String("private") || visibility == QLatin1String("private_vis")) // for compatibility with other programs m_visibility = Uml::Visibility::Private; else if (visibility == QLatin1String("protected") || visibility == QLatin1String("protected_vis")) // for compatibility with other programs m_visibility = Uml::Visibility::Protected; else if (visibility == QLatin1String("implementation")) m_visibility = Uml::Visibility::Implementation; } QString stereo = element.attribute(QLatin1String("stereotype")); if (!stereo.isEmpty()) { Uml::ID::Type stereoID = Uml::ID::fromString(stereo); m_pStereotype = umldoc->findStereotypeById(stereoID); if (m_pStereotype) { m_pStereotype->incrRefCount(); } else { uDebug() << m_name << ": UMLStereotype " << Uml::ID::toString(stereoID) << " not found, creating now."; setStereotypeCmd(stereo); } } if (element.hasAttribute(QLatin1String("abstract"))) { // for bkwd compat. QString abstract = element.attribute(QLatin1String("abstract"), QLatin1String("0")); m_bAbstract = (bool)abstract.toInt(); } else { QString isAbstract = element.attribute(QLatin1String("isAbstract"), QLatin1String("false")); m_bAbstract = (isAbstract == QLatin1String("true")); } if (element.hasAttribute(QLatin1String("static"))) { // for bkwd compat. QString staticScope = element.attribute(QLatin1String("static"), QLatin1String("0")); m_bStatic = (bool)staticScope.toInt(); } else { QString ownerScope = element.attribute(QLatin1String("ownerScope"), QLatin1String("instance")); m_bStatic = (ownerScope == QLatin1String("classifier")); } // If the node has child nodes, check whether attributes can be // extracted from them. if (element.hasChildNodes()) { QDomNode node = element.firstChild(); if (node.isComment()) node = node.nextSibling(); QDomElement elem = node.toElement(); while (!elem.isNull()) { QString tag = elem.tagName(); if (UMLDoc::tagEq(tag, QLatin1String("name"))) { m_name = elem.attribute(QLatin1String("xmi.value")); if (m_name.isEmpty()) m_name = elem.text(); } else if (UMLDoc::tagEq(tag, QLatin1String("visibility"))) { QString vis = elem.attribute(QLatin1String("xmi.value")); if (vis.isEmpty()) vis = elem.text(); if (vis == QLatin1String("private") || vis == QLatin1String("private_vis")) m_visibility = Uml::Visibility::Private; else if (vis == QLatin1String("protected") || vis == QLatin1String("protected_vis")) m_visibility = Uml::Visibility::Protected; else if (vis == QLatin1String("implementation")) m_visibility = Uml::Visibility::Implementation; } else if (UMLDoc::tagEq(tag, QLatin1String("isAbstract"))) { QString isAbstract = elem.attribute(QLatin1String("xmi.value")); if (isAbstract.isEmpty()) isAbstract = elem.text(); m_bAbstract = (isAbstract == QLatin1String("true")); } else if (UMLDoc::tagEq(tag, QLatin1String("ownerScope"))) { QString ownerScope = elem.attribute(QLatin1String("xmi.value")); if (ownerScope.isEmpty()) ownerScope = elem.text(); m_bStatic = (ownerScope == QLatin1String("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 != ot_Operation && m_BaseType != ot_Attribute && m_BaseType != ot_EnumLiteral && m_BaseType != ot_EntityAttribute && m_BaseType != ot_Template && m_BaseType != ot_Stereotype && m_BaseType != ot_Role && m_BaseType != ot_UniqueConstraint && m_BaseType != ot_ForeignKeyConstraint && m_BaseType != ot_CheckConstraint) { if (m_pUMLPackage) { m_pUMLPackage->addObject(this); } else if (umldoc->rootFolderType(this) == Uml::ModelType::N_MODELTYPES) { // m_pUMLPackage is not set on the root folders. uDebug() << m_name << ": m_pUMLPackage is not set"; } } return load(element); }
/** * Resolve referenced objects (if any.) * Needs to be called after all UML objects are loaded from file. * This needs to be done after all model objects are loaded because * some of the xmi.id's might be forward references, i.e. they may * identify model objects which were not yet loaded at the point of * reference. * The default implementation attempts resolution of the m_SecondaryId. * * @return True for success. */ bool UMLObject::resolveRef() { if (m_pSecondary || (m_SecondaryId.isEmpty() && m_SecondaryFallback.isEmpty())) { maybeSignalObjectCreated(); return true; } #ifdef VERBOSE_DEBUGGING uDebug() << m_name << ": m_SecondaryId is " << m_SecondaryId; #endif UMLDoc *pDoc = UMLApp::app()->document(); // 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(Uml::ID::fromString(m_SecondaryId)); if (m_pSecondary != NULL) { if (m_pSecondary->baseType() == ot_Stereotype) { m_pStereotype = dynamic_cast<UMLStereotype*>(m_pSecondary.data()); m_pStereotype->incrRefCount(); m_pSecondary = NULL; } m_SecondaryId = QString(); maybeSignalObjectCreated(); return true; } if (m_SecondaryFallback.isEmpty()) { uDebug() << "object with xmi.id=" << m_SecondaryId << " not found, setting to undef"; UMLFolder *datatypes = pDoc->datatypeFolder(); m_pSecondary = Object_Factory::createUMLObject(ot_Datatype, QLatin1String("undef"), datatypes, false); return true; } } if (m_SecondaryFallback.isEmpty()) { uError() << m_name << ": cannot find type with id " << m_SecondaryId; return false; } #ifdef VERBOSE_DEBUGGING uDebug() << m_name << ": could not resolve secondary ID " << m_SecondaryId << ", using secondary fallback " << m_SecondaryFallback; #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, ot_UMLObject, this); if (m_pSecondary) { m_SecondaryId = QString(); maybeSignalObjectCreated(); return true; } // Work around Object_Factory::createUMLObject()'s incapability // of on-the-fly scope creation: if (m_SecondaryId.contains(QLatin1String("::"))) { // TODO: Merge Import_Utils::createUMLObject() into Object_Factory::createUMLObject() m_pSecondary = Import_Utils::createUMLObject(ot_UMLObject, m_SecondaryId, m_pUMLPackage); if (m_pSecondary) { if (Import_Utils::newUMLObjectWasCreated()) { maybeSignalObjectCreated(); qApp->processEvents(); uDebug() << "Import_Utils::createUMLObject() created a new type for " << m_SecondaryId; } else { uDebug() << "Import_Utils::createUMLObject() returned an existing type for " << m_SecondaryId; } m_SecondaryId = QString(); return true; } uError() << "Import_Utils::createUMLObject() failed to create a new type for " << m_SecondaryId; return false; } uDebug() << "Creating new type for " << m_SecondaryId; // 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(QLatin1Char('*')) || m_SecondaryId.contains(QLatin1Char('&'))); ObjectType ot = ot_Class; if (isReferenceType) { ot = ot_Datatype; } else { if (Model_Utils::isCommonDataType(m_SecondaryId)) ot = ot_Datatype; } m_pSecondary = Object_Factory::createUMLObject(ot, m_SecondaryId, NULL); if (m_pSecondary == NULL) return false; m_SecondaryId = QString(); maybeSignalObjectCreated(); //qApp->processEvents(); return true; }
/** * Creates the <UML:Generalization> or <UML:Association> XMI element * including its role objects. */ bool UMLAssociation::load( QDomElement & element ) { if (id() == Uml::id_None) return false; // old style XMI file. No real info in this association. UMLDoc * doc = UMLApp::app()->document(); UMLObject * obj[2] = { NULL, NULL }; if (m_AssocType == Uml::AssociationType::Generalization || m_AssocType == Uml::AssociationType::Realization || m_AssocType == Uml::AssociationType::Dependency || m_AssocType == Uml::AssociationType::Child2Category || m_AssocType == Uml::AssociationType::Category2Parent ) { for (unsigned r = Uml::A; r <= Uml::B; ++r) { const QString fetch = (m_AssocType == Uml::AssociationType::Generalization ? r == Uml::A ? "child" : "parent" : r == Uml::A ? "client" : "supplier"); QString roleIdStr = element.attribute(fetch, ""); if (roleIdStr.isEmpty()) { // Might be given as a child node instead - see below. continue; } // set umlobject of role if possible (else defer resolution) obj[r] = doc->findObjectById(STR2ID(roleIdStr)); Uml::Role_Type role = (Uml::Role_Type)r; if (obj[r] == NULL) { m_pRole[role]->setSecondaryId(roleIdStr); // defer to resolveRef() } else { m_pRole[role]->setObject(obj[r]); if (m_pUMLPackage == NULL) { Uml::ModelType mt = Model_Utils::convert_OT_MT(obj[r]->baseType()); m_pUMLPackage = doc->rootFolder(mt); uDebug() << "assoctype " << m_AssocType << ": setting model type " << mt; } } } if (obj[A] == NULL || obj[B] == NULL) { for (QDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling()) { if (node.isComment()) continue; QDomElement tempElement = node.toElement(); QString tag = tempElement.tagName(); if (Model_Utils::isCommonXMIAttribute(tag)) continue; // Permitted tag names: // roleA: "child" "subtype" "client" // roleB: "parent" "supertype" "supplier" QString idStr = tempElement.attribute( "xmi.id", "" ); if (idStr.isEmpty()) idStr = tempElement.attribute( "xmi.idref", "" ); if (idStr.isEmpty()) { QDomNode inner = node.firstChild(); QDomElement tmpElem = inner.toElement(); idStr = tmpElem.attribute( "xmi.id", "" ); if (idStr.isEmpty()) idStr = tmpElem.attribute( "xmi.idref", "" ); } if (idStr.isEmpty()) { uError() << "type " << m_AssocType << ", id " << ID2STR(id()) << ": " << "xmi id not given for " << tag; continue; } // Since we know for sure that we're dealing with a non // umbrello file, use deferred resolution unconditionally. if (UMLDoc::tagEq(tag, "child") || UMLDoc::tagEq(tag, "subtype") || UMLDoc::tagEq(tag, "client")) { getUMLRole(A)->setSecondaryId(idStr); } else { getUMLRole(B)->setSecondaryId(idStr); } } } // it is a realization if either endpoint is an interface if (isRealization(obj[A], obj[B])) { m_AssocType = Uml::AssociationType::Realization; } return true; } for (QDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling()) { // uml13.dtd compliant format (new style) if (node.isComment()) continue; QDomElement tempElement = node.toElement(); QString tag = tempElement.tagName(); if (Model_Utils::isCommonXMIAttribute(tag)) continue; if (!UMLDoc::tagEq(tag, "Association.connection") && !UMLDoc::tagEq(tag, "Namespace.ownedElement") && !UMLDoc::tagEq(tag, "Namespace.contents")) { uWarning() << "unknown child node " << tag; continue; } // Load role A. node = tempElement.firstChild(); while (node.isComment()) node = node.nextSibling(); tempElement = node.toElement(); if (tempElement.isNull()) { uWarning() << "UML:Association : element (A) is Null"; return false; } tag = tempElement.tagName(); if (!UMLDoc::tagEq(tag, "AssociationEndRole") && !UMLDoc::tagEq(tag, "AssociationEnd")) { uWarning() << "unknown child (A) tag " << tag; return false; } if (! getUMLRole(A)->loadFromXMI(tempElement)) return false; // Load role B. node = node.nextSibling(); while (node.isComment()) node = node.nextSibling(); tempElement = node.toElement(); if (tempElement.isNull()) { uWarning() << "UML:Association : element (B) is Null"; return false; } tag = tempElement.tagName(); if (!UMLDoc::tagEq(tag, "AssociationEndRole") && !UMLDoc::tagEq(tag, "AssociationEnd")) { uWarning() << "unknown child (B) tag " << tag; return false; } if (! getUMLRole(B)->loadFromXMI(tempElement)) return false; if (m_pUMLPackage == NULL) { Uml::ModelType mt = Model_Utils::convert_OT_MT(getObject(B)->baseType()); m_pUMLPackage = doc->rootFolder(mt); uDebug() << "setting model type " << mt; } // setting the association type: // // In the old days, we could just record this on the association, // and be done with it. But thats not how the UML13.dtd does things. // As a result, we are checking roleA for information about the // parent association (!) which by this point in the parse, should // be set. However, the information that the roles are allowed to have // is not complete, so we need to finish the analysis here. // find self-associations if (m_AssocType == Uml::AssociationType::Association && getObjectId(A) == getObjectId(B)) m_AssocType = Uml::AssociationType::Association_Self; // fall-back default type if (m_AssocType == Uml::AssociationType::Unknown) { m_AssocType = Uml::AssociationType::Association; } return true; } // From here on it's old-style stuff. QString assocTypeStr = element.attribute( "assoctype", "-1" ); Uml::AssociationType assocType = Uml::AssociationType::Unknown; if (assocTypeStr[0] >= 'a' && assocTypeStr[0] <= 'z') { // In an earlier version, the natural assoctype names were saved. const QString assocTypeString[] = { "generalization", // Uml::AssociationType::Generalization "aggregation", // Uml::AssociationType::Aggregation "dependency", // Uml::AssociationType::Dependency "association", // Uml::AssociationType::Association "associationself", // Uml::AssociationType::Association_Self "collmessage", // Uml::AssociationType::Coll_Message "seqmessage", // Uml::AssociationType::Seq_Message "collmessageself", // Uml::AssociationType::Coll_Message_Self "seqmessageself", // Uml::AssociationType::Seq_Message_Self "implementation", // Uml::AssociationType::Implementation "composition", // Uml::AssociationType::Composition "realization", // Uml::AssociationType::Realization "uniassociation", // Uml::AssociationType::UniAssociation "anchor", // Uml::AssociationType::Anchor "state", // Uml::AssociationType::State "activity", // Uml::AssociationType::Activity "exception", // Uml::AssociationType::Exception "category2parent" // Uml::AssociationType::Category2Parent "child2category" // Uml::AssociationType::Child2Category "relationship" // Uml::AssociationType::Relationship }; const int arraySize = sizeof(assocTypeString)/sizeof(QString); uDebug() << "AssociationType string array size = " << arraySize; int index; for (index = 0; index < arraySize; ++index) if (assocTypeStr == assocTypeString[index]) break; if (index < arraySize) assocType = Uml::AssociationType::Value(index); } else { int assocTypeNum = assocTypeStr.toInt(); if (assocTypeNum < (int)Uml::AssociationType::Generalization || // first enum assocTypeNum > (int)Uml::AssociationType::Relationship) { // last enum uWarning() << "bad assoctype of UML:AssociationType " << ID2STR(id()); return false; } assocType = Uml::AssociationType::Value(assocTypeNum); } setAssociationType( assocType ); Uml::IDType roleAObjID = STR2ID(element.attribute( "rolea", "-1" )); Uml::IDType roleBObjID = STR2ID(element.attribute( "roleb", "-1" )); if (assocType == Uml::AssociationType::Aggregation || assocType == Uml::AssociationType::Composition) { // Flip roles to compensate for changed diamond logic in AssociationLine. // For further explanations see AssociationWidget::loadFromXMI. Uml::IDType tmp = roleAObjID; roleAObjID = roleBObjID; roleBObjID = tmp; } UMLObject * objA = doc->findObjectById(roleAObjID); UMLObject * objB = doc->findObjectById(roleBObjID); if(objA) getUMLRole(A)->setObject(objA); else return false; if(objB) getUMLRole(B)->setObject(objB); else return false; setMulti(element.attribute( "multia", "" ), A); setMulti(element.attribute( "multib", "" ), B); setRoleName(element.attribute( "namea", "" ), A); setRoleName(element.attribute( "nameb", "" ), B); setRoleDoc(element.attribute( "doca", "" ), A); setRoleDoc(element.attribute( "docb", "" ), B); // Visibility defaults to Public if it cant set it here.. QString visibilityA = element.attribute( "visibilitya", "0"); QString visibilityB = element.attribute( "visibilityb", "0"); int vis = visibilityA.toInt(); if (vis >= 200) // bkwd compat. vis -= 200; setVisibility((Uml::Visibility::Value)vis, A); vis = visibilityB.toInt(); if (vis >= 200) // bkwd compat. vis -= 200; setVisibility((Uml::Visibility::Value)vis, B); // Changeability defaults to Changeable if it cant set it here.. QString changeabilityA = element.attribute( "changeabilitya", "0"); QString changeabilityB = element.attribute( "changeabilityb", "0"); if (changeabilityA.toInt() > 0) setChangeability(Uml::Changeability(Uml::Changeability::Value(changeabilityA.toInt())), A); if (changeabilityB.toInt() > 0) setChangeability(Uml::Changeability(Uml::Changeability::Value(changeabilityB.toInt())), B); return true; }
/** * Loads the <UML:AssociationEnd> XMI element. * Auxiliary to UMLObject::loadFromXMI. */ bool UMLRole::load(QDomElement & element) { UMLDoc * doc = UMLApp::app()->document(); QString type = element.attribute(QLatin1String("type")); if (!type.isEmpty()) { if (!m_SecondaryId.isEmpty()) uWarning() << "overwriting old m_SecondaryId \"" << m_SecondaryId << " with new value \"" << type << "\""; m_SecondaryId = type; } // Inspect child nodes - for multiplicity (and type if not set above.) for (QDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling()) { if (node.isComment()) continue; QDomElement tempElement = node.toElement(); QString tag = tempElement.tagName(); if (UMLDoc::tagEq(tag, QLatin1String("name"))) { m_name = tempElement.text(); } else if (UMLDoc::tagEq(tag, QLatin1String("AssociationEnd.multiplicity"))) { /* * There are different ways in which the multiplicity might be given: * - direct value in the <AssociationEnd.multiplicity> tag, * - attributes "lower" and "upper" of a subordinate <MultiplicityRange>, * - direct value in subordinate <MultiplicityRange.lower> and * <MultiplicityRange.upper> tags */ QDomNode n = tempElement.firstChild(); if (node.isNull() || tempElement.isNull() || n.isNull() || n.toElement().isNull()) { m_Multi = tempElement.text().trimmed(); continue; } tempElement = n.toElement(); tag = tempElement.tagName(); if (!UMLDoc::tagEq(tag, QLatin1String("Multiplicity"))) { m_Multi = tempElement.text().trimmed(); continue; } n = tempElement.firstChild(); tempElement = n.toElement(); tag = tempElement.tagName(); if (!UMLDoc::tagEq(tag, QLatin1String("Multiplicity.range"))) { m_Multi = tempElement.text().trimmed(); continue; } n = tempElement.firstChild(); tempElement = n.toElement(); tag = tempElement.tagName(); if (!UMLDoc::tagEq(tag, QLatin1String("MultiplicityRange"))) { m_Multi = tempElement.text().trimmed(); continue; } QString multiUpper; if (tempElement.hasAttribute(QLatin1String("lower"))) { m_Multi = tempElement.attribute(QLatin1String("lower")); multiUpper = tempElement.attribute(QLatin1String("upper")); if (!multiUpper.isEmpty()) { if (!m_Multi.isEmpty()) m_Multi.append(QLatin1String("..")); m_Multi.append(multiUpper); } continue; } n = tempElement.firstChild(); while (!n.isNull()) { tempElement = n.toElement(); tag = tempElement.tagName(); if (UMLDoc::tagEq(tag, QLatin1String("MultiplicityRange.lower"))) { m_Multi = tempElement.text(); } else if (UMLDoc::tagEq(tag, QLatin1String("MultiplicityRange.upper"))) { multiUpper = tempElement.text(); } n = n.nextSibling(); } if (!multiUpper.isEmpty()) { if (!m_Multi.isEmpty()) m_Multi.append(QLatin1String("..")); m_Multi.append(multiUpper); } } else if (m_SecondaryId.isEmpty() && (UMLDoc::tagEq(tag, QLatin1String("type")) || UMLDoc::tagEq(tag, QLatin1String("participant")))) { m_SecondaryId = tempElement.attribute(QLatin1String("xmi.id")); if (m_SecondaryId.isEmpty()) m_SecondaryId = tempElement.attribute(QLatin1String("xmi.idref")); if (m_SecondaryId.isEmpty()) { QDomNode inner = tempElement.firstChild(); QDomElement innerElem = inner.toElement(); m_SecondaryId = innerElem.attribute(QLatin1String("xmi.id")); if (m_SecondaryId.isEmpty()) m_SecondaryId = innerElem.attribute(QLatin1String("xmi.idref")); } } } if (!m_Multi.isEmpty()) uDebug() << name() << ": m_Multi is " << m_Multi; if (m_SecondaryId.isEmpty()) { uError() << name() << ": type not given or illegal"; return false; } UMLObject * obj; obj = doc->findObjectById(Uml::ID::fromString(m_SecondaryId)); if (obj) { m_pSecondary = obj; m_SecondaryId = QString(); } // block signals to prevent needless updating blockSignals(true); // Here comes the handling of the association type. // This is open for discussion - I'm pretty sure there are better ways.. // Yeah, for one, setting the *parent* object parameters from here is sucky // as hell. Why are we using roleA to store what is essentially a parent (association) // parameter, eh? The UML13.dtd is pretty silly, but since that is what // is driving us to that point, we have to go with it. Some analysis of // the component roles/linked items needs to be done in order to get things // right. *sigh* -b.t. // Setting association type from the role (A) // Determination of the "aggregation" attribute used to be done only // when (m_role == Uml::RoleType::A) but some XMI writers (e.g. StarUML) place // the aggregation attribute at role B. // The role end with the aggregation unequal to "none" wins. QString aggregation = element.attribute(QLatin1String("aggregation"), QLatin1String("none")); if (aggregation == QLatin1String("composite")) m_pAssoc->setAssociationType(Uml::AssociationType::Composition); else if (aggregation == QLatin1String("shared") // UML1.3 || aggregation == QLatin1String("aggregate")) // UML1.4 m_pAssoc->setAssociationType(Uml::AssociationType::Aggregation); if (!element.hasAttribute(QLatin1String("isNavigable"))) { // Backward compatibility mode: In Umbrello version 1.3.x the // logic for saving the isNavigable flag was wrong. // May happen on loading role A. m_pAssoc->setOldLoadMode(true); } else if (m_pAssoc->getOldLoadMode() == true) { // Here is the original logic: // "Role B: // If isNavigable is not given, we make no change to the // association type. // If isNavigable is given, and is "true", then we assume that // the association's other end (role A) is not navigable, and // therefore we change the association type to UniAssociation. // The case that isNavigable is given as "false" is ignored. // Combined with the association type logic for role A, this // allows us to support at_Association and at_UniAssociation." if (element.attribute(QLatin1String("isNavigable")) == QLatin1String("true")) m_pAssoc->setAssociationType(Uml::AssociationType::UniAssociation); } else if (element.attribute(QLatin1String("isNavigable")) == QLatin1String("false")) { m_pAssoc->setAssociationType(Uml::AssociationType::UniAssociation); } //FIXME not standard XMI if (element.hasAttribute(QLatin1String("relationship"))) { if (element.attribute(QLatin1String("relationship")) == QLatin1String("true")) { m_pAssoc->setAssociationType(Uml::AssociationType::Relationship); } } if (m_Multi.isEmpty()) m_Multi = element.attribute(QLatin1String("multiplicity")); // Changeability defaults to Changeable if it cant set it here.. m_Changeability = Uml::Changeability::Changeable; QString changeability = element.attribute(QLatin1String("changeability")); if (changeability.isEmpty()) element.attribute(QLatin1String("changeable")); // for backward compatibility if (changeability == QLatin1String("frozen")) m_Changeability = Uml::Changeability::Frozen; else if (changeability == QLatin1String("addOnly")) m_Changeability = Uml::Changeability::AddOnly; // finished config, now unblock blockSignals(false); return true; }
UMLWidget* makeWidgetFromXMI(const QString& tag, const QString& idStr, UMLView *view) { UMLWidget *widget = NULL; // Loading of widgets which do NOT represent any UMLObject, // just graphic stuff with no real model information //FIXME while boxes and texts are just diagram objects, activities and // states should be UMLObjects if (tag == "statewidget" || tag == "UML:StateWidget") { widget = new StateWidget(view, StateWidget::Normal, Uml::id_Reserved); } else if (tag == "notewidget" || tag == "UML:NoteWidget") { widget = new NoteWidget(view, NoteWidget::Normal, Uml::id_Reserved); } else if (tag == "boxwidget") { widget = new BoxWidget(view, Uml::id_Reserved); } else if (tag == "floatingtext" || tag == "UML:FloatingTextWidget") { widget = new FloatingTextWidget(view, Uml::tr_Floating, "", Uml::id_Reserved); } else if (tag == "activitywidget" || tag == "UML:ActivityWidget") { widget = new ActivityWidget(view, ActivityWidget::Initial, Uml::id_Reserved); } else if (tag == "messagewidget") { widget = new MessageWidget(view, Uml::sequence_message_asynchronous, Uml::id_Reserved); } else if (tag == "forkjoin") { widget = new ForkJoinWidget(view, false, Uml::id_Reserved); } else if (tag == "preconditionwidget") { widget = new PreconditionWidget(view, NULL, Uml::id_Reserved); } else if (tag == "combinedFragmentwidget") { widget = new CombinedFragmentWidget(view, CombinedFragmentWidget::Ref, Uml::id_Reserved); } else if (tag == "signalwidget") { widget = new SignalWidget(view, SignalWidget::Send, Uml::id_Reserved); } else if (tag == "floatingdashlinewidget") { widget = new FloatingDashLineWidget(view, Uml::id_Reserved); } else if (tag == "objectnodewidget") { widget = new ObjectNodeWidget(view, ObjectNodeWidget::Normal, Uml::id_Reserved); } else if (tag == "regionwidget") { widget = new RegionWidget(view, Uml::id_Reserved); } else if (tag == "pinwidget") { widget = new PinWidget(view, NULL, Uml::id_Reserved); } else { // Loading of widgets which represent an UMLObject // Find the UMLObject and create the Widget to represent it Uml::IDType id = STR2ID(idStr); UMLDoc *umldoc = UMLApp::app()->document(); UMLObject *o = umldoc->findObjectById(id); if (o == NULL) { uDebug() << "makeWidgetFromXMI: cannot find object with id " << ID2STR(id) << endl; } if (tag == "actorwidget" || tag == "UML:ActorWidget") { if (validateObjType(Uml::ot_Actor, o, id)) widget = new ActorWidget(view, static_cast<UMLActor*>(o)); } else if (tag == "usecasewidget" || tag == "UML:UseCaseWidget") { if (validateObjType(Uml::ot_UseCase, o, id)) widget = new UseCaseWidget(view, static_cast<UMLUseCase*>(o)); } else if (tag == "classwidget" || tag == "UML:ClassWidget") { if (validateObjType(Uml::ot_Class, o, id)) widget = new ClassifierWidget(view, static_cast<UMLClassifier*>(o)); } else if (tag == "packagewidget") { if (validateObjType(Uml::ot_Package, o, id)) widget = new PackageWidget(view, static_cast<UMLPackage*>(o)); } else if (tag == "componentwidget") { if (validateObjType(Uml::ot_Component, o, id)) widget = new ComponentWidget(view, static_cast<UMLComponent*>(o)); } else if (tag == "nodewidget") { if (validateObjType(Uml::ot_Node, o, id)) widget = new NodeWidget(view, static_cast<UMLNode*>(o)); } else if (tag == "artifactwidget") { if (validateObjType(Uml::ot_Artifact, o, id)) widget = new ArtifactWidget(view, static_cast<UMLArtifact*>(o)); } else if (tag == "interfacewidget") { if (validateObjType(Uml::ot_Interface, o, id)) widget = new ClassifierWidget(view, static_cast<UMLClassifier*>(o)); } else if (tag == "datatypewidget") { if (validateObjType(Uml::ot_Datatype, o, id)) widget = new DatatypeWidget(view, static_cast<UMLClassifier*>(o)); } else if (tag == "enumwidget") { if (validateObjType(Uml::ot_Enum, o, id)) widget = new EnumWidget(view, static_cast<UMLEnum*>(o)); } else if (tag == "entitywidget") { if (validateObjType(Uml::ot_Entity, o, id)) widget = new EntityWidget(view, static_cast<UMLEntity*>(o)); } else if (tag == "categorywidget") { if (validateObjType(Uml::ot_Category, o, id)) widget = new CategoryWidget(view, static_cast<UMLCategory*>(o)); } else if (tag == "objectwidget" || tag == "UML:ObjectWidget") { widget = new ObjectWidget(view, o ); } else { uWarning() << "Trying to create an unknown widget:" << tag; } } return widget; }