summaryrefslogtreecommitdiffstats
path: root/umbrello/umbrello/codegenerators/javawriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'umbrello/umbrello/codegenerators/javawriter.cpp')
-rw-r--r--umbrello/umbrello/codegenerators/javawriter.cpp936
1 files changed, 936 insertions, 0 deletions
diff --git a/umbrello/umbrello/codegenerators/javawriter.cpp b/umbrello/umbrello/codegenerators/javawriter.cpp
new file mode 100644
index 00000000..3e945c60
--- /dev/null
+++ b/umbrello/umbrello/codegenerators/javawriter.cpp
@@ -0,0 +1,936 @@
+/***************************************************************************
+ 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 <qfile.h>
+#include <qtextstream.h>
+#include <qregexp.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();
+
+ QString 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
+ QFile 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
+ QTextStream java(&file);
+
+ //try to find a heading file (license, coments, etc)
+ QString str;
+ str = getHeadingFile(".java");
+ if(!str.isEmpty()) {
+ str.replace(QRegExp("%filename%"),fileName);
+ str.replace(QRegExp("%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;
+ QString 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, QTextStream &java)
+{
+
+ QString 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
+ QString 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) ? QString("abstract ") : QString(""))<<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; ) {
+ QString formalName = t->getName();
+ java << formalName;
+ QString 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, QTextStream &java )
+{
+ UMLAttribute *at;
+
+ for(at=atpub.first(); at; at=atpub.next())
+ {
+ QString documentation = at->getDoc();
+ QString staticValue = at->getStatic() ? "static " : "";
+ QString typeName = fixTypeName(at->getTypeName());
+ QString initialValue = fixInitialStringDeclValue(at->getInitialValue(), typeName);
+ if(!documentation.isEmpty())
+ writeComment(documentation, m_indentation, java, true);
+ java<<startline<<staticValue<<"public "<<typeName<<" "<<cleanName(at->getName())
+ <<(initialValue.isEmpty()?QString(""):QString(" = ") + initialValue)<<";";
+ }
+
+ for(at=atprot.first();at;at=atprot.next())
+ {
+ QString documentation = at->getDoc();
+ QString typeName = fixTypeName(at->getTypeName());
+ QString staticValue = at->getStatic() ? "static " : "";
+ QString initialValue = fixInitialStringDeclValue(at->getInitialValue(), typeName);
+ if(!documentation.isEmpty())
+ writeComment(documentation, m_indentation, java, true);
+ java<<startline<<staticValue<<"protected "<<typeName<<" "<<cleanName(at->getName())
+ <<(initialValue.isEmpty()?QString(""):QString(" = ") + initialValue)<<";";
+ }
+
+ for(at=atpriv.first();at;at=atpriv.next())
+ {
+ QString documentation = at->getDoc();
+ QString typeName = fixTypeName(at->getTypeName());
+ QString staticValue = at->getStatic() ? "static " : "";
+ QString initialValue = fixInitialStringDeclValue(at->getInitialValue(), typeName);
+ if(!documentation.isEmpty())
+ writeComment(documentation, m_indentation, java, true);
+ java<<startline<<staticValue<<"private "<<typeName<<" "<<cleanName(at->getName())
+ <<(initialValue.isEmpty()?QString(""):QString(" = ") + initialValue)<<";";
+ }
+
+}
+
+void JavaWriter::writeAttributeMethods(UMLAttributeList &atpub, Uml::Visibility visibility, QTextStream &java)
+{
+
+ UMLAttribute *at;
+ for(at=atpub.first(); at; at=atpub.next())
+ {
+ QString 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 QString &comment, const QString &myIndent,
+ QTextStream &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(QRegExp("\n"))) {
+
+ if(javaDocStyle)
+ java << myIndent << "/**" << m_endl;
+ QStringList lines = QStringList::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(QString header, QString body, QString end, QString indent, QTextStream &java)
+{
+ writeBlankLine(java);
+ java<<indent<<"/**"<<m_endl;
+ if (!header.isEmpty())
+ java<<formatDoc(header, indent+" * ");
+ if (!body.isEmpty())
+ java<<formatDoc(body, indent+" * ");
+ if (!end.isEmpty())
+ {
+ QStringList lines = QStringList::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, QTextStream &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)
+ {
+ QString 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)
+ {
+ QString 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(QString fieldClassName,
+ QString roleName, QString multi,
+ QString doc, Uml::Visibility visib, QTextStream &java)
+{
+ // ONLY write out IF there is a rolename given
+ // otherwise its not meant to be declared in the code
+ if (roleName.isEmpty())
+ return;
+
+ QString 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(QRegExp("^[01]$")))
+ {
+ QString fieldVarName = "m_" + roleName.replace(0, 1, roleName.left(1).lower());
+ java<<startline<<scope<<" "<<fieldClassName<<" "<<fieldVarName<<";";
+ }
+ else
+ {
+ QString 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, QTextStream &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()) {
+ QString 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()) {
+ QString 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 (QString fieldClassName, QString roleName, QString multi,
+ QString description, Uml::Visibility visib, Uml::Changeability_Type change,
+ QTextStream &java)
+{
+ if(multi.isEmpty() || multi.contains(QRegExp("^[01]$")))
+ {
+ QString fieldVarName = "m_" + roleName.replace(0, 1, roleName.left(1).lower());
+ writeSingleAttributeAccessorMethods(fieldClassName, fieldVarName, roleName,
+ description, visib, change, false, java);
+ }
+ else
+ {
+ QString fieldVarName = roleName.lower() + "Vector";
+ writeVectorAttributeAccessorMethods(fieldClassName, fieldVarName, roleName,
+ description, visib, change, java);
+ }
+}
+
+void JavaWriter::writeVectorAttributeAccessorMethods (QString fieldClassName, QString fieldVarName,
+ QString fieldName, QString description,
+ Uml::Visibility visibility, Uml::Changeability_Type changeType,
+ QTextStream &java)
+{
+
+ fieldClassName = fixTypeName(fieldClassName);
+ fieldName = Codegen_Utils::capitalizeFirstLetter(fieldName);
+ QString 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(QString fieldClassName, QString fieldVarName,
+ QString fieldName, QString description,
+ Uml::Visibility visibility, Uml::Changeability_Type change,
+ bool isFinal, QTextStream &java)
+{
+
+ QString 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, QTextStream &java)
+{
+
+ if (forceDoc())
+ {
+ java<<startline;
+ writeComment("", m_indentation, java);
+ writeComment("Constructors", m_indentation, java);
+ writeComment("", m_indentation, java);
+ writeBlankLine(java);
+ }
+
+ // write the first constructor
+ QString 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"
+QString JavaWriter::fixTypeName(const QString& string)
+{
+ if (string.isEmpty())
+ return "void";
+ if (string == "string")
+ return "String";
+ if (string == "bool")
+ return "boolean";
+ return string;
+}
+
+QStringList JavaWriter::defaultDatatypes() {
+ QStringList 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, QTextStream &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, QTextStream &java) {
+ UMLOperation *op;
+ UMLAttributeList atl;
+ UMLAttribute *at;
+ int i,j;
+ QString str;
+
+ // generate method decl for each operation given
+ for( op=oplist.first(); op ;op=oplist.next())
+ {
+
+ QString returnStr = "";
+ // write documentation
+
+ QString 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++) {
+ QString typeName = fixTypeName(at->getTypeName());
+ QString atName = cleanName(at->getName());
+ str += typeName + ' ' + atName +
+ (!(at->getInitialValue().isEmpty()) ?
+ (QString(" = ")+at->getInitialValue()) :
+ QString(""))
+ + ((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;
+ }
+}
+
+QString JavaWriter::fixInitialStringDeclValue(QString value, QString type)
+{
+ // check for strings only
+ if (!value.isEmpty() && type == "String") {
+ if (!value.startsWith("\""))
+ value.prepend("\"");
+ if (!value.endsWith("\""))
+ value.append("\"");
+ }
+ return value;
+}
+
+QString JavaWriter::scopeToJavaDecl(Uml::Visibility scope)
+{
+ QString 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.
+QString JavaWriter::getUMLObjectName(UMLObject *obj)
+{
+ return(obj!=0)?obj->getName():QString("NULL");
+}
+
+void JavaWriter::writeBlankLine(QTextStream &java)
+{
+ java<<m_endl;
+}
+