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.
937 lines
32 KiB
937 lines
32 KiB
/***************************************************************************
|
|
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;
|
|
}
|
|
|