/***************************************************************************
javawriter . cpp - description
This is the " old " code generator that does not support code editing
in the Modeller but uses significantly less file space because the
source code is not replicated in the XMI file .
- - - - - - - - - - - - - - - - - - -
copyright : ( C ) 2003 Brian Thomas brian . thomas @ gsfc . nasa . gov
( C ) 2004 - 2006 Umbrello UML Modeller Authors < uml - devel @ uml . sf . net >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/***************************************************************************
* *
* 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 . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// own header
# include "javawriter.h"
// qt includes
# include <tqfile.h>
# include <tqtextstream.h>
# include <tqregexp.h>
// kde includes
# include <kdebug.h>
// app includes
# include "codegen_utils.h"
# include "../umldoc.h"
# include "../classifier.h"
# include "../operation.h"
# include "../attribute.h"
# include "../association.h"
# include "../template.h"
# include "../umltemplatelist.h"
JavaWriter : : JavaWriter ( ) {
startline = m_endl + m_indentation ;
}
JavaWriter : : ~ JavaWriter ( ) { }
Uml : : Programming_Language JavaWriter : : getLanguage ( ) {
return Uml : : pl_Java ;
}
void JavaWriter : : writeClass ( UMLClassifier * c )
{
if ( ! c ) {
kDebug ( ) < < " Cannot write class of NULL concept! \n " ;
return ;
}
isInterface = c - > isInterface ( ) ;
TQString fileName = cleanName ( c - > getName ( ) . lower ( ) ) ;
//find an appropriate name for our file
fileName = findFileName ( c , " .java " ) ;
if ( fileName . isEmpty ( ) ) {
emit codeGenerated ( c , false ) ;
return ;
}
// check that we may open that file for writing
TQFile file ;
if ( ! openFile ( file , fileName ) ) {
emit codeGenerated ( c , false ) ;
return ;
}
// Preparations
//
// sort attributes by Scope
UMLAttributeList atl ;
UMLAttributeList atpub , atprot , atpriv ;
UMLAttributeList final_atpub , final_atprot , final_atpriv ;
atpub . setAutoDelete ( false ) ;
final_atpub . setAutoDelete ( false ) ;
atprot . setAutoDelete ( false ) ;
final_atprot . setAutoDelete ( false ) ;
atpriv . setAutoDelete ( false ) ;
final_atpriv . setAutoDelete ( false ) ;
if ( ! isInterface ) {
UMLAttributeList atl = c - > getAttributeList ( ) ;
for ( UMLAttribute * at = atl . first ( ) ; at ; at = atl . next ( ) ) {
switch ( at - > getVisibility ( ) )
{
case Uml : : Visibility : : Public :
if ( at - > getStatic ( ) )
final_atpub . append ( at ) ;
else
atpub . append ( at ) ;
break ;
case Uml : : Visibility : : Protected :
if ( at - > getStatic ( ) )
final_atprot . append ( at ) ;
else
atprot . append ( at ) ;
break ;
case Uml : : Visibility : : Private :
if ( at - > getStatic ( ) )
final_atpriv . append ( at ) ;
else
atpriv . append ( at ) ;
break ;
default :
break ;
}
}
}
// another preparation, determine what we have
UMLAssociationList associations = c - > getSpecificAssocs ( Uml : : at_Association ) ; // BAD! only way to get "general" associations.
UMLAssociationList uniAssociations = c - > getUniAssociationToBeImplemented ( ) ;
UMLAssociationList aggregations = c - > getAggregations ( ) ;
UMLAssociationList compositions = c - > getCompositions ( ) ;
bool hasAssociations = aggregations . count ( ) > 0 | | associations . count ( ) > 0 | | compositions . count ( ) > 0 | | uniAssociations . count ( ) > 0 ;
bool hasAttributes = ( atl . count ( ) > 0 ) ;
bool hasAccessorMethods = hasAttributes | | hasAssociations ;
bool hasOperationMethods = ( c - > getOpList ( ) . count ( ) > 0 ) ;
// this is a bit too simplistic..some associations are for
// SINGLE objects, and WONT be declared as Vectors, so this
// is a bit overly inclusive
bool hasVectorFields = hasAssociations ? true : false ;
// open text stream to file
TQTextStream java ( & file ) ;
//try to find a heading file (license, coments, etc)
TQString str ;
str = getHeadingFile ( " .java " ) ;
if ( ! str . isEmpty ( ) ) {
str . replace ( TQRegExp ( " %filename% " ) , fileName ) ;
str . replace ( TQRegExp ( " %filepath% " ) , file . name ( ) ) ;
java < < str < < m_endl ;
}
if ( ! c - > getPackage ( ) . isEmpty ( ) )
java < < " package " < < c - > getPackage ( ) < < " ; " < < m_endl ;
// IMPORT statements
// Q: Why all utils? Isnt just List and Vector the only classes we are using?
// A: doesn't matter at all; its more readable to just include '*' and java compilers
// don't slow down or anything. (TZ)
if ( hasVectorFields )
{
writeBlankLine ( java ) ;
java < < " import java.util.*; " < < m_endl ;
}
//only import classes in a different package as this class
UMLPackageList imports ;
findObjectsRelated ( c , imports ) ;
for ( UMLPackage * con = imports . first ( ) ; con ; con = imports . next ( ) ) {
if ( con - > getBaseType ( ) = = Uml : : ot_Datatype )
continue ;
TQString pkg = con - > getPackage ( ) ;
if ( ! pkg . isEmpty ( ) & & pkg ! = c - > getPackage ( ) )
java < < " import " < < pkg < < " . " < < cleanName ( con - > getName ( ) ) < < " ; "
< < m_endl ;
}
writeBlankLine ( java ) ;
// write the opening declaration for the class incl any documentation,
// interfaces and/or inheritence issues we have
writeClassDecl ( c , java ) ;
// start body of class
java < < " { " < < m_endl ;
// ATTRIBUTES
//
// write comment for section IF needed
if ( forceDoc ( ) | | hasAccessorMethods )
{
writeComment ( " " , m_indentation , java ) ;
writeComment ( " Fields " , m_indentation , java ) ;
writeComment ( " " , m_indentation , java ) ;
writeBlankLine ( java ) ;
}
writeAttributeDecls ( final_atpub , final_atprot , final_atpriv , java ) ;
writeAttributeDecls ( atpub , atprot , atpriv , java ) ;
writeAssociationDecls ( associations , c - > getID ( ) , java ) ;
writeAssociationDecls ( uniAssociations , c - > getID ( ) , java ) ;
writeAssociationDecls ( aggregations , c - > getID ( ) , java ) ;
writeAssociationDecls ( compositions , c - > getID ( ) , java ) ;
// Constructors: anything we more we need to do here ?
//
if ( ! isInterface )
writeConstructor ( c , java ) ;
// METHODS
//
// write comment for section IF needed
if ( forceDoc ( ) | | hasAccessorMethods | | hasOperationMethods )
{
java < < startline ;
writeComment ( " " , m_indentation , java ) ;
writeComment ( " Methods " , m_indentation , java ) ;
writeComment ( " " , m_indentation , java ) ;
writeBlankLine ( java ) ;
writeBlankLine ( java ) ;
}
// write comment for sub-section IF needed
if ( forceDoc ( ) | | hasAccessorMethods )
{
writeComment ( " " , m_indentation , java ) ;
writeComment ( " Accessor methods " , m_indentation , java ) ;
writeComment ( " " , m_indentation , java ) ;
writeBlankLine ( java ) ;
}
// Accessors for attributes
writeAttributeMethods ( final_atpub , Uml : : Visibility : : Public , java ) ;
writeAttributeMethods ( final_atprot , Uml : : Visibility : : Protected , java ) ;
writeAttributeMethods ( final_atpriv , Uml : : Visibility : : Private , java ) ;
writeAttributeMethods ( atpub , Uml : : Visibility : : Public , java ) ;
writeAttributeMethods ( atprot , Uml : : Visibility : : Protected , java ) ;
writeAttributeMethods ( atpriv , Uml : : Visibility : : Private , java ) ;
// accessor methods for associations
// first: determine the name of the other class
writeAssociationMethods ( associations , c , java ) ;
writeAssociationMethods ( uniAssociations , c , java ) ;
writeAssociationMethods ( aggregations , c , java ) ;
writeAssociationMethods ( compositions , c , java ) ;
// Other operation methods
// all other operations are now written
// write comment for sub-section IF needed
if ( forceDoc ( ) | | hasOperationMethods )
{
writeComment ( " " , m_indentation , java ) ;
writeComment ( " Other methods " , m_indentation , java ) ;
writeComment ( " " , m_indentation , java ) ;
writeBlankLine ( java ) ;
}
writeOperations ( c , java ) ;
writeBlankLine ( java ) ;
java < < " } " < < m_endl ; // end class
file . close ( ) ;
emit codeGenerated ( c , true ) ;
}
void JavaWriter : : writeClassDecl ( UMLClassifier * c , TQTextStream & java )
{
TQString classname = cleanName ( c - > getName ( ) ) ; // our class name
// write documentation for class, if any, first
if ( forceDoc ( ) | | ! c - > getDoc ( ) . isEmpty ( ) )
{
if ( isInterface )
writeDocumentation ( " Interface " + classname , c - > getDoc ( ) , " " , " " , java ) ;
else
writeDocumentation ( " Class " + classname , c - > getDoc ( ) , " " , " " , java ) ;
writeBlankLine ( java ) ;
}
// Now write the actual class declaration
TQString scope = " " ; // = scopeToJavaDecl(c->getVisibility());
if ( c - > getVisibility ( ) ! = Uml : : Visibility : : Public ) {
// We should emit a warning in here .. java doesn't like to allow
// private/protected classes. The best we can do (I believe)
// is to let these declarations default to "package visibility"
// which is a level between traditional "private" and "protected"
// scopes. To get this visibility level we just print nothing..
} else
scope = " public " ;
java < < ( ( c - > getAbstract ( ) & & ! isInterface ) ? TQString ( " abstract " ) : TQString ( " " ) ) < < scope ;
if ( isInterface )
java < < " interface " ;
else
java < < " class " ;
java < < classname ;
// Generics
UMLTemplateList template_params = c - > getTemplateList ( ) ;
if ( template_params . count ( ) ) {
java < < " < " ;
for ( UMLTemplate * t = template_params . first ( ) ; t ; ) {
TQString formalName = t - > getName ( ) ;
java < < formalName ;
TQString typeName = t - > getTypeName ( ) ;
if ( typeName ! = " class " ) {
java < < " extends " < < typeName ;
}
if ( ( t = template_params . next ( ) ) ! = NULL )
java < < " , " ;
}
java < < " > " < < m_endl ;
}
// write inheritances out
UMLClassifier * concept ;
UMLClassifierList superclasses = c - > findSuperClassConcepts ( UMLClassifier : : CLASS ) ;
int i = 0 ;
for ( concept = superclasses . first ( ) ; concept ; concept = superclasses . next ( ) )
{
if ( i = = 0 )
{
java < < " extends " ;
}
else
{
//The java generated code is wrong ! : No multiple inheritence of class
java < < " , " ;
}
java < < cleanName ( concept - > getName ( ) ) ;
i + + ;
}
UMLClassifierList superInterfaces = c - > findSuperClassConcepts ( UMLClassifier : : INTERFACE ) ;
i = 0 ;
for ( concept = superInterfaces . first ( ) ; concept ; concept = superInterfaces . next ( ) )
{
if ( i = = 0 )
{
if ( isInterface )
java < < " extends " ;
else
java < < " implements " ;
}
else
{
//The java generated code is OK ! : multiple inheritence of interface
java < < " , " ;
}
java < < cleanName ( concept - > getName ( ) ) ;
i + + ;
}
}
void JavaWriter : : writeAttributeDecls ( UMLAttributeList & atpub , UMLAttributeList & atprot ,
UMLAttributeList & atpriv , TQTextStream & java )
{
UMLAttribute * at ;
for ( at = atpub . first ( ) ; at ; at = atpub . next ( ) )
{
TQString documentation = at - > getDoc ( ) ;
TQString staticValue = at - > getStatic ( ) ? " static " : " " ;
TQString typeName = fixTypeName ( at - > getTypeName ( ) ) ;
TQString initialValue = fixInitialStringDeclValue ( at - > getInitialValue ( ) , typeName ) ;
if ( ! documentation . isEmpty ( ) )
writeComment ( documentation , m_indentation , java , true ) ;
java < < startline < < staticValue < < " public " < < typeName < < " " < < cleanName ( at - > getName ( ) )
< < ( initialValue . isEmpty ( ) ? TQString ( " " ) : TQString ( " = " ) + initialValue ) < < " ; " ;
}
for ( at = atprot . first ( ) ; at ; at = atprot . next ( ) )
{
TQString documentation = at - > getDoc ( ) ;
TQString typeName = fixTypeName ( at - > getTypeName ( ) ) ;
TQString staticValue = at - > getStatic ( ) ? " static " : " " ;
TQString initialValue = fixInitialStringDeclValue ( at - > getInitialValue ( ) , typeName ) ;
if ( ! documentation . isEmpty ( ) )
writeComment ( documentation , m_indentation , java , true ) ;
java < < startline < < staticValue < < " protected " < < typeName < < " " < < cleanName ( at - > getName ( ) )
< < ( initialValue . isEmpty ( ) ? TQString ( " " ) : TQString ( " = " ) + initialValue ) < < " ; " ;
}
for ( at = atpriv . first ( ) ; at ; at = atpriv . next ( ) )
{
TQString documentation = at - > getDoc ( ) ;
TQString typeName = fixTypeName ( at - > getTypeName ( ) ) ;
TQString staticValue = at - > getStatic ( ) ? " static " : " " ;
TQString initialValue = fixInitialStringDeclValue ( at - > getInitialValue ( ) , typeName ) ;
if ( ! documentation . isEmpty ( ) )
writeComment ( documentation , m_indentation , java , true ) ;
java < < startline < < staticValue < < " private " < < typeName < < " " < < cleanName ( at - > getName ( ) )
< < ( initialValue . isEmpty ( ) ? TQString ( " " ) : TQString ( " = " ) + initialValue ) < < " ; " ;
}
}
void JavaWriter : : writeAttributeMethods ( UMLAttributeList & atpub , Uml : : Visibility visibility , TQTextStream & java )
{
UMLAttribute * at ;
for ( at = atpub . first ( ) ; at ; at = atpub . next ( ) )
{
TQString fieldName = cleanName ( at - > getName ( ) ) ;
// force capitalizing the field name, this is silly,
// from what I can tell, this IS the default behavior for
// cleanName. I dunno why its not working -b.t.
fieldName . stripWhiteSpace ( ) ;
fieldName . replace ( 0 , 1 , fieldName . at ( 0 ) . upper ( ) ) ;
writeSingleAttributeAccessorMethods ( at - > getTypeName ( ) ,
cleanName ( at - > getName ( ) ) ,
fieldName ,
at - > getDoc ( ) ,
visibility , Uml : : chg_Changeable , at - > getStatic ( ) , java ) ;
}
}
void JavaWriter : : writeComment ( const TQString & comment , const TQString & myIndent ,
TQTextStream & java , bool javaDocStyle )
{
// in the case we have several line comment..
// NOTE: this part of the method has the problem of adopting UNIX newline,
// need to resolve for using with MAC/WinDoze eventually I assume
if ( comment . contains ( TQRegExp ( " \n " ) ) ) {
if ( javaDocStyle )
java < < myIndent < < " /** " < < m_endl ;
TQStringList lines = TQStringList : : split ( " \n " , comment ) ;
for ( uint i = 0 ; i < lines . count ( ) ; i + + )
{
writeBlankLine ( java ) ;
if ( javaDocStyle )
java < < myIndent < < " * " ;
else
java < < myIndent < < " // " ;
java < < lines [ i ] ;
}
if ( javaDocStyle )
java < < myIndent < < " */ " < < m_endl ;
} else {
// this should be more fancy in the future, breaking it up into 80 char
// lines so that it doesn't look too bad
writeBlankLine ( java ) ;
if ( javaDocStyle )
java < < myIndent < < " /** " < < m_endl < < myIndent < < " * " ;
else
java < < myIndent < < " // " ;
if ( comment . length ( ) > 0 )
java < < " " < < comment ;
if ( javaDocStyle )
java < < m_endl < < myIndent < < " */ " ;
}
}
void JavaWriter : : writeDocumentation ( TQString header , TQString body , TQString end , TQString indent , TQTextStream & java )
{
writeBlankLine ( java ) ;
java < < indent < < " /** " < < m_endl ;
if ( ! header . isEmpty ( ) )
java < < formatDoc ( header , indent + " * " ) ;
if ( ! body . isEmpty ( ) )
java < < formatDoc ( body , indent + " * " ) ;
if ( ! end . isEmpty ( ) )
{
TQStringList lines = TQStringList : : split ( " \n " , end ) ;
for ( uint i = 0 ; i < lines . count ( ) ; i + + )
java < < formatDoc ( lines [ i ] , indent + " * " ) ;
}
java < < indent < < " */ " ;
}
void JavaWriter : : writeAssociationDecls ( UMLAssociationList associations , Uml : : IDType id , TQTextStream & java )
{
if ( forceSections ( ) | | ! associations . isEmpty ( ) )
{
bool printRoleA = false , printRoleB = false ;
for ( UMLAssociation * a = associations . first ( ) ; a ; a = associations . next ( ) )
{
// it may seem counter intuitive, but you want to insert the role of the
// *other* class into *this* class.
if ( a - > getObjectId ( Uml : : A ) = = id )
printRoleB = true ;
if ( a - > getObjectId ( Uml : : B ) = = id )
printRoleA = true ;
// First: we insert documentaion for association IF it has either role AND some documentation (!)
if ( ( printRoleA | | printRoleB ) & & ! ( a - > getDoc ( ) . isEmpty ( ) ) )
writeComment ( a - > getDoc ( ) , m_indentation , java ) ;
// print RoleB decl
if ( printRoleB )
{
TQString fieldClassName = cleanName ( getUMLObjectName ( a - > getObject ( Uml : : B ) ) ) ;
writeAssociationRoleDecl ( fieldClassName , a - > getRoleName ( Uml : : B ) , a - > getMulti ( Uml : : B ) , a - > getRoleDoc ( Uml : : B ) , a - > getVisibility ( Uml : : B ) , java ) ;
}
// print RoleA decl
if ( printRoleA )
{
TQString fieldClassName = cleanName ( getUMLObjectName ( a - > getObject ( Uml : : A ) ) ) ;
writeAssociationRoleDecl ( fieldClassName , a - > getRoleName ( Uml : : A ) , a - > getMulti ( Uml : : A ) , a - > getRoleDoc ( Uml : : A ) , a - > getVisibility ( Uml : : A ) , java ) ;
}
}
}
}
void JavaWriter : : writeAssociationRoleDecl ( TQString fieldClassName ,
TQString roleName , TQString multi ,
TQString doc , Uml : : Visibility visib , TQTextStream & java )
{
// ONLY write out IF there is a rolename given
// otherwise its not meant to be declared in the code
if ( roleName . isEmpty ( ) )
return ;
TQString scope = scopeToJavaDecl ( visib ) ;
// always put space between this and prior decl, if any
writeBlankLine ( java ) ;
if ( ! doc . isEmpty ( ) )
writeComment ( doc , m_indentation , java ) ;
// declare the association based on whether it is this a single variable
// or a List (Vector). One day this will be done correctly with special
// multiplicity object that we don't have to figure out what it means via regex.
if ( multi . isEmpty ( ) | | multi . contains ( TQRegExp ( " ^[01]$ " ) ) )
{
TQString fieldVarName = " m_ " + roleName . replace ( 0 , 1 , roleName . left ( 1 ) . lower ( ) ) ;
java < < startline < < scope < < " " < < fieldClassName < < " " < < fieldVarName < < " ; " ;
}
else
{
TQString fieldVarName = roleName . lower ( ) + " Vector " ;
java < < startline < < scope < < " Vector " < < fieldVarName < < " = new Vector(); " ;
// from here we could initialize default values, or put in an init() section
// of the constructors
}
}
void JavaWriter : : writeAssociationMethods ( UMLAssociationList associations , UMLClassifier * thisClass , TQTextStream & java )
{
if ( forceSections ( ) | | ! associations . isEmpty ( ) )
{
for ( UMLAssociation * a = associations . first ( ) ; a ; a = associations . next ( ) )
{
// insert the methods to access the role of the other
// class in the code of this one
if ( a - > getObjectId ( Uml : : A ) = = thisClass - > getID ( ) )
{
// only write out IF there is a rolename given
if ( ! a - > getRoleName ( Uml : : B ) . isEmpty ( ) ) {
TQString fieldClassName = getUMLObjectName ( a - > getObject ( Uml : : B ) ) ;
writeAssociationRoleMethod ( fieldClassName ,
a - > getRoleName ( Uml : : B ) ,
a - > getMulti ( Uml : : B ) , a - > getRoleDoc ( Uml : : B ) ,
a - > getVisibility ( Uml : : B ) ,
a - > getChangeability ( Uml : : B ) , java ) ;
}
}
if ( a - > getObjectId ( Uml : : B ) = = thisClass - > getID ( ) )
{
// only write out IF there is a rolename given
if ( ! a - > getRoleName ( Uml : : A ) . isEmpty ( ) ) {
TQString fieldClassName = getUMLObjectName ( a - > getObject ( Uml : : A ) ) ;
writeAssociationRoleMethod ( fieldClassName , a - > getRoleName ( Uml : : A ) ,
a - > getMulti ( Uml : : A ) ,
a - > getRoleDoc ( Uml : : A ) ,
a - > getVisibility ( Uml : : A ) ,
a - > getChangeability ( Uml : : A ) ,
java ) ;
}
}
}
}
}
void JavaWriter : : writeAssociationRoleMethod ( TQString fieldClassName , TQString roleName , TQString multi ,
TQString description , Uml : : Visibility visib , Uml : : Changeability_Type change ,
TQTextStream & java )
{
if ( multi . isEmpty ( ) | | multi . contains ( TQRegExp ( " ^[01]$ " ) ) )
{
TQString fieldVarName = " m_ " + roleName . replace ( 0 , 1 , roleName . left ( 1 ) . lower ( ) ) ;
writeSingleAttributeAccessorMethods ( fieldClassName , fieldVarName , roleName ,
description , visib , change , false , java ) ;
}
else
{
TQString fieldVarName = roleName . lower ( ) + " Vector " ;
writeVectorAttributeAccessorMethods ( fieldClassName , fieldVarName , roleName ,
description , visib , change , java ) ;
}
}
void JavaWriter : : writeVectorAttributeAccessorMethods ( TQString fieldClassName , TQString fieldVarName ,
TQString fieldName , TQString description ,
Uml : : Visibility visibility , Uml : : Changeability_Type changeType ,
TQTextStream & java )
{
fieldClassName = fixTypeName ( fieldClassName ) ;
fieldName = Codegen_Utils : : capitalizeFirstLetter ( fieldName ) ;
TQString strVis = scopeToJavaDecl ( visibility ) ;
// ONLY IF changeability is NOT Frozen
if ( changeType ! = Uml : : chg_Frozen )
{
writeDocumentation ( " Add a " + fieldName + " object to the " + fieldVarName + " List " , description , " " , m_indentation , java ) ;
java < < startline < < strVis < < " void add " < < fieldName < < " ( " < < fieldClassName < < " new_object ) { " ;
java < < startline < < m_indentation < < fieldVarName < < " .add(new_object); " ;
java < < startline < < " } " < < m_endl ;
}
// ONLY IF changeability is Changeable
if ( changeType = = Uml : : chg_Changeable )
{
writeDocumentation ( " Remove a " + fieldName + " object from " + fieldVarName + " List " , description , " " , m_indentation , java ) ;
java < < startline < < strVis < < " void remove " < < fieldName < < " ( " < < fieldClassName < < " new_object ) " ;
java < < startline < < " { " ;
java < < startline < < m_indentation < < fieldVarName < < " .remove(new_object); " ;
java < < startline < < " } " < < m_endl ;
}
// always allow getting the list of stuff
writeDocumentation ( " Get the List of " + fieldName + " objects held by " + fieldVarName , description , " @return List of " + fieldName + " objects held by " + fieldVarName , m_indentation , java ) ;
java < < startline < < strVis < < " List get " < < fieldName < < " List ( ) { " ;
java < < startline < < m_indentation < < " return (List) " < < fieldVarName < < " ; " ;
java < < startline < < " } " < < m_endl ;
writeBlankLine ( java ) ;
}
void JavaWriter : : writeSingleAttributeAccessorMethods ( TQString fieldClassName , TQString fieldVarName ,
TQString fieldName , TQString description ,
Uml : : Visibility visibility , Uml : : Changeability_Type change ,
bool isFinal , TQTextStream & java )
{
TQString strVis = scopeToJavaDecl ( visibility ) ;
fieldClassName = fixTypeName ( fieldClassName ) ;
fieldName = Codegen_Utils : : capitalizeFirstLetter ( fieldName ) ;
// set method
if ( change = = Uml : : chg_Changeable & & ! isFinal ) {
writeDocumentation ( " Set the value of " + fieldVarName , description , " @param newVar the new value of " + fieldVarName , m_indentation , java ) ;
java < < startline < < strVis < < " void set " < < fieldName < < " ( " < < fieldClassName < < " newVar ) { " ;
java < < startline < < m_indentation < < fieldVarName < < " = newVar; " ;
java < < startline < < " } " < < m_endl ;
}
// get method
writeDocumentation ( " Get the value of " + fieldVarName , description , " @return the value of " + fieldVarName , m_indentation , java ) ;
java < < startline < < strVis < < " " < < fieldClassName < < " get " < < fieldName < < " ( ) { " ;
java < < startline < < m_indentation < < " return " < < fieldVarName < < " ; " ;
java < < startline < < " } " ;
writeBlankLine ( java ) ;
}
void JavaWriter : : writeConstructor ( UMLClassifier * c , TQTextStream & java )
{
if ( forceDoc ( ) )
{
java < < startline ;
writeComment ( " " , m_indentation , java ) ;
writeComment ( " Constructors " , m_indentation , java ) ;
writeComment ( " " , m_indentation , java ) ;
writeBlankLine ( java ) ;
}
// write the first constructor
TQString className = cleanName ( c - > getName ( ) ) ;
java < < m_indentation < < " public " < < className < < " () { }; " ;
}
// IF the type is "string" we need to declare it as
// the Java Object "String" (there is no string primative in Java).
// Same thing again for "bool" to "boolean"
TQString JavaWriter : : fixTypeName ( const TQString & string )
{
if ( string . isEmpty ( ) )
return " void " ;
if ( string = = " string " )
return " String " ;
if ( string = = " bool " )
return " boolean " ;
return string ;
}
TQStringList JavaWriter : : defaultDatatypes ( ) {
TQStringList l ;
l . append ( " int " ) ;
l . append ( " char " ) ;
l . append ( " boolean " ) ;
l . append ( " float " ) ;
l . append ( " double " ) ;
l . append ( " byte " ) ;
l . append ( " short " ) ;
l . append ( " long " ) ;
l . append ( " String " ) ;
return l ;
}
bool JavaWriter : : compareJavaMethod ( UMLOperation * op1 , UMLOperation * op2 )
{
if ( op1 = = NULL | | op2 = = NULL )
return false ;
if ( op1 = = op2 )
return true ;
if ( op1 - > getName ( ) ! = op2 - > getName ( ) )
return false ;
UMLAttributeList atl1 = op1 - > getParmList ( ) ;
UMLAttributeList atl2 = op2 - > getParmList ( ) ;
if ( atl1 . count ( ) ! = atl2 . count ( ) )
return false ;
UMLAttribute * at1 ;
UMLAttribute * at2 ;
for ( at1 = atl1 . first ( ) , at2 = atl2 . first ( ) ; at1 & & at2 ; at1 = atl1 . next ( ) , at2 = atl2 . next ( ) )
{
if ( at1 - > getTypeName ( ) ! = at2 - > getTypeName ( ) )
return false ;
}
return true ;
}
bool JavaWriter : : javaMethodInList ( UMLOperation * umlOp , UMLOperationList & opl )
{
for ( UMLOperation * op = opl . first ( ) ; op ; op = opl . next ( ) ) {
if ( JavaWriter : : compareJavaMethod ( op , umlOp ) ) {
return true ;
}
}
return false ;
}
void JavaWriter : : getSuperImplementedOperations ( UMLClassifier * c , UMLOperationList & yetImplementedOpList , UMLOperationList & toBeImplementedOpList , bool noClassInPath )
{
UMLClassifierList superClasses = c - > findSuperClassConcepts ( ) ;
for ( UMLClassifier * concept = superClasses . first ( ) ; concept ; concept = superClasses . next ( ) )
{
getSuperImplementedOperations ( concept , yetImplementedOpList , toBeImplementedOpList , ( concept - > isInterface ( ) & & noClassInPath ) ) ;
UMLOperationList opl = concept - > getOpList ( ) ;
for ( UMLOperation * op = opl . first ( ) ; op ; op = opl . next ( ) ) {
if ( concept - > isInterface ( ) & & noClassInPath ) {
if ( ! JavaWriter : : javaMethodInList ( op , toBeImplementedOpList ) )
toBeImplementedOpList . append ( op ) ;
}
else
{
if ( ! JavaWriter : : javaMethodInList ( op , yetImplementedOpList ) )
yetImplementedOpList . append ( op ) ;
}
}
}
}
void JavaWriter : : getInterfacesOperationsToBeImplemented ( UMLClassifier * c , UMLOperationList & opList )
{
UMLOperationList yetImplementedOpList ;
UMLOperationList toBeImplementedOpList ;
getSuperImplementedOperations ( c , yetImplementedOpList , toBeImplementedOpList ) ;
for ( UMLOperation * op = toBeImplementedOpList . first ( ) ; op ; op = toBeImplementedOpList . next ( ) )
{
if ( ! JavaWriter : : javaMethodInList ( op , yetImplementedOpList ) & & ! JavaWriter : : javaMethodInList ( op , opList ) )
opList . append ( op ) ;
}
}
void JavaWriter : : writeOperations ( UMLClassifier * c , TQTextStream & java ) {
UMLOperationList opl ;
UMLOperationList oppub , opprot , oppriv ;
oppub . setAutoDelete ( false ) ;
opprot . setAutoDelete ( false ) ;
oppriv . setAutoDelete ( false ) ;
//sort operations by scope first and see if there are abstract methods
opl = c - > getOpList ( ) ;
if ( ! c - > isInterface ( ) ) {
getInterfacesOperationsToBeImplemented ( c , opl ) ;
}
for ( UMLOperation * op = opl . first ( ) ; op ; op = opl . next ( ) ) {
switch ( op - > getVisibility ( ) ) {
case Uml : : Visibility : : Public :
oppub . append ( op ) ;
break ;
case Uml : : Visibility : : Protected :
opprot . append ( op ) ;
break ;
case Uml : : Visibility : : Private :
oppriv . append ( op ) ;
break ;
default :
break ;
}
}
// do people REALLY want these comments? Hmm.
/*
if ( forceSections ( ) | | oppub . count ( ) )
{
writeComment ( " public operations " , m_indentation , java ) ;
writeBlankLine ( java ) ;
}
*/
writeOperations ( oppub , java ) ;
/*
if ( forceSections ( ) | | opprot . count ( ) )
{
writeComment ( " protected operations " , m_indentation , java ) ;
writeBlankLine ( java ) ;
}
*/
writeOperations ( opprot , java ) ;
/*
if ( forceSections ( ) | | oppriv . count ( ) )
{
writeComment ( " private operations " , m_indentation , java ) ;
writeBlankLine ( java ) ;
}
*/
writeOperations ( oppriv , java ) ;
}
void JavaWriter : : writeOperations ( UMLOperationList & oplist , TQTextStream & java ) {
UMLOperation * op ;
UMLAttributeList atl ;
UMLAttribute * at ;
int i , j ;
TQString str ;
// generate method decl for each operation given
for ( op = oplist . first ( ) ; op ; op = oplist . next ( ) )
{
TQString returnStr = " " ;
// write documentation
TQString methodReturnType = fixTypeName ( op - > getTypeName ( ) ) ;
if ( methodReturnType ! = " void " )
returnStr + = " @return " + methodReturnType + " \n " ;
str = " " ; // reset for next method
str + = ( ( op - > getAbstract ( ) & & ! isInterface ) ? " abstract " : " " ) ;
str + = scopeToJavaDecl ( op - > getVisibility ( ) ) + ' ' ;
str + = ( op - > getStatic ( ) ? " static " : " " ) ;
str + = methodReturnType + ' ' + cleanName ( op - > getName ( ) ) + " ( " ;
atl = op - > getParmList ( ) ;
i = atl . count ( ) ;
j = 0 ;
for ( at = atl . first ( ) ; at ; at = atl . next ( ) , j + + ) {
TQString typeName = fixTypeName ( at - > getTypeName ( ) ) ;
TQString atName = cleanName ( at - > getName ( ) ) ;
str + = typeName + ' ' + atName +
( ! ( at - > getInitialValue ( ) . isEmpty ( ) ) ?
( TQString ( " = " ) + at - > getInitialValue ( ) ) :
TQString ( " " ) )
+ ( ( j < i - 1 ) ? " , " : " " ) ;
returnStr + = " @param " + atName + ' ' + at - > getDoc ( ) + " \n " ;
}
str + = " ) " ;
// method only gets a body IF its not abstract
if ( op - > getAbstract ( ) | | isInterface )
str + = " ; \n \n " ; // terminate now
else
str + = startline + " { \n \n " + m_indentation + " } \n \n " ; // empty method body
// write it out
writeDocumentation ( " " , op - > getDoc ( ) , returnStr , m_indentation , java ) ;
java < < startline < < str ;
}
}
TQString JavaWriter : : fixInitialStringDeclValue ( TQString value , TQString type )
{
// check for strings only
if ( ! value . isEmpty ( ) & & type = = " String " ) {
if ( ! value . startsWith ( " \" " ) )
value . prepend ( " \" " ) ;
if ( ! value . endsWith ( " \" " ) )
value . append ( " \" " ) ;
}
return value ;
}
TQString JavaWriter : : scopeToJavaDecl ( Uml : : Visibility scope )
{
TQString scopeString ;
switch ( scope )
{
case Uml : : Visibility : : Public :
scopeString = " public " ;
break ;
case Uml : : Visibility : : Protected :
scopeString = " protected " ;
break ;
case Uml : : Visibility : : Private :
default :
scopeString = " private " ;
break ;
}
return scopeString ;
}
// methods like this _shouldn't_ be needed IF we properly did things thruought the code.
TQString JavaWriter : : getUMLObjectName ( UMLObject * obj )
{
return ( obj ! = 0 ) ? obj - > getName ( ) : TQString ( " NULL " ) ;
}
void JavaWriter : : writeBlankLine ( TQTextStream & java )
{
java < < m_endl ;
}