umbrello API Documentation

pythonwriter.cpp

00001 /***************************************************************************
00002                           pythonwriter.h  -  description
00003                              -------------------
00004     begin                : Sat Dec 21 2002
00005     copyright            : Vincent Decorges
00006     email                : vincent.decorges@eivd.ch
00007       (C) 2003-2006  Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
00008  ***************************************************************************/
00009 
00010 /***************************************************************************
00011  *                                                                         *
00012  *   This program is free software; you can redistribute it and/or modify  *
00013  *   it under the terms of the GNU General Public License as published by  *
00014  *   the Free Software Foundation; either version 2 of the License, or     *
00015  *   (at your option) any later version.                                   *
00016  *                                                                         *
00017  ***************************************************************************/
00018 
00019 #include "pythonwriter.h"
00020 
00021 #include <kdebug.h>
00022 #include <klocale.h>
00023 #include <kmessagebox.h>
00024 #include <qfile.h>
00025 #include <qtextstream.h>
00026 #include <qregexp.h>
00027 
00028 #include "../umldoc.h"
00029 #include "../umlattributelist.h"
00030 #include "../association.h"
00031 #include "../attribute.h"
00032 #include "../classifier.h"
00033 #include "../attribute.h"
00034 #include "../operation.h"
00035 #include "../umlnamespace.h"
00036 
00037 PythonWriter::PythonWriter() : m_bNeedPass(true) {
00038 }
00039 
00040 PythonWriter::~PythonWriter() {}
00041 
00042 void PythonWriter::writeClass(UMLClassifier *c) {
00043     if(!c) {
00044         kDebug()<<"Cannot write class of NULL concept!" << endl;
00045         return;
00046     }
00047 
00048     QString classname = cleanName(c->getName());
00049 
00050     UMLClassifierList superclasses = c->getSuperClasses();
00051     UMLAssociationList aggregations = c->getAggregations();
00052     UMLAssociationList compositions = c->getCompositions();
00053 
00054     m_bNeedPass = true;
00055 
00056     //find an appropriate name for our file
00057     QString fileName = findFileName(c, ".py");
00058     if (fileName.isEmpty()) {
00059         emit codeGenerated(c, false);
00060         return;
00061     }
00062 
00063     QChar first = fileName.at(0);
00064     //Replace the first letter of the filename because
00065     //python class begin with an upper caracter (convention)
00066     first = first.upper();
00067     fileName = fileName.replace(0, 1, first);
00068 
00069     QFile fileh;
00070     if( !openFile(fileh, fileName) ) {
00071         emit codeGenerated(c, false);
00072         return;
00073     }
00074     QTextStream h(&fileh);
00075 
00077     //Start generating the code!!
00079 
00080 
00081     //try to find a heading file (license, coments, etc)
00082     QString str;
00083 
00084     str = getHeadingFile(".py");
00085     if(!str.isEmpty()) {
00086         str.replace(QRegExp("%filename%"), fileName);
00087         str.replace(QRegExp("%filepath%"), fileh.name());
00088         h<<str<<m_endl;
00089     }
00090 
00091     // generate import statement for superclasses and take packages into account
00092     str = cleanName(c->getName());
00093     QString pkg = cleanName(c->getPackage());
00094     if (!pkg.isEmpty())
00095         str.prepend(pkg + '.');
00096     QStringList includesList  = QStringList(str); //save imported classes
00097     int i = superclasses.count();
00098     for (UMLClassifier *classifier = superclasses.first();
00099             classifier && i; classifier = superclasses.next(), i--) {
00100         str = cleanName(classifier->getName());
00101         pkg = cleanName(classifier->getPackage());
00102         if (!pkg.isEmpty())
00103             str.prepend(pkg + '.');
00104         includesList.append(str);
00105         h << "from " + str + " import *" << m_endl;
00106     }
00107 
00108     //write includes and take namespaces into account
00109     UMLPackageList includes;
00110     findObjectsRelated(c,includes);
00111     UMLPackage* conc;
00112     for(conc = includes.first(); conc ;conc = includes.next()) {
00113         QString headerName = findFileName(conc, ".py");
00114         if ( !headerName.isEmpty() ) {
00115             headerName.remove(QRegExp(".py$"));
00116             first = headerName.at(0);
00117             first = first.upper();
00118             headerName = headerName.replace(0, 1, first);
00119             str = headerName.replace(QChar('/'),QChar('.'));
00120             if (includesList.findIndex(str) < 0)  // not yet imported
00121                 h << "from " << str << " import *" << m_endl;
00122         }
00123     }
00124     h<<m_endl;
00125 
00126     h << "class " << classname << (superclasses.count() > 0 ? " (" : "(object)");
00127     i = superclasses.count();
00128 
00129     for (UMLClassifier *obj = superclasses.first();
00130             obj && i; obj = superclasses.next(), i--) {
00131 
00132         h<<cleanName(obj->getName())<<(i>1?", ":"");
00133     }
00134 
00135 
00136     h<<(superclasses.count() > 0 ? ")":"")<<":"<<m_endl<<m_endl;
00137 
00138     if (forceDoc() || !c->getDoc().isEmpty()) {
00139         h << m_indentation << "\"\"\"" << m_endl;
00140         h << formatDoc(c->getDoc(), m_indentation + ' ') << m_endl;
00141         h << m_indentation << ":version:" << m_endl;
00142         h << m_indentation << ":author:" << m_endl;
00143         h << m_indentation << "\"\"\"" << m_endl << m_endl;
00144         m_bNeedPass = false;
00145     }
00146 
00147     // attributes
00148     writeAttributes(c->getAttributeList(), h);
00149 
00150     //operations
00151     writeOperations(c,h);
00152 
00153     if (m_bNeedPass)
00154         h << m_indentation << "pass" << m_endl;
00155 
00156     //finish files
00157     h<<m_endl<<m_endl;
00158 
00159     //close files and notfiy we are done
00160     fileh.close();
00161     emit codeGenerated(c, true);
00162 }
00163 
00164 
00166 //  Helper Methods
00167 
00168 void PythonWriter::writeAttributes(UMLAttributeList atList, QTextStream &py) {
00169     if (!forceDoc() || atList.count() == 0)
00170         return;
00171     py << m_indentation << "\"\"\" ATTRIBUTES" << m_endl << m_endl;
00172     for (UMLAttribute *at = atList.first(); at; at = atList.next()) {
00173         py << formatDoc(at->getDoc(), m_indentation + ' ') << m_endl;
00174         Uml::Visibility vis = at->getVisibility();
00175         py << m_indentation << cleanName(at->getName()) << "  ("
00176             << vis.toString() << ")" << m_endl << m_endl ;
00177     } // end for
00178     py << m_indentation << "\"\"\"" << m_endl << m_endl;
00179 }
00180 
00181 void PythonWriter::writeOperations(UMLClassifier *c, QTextStream &h) {
00182 
00183     //Lists to store operations  sorted by scope
00184     UMLOperationList oppub,opprot,oppriv;
00185 
00186     oppub.setAutoDelete(false);
00187     opprot.setAutoDelete(false);
00188     oppriv.setAutoDelete(false);
00189 
00190     //sort operations by scope first and see if there are abstract methods
00191     UMLOperationList opl(c->getOpList());
00192     for(UMLOperation *op = opl.first(); op ; op = opl.next()) {
00193         switch(op->getVisibility()) {
00194           case Uml::Visibility::Public:
00195             oppub.append(op);
00196             break;
00197           case Uml::Visibility::Protected:
00198             opprot.append(op);
00199             break;
00200           case Uml::Visibility::Private:
00201             oppriv.append(op);
00202             break;
00203           default:
00204             break;
00205         }
00206     }
00207 
00208     QString classname(cleanName(c->getName()));
00209 
00210     //write operations to file
00211     if(forceSections() || !oppub.isEmpty()) {
00212         writeOperations(classname,oppub,h,PUBLIC);
00213     }
00214 
00215     if(forceSections() || !opprot.isEmpty()) {
00216         writeOperations(classname,opprot,h,PROTECTED);
00217     }
00218 
00219     if(forceSections() || !oppriv.isEmpty()) {
00220         writeOperations(classname,oppriv,h,PRIVATE);
00221     }
00222 
00223 }
00224 
00225 void PythonWriter::writeOperations(const QString& /*classname*/, UMLOperationList &opList,
00226                                    QTextStream &h, Access access) {
00227     UMLOperation *op;
00228     UMLAttribute *at;
00229 
00230     QString sAccess;
00231 
00232     switch (access) {
00233 
00234     case PUBLIC:
00235         sAccess = QString("");
00236         break;
00237     case PRIVATE:
00238         sAccess = QString("__");
00239         break;
00240     case PROTECTED:
00241         sAccess = QString("_");
00242         break;
00243     }
00244 
00245 
00246     for(op=opList.first(); op ; op=opList.next()) {
00247         UMLAttributeList atl = op->getParmList();
00248         //write method doc if we have doc || if at least one of the params has doc
00249         bool writeDoc = forceDoc() || !op->getDoc().isEmpty();
00250         for (at = atl.first(); at; at = atl.next())
00251             writeDoc |= !at->getDoc().isEmpty();
00252 
00253         h<< m_indentation << "def "<< sAccess + cleanName(op->getName()) << "(self";
00254 
00255         int j=0;
00256         for (at = atl.first(); at; at = atl.next(), j++) {
00257             h << ", " << cleanName(at->getName())
00258             << (!(at->getInitialValue().isEmpty()) ?
00259                 (QString(" = ")+at->getInitialValue()) :
00260                 QString(""));
00261         }
00262 
00263         h<<"):"<<m_endl;
00264 
00265         if( writeDoc )  //write method documentation
00266         {
00267             h << m_indentation << m_indentation << "\"\"\"" << m_endl;
00268             h << formatDoc(op->getDoc(), m_indentation + m_indentation + ' ') << m_endl;
00269 
00270             for (at = atl.first(); at; at = atl.next())  //write parameter documentation
00271             {
00272                 if(forceDoc() || !at->getDoc().isEmpty()) {
00273                     h<<m_indentation<<m_indentation<<"@param "<<at->getTypeName()<<
00274                     " " << cleanName(at->getName());
00275                     h<<" : "<<at->getDoc()<<m_endl;
00276                 }
00277             }//end for : write parameter documentation
00278             h<<m_indentation<<m_indentation<<"@return " + op->getTypeName()<<" :"<<m_endl;
00279             h<<m_indentation<<m_indentation<<"@author"<<m_endl;
00280             h<<m_indentation<<m_indentation<<"\"\"\""<<m_endl;
00281         }
00282         h<<m_indentation<<m_indentation<<"pass"<<m_endl<<m_endl;
00283         m_bNeedPass = false;
00284     }//end for
00285 }
00286 
00290 Uml::Programming_Language PythonWriter::getLanguage() {
00291     return Uml::pl_Python;
00292 }
00293 
00294 const QStringList PythonWriter::reservedKeywords() const {
00295 
00296     static QStringList keywords;
00297 
00298     if (keywords.isEmpty()) {
00299         keywords << "abs"
00300         << "and"
00301         << "apply"
00302         << "ArithmeticError"
00303         << "assert"
00304         << "AssertionError"
00305         << "AttributeError"
00306         << "break"
00307         << "buffer"
00308         << "callable"
00309         << "chr"
00310         << "class"
00311         << "classmethod"
00312         << "cmp"
00313         << "coerce"
00314         << "compile"
00315         << "complex"
00316         << "continue"
00317         << "def"
00318         << "del"
00319         << "delattr"
00320         << "DeprecationWarning"
00321         << "dict"
00322         << "dir"
00323         << "divmod"
00324         << "elif"
00325         << "Ellipsis"
00326         << "else"
00327         << "EnvironmentError"
00328         << "EOFError"
00329         << "eval"
00330         << "except"
00331         << "Exception"
00332         << "exec"
00333         << "execfile"
00334         << "file"
00335         << "filter"
00336         << "finally"
00337         << "float"
00338         << "FloatingPointError"
00339         << "for"
00340         << "from"
00341         << "getattr"
00342         << "global"
00343         << "globals"
00344         << "hasattr"
00345         << "hash"
00346         << "hex"
00347         << "id"
00348         << "if"
00349         << "import"
00350         << "__import__"
00351         << "ImportError"
00352         << "in"
00353         << "IndentationError"
00354         << "IndexError"
00355         << "input"
00356         << "int"
00357         << "intern"
00358         << "IOError"
00359         << "is"
00360         << "isinstance"
00361         << "issubclass"
00362         << "iter"
00363         << "KeyboardInterrupt"
00364         << "KeyError"
00365         << "lambda"
00366         << "len"
00367         << "list"
00368         << "locals"
00369         << "long"
00370         << "LookupError"
00371         << "map"
00372         << "max"
00373         << "MemoryError"
00374         << "min"
00375         << "NameError"
00376         << "None"
00377         << "not"
00378         << "NotImplemented"
00379         << "NotImplementedError"
00380         << "object"
00381         << "oct"
00382         << "open"
00383         << "or"
00384         << "ord"
00385         << "OSError"
00386         << "OverflowError"
00387         << "OverflowWarning"
00388         << "pass"
00389         << "pow"
00390         << "print"
00391         << "property"
00392         << "raise"
00393         << "range"
00394         << "raw_input"
00395         << "reduce"
00396         << "ReferenceError"
00397         << "reload"
00398         << "repr"
00399         << "return"
00400         << "round"
00401         << "RuntimeError"
00402         << "RuntimeWarning"
00403         << "setattr"
00404         << "slice"
00405         << "StandardError"
00406         << "staticmethod"
00407         << "StopIteration"
00408         << "str"
00409         << "super"
00410         << "SyntaxError"
00411         << "SyntaxWarning"
00412         << "SystemError"
00413         << "SystemExit"
00414         << "TabError"
00415         << "try"
00416         << "tuple"
00417         << "type"
00418         << "TypeError"
00419         << "UnboundLocalError"
00420         << "unichr"
00421         << "unicode"
00422         << "UnicodeError"
00423         << "UserWarning"
00424         << "ValueError"
00425         << "vars"
00426         << "Warning"
00427         << "while"
00428         << "WindowsError"
00429         << "xrange"
00430         << "yield"
00431         << "ZeroDivisionError"
00432         << "zip";
00433     }
00434 
00435     return keywords;
00436 }
00437 
00438 #include "pythonwriter.moc"
KDE Logo
This file is part of the documentation for umbrello Version 3.1.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Jun 26 08:07:59 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003