/***************************************************************************
* *
* 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"