You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdesdk/umbrello/umbrello/codedocument.cpp

503 lines
14 KiB

/***************************************************************************
* *
* 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 <tqregexp.h>
#include <tqdatetime.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 TQString &new_var ) {
m_filename = new_var;
}
/**
* Get the value of m_filename
* @return the value of m_filename
*/
TQString 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 TQString &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
*/
TQString 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
*/
TQString CodeDocument::getPath ( ) {
TQString path = getPackage();
// Replace all white spaces with blanks
path = path.simplifyWhiteSpace();
// Replace all blanks with underscore
path.replace(TQRegExp(" "), "_");
// this allows multiple directory paths (ala Java, some other languages)
// in from the package specification
path.replace(TQRegExp("\\."),"/"); // 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()
*/
TQString CodeDocument::getPackage ( ) const {
if (m_package)
return m_package->getName();
return TQString();
}
/**
* Set the value of m_ID
* @param new_var the new value of m_ID
*/
void CodeDocument::setID ( const TQString &new_var ) {
m_ID = new_var;
}
/**
* Get the value of m_ID
* @return the value of m_ID
*/
TQString 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
//
TQString CodeDocument::getUniqueTag ( const TQString& prefix )
{
TQString tag = prefix ;
if(tag.isEmpty())
tag += "tblock";
tag = tag + "_0";
int number = lastTagIndex;
for ( ; findTextBlockByTag(tag, true); number++) {
tag = prefix + '_' + TQString::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;
TQString 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
TQString 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
//
TQString CodeDocument::cleanName ( const TQString &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
TQString headingText = UMLApp::app()->getCommonPolicy()->getHeadingFile(getFileExtension());
headingText.replace(TQRegExp("%filename%"),getFileName()+getFileExtension());
headingText.replace(TQRegExp("%filepath%"),getPath());
headingText.replace( TQRegExp("%time%"), TQTime::currentTime().toString());
headingText.replace( TQRegExp("%date%"), TQDate::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 TQString
*/
TQString 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 TQString("");
TQString 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()) {
TQString 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 ( TQDomElement & root ) {
setAttributesFromNode(root);
}
/** set attributes of the node that represents this class
* in the XMI document.
*/
void CodeDocument::setAttributesOnNode ( TQDomDocument & doc, TQDomElement & 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
TQDomElement 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 ( TQDomElement & root) {
// now set local attributes
setFileName(root.attribute("fileName",""));
setFileExtension(root.attribute("fileExt",""));
TQString pkgStr = root.attribute("package","");
if (!pkgStr.isEmpty() && pkgStr != "-1") {
UMLDoc *umldoc = UMLApp::app()->getDocument();
if (pkgStr.contains( TQRegExp("\\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
TQDomNode node = root.firstChild();
TQDomElement element = node.toElement();
while( !element.isNull() ) {
TQString tag = element.tagName();
if( tag == "header" ) {
TQDomNode cnode = element.firstChild();
TQDomElement 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 ( TQDomDocument & doc, TQDomElement & root ) {
TQDomElement 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 TQString &tag )
{
m_childTextBlockTagMap.erase(tag);
}
void CodeDocument::addChildTagToMap ( const TQString &tag, TextBlock * tb)
{
m_childTextBlockTagMap.insert(tag, tb);
}
TextBlock * CodeDocument::findTextBlockByTag( const TQString &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 = TQString("");
m_ID = TQString(""); // 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 TQString &tag ) {
kWarning()<<"Called findCodeClassFieldMethodByTag("<<tag<<") for a regular CodeDocument"<<endl;
return (TextBlock *) NULL;
}
#include "codedocument.moc"