diff options
Diffstat (limited to 'umbrello/umbrello/codedocument.cpp')
-rw-r--r-- | umbrello/umbrello/codedocument.cpp | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/umbrello/umbrello/codedocument.cpp b/umbrello/umbrello/codedocument.cpp new file mode 100644 index 00000000..e0bf0e73 --- /dev/null +++ b/umbrello/umbrello/codedocument.cpp @@ -0,0 +1,502 @@ +/*************************************************************************** + * * + * 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 <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Wed Jun 18 2003 + */ + +// own header +#include "codedocument.h" + +// qt/kde includes +#include <qregexp.h> +#include <qdatetime.h> +#include <kdebug.h> + +// local includes +#include "codegenerator.h" +#include "package.h" +#include "umldoc.h" +#include "uml.h" + +// Constructors/Destructors +// + +CodeDocument::CodeDocument () : CodeGenObjectWithTextBlocks(this) +{ + initDoc(); +} + + +CodeDocument::~CodeDocument ( ) { + // delete all the text blocks we have + TextBlock *tb; + for (TextBlockListIt it(m_textblockVector); (tb = it.current()) != NULL; ++it) + delete tb; + m_textblockVector.clear(); + delete m_header; +} + +// +// Methods +// + + +// Accessor methods +// + + +// Public attribute accessor methods +// + + +/** + * Set the value of m_filename + * @param new_var the new value of m_filename + */ +void CodeDocument::setFileName ( const QString &new_var ) { + m_filename = new_var; +} + +/** + * Get the value of m_filename + * @return the value of m_filename + */ +QString CodeDocument::getFileName ( ) const { + return m_filename; +} + +/** + * Set the value of m_filename + * @param new_var the new value of m_filename + */ +void CodeDocument::setFileExtension ( const QString &new_var ) { + m_fileExtension = new_var; + updateHeader(); // because we are using new heading file +} + +/** + * Get the value of m_filename + * @return the value of m_filename + */ +QString CodeDocument::getFileExtension( ) const { + return m_fileExtension; +} + +/** + * Set the value of the package. + * @param new_var the new value of m_package + */ +void CodeDocument::setPackage ( UMLPackage *new_var ) { + m_package = new_var; +} + +/** + * Get the value of path for this code document. + * @return the value of the path + */ +QString CodeDocument::getPath ( ) { + + QString path = getPackage(); + + // Replace all white spaces with blanks + path = path.simplifyWhiteSpace(); + + // Replace all blanks with underscore + path.replace(QRegExp(" "), "_"); + + // this allows multiple directory paths (ala Java, some other languages) + // in from the package specification + path.replace(QRegExp("\\."),"/"); // Simple hack!.. but this is more or less language + // dependant and should probably be commented out. + // Still, as a general default it may be useful -b.t. + return path; +} + +/** + * Get the value of package name. + * @return the value of m_package->getName() + */ +QString CodeDocument::getPackage ( ) const { + if (m_package) + return m_package->getName(); + return QString(); +} + +/** + * Set the value of m_ID + * @param new_var the new value of m_ID + */ +void CodeDocument::setID ( const QString &new_var ) { + m_ID = new_var; +} + +/** + * Get the value of m_ID + * @return the value of m_ID + */ +QString CodeDocument::getID ( ) const { + return m_ID; +} + +/** + * Set the value of m_writeOutCode + * Whether or not to write out this code document and any codeblocks, etc that it + * owns. + * @param new_var the new value of m_writeOutCode + */ +void CodeDocument::setWriteOutCode ( bool new_var ) { + m_writeOutCode = new_var; +} + +/** + * Get the value of m_writeOutCode + * Whether or not to write out this code document and any codeblocks, etc that it + * owns. + * @return the value of m_writeOutCode + */ +bool CodeDocument::getWriteOutCode ( ) { + return m_writeOutCode; +} + +/** + * Set the Header comment + */ +void CodeDocument::setHeader ( CodeComment * header ) { + m_header = header; +} + +/** + * Get the Header comment + */ +CodeComment * CodeDocument::getHeader ( ) { + return m_header; +} + +// +// Other methods +// + +QString CodeDocument::getUniqueTag ( const QString& prefix ) +{ + QString tag = prefix ; + if(tag.isEmpty()) + tag += "tblock"; + + tag = tag + "_0"; + int number = lastTagIndex; + for ( ; findTextBlockByTag(tag, true); number++) { + tag = prefix + '_' + QString::number(number); + } + lastTagIndex = number; + return tag; +} + +/** + * Insert a new text block before/after the existing text block. Returns + * false if it cannot insert the textblock. + */ +bool CodeDocument::insertTextBlock(TextBlock * newBlock, TextBlock * existingBlock, bool after) +{ + + if(!newBlock || !existingBlock) + return false; + + QString tag = existingBlock->getTag(); + if(!findTextBlockByTag(tag, true)) + return false; + + int index = m_textblockVector.findRef(existingBlock); + if(index < 0) + { + // may be hiding in child hierarchical codeblock + for(TextBlock * tb = m_textblockVector.first(); tb ; tb = m_textblockVector.next()) + { + HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(tb); + if(hb && hb->insertTextBlock(newBlock, existingBlock, after)) + return true; // found, and inserted, otherwise keep going + } + // ugh. where is the child block? + kWarning()<<" Warning: couldnt insert text block (tag:"<<newBlock->getTag()<<"). Reference text block (tag:"<<existingBlock->getTag()<<") not found."<<endl; + return false; + } + + // if we get here.. it was in this object so insert + + // check for tag FIRST + QString new_tag = newBlock->getTag(); + + // assign a tag if one doesn't already exist + if(new_tag.isEmpty()) + { + new_tag = getUniqueTag(); + newBlock->setTag(new_tag); + } + + if(m_textBlockTagMap.contains(new_tag)) + return false; // return false, we already have some object with this tag in the list + else + m_textBlockTagMap.insert(new_tag, newBlock); + + if(after) + index++; + + m_textblockVector.insert(index,newBlock); + + return true; +} + +/** + * Get the value of m_dialog + * @return the value of m_dialog + */ +/* +CodeDocumentDialog * CodeDocument::getDialog ( ) { + return m_dialog; +} +*/ + +// Other methods +// + +QString CodeDocument::cleanName ( const QString &name ) { + return CodeGenerator::cleanName(name); +} + +// update the text and status of the head comment +void CodeDocument::updateHeader () { + + //try to find a heading file (license, coments, etc) then extract its text + QString headingText = UMLApp::app()->getCommonPolicy()->getHeadingFile(getFileExtension()); + + headingText.replace(QRegExp("%filename%"),getFileName()+getFileExtension()); + headingText.replace(QRegExp("%filepath%"),getPath()); + headingText.replace( QRegExp("%time%"), QTime::currentTime().toString()); + headingText.replace( QRegExp("%date%"), QDate::currentDate().toString()); + + getHeader()->setText(headingText); + + // update the write out status of the header + if(UMLApp::app()->getCommonPolicy()->getIncludeHeadings()) + getHeader()->setWriteOutText(true); + else + getHeader()->setWriteOutText(false); + +} + +/** + * create the string representation of this object. + * @return QString + */ +QString CodeDocument::toString ( ) { + + // IF the whole document is turned "Off" then don't bother + // checking individual code blocks, just send back empty string + if(!getWriteOutCode()) + return QString(""); + + QString content = getHeader()->toString(); + + // update the time/date + + // comments, import, package codeblocks go next + TextBlockList * items = getTextBlockList(); + for (TextBlock *c = items->first(); c; c = items->next()) + { + if(c->getWriteOutText()) { + QString str = c->toString(); + if(!str.isEmpty()) + content.append(str); + } + } + return content; +} + +void CodeDocument::synchronize() { + updateContent(); +} + +// need to overload method to beable to clear the childTextBlockMap +void CodeDocument::resetTextBlocks() { + CodeGenObjectWithTextBlocks::resetTextBlocks(); + m_childTextBlockTagMap.clear(); +} + +/** + * load params from the appropriate XMI element node. + */ +void CodeDocument::loadFromXMI ( QDomElement & root ) { + setAttributesFromNode(root); +} + +/** set attributes of the node that represents this class + * in the XMI document. + */ +void CodeDocument::setAttributesOnNode ( QDomDocument & doc, QDomElement & docElement) +{ + + // superclass call + CodeGenObjectWithTextBlocks::setAttributesOnNode(doc,docElement); + + // now set local attributes/fields + docElement.setAttribute("fileName",getFileName()); + docElement.setAttribute("fileExt",getFileExtension()); + Uml::IDType pkgId = Uml::id_None; + if (m_package) + pkgId = m_package->getID(); + docElement.setAttribute("package", ID2STR(pkgId)); + docElement.setAttribute("writeOutCode",getWriteOutCode()?"true":"false"); + docElement.setAttribute("id",getID()); + + // set the a header + // which we will store in its own separate child node block + QDomElement commElement = doc.createElement( "header" ); + getHeader()->saveToXMI(doc, commElement); // comment + docElement.appendChild( commElement); + + // doc codePolicy? + // FIX: store ONLY if different from the parent generator + // policy.. something which is not possible right now. -b.t. + +} + +/** set the class attributes of this object from + * the passed element node. + */ +void CodeDocument::setAttributesFromNode ( QDomElement & root) { + + // now set local attributes + setFileName(root.attribute("fileName","")); + setFileExtension(root.attribute("fileExt","")); + QString pkgStr = root.attribute("package",""); + if (!pkgStr.isEmpty() && pkgStr != "-1") { + UMLDoc *umldoc = UMLApp::app()->getDocument(); + if (pkgStr.contains( QRegExp("\\D") )) { + // suspecting pre-1.5.3 file format where the package name was + // saved instead of the package ID. + UMLObject *o = umldoc->findUMLObject(pkgStr); + m_package = dynamic_cast<UMLPackage*>(o); + } + if (m_package == NULL) { + UMLObject *o = umldoc->findObjectById(STR2ID(pkgStr)); + m_package = dynamic_cast<UMLPackage*>(o); + } + } + setWriteOutCode(root.attribute("writeOutCode","true") == "true" ? true : false); + setID(root.attribute("id","")); + + // load comment now + // by looking for our particular child element + QDomNode node = root.firstChild(); + QDomElement element = node.toElement(); + while( !element.isNull() ) { + QString tag = element.tagName(); + if( tag == "header" ) { + QDomNode cnode = element.firstChild(); + QDomElement celem = cnode.toElement(); + getHeader()->loadFromXMI(celem); + break; + } + node = element.nextSibling(); + element = node.toElement(); + } + + // a rare case where the super-class load is AFTER local attributes + CodeGenObjectWithTextBlocks::setAttributesFromNode(root); +} + +/** + * Save the XMI representation of this object + */ +void CodeDocument::saveToXMI ( QDomDocument & doc, QDomElement & root ) { + QDomElement docElement = doc.createElement( "codedocument" ); + + setAttributesOnNode(doc, docElement); + + root.appendChild( docElement ); +} + +// vanilla code documents don't have much +// to do.. override this with a different +// version for your own documents +void CodeDocument::updateContent() { + updateHeader(); // doing this insures time/date stamp is at the time of this call +} + +/** + * create a new CodeBlock object belonging to this CodeDocument. + * @return CodeBlock + */ +CodeBlock * CodeDocument::newCodeBlock ( ) { + return new CodeBlock(this); +} + +/** + * create a new CodeBlockWithComments object belonging to this CodeDocument. + * @return CodeBlockWithComments + */ +CodeBlockWithComments * CodeDocument::newCodeBlockWithComments ( ) { + return new CodeBlockWithComments(this); +} + +HierarchicalCodeBlock * CodeDocument::newHierarchicalCodeBlock ( ) { + HierarchicalCodeBlock *hb = new HierarchicalCodeBlock(this); + //hb->update(); + return hb; +} + +void CodeDocument::removeChildTagFromMap ( const QString &tag ) +{ + m_childTextBlockTagMap.erase(tag); +} + +void CodeDocument::addChildTagToMap ( const QString &tag, TextBlock * tb) +{ + m_childTextBlockTagMap.insert(tag, tb); +} + +TextBlock * CodeDocument::findTextBlockByTag( const QString &tag , bool descendIntoChildren) +{ + //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]; + + if (descendIntoChildren) + if(m_childTextBlockTagMap.contains(tag)) + return m_childTextBlockTagMap[tag]; + + return (TextBlock*) NULL; +} + +void CodeDocument::initDoc () { + + m_writeOutCode = true; + m_package = NULL; + m_fileExtension = QString(""); + m_ID = QString(""); // leave with NO ID as a default + + //m_textblockVector.setAutoDelete(false); + + setHeader(new CodeComment(this)); + + lastTagIndex = 0; + + // m_dialog = new CodeDocumentDialog( ); + +} + +TextBlock * CodeDocument::findCodeClassFieldTextBlockByTag ( const QString &tag ) { + kWarning()<<"Called findCodeClassFieldMethodByTag("<<tag<<") for a regular CodeDocument"<<endl; + return (TextBlock *) NULL; +} + +#include "codedocument.moc" |