pascalwriter.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "pascalwriter.h"
00013
00014 #include <kdebug.h>
00015 #include <klocale.h>
00016 #include <kmessagebox.h>
00017 #include <qfile.h>
00018 #include <qregexp.h>
00019 #include <qtextstream.h>
00020
00021 #include "../umldoc.h"
00022 #include "../uml.h"
00023 #include "../classifier.h"
00024 #include "../enum.h"
00025 #include "../classifierlistitem.h"
00026 #include "../umlclassifierlistitemlist.h"
00027 #include "../umltemplatelist.h"
00028 #include "../folder.h"
00029 #include "../association.h"
00030 #include "../attribute.h"
00031 #include "../operation.h"
00032 #include "../template.h"
00033 #include "../umlnamespace.h"
00034 #include "classifierinfo.h"
00035
00036 const QString PascalWriter::defaultPackageSuffix = "_Holder";
00037
00038 PascalWriter::PascalWriter() {
00039 }
00040
00041 PascalWriter::~PascalWriter() {}
00042
00046 Uml::Programming_Language PascalWriter::getLanguage() {
00047 return Uml::pl_Pascal;
00048 }
00049
00050
00051 bool PascalWriter::isOOClass(UMLClassifier *c) {
00052 Uml::Object_Type ot = c->getBaseType();
00053 if (ot == Uml::ot_Interface)
00054 return true;
00055 if (ot == Uml::ot_Enum)
00056 return false;
00057 if (ot != Uml::ot_Class) {
00058 kDebug() << "PascalWriter::isOOClass: unknown object type " << ot << endl;
00059 return false;
00060 }
00061 QString stype = c->getStereotype();
00062 if (stype == "CORBAConstant" || stype == "CORBATypedef" ||
00063 stype == "CORBAStruct" || stype == "CORBAUnion")
00064 return false;
00065
00066
00067 return true;
00068 }
00069
00070 QString PascalWriter::qualifiedName(UMLPackage *p, bool withType, bool byValue) {
00071 UMLPackage *umlPkg = p->getUMLPackage();
00072 QString className = cleanName(p->getName());
00073 QString retval;
00074
00075 if (umlPkg == UMLApp::app()->getDocument()->getRootFolder(Uml::mt_Logical))
00076 umlPkg = NULL;
00077
00078 UMLClassifier *c = dynamic_cast<UMLClassifier*>(p);
00079 if (umlPkg == NULL) {
00080 retval = className;
00081 if (c == NULL || !isOOClass(c))
00082 retval.append(defaultPackageSuffix);
00083 } else {
00084 retval = umlPkg->getFullyQualifiedName(".");
00085 if (isOOClass(c)) {
00086 retval.append(".");
00087 retval.append(className);
00088 }
00089 }
00090 if (! withType)
00091 return retval;
00092 if (c && isOOClass(c)) {
00093 retval.append(".Object");
00094 if (! byValue)
00095 retval.append("_Ptr");
00096 } else {
00097 retval.append(".");
00098 retval.append(className);
00099 }
00100 return retval;
00101 }
00102
00103 void PascalWriter::computeAssocTypeAndRole
00104 (UMLAssociation *a, QString& typeName, QString& roleName) {
00105 roleName = a->getRoleName(Uml::A);
00106 if (roleName.isEmpty()) {
00107 if (a->getMulti(Uml::A).isEmpty()) {
00108 roleName = "M_";
00109 roleName.append(typeName);
00110 } else {
00111 roleName = typeName;
00112 roleName.append("_Vector");
00113 }
00114 }
00115 UMLClassifier* c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A));
00116 if (c == NULL)
00117 return;
00118 typeName = cleanName(c->getName());
00119 if (! a->getMulti(Uml::A).isEmpty())
00120 typeName.append("_Array_Access");
00121 }
00122
00123 void PascalWriter::writeClass(UMLClassifier *c) {
00124 if (!c) {
00125 kDebug() << "Cannot write class of NULL concept!" << endl;
00126 return;
00127 }
00128
00129 const bool isClass = !c->isInterface();
00130 QString classname = cleanName(c->getName());
00131 QString fileName = qualifiedName(c).lower();
00132 fileName.replace('.', '-');
00133
00134
00135 fileName = overwritableName(c, fileName, ".pas");
00136 if (fileName.isEmpty()) {
00137 emit codeGenerated(c, false);
00138 return;
00139 }
00140
00141 QFile file;
00142 if (!openFile(file, fileName)) {
00143 emit codeGenerated(c, false);
00144 return;
00145 }
00146
00147
00148
00149 QTextStream pas(&file);
00150
00151 QString str;
00152 str = getHeadingFile(".pas");
00153 if (!str.isEmpty()) {
00154 str.replace(QRegExp("%filename%"), fileName);
00155 str.replace(QRegExp("%filepath%"), file.name());
00156 pas << str << endl;
00157 }
00158
00159 QString unit = qualifiedName(c);
00160 pas << "unit " << unit << ";" << m_endl << m_endl;
00161 pas << "INTERFACE" << m_endl << m_endl;
00162
00163 UMLPackageList imports;
00164 findObjectsRelated(c, imports);
00165 if (imports.count()) {
00166 pas << "uses" << m_endl;
00167 bool first = true;
00168 for (UMLPackage *con = imports.first(); con; con = imports.next()) {
00169 if (con->getBaseType() != Uml::ot_Datatype) {
00170 if (first)
00171 first = false;
00172 else
00173 pas << "," << m_endl;
00174 pas << " " << qualifiedName(con);
00175 }
00176 }
00177 pas << ";" << m_endl << m_endl;
00178 }
00179
00180 pas << "type" << m_endl;
00181 m_indentLevel++;
00182 if (c->getBaseType() == Uml::ot_Enum) {
00183 UMLEnum *ue = static_cast<UMLEnum*>(c);
00184 UMLClassifierListItemList litList = ue->getFilteredList(Uml::ot_EnumLiteral);
00185 uint i = 0;
00186 pas << getIndent() << classname << " = (" << m_endl;
00187 m_indentLevel++;
00188 for (UMLClassifierListItem *lit = litList.first(); lit; lit = litList.next()) {
00189 QString enumLiteral = cleanName(lit->getName());
00190 pas << getIndent() << enumLiteral;
00191 if (++i < litList.count())
00192 pas << "," << m_endl;
00193 }
00194 m_indentLevel--;
00195 pas << ");" << m_endl << m_endl;
00196 m_indentLevel--;
00197 pas << "end." << m_endl << m_endl;
00198 return;
00199 }
00200 UMLAttributeList atl = c->getAttributeList();
00201 if (! isOOClass(c)) {
00202 QString stype = c->getStereotype();
00203 if (stype == "CORBAConstant") {
00204 pas << getIndent() << "// " << stype << " is Not Yet Implemented" << m_endl << m_endl;
00205 } else if(stype == "CORBAStruct") {
00206 if (isClass) {
00207 UMLAttribute *at;
00208 pas << getIndent() << classname << " = record" << m_endl;
00209 m_indentLevel++;
00210 for (at = atl.first(); at; at = atl.next()) {
00211 QString name = cleanName(at->getName());
00212 QString typeName = at->getTypeName();
00213 pas << getIndent() << name << " : " << typeName;
00214 QString initialVal = at->getInitialValue();
00215 if (initialVal.latin1() && ! initialVal.isEmpty())
00216 pas << " := " << initialVal;
00217 pas << ";" << m_endl;
00218 }
00219 m_indentLevel--;
00220 pas << "end;" << m_endl << m_endl;
00221 }
00222 } else if(stype == "CORBAUnion") {
00223 pas << getIndent() << "// " << stype << " is Not Yet Implemented" << m_endl << m_endl;
00224 } else if(stype == "CORBATypedef") {
00225 pas << getIndent() << "// " << stype << " is Not Yet Implemented" << m_endl << m_endl;
00226 } else {
00227 pas << getIndent() << "// " << stype << ": Unknown stereotype" << m_endl << m_endl;
00228 }
00229 m_indentLevel--;
00230 pas << getIndent() << "end." << m_endl << m_endl;
00231 return;
00232 }
00233
00234
00235 if (forceDoc() || !c->getDoc().isEmpty()) {
00236 pas << "//" << m_endl;
00237 pas << "// class " << classname << endl;
00238 pas << formatDoc(c->getDoc(), "// ");
00239 pas << m_endl;
00240 }
00241
00242 UMLClassifierList superclasses = c->getSuperClasses();
00243
00244 pas << getIndent() << classname << " = object";
00245 if (!superclasses.isEmpty()) {
00246
00247 UMLClassifier* parent = superclasses.first();
00248 pas << "(" << qualifiedName(parent) << ")";
00249 }
00250 pas << m_endl;
00251
00252 ClassifierInfo info(c, UMLApp::app()->getDocument());
00253 UMLAttributeList atpub = info.atpub;
00254 if (isClass && (forceSections() || atpub.count())) {
00255 pas << getIndent() << "// Public attributes:" << m_endl;
00256 UMLAttribute *at;
00257 for (at = atpub.first(); at; at = atpub.next()) {
00258
00259
00260 pas << getIndent() << cleanName(at->getName()) << " : "
00261 << at->getTypeName();
00262 if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty())
00263 pas << " := " << at->getInitialValue();
00264 pas << ";" << m_endl;
00265 }
00266 }
00267 bool haveAttrs = (isClass && atl.count());
00268
00269
00270 UMLOperationList opl(c->getOpList());
00271 UMLOperationList oppub;
00272 oppub.setAutoDelete(false);
00273 UMLOperation *op;
00274 for (op = opl.first(); op; op = opl.next()) {
00275 if (op->getVisibility() == Uml::Visibility::Public)
00276 oppub.append(op);
00277 }
00278 if (forceSections() || oppub.count())
00279 pas << getIndent() << "// Public methods:" << m_endl << m_endl;
00280 for (op = oppub.first(); op; op = oppub.next())
00281 writeOperation(op, pas);
00282
00283 if (info.atprot.count()) {
00284 pas << "protected" << m_endl << m_endl;
00285 UMLAttribute *at;
00286 UMLAttributeList atprot = info.atprot;
00287 for (at = atprot.first(); at; at = atprot.next()) {
00288
00289
00290 pas << getIndent() << cleanName(at->getName()) << " : "
00291 << at->getTypeName();
00292 if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty())
00293 pas << " := " << at->getInitialValue();
00294 pas << ";" << m_endl;
00295 }
00296 pas << m_endl;
00297 }
00298 if (info.atpriv.count()) {
00299 pas << "private" << m_endl << m_endl;
00300 UMLAttribute *at;
00301 UMLAttributeList atpriv = info.atpriv;
00302 for (at = atpriv.first(); at; at = atpriv.next()) {
00303
00304
00305 pas << getIndent() << cleanName(at->getName()) << " : "
00306 << at->getTypeName();
00307 if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty())
00308 pas << " := " << at->getInitialValue();
00309 pas << ";" << m_endl;
00310 }
00311 pas << m_endl;
00312 }
00313 pas << getIndent() << "end;" << m_endl << m_endl;
00314
00315 pas << getIndent() << "P" << classname << " = ^" << classname <<";" << m_endl << m_endl;
00316
00317 m_indentLevel--;
00318 pas << "end;" << m_endl << m_endl;
00319 file.close();
00320 emit codeGenerated(c, true);
00321 }
00322
00323
00324 void PascalWriter::writeOperation(UMLOperation *op, QTextStream &pas, bool is_comment) {
00325 if (op->getStatic()) {
00326 pas << "// TODO: generate status method " << op->getName() << m_endl;
00327 return;
00328 }
00329 UMLAttributeList atl = op->getParmList();
00330 QString rettype = op->getTypeName();
00331 bool use_procedure = (rettype.isEmpty() || rettype == "void");
00332
00333 pas << getIndent();
00334 if (is_comment)
00335 pas << "
00336 if (use_procedure)
00337 pas << "procedure ";
00338 else
00339 pas << "function ";
00340 pas << cleanName(op->getName()) << " ";
00341 if (atl.count()) {
00342 pas << "(" << m_endl;
00343 uint i = 0;
00344 m_indentLevel++;
00345 for (UMLAttribute *at = atl.first(); at; at = atl.next()) {
00346 pas << getIndent();
00347 if (is_comment)
00348 pas << "
00349 pas << cleanName(at->getName()) << " : ";
00350 Uml::Parameter_Direction pk = at->getParmKind();
00351 if (pk != Uml::pd_In)
00352 pas << "var ";
00353 pas << at->getTypeName();
00354 if (! at->getInitialValue().isEmpty())
00355 pas << " := " << at->getInitialValue();
00356 if (++i < (uint)atl.count())
00357 pas << ";" << m_endl;
00358 }
00359 m_indentLevel--;
00360 pas << ")";
00361 }
00362 if (! use_procedure)
00363 pas << " : " << rettype;
00364 pas << "; virtual; abstract;" << m_endl << m_endl;
00365
00366
00367 }
00368
00369 QStringList PascalWriter::defaultDatatypes() {
00370 QStringList l;
00371 l.append("AnsiString");
00372 l.append("Boolean");
00373 l.append("Byte");
00374 l.append("ByteBool");
00375 l.append("Cardinal");
00376 l.append("Character");
00377 l.append("Currency");
00378 l.append("Double");
00379 l.append("Extended");
00380 l.append("Int64");
00381 l.append("Integer");
00382 l.append("Longint");
00383 l.append("LongBool");
00384 l.append("Longword");
00385 l.append("QWord");
00386 l.append("Real");
00387 l.append("Shortint");
00388 l.append("ShortString");
00389 l.append("Single");
00390 l.append("Smallint");
00391 l.append("String");
00392 l.append("WideString");
00393 l.append("Word");
00394 return l;
00395 }
00396
00403 bool PascalWriter::isReservedKeyword(const QString & rPossiblyReservedKeyword) {
00404
00405 const QStringList keywords = reservedKeywords();
00406
00407 QStringList::ConstIterator it;
00408 for (it = keywords.begin(); it != keywords.end(); ++it)
00409 if ((*it).lower() == rPossiblyReservedKeyword.lower())
00410 return true;
00411
00412 return false;
00413 }
00414
00418 const QStringList PascalWriter::reservedKeywords() const {
00419
00420 static QStringList keywords;
00421
00422 if ( keywords.isEmpty() ) {
00423 keywords.append( "absolute" );
00424 keywords.append( "abstract" );
00425 keywords.append( "and" );
00426 keywords.append( "array" );
00427 keywords.append( "as" );
00428 keywords.append( "asm" );
00429 keywords.append( "assembler" );
00430 keywords.append( "automated" );
00431 keywords.append( "begin" );
00432 keywords.append( "case" );
00433 keywords.append( "cdecl" );
00434 keywords.append( "class" );
00435 keywords.append( "const" );
00436 keywords.append( "constructor" );
00437 keywords.append( "contains" );
00438 keywords.append( "default" );
00439 keywords.append( "deprecated" );
00440 keywords.append( "destructor" );
00441 keywords.append( "dispid" );
00442 keywords.append( "dispinterface" );
00443 keywords.append( "div" );
00444 keywords.append( "do" );
00445 keywords.append( "downto" );
00446 keywords.append( "dynamic" );
00447 keywords.append( "else" );
00448 keywords.append( "end" );
00449 keywords.append( "except" );
00450 keywords.append( "export" );
00451 keywords.append( "exports" );
00452 keywords.append( "external" );
00453 keywords.append( "far" );
00454 keywords.append( "file" );
00455 keywords.append( "final" );
00456 keywords.append( "finalization" );
00457 keywords.append( "finally" );
00458 keywords.append( "for" );
00459 keywords.append( "forward" );
00460 keywords.append( "function" );
00461 keywords.append( "goto" );
00462 keywords.append( "if" );
00463 keywords.append( "implementation" );
00464 keywords.append( "implements" );
00465 keywords.append( "in" );
00466 keywords.append( "index" );
00467 keywords.append( "inherited" );
00468 keywords.append( "initialization" );
00469 keywords.append( "inline" );
00470 keywords.append( "inline" );
00471 keywords.append( "interface" );
00472 keywords.append( "is" );
00473 keywords.append( "label" );
00474 keywords.append( "library" );
00475 keywords.append( "library" );
00476 keywords.append( "local" );
00477 keywords.append( "message" );
00478 keywords.append( "mod" );
00479 keywords.append( "name" );
00480 keywords.append( "near" );
00481 keywords.append( "nil" );
00482 keywords.append( "nodefault" );
00483 keywords.append( "not" );
00484 keywords.append( "object" );
00485 keywords.append( "of" );
00486 keywords.append( "or" );
00487 keywords.append( "out" );
00488 keywords.append( "overload" );
00489 keywords.append( "override" );
00490 keywords.append( "package" );
00491 keywords.append( "packed" );
00492 keywords.append( "pascal" );
00493 keywords.append( "platform" );
00494 keywords.append( "private" );
00495 keywords.append( "procedure" );
00496 keywords.append( "program" );
00497 keywords.append( "property" );
00498 keywords.append( "protected" );
00499 keywords.append( "public" );
00500 keywords.append( "published" );
00501 keywords.append( "raise" );
00502 keywords.append( "read" );
00503 keywords.append( "readonly" );
00504 keywords.append( "record" );
00505 keywords.append( "register" );
00506 keywords.append( "reintroduce" );
00507 keywords.append( "repeat" );
00508 keywords.append( "requires" );
00509 keywords.append( "resident" );
00510 keywords.append( "resourcestring" );
00511 keywords.append( "safecall" );
00512 keywords.append( "sealed" );
00513 keywords.append( "set" );
00514 keywords.append( "shl" );
00515 keywords.append( "shr" );
00516 keywords.append( "static" );
00517 keywords.append( "stdcall" );
00518 keywords.append( "stored" );
00519 keywords.append( "string" );
00520 keywords.append( "then" );
00521 keywords.append( "threadvar" );
00522 keywords.append( "to" );
00523 keywords.append( "try" );
00524 keywords.append( "type" );
00525 keywords.append( "unit" );
00526 keywords.append( "unsafe" );
00527 keywords.append( "until" );
00528 keywords.append( "uses" );
00529 keywords.append( "var" );
00530 keywords.append( "varargs" );
00531 keywords.append( "virtual" );
00532 keywords.append( "while" );
00533 keywords.append( "with" );
00534 keywords.append( "write" );
00535 keywords.append( "writeonly" );
00536 keywords.append( "xor" );
00537 }
00538
00539 return keywords;
00540 }
00541
00542 #include "pascalwriter.moc"
This file is part of the documentation for umbrello Version 3.1.0.