00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "petaltree2uml.h"
00014
00015 #include <qregexp.h>
00016 #include <kdebug.h>
00017
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("^.*::"));
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
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
00350 AttributesReader attReader(c);
00351 attReader.read(node, c->getName());
00352
00353 OperationsReader opReader(c);
00354 opReader.read(node, c->getName());
00355
00356 SuperclassesReader superReader(c);
00357 superReader.read(node, c->getName());
00358
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
00382
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
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
00576 umldoc->setCurrentRoot(Uml::mt_UseCase);
00577 importView(root, "root_usecase_package", "logical_models", lv->theUseCaseView());
00578
00579
00580 umldoc->setCurrentRoot(Uml::mt_Component);
00581 importView(root, "root_subsystem", "physical_models", lv->theComponentView());
00582
00583
00584 umldoc->setCurrentRoot(Uml::mt_Deployment);
00585 importView(root, "process_structure", "ProcsNDevs", lv->theDeploymentView());
00586
00587
00588 umldoc->setCurrentRoot(Uml::mt_Logical);
00589 Import_Utils::assignUniqueIdOnCreation(true);
00590 umldoc->resolveTypes();
00591 return true;
00592 }
00593
00594 }
00595