umbrello API Documentation

petaltree2uml.cpp

00001 /***************************************************************************
00002  *                                                                         *
00003  *   This program is free software; you can redistribute it and/or modify  *
00004  *   it under the terms of the GNU General Public License as published by  *
00005  *   the Free Software Foundation; either version 2 of the License, or     *
00006  *   (at your option) any later version.                                   *
00007  *                                                                         *
00008  *   copyright (C) 2006-2007                                               *
00009  *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
00010  ***************************************************************************/
00011 
00012 // own header
00013 #include "petaltree2uml.h"
00014 // qt/kde includes
00015 #include <qregexp.h>
00016 #include <kdebug.h>
00017 // app includes
00018 #include "petalnode.h"
00019 #include "codeimport/import_utils.h"
00020 #include "package.h"
00021 #include "classifier.h"
00022 #include "attribute.h"
00023 #include "operation.h"
00024 #include "association.h"
00025 #include "umlrole.h"
00026 #include "usecase.h"
00027 #include "component.h"
00028 #include "node.h"
00029 #include "uml.h"
00030 #include "umldoc.h"
00031 #include "umllistview.h"
00032 #include "umllistviewitem.h"
00033 
00034 namespace Import_Rose {
00035 
00040 QString clean(const QString& s) {
00041     if (s.isNull())
00042         return QString();
00043     QString str = s;
00044     str.remove("\"");
00045     str.remove(QRegExp("^Logical View::"));
00046     return str;
00047 }
00048 
00052 Uml::IDType quid(const PetalNode *node) {
00053     QString quidStr = node->findAttribute("quid").string;
00054     if (quidStr.isEmpty())
00055         return Uml::id_None;
00056     quidStr.remove("\"");
00057     return STR2ID(quidStr);
00058 }
00059 
00063 QString quidu(const PetalNode *node) {
00064     QString quiduStr = node->findAttribute("quidu").string;
00065     if (quiduStr.isEmpty())
00066         return QString();
00067     quiduStr.remove("\"");
00068     return quiduStr;
00069 }
00070 
00076 Uml::Object_Type typeToCreate(const QString& name) {
00077     QString n = name;
00078     n.remove(QRegExp("^.*::"));  // don't consider the scope prefix, it may contain spaces
00079     Uml::Object_Type t = (n.contains(QRegExp("\\W")) ? Uml::ot_Datatype : Uml::ot_Class);
00080     return t;
00081 }
00082 
00089 void transferVisibility(const PetalNode *from, UMLObject *to) {
00090     QString vis = from->findAttribute("exportControl").string;
00091     if (!vis.isEmpty()) {
00092         Uml::Visibility v = Uml::Visibility::fromString(clean(vis.lower()));
00093         to->setVisibility(v);
00094     }
00095 }
00096 
00101 class ClassifierListReader {
00102 public:
00104     ClassifierListReader(const char* attributeTag,
00105                          const char* elementName,
00106                          const char* itemTypeDesignator) :
00107         m_attributeTag(attributeTag),
00108         m_elementName(elementName),
00109         m_itemTypeDesignator(itemTypeDesignator) {
00110     }
00112     virtual ~ClassifierListReader() {}
00113 
00118     virtual UMLObject *createListItem() = 0;
00119 
00120     virtual void setTypeReferences(UMLObject *item,
00121                                    const QString& quid, const QString& type) {
00122         if (!quid.isEmpty()) {
00123             item->setSecondaryId(quid);
00124         }
00125         if (!type.isEmpty()) {
00126             item->setSecondaryFallback(type);
00127         }
00128     }
00129 
00139     virtual void insertAtParent(const PetalNode *node, UMLObject *o) = 0;
00140 
00150     void read(const PetalNode *node, const QString& name) {
00151         PetalNode *attributes = node->findAttribute(m_attributeTag).node;
00152         if (attributes == NULL) {
00153 #ifdef VERBOSE_DEBUGGING
00154             kDebug() << "read(" << name << "): no " << m_attributeTag << " found"
00155                       << endl;
00156 #endif
00157             return;
00158         }
00159         PetalNode::NameValueList attributeList = attributes->attributes();
00160         for (uint i = 0; i < attributeList.count(); i++) {
00161             PetalNode *attNode = attributeList[i].second.node;
00162             QStringList initialArgs = attNode->initialArgs();
00163             if (attNode->name() != m_elementName) {
00164                 kDebug() << "read(" << name << "): expecting " << m_elementName
00165                           << ", " << "found " << initialArgs[0] << endl;
00166                 continue;
00167             }
00168             UMLObject *item = createListItem();
00169             if (initialArgs.count() > 1)
00170                 item->setName(clean(initialArgs[1]));
00171             item->setID(quid(attNode));
00172             QString quidref = quidu(attNode);
00173             QString type = clean(attNode->findAttribute(m_itemTypeDesignator).string);
00174             setTypeReferences(item, quidref, type);
00175             transferVisibility(attNode, item);
00176             QString doc = attNode->findAttribute("documentation").string;
00177             if (! doc.isEmpty())
00178                 item->setDoc(doc);
00179             insertAtParent(attNode, item);
00180         }
00181     }
00182 protected:
00183     const QString m_attributeTag, m_elementName, m_itemTypeDesignator;
00184 };
00185 
00186 class AttributesReader : public ClassifierListReader {
00187 public:
00188     AttributesReader(UMLClassifier *c)
00189       : ClassifierListReader("class_attributes", "ClassAttribute", "type") {
00190         m_classifier = c;
00191     }
00192     virtual ~AttributesReader() {}
00193     UMLObject *createListItem() {
00194         return new UMLAttribute(m_classifier);
00195     }
00196     void insertAtParent(const PetalNode *, UMLObject *item) {
00197         m_classifier->addAttribute(static_cast<UMLAttribute*>(item));
00198     }
00199 protected:
00200     UMLClassifier *m_classifier;
00201 };
00202 
00203 class ParametersReader : public ClassifierListReader {
00204 public:
00205     ParametersReader(UMLOperation *op)
00206       : ClassifierListReader("parameters", "Parameter", "type") {
00207         m_operation = op;
00208     }
00209     virtual ~ParametersReader() {}
00210     UMLObject *createListItem() {
00211         return new UMLAttribute(m_operation);
00212     }
00213     void insertAtParent(const PetalNode *, UMLObject *item) {
00214         m_operation->addParm(static_cast<UMLAttribute*>(item));
00215     }
00216 protected:
00217     UMLOperation *m_operation;
00218 };
00219 
00220 class OperationsReader : public ClassifierListReader {
00221 public:
00222     OperationsReader(UMLClassifier *c)
00223       : ClassifierListReader("operations", "Operation", "result") {
00224         m_classifier = c;
00225     }
00226     virtual ~OperationsReader() {}
00227     UMLObject *createListItem() {
00228         return new UMLOperation(m_classifier);
00229     }
00230     void insertAtParent(const PetalNode *node, UMLObject *item) {
00231         UMLOperation *op = static_cast<UMLOperation*>(item);
00232         ParametersReader parmReader(op);
00233         parmReader.read(node, m_classifier->getName());
00234         m_classifier->addOperation(op);
00235     }
00236 protected:
00237     UMLClassifier *m_classifier;
00238 };
00239 
00240 class SuperclassesReader : public ClassifierListReader {
00241 public:
00242     SuperclassesReader(UMLClassifier *c)
00243       : ClassifierListReader("superclasses", "Inheritance_Relationship", "supplier") {
00244         m_classifier = c;
00245     }
00246     virtual ~SuperclassesReader() {}
00247     UMLObject *createListItem() {
00248         return new UMLAssociation(Uml::at_Generalization);
00249     }
00254     void setTypeReferences(UMLObject *item,
00255                            const QString& quid, const QString& type) {
00256         UMLAssociation *assoc = static_cast<UMLAssociation*>(item);
00257         if (!quid.isEmpty()) {
00258             assoc->getUMLRole(Uml::B)->setSecondaryId(quid);
00259         }
00260         if (!type.isEmpty()) {
00261             assoc->getUMLRole(Uml::B)->setSecondaryFallback(type);
00262         }
00263     }
00264     void insertAtParent(const PetalNode *, UMLObject *item) {
00265         UMLAssociation *assoc = static_cast<UMLAssociation*>(item);
00266         assoc->setObject(m_classifier, Uml::A);
00267         UMLApp::app()->getDocument()->addAssociation(assoc);
00268     }
00269 protected:
00270     UMLClassifier *m_classifier;
00271 };
00272 
00273 class RealizationsReader : public ClassifierListReader {
00274 public:
00275     RealizationsReader(UMLClassifier *c)
00276       : ClassifierListReader("realized_interfaces", "Realize_Relationship", "supplier") {
00277         m_classifier = c;
00278     }
00279     virtual ~RealizationsReader() {}
00280     UMLObject *createListItem() {
00281         return new UMLAssociation(Uml::at_Realization);
00282     }
00287     void setTypeReferences(UMLObject *item,
00288                            const QString& quid, const QString& type) {
00289         UMLAssociation *assoc = static_cast<UMLAssociation*>(item);
00290         if (!quid.isEmpty()) {
00291             assoc->getUMLRole(Uml::B)->setSecondaryId(quid);
00292         }
00293         if (!type.isEmpty()) {
00294             assoc->getUMLRole(Uml::B)->setSecondaryFallback(type);
00295         }
00296     }
00297     void insertAtParent(const PetalNode *, UMLObject *item) {
00298         UMLAssociation *assoc = static_cast<UMLAssociation*>(item);
00299         assoc->setObject(m_classifier, Uml::A);
00300         UMLApp::app()->getDocument()->addAssociation(assoc);
00301     }
00302 protected:
00303     UMLClassifier *m_classifier;
00304 };
00305 
00313 bool umbrellify(PetalNode *node, UMLPackage *parentPkg = NULL) {
00314     if (node == NULL) {
00315         kError() << "umbrellify: node is NULL" << endl;
00316         return false;
00317     }
00318     QStringList args = node->initialArgs();
00319     QString objType = args[0];
00320     QString name = clean(args[1]);
00321     Uml::IDType id = quid(node);
00322 
00323     if (objType == "Class_Category") {
00324         UMLObject *o = Import_Utils::createUMLObject(Uml::ot_Package, name, parentPkg);
00325         o->setID(id);
00326         PetalNode *logical_models = node->findAttribute("logical_models").node;
00327         if (logical_models == NULL) {
00328             kError() << "umbrellify: cannot find logical_models" << endl;
00329             return false;
00330         }
00331         UMLPackage *localParent = static_cast<UMLPackage*>(o);
00332         PetalNode::NameValueList atts = logical_models->attributes();
00333         for (uint i = 0; i < atts.count(); i++) {
00334             umbrellify(atts[i].second.node, localParent);
00335         }
00336 
00337     } else if (objType == "Class") {
00338         UMLObject *o = Import_Utils::createUMLObject(Uml::ot_Class, name, parentPkg);
00339         o->setID(id);
00340         UMLClassifier *c = static_cast<UMLClassifier*>(o);
00341         // set stereotype
00342         QString stereotype = clean(node->findAttribute("stereotype").string);
00343         if (!stereotype.isEmpty()) {
00344             if (stereotype.lower() == "interface")
00345                 c->setBaseType(Uml::ot_Interface);
00346             else
00347                 c->setStereotype(stereotype);
00348         }
00349         // insert attributes
00350         AttributesReader attReader(c);
00351         attReader.read(node, c->getName());
00352         // insert operations
00353         OperationsReader opReader(c);
00354         opReader.read(node, c->getName());
00355         // insert generalizations
00356         SuperclassesReader superReader(c);
00357         superReader.read(node, c->getName());
00358         // insert realizations
00359         RealizationsReader realReader(c);
00360         realReader.read(node, c->getName());
00361 
00362     } else if (objType == "Association") {
00363         PetalNode *roles = node->findAttribute("roles").node;
00364         if (node == NULL) {
00365             kError() << "umbrellify: cannot find roles of Association" << endl;
00366             return false;
00367         }
00368         UMLAssociation *assoc = new UMLAssociation(Uml::at_UniAssociation);
00369         PetalNode::NameValueList roleList = roles->attributes();
00370         for (uint i = 0; i <= 1; i++) {
00371             PetalNode *roleNode = roleList[i].second.node;
00372             if (roleNode == NULL) {
00373                 kError() << "umbrellify: roleNode of Association is NULL" << endl;
00374                 return false;
00375             }
00376             if (roleNode->name() != "Role") {
00377                 kDebug() << "umbrellify(" << name << "): expecting Role, found \""
00378                           << roleNode->name() << endl;
00379                 continue;
00380             }
00381             // index 0 corresponds to Umbrello roleB
00382             // index 1 corresponds to Umbrello roleA
00383             UMLRole *role = assoc->getUMLRole((Uml::Role_Type) !i);
00384             QStringList initialArgs = roleNode->initialArgs();
00385             if (initialArgs.count() > 1) {
00386                 QString roleName = clean(initialArgs[1]);
00387                 if (! roleName.startsWith("$UNNAMED"))
00388                     role->setName(roleName);
00389             }
00390             role->setID(quid(roleNode));
00391             QString quidref = quidu(roleNode);
00392             QString type = clean(roleNode->findAttribute("supplier").string);
00393             if (!quidref.isEmpty()) {
00394                 role->setSecondaryId(quidref);
00395             }
00396             if (!type.isEmpty()) {
00397                 role->setSecondaryFallback(type);
00398             }
00399             QString label = clean(roleNode->findAttribute("label").string);
00400             if (!label.isEmpty()) {
00401                 role->setName(label);
00402             }
00403             QString client_cardinality = clean(roleNode->findAttribute("client_cardinality").string);
00404             if (!client_cardinality.isEmpty()) {
00405                 role->setMultiplicity(client_cardinality);
00406             }
00407             QString is_navigable = clean(roleNode->findAttribute("is_navigable").string);
00408             if (is_navigable == "FALSE") {
00409                 assoc->setAssocType(Uml::at_Association);
00410             }
00411             QString is_aggregate = clean(roleNode->findAttribute("is_aggregate").string);
00412             if (is_aggregate == "TRUE") {
00413                 assoc->setAssocType(Uml::at_Aggregation);
00414             }
00415             QString containment = clean(roleNode->findAttribute("Containment").string);
00416             if (containment == "By Value") {
00417                 assoc->setAssocType(Uml::at_Composition);
00418             }
00419             QString doc = roleNode->findAttribute("documentation").string;
00420             if (! doc.isEmpty())
00421                 role->setDoc(doc);
00422         }
00423         UMLApp::app()->getDocument()->addAssociation(assoc);
00424 
00425     } else {
00426         kDebug() << "umbrellify: object type " << objType
00427                   << " is not yet implemented" << endl;
00428     }
00429     return true;
00430 }
00431 
00432 Uml::ListView_Type folderType(UMLListViewItem *parent) {
00433     Uml::ListView_Type type = Uml::lvt_Unknown;
00434     switch (parent->getType()) {
00435         case Uml::lvt_Logical_View:
00436         case Uml::lvt_Logical_Folder:
00437             type = Uml::lvt_Logical_Folder;
00438             break;
00439         case Uml::lvt_UseCase_View:
00440         case Uml::lvt_UseCase_Folder:
00441             type = Uml::lvt_UseCase_Folder;
00442             break;
00443         case Uml::lvt_Component_View:
00444         case Uml::lvt_Component_Folder:
00445             type = Uml::lvt_Component_Folder;
00446             break;
00447         case Uml::lvt_Deployment_View:
00448         case Uml::lvt_Deployment_Folder:
00449             type = Uml::lvt_Deployment_Folder;
00450             break;
00451         default:
00452             break;
00453     }
00454     return type;
00455 }
00456 
00465 bool umbrellify(PetalNode *node, const QString& modelsName, UMLListViewItem *parent) {
00466     if (node == NULL) {
00467         kError() << "umbrellify: node is NULL" << endl;
00468         return false;
00469     }
00470     QStringList args = node->initialArgs();
00471     QString objType = args[0];
00472     QString name = clean(args[1]);
00473     Uml::IDType id = quid(node);
00474     UMLObject *obj = NULL;
00475     UMLListViewItem *item = NULL;
00476 
00477     if (objType == "Class_Category") {
00478         Uml::ListView_Type lvType = folderType(parent);
00479         item = new UMLListViewItem( parent, name, lvType, id );
00480     } else if (objType == "UseCase") {
00481         UMLUseCase *uc = new UMLUseCase(name, id);
00482         item = new UMLListViewItem(parent, name, Uml::lvt_UseCase, uc);
00483         obj = uc;
00484     } else if (objType == "SubSystem") {
00485         UMLComponent *comp = new UMLComponent(name, id);
00486         item = new UMLListViewItem(parent, name, Uml::lvt_Component, comp);
00487         obj = comp;
00488     } else if (objType == "Processor" || objType == "Device") {
00489         UMLNode *un = new UMLNode(name, id);
00490         un->setStereotype(objType.lower());
00491         item = new UMLListViewItem(parent, name, Uml::lvt_Node, un);
00492         obj = un;
00493     } else {
00494         kDebug() << "umbrellify: object type " << objType
00495                   << " is not yet implemented" << endl;
00496         return true;
00497     }
00498     PetalNode *models = node->findAttribute(modelsName).node;
00499     if (models) {
00500         PetalNode::NameValueList atts = models->attributes();
00501         for (uint i = 0; i < atts.count(); i++) {
00502             if (! umbrellify(atts[i].second.node, modelsName, item))
00503                 return false;
00504         }
00505     }
00506     if (obj) {
00507         QString doc = node->findAttribute("documentation").string;
00508         if (! doc.isEmpty())
00509             obj->setDoc(doc);
00510         UMLDoc *theDocument = UMLApp::app()->getDocument();
00511         theDocument->addUMLObject(obj);
00512     }
00513     return true;
00514 }
00515 
00519 bool importView(PetalNode *root, const QString& rootName,
00520                 const QString& modelsName, UMLListViewItem *lvParent) {
00521     PetalNode *viewRoot = root->findAttribute(rootName).node;
00522     if (viewRoot == NULL) {
00523         kDebug() << "importView: cannot find " << rootName << endl;
00524         return false;
00525     }
00526     PetalNode *models = viewRoot->findAttribute(modelsName).node;
00527     if (models == NULL) {
00528         kError() << "importView: cannot find " << modelsName
00529                   << " of " << rootName << endl;
00530         return false;
00531     }
00532     PetalNode::NameValueList atts = models->attributes();
00533     for (uint i = 0; i < atts.count(); i++) {
00534         umbrellify(atts[i].second.node, modelsName, lvParent);
00535     }
00536     return true;
00537 }
00538 
00539 bool petalTree2Uml(PetalNode *root) {
00540     if (root == NULL) {
00541         kError() << "petalTree2Uml: root is NULL" << endl;
00542         return false;
00543     }
00544     if (root->name() != "Design") {
00545         kError() << "petalTree2Uml: expecting root name Design" << endl;
00546         return false;
00547     }
00548     /*************************** import  Logical View ********************************/
00549     PetalNode *root_category = root->findAttribute("root_category").node;
00550     if (root_category == NULL) {
00551         kError() << "petalTree2Uml: cannot find root_category" << endl;
00552         return false;
00553     }
00554     if (root_category->name() != "Class_Category") {
00555         kError() << "petalTree2Uml: expecting root_category object Class_Category"
00556                   << endl;
00557         return false;
00558     }
00559     PetalNode *logical_models = root_category->findAttribute("logical_models").node;
00560     if (logical_models == NULL) {
00561         kError() << "petalTree2Uml: cannot find logical_models" << endl;
00562         return false;
00563     }
00564     UMLDoc *umldoc = UMLApp::app()->getDocument();
00565     umldoc->setCurrentRoot(Uml::mt_Logical);
00566     Import_Utils::assignUniqueIdOnCreation(false);
00567     PetalNode::NameValueList atts = logical_models->attributes();
00568     for (uint i = 0; i < atts.count(); i++) {
00569         umbrellify(atts[i].second.node);
00570     }
00571 
00573     UMLListView *lv = UMLApp::app()->getListView();
00574 
00575     /*************************** import Use Case View ********************************/
00576     umldoc->setCurrentRoot(Uml::mt_UseCase);
00577     importView(root, "root_usecase_package", "logical_models", lv->theUseCaseView());
00578 
00579     /*************************** import Component View *******************************/
00580     umldoc->setCurrentRoot(Uml::mt_Component);
00581     importView(root, "root_subsystem", "physical_models", lv->theComponentView());
00582 
00583     /*************************** import Deployment View ******************************/
00584     umldoc->setCurrentRoot(Uml::mt_Deployment);
00585     importView(root, "process_structure", "ProcsNDevs", lv->theDeploymentView());
00586 
00587     /***************************       wrap up        ********************************/
00588     umldoc->setCurrentRoot(Uml::mt_Logical);
00589     Import_Utils::assignUniqueIdOnCreation(true);
00590     umldoc->resolveTypes();
00591     return true;
00592 }
00593 
00594 }  // namespace Import_Rose
00595 
KDE Logo
This file is part of the documentation for umbrello Version 3.1.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Jun 26 08:07:59 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003