umbrello API Documentation

import_utils.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) 2005-2007                                               *
00009  *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
00010  ***************************************************************************/
00011 
00012 // own header
00013 #include "import_utils.h"
00014 // qt/kde includes
00015 #include <qmap.h>
00016 #include <qregexp.h>
00017 #include <kmessagebox.h>
00018 #include <kdebug.h>
00019 #include <klocale.h>
00020 // app includes
00021 #include "../uml.h"
00022 #include "../umldoc.h"
00023 #include "../umllistview.h"
00024 #include "../umllistviewitem.h"
00025 #include "../umlobject.h"
00026 #include "../package.h"
00027 #include "../folder.h"
00028 #include "../enum.h"
00029 #include "../classifier.h"
00030 #include "../operation.h"
00031 #include "../attribute.h"
00032 #include "../template.h"
00033 #include "../association.h"
00034 #include "../object_factory.h"
00035 
00036 #include <stdlib.h>
00037 
00038 namespace Import_Utils {
00039 
00046 bool bNewUMLObjectWasCreated = false;
00047 
00052 UMLClassifier * gRelatedClassifier = NULL;
00053 
00062 bool bPutAtGlobalScope = false;
00063 
00067 QStringList incPathList;
00068 
00069 void putAtGlobalScope(bool yesno) {
00070     bPutAtGlobalScope = yesno;
00071 }
00072 
00073 void setRelatedClassifier(UMLClassifier *c) {
00074     gRelatedClassifier = c;
00075 }
00076 
00077 void assignUniqueIdOnCreation(bool yesno) {
00078     Object_Factory::assignUniqueIdOnCreation(yesno);
00079 }
00080 
00081 bool newUMLObjectWasCreated() {
00082     return bNewUMLObjectWasCreated;
00083 }
00084 
00085 QString formatComment(const QString &comment) {
00086     if (comment.isEmpty())
00087         return comment;
00088 
00089     QStringList lines = QStringList::split("\n", comment);
00090     QString& first = lines.first();
00091     QRegExp wordex("\\w");
00092     if (first.startsWith("/*")) {
00093         int wordpos = wordex.search(first);
00094         if (wordpos != -1)
00095             first = first.mid(wordpos);  // remove comment start
00096         else
00097             lines.pop_front();  // nothing interesting on this line
00098     }
00099     QString& last = lines.last();
00100     int endpos = last.find("*/");
00101     if (endpos != -1) {
00102         if (last.contains(wordex))
00103             last = last.mid(0, endpos - 1);  // remove comment end
00104         else
00105             lines.pop_back();  // nothing interesting on this line
00106     }
00107     if (! lines.count())
00108         return "";
00109 
00110     QStringList::Iterator end(lines.end());
00111     for (QStringList::Iterator lit(lines.begin()); lit != end; ++lit) {
00112         (*lit).remove(QRegExp("^\\s+"));
00113         (*lit).remove(QRegExp("^\\*+\\s?"));
00114     }
00115     return lines.join("\n");
00116 }
00117 
00118 /*
00119 UMLObject* findUMLObject(QString name,
00120                                       Uml::Object_Type type) {
00121     // Why an extra wrapper? See comment at addMethodParameter()
00122     UMLObject * o = umldoc->findUMLObject(name, type);
00123     return o;
00124 }
00125  */
00126 
00127 UMLObject *createUMLObject(Uml::Object_Type type,
00128                            const QString& inName,
00129                            UMLPackage *parentPkg,
00130                            const QString& comment,
00131                            const QString& stereotype) {
00132     QString name = inName;
00133     UMLDoc *umldoc = UMLApp::app()->getDocument();
00134     UMLFolder *logicalView = umldoc->getRootFolder(Uml::mt_Logical);
00135     const Uml::Programming_Language pl = UMLApp::app()->getActiveLanguage();
00136     if (parentPkg == NULL) {
00137         // kDebug() << "Import_Utils::createUMLObject(" << name
00138         //     << "): parentPkg is NULL, assuming Logical View" << endl;
00139         parentPkg = logicalView;
00140     }
00141     UMLObject * o = umldoc->findUMLObject(name, type, parentPkg);
00142     bNewUMLObjectWasCreated = false;
00143     if (o == NULL) {
00144         // Strip possible adornments and look again.
00145         int isConst = name.contains(QRegExp("^const "));
00146         name.remove(QRegExp("^const\\s+"));
00147         QString typeName(name);
00148         const int isAdorned = typeName.contains( QRegExp("[^\\w:\\. ]") );
00149         const int isPointer = typeName.contains('*');
00150         const int isRef = typeName.contains('&');
00151         typeName.remove(QRegExp("[^\\w:\\. ].*$"));
00152         typeName = typeName.simplifyWhiteSpace();
00153         UMLObject *origType = umldoc->findUMLObject(typeName, Uml::ot_UMLObject, parentPkg);
00154         if (origType == NULL) {
00155             // Still not found. Create the stripped down type.
00156             if (bPutAtGlobalScope)
00157                 parentPkg = logicalView;
00158             // Find, or create, the scopes.
00159             QStringList components;
00160             if (typeName.contains("::")) {
00161                 components = QStringList::split("::", typeName);
00162             } else if (typeName.contains(".")) {
00163                 components = QStringList::split(".", typeName);
00164             }
00165             if (components.count() > 1) {
00166                 typeName = components.back();
00167                 components.pop_back();
00168                 while ( components.count() ) {
00169                     QString scopeName = components.front();
00170                     components.pop_front();
00171                     o = umldoc->findUMLObject(scopeName, Uml::ot_UMLObject, parentPkg);
00172                     if (o) {
00173                         parentPkg = static_cast<UMLPackage*>(o);
00174                         continue;
00175                     }
00176                     int wantNamespace = KMessageBox::Yes;
00177                     if (pl == Uml::pl_Cpp) {
00178                         /* We know std and Qt are namespaces */
00179                         if (scopeName != "std" && scopeName != "Qt") {
00180                             wantNamespace = KMessageBox::questionYesNo(NULL,
00181                                         i18n("Is the scope %1 a namespace or a class?").arg(scopeName),
00182                                         i18n("C++ Import Requests Your Help"),
00183                                         i18n("Namespace"), i18n("Class"));
00184                         }
00185                     }
00186                     Uml::Object_Type ot = (wantNamespace == KMessageBox::Yes ? Uml::ot_Package : Uml::ot_Class);
00187                     o = Object_Factory::createUMLObject(ot, scopeName, parentPkg);
00188                     parentPkg = static_cast<UMLPackage*>(o);
00189                     UMLListView *listView = UMLApp::app()->getListView();
00190                     UMLListViewItem *lvitem = listView->findUMLObject(o);
00191                     listView->setCurrentItem(lvitem);
00192                 }
00193                 // All scope qualified datatypes live in the global scope.
00194                 bPutAtGlobalScope = true;
00195             }
00196             Uml::Object_Type t = type;
00197             if (type == Uml::ot_UMLObject || isAdorned)
00198                 t = Uml::ot_Class;
00199             origType = Object_Factory::createUMLObject(t, typeName, parentPkg, false);
00200             bNewUMLObjectWasCreated = true;
00201             bPutAtGlobalScope = false;
00202         }
00203         if (isConst || isAdorned) {
00204             // Create the full given type (including adornments.)
00205             if (isConst)
00206                 name.prepend("const ");
00207             o = Object_Factory::createUMLObject(Uml::ot_Datatype, name,
00208                                                 umldoc->getDatatypeFolder(),
00209                                                 false); //solicitNewName
00210             UMLClassifier *dt = static_cast<UMLClassifier*>(o);
00211             UMLClassifier *c = dynamic_cast<UMLClassifier*>(origType);
00212             if (c)
00213                 dt->setOriginType(c);
00214             else
00215                 kError() << "createUMLObject(" << name << "): "
00216                 << "origType " << typeName << " is not a UMLClassifier"
00217                 << endl;
00218             if (isRef || isPointer)
00219                 dt->setIsReference();
00220             /*
00221             if (isPointer) {
00222                 UMLObject *pointerDecl = Object_Factory::createUMLObject(Uml::ot_Datatype, type);
00223                 UMLClassifier *dt = static_cast<UMLClassifier*>(pointerDecl);
00224                 dt->setOriginType(classifier);
00225                 dt->setIsReference();
00226                 classifier = dt;
00227             }  */
00228         } else {
00229             o = origType;
00230         }
00231     } else if (parentPkg && !bPutAtGlobalScope) {
00232         UMLPackage *existingPkg = o->getUMLPackage();
00233         if (existingPkg != umldoc->getDatatypeFolder()) {
00234             if (existingPkg)
00235                 existingPkg->removeObject(o);
00236             else
00237                 kError() << "createUMLObject(" << name << "): "
00238                     << "o->getUMLPackage() was NULL" << endl;
00239             o->setUMLPackage(parentPkg);
00240             parentPkg->addObject(o);
00241         }
00242     }
00243     QString strippedComment = formatComment(comment);
00244     if (! strippedComment.isEmpty()) {
00245         o->setDoc(strippedComment);
00246     }
00247     if (!stereotype.isEmpty()) {
00248         o->setStereotype(stereotype);
00249     }
00250     if (gRelatedClassifier == NULL || gRelatedClassifier == o)
00251         return o;
00252     QRegExp templateInstantiation("^[\\w:\\.]+\\s*<(.*)>");
00253     int pos = templateInstantiation.search(name);
00254     if (pos == -1)
00255         return o;
00256     // Create dependencies on template parameters.
00257     QString caption = templateInstantiation.cap(1);
00258     QStringList params = QStringList::split(QRegExp("[^\\w:\\.]+"), caption);
00259     if (!params.count())
00260         return o;
00261     QStringList::Iterator end(params.end());
00262     for (QStringList::Iterator it(params.begin()); it != end; ++it) {
00263         UMLObject *p = umldoc->findUMLObject(*it, Uml::ot_UMLObject, parentPkg);
00264         if (p == NULL || p->getBaseType() == Uml::ot_Datatype)
00265             continue;
00266         const Uml::Association_Type at = Uml::at_Dependency;
00267         UMLAssociation *assoc = umldoc->findAssociation(at, gRelatedClassifier, p);
00268         if (assoc)
00269             continue;
00270         assoc = new UMLAssociation(at, gRelatedClassifier, p);
00271         assoc->setUMLPackage(umldoc->getRootFolder(Uml::mt_Logical));
00272         umldoc->addAssociation(assoc);
00273     }
00274     return o;
00275 }
00276 
00277 UMLOperation* makeOperation(UMLClassifier *parent, const QString &name) {
00278     UMLOperation *op = Object_Factory::createOperation(parent, name);
00279     return op;
00280 }
00281 
00282 UMLObject* insertAttribute(UMLClassifier *owner,
00283                            Uml::Visibility scope,
00284                            const QString& name,
00285                            UMLClassifier *attrType,
00286                            const QString& comment /* ="" */,
00287                            bool isStatic /* =false */) {
00288     Uml::Object_Type ot = owner->getBaseType();
00289     Uml::Programming_Language pl = UMLApp::app()->getActiveLanguage();
00290     if (! (ot == Uml::ot_Class || ot == Uml::ot_Interface && pl == Uml::pl_Java)) {
00291         kDebug() << "insertAttribute: Don't know what to do with "
00292         << owner->getName() << " (object type " << ot << ")" << endl;
00293         return NULL;
00294     }
00295     UMLObject *o = owner->findChildObject(name, Uml::ot_Attribute);
00296     if (o) {
00297         return o;
00298     }
00299 
00300     UMLAttribute *attr = owner->addAttribute(name, attrType, scope);
00301     attr->setStatic(isStatic);
00302     QString strippedComment = formatComment(comment);
00303     if (! strippedComment.isEmpty()) {
00304         attr->setDoc(strippedComment);
00305     }
00306 
00307     UMLApp::app()->getDocument()->setModified(true);
00308     return attr;
00309 }
00310 
00311 UMLObject* insertAttribute(UMLClassifier *owner, Uml::Visibility scope,
00312                            const QString& name,
00313                            const QString& type,
00314                            const QString& comment /* ="" */,
00315                            bool isStatic /* =false */) {
00316     UMLObject *attrType = owner->findTemplate(type);
00317     if (attrType == NULL) {
00318         bPutAtGlobalScope = true;
00319         gRelatedClassifier = owner;
00320         attrType = createUMLObject(Uml::ot_UMLObject, type, owner);
00321         gRelatedClassifier = NULL;
00322         bPutAtGlobalScope = false;
00323     }
00324     return insertAttribute (owner, scope, name,
00325                             static_cast<UMLClassifier*>(attrType),
00326                             comment, isStatic);
00327 }
00328 
00329 void insertMethod(UMLClassifier *klass, UMLOperation* &op,
00330                   Uml::Visibility scope, const QString& type,
00331                   bool isStatic, bool isAbstract,
00332                   bool isFriend, bool isConstructor,
00333                   const QString& comment) {
00334     op->setVisibility(scope);
00335     if (!type.isEmpty()     // return type may be missing (constructor/destructor)
00336         && type != "void") {
00337         if (type == klass->getName()) {
00338             op->setType(klass);
00339         } else {
00340             UMLObject *typeObj = klass->findTemplate(type);
00341             if (typeObj == NULL) {
00342                 bPutAtGlobalScope = true;
00343                 gRelatedClassifier = klass;
00344                 typeObj = createUMLObject(Uml::ot_UMLObject, type, klass);
00345                 gRelatedClassifier = NULL;
00346                 bPutAtGlobalScope = false;
00347                 op->setType(typeObj);
00348             }
00349         }
00350     }
00351 
00352     op->setStatic(isStatic);
00353     op->setAbstract(isAbstract);
00354 
00355     // if the operation is friend, add it as a stereotype
00356     if (isFriend)
00357         op->setStereotype("friend");
00358     // if the operation is a constructor, add it as a stereotype
00359     if (isConstructor)
00360         op->setStereotype("constructor");
00361 
00362     QString strippedComment = formatComment(comment);
00363     if (! strippedComment.isEmpty()) {
00364         op->setDoc(strippedComment);
00365     }
00366 
00367     UMLAttributeList params = op->getParmList();
00368     UMLOperation *exist = klass->checkOperationSignature(op->getName(), params);
00369     if (exist) {
00370         // copy contents to existing operation
00371         exist->setVisibility(scope);
00372         exist->setStatic(isStatic);
00373         exist->setAbstract(isAbstract);
00374         if (! strippedComment.isEmpty())
00375             exist->setDoc(strippedComment);
00376         UMLAttributeList exParams = exist->getParmList();
00377         UMLAttribute *param, *exParam = exParams.first();
00378         for (UMLAttributeListIt it(params); (param = it.current()) != NULL;
00379                                             ++it, exParam = exParams.next()) {
00380             exParam->setName(param->getName());
00381             exParam->setVisibility(param->getVisibility());
00382             exParam->setStatic(param->getStatic());
00383             exParam->setAbstract(param->getAbstract());
00384             exParam->setDoc(param->getDoc());
00385             exParam->setInitialValue(param->getInitialValue());
00386             exParam->setParmKind(param->getParmKind());
00387         }
00388         // delete incoming UMLOperation and pass out the existing one
00389         delete op;
00390         op = exist;
00391     } else {
00392         klass->addOperation(op);
00393     }
00394 }
00395 
00396 UMLAttribute* addMethodParameter(UMLOperation *method,
00397                                  const QString& type,
00398                                  const QString& name) {
00399     UMLClassifier *owner = static_cast<UMLClassifier*>(method->parent());
00400     UMLObject *typeObj = owner->findTemplate(type);
00401     if (typeObj == NULL) {
00402         bPutAtGlobalScope = true;
00403         gRelatedClassifier = owner;
00404         typeObj = createUMLObject(Uml::ot_UMLObject, type, owner);
00405         gRelatedClassifier = NULL;
00406         bPutAtGlobalScope = false;
00407     }
00408     UMLAttribute *attr = Object_Factory::createAttribute(method, name, typeObj);
00409     method->addParm(attr);
00410     return attr;
00411 }
00412 
00413 void addEnumLiteral(UMLEnum *enumType, const QString &literal, const QString &comment) {
00414     UMLObject *el = enumType->addEnumLiteral(literal);
00415     el->setDoc(comment);
00416 }
00417 
00418 void createGeneralization(UMLClassifier *child, UMLClassifier *parent) {
00419     // if the child is an interface, so is the parent.
00420     if (child->isInterface())
00421         parent->setBaseType(Uml::ot_Interface);
00422     Uml::Association_Type association = Uml::at_Generalization;
00423 
00424     if (parent->isInterface() && !child->isInterface()) {
00425         // if the parent is an interface, but the child is not, then
00426         // this is really realization.
00427         //
00428         association = Uml::at_Realization;
00429     }
00430     UMLAssociation *assoc = new UMLAssociation(association, child, parent);
00431     UMLDoc *umldoc = UMLApp::app()->getDocument();
00432     assoc->setUMLPackage(umldoc->getRootFolder(Uml::mt_Logical));
00433     umldoc->addAssociation(assoc);
00434 }
00435 
00436 void createGeneralization(UMLClassifier *child, const QString &parentName) {
00437     UMLObject *parentObj = createUMLObject( Uml::ot_Class, parentName );
00438     UMLClassifier *parent = static_cast<UMLClassifier*>(parentObj);
00439     createGeneralization(child, parent);
00440 }
00441 
00442 QStringList includePathList() {
00443     QStringList includePathList(incPathList);
00444     char *umbrello_incpath = getenv( "UMBRELLO_INCPATH" );
00445     if (umbrello_incpath) {
00446         includePathList += QStringList::split( ':', umbrello_incpath );
00447     }
00448     return includePathList;
00449 }
00450 
00451 void addIncludePath(const QString& path) {
00452     if (! incPathList.contains(path))
00453         incPathList.append(path);
00454 }
00455 
00456 
00457 bool isDatatype(const QString& name, UMLPackage *parentPkg) {
00458     UMLDoc *umldoc = UMLApp::app()->getDocument();
00459     UMLObject * o = umldoc->findUMLObject(name, Uml::ot_Datatype, parentPkg);
00460     return (o!=NULL);
00461 }
00462 
00463 }  // end namespace Import_Utils
00464 
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:57 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003