umbrello API Documentation

codegenobjectwithtextblocks.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   : Tue Aug 19 2003
00015  */
00016 
00017 // own header
00018 #include "codegenobjectwithtextblocks.h"
00019 
00020 // qt/kde includes
00021 #include <kdebug.h>
00022 
00023 // local includes
00024 #include "umldoc.h"
00025 #include "codedocument.h"
00026 #include "codeoperation.h"
00027 #include "codegenerators/codegenfactory.h"
00028 #include "classifiercodedocument.h"
00029 #include "hierarchicalcodeblock.h"
00030 #include "uml.h"
00031 
00032 // Constructors/Destructors
00033 //
00034 
00035 CodeGenObjectWithTextBlocks::CodeGenObjectWithTextBlocks ( CodeDocument *parent )
00036   : m_pCodeDoc(parent)
00037 {
00038     initFields();
00039 }
00040 
00041 CodeGenObjectWithTextBlocks::~CodeGenObjectWithTextBlocks ( ) {
00042     resetTextBlocks();
00043     // delete all the text blocks we have
00044     TextBlock *tb;
00045     for (TextBlockListIt it(m_textblockVector); (tb = it.current()) != NULL; ++it)
00046       delete tb;
00047 
00048     m_textBlockTagMap.clear();
00049     m_textblockVector.clear();
00050 }
00051 
00052 //
00053 // Methods
00054 //
00055 
00056 
00057 // Accessor methods
00058 //
00059 
00065 TextBlockList * CodeGenObjectWithTextBlocks::getTextBlockList ( ) {
00066     return &m_textblockVector;
00067 }
00068 
00069 // Other methods
00070 //
00071 
00075 bool CodeGenObjectWithTextBlocks::addTextBlock(TextBlock* add_object ) {
00076 
00077     QString tag = add_object->getTag();
00078 
00079     // assign a tag if one doesn't already exist
00080     if(tag.isEmpty())
00081     {
00082         tag = getUniqueTag();
00083         add_object->setTag(tag);
00084     }
00085     else
00086     {
00087 
00088         // if it has a tag, check to see that its not in some other parent object
00089         // IF it is then we will need to remove it FIRST before adding to new parent
00090         CodeDocument * parentDoc = add_object->getParentDocument();
00091         if(parentDoc) {
00092 
00093             CodeGenObjectWithTextBlocks * oldParent = parentDoc->findParentObjectForTaggedTextBlock (tag);
00094             if(oldParent && oldParent != this)
00095                 oldParent->removeTextBlock(add_object);
00096         }
00097     }
00098 
00099     if(m_textBlockTagMap.contains(tag))
00100         return false; // return false, we already have some object with this tag in the list
00101 
00102     // if we get here, then the object is a "fresh" one, we havent
00103     // added before. Add it now and return true.
00104     m_textBlockTagMap.insert(tag, add_object);
00105     m_textblockVector.append(add_object);
00106 
00107     return true;
00108 }
00109 
00113 bool CodeGenObjectWithTextBlocks::removeTextBlock ( TextBlock * remove_object ) {
00114 
00115     // check if we can remove it from our local list
00116     if(!m_textblockVector.removeRef(remove_object))
00117     {
00118         // may be hiding in child hierarchical codeblock
00119         TextBlock * tb;
00120         for(TextBlockListIt it(m_textblockVector); (tb = it.current()) != NULL; ++it)
00121         {
00122             HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(tb);
00123             if(hb && hb->removeTextBlock(remove_object))
00124                 return true;
00125         }
00126     }
00127 
00128     // if we get here.. it was in this object so remove from our map
00129     QString tag = remove_object->getTag();
00130     if(!tag.isEmpty())
00131         m_textBlockTagMap.erase(tag);
00132 
00133     return true;
00134 }
00135 
00136 TextBlock * CodeGenObjectWithTextBlocks::findTextBlockByTag( const QString &tag )
00137 {
00138     //if we already know to which file this class was written/should be written, just return it.
00139     if(m_textBlockTagMap.contains(tag))
00140         return m_textBlockTagMap[tag];
00141 
00142     return (TextBlock*) NULL;
00143 }
00144 
00145 // IMPORTANT: this will only search for a parent from the viewpoint of this object
00146 // and down into its Hierarchical codeblocks. This means you should start any
00147 // search from the parent document of the text block. This method NOT meant for
00148 // casual usage.
00149 CodeGenObjectWithTextBlocks * CodeGenObjectWithTextBlocks::findParentObjectForTaggedTextBlock (const QString & tag) {
00150 
00151     // what??!? no tag, then CANT be here
00152     if(tag.isEmpty())
00153         return (CodeGenObjectWithTextBlocks*) NULL;
00154 
00155     if(!findTextBlockByTag(tag))
00156     {
00157         // may be hiding in child hierarchical codeblock
00158         for(TextBlock * tb = m_textblockVector.first(); tb ; tb = m_textblockVector.next())
00159         {
00160             HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(tb);
00161             if(hb) {
00162                 CodeGenObjectWithTextBlocks* cgowtb = dynamic_cast<CodeGenObjectWithTextBlocks*>(hb);
00163                 CodeGenObjectWithTextBlocks * obj = cgowtb->findParentObjectForTaggedTextBlock(tag);
00164                 if(obj)
00165                     return obj;
00166             }
00167         }
00168 
00169     } else
00170         return this;
00171 
00172     // shouldn't happen unless the textblock doesn't exist in this object
00173     // or its children at all
00174     return (CodeGenObjectWithTextBlocks*) NULL;
00175 
00176 }
00177 
00184 HierarchicalCodeBlock * CodeGenObjectWithTextBlocks::getHierarchicalCodeBlock ( const QString &tag, const QString &comment, int indentLevel ) {
00185 
00186     // now actually declare the fields
00187     HierarchicalCodeBlock * codeBlock = dynamic_cast<HierarchicalCodeBlock*>(findTextBlockByTag(tag));
00188     if (!codeBlock) {
00189         codeBlock = newHierarchicalCodeBlock();
00190         codeBlock->setTag(tag);
00191         codeBlock->setComment(CodeGenFactory::newCodeComment(m_pCodeDoc));
00192         // don't write empty comments out
00193         if(comment.isEmpty())
00194             codeBlock->getComment()->setWriteOutText(false);
00195 
00196         if(!addTextBlock(codeBlock))
00197         {
00198             delete codeBlock;
00199             return (HierarchicalCodeBlock*) NULL;
00200         }
00201     }
00202 
00203     codeBlock->setOverallIndentationLevel (indentLevel);
00204     codeBlock->getComment()->setText(comment);
00205 
00206     return codeBlock;
00207 }
00208 
00209 
00216 CodeBlockWithComments * CodeGenObjectWithTextBlocks::getCodeBlockWithComments ( const QString &tag, const QString &comment, int indentLevel ) {
00217 
00218     // now actually declare the fields
00219     CodeBlockWithComments * codeBlock = dynamic_cast<CodeBlockWithComments*>(findTextBlockByTag(tag));
00220     if (!codeBlock) {
00221         codeBlock = newCodeBlockWithComments();
00222         codeBlock->setTag(tag);
00223         codeBlock->setComment(CodeGenFactory::newCodeComment(m_pCodeDoc));
00224         // don't write empty comments out
00225         if(comment.isEmpty())
00226             codeBlock->getComment()->setWriteOutText(false);
00227         if(!addTextBlock(codeBlock))
00228             return (CodeBlockWithComments*) NULL;
00229     }
00230     codeBlock->setOverallIndentationLevel (indentLevel);
00231     codeBlock->getComment()->setText(comment);
00232 
00233     return codeBlock;
00234 
00235 }
00236 
00237 
00244 CodeComment * CodeGenObjectWithTextBlocks::addOrUpdateTaggedCodeComment ( const QString &tag, const QString &text, int indentationLevel)
00245 {
00246 
00247     TextBlock * tBlock = findTextBlockByTag(tag);
00248     CodeComment * codeComment = dynamic_cast<CodeComment*>(tBlock);
00249     bool createdCodeComment = false;
00250 
00251     if(!codeComment) {
00252         createdCodeComment = true;
00253         codeComment = CodeGenFactory::newCodeComment(m_pCodeDoc);
00254         codeComment->setTag(tag);
00255         if(!addTextBlock(codeComment))
00256         {
00257             delete codeComment;
00258             return (CodeComment*) NULL; // hmm. total failure..,was there a preexisting comment with this tag?? lets return null
00259         }
00260     }
00261 
00262     codeComment->setText(text);
00263     if(createdCodeComment)
00264         if(!text.isEmpty())
00265             codeComment->setWriteOutText(true); // set to visible, if we created
00266         else
00267             codeComment->setWriteOutText(false); // set to not visible, if we created
00268 
00269     codeComment->setIndentationLevel(indentationLevel);
00270 
00271     return codeComment;
00272 }
00273 
00274 
00283 CodeBlockWithComments * CodeGenObjectWithTextBlocks::addOrUpdateTaggedCodeBlockWithComments (const QString &tag, const QString &text, const QString &ctext, int indentLevel, bool forceUserBlockUpdate )
00284 {
00285 
00286     TextBlock * tBlock = findTextBlockByTag(tag);
00287     CodeBlockWithComments * codeBlock = dynamic_cast<CodeBlockWithComments*>(tBlock);
00288     bool createdCodeBlock = false;
00289 
00290     if(!codeBlock) {
00291         createdCodeBlock = true;
00292         codeBlock = newCodeBlockWithComments();
00293         codeBlock->setTag(tag);
00294         if(!addTextBlock(codeBlock))
00295         {
00296             delete codeBlock;
00297             return (CodeBlockWithComments*) NULL; // hmm. total failure..,was there a preexisting codeblock with this tag?? lets return null
00298         }
00299     }
00300 
00301     // ONLY update IF we are forcing the update of user blocks OR its an "AutoGenerated" Block
00302     if(forceUserBlockUpdate || codeBlock->getContentType() == CodeBlock::AutoGenerated)
00303     {
00304 
00305         codeBlock->setText(text);
00306         codeBlock->getComment()->setText(ctext);
00307 
00308         // if we created this from scratch, make it write out only when the block isnt empty
00309         if (createdCodeBlock)
00310         {
00311             if(!ctext.isEmpty())
00312                 codeBlock->getComment()->setWriteOutText(true);
00313             else
00314                 codeBlock->getComment()->setWriteOutText(false);
00315 
00316             if(!text.isEmpty())
00317                 codeBlock->setWriteOutText(true);
00318             else
00319                 codeBlock->setWriteOutText(false);
00320         }
00321 
00322         codeBlock->setOverallIndentationLevel(indentLevel);
00323 
00324     }
00325 
00326     return codeBlock;
00327 
00328 }
00329 
00330 void CodeGenObjectWithTextBlocks::resetTextBlocks() {
00331     TextBlock *tb;
00332     for (TextBlockListIt it(m_textblockVector); (tb = it.current()) != NULL; ++it)
00333         delete tb;
00334     m_textBlockTagMap.clear();
00335     m_textblockVector.clear();
00336 }
00337 
00338 
00339 void CodeGenObjectWithTextBlocks::setAttributesFromObject (CodeGenObjectWithTextBlocks * obj)
00340 {
00341     TextBlockList * list = obj->getTextBlockList();
00342     for (TextBlock * tb = list->first(); tb; tb=list->next())
00343     {
00344         // FIX : we need some functionality like
00345         // loadChildTextBlocksFromObject(obj) here
00346     }
00347 }
00348 
00349 void CodeGenObjectWithTextBlocks::setAttributesOnNode (QDomDocument & doc, QDomElement & root) {
00350 
00351     // set a section to hold document content
00352     QDomElement tblockElement = doc.createElement( "textblocks" );
00353 
00354     // only concrete calls to textblocks are saved
00355     TextBlockList * tbList = getTextBlockList();
00356     for (TextBlock * block = tbList->first(); block; block= tbList->next())
00357         block->saveToXMI(doc, tblockElement);
00358 
00359     root.appendChild( tblockElement);
00360 
00361 }
00362 
00366 void CodeGenObjectWithTextBlocks::setAttributesFromNode ( QDomElement & root)
00367 {
00368 
00369     // clear existing codeblocks
00370     resetTextBlocks();
00371 
00372     // now load em back in
00373     loadChildTextBlocksFromNode(root);
00374 
00375 }
00376 
00377 // load text blocks
00378 // in this vanilla version, we only load comments and codeblocks
00379 // as they are the only instanciatable (vanilla) things
00380 // this method should be overridden if this class is inherited
00381 // by some other class that is concrete and takes children
00382 // derived from codeblock/codecomment
00383 void CodeGenObjectWithTextBlocks::loadChildTextBlocksFromNode ( QDomElement & root)
00384 {
00385 
00386     QDomNode tnode = root.firstChild();
00387     QDomElement telement = tnode.toElement();
00388     bool loadCheckForChildrenOK = false;
00389     while( !telement.isNull() ) {
00390         QString nodeName = telement.tagName();
00391 
00392         if( nodeName == "textblocks" ) {
00393 
00394             QDomNode node = telement.firstChild();
00395             QDomElement element = node.toElement();
00396 
00397             // if there is nothing to begin with, then we don't worry about it
00398             loadCheckForChildrenOK = element.isNull() ? true : false;
00399 
00400             while( !element.isNull() ) {
00401                 QString name = element.tagName();
00402 
00403                 if( name == "codecomment" ) {
00404                     CodeComment * block = CodeGenFactory::newCodeComment(m_pCodeDoc);
00405                     block->loadFromXMI(element);
00406                     if(!addTextBlock(block))
00407                     {
00408                         kError()<<"loadFromXMI: unable to add codeComment to :"<<this<<endl;
00409                         delete block;
00410                     } else
00411                         loadCheckForChildrenOK= true;
00412                 } else
00413                     if( name == "codeaccessormethod" ||
00414                             name == "ccfdeclarationcodeblock"
00415                       ) {
00416                         QString acctag = element.attribute("tag","");
00417                         // search for our method in the
00418                         TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag);
00419                         if(!tb || !addTextBlock(tb))
00420                         {
00421                             kError()<<"loadFromXMI : unable to add code accessor/decl method block (tag:"<<acctag<<") to:"<<this<<endl;
00422                             // DON'T delete
00423 
00424                         } else
00425                             loadCheckForChildrenOK= true;
00426 
00427                     } else
00428                         if( name == "codeblock" ) {
00429                             CodeBlock * block = newCodeBlock();
00430                             block->loadFromXMI(element);
00431                             if(!addTextBlock(block))
00432                             {
00433                                 kError()<<"loadFromXMI : unable to add codeBlock to :"<<this<<endl;
00434                                 delete block;
00435                             } else
00436                                 loadCheckForChildrenOK= true;
00437                         } else
00438                             if( name == "codeblockwithcomments" ) {
00439                                 CodeBlockWithComments * block = newCodeBlockWithComments();
00440                                 block->loadFromXMI(element);
00441                                 if(!addTextBlock(block))
00442                                 {
00443                                     kError()<<"loadFromXMI : unable to add codeBlockwithcomments to:"<<this<<endl;
00444                                     delete block;
00445                                 } else
00446                                     loadCheckForChildrenOK= true;
00447                             } else
00448                                 if( name == "header" ) {
00449                                     // do nothing.. this is treated elsewhere
00450                                 } else
00451                                     if( name == "hierarchicalcodeblock" ) {
00452                                         HierarchicalCodeBlock * block = new HierarchicalCodeBlock(m_pCodeDoc);
00453                                         block->loadFromXMI(element);
00454                                         if(!addTextBlock(block))
00455                                         {
00456                                             kError()<<"loadFromXMI : unable to add hierarchicalcodeBlock to:"<<this<<endl;
00457                                             delete block;
00458                                         } else
00459                                             loadCheckForChildrenOK= true;
00460                                     } else
00461                                         if( name == "codeoperation" ) {
00462                                             // find the code operation by id
00463                                             QString id = element.attribute("parent_id","-1");
00464                                             UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(STR2ID(id));
00465                                             UMLOperation * op = dynamic_cast<UMLOperation*>(obj);
00466                                             if(op) {
00467                                                 CodeOperation * block = CodeGenFactory::newCodeOperation(dynamic_cast<ClassifierCodeDocument*>(m_pCodeDoc), op);
00468                                                 block->loadFromXMI(element);
00469                                                 if(addTextBlock(block))
00470                                                     loadCheckForChildrenOK= true;
00471                                                 else
00472                                                 {
00473                                                     kError()<<"loadFromXMI : unable to add codeoperation to:"<<this<<endl;
00474                                                     delete block;
00475                                                 }
00476                                             } else
00477                                                 kError()<<"loadFromXMI : unable to create codeoperation for obj id:"<<id<<endl;
00478                                         }
00479                 /*
00480                                                 // only needed for extreme debugging conditions (E.g. making new codeclassdocument loader)
00481                                                 else
00482                                                         kWarning()<<" LoadFromXMI: Got strange tag in text block stack:"<<name.latin1()<<", ignorning"<<endl;
00483                 */
00484 
00485                 node = element.nextSibling();
00486                 element = node.toElement();
00487             }
00488             break;
00489         }
00490 
00491         tnode = telement.nextSibling();
00492         telement = tnode.toElement();
00493     }
00494 
00495     if(!loadCheckForChildrenOK)
00496     {
00497         CodeDocument * test = dynamic_cast<CodeDocument*>(this);
00498         if(test)
00499         {
00500             kWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<<test->getFileName()<<" "<<this<<endl;
00501         } else {
00502             HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(this);
00503             if(hb)
00504                 kWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<<hb->getTag()<<" "<<this<<endl;
00505             else
00506                 kDebug()<<" loadChildBlocks : unable to initialize any child blocks in UNKNOWN OBJ:"<<this<<endl;
00507         }
00508     }
00509 
00510 }
00511 
00512 void CodeGenObjectWithTextBlocks::initFields ( ) {
00513 
00514     m_textblockVector.setAutoDelete(false);
00515 
00516 }
00517 
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:55 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003