00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "import_utils.h"
00014
00015 #include <qmap.h>
00016 #include <qregexp.h>
00017 #include <kmessagebox.h>
00018 #include <kdebug.h>
00019 #include <klocale.h>
00020
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);
00096 else
00097 lines.pop_front();
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);
00104 else
00105 lines.pop_back();
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
00120
00121
00122
00123
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
00138
00139 parentPkg = logicalView;
00140 }
00141 UMLObject * o = umldoc->findUMLObject(name, type, parentPkg);
00142 bNewUMLObjectWasCreated = false;
00143 if (o == NULL) {
00144
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
00156 if (bPutAtGlobalScope)
00157 parentPkg = logicalView;
00158
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
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
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
00205 if (isConst)
00206 name.prepend("const ");
00207 o = Object_Factory::createUMLObject(Uml::ot_Datatype, name,
00208 umldoc->getDatatypeFolder(),
00209 false);
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
00222
00223
00224
00225
00226
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
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 ) {
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 ) {
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()
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
00356 if (isFriend)
00357 op->setStereotype("friend");
00358
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
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
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
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
00426
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 }
00464