00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "tclwriter.h"
00019
00020 #include <qfile.h>
00021 #include <qtextstream.h>
00022 #include <qregexp.h>
00023 #include <kdebug.h>
00024
00025 #include "classifierinfo.h"
00026 #include "codegen_utils.h"
00027 #include "../umldoc.h"
00028 #include "../classifier.h"
00029 #include "../operation.h"
00030 #include "../template.h"
00031 #include "../umltemplatelist.h"
00032 #include "../umlclassifierlistitemlist.h"
00033 #include "../classifierlistitem.h"
00034 #include "../model_utils.h"
00035
00036 static const char *tclwords[] = {
00037 "body",
00038 "break",
00039 "case",
00040 "class",
00041 "common",
00042 "concat",
00043 "configbody",
00044 "constructor",
00045 "continue",
00046 "default",
00047 "destructor",
00048 "else",
00049 "elseif",
00050 "for",
00051 "foreach",
00052 "global",
00053 "if",
00054 "incr",
00055 "lappend",
00056 "lindex",
00057 "list",
00058 "llength",
00059 "load",
00060 "lrange",
00061 "lreplace",
00062 "method",
00063 "namespace",
00064 "private",
00065 "proc",
00066 "protected",
00067 "public",
00068 "return",
00069 "set",
00070 "source",
00071 "switch",
00072 "then",
00073 "upvar",
00074 "variable",
00075 "virtual",
00076 "while",
00077 0
00078 };
00079
00080 TclWriter::TclWriter()
00081 {
00082 }
00083
00084 TclWriter::~TclWriter()
00085 {
00086 }
00087
00088 Uml::Programming_Language
00089 TclWriter::getLanguage()
00090 {
00091 return Uml::pl_Tcl;
00092 }
00093
00094 void
00095 TclWriter::writeClass(UMLClassifier * c)
00096 {
00097
00098 if (!c) {
00099 kDebug() << "Cannot write class of NULL concept!\n";
00100 return;
00101 }
00102 QFile fileh, filetcl;
00103
00104
00105 QString fileName = findFileName(c, ".tcl");
00106 if (fileName.isEmpty()) {
00107 emit codeGenerated(c, false);
00108 return;
00109 }
00110
00111 if (!openFile(fileh, fileName)) {
00112 emit codeGenerated(c, false);
00113 return;
00114 }
00115
00116 classifierInfo = new ClassifierInfo(c, m_doc);
00117 classifierInfo->fileName = fileName;
00118 classifierInfo->className = cleanName(c->getName());
00119 mClass = cleanName(c->getName());
00120 if (!c->getPackage().isEmpty()) {
00121 mNamespace = "::" + cleanName(c->getPackage());
00122 mClassGlobal = mNamespace + "::" + mClass;
00123 } else {
00124 mNamespace = "::";
00125 mClassGlobal = "::" + mClass;
00126 }
00127
00128
00129 writeHeaderFile(c, fileh);
00130 fileh.close();
00131
00132
00133
00134 bool need_impl = true;
00135 if (!classifierInfo->isInterface) {
00136 if (c->getBaseType() == Uml::ot_Enum)
00137 need_impl = false;
00138 }
00139 if (need_impl) {
00140 if (!openFile(filetcl, fileName + "body")) {
00141 emit codeGenerated(c, false);
00142 return;
00143 }
00144
00145 writeSourceFile(c, filetcl);
00146 filetcl.close();
00147 }
00148
00149 classifierInfo = 0;
00150
00151 emit codeGenerated(c, true);
00152
00153 }
00154
00155 void
00156 TclWriter::writeHeaderFile(UMLClassifier * c, QFile & fileh)
00157 {
00158
00159 QTextStream stream(&fileh);
00160 mStream = &stream;
00161
00162
00163 m_indentLevel = 0;
00164
00165
00166 QString str = getHeadingFile(".tcl");
00167 if (!str.isEmpty()) {
00168 str.replace(QRegExp("%filename%"), classifierInfo->fileName);
00169 str.replace(QRegExp("%filepath%"), fileh.name());
00170 writeCode(str);
00171 }
00172
00173 writeCode("namespace eval " + mNamespace + " {");
00174 m_indentLevel++;
00175
00176
00177 writeComm("Do not load twice");
00178 writeCode("if {[namespace exist " + mClass + "]} return");
00179
00180
00181 UMLClassifierList superclasses = classifierInfo->superclasses;
00182 if (superclasses.count() > 0) {
00183 writeComm
00184 ("Source found and used class files and import class command if necessary");
00185
00186 for (UMLClassifier * classifier = superclasses.first(); classifier;
00187 classifier = superclasses.next()) {
00188 writeUse(classifier);
00189 }
00190 }
00191
00192 if (classifierInfo->hasAssociations) {
00193 writeAssociationIncl(classifierInfo->plainAssociations, c->getID(),
00194 "Associations");
00195 writeAssociationIncl(classifierInfo->aggregations, c->getID(),
00196 "Aggregations");
00197 writeAssociationIncl(classifierInfo->compositions, c->getID(),
00198 "Compositions");
00199 }
00200
00201 writeDocu("\n@class\t" + mClass + m_endl + c->getDoc());
00202
00203
00204 if ((c->getAbstract() || classifierInfo->isInterface)
00205 && !hasAbstractOps(c)) {
00206 writeComm("TODO abstract class" + mClass +
00207 "\nInherit from it and create only objects from the derived classes");
00208 }
00209
00210 if (!classifierInfo->isInterface) {
00211
00212 if (c->getBaseType() == Uml::ot_Enum) {
00213 UMLClassifierListItemList litList =
00214 c->getFilteredList(Uml::ot_EnumLiteral);
00215 writeCode("set enum_" + mClass + " [list\\");
00216 m_indentLevel++;
00217 for (UMLClassifierListItem * lit = litList.first(); lit;
00218 lit = litList.next()) {
00219 QString enumLiteral = cleanName(lit->getName());
00220 writeCode(enumLiteral + "\\");
00221 }
00222 m_indentLevel--;
00223 writeCode("];# end of enum");
00224 m_indentLevel--;
00225 writeCode("};# end of namespace");
00226 return;
00227 }
00228 }
00229
00230 UMLTemplateList template_params = c->getTemplateList();
00231 if (template_params.count()) {
00232 writeCode("#TODO template<");
00233 for (UMLTemplate * t = template_params.first(); t;
00234 t = template_params.next()) {
00235 QString formalName = t->getName();
00236 QString typeName = t->getTypeName();
00237 writeCode(typeName + "# " + formalName);
00238 }
00239 }
00240
00241 writeCode("class " + mClass + " {");
00242 m_indentLevel++;
00243 if (classifierInfo->superclasses.count() > 0) {
00244 QString code = "inherit";
00245 for (UMLClassifier * superClass = classifierInfo->superclasses.first();
00246 superClass; superClass = classifierInfo->superclasses.next()) {
00247
00248
00249
00250
00251 if (superClass->getPackage().isEmpty()) {
00252 code += " ::" + cleanName(superClass->getName());
00253 } else {
00254 code +=
00255 " ::" + cleanName(superClass->getPackage()) + "::" +
00256 cleanName(superClass->getName());
00257 }
00258 }
00259 writeCode(code);
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269 if (!classifierInfo->isInterface) {
00270 writeConstructorHeader();
00271 writeDestructorHeader();
00272 }
00273
00274 writeAttributeDecl(Uml::Visibility::Public, true);
00275 writeAttributeDecl(Uml::Visibility::Public, false);
00276
00277 writeAssociationDecl(classifierInfo->plainAssociations, Uml::Visibility::Public,
00278 c->getID(), "Associations");
00279 writeAssociationDecl(classifierInfo->aggregations, Uml::Visibility::Public, c->getID(),
00280 "Aggregations");
00281 writeAssociationDecl(classifierInfo->compositions, Uml::Visibility::Public, c->getID(),
00282 "Compositions");
00283
00284 writeOperationHeader(c, Uml::Visibility::Public);
00285
00286
00287
00288
00289 writeAttributeDecl(Uml::Visibility::Protected, true);
00290 writeAttributeDecl(Uml::Visibility::Protected, false);
00291
00292 writeAssociationDecl(classifierInfo->plainAssociations, Uml::Visibility::Protected,
00293 c->getID(), "Association");
00294 writeAssociationDecl(classifierInfo->aggregations, Uml::Visibility::Protected,
00295 c->getID(), "Aggregation");
00296 writeAssociationDecl(classifierInfo->compositions, Uml::Visibility::Protected,
00297 c->getID(), "Composition");
00298
00299 writeOperationHeader(c, Uml::Visibility::Protected);
00300
00301
00302
00303
00304 writeAttributeDecl(Uml::Visibility::Private, true);
00305 writeAttributeDecl(Uml::Visibility::Private, false);
00306
00307 writeAssociationDecl(classifierInfo->plainAssociations, Uml::Visibility::Private,
00308 c->getID(), "Associations");
00309 writeAssociationDecl(classifierInfo->aggregations, Uml::Visibility::Private, c->getID(),
00310 "Aggregations");
00311 writeAssociationDecl(classifierInfo->compositions, Uml::Visibility::Private, c->getID(),
00312 "Compositions");
00313
00314 writeOperationHeader(c, Uml::Visibility::Private);
00315 writeInitAttributeHeader();
00316
00317
00318 m_indentLevel--;
00319 writeCode("};# end of class");
00320
00321
00322 m_indentLevel--;
00323 writeCode("};# end of namespace");
00324 }
00325
00326 void
00327 TclWriter::writeSourceFile(UMLClassifier * c, QFile & filetcl)
00328 {
00329
00330 QTextStream stream(&filetcl);
00331 mStream = &stream;
00332
00333
00334 m_indentLevel = 0;
00335
00336
00337 QString str;
00338 str = getHeadingFile(".tclbody");
00339 if (!str.isEmpty()) {
00340 str.replace(QRegExp("%filename%"), classifierInfo->fileName + "body");
00341 str.replace(QRegExp("%filepath%"), filetcl.name());
00342 writeCode(str);
00343 }
00344
00345
00346
00347 if (!classifierInfo->isInterface) {
00348 writeConstructorSource();
00349 writeDestructorSource();
00350 }
00351
00352 writeAttributeSource();
00353
00354 writeAssociationSource(classifierInfo->plainAssociations, c->getID());
00355 writeAssociationSource(classifierInfo->aggregations, c->getID());
00356 writeAssociationSource(classifierInfo->compositions, c->getID());
00357
00358 writeOperationSource(c, Uml::Visibility::Public);
00359 writeOperationSource(c, Uml::Visibility::Protected);
00360 writeOperationSource(c, Uml::Visibility::Private);
00361
00362 writeInitAttributeSource();
00363 }
00364
00365 void
00366 TclWriter::writeCode(const QString &text)
00367 {
00368 *mStream << getIndent() << text << m_endl;
00369 }
00370
00371 void
00372 TclWriter::writeComm(const QString &text)
00373 {
00374 QStringList lines = QStringList::split("\n", text, true);
00375 for (uint i = 0; i < lines.count(); i++) {
00376 *mStream << getIndent() << "# " << lines[i] << m_endl;
00377 }
00378 }
00379
00380 void
00381 TclWriter::writeDocu(const QString &text)
00382 {
00383 QStringList lines = QStringList::split("\n", text, true);
00384 for (uint i = 0; i < lines.count(); i++) {
00385 *mStream << getIndent() << "## " << lines[i] << m_endl;
00386 }
00387 }
00388
00389
00390
00391
00392
00393 void
00394 TclWriter::writeAssociationIncl(UMLAssociationList list, Uml::IDType myId,
00395 const QString &type)
00396 {
00397 for (UMLAssociation * a = list.first(); a; a = list.next()) {
00398 UMLClassifier *classifier = NULL;
00399
00400 writeComm(m_endl + type + m_endl + a->toString() + m_endl + a->getDoc());
00401
00402
00403 if (a->getObjectId(Uml::A) == myId && !a->getRoleName(Uml::B).isEmpty()) {
00404 classifier = dynamic_cast < UMLClassifier * >(a->getObject(Uml::B));
00405 writeUse(classifier);
00406 } else if (a->getObjectId(Uml::B) == myId
00407 && !a->getRoleName(Uml::A).isEmpty()) {
00408 classifier = dynamic_cast < UMLClassifier * >(a->getObject(Uml::A));
00409 if (classifier->getPackage().isEmpty())
00410 writeCode("namespace eval " + cleanName(classifier->getName()) +
00411 " {}");
00412 } else {
00413
00414
00415
00416
00417
00418 }
00419 }
00420 }
00421
00422 void
00423 TclWriter::writeUse(UMLClassifier * c)
00424 {
00425 QString myNs;
00426
00427 if (!c->getPackage().isEmpty()) {
00428 myNs = cleanName(c->getPackage());
00429 } else {
00430 myNs = "";
00431 }
00432
00433 if (("::"+myNs) != mNamespace) {
00434 if (c->getPackage().isEmpty()) {
00435 writeCode("source " + findFileName(c, ".tcl"));
00436 writeCode("namespace import ::" + cleanName(c->getName()));
00437 } else {
00438 writeCode("package require " + myNs);
00439 writeCode("namespace import ::" + myNs + "::" +
00440 cleanName(c->getName()));
00441 }
00442 } else {
00443
00444 writeCode("source " + findFileName(c, ".tcl"));
00445 }
00446 }
00447
00448 void
00449 TclWriter::writeConstructorHeader()
00450 {
00451
00452 writeDocu
00453 (m_endl + "@func constructor" + m_endl +
00454 "@par args contain all configuration parameters" + m_endl);
00455
00456 writeCode("constructor {args} {}" + m_endl);
00457 }
00458
00459 void
00460 TclWriter::writeConstructorSource()
00461 {
00462 writeComm(mClassGlobal + "::constructor");
00463 writeCode(mClassGlobal + "::constructor {args} {");
00464 m_indentLevel++;
00465 if (classifierInfo->hasAttributes) {
00466 writeCode("initAttributes");
00467 }
00468 writeCode("eval configure $args");
00469 m_indentLevel--;
00470 writeCode('}' + m_endl);
00471 }
00472
00473 void
00474 TclWriter::writeDestructorHeader()
00475 {
00476
00477 writeDocu(m_endl + "@func destructor" + m_endl);
00478
00479 writeCode("destructor {} {}");
00480 }
00481
00482 void
00483 TclWriter::writeDestructorSource()
00484 {
00485 writeComm(mClassGlobal + "::destructor");
00486 writeCode(mClassGlobal + "::destructor {} {" + m_endl + '}' + m_endl);
00487 }
00488
00489 void
00490 TclWriter::writeAttributeDecl(Uml::Visibility visibility, bool writeStatic)
00491 {
00492 if (classifierInfo->isInterface)
00493 return;
00494
00495 QString scope = visibility.toString();
00496 QString type;
00497 if (writeStatic) {
00498 type = "common";
00499 } else {
00500 type = "variable";
00501 }
00502 UMLAttributeList *list = NULL;
00503 switch (visibility) {
00504 case Uml::Visibility::Private:
00505 if (writeStatic) {
00506 list = &(classifierInfo->static_atpriv);
00507 } else {
00508 list = &(classifierInfo->atpriv);
00509 }
00510 break;
00511
00512 case Uml::Visibility::Protected:
00513 if (writeStatic) {
00514 list = &(classifierInfo->static_atprot);
00515 } else {
00516 list = &(classifierInfo->atprot);
00517 }
00518 break;
00519
00520 case Uml::Visibility::Public:
00521 if (writeStatic) {
00522 list = &(classifierInfo->static_atpub);
00523 } else {
00524 list = &(classifierInfo->atpub);
00525 }
00526 break;
00527 default:
00528 break;
00529 }
00530
00531 if (list && list->count() > 0) {
00532 writeComm(m_endl + scope + ' ' + type + " attributes" + m_endl);
00533
00534 QString documentation;
00535 for (UMLAttribute * at = list->first(); at; at = list->next()) {
00536 documentation = at->getDoc();
00537 QString varName = cleanName(at->getName());
00538 QString typeName = fixTypeName(at->getTypeName());
00539 writeDocu(m_endl + "@var " + scope + ' ' + type + ' ' + typeName + ' ' +
00540 varName + m_endl + documentation);
00541 writeCode(scope + ' ' + type + ' ' + varName + m_endl);
00542 }
00543 }
00544 }
00545
00546 void
00547 TclWriter::writeAssociationDecl(UMLAssociationList associations,
00548 Uml::Visibility permitScope, Uml::IDType id,
00549 const QString &)
00550 {
00551 if (forceSections() || !associations.isEmpty()) {
00552 bool printRoleA = false, printRoleB = false;
00553 for (UMLAssociation * a = associations.first(); a;
00554 a = associations.next()) {
00555
00556
00557
00558 if (a->getObjectId(Uml::A) == id && !a->getRoleName(Uml::B).isEmpty())
00559 printRoleB = true;
00560
00561 if (a->getObjectId(Uml::B) == id && !a->getRoleName(Uml::A).isEmpty())
00562 printRoleA = true;
00563
00564
00565
00566 if (printRoleB && a->getVisibility(Uml::B) == permitScope) {
00567
00568 QString fieldClassName =
00569 cleanName(getUMLObjectName(a->getObject(Uml::B)));
00570 writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::B),
00571 a->getMulti(Uml::B), a->getRoleDoc(Uml::B),
00572 permitScope.toString());
00573 }
00574
00575 if (printRoleA && a->getVisibility(Uml::A) == permitScope) {
00576 QString fieldClassName =
00577 cleanName(getUMLObjectName(a->getObject(Uml::A)));
00578 writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::A),
00579 a->getMulti(Uml::A), a->getRoleDoc(Uml::A),
00580 permitScope.toString());
00581 }
00582
00583 printRoleA = false;
00584 printRoleB = false;
00585 }
00586 }
00587 }
00588
00589 void
00590 TclWriter::writeAssociationRoleDecl(const QString &fieldClassName, const QString &roleName,
00591 const QString &multi, const QString &doc, const QString &scope)
00592 {
00593
00594
00595 if (roleName.isEmpty())
00596 return;
00597
00598
00599
00600
00601
00602 if (multi.isEmpty() || multi.contains(QRegExp("^[01]$"))) {
00603 QString fieldVarName = roleName.lower();
00604
00605
00606
00607 if (ObjectFieldVariables.findIndex(fieldVarName) == -1 &&
00608 multi.contains(QRegExp("^1$"))
00609 ) {
00610
00611 ObjectFieldVariables.append(fieldVarName);
00612 ObjectFieldVariables.append(fieldClassName);
00613 }
00614 writeDocu(m_endl + "@var " + scope + " variable <" + fieldClassName +
00615 "> " + fieldVarName + m_endl + doc);
00616 writeCode(scope + " variable " + fieldVarName + m_endl);
00617 } else {
00618 QString fieldVarName = roleName.lower();
00619
00620
00621
00622 if (VectorFieldVariables.findIndex(fieldVarName) == -1)
00623 VectorFieldVariables.append(fieldVarName);
00624 writeDocu(m_endl + "@var" + scope + " variable <" + fieldClassName +
00625 "*> " + fieldVarName + m_endl + doc);
00626 writeCode(scope + " variable " + fieldVarName + m_endl);
00627 }
00628 }
00629
00630 void
00631 TclWriter::writeInitAttributeHeader()
00632 {
00633 if (classifierInfo->hasAttributes) {
00634 writeDocu("@method private initAttributes" + m_endl +
00635 "Initialize all internal variables");
00636 writeCode("private method initAttributes {}");
00637 }
00638 }
00639
00640 void
00641 TclWriter::writeInitAttributeSource()
00642 {
00643
00644 if (classifierInfo->hasAttributes) {
00645 QString varName;
00646
00647 writeComm(mClassGlobal + "::initAttributes");
00648 writeCode("body " + mClassGlobal + "::initAttributes {} {");
00649 m_indentLevel++;
00650
00651
00652 UMLAttributeList *atl = classifierInfo->getAttList();
00653 for (UMLAttribute * at = atl->first(); at; at = atl->next()) {
00654 if (!at->getInitialValue().isEmpty()) {
00655 varName = cleanName(at->getName());
00656 writeCode("set " + varName + ' ' + at->getInitialValue());
00657 }
00658 }
00659
00660 QStringList::Iterator it;
00661 for (it = VectorFieldVariables.begin();
00662 it != VectorFieldVariables.end(); ++it) {
00663 varName = *it;
00664 writeCode("set " + varName + " [list]");
00665 }
00666
00667 for (it = ObjectFieldVariables.begin();
00668 it != ObjectFieldVariables.end(); ++it) {
00669 varName = *it;
00670 it++;
00671 QString fieldClassName = *it;
00672 writeCode("set " + varName + " [list]");
00673 }
00674
00675 ObjectFieldVariables.clear();
00676 VectorFieldVariables.clear();
00677
00678 m_indentLevel--;
00679 writeCode('}' + m_endl);
00680 }
00681 }
00682
00683 void
00684 TclWriter::writeOperationHeader(UMLClassifier * c, Uml::Visibility permitScope)
00685 {
00686
00687 UMLOperationList oplist;
00688 UMLOperation *op;
00689 UMLAttribute *at;
00690 int j;
00691
00692
00693 UMLOperationList inputlist = c->getOpList();
00694 for (UMLOperation * op = inputlist.first(); op; op = inputlist.next()) {
00695 switch (op->getVisibility()) {
00696 case Uml::Visibility::Public:
00697 if (permitScope == Uml::Visibility::Public)
00698 oplist.append(op);
00699 break;
00700 case Uml::Visibility::Protected:
00701 if (permitScope == Uml::Visibility::Protected)
00702 oplist.append(op);
00703 break;
00704 case Uml::Visibility::Private:
00705 if (permitScope == Uml::Visibility::Private)
00706 oplist.append(op);
00707 break;
00708 default:
00709 break;
00710 }
00711 }
00712
00713
00714 if (oplist.count() > 0) {
00715 writeComm("Operations");
00716 }
00717 for (op = oplist.first(); op; op = oplist.next()) {
00718 QString doc = "";
00719 QString code = "";
00720 QString methodReturnType = fixTypeName(op->getTypeName());
00721 QString name = cleanName(op->getName());
00722 QString scope = permitScope.toString();
00723 if (op->getAbstract() || classifierInfo->isInterface) {
00724
00725
00726 }
00727
00728 if (op->getStatic()) {
00729 doc = m_endl + "@fn " + scope + " proc " + name + m_endl;
00730 code = scope + " proc " + name + " {";
00731 } else {
00732 doc = m_endl + "@fn " + scope + " method " + name + m_endl;
00733 code = scope + " method " + name + " {";
00734 }
00735
00736 UMLAttributeList atl = op->getParmList();
00737 j = 0;
00738 for (at = atl.first(); at; at = atl.next(), j++) {
00739 QString typeName = fixTypeName(at->getTypeName());
00740 QString atName = cleanName(at->getName());
00741 if (at->getInitialValue().isEmpty()) {
00742 doc +=
00743 "@param " + typeName + ' ' + atName + m_endl + at->getDoc() +
00744 m_endl;
00745 code += ' ' + atName;
00746 } else {
00747 doc +=
00748 "@param " + typeName + ' ' + atName + " (default=" +
00749 at->getInitialValue() + ") " + m_endl + at->getDoc() + m_endl;
00750 code += " {" + atName + ' ' + at->getInitialValue() + "} ";
00751 }
00752 }
00753 if (methodReturnType != "void") {
00754 doc += "@return " + methodReturnType + m_endl;
00755 }
00756 writeDocu(doc + op->getDoc());
00757 writeCode(code + "} {}" + m_endl);
00758 }
00759 }
00760
00761 void
00762 TclWriter::writeOperationSource(UMLClassifier * c, Uml::Visibility permitScope)
00763 {
00764
00765 UMLOperationList oplist;
00766 UMLOperation *op;
00767 UMLAttribute *at;
00768 int j;
00769
00770
00771 UMLOperationList inputlist = c->getOpList();
00772 for (UMLOperation * op = inputlist.first(); op; op = inputlist.next()) {
00773 switch (op->getVisibility()) {
00774 case Uml::Visibility::Public:
00775 if (permitScope == Uml::Visibility::Public)
00776 oplist.append(op);
00777 break;
00778 case Uml::Visibility::Protected:
00779 if (permitScope == Uml::Visibility::Protected)
00780 oplist.append(op);
00781 break;
00782 case Uml::Visibility::Private:
00783 if (permitScope == Uml::Visibility::Private)
00784 oplist.append(op);
00785 break;
00786 default:
00787 break;
00788 }
00789 }
00790
00791
00792 for (op = oplist.first(); op; op = oplist.next()) {
00793 QString code = "";
00794 QString methodReturnType = fixTypeName(op->getTypeName());
00795 QString name;
00796
00797 if (op->getAbstract() || classifierInfo->isInterface) {
00798 continue;
00799 }
00800 name = mClassGlobal + "::" + cleanName(op->getName());
00801 writeComm(name);
00802 code = "body " + name + " {";
00803
00804 UMLAttributeList atl = op->getParmList();
00805 j = 0;
00806 for (at = atl.first(); at; at = atl.next(), j++) {
00807 QString atName = cleanName(at->getName());
00808 if (at->getInitialValue().isEmpty()) {
00809 code += ' ' + atName;
00810 } else {
00811 code += " {" + atName + ' ' + at->getInitialValue() + "} ";
00812 }
00813 }
00814 writeCode(code += "} {");
00815 m_indentLevel++;
00816 if (methodReturnType != "void") {
00817 writeCode("return " + methodReturnType);
00818 } else {
00819 writeCode("return");
00820 }
00821 m_indentLevel--;
00822 writeCode('}' + m_endl);
00823 }
00824 }
00825
00826 void
00827 TclWriter::writeAttributeSource()
00828 {
00829 UMLAttributeList *list = &(classifierInfo->atpub);
00830 UMLAttribute *at;
00831 for (at = list->first(); at; at = list->next()) {
00832 QString name = mClassGlobal + "::" + cleanName(at->getName());
00833
00834 writeComm(name);
00835 writeCode("configbody " + name + " {} {" + m_endl + '}' + m_endl);
00836 }
00837 }
00838
00839 void
00840 TclWriter::writeAssociationSource(UMLAssociationList associations,
00841 Uml::IDType id)
00842 {
00843 if (associations.isEmpty()) {
00844 return;
00845 }
00846
00847 bool printRoleA = false, printRoleB = false;
00848 for (UMLAssociation * a = associations.first(); a; a = associations.next()) {
00849
00850
00851
00852 if (a->getObjectId(Uml::A) == id && !a->getRoleName(Uml::B).isEmpty())
00853 printRoleB = true;
00854
00855 if (a->getObjectId(Uml::B) == id && !a->getRoleName(Uml::A).isEmpty())
00856 printRoleA = true;
00857
00858
00859 if (printRoleB && a->getVisibility(Uml::B) == Uml::Visibility::Public) {
00860
00861 QString fieldClassName =
00862 cleanName(getUMLObjectName(a->getObject(Uml::B)));
00863 writeAssociationRoleSource(fieldClassName, a->getRoleName(Uml::B),
00864 a->getMulti(Uml::B));
00865 }
00866
00867 if (printRoleA && a->getVisibility(Uml::A) == Uml::Visibility::Public) {
00868 QString fieldClassName =
00869 cleanName(getUMLObjectName(a->getObject(Uml::A)));
00870 writeAssociationRoleSource(fieldClassName, a->getRoleName(Uml::A),
00871 a->getMulti(Uml::A));
00872 }
00873
00874 printRoleA = false;
00875 printRoleB = false;
00876 }
00877 }
00878
00879 void
00880 TclWriter::writeAssociationRoleSource(const QString &fieldClassName,
00881 const QString &roleName, const QString &multi)
00882 {
00883
00884
00885 if (roleName.isEmpty())
00886 return;
00887
00888
00889
00890
00891 if (multi.isEmpty() || multi.contains(QRegExp("^[01]$"))) {
00892 QString fieldVarName = roleName.lower();
00893
00894 writeCode("configbody " + mClassGlobal + "::" + fieldVarName + " {} {");
00895 m_indentLevel++;
00896 writeCode("if {![$" + fieldVarName + " isa " + fieldClassName + "]} {");
00897 m_indentLevel++;
00898 writeCode("return -code error \"expected object of class: " +
00899 fieldClassName + "\"");
00900 m_indentLevel--;
00901 writeCode("}");
00902 m_indentLevel--;
00903
00904 } else {
00905 QString fieldVarName = roleName.lower();
00906
00907 writeCode("configbody " + mClassGlobal + "::" + fieldVarName + " {} {");
00908 m_indentLevel++;
00909 writeCode("foreach myObj $" + fieldVarName + " {");
00910 m_indentLevel++;
00911 writeCode("if {![$myObj isa " + fieldClassName + "]} {");
00912 m_indentLevel++;
00913 writeCode("return -code error \"expected object of class: " +
00914 fieldClassName + "\"");
00915 m_indentLevel--;
00916 writeCode("}");
00917 m_indentLevel--;
00918 writeCode("}");
00919 m_indentLevel--;
00920 }
00921 writeCode('}' + m_endl);
00922 }
00923
00924 QString
00925 TclWriter::fixTypeName(const QString &string)
00926 {
00927 if (string.isEmpty())
00928 return "void";
00929 return string;
00930 }
00931
00932
00933 QString
00934 TclWriter::getUMLObjectName(UMLObject * obj)
00935 {
00936 return (obj != 0) ? obj->getName() : QString("NULL");
00937 }
00938
00939 const QStringList
00940 TclWriter::reservedKeywords() const
00941 {
00942 static QStringList keywords;
00943
00944 if (keywords.isEmpty())
00945 {
00946 for (int i = 0; tclwords[i]; i++)
00947 keywords.append(tclwords[i]);
00948 }
00949 return keywords;
00950 }
00951