/*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * copyright (C) 2004-2007 * * Umbrello UML Modeller Authors * ***************************************************************************/ /* This code generated by: * Author : thomas * Date : Tue Aug 19 2003 */ // own header #include "codegenobjectwithtextblocks.h" // qt/kde includes #include // local includes #include "umldoc.h" #include "codedocument.h" #include "codeoperation.h" #include "codegenerators/codegenfactory.h" #include "classifiercodedocument.h" #include "hierarchicalcodeblock.h" #include "uml.h" // Constructors/Destructors // CodeGenObjectWithTextBlocks::CodeGenObjectWithTextBlocks ( CodeDocument *parent ) : m_pCodeDoc(parent) { initFields(); } CodeGenObjectWithTextBlocks::~CodeGenObjectWithTextBlocks ( ) { resetTextBlocks(); // delete all the text blocks we have TextBlock *tb; for (TextBlockListIt it(m_textblockVector); (tb = it.current()) != NULL; ++it) delete tb; m_textBlockTagMap.clear(); m_textblockVector.clear(); } // // Methods // // Accessor methods // /** * Get the list of TextBlock objects held by m_textblockVector * @return TQPtrList list of TextBlock objects held by * m_textblockVector */ TextBlockList * CodeGenObjectWithTextBlocks::getTextBlockList ( ) { return &m_textblockVector; } // Other methods // /** * Add a TextBlock object to the m_textblockVector List */ bool CodeGenObjectWithTextBlocks::addTextBlock(TextBlock* add_object ) { TQString tag = add_object->getTag(); // assign a tag if one doesn't already exist if(tag.isEmpty()) { tag = getUniqueTag(); add_object->setTag(tag); } else { // if it has a tag, check to see that its not in some other parent object // IF it is then we will need to remove it FIRST before adding to new parent CodeDocument * parentDoc = add_object->getParentDocument(); if(parentDoc) { CodeGenObjectWithTextBlocks * oldParent = parentDoc->findParentObjectForTaggedTextBlock (tag); if(oldParent && oldParent != this) oldParent->removeTextBlock(add_object); } } if(m_textBlockTagMap.contains(tag)) return false; // return false, we already have some object with this tag in the list // if we get here, then the object is a "fresh" one, we havent // added before. Add it now and return true. m_textBlockTagMap.insert(tag, add_object); m_textblockVector.append(add_object); return true; } /** * Remove a TextBlock object from m_textblockVector List */ bool CodeGenObjectWithTextBlocks::removeTextBlock ( TextBlock * remove_object ) { // check if we can remove it from our local list if(!m_textblockVector.removeRef(remove_object)) { // may be hiding in child hierarchical codeblock TextBlock * tb; for(TextBlockListIt it(m_textblockVector); (tb = it.current()) != NULL; ++it) { HierarchicalCodeBlock * hb = dynamic_cast(tb); if(hb && hb->removeTextBlock(remove_object)) return true; } } // if we get here.. it was in this object so remove from our map TQString tag = remove_object->getTag(); if(!tag.isEmpty()) m_textBlockTagMap.erase(tag); return true; } TextBlock * CodeGenObjectWithTextBlocks::findTextBlockByTag( const TQString &tag ) { //if we already know to which file this class was written/should be written, just return it. if(m_textBlockTagMap.contains(tag)) return m_textBlockTagMap[tag]; return (TextBlock*) NULL; } // IMPORTANT: this will only search for a parent from the viewpoint of this object // and down into its Hierarchical codeblocks. This means you should start any // search from the parent document of the text block. This method NOT meant for // casual usage. CodeGenObjectWithTextBlocks * CodeGenObjectWithTextBlocks::findParentObjectForTaggedTextBlock (const TQString & tag) { // what??!? no tag, then CANT be here if(tag.isEmpty()) return (CodeGenObjectWithTextBlocks*) NULL; if(!findTextBlockByTag(tag)) { // may be hiding in child hierarchical codeblock for(TextBlock * tb = m_textblockVector.first(); tb ; tb = m_textblockVector.next()) { HierarchicalCodeBlock * hb = dynamic_cast(tb); if(hb) { CodeGenObjectWithTextBlocks* cgowtb = dynamic_cast(hb); CodeGenObjectWithTextBlocks * obj = cgowtb->findParentObjectForTaggedTextBlock(tag); if(obj) return obj; } } } else return this; // shouldn't happen unless the textblock doesn't exist in this object // or its children at all return (CodeGenObjectWithTextBlocks*) NULL; } /** * @return HierarchicalCodeBlock * @param tag * @param comment * @param indentLevel */ HierarchicalCodeBlock * CodeGenObjectWithTextBlocks::getHierarchicalCodeBlock ( const TQString &tag, const TQString &comment, int indentLevel ) { // now actually declare the fields HierarchicalCodeBlock * codeBlock = dynamic_cast(findTextBlockByTag(tag)); if (!codeBlock) { codeBlock = newHierarchicalCodeBlock(); codeBlock->setTag(tag); codeBlock->setComment(CodeGenFactory::newCodeComment(m_pCodeDoc)); // don't write empty comments out if(comment.isEmpty()) codeBlock->getComment()->setWriteOutText(false); if(!addTextBlock(codeBlock)) { delete codeBlock; return (HierarchicalCodeBlock*) NULL; } } codeBlock->setOverallIndentationLevel (indentLevel); codeBlock->getComment()->setText(comment); return codeBlock; } /** * @return CodeBlockWithComments * @param tag * @param comment * @param indentLevel */ CodeBlockWithComments * CodeGenObjectWithTextBlocks::getCodeBlockWithComments ( const TQString &tag, const TQString &comment, int indentLevel ) { // now actually declare the fields CodeBlockWithComments * codeBlock = dynamic_cast(findTextBlockByTag(tag)); if (!codeBlock) { codeBlock = newCodeBlockWithComments(); codeBlock->setTag(tag); codeBlock->setComment(CodeGenFactory::newCodeComment(m_pCodeDoc)); // don't write empty comments out if(comment.isEmpty()) codeBlock->getComment()->setWriteOutText(false); if(!addTextBlock(codeBlock)) return (CodeBlockWithComments*) NULL; } codeBlock->setOverallIndentationLevel (indentLevel); codeBlock->getComment()->setText(comment); return codeBlock; } /** * @return CodeComment * @param tag * @param text * @param indentationLevel */ CodeComment * CodeGenObjectWithTextBlocks::addOrUpdateTaggedCodeComment ( const TQString &tag, const TQString &text, int indentationLevel) { TextBlock * tBlock = findTextBlockByTag(tag); CodeComment * codeComment = dynamic_cast(tBlock); bool createdCodeComment = false; if(!codeComment) { createdCodeComment = true; codeComment = CodeGenFactory::newCodeComment(m_pCodeDoc); codeComment->setTag(tag); if(!addTextBlock(codeComment)) { delete codeComment; return (CodeComment*) NULL; // hmm. total failure..,was there a preexisting comment with this tag?? lets return null } } codeComment->setText(text); if(createdCodeComment) if(!text.isEmpty()) codeComment->setWriteOutText(true); // set to visible, if we created else codeComment->setWriteOutText(false); // set to not visible, if we created codeComment->setIndentationLevel(indentationLevel); return codeComment; } /** * @return CodeBlockWithComments * @param tag * @param text * @param comment * @param indentLevel * @param forceUserBlockUpdate */ CodeBlockWithComments * CodeGenObjectWithTextBlocks::addOrUpdateTaggedCodeBlockWithComments (const TQString &tag, const TQString &text, const TQString &ctext, int indentLevel, bool forceUserBlockUpdate ) { TextBlock * tBlock = findTextBlockByTag(tag); CodeBlockWithComments * codeBlock = dynamic_cast(tBlock); bool createdCodeBlock = false; if(!codeBlock) { createdCodeBlock = true; codeBlock = newCodeBlockWithComments(); codeBlock->setTag(tag); if(!addTextBlock(codeBlock)) { delete codeBlock; return (CodeBlockWithComments*) NULL; // hmm. total failure..,was there a preexisting codeblock with this tag?? lets return null } } // ONLY update IF we are forcing the update of user blocks OR its an "AutoGenerated" Block if(forceUserBlockUpdate || codeBlock->getContentType() == CodeBlock::AutoGenerated) { codeBlock->setText(text); codeBlock->getComment()->setText(ctext); // if we created this from scratch, make it write out only when the block isnt empty if (createdCodeBlock) { if(!ctext.isEmpty()) codeBlock->getComment()->setWriteOutText(true); else codeBlock->getComment()->setWriteOutText(false); if(!text.isEmpty()) codeBlock->setWriteOutText(true); else codeBlock->setWriteOutText(false); } codeBlock->setOverallIndentationLevel(indentLevel); } return codeBlock; } void CodeGenObjectWithTextBlocks::resetTextBlocks() { TextBlock *tb; for (TextBlockListIt it(m_textblockVector); (tb = it.current()) != NULL; ++it) delete tb; m_textBlockTagMap.clear(); m_textblockVector.clear(); } void CodeGenObjectWithTextBlocks::setAttributesFromObject (CodeGenObjectWithTextBlocks * obj) { TextBlockList * list = obj->getTextBlockList(); for (TextBlock * tb = list->first(); tb; tb=list->next()) { // FIX : we need some functionality like // loadChildTextBlocksFromObject(obj) here } } void CodeGenObjectWithTextBlocks::setAttributesOnNode (TQDomDocument & doc, TQDomElement & root) { // set a section to hold document content TQDomElement tblockElement = doc.createElement( "textblocks" ); // only concrete calls to textblocks are saved TextBlockList * tbList = getTextBlockList(); for (TextBlock * block = tbList->first(); block; block= tbList->next()) block->saveToXMI(doc, tblockElement); root.appendChild( tblockElement); } /** set the class attributes of this object from * the passed element node. */ void CodeGenObjectWithTextBlocks::setAttributesFromNode ( TQDomElement & root) { // clear existing codeblocks resetTextBlocks(); // now load em back in loadChildTextBlocksFromNode(root); } // load text blocks // in this vanilla version, we only load comments and codeblocks // as they are the only instanciatable (vanilla) things // this method should be overridden if this class is inherited // by some other class that is concrete and takes children // derived from codeblock/codecomment void CodeGenObjectWithTextBlocks::loadChildTextBlocksFromNode ( TQDomElement & root) { TQDomNode tnode = root.firstChild(); TQDomElement telement = tnode.toElement(); bool loadCheckForChildrenOK = false; while( !telement.isNull() ) { TQString nodeName = telement.tagName(); if( nodeName == "textblocks" ) { TQDomNode node = telement.firstChild(); TQDomElement element = node.toElement(); // if there is nothing to begin with, then we don't worry about it loadCheckForChildrenOK = element.isNull() ? true : false; while( !element.isNull() ) { TQString name = element.tagName(); if( name == "codecomment" ) { CodeComment * block = CodeGenFactory::newCodeComment(m_pCodeDoc); block->loadFromXMI(element); if(!addTextBlock(block)) { kError()<<"loadFromXMI: unable to add codeComment to :"<loadFromXMI(element); if(!addTextBlock(block)) { kError()<<"loadFromXMI : unable to add codeBlock to :"<loadFromXMI(element); if(!addTextBlock(block)) { kError()<<"loadFromXMI : unable to add codeBlockwithcomments to:"<loadFromXMI(element); if(!addTextBlock(block)) { kError()<<"loadFromXMI : unable to add hierarchicalcodeBlock to:"<getDocument()->findObjectById(STR2ID(id)); UMLOperation * op = dynamic_cast(obj); if(op) { CodeOperation * block = CodeGenFactory::newCodeOperation(dynamic_cast(m_pCodeDoc), op); block->loadFromXMI(element); if(addTextBlock(block)) loadCheckForChildrenOK= true; else { kError()<<"loadFromXMI : unable to add codeoperation to:"<(this); if(test) { kWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<getFileName()<<" "<(this); if(hb) kWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<getTag()<<" "<