umbrello API Documentation

cppheadercodedocument.cpp

00001 /***************************************************************************
00002  *                                                                         *
00003  *   This program is free software; you can redistribute it and/or modify  *
00004  *   it under the terms of the GNU General Public License as published by  *
00005  *   the Free Software Foundation; either version 2 of the License, or     *
00006  *   (at your option) any later version.                                   *
00007  *                                                                         *
00008  *   copyright (C) 2004-2007                                               *
00009  *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
00010  ***************************************************************************/
00011 
00012 /*  This code generated by:
00013  *      Author : thomas
00014  *      Date   : Thu Aug 28 2003
00015  */
00016 
00029 // own header
00030 #include "cppheadercodedocument.h"
00031 
00032 // qt/kde includes
00033 #include <qregexp.h>
00034 #include <kdebug.h>
00035 
00036 // local includes
00037 #include "cppcodegenerator.h"
00038 #include "cppcodegenerationpolicy.h"
00039 #include "cppcodedocumentation.h"
00040 #include "cppheadercodeaccessormethod.h"
00041 #include "cppheadercodeoperation.h"
00042 #include "cppheaderclassdeclarationblock.h"
00043 #include "cppheadercodeclassfielddeclarationblock.h"
00044 #include "../umlpackagelist.h"
00045 #include "../package.h"
00046 #include "../umlclassifierlistitemlist.h"
00047 #include "../classifierlistitem.h"
00048 #include "../enum.h"
00049 #include "../uml.h"
00050 
00051 // Constructors/Destructors
00052 //
00053 
00054 CPPHeaderCodeDocument::CPPHeaderCodeDocument ( UMLClassifier * concept )
00055         : ClassifierCodeDocument (concept) {
00056     setFileExtension(".h");
00057 
00058     //initCodeClassFields(); // this is dubious because it calls down to
00059                              // CodeGenFactory::newCodeClassField(this)
00060                              // but "this" is still in construction at that time.
00061 
00062     // needed? I doubt it, but it feels good to do it.
00063     classDeclCodeBlock = 0;
00064     publicBlock = 0;
00065     protectedBlock = 0;
00066     privateBlock = 0;
00067     namespaceBlock = 0;
00068     pubConstructorBlock = 0;
00069     protConstructorBlock = 0;
00070     privConstructorBlock = 0;
00071     pubOperationsBlock = 0;
00072     privOperationsBlock = 0;
00073     protOperationsBlock = 0;
00074 
00075     // this will call updateContent() as well as other things that sync our document.
00076     //synchronize();
00077 
00078 }
00079 
00080 CPPHeaderCodeDocument::~CPPHeaderCodeDocument ( ) { }
00081 
00082 //
00083 // Methods
00084 //
00085 
00086 // Accessor methods
00087 //
00088 
00089 CPPHeaderClassDeclarationBlock * CPPHeaderCodeDocument::getClassDecl()
00090 {
00091 
00092     if(!classDeclCodeBlock) {
00093         classDeclCodeBlock = new CPPHeaderClassDeclarationBlock (this); // was deleted before our load
00094         classDeclCodeBlock->setTag("classDeclarationBlock");
00095     }
00096     return classDeclCodeBlock;
00097 }
00098 
00099 // Other methods
00100 //
00101 
00102 // Sigh. NOT optimal. The only reason that we need to have this
00103 // is so we can create the CPPHeaderClassDeclarationBlock.
00104 // would be better if we could create a handler interface that each
00105 // codeblock used so all we have to do here is add the handler
00106 void CPPHeaderCodeDocument::loadChildTextBlocksFromNode ( QDomElement & root)
00107 {
00108 
00109     QDomNode tnode = root.firstChild();
00110     QDomElement telement = tnode.toElement();
00111     bool loadCheckForChildrenOK = false;
00112     while( !telement.isNull() ) {
00113         QString nodeName = telement.tagName();
00114 
00115         if( nodeName == "textblocks" ) {
00116 
00117             QDomNode node = telement.firstChild();
00118             QDomElement element = node.toElement();
00119 
00120             // if there is nothing to begin with, then we don't worry about it
00121             loadCheckForChildrenOK = element.isNull() ? true : false;
00122 
00123             while( !element.isNull() ) {
00124                 QString name = element.tagName();
00125 
00126                 if( name == "codecomment" ) {
00127                     CodeComment * block = new CPPCodeDocumentation(this);
00128                     block->loadFromXMI(element);
00129                     if(!addTextBlock(block))
00130                     {
00131                         kError()<<"Unable to add codeComment to :"<<this<<endl;
00132                         block->deleteLater();
00133                     } else
00134                         loadCheckForChildrenOK= true;
00135                 } else
00136                     if( name == "codeaccessormethod" ||
00137                             name == "ccfdeclarationcodeblock"
00138                       ) {
00139                         QString acctag = element.attribute("tag","");
00140                         // search for our method in the
00141                         TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag);
00142                         if(!tb || !addTextBlock(tb))
00143                         {
00144                             kError()<<"Unable to add codeclassfield child method to:"<<this<<endl;
00145                             // DON'T delete
00146                         } else
00147                             loadCheckForChildrenOK= true;
00148 
00149                     } else
00150                         if( name == "codeblock" ) {
00151                             CodeBlock * block = newCodeBlock();
00152                             block->loadFromXMI(element);
00153                             if(!addTextBlock(block))
00154                             {
00155                                 kError()<<"Unable to add codeBlock to :"<<this<<endl;
00156                                 block->deleteLater();
00157                             } else
00158                                 loadCheckForChildrenOK= true;
00159                         } else
00160                             if( name == "codeblockwithcomments" ) {
00161                                 CodeBlockWithComments * block = newCodeBlockWithComments();
00162                                 block->loadFromXMI(element);
00163                                 if(!addTextBlock(block))
00164                                 {
00165                                     kError()<<"Unable to add codeBlockwithcomments to:"<<this<<endl;
00166                                     block->deleteLater();
00167                                 } else
00168                                     loadCheckForChildrenOK= true;
00169                             } else
00170                                 if( name == "header" ) {
00171                                     // do nothing.. this is treated elsewhere
00172                                 } else
00173                                     if( name == "hierarchicalcodeblock" ) {
00174                                         HierarchicalCodeBlock * block = newHierarchicalCodeBlock();
00175                                         block->loadFromXMI(element);
00176                                         if(!addTextBlock(block))
00177                                         {
00178                                             kError()<<"Unable to add hierarchicalcodeBlock to:"<<this<<endl;
00179                                             block->deleteLater();
00180                                         } else
00181                                             loadCheckForChildrenOK= true;
00182                                     } else
00183                                         if( name == "codeoperation" ) {
00184                                             // find the code operation by id
00185                                             QString id = element.attribute("parent_id","-1");
00186                                             UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(STR2ID(id));
00187                                             UMLOperation * op = dynamic_cast<UMLOperation*>(obj);
00188                                             if(op) {
00189                                                 CodeOperation * block = new CPPHeaderCodeOperation(this, op);
00190                                                 block->loadFromXMI(element);
00191                                                 if(addTextBlock(block))
00192                                                     loadCheckForChildrenOK= true;
00193                                                 else
00194                                                 {
00195                                                     kError()<<"Unable to add codeoperation to:"<<this<<endl;
00196                                                     block->deleteLater();
00197                                                 }
00198                                             } else
00199                                                 kError()<<"Unable to find operation create codeoperation for:"<<this<<endl;
00200                                         }
00201                                         else
00202                                             if( name == "cppheaderclassdeclarationblock" )
00203                                             {
00204                                                 CPPHeaderClassDeclarationBlock * block = getClassDecl();
00205                                                 block->loadFromXMI(element);
00206                                                 // normally this would be populated by the following syncToparent
00207                                                 // call, but we cant wait for it, so lets just do it now.
00208                                                 namespaceBlock = getHierarchicalCodeBlock("namespace", "Namespace", 0);
00209 
00210                                                 if(!namespaceBlock || !namespaceBlock->addTextBlock(block))
00211                                                 {
00212                                                     kError()<<"Error:cant add class declaration codeblock"<<endl;
00213                                                     // DON'T delete/release block
00214                                                     // block->release();
00215                                                 } else
00216                                                     loadCheckForChildrenOK= true;
00217 
00218                                             }
00219                 // only needed for extreme debugging conditions (E.g. making new codeclassdocument loader)
00220                 //else
00221                 //kDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignorning"<<endl;
00222 
00223                 node = element.nextSibling();
00224                 element = node.toElement();
00225             }
00226             break;
00227         }
00228 
00229         tnode = telement.nextSibling();
00230         telement = tnode.toElement();
00231     }
00232 
00233     if(!loadCheckForChildrenOK)
00234     {
00235         CodeDocument * test = dynamic_cast<CodeDocument*>(this);
00236         if(test)
00237         {
00238             kWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<<test->getFileName()<<" "<<this<<endl;
00239         } else {
00240             HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(this);
00241             if(hb)
00242                 kWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<<hb->getTag()<<" "<<this<<endl;
00243             else
00244                 kDebug()<<" loadChildBlocks : unable to initialize any child blocks in UNKNOWN OBJ:"<<this<<endl;
00245         }
00246     }
00247 
00248 }
00249 
00250 void CPPHeaderCodeDocument::resetTextBlocks()
00251 {
00252 
00253     // all special pointers need to be zero'd out.
00254     classDeclCodeBlock = 0;
00255     publicBlock = 0;
00256     protectedBlock = 0;
00257     privateBlock = 0;
00258     namespaceBlock = 0;
00259     pubConstructorBlock = 0;
00260     protConstructorBlock = 0;
00261     privConstructorBlock = 0;
00262     pubOperationsBlock = 0;
00263     privOperationsBlock = 0;
00264     protOperationsBlock = 0;
00265 
00266     // now do the traditional release of child text blocks
00267     ClassifierCodeDocument::resetTextBlocks();
00268 
00269 }
00270 
00274 // in the vannilla version, we just tack all operations on the end
00275 // of the document
00276 bool CPPHeaderCodeDocument::addCodeOperation (CodeOperation * op ) {
00277 
00278     Uml::Visibility scope = op->getParentOperation()->getVisibility();
00279     if(!op->getParentOperation()->isLifeOperation())
00280     {
00281         switch (scope) {
00282         default:
00283               case Uml::Visibility::Public:
00284             return pubOperationsBlock->addTextBlock(op);
00285             break;
00286               case Uml::Visibility::Protected:
00287             return protOperationsBlock->addTextBlock(op);
00288             break;
00289               case Uml::Visibility::Private:
00290             return privOperationsBlock->addTextBlock(op);
00291             break;
00292         }
00293     } else {
00294         switch (scope) {
00295         default:
00296               case Uml::Visibility::Public:
00297             return pubConstructorBlock->addTextBlock(op);
00298             break;
00299               case Uml::Visibility::Protected:
00300             return protConstructorBlock->addTextBlock(op);
00301             break;
00302               case Uml::Visibility::Private:
00303             return privConstructorBlock->addTextBlock(op);
00304             break;
00305         }
00306     }
00307 }
00308 
00309 
00314 /*
00315 void CPPHeaderCodeDocument::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
00316         QDomElement docElement = doc.createElement( "" );
00317 
00318         setAttributesOnNode(doc, docElement);
00319 
00320         root.appendChild( docElement );
00321 }
00322 */
00323 
00324 // This method will cause the class to rebuild its text representation.
00325 // based on the parent classifier object.
00326 // For any situation in which this is called, we are either building the code
00327 // document up, or replacing/regenerating the existing auto-generated parts. As
00328 // such, we will want to insert everything we resonablely will want
00329 // during creation. We can set various parts of the document (esp. the
00330 // comments) to appear or not, as needed.
00331 void CPPHeaderCodeDocument::updateContent( )
00332 {
00333 
00334     // Gather info on the various fields and parent objects of this class...
00335     UMLClassifier * c = getParentClassifier();
00336     CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt();
00337     CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
00338 
00339     // first, set the global flag on whether or not to show classfield info
00340     CodeClassFieldList * cfList = getCodeClassFieldList();
00341     for(CodeClassField * field = cfList->first(); field; field = cfList->next())
00342         field->setWriteOutMethods(policy->getAutoGenerateAccessors());
00343 
00344     // attribute-based ClassFields
00345     // we do it this way to have the static fields sorted out from regular ones
00346     CodeClassFieldList staticPublicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Public );
00347     CodeClassFieldList publicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Public );
00348     CodeClassFieldList staticProtectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Protected );
00349     CodeClassFieldList protectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Protected );
00350     CodeClassFieldList staticPrivateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Private );
00351     CodeClassFieldList privateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Private);
00352 
00353     // association-based ClassFields
00354     // don't care if they are static or not..all are lumped together
00355     CodeClassFieldList publicPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Public);
00356     CodeClassFieldList publicAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Public);
00357     CodeClassFieldList publicCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Public );
00358 
00359     CodeClassFieldList protPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Protected);
00360     CodeClassFieldList protAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Protected);
00361     CodeClassFieldList protCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Protected);
00362 
00363     CodeClassFieldList privPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Private);
00364     CodeClassFieldList privAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Private);
00365     CodeClassFieldList privCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Private);
00366 
00367     bool hasOperationMethods = c->getOpList().last() ? true : false;
00368     bool hasNamespace = false;
00369     bool isEnumeration = false;
00370     bool isInterface = parentIsInterface();
00371     bool hasclassFields = hasClassFields();
00372     bool forcedoc = UMLApp::app()->getCommonPolicy()->getCodeVerboseDocumentComments();
00373     QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars();
00374 
00375     UMLClassifierList superclasses = c->findSuperClassConcepts();
00376 
00377 
00378     // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT
00379     //
00380 
00381     // Write the hash define stuff to prevent multiple parsing/inclusion of header
00382     QString cppClassName = CodeGenerator::cleanName(c->getName());
00383     QString hashDefine = CodeGenerator::cleanName(c->getName().upper().simplifyWhiteSpace());
00384     QString defText = "#ifndef "+hashDefine + "_H"+ endLine + "#define "+ hashDefine + "_H";
00385     addOrUpdateTaggedCodeBlockWithComments("hashDefBlock", defText, "", 0, false);
00386 
00387     // INCLUDE CODEBLOCK
00388     //
00389     // Q: Why all utils? Isnt just List and Vector the only classes we are using?
00390     // A: doesn't matter at all; its more readable to just include '*' and cpp compilers
00391     //    don't slow down or anything. (TZ)
00392     QString includeStatement = "";
00393     bool stringGlobal = policy->stringIncludeIsGlobal();
00394     QString sStartBrak = stringGlobal ? "<" : "\"";
00395     QString sEndBrak = stringGlobal ? ">" : "\"";
00396     includeStatement.append("#include "+sStartBrak+policy->getStringClassNameInclude()+sEndBrak+endLine);
00397     if ( hasObjectVectorClassFields() )
00398     {
00399         bool vecGlobal = policy->vectorIncludeIsGlobal();
00400         QString vStartBrak = vecGlobal ? "<" : "\"";
00401         QString vEndBrak = vecGlobal ? ">" : "\"";
00402         QString value ="#include "+vStartBrak+policy->getVectorClassNameInclude()+vEndBrak;
00403         includeStatement.append(value+endLine);
00404     }
00405 
00406     //only include classes in a different package from this class
00407     UMLPackageList includes;
00408     QMap<UMLPackage *,QString> packageMap; // so we don't repeat packages
00409 
00410     CodeGenerator::findObjectsRelated(c,includes);
00411     for(UMLPackage *con = includes.first(); con ; con = includes.next())
00412         if (con->getBaseType() != Uml::ot_Datatype && !packageMap.contains(con))
00413         {
00414             packageMap.insert(con,con->getPackage());
00415             if(con != getParentClassifier())
00416                 includeStatement.append("#include \""+CodeGenerator::cleanName(con->getName().lower())+".h\""+endLine);
00417         }
00418     // now, add/update the includes codeblock
00419     CodeBlockWithComments * inclBlock = addOrUpdateTaggedCodeBlockWithComments("includes", includeStatement, QString::null, 0, false);
00420     if(includeStatement.isEmpty() && inclBlock->getContentType() == CodeBlock::AutoGenerated)
00421         inclBlock->setWriteOutText(false);
00422     else
00423         inclBlock->setWriteOutText(true);
00424 
00425     // Using
00426     QString usingStatement;
00427     for(UMLClassifier *classifier = superclasses.first(); classifier ; classifier = superclasses.next()) {
00428         if(classifier->getPackage()!=c->getPackage() && !classifier->getPackage().isEmpty()) {
00429             usingStatement.append("using "+CodeGenerator::cleanName(c->getPackage())+"::"+cleanName(c->getName())+';'+endLine);
00430         }
00431     }
00432     CodeBlockWithComments * usingBlock = addOrUpdateTaggedCodeBlockWithComments("using", usingStatement, "", 0, false);
00433     if(usingStatement.isEmpty() && usingBlock->getContentType() == CodeBlock::AutoGenerated)
00434         usingBlock->setWriteOutText(false);
00435     else
00436         usingBlock->setWriteOutText(true);
00437 
00438     // namespace
00439     // This needs special treatment. We cant use "nowriteouttext" for this, as
00440     // that will prevent the class declaration from being written. Instead, we
00441     // check if "hasNamspace" is true or not, and then indent the remaining code
00442     // appropriately as well as set the start/end text of this namespace block.
00443     if (c->getUMLPackage() && policy->getPackageIsNamespace())
00444         hasNamespace = true;
00445     else
00446         hasNamespace = false;
00447 
00448     // set start/end text of namespace block
00449     namespaceBlock = getHierarchicalCodeBlock("namespace", "Namespace", 0);
00450     if(hasNamespace) {
00451         UMLPackageList pkgList = c->getPackages();
00452         QString pkgs;
00453         UMLPackage *pkg;
00454         for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) {
00455             pkgs += "namespace " + CodeGenerator::cleanName(pkg->getName()) + " { ";
00456         }
00457         namespaceBlock->setStartText(pkgs);
00458         QString closingBraces;
00459         for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) {
00460             closingBraces += "} ";
00461         }
00462         namespaceBlock->setEndText(closingBraces);
00463         namespaceBlock->getComment()->setWriteOutText(true);
00464     } else {
00465         namespaceBlock->setStartText("");
00466         namespaceBlock->setEndText("");
00467         namespaceBlock->getComment()->setWriteOutText(false);
00468     }
00469 
00470     // Enum types for include
00471     if (!isInterface) {
00472         QString enumStatement;
00473         QString indent = UMLApp::app()->getCommonPolicy()->getIndentation();
00474         UMLEnum* e = dynamic_cast<UMLEnum*>(c);
00475         if (e) {
00476             enumStatement.append(indent + "enum "+cppClassName+" {"+endLine);
00477 
00478             // populate
00479             UMLClassifierListItemList ell = e->getFilteredList(Uml::ot_EnumLiteral);
00480             for (UMLClassifierListItem *el=ell.first(); el ; ) {
00481                 enumStatement.append(indent+indent);
00482                 enumStatement.append(CodeGenerator::cleanName(el->getName()));
00483                 if ((el=ell.next()) != 0)
00484                     enumStatement.append(", "+endLine);
00485                 else
00486                     break;
00487                 enumStatement.append(endLine);
00488             }
00489             enumStatement.append(indent+"};");
00490             isEnumeration = true;
00491         }
00492         namespaceBlock->addOrUpdateTaggedCodeBlockWithComments("enums", enumStatement, "", 0, false);
00493     }
00494 
00495     // CLASS DECLARATION BLOCK
00496     //
00497 
00498     // add the class declaration block to the namespace block.
00499     CPPHeaderClassDeclarationBlock * myClassDeclCodeBlock = getClassDecl();
00500     namespaceBlock->addTextBlock(myClassDeclCodeBlock); // note: wont add if already present
00501 
00502     // Is this really true?? hmm..
00503     if(isEnumeration)
00504         myClassDeclCodeBlock->setWriteOutText(false); // not written out IF its an enumeration class
00505     else
00506         myClassDeclCodeBlock->setWriteOutText(true);
00507 
00508     //
00509     // Main Sub-Blocks
00510     //
00511 
00512     // declare public, protected and private methods, attributes (fields).
00513     // set the start text ONLY if this is the first time we created the objects.
00514     bool createdPublicBlock = publicBlock == 0 ? true : false;
00515     publicBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("publicBlock","Public stuff",0);
00516     if (createdPublicBlock)
00517         publicBlock->setStartText("public:");
00518 
00519     bool createdProtBlock = protectedBlock == 0 ? true : false;
00520     protectedBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("protectedBlock","Protected stuff",0);
00521     if(createdProtBlock)
00522         protectedBlock->setStartText("protected:");
00523 
00524     bool createdPrivBlock = privateBlock == 0 ? true : false;
00525     privateBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("privateBlock","Private stuff",0);
00526     if(createdPrivBlock)
00527         privateBlock->setStartText("private:");
00528 
00529     //
00530     // * CLASS FIELD declaration section
00531     //
00532 
00533     // setup/get/create the field declaration code block
00534     //
00535 
00536     // public fields: Update the comment: we only set comment to appear under the following conditions
00537     HierarchicalCodeBlock * publicFieldDeclBlock = publicBlock->getHierarchicalCodeBlock("publicFieldsDecl", "Fields", 1);
00538     CodeComment * pubFcomment = publicFieldDeclBlock->getComment();
00539     if (!forcedoc && !hasclassFields )
00540         pubFcomment->setWriteOutText(false);
00541     else
00542         pubFcomment->setWriteOutText(true);
00543 
00544     // protected fields: Update the comment: we only set comment to appear under the following conditions
00545     HierarchicalCodeBlock * protectedFieldDeclBlock = protectedBlock->getHierarchicalCodeBlock("protectedFieldsDecl", "Fields", 1);
00546     CodeComment * protFcomment = protectedFieldDeclBlock->getComment();
00547     if (!forcedoc && !hasclassFields )
00548         protFcomment->setWriteOutText(false);
00549     else
00550         protFcomment->setWriteOutText(true);
00551 
00552     // private fields: Update the comment: we only set comment to appear under the following conditions
00553     HierarchicalCodeBlock * privateFieldDeclBlock = privateBlock->getHierarchicalCodeBlock("privateFieldsDecl", "Fields", 1);
00554     CodeComment * privFcomment = privateFieldDeclBlock->getComment();
00555     if (!forcedoc && !hasclassFields )
00556         privFcomment->setWriteOutText(false);
00557     else
00558         privFcomment->setWriteOutText(true);
00559 
00560 
00561     // now actually declare the fields within the appropriate HCodeBlock
00562     //
00563 
00564     // public
00565     declareClassFields(staticPublicAttribClassFields, publicFieldDeclBlock);
00566     declareClassFields(publicAttribClassFields, publicFieldDeclBlock);
00567     declareClassFields(publicPlainAssocClassFields, publicFieldDeclBlock);
00568     declareClassFields(publicAggregationClassFields, publicFieldDeclBlock);
00569     declareClassFields(publicCompositionClassFields, publicFieldDeclBlock);
00570 
00571     // protected
00572     declareClassFields(staticProtectedAttribClassFields, protectedFieldDeclBlock);
00573     declareClassFields(protectedAttribClassFields, protectedFieldDeclBlock);
00574     declareClassFields(protPlainAssocClassFields, protectedFieldDeclBlock);
00575     declareClassFields(protAggregationClassFields, protectedFieldDeclBlock);
00576     declareClassFields(protCompositionClassFields, protectedFieldDeclBlock);
00577 
00578     // private
00579     declareClassFields(staticPrivateAttribClassFields, privateFieldDeclBlock);
00580     declareClassFields(privateAttribClassFields, privateFieldDeclBlock);
00581     declareClassFields(privPlainAssocClassFields, privateFieldDeclBlock);
00582     declareClassFields(privAggregationClassFields, privateFieldDeclBlock);
00583     declareClassFields(privCompositionClassFields, privateFieldDeclBlock);
00584 
00585     //
00586     // METHODS section
00587     //
00588 
00589     // get/create the method codeblock
00590 
00591     // public methods
00592     HierarchicalCodeBlock * pubMethodsBlock = publicBlock->getHierarchicalCodeBlock("pubMethodsBlock", "", 1);
00593     CodeComment * pubMethodsComment = pubMethodsBlock->getComment();
00594     // set conditions for showing this comment
00595     if (!forcedoc && !hasclassFields && !hasOperationMethods)
00596         pubMethodsComment->setWriteOutText(false);
00597     else
00598         pubMethodsComment->setWriteOutText(true);
00599 
00600     // protected methods
00601     HierarchicalCodeBlock * protMethodsBlock = protectedBlock->getHierarchicalCodeBlock("protMethodsBlock", "", 1);
00602     CodeComment * protMethodsComment = protMethodsBlock->getComment();
00603     // set conditions for showing this comment
00604     if (!forcedoc && !hasclassFields && !hasOperationMethods)
00605         protMethodsComment->setWriteOutText(false);
00606     else
00607         protMethodsComment->setWriteOutText(true);
00608 
00609     // private methods
00610     HierarchicalCodeBlock * privMethodsBlock = privateBlock->getHierarchicalCodeBlock("privMethodsBlock", "", 1);
00611     CodeComment * privMethodsComment = privMethodsBlock->getComment();
00612     // set conditions for showing this comment
00613     if (!forcedoc && !hasclassFields && !hasOperationMethods)
00614         privMethodsComment->setWriteOutText(false);
00615     else
00616         privMethodsComment->setWriteOutText(true);
00617 
00618 
00619     // METHODS sub-section : constructor methods
00620     //
00621     CodeGenerationPolicy *pol = UMLApp::app()->getCommonPolicy();
00622 
00623     // setup/get/create the constructor codeblocks
00624 
00625     // public
00626     pubConstructorBlock = pubMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1);
00627     // special condiions for showing comment: only when autogenerateding empty constructors
00628     // Although, we *should* check for other constructor methods too
00629     CodeComment * pubConstComment = pubConstructorBlock->getComment();
00630     if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors()))
00631         pubConstComment->setWriteOutText(false);
00632     else
00633         pubConstComment->setWriteOutText(true);
00634 
00635     // protected
00636     protConstructorBlock = protMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1);
00637     // special condiions for showing comment: only when autogenerateding empty constructors
00638     // Although, we *should* check for other constructor methods too
00639     CodeComment * protConstComment = protConstructorBlock->getComment();
00640     if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors()))
00641         protConstComment->setWriteOutText(false);
00642     else
00643         protConstComment->setWriteOutText(true);
00644 
00645     // private
00646     privConstructorBlock = privMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1);
00647     // special condiions for showing comment: only when autogenerateding empty constructors
00648     // Although, we *should* check for other constructor methods too
00649     CodeComment * privConstComment = privConstructorBlock->getComment();
00650     if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors()))
00651         privConstComment->setWriteOutText(false);
00652     else
00653         privConstComment->setWriteOutText(true);
00654 
00655     // add/get the empty constructor. I guess since there is no
00656     // meta-data to state what the scope of this method is, we will make it
00657     // "public" as a default. This might present problems if the user wants
00658     // to move the block into the "private" or "protected" blocks.
00659     QString CPPClassName = CodeGenerator::cleanName(c->getName());
00660     QString emptyConstStatement = CPPClassName+" ( ) { }";
00661 
00662     // search for this first in the entire document. IF not present, put
00663     // it in the public constructor method block
00664     TextBlock * emptyConstTb = findTextBlockByTag("emptyconstructor", true);
00665     CodeBlockWithComments * emptyConstBlock = dynamic_cast<CodeBlockWithComments*>(emptyConstTb);
00666     if(!emptyConstBlock)
00667         emptyConstBlock = pubConstructorBlock->addOrUpdateTaggedCodeBlockWithComments("emptyconstructor", emptyConstStatement, "Empty Constructor", 1, false);
00668 
00669     // Now, as an additional condition we only show the empty constructor block
00670     // IF it was desired to be shown
00671     if(!isInterface && pol->getAutoGenerateConstructors())
00672         emptyConstBlock->setWriteOutText(true);
00673     else
00674         emptyConstBlock->setWriteOutText(false);
00675 
00676 
00677     // METHODS subsection : ACCESSOR METHODS
00678     //
00679 
00680     // get/create the accessor codeblock
00681 
00682     // public
00683     HierarchicalCodeBlock * pubAccessorBlock = pubMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1);
00684     // set conditions for showing section comment
00685     CodeComment * pubAccessComment = pubAccessorBlock->getComment();
00686     if (!forcedoc && !hasclassFields)
00687         pubAccessComment->setWriteOutText(false);
00688     else
00689         pubAccessComment->setWriteOutText(true);
00690 
00691     // protected
00692     HierarchicalCodeBlock * protAccessorBlock = protMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1);
00693     // set conditions for showing section comment
00694     CodeComment * protAccessComment = protAccessorBlock->getComment();
00695     if (!forcedoc && !hasclassFields)
00696         protAccessComment->setWriteOutText(false);
00697     else
00698         protAccessComment->setWriteOutText(true);
00699 
00700     // private
00701     HierarchicalCodeBlock * privAccessorBlock = privMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1);
00702     // set conditions for showing section comment
00703     CodeComment * privAccessComment = privAccessorBlock->getComment();
00704     // We've to copy the private accessorMethods to the public block
00705     if (!forcedoc && !hasclassFields)
00706         privAccessComment->setWriteOutText(false);
00707     else
00708         privAccessComment->setWriteOutText(true);
00709 
00710     // now, 2 sub-sub sections in accessor block
00711     // add/update accessor methods for attributes
00712     HierarchicalCodeBlock * pubStaticAccessors = pubAccessorBlock->getHierarchicalCodeBlock("pubStaticAccessorMethods", "", 1);
00713     HierarchicalCodeBlock * pubRegularAccessors = pubAccessorBlock->getHierarchicalCodeBlock("pubRegularAccessorMethods", "", 1);
00714     pubStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
00715     pubRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
00716 
00717     HierarchicalCodeBlock * protStaticAccessors = protAccessorBlock->getHierarchicalCodeBlock("protStaticAccessorMethods", "", 1);
00718     HierarchicalCodeBlock * protRegularAccessors = protAccessorBlock->getHierarchicalCodeBlock("protRegularAccessorMethods", "", 1);
00719     protStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
00720     protRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
00721 
00722     HierarchicalCodeBlock * privStaticAccessors = privAccessorBlock->getHierarchicalCodeBlock("privStaticAccessorMethods", "", 1);
00723     HierarchicalCodeBlock * privRegularAccessors = privAccessorBlock->getHierarchicalCodeBlock("privRegularAccessorMethods", "", 1);
00724     privStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
00725     privRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
00726 
00727     // now add in accessors as appropriate
00728 
00729     // public stuff
00730     pubStaticAccessors->addCodeClassFieldMethods(staticPublicAttribClassFields);
00731     pubRegularAccessors->addCodeClassFieldMethods(publicAttribClassFields);
00732 
00733     // generate accessors as public
00734     if (policy && policy->getAccessorsArePublic())
00735     {
00736         pubRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields);
00737         pubRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields);
00738     }
00739 
00740     pubRegularAccessors->addCodeClassFieldMethods(publicPlainAssocClassFields);
00741     pubRegularAccessors->addCodeClassFieldMethods(publicAggregationClassFields);
00742     pubRegularAccessors->addCodeClassFieldMethods(publicCompositionClassFields);
00743 
00744     // protected stuff
00745     protStaticAccessors->addCodeClassFieldMethods(staticProtectedAttribClassFields);
00746 
00747     // accessors are public so we don't have to create it here
00748     if (policy && !policy->getAccessorsArePublic())
00749         protRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields);
00750 
00751     protRegularAccessors->addCodeClassFieldMethods(protPlainAssocClassFields);
00752     protRegularAccessors->addCodeClassFieldMethods(protAggregationClassFields);
00753     protRegularAccessors->addCodeClassFieldMethods(protCompositionClassFields);
00754 
00755     // private stuff
00756     privStaticAccessors->addCodeClassFieldMethods(staticPrivateAttribClassFields);
00757 
00758     // accessors are public so we don't have to create it here
00759     if (policy && !policy->getAccessorsArePublic())
00760         privRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields);
00761 
00762     privRegularAccessors->addCodeClassFieldMethods(privPlainAssocClassFields);
00763     privRegularAccessors->addCodeClassFieldMethods(privAggregationClassFields);
00764     privRegularAccessors->addCodeClassFieldMethods(privCompositionClassFields);
00765 
00766 
00767     // METHODS subsection : Operation methods (e.g. methods derive from operations but which arent constructors)
00768     //
00769 
00770     // setup/get/create the operations codeblock
00771 
00772     // public
00773     pubOperationsBlock = pubMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1);
00774     // set conditions for showing section comment
00775     CodeComment * pubOcomment = pubOperationsBlock->getComment();
00776     if (!forcedoc && !hasOperationMethods )
00777         pubOcomment->setWriteOutText(false);
00778     else
00779         pubOcomment->setWriteOutText(true);
00780 
00781     //protected
00782     protOperationsBlock = protMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1);
00783     // set conditions for showing section comment
00784     CodeComment * protOcomment = protOperationsBlock->getComment();
00785     if (!forcedoc && !hasOperationMethods )
00786         protOcomment->setWriteOutText(false);
00787     else
00788         protOcomment->setWriteOutText(true);
00789 
00790     //private
00791     privOperationsBlock = privMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1);
00792     // set conditions for showing section comment
00793     CodeComment * privOcomment = privOperationsBlock->getComment();
00794     if (!forcedoc && !hasOperationMethods )
00795         privOcomment->setWriteOutText(false);
00796     else
00797         privOcomment->setWriteOutText(true);
00798 
00799     // Operations
00800     //
00801     // nothing to do here.. "updateOperations" in parent class puts things
00802     // in the right place using the "addCodeOperation" method we defined in this class
00803 
00804     // FINISH up with hash def block close
00805     QString defTextEnd = "#endif //"+hashDefine + "_H";
00806     addOrUpdateTaggedCodeBlockWithComments("hashDefBlockEnd", defTextEnd, "", 0, false);
00807 
00808 }
00809 
00810 
00811 #include "cppheadercodedocument.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:56 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003