00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "perlwriter.h"
00018 #include "../classifier.h"
00019 #include "../operation.h"
00020 #include "../umldoc.h"
00021 #include "../association.h"
00022 #include "../attribute.h"
00023 #include "../uml.h"
00024
00025 #include <kdebug.h>
00026 #include <qregexp.h>
00027 #include <qstring.h>
00028 #include <qdir.h>
00029 #include <qdatetime.h>
00030 #include <qtextstream.h>
00031
00032 PerlWriter::PerlWriter()
00033 {
00034 }
00035
00036 PerlWriter::~PerlWriter() {}
00037
00038 bool PerlWriter::GetUseStatements(UMLClassifier *c, QString &Ret,
00039 QString &ThisPkgName){
00040
00041 if(!c){
00042 return(false);
00043 }
00044
00045 UMLPackageList includes;
00046 findObjectsRelated(c,includes);
00047 UMLPackage *conc;
00048 QString AV = "@";
00049 QString SV = "$";
00050 QString HV = "%";
00051 for(conc = includes.first(); conc ;conc = includes.next()) {
00052 if (conc->getBaseType() == Uml::ot_Datatype)
00053 continue;
00054 QString neatName = cleanName(conc->getName());
00055 if (neatName != AV && neatName != SV && neatName != HV) {
00056 QString OtherPkgName = conc->getPackage(".");
00057 OtherPkgName.replace(QRegExp("\\."),"::");
00058 QString OtherName = OtherPkgName + "::" + cleanName(conc->getName());
00059
00060
00061
00062
00063 if(OtherName != ThisPkgName){
00064 Ret += "use ";
00065 Ret += OtherName;
00066 Ret += ';';
00067 Ret += m_endl;
00068 }
00069 }
00070 }
00071 UMLClassifierList superclasses = c->getSuperClasses();
00072 if (superclasses.count()) {
00073 Ret += m_endl;
00074 Ret += "use base qw( ";
00075 for (UMLClassifier *obj = superclasses.first();
00076 obj; obj = superclasses.next()) {
00077 QString packageName = obj->getPackage(".");
00078 packageName.replace(QRegExp("\\."),"::");
00079
00080 Ret += packageName + "::" + cleanName(obj->getName()) + ' ';
00081 }
00082 Ret += ");" + m_endl;
00083 }
00084
00085 return(true);
00086 }
00087
00088 void PerlWriter::writeClass(UMLClassifier *c) {
00089
00090
00091
00092
00093
00094
00095 QString classname = cleanName(c->getName());
00096 QString packageName = c->getPackage(".");
00097 QString fileName;
00098
00099
00100 packageName.simplifyWhiteSpace();
00101
00102
00103 packageName.replace(QRegExp(" "), "_");
00104
00105
00106
00107 packageName.replace(QRegExp("\\."),"::");
00108
00109
00110 QString ThisPkgName = packageName + "::" + classname;
00111
00112 fileName = findFileName(c, ".pm");
00113
00114
00115
00116
00117
00118
00119 CodeGenerationPolicy *pol = UMLApp::app()->getCommonPolicy();
00120 QString curDir = pol->getOutputDirectory().absPath();
00121 if (fileName.contains("::")) {
00122
00123 QString newDir;
00124 newDir = curDir;
00125 QString fragment = fileName;
00126 QDir* existing = new QDir (curDir);
00127 QRegExp regEx("(.*)(::)");
00128 regEx.setMinimal(true);
00129 while (regEx.search(fragment) > -1) {
00130 newDir = regEx.cap(1);
00131 fragment.remove(0, (regEx.pos(2) + 2));
00132 existing->setPath(curDir + '/' + newDir);
00133 if (! existing->exists()) {
00134 existing->setPath(curDir);
00135 if (! existing->mkdir(newDir)) {
00136 emit codeGenerated(c, false);
00137 return;
00138 }
00139 }
00140 curDir += '/' + newDir;
00141 }
00142 fileName = fragment + ".pm";
00143 }
00144 if (fileName.isEmpty()) {
00145 emit codeGenerated(c, false);
00146 return;
00147 }
00148 QString oldDir = pol->getOutputDirectory().absPath();
00149 pol->setOutputDirectory(curDir);
00150 QFile fileperl;
00151 if(!openFile(fileperl, fileName)) {
00152 emit codeGenerated(c, false);
00153 return;
00154 }
00155 QTextStream perl(&fileperl);
00156 pol->setOutputDirectory(oldDir);
00157
00158
00159
00160
00161
00162
00163 QString str;
00164 bool bPackageDeclared = false;
00165 bool bUseStmsWritten = false;
00166
00167 str = getHeadingFile(".pm");
00168 if(!str.isEmpty()) {
00169 str.replace(QRegExp("%filename%"),fileName);
00170 str.replace(QRegExp("%filepath%"),fileperl.name());
00171 str.replace(QRegExp("%year%"),QDate::currentDate().toString("yyyy"));
00172 str.replace(QRegExp("%date%"),QDate::currentDate().toString());
00173 str.replace(QRegExp("%time%"),QTime::currentTime().toString());
00174 str.replace(QRegExp("%package-name%"),ThisPkgName);
00175 if(str.find(QRegExp("%PACKAGE-DECLARE%"))){
00176 str.replace(QRegExp("%PACKAGE-DECLARE%"),
00177 "package " + ThisPkgName + ';'
00178 + m_endl + m_endl
00179 + "#UML_MODELER_BEGIN_PERSONAL_VARS_" + classname
00180 + m_endl + m_endl
00181 + "#UML_MODELER_END_PERSONAL_VARS_" + classname
00182 + m_endl
00183 );
00184 bPackageDeclared = true;
00185 }
00186
00187 if(str.find(QRegExp("%USE-STATEMENTS%"))){
00188 QString UseStms;
00189 if(GetUseStatements(c,UseStms,ThisPkgName)){
00190 str.replace(QRegExp("%USE-STATEMENTS%"), UseStms);
00191 bUseStmsWritten = true;
00192 }
00193 }
00194
00195 perl<<str<<m_endl;
00196 }
00197
00198
00199
00200 if(! bPackageDeclared){
00201 perl << m_endl << m_endl << "package " <<ThisPkgName << ";" << m_endl
00202 << m_endl;
00203
00204 perl << m_endl << "#UML_MODELER_BEGIN_PERSONAL_VARS_" << classname
00205 << m_endl ;
00206 perl << m_endl << "#UML_MODELER_END_PERSONAL_VARS_" << classname
00207 << m_endl << m_endl ;
00208 }
00209
00210 if(! bUseStmsWritten){
00211 QString UseStms;
00212 if(GetUseStatements(c,UseStms,ThisPkgName)){
00213 perl<<UseStms<<m_endl;
00214 }
00215 }
00216
00217 perl << m_endl;
00218
00219
00220 UMLAssociationList aggregations = c->getAggregations();
00221 UMLAssociationList compositions = c->getCompositions();
00222
00223
00224 if(forceDoc() || !c->getDoc().isEmpty()) {
00225 perl << m_endl << "=head1";
00226 perl << " " << classname.upper() << m_endl << m_endl;
00227 perl << c->getDoc();
00228 perl << m_endl << m_endl << "=cut" << m_endl << m_endl;
00229 }
00230
00231
00232 if(c->getAbstract())
00233 perl << "=head1 ABSTRACT CLASS" << m_endl << m_endl << "=cut" << m_endl;
00234
00235
00236 if (! c->isInterface())
00237 writeAttributes(c, perl);
00238
00239
00240 writeOperations(c,perl);
00241
00242 perl << m_endl;
00243
00244
00245
00246 perl << m_endl << m_endl << "return 1;" << m_endl;
00247
00248
00249 fileperl.close();
00250 emit codeGenerated(c, true);
00251 }
00252
00256 Uml::Programming_Language PerlWriter::getLanguage() {
00257 return Uml::pl_Perl;
00258 }
00259
00261
00262
00263 void PerlWriter::writeOperations(UMLClassifier *c, QTextStream &perl) {
00264
00265
00266 UMLOperationList oppub,opprot,oppriv;
00267
00268 oppub.setAutoDelete(false);
00269 opprot.setAutoDelete(false);
00270 oppriv.setAutoDelete(false);
00271
00272
00273
00274 UMLOperationList opl(c->getOpList());
00275 for(UMLOperation *op = opl.first(); op ; op = opl.next()) {
00276 switch(op->getVisibility()) {
00277 case Uml::Visibility::Public:
00278 oppub.append(op);
00279 break;
00280 case Uml::Visibility::Protected:
00281 opprot.append(op);
00282 break;
00283 case Uml::Visibility::Private:
00284 oppriv.append(op);
00285 break;
00286 default:
00287 break;
00288 }
00289 }
00290
00291 QString classname(cleanName(c->getName()));
00292
00293
00294 if(forceSections() || !oppub.isEmpty()) {
00295 perl << m_endl << "=head1 PUBLIC METHODS" << m_endl << m_endl ;
00296 writeOperations(classname,oppub,perl);
00297 perl << m_endl << m_endl << "=cut" << m_endl << m_endl;
00298 }
00299
00300 if(forceSections() || !opprot.isEmpty()) {
00301 perl << m_endl << "=head1 METHODS FOR SUBCLASSING" << m_endl << m_endl ;
00302
00303 writeOperations(classname,opprot,perl);
00304 perl << m_endl << m_endl << "=cut" << m_endl << m_endl;
00305 }
00306
00307 if(forceSections() || !oppriv.isEmpty()) {
00308 perl << m_endl << "=head1 PRIVATE METHODS" << m_endl << m_endl ;
00309
00310 writeOperations(classname,oppriv,perl);
00311 perl << m_endl << m_endl << "=cut" << m_endl << m_endl;
00312 }
00313
00314
00315 if (!c->isInterface() && hasDefaultValueAttr(c)) {
00316 UMLAttributeList atl = c->getAttributeList();
00317
00318 perl << m_endl;
00319 perl << m_endl << "=head2 _init" << m_endl << m_endl << m_endl;
00320 perl << "_init sets all " + classname + " attributes to their default values unless already set" << m_endl << m_endl << "=cut" << m_endl << m_endl;
00321 perl << "sub _init {" << m_endl << m_indentation << "my $self = shift;" << m_endl<<m_endl;
00322
00323 for(UMLAttribute *at = atl.first(); at ; at = atl.next()) {
00324 if(!at->getInitialValue().isEmpty())
00325 perl << m_indentation << "defined $self->{" << cleanName(at->getName())<<"}"
00326 << " or $self->{" << cleanName(at->getName()) << "} = "
00327 << at->getInitialValue() << ";" << m_endl;
00328 }
00329
00330 perl << " }" << m_endl;
00331 }
00332
00333 perl << m_endl << m_endl;
00334 }
00335
00336 void PerlWriter::writeOperations(const QString &, UMLOperationList &opList, QTextStream &perl) {
00337 UMLOperation *op;
00338 UMLAttribute *at;
00339
00340 for(op=opList.first(); op ; op=opList.next())
00341 {
00342 UMLAttributeList atl = op->getParmList();
00343
00344 bool writeDoc = forceDoc() || !op->getDoc().isEmpty();
00345 for (at = atl.first(); at ; at = atl.next())
00346 writeDoc |= !at->getDoc().isEmpty();
00347
00348 if( writeDoc )
00349 {
00350 perl << "=pod " << m_endl << m_endl << "=head3 " ;
00351 perl << cleanName(op->getName()) << m_endl << m_endl;
00352
00353 perl << " Parameters :" << m_endl ;
00354
00355 for (at = atl.first(); at ; at = atl.next()) {
00356 if(forceDoc() || !at->getDoc().isEmpty()) {
00357 perl << " "
00358 << cleanName(at->getName()) << " : "
00359 << at->getTypeName() << " : "
00360 << at->getDoc()
00361 << m_endl;
00362 }
00363 }
00364
00365 perl << m_endl;
00366 perl << " Return : " << m_endl;
00367 perl << " " << op->getTypeName();
00368 perl << m_endl << m_endl;
00369 perl << " Description : " << m_endl;
00370 perl << " " << op->getDoc();
00371 perl << m_endl << m_endl << "=cut" << m_endl << m_endl;
00372 }
00373
00374 perl << "sub " << cleanName(op->getName()) << m_endl << "{" << m_endl;
00375 perl << " my($self";
00376
00377 bool bStartPrinted = false;
00378
00379 for (at = atl.first(); at; at = atl.next()) {
00380 if (!bStartPrinted) {
00381 bStartPrinted = true;
00382 perl << "," << m_endl;
00383 }
00384 perl << " $"<< cleanName(at->getName()) << ", # "
00385 << at->getTypeName() << " : " << at->getDoc() << m_endl;
00386 }
00387
00388 perl << " ) = @_;" << m_endl;
00389
00390 perl << "#UML_MODELER_BEGIN_PERSONAL_CODE_" << cleanName(op->getName());
00391 perl << m_endl << "#UML_MODELER_END_PERSONAL_CODE_" << cleanName(op->getName()) << m_endl;
00392 perl << "}" << m_endl;
00393 perl << m_endl << m_endl;
00394 }
00395 }
00396
00397
00398 void PerlWriter::writeAttributes(UMLClassifier *c, QTextStream &perl) {
00399 UMLAttributeList atpub, atprot, atpriv, atdefval;
00400 atpub.setAutoDelete(false);
00401 atprot.setAutoDelete(false);
00402 atpriv.setAutoDelete(false);
00403 atdefval.setAutoDelete(false);
00404
00405
00406 UMLAttributeList atl = c->getAttributeList();
00407 UMLAttribute *at;
00408 for(at = atl.first(); at ; at = atl.next()) {
00409 if(!at->getInitialValue().isEmpty())
00410 atdefval.append(at);
00411 switch(at->getVisibility()) {
00412 case Uml::Visibility::Public:
00413 atpub.append(at);
00414 break;
00415 case Uml::Visibility::Protected:
00416 atprot.append(at);
00417 break;
00418 case Uml::Visibility::Private:
00419 atpriv.append(at);
00420 break;
00421 default:
00422 break;
00423 }
00424 }
00425
00426
00427 if(forceSections() || atpub.count()) {
00428 writeAttributes(atpub,perl);
00429 }
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439 }
00440
00441
00442 void PerlWriter::writeAttributes(UMLAttributeList &atList, QTextStream &perl)
00443 {
00444 perl << m_endl << "=head1 PUBLIC ATTRIBUTES" << m_endl << m_endl;
00445 perl << "=pod " << m_endl << m_endl ;
00446 for (UMLAttribute *at = atList.first(); at ; at = atList.next())
00447 {
00448 if (forceDoc() || !at->getDoc().isEmpty())
00449 {
00450 perl << "=head3 " << cleanName(at->getName()) << m_endl << m_endl ;
00451 perl << " Description : " << at->getDoc() << m_endl << m_endl;
00452 }
00453 }
00454 perl << m_endl << m_endl << "=cut" << m_endl << m_endl;
00455 return;
00456 }
00457
00458 QStringList PerlWriter::defaultDatatypes() {
00459 QStringList l;
00460 l.append("$");
00461 l.append("@");
00462 l.append("%");
00463 return l;
00464 }
00465
00466 const QStringList PerlWriter::reservedKeywords() const {
00467
00468 static QStringList keywords;
00469
00470 if (keywords.isEmpty()) {
00471 keywords << "abs"
00472 << "accept"
00473 << "alarm"
00474 << "and"
00475 << "atan2"
00476 << "BEGIN"
00477 << "bind"
00478 << "binmode"
00479 << "bless"
00480 << "byte"
00481 << "caller"
00482 << "carp"
00483 << "chdir"
00484 << "chmod"
00485 << "chomp"
00486 << "chop"
00487 << "chown"
00488 << "chr"
00489 << "chroot"
00490 << "close"
00491 << "closedir"
00492 << "cmp"
00493 << "confess"
00494 << "connect"
00495 << "continue"
00496 << "cos"
00497 << "croak"
00498 << "crypt"
00499 << "dbmclose"
00500 << "dbmopen"
00501 << "defined"
00502 << "delete"
00503 << "die"
00504 << "do"
00505 << "dump"
00506 << "each"
00507 << "else"
00508 << "elsif"
00509 << "END"
00510 << "endgrent"
00511 << "endhostent"
00512 << "endnetent"
00513 << "endprotoent"
00514 << "endpwent"
00515 << "endservent"
00516 << "eof"
00517 << "eq"
00518 << "eval"
00519 << "exec"
00520 << "exists"
00521 << "exit"
00522 << "exp"
00523 << "fcntl"
00524 << "fileno"
00525 << "flock"
00526 << "for"
00527 << "foreach"
00528 << "fork"
00529 << "format"
00530 << "formline"
00531 << "ge"
00532 << "getc"
00533 << "getgrent"
00534 << "getgrgid"
00535 << "getgrnam"
00536 << "gethostbyaddr"
00537 << "gethostbyname"
00538 << "gethostent"
00539 << "getlogin"
00540 << "getnetbyaddr"
00541 << "getnetbyname"
00542 << "getnetent"
00543 << "getpeername"
00544 << "getpgrp"
00545 << "getppid"
00546 << "getpriority"
00547 << "getprotobyname"
00548 << "getprotobynumber"
00549 << "getprotoent"
00550 << "getpwent"
00551 << "getpwnam"
00552 << "getpwuid"
00553 << "getservbyname"
00554 << "getservbyport"
00555 << "getservent"
00556 << "getsockname"
00557 << "getsockopt"
00558 << "glob"
00559 << "gmtime"
00560 << "goto"
00561 << "grep"
00562 << "gt"
00563 << "hex"
00564 << "if"
00565 << "import"
00566 << "index"
00567 << "int"
00568 << "integer"
00569 << "ioctl"
00570 << "join"
00571 << "keys"
00572 << "kill"
00573 << "last"
00574 << "lc"
00575 << "lcfirst"
00576 << "le"
00577 << "length"
00578 << "lib"
00579 << "link"
00580 << "listen"
00581 << "local"
00582 << "localtime"
00583 << "lock"
00584 << "log"
00585 << "lstat"
00586 << "lt"
00587 << "map"
00588 << "mkdir"
00589 << "msgctl"
00590 << "msgget"
00591 << "msgrcv"
00592 << "msgsnd"
00593 << "my"
00594 << "ne"
00595 << "new"
00596 << "next"
00597 << "no"
00598 << "not"
00599 << "oct"
00600 << "open"
00601 << "opendir"
00602 << "or"
00603 << "ord"
00604 << "our"
00605 << "pack"
00606 << "package"
00607 << "pipe"
00608 << "pop"
00609 << "pos"
00610 << "print"
00611 << "printf"
00612 << "prototype"
00613 << "push"
00614 << "quotemeta"
00615 << "rand"
00616 << "read"
00617 << "readdir"
00618 << "readline"
00619 << "readlink"
00620 << "readpipe"
00621 << "recv"
00622 << "redo"
00623 << "ref"
00624 << "rename"
00625 << "require"
00626 << "reset"
00627 << "return"
00628 << "reverse"
00629 << "rewinddir"
00630 << "rindex"
00631 << "rmdir"
00632 << "scalar"
00633 << "seek"
00634 << "seekdir"
00635 << "select"
00636 << "semctl"
00637 << "semget"
00638 << "semop"
00639 << "send"
00640 << "setgrent"
00641 << "sethostent"
00642 << "setnetent"
00643 << "setpgrp"
00644 << "setpriority"
00645 << "setprotoent"
00646 << "setpwent"
00647 << "setservent"
00648 << "setsockopt"
00649 << "shift"
00650 << "shmctl"
00651 << "shmget"
00652 << "shmread"
00653 << "shmwrite"
00654 << "shutdown"
00655 << "sigtrap"
00656 << "sin"
00657 << "sleep"
00658 << "socket"
00659 << "socketpair"
00660 << "sort"
00661 << "splice"
00662 << "split"
00663 << "sprintf"
00664 << "sqrt"
00665 << "srand"
00666 << "stat"
00667 << "strict"
00668 << "study"
00669 << "sub"
00670 << "subs"
00671 << "substr"
00672 << "switch"
00673 << "symlink"
00674 << "syscall"
00675 << "sysopen"
00676 << "sysread"
00677 << "sysseek"
00678 << "system"
00679 << "syswrite"
00680 << "tell"
00681 << "telldir"
00682 << "tie"
00683 << "tied"
00684 << "time"
00685 << "times"
00686 << "truncate"
00687 << "uc"
00688 << "ucfirst"
00689 << "umask"
00690 << "undef"
00691 << "unless"
00692 << "unlink"
00693 << "unpack"
00694 << "unshift"
00695 << "untie"
00696 << "until"
00697 << "use"
00698 << "utf8"
00699 << "utime"
00700 << "values"
00701 << "vars"
00702 << "vec"
00703 << "wait"
00704 << "waitpid"
00705 << "wantarray"
00706 << "warn"
00707 << "warnings"
00708 << "while"
00709 << "write"
00710 << "xor";
00711 }
00712
00713 return keywords;
00714 }
00715
00716 #include "perlwriter.moc"