umbrello API Documentation

javawriter.cpp

00001 /***************************************************************************
00002                           javawriter.cpp  -  description
00003     This is the "old" code generator that does not support code editing
00004     in the Modeller but uses significantly less file space because the
00005     source code is not replicated in the XMI file.
00006                              -------------------
00007     copyright            : (C) 2003 Brian Thomas brian.thomas@gsfc.nasa.gov
00008       (C) 2004-2006  Umbrello UML Modeller Authors <uml-devel@uml.sf.net>
00009 ***************************************************************************/
00010 
00011 /***************************************************************************
00012  *                                                                         *
00013  *   This program is free software; you can redistribute it and/or modify  *
00014  *   it under the terms of the GNU General Public License as published by  *
00015  *   the Free Software Foundation; either version 2 of the License, or     *
00016  *   (at your option) any later version.                                   *
00017  *                                                                         *
00018  ***************************************************************************/
00019 
00020 // own header
00021 #include "javawriter.h"
00022 // qt includes
00023 #include <qfile.h>
00024 #include <qtextstream.h>
00025 #include <qregexp.h>
00026 // kde includes
00027 #include <kdebug.h>
00028 // app includes
00029 #include "../umldoc.h"
00030 #include "../classifier.h"
00031 #include "../operation.h"
00032 #include "../attribute.h"
00033 #include "../association.h"
00034 #include "../template.h"
00035 #include "../umltemplatelist.h"
00036 
00037 JavaWriter::JavaWriter() {
00038     startline = m_endl + m_indentation;
00039 }
00040 
00041 JavaWriter::~JavaWriter() {}
00042 
00043 Uml::Programming_Language JavaWriter::getLanguage() {
00044     return Uml::pl_Java;
00045 }
00046 
00047 void JavaWriter::writeClass(UMLClassifier *c)
00048 {
00049 
00050     if (!c) {
00051         kDebug()<<"Cannot write class of NULL concept!\n";
00052         return;
00053     }
00054 
00055     isInterface = c->isInterface();
00056 
00057     QString fileName = cleanName(c->getName().lower());
00058 
00059     //find an appropriate name for our file
00060     fileName = findFileName(c,".java");
00061     if (fileName.isEmpty()) {
00062         emit codeGenerated(c, false);
00063         return;
00064     }
00065 
00066     // check that we may open that file for writing
00067     QFile file;
00068     if ( !openFile(file, fileName) ) {
00069         emit codeGenerated(c, false);
00070         return;
00071     }
00072 
00073     // Preparations
00074     //
00075 
00076     // sort attributes by Scope
00077     UMLAttributeList  atl;
00078     UMLAttributeList  atpub, atprot, atpriv;
00079     UMLAttributeList  final_atpub, final_atprot, final_atpriv;
00080     atpub.setAutoDelete(false);
00081     final_atpub.setAutoDelete(false);
00082     atprot.setAutoDelete(false);
00083     final_atprot.setAutoDelete(false);
00084     atpriv.setAutoDelete(false);
00085     final_atpriv.setAutoDelete(false);
00086 
00087     if (!isInterface) {
00088         UMLAttributeList atl = c->getAttributeList();
00089         for (UMLAttribute *at = atl.first(); at ; at = atl.next()) {
00090             switch(at->getVisibility())
00091             {
00092               case Uml::Visibility::Public:
00093                 if(at->getStatic())
00094                     final_atpub.append(at);
00095                 else
00096                     atpub.append(at);
00097                 break;
00098               case Uml::Visibility::Protected:
00099                 if(at->getStatic())
00100                     final_atprot.append(at);
00101                 else
00102                     atprot.append(at);
00103                 break;
00104               case Uml::Visibility::Private:
00105                 if(at->getStatic())
00106                     final_atpriv.append(at);
00107                 else
00108                     atpriv.append(at);
00109                 break;
00110               default:
00111                 break;
00112             }
00113         }
00114     }
00115 
00116     // another preparation, determine what we have
00117     UMLAssociationList associations = c->getSpecificAssocs(Uml::at_Association); // BAD! only way to get "general" associations.
00118     UMLAssociationList uniAssociations = c->getUniAssociationToBeImplemented();
00119 
00120     UMLAssociationList aggregations = c->getAggregations();
00121     UMLAssociationList compositions = c->getCompositions();
00122 
00123     bool hasAssociations = aggregations.count() > 0 || associations.count() > 0 || compositions.count() > 0 || uniAssociations.count() > 0;
00124     bool hasAttributes = (atl.count() > 0);
00125     bool hasAccessorMethods = hasAttributes || hasAssociations;
00126     bool hasOperationMethods = (c->getOpList().count() > 0);
00127     // this is a bit too simplistic..some associations are for
00128     // SINGLE objects, and WONT be declared as Vectors, so this
00129     // is a bit overly inclusive
00130     bool hasVectorFields = hasAssociations ? true : false;
00131 
00132     // open text stream to file
00133     QTextStream java(&file);
00134 
00135     //try to find a heading file (license, coments, etc)
00136     QString str;
00137     str = getHeadingFile(".java");
00138     if(!str.isEmpty()) {
00139         str.replace(QRegExp("%filename%"),fileName);
00140         str.replace(QRegExp("%filepath%"),file.name());
00141         java<<str<<m_endl;
00142     }
00143 
00144     if(!c->getPackage().isEmpty())
00145         java<<"package "<<c->getPackage()<<";"<<m_endl;
00146 
00147     // IMPORT statements
00148     // Q: Why all utils? Isnt just List and Vector the only classes we are using?
00149     // A: doesn't matter at all; its more readable to just include '*' and java compilers
00150     //    don't slow down or anything. (TZ)
00151     if (hasVectorFields )
00152     {
00153         writeBlankLine(java);
00154         java<<"import java.util.*;"<<m_endl;
00155     }
00156 
00157     //only import classes in a different package as this class
00158     UMLPackageList imports;
00159     findObjectsRelated(c,imports);
00160     for (UMLPackage *con = imports.first(); con; con = imports.next()) {
00161         if (con->getBaseType() == Uml::ot_Datatype)
00162             continue;
00163         QString pkg = con->getPackage();
00164         if (!pkg.isEmpty() && pkg != c->getPackage())
00165             java << "import " << pkg << "." << cleanName(con->getName()) << ";"
00166             << m_endl;
00167     }
00168     writeBlankLine(java);
00169 
00170     // write the opening declaration for the class incl any documentation,
00171     // interfaces and/or inheritence issues we have
00172     writeClassDecl(c, java);
00173 
00174     // start body of class
00175     java<<" {"<<m_endl;
00176 
00177     // ATTRIBUTES
00178     //
00179 
00180     // write comment for section IF needed
00181     if (forceDoc() || hasAccessorMethods)
00182     {
00183         writeComment("", m_indentation, java);
00184         writeComment("Fields", m_indentation, java);
00185         writeComment("", m_indentation, java);
00186         writeBlankLine(java);
00187     }
00188 
00189     writeAttributeDecls(final_atpub, final_atprot, final_atpriv, java);
00190     writeAttributeDecls(atpub, atprot, atpriv, java);
00191 
00192     writeAssociationDecls(associations, c->getID(), java);
00193     writeAssociationDecls(uniAssociations, c->getID(), java);
00194     writeAssociationDecls(aggregations, c->getID(), java);
00195     writeAssociationDecls(compositions, c->getID(), java);
00196 
00197     // Constructors: anything we more we need to do here ?
00198     //
00199     if(!isInterface)
00200         writeConstructor(c, java);
00201 
00202     // METHODS
00203     //
00204 
00205     // write comment for section IF needed
00206     if (forceDoc() || hasAccessorMethods || hasOperationMethods)
00207     {
00208 
00209         java<<startline;
00210         writeComment("", m_indentation, java);
00211         writeComment("Methods", m_indentation, java);
00212         writeComment("", m_indentation, java);
00213         writeBlankLine(java);
00214         writeBlankLine(java);
00215     }
00216 
00217     // write comment for sub-section IF needed
00218     if (forceDoc() || hasAccessorMethods )
00219     {
00220         writeComment("", m_indentation, java);
00221         writeComment("Accessor methods", m_indentation, java);
00222         writeComment("", m_indentation, java);
00223         writeBlankLine(java);
00224     }
00225 
00226     // Accessors for attributes
00227     writeAttributeMethods(final_atpub, Uml::Visibility::Public, java);
00228     writeAttributeMethods(final_atprot, Uml::Visibility::Protected, java);
00229     writeAttributeMethods(final_atpriv, Uml::Visibility::Private, java);
00230     writeAttributeMethods(atpub, Uml::Visibility::Public, java);
00231     writeAttributeMethods(atprot, Uml::Visibility::Protected, java);
00232     writeAttributeMethods(atpriv, Uml::Visibility::Private, java);
00233 
00234     // accessor methods for associations
00235 
00236     // first: determine the name of the other class
00237     writeAssociationMethods(associations, c, java);
00238     writeAssociationMethods(uniAssociations, c, java);
00239     writeAssociationMethods(aggregations, c, java);
00240     writeAssociationMethods(compositions, c, java);
00241 
00242     // Other operation methods
00243     // all other operations are now written
00244 
00245     // write comment for sub-section IF needed
00246     if (forceDoc() || hasOperationMethods)
00247     {
00248         writeComment("", m_indentation, java);
00249         writeComment("Other methods", m_indentation, java);
00250         writeComment("", m_indentation, java);
00251         writeBlankLine(java);
00252     }
00253     writeOperations(c,java);
00254 
00255     writeBlankLine(java);
00256     java<<"}"<<m_endl; // end class
00257 
00258     file.close();
00259     emit codeGenerated(c, true);
00260 }
00261 
00262 void JavaWriter::writeClassDecl(UMLClassifier *c, QTextStream &java)
00263 {
00264 
00265     QString classname = cleanName(c->getName()); // our class name
00266 
00267     // write documentation for class, if any, first
00268     if(forceDoc() || !c->getDoc().isEmpty())
00269     {
00270         if(isInterface)
00271             writeDocumentation("Interface "+classname,c->getDoc(),"","",java);
00272         else
00273             writeDocumentation("Class "+classname,c->getDoc(),"","",java);
00274 
00275         writeBlankLine(java);
00276     }
00277 
00278     // Now write the actual class declaration
00279     QString scope = ""; // = scopeToJavaDecl(c->getVisibility());
00280     if (c->getVisibility() != Uml::Visibility::Public) {
00281         // We should emit a warning in here .. java doesn't like to allow
00282         // private/protected classes. The best we can do (I believe)
00283         // is to let these declarations default to "package visibility"
00284         // which is a level between traditional "private" and "protected"
00285         // scopes. To get this visibility level we just print nothing..
00286     } else
00287         scope = "public ";
00288 
00289     java<<((c->getAbstract() && !isInterface) ? QString("abstract ") : QString(""))<<scope;
00290     if(isInterface)
00291         java<<"interface ";
00292     else
00293         java<<"class ";
00294 
00295     java<<classname;
00296 
00297     // Generics
00298     UMLTemplateList template_params = c->getTemplateList();
00299     if (template_params.count()) {
00300         java << "<";
00301         for (UMLTemplate *t = template_params.first(); t; ) {
00302             QString formalName = t->getName();
00303             java <<  formalName;
00304             QString typeName = t->getTypeName();
00305             if (typeName != "class") {
00306                 java << " extends " << typeName;
00307             }
00308             if ((t = template_params.next()) != NULL)
00309                 java << ", ";
00310         }
00311         java << ">" << m_endl;
00312     }
00313 
00314     // write inheritances out
00315     UMLClassifier *concept;
00316     UMLClassifierList superclasses = c->findSuperClassConcepts(UMLClassifier::CLASS);
00317 
00318     int i = 0;
00319     for (concept= superclasses.first(); concept; concept = superclasses.next())
00320     {
00321         if (i == 0)
00322         {
00323             java<< " extends ";
00324         }
00325         else
00326         {
00327             //The java generated code is wrong ! : No multiple inheritence of class
00328             java<< ", " ;
00329         }
00330         java<< cleanName(concept->getName());
00331         i++;
00332     }
00333 
00334     UMLClassifierList superInterfaces = c->findSuperClassConcepts(UMLClassifier::INTERFACE);
00335     i = 0;
00336     for (concept= superInterfaces.first(); concept; concept = superInterfaces.next())
00337     {
00338         if (i == 0)
00339         {
00340             if (isInterface)
00341                 java<< " extends ";
00342             else
00343                 java<< " implements ";
00344         }
00345         else
00346         {
00347             //The java generated code is OK ! : multiple inheritence of interface
00348             java<< ", " ;
00349         }
00350         java<< cleanName(concept->getName());
00351         i++;
00352     }
00353 
00354 }
00355 
00356 void JavaWriter::writeAttributeDecls(UMLAttributeList &atpub, UMLAttributeList &atprot,
00357                                      UMLAttributeList &atpriv, QTextStream &java )
00358 {
00359     UMLAttribute *at;
00360 
00361     for(at=atpub.first(); at; at=atpub.next())
00362     {
00363         QString documentation = at->getDoc();
00364         QString staticValue = at->getStatic() ? "static " : "";
00365         QString typeName = fixTypeName(at->getTypeName());
00366         QString initialValue = fixInitialStringDeclValue(at->getInitialValue(), typeName);
00367         if(!documentation.isEmpty())
00368             writeComment(documentation, m_indentation, java, true);
00369         java<<startline<<staticValue<<"public "<<typeName<<" "<<cleanName(at->getName())
00370         <<(initialValue.isEmpty()?QString(""):QString(" = ") + initialValue)<<";";
00371     }
00372 
00373     for(at=atprot.first();at;at=atprot.next())
00374     {
00375         QString documentation = at->getDoc();
00376         QString typeName = fixTypeName(at->getTypeName());
00377         QString staticValue = at->getStatic() ? "static " : "";
00378         QString initialValue = fixInitialStringDeclValue(at->getInitialValue(), typeName);
00379         if(!documentation.isEmpty())
00380             writeComment(documentation, m_indentation, java, true);
00381         java<<startline<<staticValue<<"protected "<<typeName<<" "<<cleanName(at->getName())
00382         <<(initialValue.isEmpty()?QString(""):QString(" = ") + initialValue)<<";";
00383     }
00384 
00385     for(at=atpriv.first();at;at=atpriv.next())
00386     {
00387         QString documentation = at->getDoc();
00388         QString typeName = fixTypeName(at->getTypeName());
00389         QString staticValue = at->getStatic() ? "static " : "";
00390         QString initialValue = fixInitialStringDeclValue(at->getInitialValue(), typeName);
00391         if(!documentation.isEmpty())
00392             writeComment(documentation, m_indentation, java, true);
00393         java<<startline<<staticValue<<"private "<<typeName<<" "<<cleanName(at->getName())
00394         <<(initialValue.isEmpty()?QString(""):QString(" = ") + initialValue)<<";";
00395     }
00396 
00397 }
00398 
00399 void JavaWriter::writeAttributeMethods(UMLAttributeList &atpub, Uml::Visibility visibility, QTextStream &java)
00400 {
00401 
00402     UMLAttribute *at;
00403     for(at=atpub.first(); at; at=atpub.next())
00404     {
00405         QString fieldName = cleanName(at->getName());
00406         // force capitalizing the field name, this is silly,
00407         // from what I can tell, this IS the default behavior for
00408         // cleanName. I dunno why its not working -b.t.
00409         fieldName.stripWhiteSpace();
00410         fieldName.replace(0,1,fieldName.at(0).upper());
00411 
00412         writeSingleAttributeAccessorMethods(at->getTypeName(),
00413                                             cleanName(at->getName()),
00414                                             fieldName,
00415                                             at->getDoc(),
00416                                             visibility, Uml::chg_Changeable, at->getStatic(), java);
00417     }
00418 
00419 }
00420 
00421 void JavaWriter::writeComment(const QString &comment, const QString &myIndent,
00422                               QTextStream &java, bool javaDocStyle)
00423 {
00424     // in the case we have several line comment..
00425     // NOTE: this part of the method has the problem of adopting UNIX newline,
00426     // need to resolve for using with MAC/WinDoze eventually I assume
00427     if (comment.contains(QRegExp("\n"))) {
00428 
00429         if(javaDocStyle)
00430             java << myIndent << "" << m_endl;
00443     } else {
00444         // this should be more fancy in the future, breaking it up into 80 char
00445         // lines so that it doesn't look too bad
00446         writeBlankLine(java);
00447         if(javaDocStyle)
00448             java << myIndent << "";
00455     }
00456 }
00457 
00458 void JavaWriter::writeDocumentation(QString header, QString body, QString end, QString indent, QTextStream &java)
00459 {
00460     writeBlankLine(java);
00461     java<<indent<<"";
00473 }
00474 
00475 void JavaWriter::writeAssociationDecls(UMLAssociationList associations, Uml::IDType id, QTextStream &java)
00476 {
00477 
00478     if( forceSections() || !associations.isEmpty() )
00479     {
00480         bool printRoleA = false, printRoleB = false;
00481         for(UMLAssociation *a = associations.first(); a; a = associations.next())
00482         {
00483             // it may seem counter intuitive, but you want to insert the role of the
00484             // *other* class into *this* class.
00485             if (a->getObjectId(Uml::A) == id)
00486                 printRoleB = true;
00487 
00488             if (a->getObjectId(Uml::B) == id)
00489                 printRoleA = true;
00490 
00491             // First: we insert documentaion for association IF it has either role AND some documentation (!)
00492             if ((printRoleA || printRoleB) && !(a->getDoc().isEmpty()))
00493                 writeComment(a->getDoc(), m_indentation, java);
00494 
00495             // print RoleB decl
00496             if (printRoleB)
00497             {
00498                 QString fieldClassName = cleanName(getUMLObjectName(a->getObject(Uml::B)));
00499                 writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::B), a->getMulti(Uml::B), a->getRoleDoc(Uml::B), a->getVisibility(Uml::B), java);
00500             }
00501 
00502             // print RoleA decl
00503             if (printRoleA)
00504             {
00505                 QString fieldClassName = cleanName(getUMLObjectName(a->getObject(Uml::A)));
00506                 writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::A), a->getMulti(Uml::A), a->getRoleDoc(Uml::A), a->getVisibility(Uml::A), java);
00507             }
00508         }
00509     }
00510 }
00511 
00512 void JavaWriter::writeAssociationRoleDecl(QString fieldClassName,
00513         QString roleName, QString multi,
00514         QString doc, Uml::Visibility visib, QTextStream &java)
00515 {
00516     // ONLY write out IF there is a rolename given
00517     // otherwise its not meant to be declared in the code
00518     if (roleName.isEmpty())
00519         return;
00520 
00521     QString scope = scopeToJavaDecl(visib);
00522 
00523     // always put space between this and prior decl, if any
00524     writeBlankLine(java);
00525 
00526     if (!doc.isEmpty())
00527         writeComment(doc, m_indentation, java);
00528 
00529     // declare the association based on whether it is this a single variable
00530     // or a List (Vector). One day this will be done correctly with special
00531     // multiplicity object that we don't have to figure out what it means via regex.
00532     if(multi.isEmpty() || multi.contains(QRegExp("^[01]$")))
00533     {
00534         QString fieldVarName = "m_" + roleName.replace(0, 1, roleName.left(1).lower());
00535         java<<startline<<scope<<" "<<fieldClassName<<" "<<fieldVarName<<";";
00536     }
00537     else
00538     {
00539         QString fieldVarName = roleName.lower() + "Vector";
00540         java<<startline<<scope<<" Vector "<<fieldVarName<<" = new Vector();";
00541         // from here we could initialize default values, or put in an init() section
00542         // of the constructors
00543     }
00544 
00545 }
00546 
00547 void JavaWriter::writeAssociationMethods (UMLAssociationList associations, UMLClassifier *thisClass, QTextStream &java)
00548 {
00549     if( forceSections() || !associations.isEmpty() )
00550     {
00551         for(UMLAssociation *a = associations.first(); a; a = associations.next())
00552         {
00553 
00554             // insert the methods to access the role of the other
00555             // class in the code of this one
00556             if (a->getObjectId(Uml::A) == thisClass->getID())
00557             {
00558                 // only write out IF there is a rolename given
00559                 if(!a->getRoleName(Uml::B).isEmpty()) {
00560                     QString fieldClassName = getUMLObjectName(a->getObject(Uml::B));
00561                     writeAssociationRoleMethod(fieldClassName,
00562                                                a->getRoleName(Uml::B),
00563                                                a->getMulti(Uml::B), a->getRoleDoc(Uml::B),
00564                                                a->getVisibility(Uml::B),
00565                                                a->getChangeability(Uml::B), java);
00566                 }
00567             }
00568 
00569             if (a->getObjectId(Uml::B) == thisClass->getID())
00570             {
00571                 // only write out IF there is a rolename given
00572                 if(!a->getRoleName(Uml::A).isEmpty()) {
00573                     QString fieldClassName = getUMLObjectName(a->getObject(Uml::A));
00574                     writeAssociationRoleMethod(fieldClassName, a->getRoleName(Uml::A),
00575                                                a->getMulti(Uml::A),
00576                                                a->getRoleDoc(Uml::A),
00577                                                a->getVisibility(Uml::A),
00578                                                a->getChangeability(Uml::A),
00579                                                java);
00580                 }
00581             }
00582 
00583         }
00584     }
00585 }
00586 
00587 void JavaWriter::writeAssociationRoleMethod (QString fieldClassName, QString roleName, QString multi,
00588         QString description, Uml::Visibility visib, Uml::Changeability_Type change,
00589         QTextStream &java)
00590 {
00591     if(multi.isEmpty() || multi.contains(QRegExp("^[01]$")))
00592     {
00593         QString fieldVarName = "m_" + roleName.replace(0, 1, roleName.left(1).lower());
00594         writeSingleAttributeAccessorMethods(fieldClassName, fieldVarName, roleName,
00595                                             description, visib, change, false, java);
00596     }
00597     else
00598     {
00599         QString fieldVarName = roleName.lower() + "Vector";
00600         writeVectorAttributeAccessorMethods(fieldClassName, fieldVarName, roleName,
00601                                             description, visib, change, java);
00602     }
00603 }
00604 
00605 void JavaWriter::writeVectorAttributeAccessorMethods (QString fieldClassName, QString fieldVarName,
00606         QString fieldName, QString description,
00607         Uml::Visibility visibility, Uml::Changeability_Type changeType,
00608         QTextStream &java)
00609 {
00610 
00611     fieldClassName = fixTypeName(fieldClassName);
00612     fieldName = capitaliseFirstLetter(fieldName);
00613     QString strVis = scopeToJavaDecl(visibility);
00614 
00615     // ONLY IF changeability is NOT Frozen
00616     if (changeType != Uml::chg_Frozen)
00617     {
00618         writeDocumentation("Add a "+fieldName+" object to the "+fieldVarName+" List",description,"",m_indentation,java);
00619         java<<startline<<strVis<<" void add"<<fieldName<<" ( "<<fieldClassName<<" new_object ) {";
00620         java<<startline<<m_indentation<<fieldVarName<<".add(new_object);";
00621         java<<startline<<"}"<<m_endl;
00622     }
00623 
00624     // ONLY IF changeability is Changeable
00625     if (changeType == Uml::chg_Changeable)
00626     {
00627         writeDocumentation("Remove a "+fieldName+" object from "+fieldVarName+" List",description,"",m_indentation,java);
00628         java<<startline<<strVis<<" void remove"<<fieldName<<" ( "<<fieldClassName<<" new_object )";
00629         java<<startline<<"{";
00630         java<<startline<<m_indentation<<fieldVarName<<".remove(new_object);";
00631         java<<startline<<"}"<<m_endl;
00632     }
00633 
00634     // always allow getting the list of stuff
00635     writeDocumentation("Get the List of "+fieldName+" objects held by "+fieldVarName,description,"@return List of "+fieldName+" objects held by "+fieldVarName,m_indentation,java);
00636     java<<startline<<strVis<<" List get"<<fieldName<<"List ( ) {";
00637     java<<startline<<m_indentation<<"return (List) "<<fieldVarName<<";";
00638     java<<startline<<"}"<<m_endl;
00639     writeBlankLine(java);
00640 }
00641 
00642 
00643 void JavaWriter::writeSingleAttributeAccessorMethods(QString fieldClassName, QString fieldVarName,
00644         QString fieldName, QString description,
00645         Uml::Visibility visibility, Uml::Changeability_Type change,
00646         bool isFinal, QTextStream &java)
00647 {
00648 
00649     QString strVis = scopeToJavaDecl(visibility);
00650     fieldClassName = fixTypeName(fieldClassName);
00651     fieldName = capitaliseFirstLetter(fieldName);
00652 
00653     // set method
00654     if (change == Uml::chg_Changeable && !isFinal) {
00655         writeDocumentation("Set the value of "+fieldVarName,description,"@param newVar the new value of "+fieldVarName,m_indentation,java);
00656         java<<startline<<strVis<<" void set"<<fieldName<<" ( "<<fieldClassName<<" newVar ) {";
00657         java<<startline<<m_indentation<<fieldVarName<<" = newVar;";
00658         java<<startline<<"}"<<m_endl;
00659     }
00660 
00661     // get method
00662     writeDocumentation("Get the value of "+fieldVarName,description,"@return the value of "+fieldVarName,m_indentation,java);
00663     java<<startline<<strVis<<" "<<fieldClassName<<" get"<<fieldName<<" ( ) {";
00664     java<<startline<<m_indentation<<"return "<<fieldVarName<<";";
00665     java<<startline<<"}";
00666     writeBlankLine(java);
00667 }
00668 
00669 void JavaWriter::writeConstructor(UMLClassifier *c, QTextStream &java)
00670 {
00671 
00672     if (forceDoc())
00673     {
00674         java<<startline;
00675         writeComment("", m_indentation, java);
00676         writeComment("Constructors", m_indentation, java);
00677         writeComment("", m_indentation, java);
00678         writeBlankLine(java);
00679     }
00680 
00681     // write the first constructor
00682     QString className = cleanName(c->getName());
00683     java<<m_indentation<<"public "<<className<<" () { };";
00684 
00685 }
00686 
00687 // IF the type is "string" we need to declare it as
00688 // the Java Object "String" (there is no string primative in Java).
00689 // Same thing again for "bool" to "boolean"
00690 QString JavaWriter::fixTypeName(const QString& string)
00691 {
00692     if (string.isEmpty())
00693         return "void";
00694     if (string == "string")
00695         return "String";
00696     if (string == "bool")
00697         return "boolean";
00698     return string;
00699 }
00700 
00701 QStringList JavaWriter::defaultDatatypes() {
00702     QStringList l;
00703     l.append("int");
00704     l.append("char");
00705     l.append("boolean");
00706     l.append("float");
00707     l.append("double");
00708     l.append("byte");
00709     l.append("short");
00710     l.append("long");
00711     l.append("String");
00712     return l;
00713 }
00714 
00715 
00716 bool JavaWriter::compareJavaMethod(UMLOperation *op1, UMLOperation *op2)
00717 {
00718     if (op1 == NULL || op2 == NULL)
00719         return false;
00720     if (op1 == op2)
00721         return true;
00722     if (op1->getName() != op2->getName())
00723         return false;
00724     UMLAttributeList atl1 = op1->getParmList();
00725     UMLAttributeList atl2 = op2->getParmList();
00726     if (atl1.count() != atl2.count())
00727         return false;
00728     UMLAttribute *at1;
00729     UMLAttribute *at2;
00730     for (at1  = atl1.first(), at2 = atl2.first(); at1 && at2 ; at1 = atl1.next(),at2 = atl2.next())
00731     {
00732         if (at1->getTypeName() != at2->getTypeName())
00733             return false;
00734     }
00735     return true;
00736 
00737 }
00738 
00739 bool JavaWriter::javaMethodInList(UMLOperation *umlOp, UMLOperationList &opl)
00740 {
00741     for (UMLOperation *op = opl.first(); op; op = opl.next()) {
00742         if (JavaWriter::compareJavaMethod(op, umlOp)) {
00743             return true;
00744         }
00745     }
00746     return false;
00747 }
00748 
00749 void JavaWriter::getSuperImplementedOperations(UMLClassifier *c, UMLOperationList &yetImplementedOpList ,UMLOperationList &toBeImplementedOpList, bool noClassInPath)
00750 {
00751     UMLClassifierList superClasses = c->findSuperClassConcepts();
00752 
00753     for (UMLClassifier *concept= superClasses.first(); concept; concept = superClasses.next())
00754     {
00755         getSuperImplementedOperations(concept, yetImplementedOpList, toBeImplementedOpList, (concept->isInterface() && noClassInPath));
00756         UMLOperationList opl = concept->getOpList();
00757         for (UMLOperation *op = opl.first(); op; op = opl.next()) {
00758             if (concept->isInterface() && noClassInPath) {
00759                 if (!JavaWriter::javaMethodInList(op,toBeImplementedOpList))
00760                     toBeImplementedOpList.append(op);
00761             }
00762             else
00763             {
00764                 if (!JavaWriter::javaMethodInList(op, yetImplementedOpList))
00765                     yetImplementedOpList.append(op);
00766             }
00767         }
00768     }
00769 
00770 }
00771 
00772 void JavaWriter::getInterfacesOperationsToBeImplemented(UMLClassifier *c, UMLOperationList &opList )
00773 {
00774     UMLOperationList yetImplementedOpList;
00775     UMLOperationList toBeImplementedOpList;
00776 
00777     getSuperImplementedOperations(c,yetImplementedOpList, toBeImplementedOpList);
00778     for (UMLOperation *op = toBeImplementedOpList.first(); op; op = toBeImplementedOpList.next())
00779     {
00780         if ( ! JavaWriter::javaMethodInList(op, yetImplementedOpList) && ! JavaWriter::javaMethodInList(op, opList) )
00781             opList.append(op);
00782     }
00783 }
00784 
00785 void JavaWriter::writeOperations(UMLClassifier *c, QTextStream &java) {
00786     UMLOperationList opl;
00787     UMLOperationList oppub,opprot,oppriv;
00788     oppub.setAutoDelete(false);
00789     opprot.setAutoDelete(false);
00790     oppriv.setAutoDelete(false);
00791 
00792     //sort operations by scope first and see if there are abstract methods
00793     opl = c->getOpList();
00794     if (! c->isInterface()) {
00795         getInterfacesOperationsToBeImplemented(c, opl);
00796     }
00797     for (UMLOperation *op = opl.first(); op; op = opl.next()) {
00798         switch(op->getVisibility()) {
00799           case Uml::Visibility::Public:
00800             oppub.append(op);
00801             break;
00802           case Uml::Visibility::Protected:
00803             opprot.append(op);
00804             break;
00805           case Uml::Visibility::Private:
00806             oppriv.append(op);
00807             break;
00808           default:
00809             break;
00810         }
00811     }
00812 
00813     // do people REALLY want these comments? Hmm.
00814     /*
00815       if(forceSections() || oppub.count())
00816       {
00817       writeComment("public operations",m_indentation,java);
00818         writeBlankLine(java);
00819       }
00820     */
00821     writeOperations(oppub,java);
00822 
00823     /*
00824       if(forceSections() || opprot.count())
00825       {
00826       writeComment("protected operations",m_indentation,java);
00827         writeBlankLine(java);
00828       }
00829     */
00830     writeOperations(opprot,java);
00831 
00832     /*
00833       if(forceSections() || oppriv.count())
00834       {
00835       writeComment("private operations",m_indentation,java);
00836         writeBlankLine(java);
00837       }
00838     */
00839     writeOperations(oppriv,java);
00840 
00841 }
00842 
00843 void JavaWriter::writeOperations(UMLOperationList &oplist, QTextStream &java) {
00844     UMLOperation *op;
00845     UMLAttributeList atl;
00846     UMLAttribute *at;
00847     int i,j;
00848     QString str;
00849 
00850     // generate method decl for each operation given
00851     for( op=oplist.first(); op ;op=oplist.next())
00852     {
00853 
00854         QString returnStr = "";
00855         // write documentation
00856 
00857         QString methodReturnType = fixTypeName(op->getTypeName());
00858         if(methodReturnType != "void")
00859             returnStr += "@return       "+methodReturnType+"\n";
00860 
00861         str = ""; // reset for next method
00862         str += ((op->getAbstract() && !isInterface) ? "abstract ":"");
00863         str += scopeToJavaDecl(op->getVisibility()) + ' ';
00864         str += (op->getStatic() ? "static ":"");
00865         str += methodReturnType + ' ' +cleanName(op->getName()) + "( ";
00866 
00867         atl = op->getParmList();
00868         i= atl.count();
00869         j=0;
00870         for (at = atl.first(); at; at = atl.next(), j++) {
00871             QString typeName = fixTypeName(at->getTypeName());
00872             QString atName = cleanName(at->getName());
00873             str += typeName + ' ' + atName +
00874                    (!(at->getInitialValue().isEmpty()) ?
00875                     (QString(" = ")+at->getInitialValue()) :
00876                     QString(""))
00877                    + ((j < i-1)?", ":"");
00878             returnStr += "@param        "+atName+' '+at->getDoc()+"\n";
00879         }
00880         str+= " )";
00881 
00882         // method only gets a body IF its not abstract
00883         if (op->getAbstract() || isInterface)
00884             str+=";\n\n"; // terminate now
00885         else
00886             str+=startline+"{\n\n"+m_indentation+"}\n\n"; // empty method body
00887 
00888         // write it out
00889         writeDocumentation("", op->getDoc(), returnStr, m_indentation, java);
00890         java<<startline<<str;
00891     }
00892 }
00893 
00894 QString JavaWriter::fixInitialStringDeclValue(QString value, QString type)
00895 {
00896     // check for strings only
00897     if (!value.isEmpty() && type == "String") {
00898         if (!value.startsWith("\""))
00899             value.prepend("\"");
00900         if (!value.endsWith("\""))
00901             value.append("\"");
00902     }
00903     return value;
00904 }
00905 
00906 QString JavaWriter::scopeToJavaDecl(Uml::Visibility scope)
00907 {
00908     QString scopeString;
00909     switch(scope)
00910     {
00911       case Uml::Visibility::Public:
00912         scopeString = "public";
00913         break;
00914       case Uml::Visibility::Protected:
00915         scopeString = "protected";
00916         break;
00917       case Uml::Visibility::Private:
00918     default:
00919         scopeString = "private";
00920         break;
00921     }
00922     return scopeString;
00923 }
00924 
00925 // methods like this _shouldn't_ be needed IF we properly did things thruought the code.
00926 QString JavaWriter::getUMLObjectName(UMLObject *obj)
00927 {
00928     return(obj!=0)?obj->getName():QString("NULL");
00929 }
00930 
00931 QString JavaWriter::capitaliseFirstLetter(QString string)
00932 {
00933     // we could lowercase everything tostart and then capitalize? Nah, it would
00934     // screw up formatting like getMyRadicalVariable() to getMyradicalvariable(). Bah.
00935     QChar firstChar = string.at(0);
00936     string.replace( 0, 1, firstChar.upper());
00937     return string;
00938 }
00939 
00940 void JavaWriter::writeBlankLine(QTextStream &java)
00941 {
00942     java<<m_endl;
00943 }
00944 
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:57 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003