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.
503 lines
14 KiB
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"
|