/** * Adds an AssociationWidget to the association list and creates the * corresponding UMLAssociation in the current UMLDoc. * If the association can't be added, is deleted. * * @param assoc The AssociationWidget to add. * @return True on success */ bool ToolBarStateAssociation::addAssociationInViewAndDoc(AssociationWidget* assoc) { // append in view if (m_pUMLScene->addAssociation(assoc, false)) { // if view went ok, then append in document UMLAssociation *umla = assoc->association(); if (umla) { // association with model representation in UMLDoc Uml::ModelType::Enum m = Model_Utils::convert_DT_MT(m_pUMLScene->type()); UMLDoc *umldoc = UMLApp::app()->document(); umla->setUMLPackage(umldoc->rootFolder(m)); umldoc->addAssociation(umla); } return true; } else { uError() << "cannot addAssocInViewAndDoc(), deleting"; delete assoc; return false; } }
/** * Parse a file into the PetalNode internal tree representation * and then create Umbrello objects by traversing the tree. * * @return In case of error: NULL * In case of success with non NULL parentPkg: pointer to UMLPackage created for controlled unit * In case of success with NULL parentPkg: pointer to root folder of Logical View */ UMLPackage* loadFromMDL(QFile& file, UMLPackage *parentPkg /* = 0 */) { if (parentPkg == NULL) { QString fName = file.fileName(); int lastSlash = fName.lastIndexOf(QLatin1Char('/')); if (lastSlash > 0) { dirPrefix = fName.left(lastSlash + 1); } } QTextStream stream(&file); stream.setCodec("ISO 8859-1"); QString line; PetalNode *root = NULL; uint nClosures_sav = nClosures; uint linum_sav = linum; nClosures = 0; linum = 0; while (!(line = stream.readLine()).isNull()) { linum++; if (line.contains(QRegExp(QLatin1String("^\\s*\\(object Petal")))) { bool finish = false; // Nested loop determines character set to use while (!(line = stream.readLine()).isNull()) { linum++; // CHECK: do we need petal version info? if (line.contains(QLatin1Char(')'))) { finish = true; line = line.replace(QLatin1String(QLatin1String(")")), QString()); } QStringList a = line.trimmed().split(QRegExp(QLatin1String("\\s+"))); if (a.size() == 2 && a[0] == QLatin1String("charSet")) { const QString& charSet = a[1]; if (!charSet.contains(QRegExp(QLatin1String("^\\d+$")))) { uWarning() << "Unimplemented charSet " << charSet; if (finish) break; continue; } const int charSetNum = charSet.toInt(); switch (charSetNum) { case 0: // ASCII ; case 1: // Default SETCODEC("System"); case 2: // Symbol ; // @todo SETCODEC("what"); case 77: // Mac SETCODEC("macintosh"); case 128: // ShiftJIS (Japanese) SETCODEC("Shift_JIS"); case 129: // Hangul (Korean) SETCODEC("EUC-KR"); case 130: // Johab (Korean) SETCODEC("EUC-KR"); case 134: // GB2312 (Chinese) SETCODEC("GB18030"); // "Don't use GB2312 here" (Ralf H.) case 136: // ChineseBig5 SETCODEC("Big5"); case 161: // Greek SETCODEC("windows-1253"); case 162: // Turkish SETCODEC("windows-1254"); case 163: // Vietnamese SETCODEC("windows-1258"); case 177: // Hebrew SETCODEC("windows-1255"); case 178: // Arabic SETCODEC("windows-1256"); case 186: // Baltic SETCODEC("windows-1257"); case 204: // Russian SETCODEC("windows-1251"); case 222: // Thai SETCODEC("TIS-620"); case 238: // EastEurope SETCODEC("windows-1250"); case 255: // OEM (extended ASCII) SETCODEC("windows-1252"); default: uWarning() << "Unimplemented charSet number" << charSetNum; } } if (finish) break; } if (line.isNull()) break; } else { QRegExp objectRx(QLatin1String("^\\s*\\(object ")); if (line.contains(objectRx)) { nClosures = 0; QStringList initialArgs = scan(line); initialArgs.pop_front(); // remove opening parenthesis root = readAttributes(initialArgs, stream); break; } } } file.close(); nClosures = nClosures_sav; linum = linum_sav; if (root == NULL) return NULL; if (parentPkg) { UMLPackage *child = petalTree2Uml(root, parentPkg); delete root; return child; } if (root->name() != QLatin1String("Design")) { uError() << "expecting root name Design"; delete root; return NULL; } Import_Utils::assignUniqueIdOnCreation(false); UMLDoc *umldoc = UMLApp::app()->document(); //*************************** import Logical View ********************************* umldoc->setCurrentRoot(Uml::ModelType::Logical); UMLPackage *logicalView = umldoc->rootFolder(Uml::ModelType::Logical); importView(root, logicalView, QLatin1String("root_category"), QLatin1String("logical_models"), QLatin1String("Class_Category"), QLatin1String("logical_presentations")); //*************************** import Use Case View ******************************** umldoc->setCurrentRoot(Uml::ModelType::UseCase); UMLPackage *useCaseView = umldoc->rootFolder(Uml::ModelType::UseCase); importView(root, useCaseView, QLatin1String("root_usecase_package"), QLatin1String("logical_models"), QLatin1String("Class_Category"), QLatin1String("logical_presentations")); //*************************** import Component View ******************************* umldoc->setCurrentRoot(Uml::ModelType::Component); UMLPackage *componentView = umldoc->rootFolder(Uml::ModelType::Component); importView(root, componentView, QLatin1String("root_subsystem"), QLatin1String("physical_models"), QLatin1String("SubSystem"), QLatin1String("physical_presentations")); //*************************** import Deployment View ****************************** umldoc->setCurrentRoot(Uml::ModelType::Deployment); UMLPackage *deploymentView = umldoc->rootFolder(Uml::ModelType::Deployment); importView(root, deploymentView, QLatin1String("process_structure"), QLatin1String("ProcsNDevs"), QLatin1String("Processes")); //*************************** wrap up ******************************** delete root; umldoc->setCurrentRoot(Uml::ModelType::Logical); Import_Utils::assignUniqueIdOnCreation(true); umldoc->resolveTypes(); return logicalView; }
/** * Implement abstract operation from NativeImportBase. */ bool AdaImport::parseStmt() { const int srcLength = m_source.count(); QString keyword = m_source[m_srcIndex]; UMLDoc *umldoc = UMLApp::app()->document(); //uDebug() << '"' << keyword << '"'; if (keyword == QLatin1String("with")) { if (m_inGenericFormalPart) { // mapping of generic formal subprograms or packages is not yet implemented return false; } while (++m_srcIndex < srcLength && m_source[m_srcIndex] != QLatin1String(";")) { QStringList components = m_source[m_srcIndex].toLower().split(QLatin1Char('.')); const QString& prefix = components.first(); if (prefix == QLatin1String("system") || prefix == QLatin1String("ada") || prefix == QLatin1String("gnat") || prefix == QLatin1String("interfaces") || prefix == QLatin1String("text_io") || prefix == QLatin1String("unchecked_conversion") || prefix == QLatin1String("unchecked_deallocation")) { if (advance() != QLatin1String(",")) break; continue; } parseStems(components); if (advance() != QLatin1String(",")) break; } return true; } if (keyword == QLatin1String("generic")) { m_inGenericFormalPart = true; return true; } if (keyword == QLatin1String("package")) { const QString& name = advance(); QStringList parentPkgs = name.toLower().split(QLatin1Char('.')); parentPkgs.pop_back(); // exclude the current package parseStems(parentPkgs); UMLObject *ns = NULL; if (advance() == QLatin1String("is")) { ns = Import_Utils::createUMLObject(UMLObject::ot_Package, name, currentScope(), m_comment); if (m_source[m_srcIndex + 1] == QLatin1String("new")) { m_srcIndex++; QString pkgName = advance(); UMLObject *gp = Import_Utils::createUMLObject(UMLObject::ot_Package, pkgName, currentScope()); gp->setStereotype(QLatin1String("generic")); // Add binding from instantiator to instantiatee UMLAssociation *assoc = new UMLAssociation(Uml::AssociationType::Dependency, ns, gp); assoc->setUMLPackage(umldoc->rootFolder(Uml::ModelType::Logical)); assoc->setStereotype(QLatin1String("bind")); // Work around missing display of stereotype in AssociationWidget: assoc->setName(assoc->stereotype(true)); umldoc->addAssociation(assoc); skipStmt(); } else { pushScope(static_cast<UMLPackage*>(ns)); } } else if (m_source[m_srcIndex] == QLatin1String("renames")) { m_renaming[name] = advance(); } else { uError() << "unexpected: " << m_source[m_srcIndex]; skipStmt(QLatin1String("is")); } if (m_inGenericFormalPart) { if (ns) ns->setStereotype(QLatin1String("generic")); m_inGenericFormalPart = false; } return true; } if (m_inGenericFormalPart) return false; // skip generic formal parameter (not yet implemented) if (keyword == QLatin1String("subtype")) { QString name = advance(); advance(); // "is" QString base = expand(advance()); base.remove(QLatin1String("Standard."), Qt::CaseInsensitive); UMLObject *type = umldoc->findUMLObject(base, UMLObject::ot_UMLObject, currentScope()); if (type == NULL) { type = Import_Utils::createUMLObject(UMLObject::ot_Datatype, base, currentScope()); } UMLObject *subtype = Import_Utils::createUMLObject(type->baseType(), name, currentScope(), m_comment); UMLAssociation *assoc = new UMLAssociation(Uml::AssociationType::Dependency, subtype, type); assoc->setUMLPackage(umldoc->rootFolder(Uml::ModelType::Logical)); assoc->setStereotype(QLatin1String("subtype")); // Work around missing display of stereotype in AssociationWidget: assoc->setName(assoc->stereotype(true)); umldoc->addAssociation(assoc); skipStmt(); return true; } if (keyword == QLatin1String("type")) { QString name = advance(); QString next = advance(); if (next == QLatin1String("(")) { uDebug() << name << ": discriminant handling is not yet implemented"; // @todo Find out how to map discriminated record to UML. // For now, we just create a pro forma empty record. Import_Utils::createUMLObject(UMLObject::ot_Class, name, currentScope(), m_comment, QLatin1String("record")); skipStmt(QLatin1String("end")); if ((next = advance()) == QLatin1String("case")) m_srcIndex += 2; // skip "case" ";" skipStmt(); return true; } if (next == QLatin1String(";")) { // forward declaration Import_Utils::createUMLObject(UMLObject::ot_Class, name, currentScope(), m_comment); return true; } if (next != QLatin1String("is")) { uError() << "expecting \"is\""; return false; } next = advance(); if (next == QLatin1String("(")) { // enum type UMLObject *ns = Import_Utils::createUMLObject(UMLObject::ot_Enum, name, currentScope(), m_comment); UMLEnum *enumType = static_cast<UMLEnum*>(ns); while ((next = advance()) != QLatin1String(")")) { Import_Utils::addEnumLiteral(enumType, next, m_comment); m_comment.clear(); if (advance() != QLatin1String(",")) break; } skipStmt(); return true; } bool isTaggedType = false; if (next == QLatin1String("abstract")) { m_isAbstract = true; next = advance(); } if (next == QLatin1String("tagged")) { isTaggedType = true; next = advance(); } if (next == QLatin1String("limited") || next == QLatin1String("task") || next == QLatin1String("protected") || next == QLatin1String("synchronized")) { next = advance(); // we can't (yet?) represent that } if (next == QLatin1String("private") || next == QLatin1String("interface") || next == QLatin1String("record") || (next == QLatin1String("null") && m_source[m_srcIndex+1] == QLatin1String("record"))) { UMLObject::ObjectType t = (next == QLatin1String("interface") ? UMLObject::ot_Interface : UMLObject::ot_Class); UMLObject *ns = Import_Utils::createUMLObject(t, name, currentScope(), m_comment); if (t == UMLObject::ot_Interface) { while ((next = advance()) == QLatin1String("and")) { UMLClassifier *klass = static_cast<UMLClassifier*>(ns); QString base = expand(advance()); UMLObject *p = Import_Utils::createUMLObject(UMLObject::ot_Interface, base, currentScope()); UMLClassifier *parent = static_cast<UMLClassifier*>(p); Import_Utils::createGeneralization(klass, parent); } } else { ns->setAbstract(m_isAbstract); } m_isAbstract = false; if (isTaggedType) { if (! m_classesDefinedInThisScope.contains(ns)) m_classesDefinedInThisScope.append(ns); } else { ns->setStereotype(QLatin1String("record")); } if (next == QLatin1String("record")) m_klass = static_cast<UMLClassifier*>(ns); else skipStmt(); return true; } if (next == QLatin1String("new")) { QString base = expand(advance()); QStringList baseInterfaces; while ((next = advance()) == QLatin1String("and")) { baseInterfaces.append(expand(advance())); } const bool isExtension = (next == QLatin1String("with")); UMLObject::ObjectType t; if (isExtension || m_isAbstract) { t = UMLObject::ot_Class; } else { base.remove(QLatin1String("Standard."), Qt::CaseInsensitive); UMLObject *known = umldoc->findUMLObject(base, UMLObject::ot_UMLObject, currentScope()); t = (known ? known->baseType() : UMLObject::ot_Datatype); } UMLObject *ns = Import_Utils::createUMLObject(t, base, NULL); UMLClassifier *parent = static_cast<UMLClassifier*>(ns); ns = Import_Utils::createUMLObject(t, name, currentScope(), m_comment); if (isExtension) { next = advance(); if (next == QLatin1String("null") || next == QLatin1String("record")) { UMLClassifier *klass = static_cast<UMLClassifier*>(ns); Import_Utils::createGeneralization(klass, parent); if (next == QLatin1String("record")) { // Set the m_klass for attributes. m_klass = klass; } if (baseInterfaces.count()) { t = UMLObject::ot_Interface; QStringList::Iterator end(baseInterfaces.end()); for (QStringList::Iterator bi(baseInterfaces.begin()); bi != end; ++bi) { ns = Import_Utils::createUMLObject(t, *bi, currentScope()); parent = static_cast<UMLClassifier*>(ns); Import_Utils::createGeneralization(klass, parent); } } } } skipStmt(); return true; } // Datatypes: TO BE DONE return false; } if (keyword == QLatin1String("private")) { m_currentAccess = Uml::Visibility::Private; return true; } if (keyword == QLatin1String("end")) { if (m_klass) { if (advance() != QLatin1String("record")) { uError() << "end: expecting \"record\" at " << m_source[m_srcIndex]; } m_klass = NULL; } else if (scopeIndex()) { if (advance() != QLatin1String(";")) { QString scopeName = currentScope()->fullyQualifiedName(); if (scopeName.toLower() != m_source[m_srcIndex].toLower()) uError() << "end: expecting " << scopeName << ", found " << m_source[m_srcIndex]; } popScope(); m_currentAccess = Uml::Visibility::Public; // @todo make a stack for this } else { uError() << "importAda: too many \"end\""; } skipStmt(); return true; } // subprogram if (keyword == QLatin1String("not")) keyword = advance(); if (keyword == QLatin1String("overriding")) keyword = advance(); if (keyword == QLatin1String("function") || keyword == QLatin1String("procedure")) { const QString& name = advance(); QString returnType; if (advance() != QLatin1String("(")) { // Unlike an Ada package, a UML package does not support // subprograms. // In order to map those, we would need to create a UML // class with stereotype <<utility>> for the Ada package. uDebug() << "ignoring parameterless " << keyword << " " << name; skipStmt(); return true; } UMLClassifier *klass = NULL; UMLOperation *op = NULL; const uint MAX_PARNAMES = 16; while (m_srcIndex < srcLength && m_source[m_srcIndex] != QLatin1String(")")) { QString parName[MAX_PARNAMES]; uint parNameCount = 0; do { if (parNameCount >= MAX_PARNAMES) { uError() << "MAX_PARNAMES is exceeded at " << name; break; } parName[parNameCount++] = advance(); } while (advance() == QLatin1String(",")); if (m_source[m_srcIndex] != QLatin1String(":")) { uError() << "importAda: expecting ':'"; skipStmt(); break; } const QString &direction = advance(); QString typeName; Uml::ParameterDirection::Enum dir = Uml::ParameterDirection::In; if (direction == QLatin1String("access")) { // Oops, we have to improvise here because there // is no such thing as "access" in UML. // So we use the next best thing, "inout". // Better ideas, anyone? dir = Uml::ParameterDirection::InOut; typeName = advance(); } else if (direction == QLatin1String("in")) { if (m_source[m_srcIndex + 1] == QLatin1String("out")) { dir = Uml::ParameterDirection::InOut; m_srcIndex++; } typeName = advance(); } else if (direction == QLatin1String("out")) { dir = Uml::ParameterDirection::Out; typeName = advance(); } else { typeName = direction; // In Ada, the default direction is "in" } typeName.remove(QLatin1String("Standard."), Qt::CaseInsensitive); typeName = expand(typeName); if (op == NULL) { // In Ada, the first parameter indicates the class. UMLObject *type = Import_Utils::createUMLObject(UMLObject::ot_Class, typeName, currentScope()); UMLObject::ObjectType t = type->baseType(); if ((t != UMLObject::ot_Interface && (t != UMLObject::ot_Class || type->stereotype() == QLatin1String("record"))) || !m_classesDefinedInThisScope.contains(type)) { // Not an instance bound method - we cannot represent it. skipStmt(QLatin1String(")")); break; } klass = static_cast<UMLClassifier*>(type); op = Import_Utils::makeOperation(klass, name); // The controlling parameter is suppressed. parNameCount--; if (parNameCount) { for (uint i = 0; i < parNameCount; ++i) { parName[i] = parName[i + 1]; } } } for (uint i = 0; i < parNameCount; ++i) { UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName[i]); att->setParmKind(dir); } if (advance() != QLatin1String(";")) break; } if (keyword == QLatin1String("function")) { if (advance() != QLatin1String("return")) { if (klass) uError() << "importAda: expecting \"return\" at function " << name; return false; } returnType = expand(advance()); returnType.remove(QLatin1String("Standard."), Qt::CaseInsensitive); } bool isAbstract = false; if (advance() == QLatin1String("is") && advance() == QLatin1String("abstract")) isAbstract = true; if (klass != NULL && op != NULL) Import_Utils::insertMethod(klass, op, m_currentAccess, returnType, false, isAbstract, false, false, m_comment); skipStmt(); return true; } if (keyword == QLatin1String("task") || keyword == QLatin1String("protected")) { // Can task and protected objects/types be mapped to UML? QString name = advance(); if (name == QLatin1String("type")) { name = advance(); } QString next = advance(); if (next == QLatin1String("(")) { skipStmt(QLatin1String(")")); // skip discriminant next = advance(); } if (next == QLatin1String("is")) skipStmt(QLatin1String("end")); skipStmt(); return true; } if (keyword == QLatin1String("for")) { // rep spec QString typeName = advance(); QString next = advance(); if (next == QLatin1String("'")) { advance(); // skip qualifier next = advance(); } if (next == QLatin1String("use")) { if (advance() == QLatin1String("record")) skipStmt(QLatin1String("end")); } else { uError() << "importAda: expecting \"use\" at rep spec of " << typeName; } skipStmt(); return true; } // At this point we're only interested in attribute declarations. if (m_klass == NULL || keyword == QLatin1String("null")) { skipStmt(); return true; } const QString& name = keyword; if (advance() != QLatin1String(":")) { uError() << "adaImport: expecting \":\" at " << name << " " << m_source[m_srcIndex]; skipStmt(); return true; } QString nextToken = advance(); if (nextToken == QLatin1String("aliased")) nextToken = advance(); QString typeName = expand(nextToken); QString initialValue; if (advance() == QLatin1String(":=")) { initialValue = advance(); QString token; while ((token = advance()) != QLatin1String(";")) { initialValue.append(QLatin1Char(' ') + token); } } UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name, typeName, m_comment); if (o) { UMLAttribute *attr = static_cast<UMLAttribute*>(o); attr->setInitialValue(initialValue); } skipStmt(); 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; }