idlwriter.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "idlwriter.h"
00013
00014 #include <kdebug.h>
00015 #include <kmessagebox.h>
00016 #include <qfile.h>
00017 #include <qregexp.h>
00018 #include <qtextstream.h>
00019
00020 #include "../umldoc.h"
00021 #include "../classifier.h"
00022 #include "../enum.h"
00023 #include "../classifierlistitem.h"
00024 #include "../umlclassifierlistitemlist.h"
00025 #include "../package.h"
00026 #include "../association.h"
00027 #include "../attribute.h"
00028 #include "../operation.h"
00029 #include "../umlnamespace.h"
00030
00031 IDLWriter::IDLWriter() : SimpleCodeGenerator(false) {
00032 }
00033
00034 IDLWriter::~IDLWriter() {}
00035
00036 bool IDLWriter::isOOClass(UMLClassifier *c) {
00037 QString stype = c->getStereotype();
00038 if (stype == "CORBAConstant" || stype == "CORBAEnum" ||
00039 stype == "CORBAStruct" || stype == "CORBAUnion" ||
00040 stype == "CORBASequence" || stype == "CORBAArray" ||
00041 stype == "CORBATypedef")
00042 return false;
00043
00044
00045
00046 return true;
00047 }
00048
00049 bool IDLWriter::assocTypeIsMappableToAttribute(Uml::Association_Type at) {
00050 return (at == Uml::at_Aggregation || at == Uml::at_Association ||
00051 at == Uml::at_Composition || at == Uml::at_UniAssociation);
00052 }
00053
00057 Uml::Programming_Language IDLWriter::getLanguage() {
00058 return Uml::pl_IDL;
00059 }
00060
00061 void IDLWriter::computeAssocTypeAndRole
00062 (UMLAssociation *a, UMLClassifier *c, QString& typeName, QString& roleName)
00063 {
00064
00065 bool IAmRoleA = true;
00066 UMLObject *other = a->getObject(Uml::B);
00067 Uml::Association_Type at = a->getAssocType();
00068 if (c->getName() == other->getName()) {
00069 if (at == Uml::at_Aggregation || at == Uml::at_Composition ||
00070 at == Uml::at_UniAssociation) {
00071
00072
00073
00074
00075 roleName = QString();
00076 return;
00077 }
00078 IAmRoleA = false;
00079 other = a->getObject(Uml::A);
00080 }
00081
00082 typeName = cleanName(other->getName());
00083 QString multiplicity;
00084 if (IAmRoleA)
00085 multiplicity = a->getMulti(Uml::B);
00086 else
00087 multiplicity = a->getMulti(Uml::A);
00088 if (!multiplicity.isEmpty() && multiplicity != "1")
00089 typeName.append("Vector");
00090
00091 if (IAmRoleA)
00092 roleName = a->getRoleName(Uml::B);
00093 else
00094 roleName = a->getRoleName(Uml::A);
00095 if (roleName.isEmpty()) {
00096 roleName = a->getName();
00097 if (roleName.isEmpty()) {
00098 roleName = "m_" + typeName;
00099 }
00100 }
00101 }
00102
00103 void IDLWriter::writeClass(UMLClassifier *c) {
00104 if (!c) {
00105 kDebug() << "Cannot write class of NULL concept!" << endl;
00106 return;
00107 }
00108
00109 const bool isClass = !c->isInterface();
00110 QString classname = cleanName(c->getName());
00111
00112
00113 QString fileName = findFileName(c, ".idl");
00114 if (fileName.isEmpty()) {
00115 emit codeGenerated(c, false);
00116 return;
00117 }
00118
00119 QFile file;
00120 if (!openFile(file, fileName)) {
00121 emit codeGenerated(c, false);
00122 return;
00123 }
00124
00125
00126
00127 QTextStream idl(&file);
00128
00129 QString str;
00130 str = getHeadingFile(".idl");
00131 if (!str.isEmpty()) {
00132 str.replace(QRegExp("%filename%"), fileName);
00133 str.replace(QRegExp("%filepath%"), file.name());
00134 idl << str << m_endl;
00135 }
00136
00137
00138 UMLPackageList includes;
00139 findObjectsRelated(c, includes);
00140 if (includes.count()) {
00141 for (UMLPackage *conc = includes.first(); conc; conc = includes.next()) {
00142 if (conc->getBaseType() == Uml::ot_Datatype)
00143 continue;
00144 QString incName = findFileName(conc, ".idl");
00145 if (!incName.isEmpty())
00146 idl << "#include \"" << incName << "\"" << m_endl;
00147 }
00148 idl << m_endl;
00149 }
00150
00151
00152
00153 UMLPackageList pkgList = c->getPackages();
00154 UMLPackage *pkg;
00155 for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) {
00156 idl << getIndent() << "module " << pkg->getName() << " {" << m_endl << m_endl;
00157 m_indentLevel++;
00158 }
00159
00160
00161 if (forceDoc() || !c->getDoc().isEmpty()) {
00162 idl << "//" << m_endl;
00163 idl << "// class " << classname << m_endl;
00164 idl << formatDoc(c->getDoc(), "// ");
00165 idl << m_endl;
00166 }
00167
00168 if (c->getBaseType() == Uml::ot_Enum) {
00169 UMLClassifierListItemList litList = c->getFilteredList(Uml::ot_EnumLiteral);
00170 uint i = 0;
00171 idl << getIndent() << "enum " << classname << " {" << m_endl;
00172 m_indentLevel++;
00173 for (UMLClassifierListItem *lit = litList.first(); lit; lit = litList.next()) {
00174 QString enumLiteral = cleanName(lit->getName());
00175 idl << getIndent() << enumLiteral;
00176 if (++i < litList.count())
00177 idl << ",";
00178 idl << m_endl;
00179 }
00180 m_indentLevel--;
00181 idl << getIndent() << "};" << m_endl << m_endl;
00182
00183 for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) {
00184 m_indentLevel--;
00185 idl << getIndent() << "};" << m_endl << m_endl;
00186 }
00187 return;
00188 }
00189 if (! isOOClass(c)) {
00190 QString stype = c->getStereotype();
00191 if (stype == "CORBAConstant") {
00192 kError() << "The stereotype " << stype << " cannot be applied to "
00193 << c->getName() << ", but only to attributes." << endl;
00194 return;
00195 }
00196 if (!isClass) {
00197 kError() << "The stereotype " << stype
00198 << " cannot be applied to " << c->getName()
00199 << ", but only to classes." << endl;
00200 return;
00201 }
00202 if (stype == "CORBAEnum") {
00203 UMLAttributeList atl = c->getAttributeList();
00204 UMLAttribute *at;
00205 idl << getIndent() << "enum " << classname << " {" << m_endl;
00206 m_indentLevel++;
00207 uint i = 0;
00208 for (at = atl.first(); at; at = atl.next()) {
00209 QString enumLiteral = cleanName(at->getName());
00210 idl << getIndent() << enumLiteral;
00211 if (++i < atl.count())
00212 idl << ",";
00213 idl << m_endl;
00214 }
00215 m_indentLevel--;
00216 idl << getIndent() << "};" << m_endl << m_endl;
00217 } else if (stype == "CORBAStruct") {
00218 UMLAttributeList atl = c->getAttributeList();
00219 UMLAttribute *at;
00220 idl << getIndent() << "struct " << classname << " {" << m_endl;
00221 m_indentLevel++;
00222 for (at = atl.first(); at; at = atl.next()) {
00223 QString name = cleanName(at->getName());
00224 idl << getIndent() << at->getTypeName() << " " << name << ";" << m_endl;
00225
00226 }
00227 UMLAssociationList compositions = c->getCompositions();
00228 if (!compositions.isEmpty()) {
00229 idl << getIndent() << "// Compositions." << m_endl;
00230 for (UMLAssociation *a = compositions.first(); a; a = compositions.next()) {
00231 QString memberType, memberName;
00232 computeAssocTypeAndRole(a, c, memberType, memberName);
00233 idl << getIndent() << memberType << " " << memberName << ";" << m_endl;
00234 }
00235 }
00236 UMLAssociationList aggregations = c->getAggregations();
00237 if (!aggregations.isEmpty()) {
00238 idl << getIndent() << "// Aggregations." << m_endl;
00239 for (UMLAssociation *a = aggregations.first(); a; a = aggregations.next()) {
00240 QString memberType, memberName;
00241 computeAssocTypeAndRole(a, c, memberType, memberName);
00242 idl << getIndent() << memberType << " " << memberName << ";" << m_endl;
00243 }
00244 }
00245 m_indentLevel--;
00246 idl << getIndent() << "};" << m_endl << m_endl;
00247 } else if (stype == "CORBAUnion") {
00248 idl << getIndent() << "// " << stype << " " << c->getName()
00249 << " is Not Yet Implemented" << m_endl << m_endl;
00250 } else if (stype == "CORBATypedef") {
00251 UMLClassifierList superclasses = c->getSuperClasses();
00252 UMLClassifier* firstParent = superclasses.first();
00253 idl << getIndent() << "typedef " << firstParent->getName() << " "
00254 << c->getName() << ";" << m_endl << m_endl;
00255 } else {
00256 idl << getIndent() << "// " << stype << ": Unknown stereotype" << m_endl << m_endl;
00257 }
00258
00259 for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) {
00260 m_indentLevel--;
00261 idl << getIndent() << "};" << m_endl << m_endl;
00262 }
00263 return;
00264 }
00265
00266 idl << getIndent();
00267 if (c->getAbstract())
00268 idl << "abstract ";
00269 bool isValuetype = (c->getStereotype() == "CORBAValue");
00270 if (isValuetype)
00271 idl << "valuetype ";
00272 else
00273 idl << "interface ";
00274 idl << c->getName();
00275 UMLClassifierList superclasses = c->getSuperClasses();
00276 if (! superclasses.isEmpty()) {
00277 idl << " : ";
00278 UMLClassifier *parent = superclasses.first();
00279 int n_parents = superclasses.count();
00280 while (n_parents--) {
00281 idl << parent->getFullyQualifiedName("::");
00282 if (n_parents)
00283 idl << ", ";
00284 parent = superclasses.next();
00285 }
00286 }
00287 idl << " {" << m_endl << m_endl;
00288 m_indentLevel++;
00289
00290
00291 UMLAssociation *a;
00292 bool didComment = false;
00293 UMLAssociationList assocs = c->getAssociations();
00294 for (a = assocs.first(); a; a = assocs.next()) {
00295 if (! assocTypeIsMappableToAttribute(a->getAssocType()))
00296 continue;
00297 QString multiplicity = a->getMulti(Uml::A);
00298 if (multiplicity.isEmpty() || multiplicity == "1")
00299 continue;
00300 if (!didComment) {
00301 idl << getIndent() << "// Types for association multiplicities" << m_endl << m_endl;
00302 didComment = true;
00303 }
00304 UMLClassifier* other = (UMLClassifier*)a->getObject(Uml::A);
00305 QString bareName = cleanName(other->getName());
00306 idl << getIndent() << "typedef sequence<" << other->getFullyQualifiedName("::")
00307 << "> " << bareName << "Vector;" << m_endl << m_endl;
00308 }
00309
00310
00311 if (isClass) {
00312 UMLAttributeList atl = c->getAttributeList();
00313 if (forceSections() || atl.count()) {
00314 idl << getIndent() << "// Attributes:" << m_endl << m_endl;
00315 for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
00316 QString attName = cleanName(at->getName());
00317 Uml::Visibility scope = at->getVisibility();
00318 idl << getIndent();
00319 if (isValuetype) {
00320 if (scope == Uml::Visibility::Public)
00321 idl << "public ";
00322 else
00323 idl << "private ";
00324 } else {
00325 if (scope != Uml::Visibility::Public) {
00326 idl << "// visibility should be: "
00327 << scope.toString()
00328 << m_endl;
00329 idl << getIndent();
00330 }
00331 idl << "attribute ";
00332 }
00333 idl << at->getTypeName() << " " << attName << ";"
00334 << m_endl << m_endl;
00335 }
00336 }
00337 }
00338
00339
00340 UMLOperationList opl(c->getOpList());
00341 UMLOperationList oppub;
00342 UMLOperation *op;
00343 for (op = opl.first(); op; op = opl.next()) {
00344 if (op->getVisibility() == Uml::Visibility::Public)
00345 oppub.append(op);
00346 }
00347 if (forceSections() || oppub.count()) {
00348 idl << getIndent() << "// Public methods:" << m_endl << m_endl;
00349 for (op = oppub.first(); op; op = oppub.next())
00350 writeOperation(op, idl);
00351 idl << m_endl;
00352 }
00353
00354
00355 if (forceSections() || !assocs.isEmpty()) {
00356 idl << getIndent() << "// Associations:" << m_endl << m_endl;
00357 for (a = assocs.first(); a; a = assocs.next()) {
00358 Uml::Association_Type at = a->getAssocType();
00359 if (! assocTypeIsMappableToAttribute(at))
00360 continue;
00361 QString typeName, roleName;
00362 computeAssocTypeAndRole(a, c, typeName, roleName);
00363 if (roleName.isEmpty())
00364 continue;
00365 idl << getIndent() << "// " << UMLAssociation::typeAsString(at) << m_endl;
00366 idl << getIndent();
00367 if (isValuetype)
00368 idl << "public ";
00369 else
00370 idl << "attribute ";
00371 idl << typeName << " " << roleName << ";" << m_endl;
00372 }
00373 idl << m_endl;
00374 }
00375
00376 m_indentLevel--;
00377 idl << getIndent() << "};" << m_endl << m_endl;
00378
00379
00380 for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) {
00381 m_indentLevel--;
00382 idl << getIndent() << "};" << m_endl << m_endl;
00383 }
00384 file.close();
00385 emit codeGenerated(c, true);
00386 }
00387
00388
00389 void IDLWriter::writeOperation(UMLOperation *op, QTextStream &idl, bool is_comment) {
00390 UMLAttributeList atl = op->getParmList();
00391 QString rettype = op->getTypeName();
00392
00393 if (rettype.isEmpty())
00394 rettype = "void";
00395 idl << getIndent();
00396 if (is_comment)
00397 idl << "
00398 idl << rettype << " " << cleanName(op->getName()) << " (";
00399 if (atl.count()) {
00400 idl << m_endl;
00401 m_indentLevel++;
00402 uint i = 0;
00403 for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
00404 idl << getIndent();
00405 if (is_comment)
00406 idl << "
00407 Uml::Parameter_Direction pk = at->getParmKind();
00408 if (pk == Uml::pd_Out)
00409 idl << "out ";
00410 else if (pk == Uml::pd_InOut)
00411 idl << "inout ";
00412 else
00413 idl << "in ";
00414 idl << at->getTypeName() << " " << cleanName(at->getName());
00415 if (++i < atl.count())
00416 idl << "," << m_endl;
00417 }
00418 m_indentLevel--;
00419 }
00420 idl << ");" << m_endl << m_endl;
00421 }
00422
00423 QStringList IDLWriter::defaultDatatypes() {
00424 QStringList l;
00425 l.append("boolean");
00426 l.append("char");
00427 l.append("octet");
00428 l.append("short");
00429 l.append("unsigned short");
00430 l.append("long");
00431 l.append("unsigned long");
00432 l.append("float");
00433 l.append("double");
00434 l.append("string");
00435 l.append("any");
00436 return l;
00437 }
00438
00439 const QStringList IDLWriter::reservedKeywords() const {
00440
00441 static QStringList keywords;
00442
00443 if (keywords.isEmpty()) {
00444 keywords << "any"
00445 << "attribute"
00446 << "boolean"
00447 << "case"
00448 << "char"
00449 << "const"
00450 << "context"
00451 << "default"
00452 << "double"
00453 << "enum"
00454 << "exception"
00455 << "FALSE"
00456 << "float"
00457 << "in"
00458 << "inout"
00459 << "interface"
00460 << "long"
00461 << "module"
00462 << "octet"
00463 << "oneway"
00464 << "out"
00465 << "raises"
00466 << "readonly"
00467 << "sequence"
00468 << "short"
00469 << "string"
00470 << "struct"
00471 << "switch"
00472 << "TRUE"
00473 << "typedef"
00474 << "union"
00475 << "unsigned"
00476 << "void";
00477 }
00478
00479 return keywords;
00480 }
00481
00482
This file is part of the documentation for umbrello Version 3.1.0.