diff options
Diffstat (limited to 'umbrello/umbrello/codegenerators')
131 files changed, 34264 insertions, 0 deletions
diff --git a/umbrello/umbrello/codegenerators/Makefile.am b/umbrello/umbrello/codegenerators/Makefile.am new file mode 100644 index 00000000..bc622fe0 --- /dev/null +++ b/umbrello/umbrello/codegenerators/Makefile.am @@ -0,0 +1,38 @@ +noinst_LTLIBRARIES = libcodegenerator.la + +INCLUDES = -I../dialogs -I$(top_srcdir)/umbrello/umbrello/dialogs $(all_includes) + +libcodegenerator_la_LDFLAGS = $(all_libraries) +libcodegenerator_la_METASOURCES = AUTO +libcodegenerator_la_SOURCES = codegenfactory.cpp classifierinfo.cpp \ + javacodegenerator.cpp javaantcodedocument.cpp javacodeclassfield.cpp \ + javaclassifiercodedocument.cpp javacodecomment.cpp javacodedocumentation.cpp \ + javacodeoperation.cpp javacodeaccessormethod.cpp \ + javaclassdeclarationblock.cpp javacodeclassfielddeclarationblock.cpp \ + javacodegenerationpolicy.cpp javacodegenerationpolicypage.cpp \ + javacodegenerationformbase.ui \ + cppcodegenerator.cpp cppcodedocumentation.cpp cppcodeclassfield.cpp \ + cppcodecomment.cpp cppmakecodedocument.cpp \ + cppsourcecodedocument.cpp cppsourcecodeoperation.cpp cppsourcecodeaccessormethod.cpp \ + cppsourcecodeclassfielddeclarationblock.cpp \ + cppheadercodedocument.cpp cppheaderclassdeclarationblock.cpp \ + cppheadercodeoperation.cpp cppheadercodeaccessormethod.cpp \ + cppheadercodeclassfielddeclarationblock.cpp \ + cppcodegenerationpolicy.cpp cppcodegenerationpolicypage.cpp \ + cppcodegenerationformbase.ui cppcodegenerationform.cpp \ + rubycodegenerator.cpp rubycodeclassfield.cpp \ + rubyclassifiercodedocument.cpp rubycodecomment.cpp rubycodedocumentation.cpp \ + rubycodeoperation.cpp rubycodeaccessormethod.cpp \ + rubyclassdeclarationblock.cpp rubycodeclassfielddeclarationblock.cpp \ + rubycodegenerationpolicy.cpp rubycodegenerationpolicypage.cpp \ + rubycodegenerationformbase.ui \ + simplecodegenerator.cpp \ + adawriter.cpp aswriter.cpp cppwriter.cpp csharpwriter.cpp dwriter.cpp javawriter.cpp jswriter.cpp \ + idlwriter.cpp pascalwriter.cpp perlwriter.cpp php5writer.cpp phpwriter.cpp \ + pythonwriter.cpp rubywriter.cpp sqlwriter.cpp tclwriter.cpp xmlschemawriter.cpp \ + xmlelementcodeblock.cpp xmlcodecomment.cpp \ + codegen_utils.cpp +libcodegenerator_la_COMPILE_FIRST = ../dialogs/codegenerationpolicybase.h + +KDE_OPTIONS = nofinal + diff --git a/umbrello/umbrello/codegenerators/adawriter.cpp b/umbrello/umbrello/codegenerators/adawriter.cpp new file mode 100644 index 00000000..e1c79839 --- /dev/null +++ b/umbrello/umbrello/codegenerators/adawriter.cpp @@ -0,0 +1,686 @@ +/*************************************************************************** + * adawriter.cpp - description * + * ------------------- * + * Based on javawriter.cpp by Luis De la Parra Blum * + * copyright : (C) 2002 by Oliver Kellogg * + * (C) 2003-2007 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. * + * * + ***************************************************************************/ + +#include "adawriter.h" + +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <qfile.h> +#include <qregexp.h> +#include <qtextstream.h> + +#include "../umldoc.h" +#include "../uml.h" +#include "../classifier.h" +#include "../enum.h" +#include "../classifierlistitem.h" +#include "../umlclassifierlistitemlist.h" +#include "../umltemplatelist.h" +#include "../folder.h" +#include "../association.h" +#include "../attribute.h" +#include "../operation.h" +#include "../template.h" +#include "../umlnamespace.h" + +const QString AdaWriter::defaultPackageSuffix = "_Holder"; + +AdaWriter::AdaWriter() { +} + +AdaWriter::~AdaWriter() {} + +/** + * returns "Ada" + */ +Uml::Programming_Language AdaWriter::getLanguage() { + return Uml::pl_Ada; +} + + +bool AdaWriter::isOOClass(UMLClassifier *c) { + Uml::Object_Type ot = c->getBaseType(); + if (ot == Uml::ot_Interface) + return true; + if (ot == Uml::ot_Enum) + return false; + if (ot != Uml::ot_Class) { + kDebug() << "AdaWriter::isOOClass: unknown object type " << ot << endl; + return false; + } + QString stype = c->getStereotype(); + if (stype == "CORBAConstant" || stype == "CORBATypedef" || + stype == "CORBAStruct" || stype == "CORBAUnion") + return false; + // CORBAValue, CORBAInterface, and all empty/unknown stereotypes are + // assumed to be OO classes. + return true; +} + +QString AdaWriter::className(UMLClassifier *c, bool inOwnScope) { + // If the class has an enclosing package then it is assumed that + // the class name is the type name; if the class does not have an + // enclosing package then the class name acts as the Ada package + // name. + QString retval; + QString className = cleanName(c->getName()); + UMLPackage *umlPkg = c->getUMLPackage(); + if (umlPkg == UMLApp::app()->getDocument()->getRootFolder(Uml::mt_Logical)) { + if (! inOwnScope) + retval = className + '.'; + retval.append("Object"); + } else { + if (! inOwnScope) + retval = umlPkg->getFullyQualifiedName(".") + '.'; + retval.append(className); + } + return retval; +} + +QString AdaWriter::packageName(UMLPackage *p) { + // If the class has an enclosing package then it is assumed that + // the class name is the type name; if the class does not have an + // enclosing package then the class name acts as the Ada package + // name. + UMLPackage *umlPkg = p->getUMLPackage(); + QString className = cleanName(p->getName()); + QString retval; + + if (umlPkg == UMLApp::app()->getDocument()->getRootFolder(Uml::mt_Logical)) + umlPkg = NULL; + + UMLClassifier *c = dynamic_cast<UMLClassifier*>(p); + if (umlPkg == NULL) { + retval = className; + if (c == NULL || !isOOClass(c)) + retval.append(defaultPackageSuffix); + } else { + retval = umlPkg->getFullyQualifiedName("."); + } + return retval; +} + +void AdaWriter::computeAssocTypeAndRole(UMLClassifier *c, + UMLAssociation *a, + QString& typeName, QString& roleName) { + UMLClassifier* assocEnd = dynamic_cast<UMLClassifier*>(a->getObject(Uml::B)); + if (assocEnd == NULL) + return; + const Uml::Association_Type assocType = a->getAssocType(); + if (assocType != Uml::at_Aggregation && assocType != Uml::at_Composition) + return; + const QString multi = a->getMulti(Uml::B); + bool hasNonUnityMultiplicity = (!multi.isEmpty() && multi != "1"); + hasNonUnityMultiplicity &= !multi.contains(QRegExp("^1 *\\.\\. *1$")); + roleName = cleanName(a->getRoleName(Uml::B)); + if (roleName.isEmpty()) + roleName = cleanName(a->getName()); + if (roleName.isEmpty()) { + QString artificialName = cleanName(assocEnd->getName()); + if (hasNonUnityMultiplicity) { + roleName = artificialName; + roleName.append("_Vector"); + } else { + roleName = "M_"; + roleName.append(artificialName); + } + } + typeName = className(assocEnd, (assocEnd == c)); + if (hasNonUnityMultiplicity) + typeName.append("_Array_Ptr"); + else if (assocType == Uml::at_Aggregation) + typeName.append("_Ptr"); +} + +void AdaWriter::writeClass(UMLClassifier *c) { + if (!c) { + kDebug() << "Cannot write class of NULL concept!" << endl; + return; + } + + const bool isClass = !c->isInterface(); + QString classname = cleanName(c->getName()); + QString fileName = packageName(c).lower(); + fileName.replace('.', '-'); + + //find an appropriate name for our file + fileName = overwritableName(c, fileName, ".ads"); + if (fileName.isEmpty()) { + emit codeGenerated(c, false); + return; + } + + QFile file; + if (!openFile(file, fileName)) { + emit codeGenerated(c, false); + return; + } + + // Start generating the code. + + QTextStream ada(&file); + //try to find a heading file(license, comments, etc) + QString str; + str = getHeadingFile(".ads"); + if (!str.isEmpty()) { + str.replace(QRegExp("%filename%"), fileName); + str.replace(QRegExp("%filepath%"), file.name()); + ada << str << endl; + } + + // Import referenced classes. + UMLPackageList imports; + findObjectsRelated(c, imports); + if (imports.count()) { + for (UMLPackage *con = imports.first(); con; con = imports.next()) { + if (con->getBaseType() != Uml::ot_Datatype) + ada << "with " << packageName(con) << "; " << m_endl; + } + ada << m_endl; + } + + // Generate generic formals. + UMLTemplateList template_params = c->getTemplateList(); + if (template_params.count()) { + ada << getIndent() << "generic" << m_endl; + m_indentLevel++; + for (UMLTemplate *t = template_params.first(); t; t = template_params.next()) { + QString formalName = t->getName(); + QString typeName = t->getTypeName(); + if (typeName == "class") { + ada << getIndent() << "type " << formalName << " is tagged private;" + << m_endl; + } else { + // Check whether it's a data type. + UMLClassifier *typeObj = t->getType(); + if (typeObj == NULL) { + kError() << "AdaWriter::writeClass(template_param " + << typeName << "): typeObj is NULL" << endl; + ada << getIndent() << "type " << formalName << " is new " << typeName + << " with private; -- CHECK: codegen error" + << m_endl; + } else if (typeObj->getBaseType() == Uml::ot_Datatype) { + ada << getIndent() << formalName << " : " << typeName << ";" + << m_endl; + } else { + ada << getIndent() << "type " << typeName << " is new " + << formalName << " with private;" << m_endl; + } + } + } + m_indentLevel--; + } + + // Here comes the package proper. + QString pkg = packageName(c); + ada << getIndent() << "package " << pkg << " is" << m_endl << m_endl; + m_indentLevel++; + if (c->getBaseType() == Uml::ot_Enum) { + UMLEnum *ue = static_cast<UMLEnum*>(c); + UMLClassifierListItemList litList = ue->getFilteredList(Uml::ot_EnumLiteral); + uint i = 0; + ada << getIndent() << "type " << classname << " is (" << m_endl; + m_indentLevel++; + for (UMLClassifierListItem *lit = litList.first(); lit; lit = litList.next()) { + QString enumLiteral = cleanName(lit->getName()); + ada << getIndent() << enumLiteral; + if (++i < litList.count()) + ada << "," << m_endl; + } + m_indentLevel--; + ada << ");" << m_endl << m_endl; + m_indentLevel--; + ada << getIndent() << "end " << pkg << ";" << m_endl << m_endl; + return; + } + if (! isOOClass(c)) { + QString stype = c->getStereotype(); + if (stype == "CORBAConstant") { + ada << getIndent() << "-- " << stype << " is Not Yet Implemented" << m_endl << m_endl; + } else if(stype == "CORBAStruct") { + if (isClass) { + UMLAttributeList atl = c->getAttributeList(); + UMLAttribute *at; + ada << getIndent() << "type " << classname << " is record" << m_endl; + m_indentLevel++; + for (at = atl.first(); at; at = atl.next()) { + QString name = cleanName(at->getName()); + QString typeName = at->getTypeName(); + ada << getIndent() << name << " : " << typeName; + QString initialVal = at->getInitialValue(); + if (initialVal.latin1() && ! initialVal.isEmpty()) + ada << " := " << initialVal; + ada << ";" << m_endl; + } + m_indentLevel--; + ada << getIndent() << "end record;" << m_endl << m_endl; + } + } else if(stype == "CORBAUnion") { + ada << getIndent() << "-- " << stype << " is Not Yet Implemented" << m_endl << m_endl; + } else if(stype == "CORBATypedef") { + ada << getIndent() << "-- " << stype << " is Not Yet Implemented" << m_endl << m_endl; + } else { + ada << getIndent() << "-- " << stype << ": Unknown stereotype" << m_endl << m_endl; + } + m_indentLevel--; + ada << getIndent() << "end " << pkg << ";" << m_endl << m_endl; + return; + } + + // Write class Documentation if non-empty or if force option set. + if (forceDoc() || !c->getDoc().isEmpty()) { + ada << "--" << m_endl; + ada << "-- class " << classname << endl; + ada << formatDoc(c->getDoc(), "-- "); + ada << m_endl; + } + + UMLClassifierList superclasses = c->getSuperClasses(); + + const QString name = className(c); + ada << getIndent() << "type " << name << " is "; + if (c->getAbstract()) + ada << "abstract "; + if (superclasses.isEmpty()) { + ada << "tagged "; + } else { + // FIXME: Multiple inheritance is not yet supported + UMLClassifier* parent = superclasses.first(); + ada << "new " << className(parent, false) << " with "; + } + ada << "private;" << m_endl << m_endl; + ada << getIndent() << "type " << name << "_Ptr is access all " << name << "'Class;" << m_endl << m_endl; + ada << getIndent() << "type " << name << "_Array is array (Positive range <>) of " << name << "_Ptr;" << m_endl << m_endl; + ada << getIndent() << "type " << name << "_Array_Ptr is access " << name << "_Array;" << m_endl << m_endl; + + // Generate accessors for public attributes. + UMLAttributeList atl; + if (isClass) { + UMLAttributeList atpub; + atpub.setAutoDelete(false); + + atl = c->getAttributeList(); + + UMLAttribute *at; + for (at = atl.first(); at; at = atl.next()) { + if (at->getVisibility() == Uml::Visibility::Public) + atpub.append(at); + } + if (forceSections() || atpub.count()) + ada << getIndent() << "-- Accessors for public attributes:" << m_endl << m_endl; + for (at = atpub.first(); at; at = atpub.next()) { + QString member = cleanName(at->getName()); + ada << getIndent() << "procedure Set_" << member << " ("; + if (! at->getStatic()) + ada << "Self : access " << name << "; "; + ada << "To : " << at->getTypeName() << ");" << m_endl; + ada << getIndent() << "function Get_" << member; + if (! at->getStatic()) + ada << " (Self : access " << name << ")"; + ada << " return " << at->getTypeName() << ";" << m_endl + << m_endl; + } + } + + // Generate public operations. + UMLOperationList opl(c->getOpList()); + UMLOperationList oppub; + oppub.setAutoDelete(false); + UMLOperation *op; + for (op = opl.first(); op; op = opl.next()) { + if (op->getVisibility() == Uml::Visibility::Public) + oppub.append(op); + } + if (forceSections() || oppub.count()) + ada << getIndent() << "-- Public methods:" << m_endl << m_endl; + for (op = oppub.first(); op; op = oppub.next()) + writeOperation(op, ada); + + m_indentLevel--; + ada << getIndent() << "private" << m_endl << m_endl; + m_indentLevel++; + + UMLAssociationList aggregations = c->getAggregations(); + UMLAssociationList compositions = c->getCompositions(); + + ada << getIndent() << "type " << name << " is "; + if (c->getAbstract()) + ada << "abstract "; + if (superclasses.isEmpty()) { + ada << "tagged "; + } else { + // FIXME: Multiple inheritance is not yet supported + UMLClassifier* parent = superclasses.first(); + ada << "new " << className(parent, false) << " with "; + } + ada << "record" << m_endl; + m_indentLevel++; + + if (forceSections() || !aggregations.isEmpty()) { + ada << getIndent() << "-- Aggregations:" << m_endl; + for (UMLAssociation *a = aggregations.first(); a; a = aggregations.next()) { + if (c != a->getObject(Uml::A)) + continue; + QString typeName, roleName; + computeAssocTypeAndRole(c, a, typeName, roleName); + ada << getIndent() << roleName << " : " << typeName << ";" << m_endl; + } + ada << endl; + } + if (forceSections() || !compositions.isEmpty()) { + ada << getIndent() << "-- Compositions:" << m_endl; + for (UMLAssociation *a = compositions.first(); a; a = compositions.next()) { + if (c != a->getObject(Uml::A)) + continue; + QString typeName, roleName; + computeAssocTypeAndRole(c, a, typeName, roleName); + ada << getIndent() << roleName << " : " << typeName << ";" << m_endl; + } + ada << endl; + } + + if (isClass && (forceSections() || atl.count())) { + ada << getIndent() << "-- Attributes:" << m_endl; + UMLAttribute *at; + for (at = atl.first(); at; at = atl.next()) { + if (at->getStatic()) + continue; + ada << getIndent() << cleanName(at->getName()) << " : " + << at->getTypeName(); + if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty()) + ada << " := " << at->getInitialValue(); + ada << ";" << m_endl; + } + } + bool haveAttrs = (isClass && atl.count()); + if (aggregations.isEmpty() && compositions.isEmpty() && !haveAttrs) + ada << getIndent() << "null;" << m_endl; + m_indentLevel--; + ada << getIndent() << "end record;" << m_endl << m_endl; + if (haveAttrs) { + bool seen_static_attr = false; + for (UMLAttribute *at = atl.first(); at; at = atl.next()) { + if (! at->getStatic()) + continue; + if (! seen_static_attr) { + ada << getIndent() << "-- Static attributes:" << m_endl; + seen_static_attr = true; + } + ada << getIndent(); + if (at->getVisibility() == Uml::Visibility::Private) + ada << "-- Private: "; + ada << cleanName(at->getName()) << " : " << at->getTypeName(); + if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty()) + ada << " := " << at->getInitialValue(); + ada << ";" << m_endl; + } + if (seen_static_attr) + ada << m_endl; + } + // Generate protected operations. + UMLOperationList opprot; + opprot.setAutoDelete(false); + for (op = opl.first(); op; op = opl.next()) { + if (op->getVisibility() == Uml::Visibility::Protected) + opprot.append(op); + } + if (forceSections() || opprot.count()) + ada << getIndent() << "-- Protected methods:" << m_endl << m_endl; + for (op = opprot.first(); op; op = opprot.next()) + writeOperation(op, ada); + + // Generate private operations. + // These are currently only generated as comments in the private part + // of the spec. + // Once umbrello supports the merging of automatically generated and + // hand written code sections, private operations should be generated + // into the package body. + UMLOperationList oppriv; + oppriv.setAutoDelete(false); + for (op = opl.first(); op; op = opl.next()) { + const Uml::Visibility::Value vis = op->getVisibility(); + if (vis == Uml::Visibility::Private || + vis == Uml::Visibility::Implementation) + oppriv.append(op); + } + if (forceSections() || oppriv.count()) + ada << getIndent() << "-- Private methods:" << m_endl << m_endl; + for (op = oppriv.first(); op; op = oppriv.next()) + writeOperation(op, ada, true); + + m_indentLevel--; + ada << getIndent() << "end " << pkg << ";" << m_endl << m_endl; + file.close(); + emit codeGenerated(c, true); +} + + +void AdaWriter::writeOperation(UMLOperation *op, QTextStream &ada, bool is_comment) { + UMLAttributeList atl = op->getParmList(); + QString rettype = op->getTypeName(); + bool use_procedure = (rettype.isEmpty() || rettype == "void"); + + ada << getIndent(); + if (is_comment) + ada << "-- "; + if (use_procedure) + ada << "procedure "; + else + ada << "function "; + ada << cleanName(op->getName()) << " "; + if (! (op->getStatic() && atl.count() == 0)) + ada << "("; + UMLClassifier *parentClassifier = static_cast<UMLClassifier*>(op->getUMLPackage()); + if (! op->getStatic()) { + ada << "Self : access " << className(parentClassifier); + if (atl.count()) + ada << ";" << m_endl; + } + if (atl.count()) { + uint i = 0; + m_indentLevel++; + for (UMLAttribute *at = atl.first(); at; at = atl.next()) { + ada << getIndent(); + if (is_comment) + ada << "-- "; + ada << cleanName(at->getName()) << " : "; + Uml::Parameter_Direction pk = at->getParmKind(); + if (pk == Uml::pd_Out) + ada << "out "; + else if (pk == Uml::pd_InOut) + ada << "in out "; + else + ada << "in "; + ada << at->getTypeName(); + if (! at->getInitialValue().isEmpty()) + ada << " := " << at->getInitialValue(); + if (++i < atl.count()) //FIXME gcc warning + ada << ";" << m_endl; + } + m_indentLevel--; + } + if (! (op->getStatic() && atl.count() == 0)) + ada << ")"; + if (! use_procedure) + ada << " return " << rettype; + if (op->getAbstract()) + ada << " is abstract"; + ada << ";" << m_endl << m_endl; +} + +QStringList AdaWriter::defaultDatatypes() { + QStringList l; + l.append("Boolean"); + l.append("Character"); + l.append("Positive"); + l.append("Natural"); + l.append("Integer"); + l.append("Short_Integer"); + l.append("Long_Integer"); + l.append("Float"); + l.append("Long_Float"); + l.append("Duration"); + l.append("String"); + return l; +} + +/** + * Check whether the given string is a reserved word for the + * language of this code generator + * + * @param rPossiblyReservedKeyword The string to check. + */ +bool AdaWriter::isReservedKeyword(const QString & rPossiblyReservedKeyword) { + + const QStringList keywords = reservedKeywords(); + + QStringList::ConstIterator it; + for (it = keywords.begin(); it != keywords.end(); ++it) + if ((*it).lower() == rPossiblyReservedKeyword.lower()) + return true; + + return false; +} + +/** + * get list of reserved keywords + */ +const QStringList AdaWriter::reservedKeywords() const { + + static QStringList keywords; + + if ( keywords.isEmpty() ) { + keywords.append( "abort" ); + keywords.append( "abs" ); + keywords.append( "abstract" ); + keywords.append( "accept" ); + keywords.append( "access" ); + keywords.append( "aliased" ); + keywords.append( "all" ); + keywords.append( "and" ); + keywords.append( "Argument_Error" ); + keywords.append( "array" ); + keywords.append( "Assert_Failure" ); + keywords.append( "at" ); + keywords.append( "begin" ); + keywords.append( "body" ); + keywords.append( "Boolean" ); + keywords.append( "case" ); + keywords.append( "Character" ); + keywords.append( "constant" ); + keywords.append( "Constraint_Error" ); + keywords.append( "Conversion_Error" ); + keywords.append( "Data_Error" ); + keywords.append( "declare" ); + keywords.append( "delay" ); + keywords.append( "delta" ); + keywords.append( "Dereference_Error" ); + keywords.append( "Device_Error" ); + keywords.append( "digits" ); + keywords.append( "do" ); + keywords.append( "Duration" ); + keywords.append( "else" ); + keywords.append( "elsif" ); + keywords.append( "end" ); + keywords.append( "End_Error" ); + keywords.append( "entry" ); + keywords.append( "exception" ); + keywords.append( "exit" ); + keywords.append( "false" ); + keywords.append( "Float" ); + keywords.append( "for" ); + keywords.append( "function" ); + keywords.append( "generic" ); + keywords.append( "goto" ); + keywords.append( "if" ); + keywords.append( "in" ); + keywords.append( "Index_Error" ); + keywords.append( "Integer" ); + keywords.append( "is" ); + keywords.append( "Layout_Error" ); + keywords.append( "Length_Error" ); + keywords.append( "limited" ); + keywords.append( "Long_Float" ); + keywords.append( "Long_Integer" ); + keywords.append( "Long_Long_Float" ); + keywords.append( "Long_Long_Integer" ); + keywords.append( "loop" ); + keywords.append( "mod" ); + keywords.append( "Mode_Error" ); + keywords.append( "Name_Error" ); + keywords.append( "Natural" ); + keywords.append( "new" ); + keywords.append( "not" ); + keywords.append( "null" ); + keywords.append( "of" ); + keywords.append( "or" ); + keywords.append( "others" ); + keywords.append( "out" ); + keywords.append( "package" ); + keywords.append( "Pattern_Error" ); + keywords.append( "Picture_Error" ); + keywords.append( "Pointer_Error" ); + keywords.append( "Positive" ); + keywords.append( "pragma" ); + keywords.append( "private" ); + keywords.append( "procedure" ); + keywords.append( "Program_Error" ); + keywords.append( "protected" ); + keywords.append( "raise" ); + keywords.append( "range" ); + keywords.append( "record" ); + keywords.append( "rem" ); + keywords.append( "renames" ); + keywords.append( "requeue" ); + keywords.append( "return" ); + keywords.append( "reverse" ); + keywords.append( "select" ); + keywords.append( "separate" ); + keywords.append( "Short_Float" ); + keywords.append( "Short_Integer" ); + keywords.append( "Short_Short_Float" ); + keywords.append( "Short_Short_Integer" ); + keywords.append( "Status_Error" ); + keywords.append( "Storage_Error" ); + keywords.append( "String" ); + keywords.append( "subtype" ); + keywords.append( "Tag_Error" ); + keywords.append( "tagged" ); + keywords.append( "task" ); + keywords.append( "Tasking_Error" ); + keywords.append( "terminate" ); + keywords.append( "Terminator_Error" ); + keywords.append( "then" ); + keywords.append( "Time_Error" ); + keywords.append( "Translation_Error" ); + keywords.append( "true" ); + keywords.append( "type" ); + keywords.append( "until" ); + keywords.append( "Update_Error" ); + keywords.append( "use" ); + keywords.append( "Use_Error" ); + keywords.append( "when" ); + keywords.append( "while" ); + keywords.append( "Wide_Character" ); + keywords.append( "Wide_String" ); + keywords.append( "with" ); + keywords.append( "xor" ); + } + + return keywords; +} + +#include "adawriter.moc" diff --git a/umbrello/umbrello/codegenerators/adawriter.h b/umbrello/umbrello/codegenerators/adawriter.h new file mode 100644 index 00000000..ca5d9f67 --- /dev/null +++ b/umbrello/umbrello/codegenerators/adawriter.h @@ -0,0 +1,105 @@ +/*************************************************************************** + adawriter.h - description + ------------------- + Based on javawriter.h by Luis De la Parra Blum + begin : Sat Dec 14 2002 + copyright : (C) 2002 by Oliver Kellogg + email : okellogg@users.sourceforge.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. * + * * + ***************************************************************************/ + +#ifndef ADAWRITER_H +#define ADAWRITER_H + +#include "simplecodegenerator.h" + +class UMLAssociation; +class UMLOperation; + +/** + * class AdaWriter is a code generator for UMLClassifier objects. + * Create an instance of this class, and feed it a UMLClassifier when + * calling writeClass and it will generate an Ada package spec for + * that concept + */ +class AdaWriter : public SimpleCodeGenerator { + Q_OBJECT +public: + + /** + * Basic Constructor + */ + AdaWriter (); + + /** + * Empty Destructor + */ + virtual ~AdaWriter (); + + /** + * call this method to generate Ada code for a UMLClassifier + * @param c the class to generate code for + */ + virtual void writeClass (UMLClassifier *c); + + /** + * returns "Ada" + */ + virtual Uml::Programming_Language getLanguage(); + + QStringList defaultDatatypes(); + + /** + * Check whether the given string is a reserved word for the + * language of this code generator + * + * @param rPossiblyReservedKeyword The string to check. + * @return true if the keyword is reserved + */ + virtual bool isReservedKeyword(const QString & rPossiblyReservedKeyword); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +private: + + /** + * write one operation + * @param op the class for which we are generating code + * @param ada the stream associated with the output file + */ + void writeOperation (UMLOperation *op, QTextStream &ada, bool is_comment = false); + + /** + * Compute the type and role name from the given association. + * + * @param c The UMLClassifier for which code is being generated. + * @param a The UMLAssociation to analyze. + * @param typeName Return value: type name. + * @param roleName Return value: role name. + */ + void computeAssocTypeAndRole (UMLClassifier *c, + UMLAssociation *a, + QString& typeName, QString& roleName); + + bool isOOClass (UMLClassifier *c); + + QString className(UMLClassifier *c, bool inOwnScope = true); + + QString packageName(UMLPackage *p); + + static const QString defaultPackageSuffix; + +}; + +#endif // ADAWRITER_H diff --git a/umbrello/umbrello/codegenerators/aswriter.cpp b/umbrello/umbrello/codegenerators/aswriter.cpp new file mode 100644 index 00000000..ad55839d --- /dev/null +++ b/umbrello/umbrello/codegenerators/aswriter.cpp @@ -0,0 +1,775 @@ +/*************************************************************************** + begin : Sat Feb 08 2003 + copyright : (C) 2003 by Alexander Blum + email : blum@kewbee.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "aswriter.h" +#include "../association.h" +#include "../classifier.h" +#include "../operation.h" +#include "../umldoc.h" +#include "../attribute.h" + +#include <kdebug.h> +#include <qregexp.h> +#include <qtextstream.h> + +ASWriter::ASWriter() { +} + +ASWriter::~ASWriter() {} + + +void ASWriter::writeClass(UMLClassifier *c) +{ + if(!c) + { + kDebug()<<"Cannot write class of NULL concept!" << endl; + return; + } + + QString classname = cleanName(c->getName()); + QString fileName = c->getName().lower(); + + //find an appropriate name for our file + fileName = findFileName(c,".as"); + if (fileName.isEmpty()) + { + emit codeGenerated(c, false); + return; + } + + QFile fileas; + if(!openFile(fileas,fileName)) + { + emit codeGenerated(c, false); + return; + } + QTextStream as(&fileas); + + ////////////////////////////// + //Start generating the code!! + ///////////////////////////// + + + //try to find a heading file (license, coments, etc) + QString str; + str = getHeadingFile(".as"); + if(!str.isEmpty()) + { + str.replace(QRegExp("%filename%"),fileName+".as"); + str.replace(QRegExp("%filepath%"),fileas.name()); + as << str << m_endl; + } + + + //write includes + UMLPackageList includes; + findObjectsRelated(c,includes); + for (UMLPackage *conc = includes.first(); conc; conc = includes.next()) + { + QString headerName = findFileName(conc, ".as"); + if ( !headerName.isEmpty() ) + { + as << "#include \"" << findFileName(conc,".as") << "\"" << m_endl; + } + } + as << m_endl; + + //Write class Documentation if there is somthing or if force option + if(forceDoc() || !c->getDoc().isEmpty()) + { + as << m_endl << "/**" << m_endl; + as << " * class " << classname << m_endl; + as << formatDoc(c->getDoc()," * "); + as << " */" << m_endl << m_endl; + } + + UMLClassifierList superclasses = c->getSuperClasses(); + UMLAssociationList aggregations = c->getAggregations(); + UMLAssociationList compositions = c->getCompositions(); + + //check if class is abstract and / or has abstract methods + if(c->getAbstract() && !hasAbstractOps(c)) + as << "/******************************* Abstract Class ****************************" << m_endl << " " + << classname << " does not have any pure virtual methods, but its author" << m_endl + << " defined it as an abstract class, so you should not use it directly." << m_endl + << " Inherit from it instead and create only objects from the derived classes" << m_endl + << "*****************************************************************************/" << m_endl << m_endl; + + as << classname << " = function ()" << m_endl; + as << "{" << m_endl; + as << m_indentation << "this._init ();" << m_endl; + as << "}" << m_endl; + as << m_endl; + + for(UMLClassifier *obj = superclasses.first(); + obj; obj = superclasses.next()) { + as << classname << ".prototype = new " << cleanName(obj->getName()) << " ();" << m_endl; + } + + as << m_endl; + + const bool isClass = !c->isInterface(); + if (isClass) { + + UMLAttributeList atl = c->getAttributeList(); + + as << "/**" << m_endl; + QString temp = "_init sets all " + classname + + " attributes to their default values. " + + "Make sure to call this method within your class constructor"; + as << formatDoc(temp, " * "); + as << " */" << m_endl; + as << classname << ".prototype._init = function ()" << m_endl; + as << "{" << m_endl; + for(UMLAttribute *at = atl.first(); at ; at = atl.next()) + { + if (forceDoc() || !at->getDoc().isEmpty()) + { + as << m_indentation << "/**" << m_endl + << formatDoc(at->getDoc(), m_indentation + " * ") + << m_indentation << " */" << m_endl; + } + if(!at->getInitialValue().isEmpty()) + { + as << m_indentation << "this.m_" << cleanName(at->getName()) << " = " << at->getInitialValue() << ";" << m_endl; + } + else + { + as << m_indentation << "this.m_" << cleanName(at->getName()) << " = \"\";" << m_endl; + } + } + } + + //associations + if (forceSections() || !aggregations.isEmpty ()) + { + as << m_endl << m_indentation << "/**Aggregations: */" << m_endl; + writeAssociation(classname, aggregations , as ); + + } + + if( forceSections() || !compositions.isEmpty()) + { + as << m_endl << m_indentation << "/**Compositions: */" << m_endl; + writeAssociation(classname, compositions , as ); + } + + as << m_endl; + as << m_indentation << "/**Protected: */" << m_endl; + + if (isClass) { + UMLAttributeList atl = c->getAttributeList(); + for (UMLAttribute *at = atl.first(); at ; at = atl.next()) + { + if (at->getVisibility() == Uml::Visibility::Protected) + { + as << m_indentation << "ASSetPropFlags (this, \"" << cleanName(at->getName()) << "\", 1);" << m_endl; + } + } + } + + UMLOperationList opList(c->getOpList()); + for (UMLOperation *op = opList.first(); op; op = opList.next()) + { + if (op->getVisibility() == Uml::Visibility::Protected) + { + as << m_indentation << "ASSetPropFlags (this, \"" << cleanName(op->getName()) << "\", 1);" << m_endl; + } + } + as << m_endl; + as << m_indentation << "/**Private: */" << m_endl; + if (isClass) { + UMLAttributeList atl = c->getAttributeList(); + for (UMLAttribute *at = atl.first(); at; at = atl.next()) + { + if (at->getVisibility() == Uml::Visibility::Private) + { + as << m_indentation << "ASSetPropFlags (this, \"" << cleanName(at->getName()) << "\", 7);" << m_endl; + } + } + } + + for (UMLOperation *op = opList.first(); op; op = opList.next()) + { + if (op->getVisibility() == Uml::Visibility::Protected) + { + as << m_indentation << "ASSetPropFlags (this, \"" << cleanName(op->getName()) << "\", 7);" << m_endl; + } + } + as << "}" << m_endl; + + as << m_endl; + + //operations + UMLOperationList ops(c->getOpList()); + writeOperations(classname, &ops, as); + + as << m_endl; + + //finish file + + //close files and notfiy we are done + fileas.close(); + emit codeGenerated(c, true); +} + +//////////////////////////////////////////////////////////////////////////////////// +// Helper Methods + + +void ASWriter::writeAssociation(QString& classname, UMLAssociationList& assocList , QTextStream &as ) +{ + for(UMLAssociation *a = assocList.first(); a; a = assocList.next()) + { + // association side + Uml::Role_Type role = a->getObject(Uml::A)->getName() == classname ? Uml::B:Uml::A; + + QString roleName(cleanName(a->getRoleName(role))); + + if (!roleName.isEmpty()) { + + // association doc + if (forceDoc() || !a->getDoc().isEmpty()) { + as << m_indentation << "/**" << m_endl + << formatDoc(a->getDoc(), m_indentation + " * ") + << m_indentation << " */" << m_endl; + } + + // role doc + if (forceDoc() || !a->getRoleDoc(role).isEmpty()) { + as << m_indentation << "/**" << m_endl + << formatDoc(a->getRoleDoc(role), m_indentation + " * ") + << m_indentation << " */" << m_endl; + } + + bool okCvt; + int nMulti = a->getMulti(role).toInt(&okCvt,10); + bool isNotMulti = a->getMulti(role).isEmpty() || (okCvt && nMulti == 1); + + QString typeName(cleanName(a->getObject(role)->getName())); + + if (isNotMulti) + as << m_indentation << "this.m_" << roleName << " = new " << typeName << "();" << m_endl; + else + as << m_indentation << "this.m_" << roleName << " = new Array();" << m_endl; + + // role visibility + if (a->getVisibility(role) == Uml::Visibility::Private) + { + as << m_indentation << "ASSetPropFlags (this, \"m_" << roleName << "\", 7);" << m_endl; + } + else if (a->getVisibility(role)== Uml::Visibility::Protected) + { + as << m_indentation << "ASSetPropFlags (this, \"m_" << roleName << "\", 1);" << m_endl; + } + } + } +} + +void ASWriter::writeOperations(QString classname, UMLOperationList *opList, QTextStream &as) +{ + UMLOperation *op; + UMLAttributeList atl; + UMLAttribute *at; + + for(op = opList->first(); op; op = opList->next()) + { + atl = op -> getParmList(); + //write method doc if we have doc || if at least one of the params has doc + bool writeDoc = forceDoc() || !op->getDoc().isEmpty(); + for (at = atl.first(); at ; at = atl.next()) + writeDoc |= !at->getDoc().isEmpty(); + + if( writeDoc ) //write method documentation + { + as << "/**" << m_endl << formatDoc(op->getDoc()," * "); + + for (at = atl.first(); at; at = atl.next()) //write parameter documentation + { + if(forceDoc() || !at->getDoc().isEmpty()) + { + as << " * @param " + cleanName(at->getName())<<m_endl; + as << formatDoc(at->getDoc()," * "); + } + }//end for : write parameter documentation + as << " */" << m_endl; + }//end if : write method documentation + + as << classname << ".prototype." << cleanName(op->getName()) << " = function " << "("; + + int i= atl.count(); + int j=0; + for (at = atl.first(); at; at = atl.next(),j++) + { + as << cleanName(at->getName()) + << (!(at->getInitialValue().isEmpty()) ? (QString(" = ")+at->getInitialValue()) : QString("")) + << ((j < i-1)?", ":""); + } + as << ")" << m_endl << "{" << m_endl << + m_indentation << m_endl << "}" << m_endl; + as << m_endl << m_endl; + }//end for +} + +/** + * returns "ActionScript" + */ +Uml::Programming_Language ASWriter::getLanguage() { + return Uml::pl_ActionScript; +} + +const QStringList ASWriter::reservedKeywords() const { + + static QStringList keywords; + + if ( keywords.isEmpty() ) { + keywords << "abs" + << "acos" + << "add" + << "addListener" + << "addProperty" + << "align" + << "_alpha" + << "and" + << "appendChild" + << "apply" + << "Array" + << "asin" + << "atan" + << "atan2" + << "attachMovie" + << "attachSound" + << "attributes" + << "autoSize" + << "background" + << "backgroundColor" + << "BACKSPACE" + << "beginFill" + << "beginGradientFill" + << "blockIndent" + << "bold" + << "Boolean" + << "border" + << "borderColor" + << "bottomScroll" + << "break" + << "bullet" + << "call" + << "callee" + << "caller" + << "capabilities" + << "CAPSLOCK" + << "case" + << "ceil" + << "charAt" + << "charCodeAt" + << "childNodes" + << "chr" + << "clear" + << "clearInterval" + << "cloneNode" + << "close" + << "color" + << "Color" + << "comment" + << "concat" + << "connect" + << "contentType" + << "continue" + << "CONTROL" + << "cos" + << "createElement" + << "createEmptyMovieClip" + << "createTextField" + << "createTextNode" + << "_currentframe" + << "curveTo" + << "Date" + << "default" + << "delete" + << "DELETEKEY" + << "do" + << "docTypeDecl" + << "DOWN" + << "_droptarget" + << "duplicateMovieClip" + << "duration" + << "E" + << "else" + << "embedFonts" + << "enabled" + << "END" + << "endFill" + << "endinitclip" + << "ENTER" + << "eq" + << "escape" + << "ESCAPE" + << "eval" + << "evaluate" + << "exp" + << "false" + << "firstChild" + << "floor" + << "focusEnabled" + << "_focusrect" + << "font" + << "for" + << "_framesloaded" + << "fromCharCode" + << "fscommand" + << "function" + << "ge" + << "get" + << "getAscii" + << "getBeginIndex" + << "getBounds" + << "getBytesLoaded" + << "getBytesTotal" + << "getCaretIndex" + << "getCode" + << "getDate" + << "getDay" + << "getDepth" + << "getEndIndex" + << "getFocus" + << "getFontList" + << "getFullYear" + << "getHours" + << "getMilliseconds" + << "getMinutes" + << "getMonth" + << "getNewTextFormat" + << "getPan" + << "getProperty" + << "getRGB" + << "getSeconds" + << "getTextExtent" + << "getTextFormat" + << "getTime" + << "getTimer" + << "getTimezoneOffset" + << "getTransform" + << "getURL" + << "getUTCDate" + << "getUTCDay" + << "getUTCFullYear" + << "getUTCHours" + << "getUTCMilliseconds" + << "getUTCMinutes" + << "getUTCMonth" + << "getUTCSeconds" + << "getVersion" + << "getVolume" + << "getYear" + << "_global" + << "globalToLocal" + << "goto" + << "gotoAndPlay" + << "gotoAndStop" + << "gt" + << "hasAccessibility" + << "hasAudio" + << "hasAudioEncoder" + << "hasChildNodes" + << "hasMP3" + << "hasVideoEncoder" + << "height" + << "_height" + << "hide" + << "_highquality" + << "hitArea" + << "hitTest" + << "HOME" + << "hscroll" + << "html" + << "htmlText" + << "if" + << "ifFrameLoaded" + << "ignoreWhite" + << "in" + << "include" + << "indent" + << "indexOf" + << "initclip" + << "INSERT" + << "insertBefore" + << "install" + << "instanceof" + << "int" + << "isActive" + << "isDown" + << "isFinite" + << "isNaN" + << "isToggled" + << "italic" + << "join" + << "lastChild" + << "lastIndexOf" + << "le" + << "leading" + << "LEFT" + << "leftMargin" + << "length" + << "_level" + << "lineStyle" + << "lineTo" + << "list" + << "LN10" + << "LN2" + << "load" + << "loaded" + << "loadMovie" + << "loadMovieNum" + << "loadSound" + << "loadVariables" + << "loadVariablesNum" + << "LoadVars" + << "localToGlobal" + << "log" + << "LOG10E" + << "LOG2E" + << "max" + << "maxChars" + << "maxhscroll" + << "maxscroll" + << "MAX_VALUE" + << "mbchr" + << "mblength" + << "mbord" + << "mbsubstring" + << "method" + << "min" + << "MIN_VALUE" + << "moveTo" + << "multiline" + << "_name" + << "NaN" + << "ne" + << "NEGATIVE_INFINITY" + << "new" + << "newline" + << "nextFrame" + << "nextScene" + << "nextSibling" + << "nodeName" + << "nodeType" + << "nodeValue" + << "not" + << "null" + << "Number" + << "Object" + << "on" + << "onChanged" + << "onClipEvent" + << "onClose" + << "onConnect" + << "onData" + << "onDragOut" + << "onDragOver" + << "onEnterFrame" + << "onKeyDown" + << "onKeyUp" + << "onKillFocus" + << "onLoad" + << "onMouseDown" + << "onMouseMove" + << "onMouseUp" + << "onPress" + << "onRelease" + << "onReleaseOutside" + << "onResize" + << "onRollOut" + << "onRollOver" + << "onScroller" + << "onSetFocus" + << "onSoundComplete" + << "onUnload" + << "onUpdate" + << "onXML" + << "or" + << "ord" + << "_parent" + << "parentNode" + << "parseFloat" + << "parseInt" + << "parseXML" + << "password" + << "PGDN" + << "PGUP" + << "PI" + << "pixelAspectRatio" + << "play" + << "pop" + << "position" + << "POSITIVE_INFINITY" + << "pow" + << "prevFrame" + << "previousSibling" + << "prevScene" + << "print" + << "printAsBitmap" + << "printAsBitmapNum" + << "printNum" + << "__proto__" + << "prototype" + << "push" + << "_quality" + << "random" + << "registerClass" + << "removeListener" + << "removeMovieClip" + << "removeNode" + << "removeTextField" + << "replaceSel" + << "restrict" + << "return" + << "reverse" + << "RIGHT" + << "rightMargin" + << "_root" + << "_rotation" + << "round" + << "scaleMode" + << "screenColor" + << "screenDPI" + << "screenResolutionX" + << "screenResolutionY" + << "scroll" + << "selectable" + << "send" + << "sendAndLoad" + << "set" + << "setDate" + << "setFocus" + << "setFullYear" + << "setHours" + << "setInterval" + << "setMask" + << "setMilliseconds" + << "setMinutes" + << "setMonth" + << "setNewTextFormat" + << "setPan" + << "setProperty" + << "setRGB" + << "setSeconds" + << "setSelection" + << "setTextFormat" + << "setTime" + << "setTransform" + << "setUTCDate" + << "setUTCFullYear" + << "setUTCHours" + << "setUTCMilliseconds" + << "setUTCMinutes" + << "setUTCMonth" + << "setUTCSeconds" + << "setVolume" + << "setYear" + << "shift" + << "SHIFT" + << "show" + << "showMenu" + << "sin" + << "size" + << "slice" + << "sort" + << "sortOn" + << "Sound" + << "_soundbuftime" + << "SPACE" + << "splice" + << "split" + << "sqrt" + << "SQRT1_2" + << "SQRT2" + << "start" + << "startDrag" + << "status" + << "stop" + << "stopAllSounds" + << "stopDrag" + << "String" + << "substr" + << "substring" + << "super" + << "swapDepths" + << "switch" + << "TAB" + << "tabChildren" + << "tabEnabled" + << "tabIndex" + << "tabStops" + << "tan" + << "target" + << "_target" + << "targetPath" + << "tellTarget" + << "text" + << "textColor" + << "TextFormat" + << "textHeight" + << "textWidth" + << "this" + << "toggleHighQuality" + << "toLowerCase" + << "toString" + << "_totalframes" + << "toUpperCase" + << "trace" + << "trackAsMenu" + << "true" + << "type" + << "typeof" + << "undefined" + << "underline" + << "unescape" + << "uninstall" + << "unloadMovie" + << "unloadMovieNum" + << "unshift" + << "unwatch" + << "UP" + << "updateAfterEvent" + << "url" + << "_url" + << "useHandCursor" + << "UTC" + << "valueOf" + << "var" + << "variable" + << "_visible" + << "void" + << "watch" + << "while" + << "width" + << "_width" + << "with" + << "wordWrap" + << "_x" + << "XML" + << "xmlDecl" + << "XMLSocket" + << "_xmouse" + << "_xscale" + << "_y" + << "_ymouse"; + } + + return keywords; +} + +#include "aswriter.moc" diff --git a/umbrello/umbrello/codegenerators/aswriter.h b/umbrello/umbrello/codegenerators/aswriter.h new file mode 100644 index 00000000..51a4a922 --- /dev/null +++ b/umbrello/umbrello/codegenerators/aswriter.h @@ -0,0 +1,80 @@ +/*************************************************************************** + aswriter.h - description + ------------------- + begin : Sat Feb 08 2003 + copyright : (C) 2003 by Alexander Blum + email : blum@kewbee.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef ASWRITER_H +#define ASWRITER_H + +#include "simplecodegenerator.h" +#include "../umloperationlist.h" +#include "../umlassociationlist.h" + +/** + * class ASWriter is a ActionScript code generator for UMLClassifier objects + * Just call writeClass and feed it a UMLClassifier; + */ +class ASWriter : public SimpleCodeGenerator { + Q_OBJECT +public: + + ASWriter(); + virtual ~ASWriter(); + + /** + * call this method to generate Actionscript code for a UMLClassifier + * @param c the class you want to generate code for. + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "ActionScript" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + + +private: + + /** + * we do not want to write the comment "Private methods" twice + */ + bool bPrivateSectionCommentIsWritten; + + /** + * write a list of class operations + * + * @param classname the name of the class + * @param opList the list of operations + * @param as output stream for the AS file + */ + void writeOperations(QString classname, UMLOperationList *opList, QTextStream &as); + + /** + * write a list of associations + * + * @param classname the name of the class + * @param assocList the list of associations + * @param as output stream for the AS file + */ + void writeAssociation(QString& classname, UMLAssociationList& assoclist , QTextStream &as); + +}; + +#endif //ASWRITER diff --git a/umbrello/umbrello/codegenerators/classifierinfo.cpp b/umbrello/umbrello/codegenerators/classifierinfo.cpp new file mode 100644 index 00000000..690238cf --- /dev/null +++ b/umbrello/umbrello/codegenerators/classifierinfo.cpp @@ -0,0 +1,140 @@ +/*************************************************************************** + * * + * 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) 2003 Brian Thomas brian.thomas@gsfc.nasa.gov * + * (C) 2004-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + + +#include "classifierinfo.h" + +#include "../classifier.h" +#include "../operation.h" + +ClassifierInfo::ClassifierInfo( UMLClassifier *classifier) +{ + classifier_ = classifier; + + // set default class, file names + className = classifier->getName(); + fileName = classifier->getName().lower(); + + // determine up-front what we are dealing with + isInterface = classifier->isInterface(); + + // sort attributes by Scope + if(!isInterface) { + UMLAttributeList atl = classifier->getAttributeList(); + for(UMLAttribute *at=atl.first(); at ; at=atl.next()) { + switch(at->getVisibility()) + { + case Uml::Visibility::Public: + if(at->getStatic()) + static_atpub.append(at); + else + atpub.append(at); + break; + case Uml::Visibility::Protected: + if(at->getStatic()) + static_atprot.append(at); + else + atprot.append(at); + break; + case Uml::Visibility::Private: + case Uml::Visibility::Implementation: + if(at->getStatic()) + static_atpriv.append(at); + else + atpriv.append(at); + break; + } + } + } + + // inheritance issues + superclasses = classifier->getSuperClasses(); // list of what we inherit from + + subclasses = classifier->getSubClasses(); // list of what inherits from us + + // another preparation, determine what we have + plainAssociations = classifier->getSpecificAssocs(Uml::at_Association); // BAD! only way to get "general" associations. + + uniAssociations = classifier->getUniAssociationToBeImplemented(); + + aggregations = classifier->getAggregations(); + + compositions = classifier->getCompositions(); + + // set some summary information about the classifier now + hasAssociations = plainAssociations.count() > 0 || aggregations.count() > 0 || compositions.count() > 0 || uniAssociations.count() > 0; + hasAttributes = atpub.count() > 0 || atprot.count() > 0 || atpriv.count() > 0 + || static_atpub.count() > 0 + || static_atprot.count() > 0 + || static_atpriv.count() > 0; + + hasStaticAttributes = static_atpub.count() > 0 + || static_atprot.count() > 0 + || static_atpriv.count() > 0; + + hasAccessorMethods = hasAttributes || hasAssociations; + + hasOperationMethods = classifier->getOpList().last() ? true : false; + + hasMethods = hasOperationMethods || hasAccessorMethods; + + // 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 (I guess that's better than the other way around) + hasVectorFields = hasAssociations ? true : false; +} + +ClassifierInfo::~ClassifierInfo() { } + +UMLClassifierList ClassifierInfo::getPlainAssocChildClassifierList() +{ + return findAssocClassifierObjsInRoles(&plainAssociations); +} + +UMLClassifierList ClassifierInfo::getAggregateChildClassifierList() +{ + return findAssocClassifierObjsInRoles(&aggregations); +} + +UMLClassifierList ClassifierInfo::getCompositionChildClassifierList() +{ + return findAssocClassifierObjsInRoles(&compositions); +} + +UMLClassifierList ClassifierInfo::findAssocClassifierObjsInRoles (UMLAssociationList * list) +{ + UMLClassifierList classifiers; + + for (UMLAssociation *a = list->first(); a; a = list->next()) { + // DONT accept a classifier IF the association role is empty, by + // convention, that means to ignore the classifier on that end of + // the association. + // We also ignore classifiers which are the same as the current one + // (e.g. id matches), we only want the "other" classifiers + if (a->getObjectId(Uml::A) == classifier_->getID() && !a->getRoleName(Uml::B).isEmpty()) { + UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::B)); + if(c) + classifiers.append(c); + } else if (a->getObjectId(Uml::B) == classifier_->getID() && !a->getRoleName(Uml::A).isEmpty()) { + UMLClassifier *c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A)); + if(c) + classifiers.append(c); + } + } + + return classifiers; +} + +UMLAttributeList ClassifierInfo::getAttList() +{ + return classifier_->getAttributeList(); +} + diff --git a/umbrello/umbrello/codegenerators/classifierinfo.h b/umbrello/umbrello/codegenerators/classifierinfo.h new file mode 100644 index 00000000..53b7c02b --- /dev/null +++ b/umbrello/umbrello/codegenerators/classifierinfo.h @@ -0,0 +1,126 @@ +/*************************************************************************** + * * + * 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) 2003 Brian Thomas <brian.thomas@gsfc.nasa.gov> * + * copyright (C) 2004-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef CLASSIFIERINFO_H +#define CLASSIFIERINFO_H + +#include "../umldoc.h" +#include "../attribute.h" +#include "../association.h" +#include "../umlclassifierlist.h" +#include "../umlassociationlist.h" +#include "../umlattributelist.h" + +#include <qstring.h> + + +class UMLClassifier; + + +/** + * class ClassInfo is an object to hold summary information about a classifier + * in a convenient form for easy access by a code generator. + */ +class ClassifierInfo { +public: + + /** + * Constructor, initialises a couple of variables + */ + ClassifierInfo (UMLClassifier * classifier); + + /** + * Destructor, empty + */ + virtual ~ClassifierInfo(); + + // Fields + // + + /** + * Lists of attributes of this classifier (if a class) + * Sorted by scope. + */ + UMLAttributeList atpub; + UMLAttributeList atprot; + UMLAttributeList atpriv; + + /** + * Lists of static attributes of this classifier (if a class) + */ + UMLAttributeList static_atpub; + UMLAttributeList static_atprot; + UMLAttributeList static_atpriv; + + /** + * Lists of types of associations this classifier has + */ + UMLAssociationList plainAssociations; + UMLAssociationList uniAssociations; + UMLAssociationList aggregations; + UMLAssociationList compositions; + + /** + * what sub and super classifiers are related to this class + */ + UMLClassifierList superclasses; + UMLClassifierList subclasses; + + /** + * Various conditional information about our classifier. + */ + bool isInterface; // Whether or not this classifier is an interface. + bool hasAssociations; + bool hasAttributes; + bool hasStaticAttributes; + bool hasMethods; + bool hasAccessorMethods; + bool hasOperationMethods; + bool hasVectorFields; + + /** + * Class and File names + */ + QString className; + QString fileName; + + /** + * utility functions to allow easy determination of what classifiers + * are "owned" by the current one via named association type (e.g. + * plain, aggregate or compositions). + */ + UMLClassifierList getPlainAssocChildClassifierList(); + UMLClassifierList getAggregateChildClassifierList(); + UMLClassifierList getCompositionChildClassifierList(); + + /** + * Utility method to obtain list of attributes, if they exist, for + * the current classfier. + */ + UMLAttributeList getAttList(); + +private: + + UMLClassifier* classifier_; + + /** + * Utility method called by "get*ChildClassfierList()" methods. It basically + * finds all the classifiers named in each association in the given association list + * which arent the current one. Usefull for finding which classifiers are "owned" by the + * current one via declared associations such as in aggregations/compositions. + */ + UMLClassifierList findAssocClassifierObjsInRoles (UMLAssociationList * list); + +}; + +#endif // CLASSIFIERINFO_H + diff --git a/umbrello/umbrello/codegenerators/codegen_utils.cpp b/umbrello/umbrello/codegenerators/codegen_utils.cpp new file mode 100644 index 00000000..cb94cdde --- /dev/null +++ b/umbrello/umbrello/codegenerators/codegen_utils.cpp @@ -0,0 +1,413 @@ +/*************************************************************************** + * * + * 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> * + ***************************************************************************/ + +// own header +#include "codegen_utils.h" +// app includes +#include "../uml.h" +#include "../umldoc.h" + +namespace Codegen_Utils { + +QStringList cppDatatypes() { + QStringList l; + l.append("int"); + l.append("char"); + l.append("bool"); + l.append("float"); + l.append("double"); + l.append("short"); + l.append("long"); + l.append("unsigned int"); + l.append("unsigned short"); + l.append("unsigned long"); + l.append("string"); + return l; +} + +const QStringList reservedCppKeywords() { + + static QStringList keywords; + + if (keywords.isEmpty()) { + keywords.append( "and" ); + keywords.append( "and_eq" ); + keywords.append( "__asm__" ); + keywords.append( "asm" ); + keywords.append( "__attribute__" ); + keywords.append( "auto" ); + keywords.append( "bitand" ); + keywords.append( "bitor" ); + keywords.append( "bool" ); + keywords.append( "break" ); + keywords.append( "BUFSIZ" ); + keywords.append( "case" ); + keywords.append( "catch" ); + keywords.append( "char" ); + keywords.append( "CHAR_BIT" ); + keywords.append( "CHAR_MAX" ); + keywords.append( "CHAR_MIN" ); + keywords.append( "class" ); + keywords.append( "CLOCKS_PER_SEC" ); + keywords.append( "clock_t" ); + keywords.append( "compl" ); + keywords.append( "__complex__" ); + keywords.append( "complex" ); + keywords.append( "const" ); + keywords.append( "const_cast" ); + keywords.append( "continue" ); + keywords.append( "__DATE__" ); + keywords.append( "DBL_DIG" ); + keywords.append( "DBL_EPSILON" ); + keywords.append( "DBL_MANT_DIG" ); + keywords.append( "DBL_MAX" ); + keywords.append( "DBL_MAX_10_EXP" ); + keywords.append( "DBL_MAX_EXP" ); + keywords.append( "DBL_MIN" ); + keywords.append( "DBL_MIN_10_EXP" ); + keywords.append( "DBL_MIN_EXP" ); + keywords.append( "default" ); + keywords.append( "delete" ); + keywords.append( "DIR" ); + keywords.append( "div_t" ); + keywords.append( "do" ); + keywords.append( "double" ); + keywords.append( "dynamic_cast" ); + keywords.append( "E2BIG" ); + keywords.append( "EACCES" ); + keywords.append( "EAGAIN" ); + keywords.append( "EBADF" ); + keywords.append( "EBADMSG" ); + keywords.append( "EBUSY" ); + keywords.append( "ECANCELED" ); + keywords.append( "ECHILD" ); + keywords.append( "EDEADLK" ); + keywords.append( "EDOM" ); + keywords.append( "EEXIST" ); + keywords.append( "EFAULT" ); + keywords.append( "EFBIG" ); + keywords.append( "EILSEQ" ); + keywords.append( "EINPROGRESS" ); + keywords.append( "EINTR" ); + keywords.append( "EINVAL" ); + keywords.append( "EIO" ); + keywords.append( "EISDIR" ); + keywords.append( "else" ); + keywords.append( "EMFILE" ); + keywords.append( "EMLINK" ); + keywords.append( "EMSGSIZE" ); + keywords.append( "ENAMETOOLONG" ); + keywords.append( "ENFILE" ); + keywords.append( "ENODEV" ); + keywords.append( "ENOENT" ); + keywords.append( "ENOEXEC" ); + keywords.append( "ENOLCK" ); + keywords.append( "ENOMEM" ); + keywords.append( "ENOSPC" ); + keywords.append( "ENOSYS" ); + keywords.append( "ENOTDIR" ); + keywords.append( "ENOTEMPTY" ); + keywords.append( "ENOTSUP" ); + keywords.append( "ENOTTY" ); + keywords.append( "enum" ); + keywords.append( "ENXIO" ); + keywords.append( "EOF" ); + keywords.append( "EPERM" ); + keywords.append( "EPIPE" ); + keywords.append( "ERANGE" ); + keywords.append( "EROFS" ); + keywords.append( "ESPIPE" ); + keywords.append( "ESRCH" ); + keywords.append( "ETIMEDOUT" ); + keywords.append( "EXDEV" ); + keywords.append( "EXIT_FAILURE" ); + keywords.append( "EXIT_SUCCESS" ); + keywords.append( "explicit" ); + keywords.append( "export" ); + keywords.append( "extern" ); + keywords.append( "false" ); + keywords.append( "__FILE__" ); + keywords.append( "FILE" ); + keywords.append( "FILENAME_MAX" ); + keywords.append( "float" ); + keywords.append( "FLT_DIG" ); + keywords.append( "FLT_EPSILON" ); + keywords.append( "FLT_MANT_DIG" ); + keywords.append( "FLT_MAX" ); + keywords.append( "FLT_MAX_10_EXP" ); + keywords.append( "FLT_MAX_EXP" ); + keywords.append( "FLT_MIN" ); + keywords.append( "FLT_MIN_10_EXP" ); + keywords.append( "FLT_MIN_EXP" ); + keywords.append( "FLT_RADIX" ); + keywords.append( "FLT_ROUNDS" ); + keywords.append( "FOPEN_MAX" ); + keywords.append( "for" ); + keywords.append( "fpos_t" ); + keywords.append( "friend" ); + keywords.append( "__FUNCTION__" ); + keywords.append( "__GNUC__" ); + keywords.append( "goto" ); + keywords.append( "HUGE_VAL" ); + keywords.append( "if" ); + keywords.append( "__imag__" ); + keywords.append( "inline" ); + keywords.append( "int" ); + keywords.append( "INT16_MAX" ); + keywords.append( "INT16_MIN" ); + keywords.append( "int16_t" ); + keywords.append( "INT32_MAX" ); + keywords.append( "INT32_MIN" ); + keywords.append( "int32_t" ); + keywords.append( "INT64_MAX" ); + keywords.append( "INT64_MIN" ); + keywords.append( "int64_t" ); + keywords.append( "INT8_MAX" ); + keywords.append( "INT8_MIN" ); + keywords.append( "int8_t" ); + keywords.append( "INT_FAST16_MAX" ); + keywords.append( "INT_FAST16_MIN" ); + keywords.append( "int_fast16_t" ); + keywords.append( "INT_FAST32_MAX" ); + keywords.append( "INT_FAST32_MIN" ); + keywords.append( "int_fast32_t" ); + keywords.append( "INT_FAST64_MAX" ); + keywords.append( "INT_FAST64_MIN" ); + keywords.append( "int_fast64_t" ); + keywords.append( "INT_FAST8_MAX" ); + keywords.append( "INT_FAST8_MIN" ); + keywords.append( "int_fast8_t" ); + keywords.append( "INT_LEAST16_MAX" ); + keywords.append( "INT_LEAST16_MIN" ); + keywords.append( "int_least16_t" ); + keywords.append( "INT_LEAST32_MAX" ); + keywords.append( "INT_LEAST32_MIN" ); + keywords.append( "int_least32_t" ); + keywords.append( "INT_LEAST64_MAX" ); + keywords.append( "INT_LEAST64_MIN" ); + keywords.append( "int_least64_t" ); + keywords.append( "INT_LEAST8_MAX" ); + keywords.append( "INT_LEAST8_MIN" ); + keywords.append( "int_least8_t" ); + keywords.append( "INT_MAX" ); + keywords.append( "INTMAX_MAX" ); + keywords.append( "INTMAX_MIN" ); + keywords.append( "intmax_t" ); + keywords.append( "INT_MIN" ); + keywords.append( "INTPTR_MAX" ); + keywords.append( "INTPTR_MIN" ); + keywords.append( "intptr_t" ); + keywords.append( "_IOFBF" ); + keywords.append( "_IOLBF" ); + keywords.append( "_IONBF" ); + keywords.append( "jmp_buf" ); + keywords.append( "__label__" ); + keywords.append( "LC_ALL" ); + keywords.append( "LC_COLLATE" ); + keywords.append( "LC_CTYPE" ); + keywords.append( "LC_MONETARY" ); + keywords.append( "LC_NUMERIC" ); + keywords.append( "LC_TIME" ); + keywords.append( "LDBL_DIG" ); + keywords.append( "LDBL_EPSILON" ); + keywords.append( "LDBL_MANT_DIG" ); + keywords.append( "LDBL_MAX" ); + keywords.append( "LDBL_MAX_10_EXP" ); + keywords.append( "LDBL_MAX_EXP" ); + keywords.append( "LDBL_MIN" ); + keywords.append( "LDBL_MIN_10_EXP" ); + keywords.append( "LDBL_MIN_EXP" ); + keywords.append( "ldiv_t" ); + keywords.append( "__LINE__" ); + keywords.append( "LLONG_MAX" ); + keywords.append( "long" ); + keywords.append( "LONG_MAX" ); + keywords.append( "LONG_MIN" ); + keywords.append( "L_tmpnam" ); + keywords.append( "M_1_PI" ); + keywords.append( "M_2_PI" ); + keywords.append( "M_2_SQRTPI" ); + keywords.append( "MB_CUR_MAX" ); + keywords.append( "MB_LEN_MAX" ); + keywords.append( "mbstate_t" ); + keywords.append( "M_E" ); + keywords.append( "M_LN10" ); + keywords.append( "M_LN2" ); + keywords.append( "M_LOG10E" ); + keywords.append( "M_LOG2E" ); + keywords.append( "M_PI" ); + keywords.append( "M_PI_2" ); + keywords.append( "M_PI_4" ); + keywords.append( "M_SQRT1_2" ); + keywords.append( "M_SQRT2" ); + keywords.append( "mutable" ); + keywords.append( "namespace" ); + keywords.append( "new" ); + keywords.append( "not" ); + keywords.append( "not_eq" ); + keywords.append( "NPOS" ); + keywords.append( "NULL" ); + keywords.append( "operator" ); + keywords.append( "or" ); + keywords.append( "or_eq" ); + keywords.append( "__PRETTY_FUNCTION__" ); + keywords.append( "private" ); + keywords.append( "protected" ); + keywords.append( "PTRDIFF_MAX" ); + keywords.append( "PTRDIFF_MIN" ); + keywords.append( "ptrdiff_t" ); + keywords.append( "public" ); + keywords.append( "RAND_MAX" ); + keywords.append( "__real__" ); + keywords.append( "register" ); + keywords.append( "reinterpret_cast" ); + keywords.append( "restrict" ); + keywords.append( "return" ); + keywords.append( "SCHAR_MAX" ); + keywords.append( "SCHAR_MIN" ); + keywords.append( "SEEK_CUR" ); + keywords.append( "SEEK_END" ); + keywords.append( "SEEK_SET" ); + keywords.append( "short" ); + keywords.append( "SHRT_MAX" ); + keywords.append( "SHRT_MIN" ); + keywords.append( "SIGABRT" ); + keywords.append( "SIGALRM" ); + keywords.append( "SIG_ATOMIC_MAX" ); + keywords.append( "SIG_ATOMIC_MIN" ); + keywords.append( "sig_atomic_t" ); + keywords.append( "SIGCHLD" ); + keywords.append( "SIGCONT" ); + keywords.append( "SIG_DFL" ); + keywords.append( "SIG_ERR" ); + keywords.append( "SIGFPE" ); + keywords.append( "SIGHUP" ); + keywords.append( "SIG_IGN" ); + keywords.append( "SIGILL" ); + keywords.append( "SIGINT" ); + keywords.append( "SIGKILL" ); + keywords.append( "signed" ); + keywords.append( "SIGPIPE" ); + keywords.append( "SIGQUIT" ); + keywords.append( "SIGSEGV" ); + keywords.append( "SIGSTOP" ); + keywords.append( "SIGTERM" ); + keywords.append( "SIGTRAP" ); + keywords.append( "SIGTSTP" ); + keywords.append( "SIGTTIN" ); + keywords.append( "SIGTTOU" ); + keywords.append( "SIGUSR1" ); + keywords.append( "SIGUSR2" ); + keywords.append( "SINT_MAX" ); + keywords.append( "SINT_MIN" ); + keywords.append( "SIZE_MAX" ); + keywords.append( "sizeof" ); + keywords.append( "size_t" ); + keywords.append( "SLONG_MAX" ); + keywords.append( "SLONG_MIN" ); + keywords.append( "SSHRT_MAX" ); + keywords.append( "SSHRT_MIN" ); + keywords.append( "ssize_t" ); + keywords.append( "static" ); + keywords.append( "static_cast" ); + keywords.append( "__STDC__" ); + keywords.append( "__STDC_VERSION__" ); + keywords.append( "stderr" ); + keywords.append( "stdin" ); + keywords.append( "stdout" ); + keywords.append( "struct" ); + keywords.append( "switch" ); + keywords.append( "template" ); + keywords.append( "this" ); + keywords.append( "throw" ); + keywords.append( "__TIME__" ); + keywords.append( "time_t" ); + keywords.append( "TMP_MAX" ); + keywords.append( "true" ); + keywords.append( "try" ); + keywords.append( "typedef" ); + keywords.append( "typeid" ); + keywords.append( "typename" ); + keywords.append( "typeof" ); + keywords.append( "UCHAR_MAX" ); + keywords.append( "UINT16_MAX" ); + keywords.append( "uint16_t" ); + keywords.append( "UINT32_MAX" ); + keywords.append( "uint32_t" ); + keywords.append( "UINT64_MAX" ); + keywords.append( "uint64_t" ); + keywords.append( "UINT8_MAX" ); + keywords.append( "uint8_t" ); + keywords.append( "UINT_FAST16_MAX" ); + keywords.append( "uint_fast16_t" ); + keywords.append( "UINT_FAST32_MAX" ); + keywords.append( "uint_fast32_t" ); + keywords.append( "UINT_FAST64_MAX" ); + keywords.append( "uint_fast64_t" ); + keywords.append( "UINT_FAST8_MAX" ); + keywords.append( "uint_fast8_t" ); + keywords.append( "UINT_LEAST16_MAX" ); + keywords.append( "uint_least16_t" ); + keywords.append( "UINT_LEAST32_MAX" ); + keywords.append( "uint_least32_t" ); + keywords.append( "UINT_LEAST64_MAX" ); + keywords.append( "uint_least64_t" ); + keywords.append( "UINT_LEAST8_MAX" ); + keywords.append( "uint_least8_t" ); + keywords.append( "UINT_MAX" ); + keywords.append( "UINTMAX_MAX" ); + keywords.append( "uintmax_t" ); + keywords.append( "UINTPTR_MAX" ); + keywords.append( "uintptr_t" ); + keywords.append( "ULLONG_MAX" ); + keywords.append( "ULONG_MAX" ); + keywords.append( "union" ); + keywords.append( "unsigned" ); + keywords.append( "USHRT_MAX" ); + keywords.append( "using" ); + keywords.append( "va_list" ); + keywords.append( "virtual" ); + keywords.append( "void" ); + keywords.append( "__volatile__" ); + keywords.append( "volatile" ); + keywords.append( "WCHAR_MAX" ); + keywords.append( "WCHAR_MIN" ); + keywords.append( "wchar_t" ); + keywords.append( "wctrans_t" ); + keywords.append( "wctype_t" ); + keywords.append( "WEOF" ); + keywords.append( "while" ); + keywords.append( "WINT_MAX" ); + keywords.append( "WINT_MIN" ); + keywords.append( "wint_t" ); + keywords.append( "xor" ); + keywords.append( "xor_eq" ); + } + + return keywords; +} + +void createCppStereotypes() { + UMLDoc *umldoc = UMLApp::app()->getDocument(); + umldoc->findOrCreateStereotype("constructor"); + // declares an operation as friend + umldoc->findOrCreateStereotype("friend"); + // to use in methods that aren't abstract + umldoc->findOrCreateStereotype("virtual"); +} + +QString capitalizeFirstLetter(const QString &string) { + QChar firstChar = string.at(0); + return firstChar.upper() + string.mid(1); +} + +} // end namespace Codegen_Utils + diff --git a/umbrello/umbrello/codegenerators/codegen_utils.h b/umbrello/umbrello/codegenerators/codegen_utils.h new file mode 100644 index 00000000..aaa7d117 --- /dev/null +++ b/umbrello/umbrello/codegenerators/codegen_utils.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * * + * 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> * + ***************************************************************************/ + +#ifndef CODEGEN_UTILS_H +#define CODEGEN_UTILS_H + +#include <qstringlist.h> + +namespace Codegen_Utils { + +/** + * Return list of C++ datatypes + */ +QStringList cppDatatypes(); + +/** + * Get list of C++ reserved keywords + */ +const QStringList reservedCppKeywords(); + +/** + * Add C++ stereotypes + */ +void createCppStereotypes(); + +/** + * Return the input string with the first letter capitalized. + */ +QString capitalizeFirstLetter(const QString &string); + +} + +#endif // CODEGEN_UTILS_H + diff --git a/umbrello/umbrello/codegenerators/codegenfactory.cpp b/umbrello/umbrello/codegenerators/codegenfactory.cpp new file mode 100644 index 00000000..00401653 --- /dev/null +++ b/umbrello/umbrello/codegenerators/codegenfactory.cpp @@ -0,0 +1,360 @@ +/*************************************************************************** + begin : Mon Jun 17 2002 + copyright : (C) 2002 Luis De la Parra Blum <luis@delaparra.org> + and Brian Thomas + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2003-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// own header +#include "codegenfactory.h" + +// qt/kde includes +#include <kdebug.h> + +// app includes +#include "../codegenerator.h" +#include "../umldoc.h" +#include "../uml.h" +#include "../optionstate.h" +#include "../operation.h" +#include "../attribute.h" +#include "../umlrole.h" + +#include "adawriter.h" +#include "cppwriter.h" +#include "csharpwriter.h" +#include "dwriter.h" +#include "idlwriter.h" +#include "javawriter.h" +#include "pascalwriter.h" +#include "perlwriter.h" +#include "phpwriter.h" +#include "php5writer.h" +#include "pythonwriter.h" +#include "rubywriter.h" +#include "sqlwriter.h" +#include "aswriter.h" +#include "jswriter.h" +#include "tclwriter.h" +#include "xmlschemawriter.h" + +// the new +#include "cppcodegenerator.h" +#include "javacodegenerator.h" +#include "rubycodegenerator.h" + +#include "cppheadercodedocument.h" +#include "cppsourcecodedocument.h" +#include "javaclassifiercodedocument.h" +#include "rubyclassifiercodedocument.h" +#include "javaantcodedocument.h" + +#include "cppheadercodeoperation.h" +#include "cppsourcecodeoperation.h" +#include "javacodeoperation.h" +#include "rubycodeoperation.h" + +#include "cppcodeclassfield.h" +#include "javacodeclassfield.h" +#include "rubycodeclassfield.h" + +#include "cppheadercodeaccessormethod.h" +#include "cppsourcecodeaccessormethod.h" +#include "javacodeaccessormethod.h" +#include "rubycodeaccessormethod.h" + +#include "cppheadercodeclassfielddeclarationblock.h" +#include "cppsourcecodeclassfielddeclarationblock.h" +#include "javacodeclassfielddeclarationblock.h" +#include "rubycodeclassfielddeclarationblock.h" + +#include "cppcodedocumentation.h" +#include "javacodecomment.h" +#include "rubycodecomment.h" +#include "xmlcodecomment.h" + +#include "cppcodegenerationpolicy.h" +#include "javacodegenerationpolicy.h" +#include "rubycodegenerationpolicy.h" + +namespace CodeGenFactory { + +CodeGenerator* createObject(Uml::Programming_Language pl) { + CodeGenerator* obj = 0; + Settings::OptionState optionState = Settings::getOptionState(); + UMLApp::app()->setPolicyExt(NULL); + switch (pl) { + case Uml::pl_Ada: + obj = new AdaWriter(); + break; + case Uml::pl_ActionScript: + obj = new ASWriter(); + break; + case Uml::pl_Cpp: + if (optionState.generalState.newcodegen) { + obj = new CPPCodeGenerator(); + obj->connect_newcodegen_slots(); + } else { + obj = new CppWriter(); + } + { + CPPCodeGenerationPolicy *p = + new CPPCodeGenerationPolicy(UMLApp::app()->getConfig()); + UMLApp::app()->setPolicyExt(p); + } + break; + case Uml::pl_CSharp: + obj = new CSharpWriter(); + break; + case Uml::pl_D: + obj = new DWriter(); + break; + case Uml::pl_IDL: + obj = new IDLWriter(); + break; + case Uml::pl_Java: + if (optionState.generalState.newcodegen) { + obj = new JavaCodeGenerator(); + obj->connect_newcodegen_slots(); + JavaCodeGenerationPolicy *p = + new JavaCodeGenerationPolicy(UMLApp::app()->getConfig()); + UMLApp::app()->setPolicyExt(p); + } else + obj = new JavaWriter(); + break; + case Uml::pl_JavaScript: + obj = new JSWriter(); + break; + case Uml::pl_PHP: + obj = new PhpWriter(); + break; + case Uml::pl_PHP5: + obj = new Php5Writer(); + break; + case Uml::pl_Pascal: + obj = new PascalWriter(); + break; + case Uml::pl_Perl: + obj = new PerlWriter(); + break; + case Uml::pl_Python: + obj = new PythonWriter(); + break; + case Uml::pl_Ruby: + if (optionState.generalState.newcodegen) { + obj = new RubyCodeGenerator(); + obj->connect_newcodegen_slots(); + RubyCodeGenerationPolicy *p = + new RubyCodeGenerationPolicy(UMLApp::app()->getConfig()); + UMLApp::app()->setPolicyExt(p); + } else + obj = new RubyWriter(); + break; + case Uml::pl_SQL: + obj = new SQLWriter(); + break; + case Uml::pl_Tcl: + obj = new TclWriter(); + break; + case Uml::pl_XMLSchema: + obj = new XMLSchemaWriter(); + break; + default: + kWarning() << "cannot create object of type " << pl + << ". Type unknown" << endl; + break; + } + if (obj) + obj->initFromParentDocument(); + return obj; +} + +CodeDocument * newClassifierCodeDocument (UMLClassifier * c) +{ + Settings::OptionState optionState = Settings::getOptionState(); + if (!optionState.generalState.newcodegen) + return NULL; + ClassifierCodeDocument *retval = NULL; + switch (UMLApp::app()->getActiveLanguage()) { + case Uml::pl_Cpp: + retval = new CPPSourceCodeDocument(c); + break; + case Uml::pl_Java: + retval = new JavaClassifierCodeDocument(c); + break; + case Uml::pl_Ruby: + retval = new RubyClassifierCodeDocument(c); + break; + default: + break; + } + retval->initCodeClassFields(); + retval->synchronize(); + return retval; +} + +CodeOperation *newCodeOperation(ClassifierCodeDocument *ccd, UMLOperation * op) { + CodeOperation *retval = NULL; + switch (UMLApp::app()->getActiveLanguage()) { + case Uml::pl_Cpp: + { + CPPHeaderCodeDocument *hcd = dynamic_cast<CPPHeaderCodeDocument*>(ccd); + if (hcd) + return new CPPHeaderCodeOperation(hcd, op); + CPPSourceCodeDocument *scd = dynamic_cast<CPPSourceCodeDocument*>(ccd); + if (scd) + return new CPPSourceCodeOperation(scd, op); + } + break; + case Uml::pl_Java: + retval = new JavaCodeOperation(dynamic_cast<JavaClassifierCodeDocument*>(ccd), op); + break; + case Uml::pl_Ruby: + retval = new RubyCodeOperation(dynamic_cast<RubyClassifierCodeDocument*>(ccd), op); + break; + default: + break; + } + return retval; +} + + +CodeClassField * newCodeClassField(ClassifierCodeDocument *ccd, UMLAttribute *at) { + CodeClassField *retval = NULL; + switch (UMLApp::app()->getActiveLanguage()) { + case Uml::pl_Cpp: + retval = new CPPCodeClassField(ccd, at); + break; + case Uml::pl_Java: + retval = new JavaCodeClassField(ccd, at); + break; + case Uml::pl_Ruby: + retval = new RubyCodeClassField(ccd, at); + break; + default: + break; + } + retval->finishInitialization(); + return retval; +} + +CodeClassField * newCodeClassField(ClassifierCodeDocument *ccd, UMLRole *role) { + CodeClassField *retval = NULL; + switch (UMLApp::app()->getActiveLanguage()) { + case Uml::pl_Cpp: + retval = new CPPCodeClassField(ccd, role); + break; + case Uml::pl_Java: + retval = new JavaCodeClassField(ccd, role); + break; + case Uml::pl_Ruby: + retval = new RubyCodeClassField(ccd, role); + break; + default: + break; + } + return retval; +} + +CodeAccessorMethod * newCodeAccessorMethod(ClassifierCodeDocument *ccd, + CodeClassField *cf, + CodeAccessorMethod::AccessorType type) { + CodeAccessorMethod *retval = NULL; + switch (UMLApp::app()->getActiveLanguage()) { + case Uml::pl_Cpp: + { + CPPHeaderCodeDocument *hcd = dynamic_cast<CPPHeaderCodeDocument*>(ccd); + if (hcd) { + CPPHeaderCodeAccessorMethod *chcam = new CPPHeaderCodeAccessorMethod(cf, type); + chcam->update(); + retval = chcam; + } else { + CPPSourceCodeAccessorMethod *cscam = new CPPSourceCodeAccessorMethod(cf, type); + cscam->update(); + retval = cscam; + } + } + break; + case Uml::pl_Java: + { + JavaCodeAccessorMethod *jcam = new JavaCodeAccessorMethod(cf, type); + jcam->update(); + retval = jcam; + retval->setOverallIndentationLevel(1); + } + break; + case Uml::pl_Ruby: + { + RubyCodeAccessorMethod *rcam = new RubyCodeAccessorMethod(cf, type); + rcam->update(); + retval = rcam; + retval->setOverallIndentationLevel(1); + } + break; + default: + break; + } + return retval; +} + +CodeClassFieldDeclarationBlock * newDeclarationCodeBlock (ClassifierCodeDocument *cd, + CodeClassField * cf) { + CodeClassFieldDeclarationBlock *retval = NULL; + switch (UMLApp::app()->getActiveLanguage()) { + case Uml::pl_Cpp: + { + CPPHeaderCodeDocument *hcd = dynamic_cast<CPPHeaderCodeDocument*>(cd); + if (hcd) + return new CPPHeaderCodeClassFieldDeclarationBlock(cf); + CPPSourceCodeDocument *scd = dynamic_cast<CPPSourceCodeDocument*>(cd); + if (scd) + return new CPPSourceCodeClassFieldDeclarationBlock(cf); + } + break; + case Uml::pl_Java: + retval = new JavaCodeClassFieldDeclarationBlock(cf); + break; + case Uml::pl_Ruby: + retval = new RubyCodeClassFieldDeclarationBlock(cf); + break; + default: + break; + } + return retval; +} + +CodeComment * newCodeComment (CodeDocument *cd) { + switch (UMLApp::app()->getActiveLanguage()) { + case Uml::pl_Cpp: + if (dynamic_cast<CPPHeaderCodeDocument*>(cd) || + dynamic_cast<CPPSourceCodeDocument*>(cd)) + return new CPPCodeDocumentation(cd); + break; + case Uml::pl_Java: + if (dynamic_cast<JavaClassifierCodeDocument*>(cd)) + return new JavaCodeComment(cd); + break; + case Uml::pl_Ruby: + if (dynamic_cast<RubyClassifierCodeDocument*>(cd)) + return new RubyCodeComment(cd); + break; + default: + break; + } + if (dynamic_cast<JavaANTCodeDocument*>(cd)) + return new XMLCodeComment(cd); + return new CodeComment(cd); +} + +} // end namespace CodeGenFactory + diff --git a/umbrello/umbrello/codegenerators/codegenfactory.h b/umbrello/umbrello/codegenerators/codegenfactory.h new file mode 100644 index 00000000..27a0f293 --- /dev/null +++ b/umbrello/umbrello/codegenerators/codegenfactory.h @@ -0,0 +1,119 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef CODEGENFACTORY_H +#define CODEGENFACTORY_H + +#include "../umlnamespace.h" +#include "../codeaccessormethod.h" + +// fwd decls +class CodeGenerator; +class ClassifierCodeDocument; +class CodeOperation; +class CodeClassField; +class CodeClassFieldDeclarationBlock; +class UMLClassifier; +class UMLOperation; +class UMLAttribute; +class UMLRole; + +/** + * CodeGenFactory allows creating the available code generators as well + * as the auxiliary objects required for the advanced code generators. + * + * @author Jonathan Riddell + * @author Oliver Kellogg <okellogg@users.sourceforge.net> + * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org + */ +namespace CodeGenFactory { + + /** + * Create a code generator specific to the given language. + */ + CodeGenerator* createObject(Uml::Programming_Language pl); + + + /** + * Create a CodeOperation belonging to the given ClassifierCodeDocument. + * Only applies to the advanced generators. + * + * @param cd the parent ClassifierCodeDocument. + * @param op the related UMLOperation + * @return CodeOperation which is specific to the current language + */ + CodeOperation *newCodeOperation(ClassifierCodeDocument *cd, UMLOperation * op); + + /** + * Create an attribute CodeClassField belonging to the given + * ClassifierCodeDocument. + * Only applies to the advanced generators. + * + * @param cd the parent ClassifierCodeDocument + * @param at attribute which is parent of this class field + * @return CodeClassField which is specific to the current language + */ + CodeClassField * newCodeClassField (ClassifierCodeDocument *cd, UMLAttribute * at); + + /** + * Create an association role CodeClassField belonging to the given + * ClassifierCodeDocument. + * Only applies to the advanced generators. + * + * @param cd the parent ClassifierCodeDocument + * @param role association role which is parent of this class field + * @return CodeClassField which is specific to the current language + */ + CodeClassField * newCodeClassField(ClassifierCodeDocument *cd, UMLRole *role); + + /** + * Create a CodeAccessorMethod object belonging to the given ClassifierCodeDocument. + * Only applies to the advanced generators. + * + * @param cd the parent ClassifierCodeDocument + * @param cf CodeClassField which is parent of this object + * @param type CodeAccessorMethod::AccessorType to create + * + * @return CodeAccessorMethod which is specific to the current language + */ + CodeAccessorMethod * newCodeAccessorMethod(ClassifierCodeDocument *cd, + CodeClassField *cf, + CodeAccessorMethod::AccessorType type); + + /** + * Create a CodeClassFieldDeclarationBlock object belonging to the given + * ClassifierCodeDocument. + * Only applies to the advanced generators. + * + * @param cd the parent ClassifierCodeDocument + * @param cf CodeClassField which is parent of this object + * + * @return CodeClassFieldDeclarationBlock which is specific to the current language + */ + CodeClassFieldDeclarationBlock * newDeclarationCodeBlock (ClassifierCodeDocument *cd, + CodeClassField * cf); + + /** + * Create a new CodeComment object belonging to the given CodeDocument. + * Only applies to the advanced generators. + * + * @param cd the parent CodeDocument + * @return CodeBlockWithComments + */ + CodeComment * newCodeComment (CodeDocument *cd); + + /** + * Currently unused (for possible future use) + */ + CodeDocument * newClassifierCodeDocument (UMLClassifier * classifier); +} + +#endif //CODEGENFACTORY_H diff --git a/umbrello/umbrello/codegenerators/codegenpolicyext.h b/umbrello/umbrello/codegenerators/codegenpolicyext.h new file mode 100644 index 00000000..97ace9f2 --- /dev/null +++ b/umbrello/umbrello/codegenerators/codegenpolicyext.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * * + * 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) 2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef CODEGENPOLICYEXT_H +#define CODEGENPOLICYEXT_H + +#include <qobject.h> + +class QWidget; +class KConfig; +class CodeGenerationPolicyPage; + +/** + * Base class for programming language specific code generation policy extensions. + * Not to be confused with CodeGenerationPolicy which contains the programming + * language independent policies. + * + * @author Oliver Kellogg <okellogg@users.sourceforge.net> + * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org + */ + +class CodeGenPolicyExt : public QObject { +public: + CodeGenPolicyExt() {} + virtual ~CodeGenPolicyExt() {} + + /** + * Create a new dialog interface for this object. + * @return dialog object + */ + virtual CodeGenerationPolicyPage * createPage(QWidget *parent = 0, const char *name = 0) = 0; + + /** + * set the defaults from a config file for this code generator from the passed KConfig pointer. + */ + virtual void setDefaults(KConfig * config, bool emitUpdateSignal = true) = 0; + + /** + * write Default params to passed KConfig pointer. + */ + virtual void writeConfig (KConfig * config) = 0; +}; + +#endif diff --git a/umbrello/umbrello/codegenerators/cppcodeclassfield.cpp b/umbrello/umbrello/codegenerators/cppcodeclassfield.cpp new file mode 100644 index 00000000..b6b2fb72 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodeclassfield.cpp @@ -0,0 +1,108 @@ +/*************************************************************************** + * * + * 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 : Mon Sep 1 2003 + */ + +// own header +#include "cppcodeclassfield.h" + +// qt/kde includes +#include <kdebug.h> + +// local includes +#include "../codegenerator.h" +#include "../classifiercodedocument.h" +#include "../attribute.h" +#include "../umlobject.h" +#include "../umlrole.h" +#include "../uml.h" +#include "cppcodegenerationpolicy.h" + + +// Constructors/Destructors +// + +CPPCodeClassField::CPPCodeClassField (ClassifierCodeDocument * parentDoc, UMLRole * role) + : CodeClassField(parentDoc, role) +{ + +} + +CPPCodeClassField::CPPCodeClassField (ClassifierCodeDocument * parentDoc, UMLAttribute * attrib) + : CodeClassField(parentDoc, attrib) +{ + +} + +CPPCodeClassField::~CPPCodeClassField ( ) { } + +// +// Methods +// + +// Other methods +// + +QString CPPCodeClassField::getFieldName() { + if (parentIsAttribute()) + { + UMLAttribute * at = (UMLAttribute*) getParentObject(); + return cleanName(at->getName()); + } + else + { + UMLRole * role = (UMLRole*) getParentObject(); + QString roleName = role->getName(); + if(fieldIsSingleValue()) { + return roleName.replace(0, 1, roleName.left(1).lower()); + } else { + return roleName.lower() + "Vector"; + } + } +} + +QString CPPCodeClassField::getListFieldClassName () { + CodeGenPolicyExt * p = UMLApp::app()->getPolicyExt(); + CPPCodeGenerationPolicy *policy = dynamic_cast<CPPCodeGenerationPolicy*>(p); + return policy->getVectorClassName(); +} + +QString CPPCodeClassField::getInitialValue() { + + if (parentIsAttribute()) + { + UMLAttribute * at = dynamic_cast<UMLAttribute*>( getParentObject() ); + if (at) { + return fixInitialStringDeclValue(at->getInitialValue(), getTypeName()); + } else { + kError() << "CPPCodeClassField::getInitialValue: parent object is not a UMLAttribute" + << endl; + return ""; + } + } + else + { + if(fieldIsSingleValue()) { + // FIX : IF the multiplicity is "1" then we should init a new object here, if its 0 or 1, + // then we can just return 'empty' string (minor problem). + return ""; + } else { + return " new "+getListFieldClassName()+"( )"; + } + } + +} + + +#include "cppcodeclassfield.moc" diff --git a/umbrello/umbrello/codegenerators/cppcodeclassfield.h b/umbrello/umbrello/codegenerators/cppcodeclassfield.h new file mode 100644 index 00000000..d9c20255 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodeclassfield.h @@ -0,0 +1,62 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + + + +#ifndef CPPCODECLASSFIELD_H +#define CPPCODECLASSFIELD_H + +#include <qstring.h> + +#include "../codeclassfield.h" + +class ClassifierCodeDocument; + +class CPPCodeClassField : public CodeClassField +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructors + */ + CPPCodeClassField (ClassifierCodeDocument * parentDoc, UMLRole * role); + CPPCodeClassField (ClassifierCodeDocument * parentDoc, UMLAttribute * attrib); + + /** + * Empty Destructor + */ + virtual ~CPPCodeClassField ( ); + + QString getFieldType(); + QString getFieldName(); + QString getInitialValue(); + /** get the name of the class which holds lists, e.g. "QPtrlist" or + * "Vector" or "List" and so on. + */ + QString getListFieldClassName(); + + +protected: + +private: + +}; + +#endif // CPPCODECLASSFIELD_H diff --git a/umbrello/umbrello/codegenerators/cppcodecomment.cpp b/umbrello/umbrello/codegenerators/cppcodecomment.cpp new file mode 100644 index 00000000..8d480e93 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodecomment.cpp @@ -0,0 +1,98 @@ + +/*************************************************************************** + * * + * 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 : Mon Sep 1 2003 + */ + +// own header +#include "cppcodecomment.h" + +// qt/kde includes +#include <qregexp.h> + +// Constructors/Destructors +// + +CPPCodeComment::CPPCodeComment ( CodeDocument * doc, const QString & text ) + : CodeComment (doc, text) +{ + +} + +CPPCodeComment::~CPPCodeComment ( ) { } + +// +// Methods +// + + +// Accessor methods +// + + +// Public attribute accessor methods +// + +// Other methods +// + +/** + * Save the XMI representation of this object + */ +void CPPCodeComment::saveToXMI ( QDomDocument & doc, QDomElement & root ) { + QDomElement blockElement = doc.createElement( "cppcodecomment" ); + setAttributesOnNode(doc, blockElement); // as we added no additional fields to this class we may + // just use parent TextBlock method + root.appendChild( blockElement ); +} + +/** + * @return QString + */ +QString CPPCodeComment::toString ( ) +{ + + QString output = ""; + + // simple output method + if(getWriteOutText()) + { + QString indent = getIndentationString(); + QString endLine = getNewLineEndingChars(); + output.append(formatMultiLineText (getText()+endLine, indent +"// ", endLine)); + } + + return output; +} + +QString CPPCodeComment::getNewEditorLine ( int amount ) { + QString line = getIndentationString(amount) + "// "; + return line; +} + +/** UnFormat a long text string. Typically, this means removing + * the indentaion (linePrefix) and/or newline chars from each line. + */ +QString CPPCodeComment::unformatText ( const QString & text , const QString & indent) +{ + + // remove leading or trailing comment stuff + QString mytext = TextBlock::unformatText(text, indent); + + // now leading slashes + mytext.remove(QRegExp("^\\/\\/\\s*")); + return mytext; +} + +#include "cppcodecomment.moc" diff --git a/umbrello/umbrello/codegenerators/cppcodecomment.h b/umbrello/umbrello/codegenerators/cppcodecomment.h new file mode 100644 index 00000000..085e1a7f --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodecomment.h @@ -0,0 +1,83 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + + + +#ifndef CPPCODECOMMENT_H +#define CPPCODECOMMENT_H + +#include <qstring.h> +#include "../codecomment.h" + +/** + * class CPPCodeComment + * A CPP code comment. There is only a single styles of comments: + * these are simply started with double slash sequence and no terminating + * characters + */ + +class CPPCodeComment : virtual public CodeComment +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + + /** + * Constructors + */ + explicit CPPCodeComment ( CodeDocument * doc, const QString & text = ""); + + /** + * Empty Destructor + */ + virtual ~CPPCodeComment ( ); + + // Public attributes + // + + + // other + + /** + * Save the XMI representation of this object + */ + virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ); + + /** + * @return QString + */ + QString toString ( ); + + + /** UnFormat a long text string. Typically, this means removing + * the indentaion (linePrefix) and/or newline chars from each line. + */ + virtual QString unformatText ( const QString & text, const QString & indent = "" ); + + /** a special version here because we want to not only indent + * the new line, but to add the "//" sequence as well. + */ + virtual QString getNewEditorLine ( int amount ); + +protected: + +private: + +}; + +#endif // CPPCODECOMMENT_H diff --git a/umbrello/umbrello/codegenerators/cppcodedocumentation.cpp b/umbrello/umbrello/codegenerators/cppcodedocumentation.cpp new file mode 100644 index 00000000..833e648e --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodedocumentation.cpp @@ -0,0 +1,141 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Jun 23 2003 + */ + +// own header +#include "cppcodedocumentation.h" +// qt/kde includes +#include <qregexp.h> +#include <kdebug.h> +// app includes +#include "../codedocument.h" +#include "../codegenerator.h" +#include "../codegenerationpolicy.h" +#include "../uml.h" + +// Constructors/Destructors +// + +CPPCodeDocumentation::CPPCodeDocumentation ( CodeDocument * doc, const QString & text ) + : CodeComment (doc, text) +{ + +} + +CPPCodeDocumentation::~CPPCodeDocumentation ( ) { } + +// +// Methods +// + + +// Accessor methods +// + +// Other methods +// + +/** + * Save the XMI representation of this object + */ +void CPPCodeDocumentation::saveToXMI ( QDomDocument & doc, QDomElement & root ) { + QDomElement blockElement = doc.createElement( "cppcodedocumentation" ); + setAttributesOnNode(doc, blockElement); // as we added no additional fields to this class we may + // just use parent TextBlock method + root.appendChild( blockElement ); +} + +/** + * @return QString + */ +QString CPPCodeDocumentation::toString ( ) +{ + + QString output = ""; + + // simple output method + if(getWriteOutText()) + { + bool useDoubleDashOutput = true; + + // need to figure out output type from cpp policy + CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy(); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + useDoubleDashOutput = false; + + QString indent = getIndentationString(); + QString endLine = getNewLineEndingChars(); + QString body = getText(); + if(useDoubleDashOutput) + { + if(!body.isEmpty()) + output.append(formatMultiLineText (body, indent +"// ", endLine)); + } else { + output.append(indent+"/**"+endLine); + output.append(formatMultiLineText (body, indent +" * ", endLine)); + output.append(indent+" */"+endLine); + } + } + + return output; +} + +QString CPPCodeDocumentation::getNewEditorLine ( int amount ) +{ + CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy(); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + return getIndentationString(amount) + " * "; + else + return getIndentationString(amount) + "// "; +} + +int CPPCodeDocumentation::firstEditableLine() { + CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy(); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + return 1; + return 0; +} + +int CPPCodeDocumentation::lastEditableLine() { + CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy(); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + { + return -1; // very last line is NOT editable + } + return 0; +} + +/** UnFormat a long text string. Typically, this means removing + * the indentaion (linePrefix) and/or newline chars from each line. + */ +QString CPPCodeDocumentation::unformatText ( const QString & text , const QString & indent) +{ + + QString mytext = TextBlock::unformatText(text, indent); + CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy(); + // remove leading or trailing comment stuff + mytext.remove(QRegExp('^'+indent)); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + { + mytext.remove(QRegExp("^\\/\\*\\*\\s*\n?")); + mytext.remove(QRegExp("\\s*\\*\\/\\s*\n?$")); + mytext.remove(QRegExp("^\\s*\\*\\s*")); + } else + mytext.remove(QRegExp("^\\/\\/\\s*")); + + return mytext; +} + + diff --git a/umbrello/umbrello/codegenerators/cppcodedocumentation.h b/umbrello/umbrello/codegenerators/cppcodedocumentation.h new file mode 100644 index 00000000..79bc4fe0 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodedocumentation.h @@ -0,0 +1,95 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + + + +#ifndef CPPCODEDOCUMENTATION_H +#define CPPCODEDOCUMENTATION_H + +#include <qstring.h> +#include "../codecomment.h" + +class CodeDocument; + +/** + * class CPPCodeDocumentation + * A CPP code comment. There is only a single styles of comments: + * these are simply started with double slash sequence and no terminating + * characters + */ + +class CPPCodeDocumentation : virtual public CodeComment +{ +public: + + // Constructors/Destructors + // + + + /** + * Constructors + */ + explicit CPPCodeDocumentation ( CodeDocument * doc, const QString & text = ""); + + /** + * Empty Destructor + */ + virtual ~CPPCodeDocumentation ( ); + + // Public attributes + // + + // Other + // + + /** + * Save the XMI representation of this object + */ + virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ); + + /** + * @return QString + */ + QString toString ( ); + + + /** UnFormat a long text string. Typically, this means removing + * the indentaion (linePrefix) and/or newline chars from each line. + */ + virtual QString unformatText ( const QString & text, const QString & indent = "" ); + + /** a special version here because we want to not only indent + * the new line, but to add the " * " sequence as well. + */ + virtual QString getNewEditorLine ( int amount ); + + /** Ush. These are terrifically bad and must one day go away. + * Both methods indicate the range of lines in this textblock + * which may be edited by the codeeditor (assuming that any are + * actually editable). The default case is no lines are editable. + * The line numbering starts with '0' and a '-1' means no line + * qualifies. + */ + virtual int firstEditableLine(); + virtual int lastEditableLine(); + +protected: + +private: + +}; + +#endif // CPPCODEDOCUMENTATION_H diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationform.cpp b/umbrello/umbrello/codegenerators/cppcodegenerationform.cpp new file mode 100644 index 00000000..a4acf713 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodegenerationform.cpp @@ -0,0 +1,305 @@ +/*************************************************************************** + * * + * 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 : Thu Nov 20 2003 + */ + +// own header +#include "cppcodegenerationform.h" + +// qt/kde includes +#include <qlabel.h> +#include <qregexp.h> +#include <qlistview.h> +#include <kfiledialog.h> +#include <kdebug.h> +#include <klocale.h> +#include <kcombobox.h> +#include <kmessagebox.h> + + +CPPCodeGenerationForm::CPPCodeGenerationForm( QWidget *parent, const char *name ) + : CPPCodeGenerationFormBase (parent,name) +{ + init(); + + GeneralOptionsListView->addColumn(tr2i18n("General Options")); + pOptionPackageIsANamespace = new QCheckListItem( GeneralOptionsListView, + tr2i18n("Package is a namespace"), + QCheckListItem::CheckBox ); + pOptionVirtualDestructors = new QCheckListItem( GeneralOptionsListView, + tr2i18n("Virtual destructors"), + QCheckListItem::CheckBox ); + pOptionGenerateEmptyConstructors = new QCheckListItem( GeneralOptionsListView, + tr2i18n("Generate empty constructors"), + QCheckListItem::CheckBox ); + pOptionGenerateAccessorMethods = new QCheckListItem( GeneralOptionsListView, + tr2i18n("Generate accessor methods"), + QCheckListItem::CheckBox ); + pOptionOperationsAreInline = new QCheckListItem( GeneralOptionsListView, + tr2i18n("Operations are inline"), + QCheckListItem::CheckBox ); + pOptionAccessorsAreInline = new QCheckListItem( GeneralOptionsListView, + tr2i18n("Accessors are inline"), + QCheckListItem::CheckBox ); + + pOptionAccessorsArePublic = new QCheckListItem( GeneralOptionsListView, + tr2i18n("Accessors are public"), + QCheckListItem::CheckBox ); + + connect(GeneralOptionsListView, + SIGNAL(clicked(QListViewItem *)), this, + SLOT(generalOptionsListViewClicked(QListViewItem *)) + ); + +} + +CPPCodeGenerationForm::~CPPCodeGenerationForm() +{ +} + +void CPPCodeGenerationForm::browseClicked() +{ + QString button = sender()->name(); + QString file = KFileDialog::getOpenFileName( QString::null, "*.h", this, "Get Header File"); + + if(file.isEmpty()) + return; + + if(button=="m_browseStringButton") { + // search for match in history list, if absent, then add it + m_stringIncludeFileHistoryCombo->setCurrentItem(file, true); + } + else if(button=="m_browseListButton") { + // search for match in history list, if absent, then add it + m_listIncludeFileHistoryCombo->setCurrentItem(file, true); + } +} + +void CPPCodeGenerationForm::generalOptionsListViewClicked(QListViewItem *pSender) { + + // operations are inline and accessors are operations :) + if (pOptionOperationsAreInline->isOn() && pOptionGenerateAccessorMethods->isOn()) + pOptionAccessorsAreInline->setOn(true); + + if (pSender == pOptionPackageIsANamespace) { +#if 0 + KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): " + "sender=pOptionPackageIsANamespace"); +#endif + return; + } + if (pSender == pOptionVirtualDestructors) { +#if 0 + KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): " + "sender=pOptionVirtualDestructors"); +#endif + return; + } + if (pSender == pOptionGenerateEmptyConstructors) { +#if 0 + KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): " + "sender=pOptionVirtualDestructors"); +#endif + return; + } + if (pSender == pOptionGenerateAccessorMethods) { + pOptionAccessorsAreInline->setEnabled(pOptionGenerateAccessorMethods->isOn()); + pOptionAccessorsArePublic->setEnabled(pOptionGenerateAccessorMethods->isOn()); + // reset the value if needed + if (!pOptionGenerateAccessorMethods->isOn()) + { + pOptionAccessorsAreInline->setOn(false); + pOptionAccessorsArePublic->setOn(false); + } +#if 0 + KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): " + "sender=pOptionGenerateAccessorMethods"); +#endif + return; + } + if (pSender == pOptionOperationsAreInline) { +#if 0 + KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): " + "sender=pOptionOperationsAreInline"); +#endif + return; + } + if (pSender == pOptionAccessorsAreInline) { +#if 0 + KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): " + "sender=pOptionAccessorsAreInline"); +#endif + return; + } + +#if 0 + KMessageBox::error(0, "CPPCodeGenerationForm::generalOptionsListViewClicked(): " + "unknown sender"); +#endif + return; +} + +void CPPCodeGenerationForm::init() { + pOptionPackageIsANamespace = NULL; + pOptionVirtualDestructors = NULL; + pOptionGenerateEmptyConstructors = NULL; + pOptionGenerateAccessorMethods = NULL; + pOptionOperationsAreInline = NULL; + pOptionAccessorsAreInline = NULL; +} + +/** + * + * set the display state of option "Package Is Namespace" + * + */ +void CPPCodeGenerationForm::setPackageIsANamespace(bool bFlag) { + pOptionPackageIsANamespace->setOn(bFlag); +} + +/** + * + * set the display state of option "Virtual Destructors" + * + */ +void CPPCodeGenerationForm::setVirtualDestructors(bool bFlag) { + pOptionVirtualDestructors->setOn(bFlag); +} + +/** + * + * set the display state of option "Generate Empty Constructors" + * + */ +void CPPCodeGenerationForm::setGenerateEmptyConstructors(bool bFlag) { + pOptionGenerateEmptyConstructors->setOn(bFlag); +} + +/** + * + * set the display state of option "Generate Accessor Methods" + * + */ +void CPPCodeGenerationForm::setGenerateAccessorMethods(bool bFlag) { + pOptionGenerateAccessorMethods->setOn(bFlag); + // initial settings + pOptionAccessorsAreInline->setEnabled(pOptionGenerateAccessorMethods->isOn()); + pOptionAccessorsArePublic->setEnabled(pOptionGenerateAccessorMethods->isOn()); + // reset the value if needed + if (!pOptionGenerateAccessorMethods->isOn()) + { + pOptionAccessorsAreInline->setOn(false); + pOptionAccessorsArePublic->setOn(false); + } +} + +/** + * + * set the display state of option "Operations Are Inline" + * + */ +void CPPCodeGenerationForm::setOperationsAreInline(bool bFlag) { + pOptionOperationsAreInline->setOn(bFlag); +} + +/** + * + * set the display state of option "Accessors Are Inline" + * + */ +void CPPCodeGenerationForm::setAccessorsAreInline(bool bFlag) { + pOptionAccessorsAreInline->setOn(bFlag); +} + +/** + * + * set the display state of option "Accessors Are Public" + * + */ +void CPPCodeGenerationForm::setAccessorsArePublic(bool bFlag) { + pOptionAccessorsArePublic->setOn(bFlag); +} + +/** + * + * get the display state of option "Package Is Namespace" + * + */ +bool CPPCodeGenerationForm::getPackageIsANamespace() +{ + return pOptionPackageIsANamespace->isOn(); +} + +/** + * + * get the display state of option "Virtual Destructors" + * + */ +bool CPPCodeGenerationForm::getVirtualDestructors() +{ + return pOptionVirtualDestructors->isOn(); +} + +/** + * + * get the display state of option "Generate Empty Constructors" + * + */ +bool CPPCodeGenerationForm::getGenerateEmptyConstructors() +{ + return pOptionGenerateEmptyConstructors->isOn(); +} + +/** + * + * get the display state of option "Generate Accessor Methods" + * + */ +bool CPPCodeGenerationForm::getGenerateAccessorMethods() +{ + return pOptionGenerateAccessorMethods->isOn(); +} + +/** + * + * get the display state of option "Operations Are Inline" + * + */ +bool CPPCodeGenerationForm::getOperationsAreInline() +{ + return pOptionOperationsAreInline->isOn(); +} + +/** + * + * get the display state of option "Accessors Are Inline" + * + */ +bool CPPCodeGenerationForm::getAccessorsAreInline() +{ + return pOptionAccessorsAreInline->isOn(); +} + +/** + * + * get the display state of option "Accessors Are Public" + * + */ +bool CPPCodeGenerationForm::getAccessorsArePublic() +{ + return pOptionAccessorsArePublic->isOn(); +} + + +#include "cppcodegenerationform.moc" diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationform.h b/umbrello/umbrello/codegenerators/cppcodegenerationform.h new file mode 100644 index 00000000..73441a82 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodegenerationform.h @@ -0,0 +1,150 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Wed Jul 30 2003 + */ + +#ifndef CPPCODEGENERATIONFORM_H +#define CPPCODEGENERATIONFORM_H + +#include "cppcodegenerationformbase.h" + +class QCheckListItem; + +/** + * @author Brian Thomas + */ + +class CPPCodeGenerationForm : public CPPCodeGenerationFormBase { + Q_OBJECT +public: + + /** + * std ctor + */ + explicit CPPCodeGenerationForm (QWidget *parent=0, const char *name=0); + + /** + * std dtor + */ + virtual ~CPPCodeGenerationForm(); + + /** + * set the display state of option "Package Is A Namespace" + */ + void setPackageIsANamespace(bool bFlag = true); + + /** + * set the display state of option "Virtual Destructors" + */ + void setVirtualDestructors(bool bFlag = true); + + /** + * set the display state of option "Generate Empty Constructors" + */ + void setGenerateEmptyConstructors(bool bFlag = true); + + /** + * set the display state of option "Generate Accessor Methods" + */ + void setGenerateAccessorMethods(bool bFlag = true); + + /** + * set the display state of option "Operations Are Inline" + */ + void setOperationsAreInline(bool bFlag = true); + + /** + * set the display state of option "Accessors Are Inline" + */ + void setAccessorsAreInline(bool bFlag = true); + + /** + * set the display state of option "Accessors Are Public" + */ + void setAccessorsArePublic(bool bFlag = true); + + /** + * set the display state of option "Generate Makefile Document" + */ + void setGenerateMakefileDocument(bool bFlag = true); + + /** + * get the display state of option "Package Is A Namespace" + */ + bool getPackageIsANamespace(); + + /** + * get the display state of option "Virtual Destructors" + */ + bool getVirtualDestructors(); + + /** + * get the display state of option "Generate Empty Constructors" + */ + bool getGenerateEmptyConstructors(); + + /** + * get the display state of option "Generate Accessors Methods" + */ + bool getGenerateAccessorMethods(); + + /** + * get the display state of option "Operations Are Inline" + */ + bool getOperationsAreInline(); + + /** + * get the display state of option "Accessors Are Inline" + */ + bool getAccessorsAreInline(); + + /** + * get the display state of option "Accessors Are Public" + */ + bool getAccessorsArePublic(); + + /** + * get the display state of option "Generate Makefile Document" + */ + bool getGenerateMakefileDocument(); + +protected: + +public slots: + + virtual void browseClicked(); + +private slots: + virtual void generalOptionsListViewClicked(QListViewItem *); + +private: + + /* + * check boxes for the available options + */ + QCheckListItem *pOptionPackageIsANamespace; + QCheckListItem *pOptionVirtualDestructors; + QCheckListItem *pOptionGenerateEmptyConstructors; + QCheckListItem *pOptionGenerateAccessorMethods; + QCheckListItem *pOptionOperationsAreInline; + QCheckListItem *pOptionAccessorsAreInline; + QCheckListItem *pOptionAccessorsArePublic; + + /** + * initialize all attributes + */ + void init(); + +}; + +#endif + diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationformbase.ui b/umbrello/umbrello/codegenerators/cppcodegenerationformbase.ui new file mode 100644 index 00000000..2599ae35 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodegenerationformbase.ui @@ -0,0 +1,481 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>CPPCodeGenerationFormBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>CPPCodeGenerationFormBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>648</width> + <height>549</height> + </rect> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="geometry"> + <rect> + <x>11</x> + <y>44</y> + <width>436</width> + <height>72</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Documentation</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QComboBox" row="0" column="1"> + <item> + <property name="text"> + <string>Slash-Slash (//)</string> + </property> + </item> + <item> + <property name="text"> + <string>Slash-Star (/** */)</string> + </property> + </item> + <property name="name"> + <cstring>m_SelectCommentStyle</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Style:</string> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="geometry"> + <rect> + <x>11</x> + <y>11</y> + <width>436</width> + <height>27</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><p align="center">C++ Code Generation</p></string> + </property> + </widget> + <widget class="QTabWidget"> + <property name="name"> + <cstring>tabWidget2</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>120</y> + <width>436</width> + <height>305</height> + </rect> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>General</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QListView"> + <property name="name"> + <cstring>GeneralOptionsListView</cstring> + </property> + </widget> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Method Body Generation</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="2" column="0"> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>410</width> + <height>113</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel2_2_2_2</cstring> + </property> + <property name="text"> + <string>Use following for classes in generated code:</string> + </property> + </widget> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout17</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KHistoryCombo" row="1" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_listClassHCombo</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="editable"> + <bool>false</bool> + </property> + <property name="currentItem"> + <number>0</number> + </property> + <property name="insertionPolicy"> + <enum>NoInsertion</enum> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + <property name="historyItems"> + <stringlist> + <string>QPtrList</string> + <string>vector</string> + </stringlist> + </property> + </widget> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel1_3_2_2_2</cstring> + </property> + <property name="text"> + <string><b>Variable</b></string> + </property> + </widget> + <widget class="QPushButton" row="2" column="4" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_browseStringButton</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>32</width> + <height>32767</height> + </size> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> + <widget class="QCheckBox" row="2" column="7"> + <property name="name"> + <cstring>m_globalStringCheckBox</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="KHistoryCombo" row="2" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_stringClassHCombo</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="editable"> + <bool>false</bool> + </property> + <property name="currentItem"> + <number>0</number> + </property> + <property name="insertionPolicy"> + <enum>NoInsertion</enum> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + <property name="historyItems"> + <stringlist> + <string>QString</string> + <string>string</string> + </stringlist> + </property> + </widget> + <spacer row="2" column="6"> + <property name="name"> + <cstring>spacer2_2_2_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Minimum</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer row="1" column="6"> + <property name="name"> + <cstring>spacer1_2_2_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Minimum</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>stringClassTextLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><p align="center">String</p></string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>listClassTextLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><p align="center">List</p></string> + </property> + </widget> + <widget class="KHistoryCombo" row="1" column="3"> + <property name="name"> + <cstring>m_listIncludeFileHistoryCombo</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="currentItem"> + <number>0</number> + </property> + <property name="insertionPolicy"> + <enum>AtTop</enum> + </property> + <property name="historyItems"> + <stringlist> + <string>qptrlist.h</string> + <string>vector</string> + </stringlist> + </property> + </widget> + <widget class="QLabel" row="0" column="5" rowspan="1" colspan="3"> + <property name="name"> + <cstring>textLabel4_2_2_2</cstring> + </property> + <property name="text"> + <string><i>global?</i></string> + </property> + </widget> + <widget class="KHistoryCombo" row="2" column="3"> + <property name="name"> + <cstring>m_stringIncludeFileHistoryCombo</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="currentItem"> + <number>0</number> + </property> + <property name="insertionPolicy"> + <enum>AtTop</enum> + </property> + <property name="historyItems"> + <stringlist> + <string>qstring.h</string> + <string>string</string> + </stringlist> + </property> + </widget> + <widget class="QCheckBox" row="1" column="7"> + <property name="name"> + <cstring>m_globalListCheckBox</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>textLabel3_2_2</cstring> + </property> + <property name="text"> + <string>Class name</string> + </property> + </widget> + <widget class="QPushButton" row="1" column="4" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_browseListButton</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>32</width> + <height>32767</height> + </size> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> + <widget class="QLabel" row="0" column="3" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel5_2_2_2</cstring> + </property> + <property name="text"> + <string><i><p align="center">Include file</p></i></string> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + </widget> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>m_browseListButton</sender> + <signal>clicked()</signal> + <receiver>CPPCodeGenerationFormBase</receiver> + <slot>browseClicked()</slot> + </connection> + <connection> + <sender>m_browseStringButton</sender> + <signal>clicked()</signal> + <receiver>CPPCodeGenerationFormBase</receiver> + <slot>browseClicked()</slot> + </connection> +</connections> +<slots> + <slot>browseClicked()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klineedit.h</includehint> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationpolicy.cpp b/umbrello/umbrello/codegenerators/cppcodegenerationpolicy.cpp new file mode 100644 index 00000000..d0359603 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodegenerationpolicy.cpp @@ -0,0 +1,390 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Jun 23 2003 + */ + +// own header +#include "cppcodegenerationpolicy.h" +// qt/kde includes +#include <qregexp.h> +#include <kdebug.h> +#include <kconfig.h> +// app includes +#include "cppcodegenerationpolicypage.h" +#include "../uml.h" + +const bool CPPCodeGenerationPolicy::DEFAULT_AUTO_GEN_ACCESSORS = true; +const bool CPPCodeGenerationPolicy::DEFAULT_INLINE_ACCESSORS = false; +const bool CPPCodeGenerationPolicy::DEFAULT_INLINE_OPERATIONS = false; +const bool CPPCodeGenerationPolicy::DEFAULT_VIRTUAL_DESTRUCTORS = true; +const bool CPPCodeGenerationPolicy::DEFAULT_PACKAGE_IS_NAMESPACE = true; +const char * CPPCodeGenerationPolicy::DEFAULT_STRING_CLASS_NAME = "string"; +const char * CPPCodeGenerationPolicy::DEFAULT_STRING_CLASS_INCLUDE = "string"; +const char * CPPCodeGenerationPolicy::DEFAULT_VECTOR_CLASS_NAME = "vector"; +const char * CPPCodeGenerationPolicy::DEFAULT_VECTOR_CLASS_INCLUDE = "vector"; +const char * CPPCodeGenerationPolicy::DEFAULT_VECTOR_METHOD_APPEND = "%VARNAME%.push_back(value);"; +const char * CPPCodeGenerationPolicy::DEFAULT_VECTOR_METHOD_REMOVE = "int size = %VARNAME%.size();\nfor ( int i = 0; i < size; ++i) {\n\t%ITEMCLASS% item = %VARNAME%.at(i);\n\tif(item == value) {\n\t\tvector<%ITEMCLASS%>::iterator it = %VARNAME%.begin() + i;\n\t\t%VARNAME%.erase(it);\n\t\treturn;\n\t}\n }"; +const char * CPPCodeGenerationPolicy::DEFAULT_VECTOR_METHOD_INIT = ""; // nothing to do in std::vector +const char * CPPCodeGenerationPolicy::DEFAULT_OBJECT_METHOD_INIT = "%VARNAME% = new %ITEMCLASS%( );"; +const bool CPPCodeGenerationPolicy::DEFAULT_STRING_INCLUDE_GLOBAL = true; +const bool CPPCodeGenerationPolicy::DEFAULT_VECTOR_INCLUDE_GLOBAL = true; +const bool CPPCodeGenerationPolicy::DEFAULT_PUBLIC_ACCESSORS = false; + + +// Constructors/Destructors +// + +CPPCodeGenerationPolicy::CPPCodeGenerationPolicy(KConfig *config) +{ + init(); + setDefaults(config,false); +} + +CPPCodeGenerationPolicy::~CPPCodeGenerationPolicy ( ) { } + +// +// Methods +// + +// Accessor methods +// +/** + * Set the value of m_publicAccessors + * @param new_var the new value + */ +void CPPCodeGenerationPolicy::setAccessorsArePublic ( bool var ) +{ + m_publicAccessors = var; + // @todo we should probably use an own signal for this + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + +/** + * Get the value of m_publicAccessors + * @return value the boolean value of m_publicAccessors + */ +bool CPPCodeGenerationPolicy::getAccessorsArePublic( ) +{ + return m_publicAccessors; +} + +/** + * Set the value of m_inlineAccessors + * @param new_var the new value + */ +void CPPCodeGenerationPolicy::setAccessorsAreInline ( bool var ) +{ + m_inlineAccessors = var; + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + +/** + * Get the value of m_inlineAccessors + * @return value the boolean value of m_inlineAccessors + */ +bool CPPCodeGenerationPolicy::getAccessorsAreInline( ) +{ + return m_inlineAccessors; +} + +/** + * Set the value of m_inlineOperations + * @param new_var the new value + */ +void CPPCodeGenerationPolicy::setOperationsAreInline ( bool var ) +{ + m_inlineOperations = var; + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + +/** + * Get the value of m_inlineOperations + * @return value the boolean value of m_inlineOperations + */ +bool CPPCodeGenerationPolicy::getOperationsAreInline( ) +{ + return m_inlineOperations; +} + +/** + * Set the value of m_virtualDestructors + * @param new_var the new value + */ +void CPPCodeGenerationPolicy::setDestructorsAreVirtual ( bool var ) +{ + m_virtualDestructors = var; + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + +/** + * Get the value of m_virtualDestructors + * @return value the boolean value of m_virtualDestructors + */ +bool CPPCodeGenerationPolicy::getDestructorsAreVirtual( ) +{ + return m_virtualDestructors; +} + +/** + * Set the value of m_packageIsNamespace + * @param new_var the new value + */ +void CPPCodeGenerationPolicy::setPackageIsNamespace ( bool var ) { + m_packageIsNamespace = var; + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + +/** + * Get the value of m_packageIsNamespace + * @return value the boolean value of m_packageIsNamespace + */ +bool CPPCodeGenerationPolicy::getPackageIsNamespace( ) { + return m_packageIsNamespace; +} + +/** + * Set the value of m_autoGenerateAccessors + * @param new_var the new value + */ +void CPPCodeGenerationPolicy::setAutoGenerateAccessors( bool var ) { + m_autoGenerateAccessors = var; + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + +bool CPPCodeGenerationPolicy::getAutoGenerateAccessors( ){ + return m_autoGenerateAccessors; +} + +QString CPPCodeGenerationPolicy::getStringClassName() { + return m_stringClassName; +} + +QString CPPCodeGenerationPolicy::getStringClassNameInclude() { + return m_stringClassNameInclude; +} + +QString CPPCodeGenerationPolicy::getVectorClassName() { + return m_vectorClassName; +} + +QString CPPCodeGenerationPolicy::getVectorClassNameInclude() { + return m_vectorClassNameInclude; +} + +void CPPCodeGenerationPolicy::setStringClassName(const QString &value) { + m_stringClassName = value; + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + +void CPPCodeGenerationPolicy::setStringClassNameInclude(const QString &value) { + m_stringClassNameInclude = value; + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + +void CPPCodeGenerationPolicy::setVectorClassName(const QString &value) { + m_vectorClassName = value; + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + +void CPPCodeGenerationPolicy::setVectorClassNameInclude(const QString &value) { + m_vectorClassNameInclude = value; + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + +/** determine if the string include is global one */ +bool CPPCodeGenerationPolicy::stringIncludeIsGlobal () { + return m_stringIncludeIsGlobal; +} + +bool CPPCodeGenerationPolicy::vectorIncludeIsGlobal () { + return m_vectorIncludeIsGlobal; +} + +void CPPCodeGenerationPolicy::setStringIncludeIsGlobal(bool value) { + m_stringIncludeIsGlobal = value; + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + +void CPPCodeGenerationPolicy::setVectorIncludeIsGlobal(bool value) { + m_vectorIncludeIsGlobal = value; + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + +QString CPPCodeGenerationPolicy::getVectorMethodAppend(const QString & variableName, const QString & itemClassName) { + QString value = m_vectorMethodAppendBase; + if(!variableName.isEmpty()) + value.replace(QRegExp("%VARNAME%"),variableName); + value.replace(QRegExp("%VECTORTYPENAME%"), m_vectorClassName); + if(!itemClassName.isEmpty()) + value.replace(QRegExp("%ITEMCLASS%"),itemClassName); + return value; +} + +QString CPPCodeGenerationPolicy::getVectorMethodRemove(const QString & variableName, const QString & itemClassName) { + QString value = m_vectorMethodRemoveBase; + if(!variableName.isEmpty()) + value.replace(QRegExp("%VARNAME%"),variableName); + value.replace(QRegExp("%VECTORTYPENAME%"), m_vectorClassName); + if(!itemClassName.isEmpty()) + value.replace(QRegExp("%ITEMCLASS%"),itemClassName); + return value; +} + +QString CPPCodeGenerationPolicy::getVectorMethodInit(const QString & variableName, const QString & itemClassName) { + QString value = m_vectorMethodInitBase; + if(!variableName.isEmpty()) + value.replace(QRegExp("%VARNAME%"),variableName); + value.replace(QRegExp("%VECTORTYPENAME%"), m_vectorClassName); + if(!itemClassName.isEmpty()) + value.replace(QRegExp("%ITEMCLASS%"),itemClassName); + return value; +} + +QString CPPCodeGenerationPolicy::getObjectMethodInit(const QString & variableName, const QString & itemClassName) { + QString value = m_objectMethodInitBase; + if(!variableName.isEmpty()) + value.replace(QRegExp("%VARNAME%"),variableName); + value.replace(QRegExp("%VECTORTYPENAME%"), m_vectorClassName); + if(!itemClassName.isEmpty()) + value.replace(QRegExp("%ITEMCLASS%"),itemClassName); + return value; +} + +// Other methods +// + +void CPPCodeGenerationPolicy::writeConfig ( KConfig * config ) +{ + + // write ONLY the CPP specific stuff + config->setGroup("CPP Code Generation"); + + config->writeEntry("autoGenAccessors",getAutoGenerateAccessors()); + + config->writeEntry("inlineAccessors",getAccessorsAreInline()); + config->writeEntry("publicAccessors",getAccessorsArePublic()); + config->writeEntry("inlineOps",getOperationsAreInline()); + config->writeEntry("virtualDestructors",getDestructorsAreVirtual()); + config->writeEntry("packageIsNamespace",getPackageIsNamespace()); + + config->writeEntry("stringClassName",getStringClassName()); + config->writeEntry("stringClassNameInclude",getStringClassNameInclude()); + config->writeEntry("stringIncludeIsGlobal",stringIncludeIsGlobal()); + + config->writeEntry("vectorClassName",getVectorClassName()); + config->writeEntry("vectorClassNameInclude",getVectorClassNameInclude()); + config->writeEntry("vectorIncludeIsGlobal",vectorIncludeIsGlobal()); + +} + +void CPPCodeGenerationPolicy::setDefaults ( CPPCodeGenerationPolicy * cppclone, bool emitUpdateSignal ) +{ + blockSignals(true); // we need to do this because otherwise most of these + // settors below will each send the modifiedCodeContent() signal + // needlessly (we can just make one call at the end). + + { + setAutoGenerateAccessors(cppclone->getAutoGenerateAccessors()); + + setAccessorsAreInline(cppclone->getAccessorsAreInline()); + setOperationsAreInline(cppclone->getOperationsAreInline()); + setDestructorsAreVirtual(cppclone->getDestructorsAreVirtual()); + setPackageIsNamespace(cppclone->getPackageIsNamespace()); + + setStringClassName(cppclone->getStringClassName() ); + setStringClassNameInclude(cppclone->getStringClassNameInclude()); + setStringIncludeIsGlobal(cppclone->stringIncludeIsGlobal()); + + setVectorClassName(cppclone->getVectorClassName()); + setVectorClassNameInclude(cppclone->getVectorClassNameInclude()); + setVectorIncludeIsGlobal(cppclone->vectorIncludeIsGlobal()); + + } + + blockSignals(false); // "as you were citizen" + + if(emitUpdateSignal) + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); + +} + +void CPPCodeGenerationPolicy::setDefaults( KConfig * config, bool emitUpdateSignal ) +{ + + if(!config) + return; + + blockSignals(true); // we need to do this because otherwise most of these + // settors below will each send the modifiedCodeContent() signal + // needlessly (we can just make one call at the end). + + // now do cpp specific stuff + config -> setGroup("CPP Code Generation"); + + setAutoGenerateAccessors(config->readBoolEntry("autoGenAccessors",DEFAULT_AUTO_GEN_ACCESSORS)); + + setAccessorsAreInline(config->readBoolEntry("inlineAccessors",DEFAULT_INLINE_ACCESSORS)); + setAccessorsArePublic(config->readBoolEntry("publicAccessors",DEFAULT_PUBLIC_ACCESSORS)); + setOperationsAreInline(config->readBoolEntry("inlineOps",DEFAULT_INLINE_OPERATIONS)); + setDestructorsAreVirtual(config->readBoolEntry("virtualDestructors",DEFAULT_VIRTUAL_DESTRUCTORS)); + setPackageIsNamespace(config->readBoolEntry("packageIsNamespace",DEFAULT_PACKAGE_IS_NAMESPACE)); + + setStringClassName(config->readEntry("stringClassName",DEFAULT_STRING_CLASS_NAME) ); + setStringClassNameInclude(config->readEntry("stringClassNameInclude",DEFAULT_STRING_CLASS_INCLUDE ) ); + setStringIncludeIsGlobal(config->readBoolEntry("stringIncludeIsGlobal",DEFAULT_STRING_INCLUDE_GLOBAL) ); + + setVectorClassName(config->readEntry("vectorClassName",DEFAULT_VECTOR_CLASS_NAME) ); + setVectorClassNameInclude(config->readEntry("vectorClassNameInclude",DEFAULT_VECTOR_CLASS_INCLUDE) ); + setVectorIncludeIsGlobal(config->readBoolEntry("vectorIncludeIsGlobal",DEFAULT_VECTOR_INCLUDE_GLOBAL) ); + + blockSignals(false); // "as you were citizen" + + if(emitUpdateSignal) + UMLApp::app()->getCommonPolicy()->emitModifiedCodeContentSig(); +} + + +/** + * Create a new dialog interface for this object. + * @return dialog object + */ +CodeGenerationPolicyPage * CPPCodeGenerationPolicy::createPage ( QWidget *parent, const char *name ) { + return new CPPCodeGenerationPolicyPage ( parent, name, this ); +} + +void CPPCodeGenerationPolicy::init() { + + m_inlineAccessors = DEFAULT_INLINE_ACCESSORS; + m_publicAccessors = DEFAULT_PUBLIC_ACCESSORS; + m_inlineOperations = DEFAULT_INLINE_OPERATIONS; + m_virtualDestructors = DEFAULT_VIRTUAL_DESTRUCTORS; + m_packageIsNamespace = DEFAULT_PACKAGE_IS_NAMESPACE; + + m_stringClassName = DEFAULT_STRING_CLASS_NAME; + m_stringClassNameInclude = DEFAULT_STRING_CLASS_INCLUDE; + m_stringIncludeIsGlobal = DEFAULT_STRING_INCLUDE_GLOBAL; + + m_vectorClassName = DEFAULT_VECTOR_CLASS_NAME; + m_vectorClassNameInclude = DEFAULT_VECTOR_CLASS_INCLUDE; + m_vectorIncludeIsGlobal = DEFAULT_VECTOR_INCLUDE_GLOBAL; + + m_vectorMethodAppendBase = DEFAULT_VECTOR_METHOD_APPEND; + m_vectorMethodRemoveBase = DEFAULT_VECTOR_METHOD_REMOVE; + m_vectorMethodInitBase = DEFAULT_VECTOR_METHOD_INIT; + m_objectMethodInitBase = DEFAULT_OBJECT_METHOD_INIT; + +} + + +#include "cppcodegenerationpolicy.moc" diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationpolicy.h b/umbrello/umbrello/codegenerators/cppcodegenerationpolicy.h new file mode 100644 index 00000000..cda5d1f8 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodegenerationpolicy.h @@ -0,0 +1,227 @@ +/*************************************************************************** + * * + * 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) 2003-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Jun 23 2003 + */ + +#ifndef CPPCODEGENERATIONPOLICY_H +#define CPPCODEGENERATIONPOLICY_H + +#include <qstring.h> +#include "codegenpolicyext.h" +#include "../codegenerationpolicy.h" + +class KConfig; +class CodeGenerationPolicyPage; + +class CPPCodeGenerationPolicy : public CodeGenPolicyExt +{ + Q_OBJECT +public: + + static const bool DEFAULT_AUTO_GEN_EMPTY_CONSTRUCTORS; + static const bool DEFAULT_AUTO_GEN_ACCESSORS; + static const bool DEFAULT_INLINE_ACCESSORS; + static const bool DEFAULT_INLINE_OPERATIONS; + static const bool DEFAULT_VIRTUAL_DESTRUCTORS; + static const bool DEFAULT_PACKAGE_IS_NAMESPACE; + static const bool DEFAULT_PUBLIC_ACCESSORS; + + static const bool DEFAULT_STRING_INCLUDE_GLOBAL; + static const bool DEFAULT_VECTOR_INCLUDE_GLOBAL; + + static const char * DEFAULT_STRING_CLASS_NAME; + static const char * DEFAULT_STRING_CLASS_INCLUDE; + static const char * DEFAULT_VECTOR_CLASS_NAME; + static const char * DEFAULT_VECTOR_CLASS_INCLUDE; + static const char * DEFAULT_VECTOR_METHOD_APPEND; + static const char * DEFAULT_VECTOR_METHOD_REMOVE; + static const char * DEFAULT_VECTOR_METHOD_INIT; + static const char * DEFAULT_OBJECT_METHOD_INIT; + + // Constructors/Destructors + // + + /** + * Constructors + */ + CPPCodeGenerationPolicy ( KConfig * config = 0 ); + + /** + * Empty Destructor + */ + virtual ~CPPCodeGenerationPolicy ( ); + + // Public attribute accessor methods + // + + /** + * Set the value of m_inlineAccessors + * @param var the new value + */ + void setAccessorsAreInline ( bool var ); + + /** + * Get the value of m_inlineAccessors + * @return value the boolean value of m_inlineAccessors + */ + bool getAccessorsAreInline( ); + + /** + * Set the value of m_inlineOperations + * @param var the new value + */ + void setOperationsAreInline ( bool var ); + + /** + * Get the value of m_inlineOperations + * @return value the boolean value of m_inlineOperations + */ + bool getOperationsAreInline( ); + + /** + * Set the value of m_virtualDestructors + * @param var the new value + */ + void setDestructorsAreVirtual ( bool var ); + + /** + * Get the value of m_virtualDestructors + * @return value the boolean value of m_virtualDestructors + */ + bool getDestructorsAreVirtual( ); + + /** + * Set the value of m_packageIsNamespace + * @param var the new value + */ + void setPackageIsNamespace ( bool var ); + + /** + * Get the value of m_packageIsNamespace + * @return value the boolean value of m_packageIsNamespace + */ + bool getPackageIsNamespace( ); + + + /** + * Set the value of m_autoGenerateAccessors + * @param var the new value + */ + void setAutoGenerateAccessors ( bool var ); + + /** + * Get the value of m_autoGenerateAccessors + * @return value the boolean value of m_autoGenerateAccessors + */ + bool getAutoGenerateAccessors( ); + + /** + * Set the value of m_publicAccessors + * @param var the new value + */ + void setAccessorsArePublic ( bool var ); + + /** + * Get the value of m_publicAccessors + * @return value the boolean value of m_inlineAccessors + */ + bool getAccessorsArePublic( ); + + /** We want to be flexible about which classes are allowed for generation + * of the CPP code. In the next 4 methods, we give accessors that allow getting + * the names of the classes, and their include files for string and vectors. + */ + QString getStringClassName(); + QString getStringClassNameInclude(); + QString getVectorClassName(); + QString getVectorClassNameInclude(); + + /** determine if the string include is global one */ + bool stringIncludeIsGlobal (); + bool vectorIncludeIsGlobal (); + + /** also allow setting these parameters! */ + void setStringClassName(const QString &value); + void setStringClassNameInclude(const QString &value); + void setVectorClassName(const QString &value); + void setVectorClassNameInclude(const QString &value); + + /** allow setting of these params */ + void setStringIncludeIsGlobal (bool value); + void setVectorIncludeIsGlobal (bool value); + + /** More flexible generation. We want to allow the user to specify how the + * bodies of the vector methods should be auto-generated. + */ + QString getVectorMethodAppend(const QString & variableName ="", const QString & itemClassName = ""); + QString getVectorMethodRemove(const QString & variableName ="", const QString & itemClassName = ""); + QString getVectorMethodInit(const QString & variableName ="", const QString & itemClassName = ""); + + /** Be somewhat flexible about how new object classes are initialized. + * Not sure if this should be user configureable. For now, it isnt. + */ + QString getObjectMethodInit(const QString & variableName ="", const QString & itemClassName = ""); + + /** + * set the defaults for this code generator from the passed generator. + */ + virtual void setDefaults (CPPCodeGenerationPolicy * defaults, bool emitUpdateSignal = true); + + /** + * set the defaults from a config file for this code generator from the passed KConfig pointer. + */ + virtual void setDefaults(KConfig * config, bool emitUpdateSignal = true); + + /** + * write Default params to passed KConfig pointer. + */ + virtual void writeConfig (KConfig * config); + + /** + * Create a new dialog interface for this object. + * @return dialog object + */ + CodeGenerationPolicyPage * createPage ( QWidget *parent = 0, const char * name = 0); + +protected: + + /** + */ + void init ( ); + +private: + + bool m_autoGenerateAccessors; + + bool m_inlineAccessors; + bool m_inlineOperations; + bool m_virtualDestructors; + bool m_packageIsNamespace; + bool m_publicAccessors; + + bool m_stringIncludeIsGlobal; + bool m_vectorIncludeIsGlobal; + + QString m_stringClassName; + QString m_stringClassNameInclude; + QString m_vectorClassName; + QString m_vectorClassNameInclude; + QString m_vectorMethodAppendBase; + QString m_vectorMethodRemoveBase; + QString m_vectorMethodInitBase; + QString m_objectMethodInitBase; + +}; + +#endif // CPPCODEGENERATIONPOLICY_H diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.cpp b/umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.cpp new file mode 100644 index 00000000..f05833dc --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.cpp @@ -0,0 +1,94 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Wed Jul 30 2003 + */ + +// own header +#include "cppcodegenerationpolicypage.h" +// qt/kde includes +#include <kdebug.h> +#include <klocale.h> +#include <qlabel.h> +#include <kcombobox.h> +#include <qcheckbox.h> +// app includes +#include "cppcodegenerationformbase.h" +#include "../uml.h" + +CPPCodeGenerationPolicyPage::CPPCodeGenerationPolicyPage( QWidget *parent, const char *name, CPPCodeGenerationPolicy * policy ) + : CodeGenerationPolicyPage(parent, name, policy) +{ + CodeGenerationPolicy *common = UMLApp::app()->getCommonPolicy(); + form = new CPPCodeGenerationForm(this); + form->m_SelectCommentStyle->setCurrentItem((int)(common->getCommentStyle())); + form->setPackageIsANamespace(policy->getPackageIsNamespace()); + form->setVirtualDestructors(policy->getDestructorsAreVirtual()); + form->setGenerateAccessorMethods(policy->getAutoGenerateAccessors()); + form->setGenerateEmptyConstructors(common->getAutoGenerateConstructors()); + form->setOperationsAreInline(policy->getOperationsAreInline()); + form->setAccessorsAreInline(policy->getAccessorsAreInline()); + form->setAccessorsArePublic(policy->getAccessorsArePublic()); + + form->m_stringClassHCombo->setCurrentItem(policy->getStringClassName(),true); + form->m_listClassHCombo->setCurrentItem(policy->getVectorClassName(),true); + + form->m_stringIncludeFileHistoryCombo->setCurrentItem(policy->getStringClassNameInclude(),true); + form->m_listIncludeFileHistoryCombo->setCurrentItem(policy->getVectorClassNameInclude(),true); + + form->m_globalStringCheckBox->setChecked(policy->stringIncludeIsGlobal()); + form->m_globalListCheckBox->setChecked(policy->vectorIncludeIsGlobal()); +} + +CPPCodeGenerationPolicyPage::~CPPCodeGenerationPolicyPage() +{ +} + +void CPPCodeGenerationPolicyPage::apply() +{ + CodeGenerationPolicy *common = UMLApp::app()->getCommonPolicy(); + + // now do our cpp-specific configs + CPPCodeGenerationPolicy * parent = (CPPCodeGenerationPolicy*) m_parentPolicy; + + // block signals so that we don't generate too many sync signals for child code + // documents + parent->blockSignals(true); + + common->setCommentStyle((CodeGenerationPolicy::CommentStyle ) form->m_SelectCommentStyle->currentItem()); + common->setAutoGenerateConstructors(form->getGenerateEmptyConstructors()); + parent->setAutoGenerateAccessors(form->getGenerateAccessorMethods()); + + parent->setDestructorsAreVirtual(form->getVirtualDestructors()); + parent->setPackageIsNamespace(form->getPackageIsANamespace()); + parent->setAccessorsAreInline(form->getAccessorsAreInline()); + parent->setOperationsAreInline(form->getOperationsAreInline()); + parent->setAccessorsArePublic(form->getAccessorsArePublic()); + + parent->setStringClassName(form->m_stringClassHCombo->currentText()); + parent->setStringClassNameInclude(form->m_stringIncludeFileHistoryCombo->currentText()); + parent->setStringIncludeIsGlobal(form->m_globalStringCheckBox->isChecked()); + + parent->setVectorClassName(form->m_listClassHCombo->currentText()); + parent->setVectorClassNameInclude(form->m_listIncludeFileHistoryCombo->currentText()); + parent->setVectorIncludeIsGlobal(form->m_globalListCheckBox->isChecked()); + + parent->blockSignals(false); + + // now send out modified code content signal + common->emitModifiedCodeContentSig(); + +} + + +#include "cppcodegenerationpolicypage.moc" diff --git a/umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.h b/umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.h new file mode 100644 index 00000000..a1d6633b --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodegenerationpolicypage.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * * + * 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) 2003-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Wed Jul 30 2003 + */ + +#ifndef CPPCODEGENERATIONPOLICYPAGE_H +#define CPPCODEGENERATIONPOLICYPAGE_H + +#include "../dialogs/codegenerationpolicypage.h" + +#include "cppcodegenerationform.h" +#include "cppcodegenerationpolicy.h" + +/** + * @author Brian Thomas + */ + +class CPPCodeGenerationPolicyPage : public CodeGenerationPolicyPage { + Q_OBJECT +public: + + explicit CPPCodeGenerationPolicyPage (QWidget *parent=0, const char *name=0, CPPCodeGenerationPolicy * policy = 0); + + virtual ~CPPCodeGenerationPolicyPage(); + +protected: + + CPPCodeGenerationForm * form; + +public slots: + + void apply(); + +}; + +#endif + diff --git a/umbrello/umbrello/codegenerators/cppcodegenerator.cpp b/umbrello/umbrello/codegenerators/cppcodegenerator.cpp new file mode 100644 index 00000000..1130107b --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodegenerator.cpp @@ -0,0 +1,366 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Thu Jun 19 2003 + */ + +// own header +#include "cppcodegenerator.h" + +// qt/kde includes +#include <qregexp.h> +#include <kdebug.h> +#include <kconfig.h> + +// app includes +#include "cppcodedocumentation.h" +#include "cppcodegenerationpolicy.h" +#include "cppsourcecodedocument.h" +#include "cppheadercodedocument.h" +#include "codegen_utils.h" +#include "codeviewerdialog.h" +#include "../codedocumentlist.h" +#include "../uml.h" + +const bool CPPCodeGenerator::DEFAULT_BUILD_MAKEFILE = false; + +// Constructors/Destructors +// + +CPPCodeGenerator::CPPCodeGenerator () { + initAttributes(); +} + +CPPCodeGenerator::~CPPCodeGenerator ( ) { + // destroy all separately owned codedocuments (e.g. header docs) + CodeDocument *doc; + for (CodeDocumentListIt it(m_headercodedocumentVector); + (doc = it.current()) != NULL; ++it) + delete doc; + m_headercodedocumentVector.clear(); +} + +// +// Methods +// + +// Accessor methods +// + +/** + * returns "C++" + */ +Uml::Programming_Language CPPCodeGenerator::getLanguage() { + return Uml::pl_Cpp; +} + +/** + * Set the value of m_createMakefile + * @param new_var the new value of m_createMakefile + */ +void CPPCodeGenerator::setCreateProjectMakefile ( bool buildIt) { + m_createMakefile = buildIt; + CodeDocument * antDoc = findCodeDocumentByID(CPPMakefileCodeDocument::DOCUMENT_ID_VALUE); + if (antDoc) + antDoc->setWriteOutCode(buildIt); +} + +/** + * Get the value of m_createMakefile + * @return the value of m_createMakefile + */ +bool CPPCodeGenerator::getCreateProjectMakefile ( ) { + return m_createMakefile; +} + +bool CPPCodeGenerator::addHeaderCodeDocument ( CPPHeaderCodeDocument * doc ) +{ + + QString tag = doc->getID(); + + // assign a tag if one doesn't already exist + if(tag.isEmpty()) + { + tag = "cppheader"+ID2STR(doc->getParentClassifier()->getID()); + doc->setID(tag); + } + + if(m_codeDocumentDictionary.find(tag)) + return false; // return false, we already have some object with this tag in the list + else + m_codeDocumentDictionary.insert(tag, doc); + + m_headercodedocumentVector.append(doc); + return true; +} + +/** + * Remove a header CodeDocument object from m_headercodedocumentVector List + */ +bool CPPCodeGenerator::removeHeaderCodeDocument ( CPPHeaderCodeDocument * remove_object ) { + QString tag = remove_object->getID(); + if(!(tag.isEmpty())) + m_codeDocumentDictionary.remove(tag); + else + return false; + + m_headercodedocumentVector.remove(remove_object); + return true; +} + +// In the C++ version, we need to make both source and header files as well +// as the makefile available. +CodeViewerDialog * CPPCodeGenerator::getCodeViewerDialog ( QWidget* parent, CodeDocument *doc, + Settings::CodeViewerState state) +{ + + ClassifierCodeDocument * cdoc = dynamic_cast<ClassifierCodeDocument*>(doc); + if(!cdoc) + // bah..not a classcode document?? then just use vanilla version + return CodeGenerator::getCodeViewerDialog(parent,doc,state); + else { + // build with passed (source) code document + CodeViewerDialog *dialog; + + // use classifier to find appropriate header document + UMLClassifier * c = cdoc->getParentClassifier(); + CPPHeaderCodeDocument * hdoc = findHeaderCodeDocumentByClassifier(c); + if(hdoc) + { + // if we have a header document..build with that + dialog = new CodeViewerDialog(parent, hdoc, state); + dialog->addCodeDocument(doc); + } else + // shouldn't happen, but lets try to gracefully deliver something. + dialog = new CodeViewerDialog(parent, doc, state); + + // add in makefile if available and desired + if(getCreateProjectMakefile()) + dialog->addCodeDocument(findCodeDocumentByID(CPPMakefileCodeDocument::DOCUMENT_ID_VALUE)); + + return dialog; + } +} + +// Other methods +// + +// Change the following dataTypes to the ones the user really +// wants in their code. Not yet complete. +QString CPPCodeGenerator::fixTypeName(const QString &string) +{ + return cleanName(string); +} + +// special method needed so that we write out the header code documents +void CPPCodeGenerator::saveToXMI ( QDomDocument & doc, QDomElement & root ) { + QDomElement docElement = doc.createElement( "codegenerator" ); + docElement.setAttribute("language", "C++"); + + CodeDocumentList * docList = getCodeDocumentList(); + for (CodeDocument * codeDoc = docList->first(); codeDoc; codeDoc= docList->next()) + codeDoc->saveToXMI(doc, docElement); + + for (CodeDocument * hcodeDoc = m_headercodedocumentVector.first(); hcodeDoc; hcodeDoc=m_headercodedocumentVector.next()) + hcodeDoc->saveToXMI(doc, docElement); + + root.appendChild( docElement ); +} + +/** + * Force a synchronize of this code generator, and its present contents, to that of the parent UMLDocument. + * Need to override parent method because we have header documents to consider too. + */ +void CPPCodeGenerator::syncCodeToDocument ( ) { + + CodeDocumentList * docList = getCodeDocumentList(); + + for (CodeDocument * doc = docList->first(); doc; doc=docList->next()) + doc->synchronize(); + + for (CodeDocument * hcodeDoc = m_headercodedocumentVector.first(); hcodeDoc; hcodeDoc=m_headercodedocumentVector.next()) + hcodeDoc->synchronize(); + +} + +/** + * Write out all code documents to file as appropriate. + */ +void CPPCodeGenerator::writeCodeToFile ( ) +{ + // write all source documents (incl. Makefile) + writeListedCodeDocsToFile(getCodeDocumentList()); + + // write all header documents + writeListedCodeDocsToFile(&m_headercodedocumentVector); + +} + +// overridden because we need to be able to generate code for +// both the header and source documents +void CPPCodeGenerator::writeCodeToFile ( UMLClassifierList & concepts) { + CodeDocumentList docs; + docs.setAutoDelete(false); + + for (UMLClassifier *concept= concepts.first(); concept; concept= concepts.next()) + { + CodeDocument * doc = findCodeDocumentByClassifier(concept); + if(doc) + docs.append(doc); + CodeDocument * hdoc = findHeaderCodeDocumentByClassifier(concept); + if(hdoc) + docs.append(hdoc); + } + + writeListedCodeDocsToFile(&docs); +} + + +/** + * Find a cppheadercodedocument by the given classifier. + * @return CPPHeaderCodeDocument +* @param classifier +*/ +CPPHeaderCodeDocument * CPPCodeGenerator::findHeaderCodeDocumentByClassifier (UMLClassifier * classifier ) +{ + CodeDocument * doc = findCodeDocumentByID("cppheader"+ID2STR(classifier->getID())); + return dynamic_cast<CPPHeaderCodeDocument*>(doc); +} + +/** + * @return ClassifierCodeDocument + * @param classifier The classifier for which the CodeDocument is to be created + */ +// source document version. +CodeDocument * CPPCodeGenerator::newClassifierCodeDocument (UMLClassifier * classifier) +{ + ClassifierCodeDocument *doc = new CPPSourceCodeDocument(classifier); + doc->initCodeClassFields(); + return doc; +} + +CPPHeaderCodeDocument * CPPCodeGenerator::newHeaderClassifierCodeDocument (UMLClassifier * classifier) +{ + CPPHeaderCodeDocument *doc = new CPPHeaderCodeDocument(classifier); + doc->initCodeClassFields(); + return doc; +} + +/** + * @return CPPMakefileCodeDocument + * @param this + */ +CPPMakefileCodeDocument * CPPCodeGenerator::newMakefileCodeDocument ( ) { + return new CPPMakefileCodeDocument(); +} + + +/** + * Overloaded so that we may have both source and header documents for each + * classifier. + */ +void CPPCodeGenerator::initFromParentDocument( ) { + + // Walk through the document converting classifiers into + // classifier code documents as needed (e.g only if doesn't exist) + UMLClassifierList concepts = UMLApp::app()->getDocument()->getClassesAndInterfaces(); + for (UMLClassifier *c = concepts.first(); c; c = concepts.next()) + { + + // Doesn't exist? Then build one. + CodeDocument * codeDoc = findCodeDocumentByClassifier(c); + if (!codeDoc) + { + codeDoc = newClassifierCodeDocument(c); + codeDoc->synchronize(); + addCodeDocument(codeDoc); // this will also add a unique tag to the code document + } + + CPPHeaderCodeDocument * hcodeDoc = findHeaderCodeDocumentByClassifier(c); + if (!hcodeDoc) + { + hcodeDoc = newHeaderClassifierCodeDocument(c); + hcodeDoc->synchronize(); + addHeaderCodeDocument(hcodeDoc); // this will also add a unique tag to the code document + } + } + +} + +// need to worry about adding both source, and header documents for each +// classifier +void CPPCodeGenerator::checkAddUMLObject (UMLObject * obj) { + if (!obj) + return; + + // if the obj being created is a native data type + // there's no reason to create a .h/.cpp file + if (isReservedKeyword(obj->getName())) + return; + + UMLClassifier * c = dynamic_cast<UMLClassifier*>(obj); + if(c) { + CodeDocument * cDoc = newClassifierCodeDocument(c); + CPPHeaderCodeDocument * hcodeDoc = newHeaderClassifierCodeDocument(c); + addCodeDocument(cDoc); + addHeaderCodeDocument(hcodeDoc); // this will also add a unique tag to the code document + } +} + +// need to worry about removing both source, and header documents for each +// classifier +void CPPCodeGenerator::checkRemoveUMLObject (UMLObject * obj) +{ + + if (!obj) + return; + + UMLClassifier * c = dynamic_cast<UMLClassifier*>(obj); + if(c) { + + // source + ClassifierCodeDocument * cDoc = (ClassifierCodeDocument*) findCodeDocumentByClassifier(c); + if (cDoc) + removeCodeDocument(cDoc); + + // header + CPPHeaderCodeDocument * hcodeDoc = findHeaderCodeDocumentByClassifier(c); + if (hcodeDoc) + removeHeaderCodeDocument(hcodeDoc); + } + +} + +void CPPCodeGenerator::initAttributes ( ) +{ + m_createMakefile = false; + + UMLApp::app()->setPolicyExt ( new CPPCodeGenerationPolicy(UMLApp::app()->getConfig()) ); + + // load Classifier documents from parent document + //initFromParentDocument(); +} + +QStringList CPPCodeGenerator::defaultDatatypes() { + return Codegen_Utils::cppDatatypes(); +} + +const QStringList CPPCodeGenerator::reservedKeywords() const { + return Codegen_Utils::reservedCppKeywords(); +} + +void CPPCodeGenerator::createDefaultStereotypes (){ + Codegen_Utils::createCppStereotypes(); +} + +#include "cppcodegenerator.moc" diff --git a/umbrello/umbrello/codegenerators/cppcodegenerator.h b/umbrello/umbrello/codegenerators/cppcodegenerator.h new file mode 100644 index 00000000..7104d403 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppcodegenerator.h @@ -0,0 +1,167 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Thu Jun 19 2003 + */ + + +#ifndef CPPCODEGENERATOR_H +#define CPPCODEGENERATOR_H + +#include <qstring.h> +#include "../codedocumentlist.h" +#include "../codeviewerstate.h" +#include "../codegenerator.h" +#include "../umldoc.h" +#include "cppmakecodedocument.h" + +class CodeViewerDialog; +class CPPHeaderCodeDocument; +class CodeBlockWithComments; +class KConfig; + +class CPPCodeGenerator : public CodeGenerator +{ + Q_OBJECT +public: + + static const bool DEFAULT_BUILD_MAKEFILE; + + // Constructors/Destructors + // + + /** + * Basic Constructor + */ + CPPCodeGenerator (); + + /** + * Empty Destructor + */ + virtual ~CPPCodeGenerator ( ); + + /** + * Set the value of m_createMakefile + * @param new_var the new value of m_createMakefile + */ + void setCreateProjectMakefile ( bool new_var ); + + /** + * Get the value of m_createMakefile + * @return the value of m_createMakefile + */ + bool getCreateProjectMakefile ( ); + + // Public attribute accessor methods + // + + QString fixTypeName(const QString &string); + + /** + * Add a header CodeDocument object from m_headercodedocumentVector List + */ + bool addHeaderCodeDocument ( CPPHeaderCodeDocument * doc ); + + /** + * Remove a header CodeDocument object from m_headercodedocumentVector List + */ + bool removeHeaderCodeDocument ( CPPHeaderCodeDocument * remove_object ); + + /** + * returns "Cpp" + */ + Uml::Programming_Language getLanguage(); + + // generate 2 different types of classifier code documents. + CodeDocument * newClassifierCodeDocument (UMLClassifier * classifier); + CPPHeaderCodeDocument * newHeaderClassifierCodeDocument (UMLClassifier * classifier); + + /** Get the editing dialog for this code document + */ + virtual CodeViewerDialog * getCodeViewerDialog( QWidget* parent, CodeDocument * doc, + Settings::CodeViewerState state); + + /** + * Write out all code documents to file as appropriate. + */ + virtual void writeCodeToFile ( ); + + // this method is here to provide class wizard the + // ability to write out only those classes which + // are selected by the user. + virtual void writeCodeToFile(UMLClassifierList &list); + + /** + * Add C++ primitives as datatypes + */ + QStringList defaultDatatypes(); + + /** + * Save the XMI representation of this object + */ + virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + + /** + * Add the default stereotypes for c++ (constructor, int etc) + */ + virtual void createDefaultStereotypes (); + + void initFromParentDocument( ); + +protected: + + /** + * @return CPPMakeCodeDocument + */ + CPPMakefileCodeDocument * newMakefileCodeDocument ( ); + + /** + * Find a cppheadercodedocument by the given classifier. + * @return CPPHeaderCodeDocument + * @param classifier + */ + CPPHeaderCodeDocument * findHeaderCodeDocumentByClassifier (UMLClassifier * classifier ); + +private: + + bool m_createMakefile; + + // a separate list for recording the header documents + CodeDocumentList m_headercodedocumentVector; + + void initAttributes ( ) ; + +public slots: + + /** These 2 functions check for adding or removing objects to the UMLDocument + * they are need to be overridden here because unlike in the Java (or most other lang) + * we add 2 types of classifiercodedocument per classifier, + * e.g. a "source" and a "header" document. + */ + virtual void checkAddUMLObject (UMLObject * obj); + virtual void checkRemoveUMLObject (UMLObject * obj); + + /** + * Force a synchronize of this code generator, and its present contents, to that of the parent UMLDocument. + * "UserGenerated" code will be preserved, but Autogenerated contents will be updated/replaced + * or removed as is apppropriate. + */ + virtual void syncCodeToDocument ( ); +}; + +#endif // CPPCODEGENERATOR_H diff --git a/umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.cpp b/umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.cpp new file mode 100644 index 00000000..ea5612c9 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.cpp @@ -0,0 +1,160 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + +#include "cppheaderclassdeclarationblock.h" +#include "cppcodegenerator.h" +#include "cppcodegenerationpolicy.h" +#include "cppcodedocumentation.h" +#include "../model_utils.h" +#include "../uml.h" + +// Constructors/Destructors +// + +CPPHeaderClassDeclarationBlock::CPPHeaderClassDeclarationBlock + ( CPPHeaderCodeDocument * parentDoc, const QString &startText, const QString &endText, const QString &comment) + : OwnedHierarchicalCodeBlock(parentDoc->getParentClassifier(), parentDoc, startText, endText, comment) +{ + init(parentDoc, comment); +} + +CPPHeaderClassDeclarationBlock::~CPPHeaderClassDeclarationBlock ( ) { } + +// +// Methods +// + +/** + * load params from the appropriate XMI element node. + */ +void CPPHeaderClassDeclarationBlock::loadFromXMI ( QDomElement & root ) +{ + setAttributesFromNode(root); +} + +/** set the class attributes from a passed object + */ +void CPPHeaderClassDeclarationBlock::setAttributesFromObject (TextBlock * obj) +{ + HierarchicalCodeBlock::setAttributesFromObject(obj); +} + +/** + * Save the XMI representation of this object + */ +void CPPHeaderClassDeclarationBlock::saveToXMI ( QDomDocument & doc, QDomElement & root ) { + QDomElement blockElement = doc.createElement( "cppheaderclassdeclarationblock" ); + + setAttributesOnNode(doc, blockElement); + + root.appendChild( blockElement ); +} + +// Accessor methods +// + +// Other methods +// + +/** + * update the start and end text for this hierarchicalcodeblock. + */ +void CPPHeaderClassDeclarationBlock::updateContent ( ) +{ + + CPPHeaderCodeDocument *parentDoc = dynamic_cast<CPPHeaderCodeDocument*>(getParentDocument()); + UMLClassifier *c = parentDoc->getParentClassifier(); + QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars(); + bool isInterface = parentDoc->parentIsInterface(); // a little shortcut + QString CPPHeaderClassName = CodeGenerator::cleanName(c->getName()); + bool forceDoc = UMLApp::app()->getCommonPolicy()->getCodeVerboseDocumentComments(); + + // COMMENT + + //check if class is abstract.. it should have abstract methods + if(!isInterface && c->getAbstract() && !c->hasAbstractOps()) + { + getComment()->setText("******************************* Abstract Class ****************************"+endLine + +CPPHeaderClassName+" does not have any pure virtual methods, but its author"+endLine + +" defined it as an abstract class, so you should not use it directly."+endLine + +" Inherit from it instead and create only objects from the derived classes"+endLine + +"*****************************************************************************"); + } else { + if(isInterface) + getComment()->setText("Interface "+CPPHeaderClassName+endLine+c->getDoc()); + else + getComment()->setText("Class "+CPPHeaderClassName+endLine+c->getDoc()); + } + + if(forceDoc || !c->getDoc().isEmpty()) + getComment()->setWriteOutText(true); + else + getComment()->setWriteOutText(false); + + + // Now set START/ENDING Text + QString startText = ""; + + /* + */ + + /* + if(parentDoc->parentIsInterface()) + startText.append("interface "); + else + */ + startText.append("class "); + + startText.append(CPPHeaderClassName); + + // write inheritances out + UMLClassifierList superclasses = c->findSuperClassConcepts(); + int nrof_superclasses = superclasses.count(); + + // write out inheritance + int i = 0; + if(nrof_superclasses >0) + startText.append(" : "); + for (UMLClassifier * concept= superclasses.first(); concept; concept = superclasses.next()) + { + startText.append(concept->getVisibility().toString() + ' ' + + CodeGenerator::cleanName(concept->getName())); + if(i != (nrof_superclasses-1)) + startText.append(", "); + i++; + } + + // Set the header and end text for the hier.codeblock + setStartText(startText+" {"); + + // setEndText("}"); // not needed + +} + +void CPPHeaderClassDeclarationBlock::init (CPPHeaderCodeDocument *parentDoc, const QString &comment) +{ + + setComment(new CPPCodeDocumentation(parentDoc)); + getComment()->setText(comment); + + setEndText("};"); + + updateContent(); + +} + + +#include "cppheaderclassdeclarationblock.moc" diff --git a/umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.h b/umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.h new file mode 100644 index 00000000..683f0475 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppheaderclassdeclarationblock.h @@ -0,0 +1,67 @@ + + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + +#ifndef CPPHEADERCLASSDECLARATIONBLOCK_H +#define CPPHEADERCLASSDECLARATIONBLOCK_H + +#include <qstring.h> + +#include "cppheadercodedocument.h" +#include "../ownedhierarchicalcodeblock.h" + +class CPPHeaderClassDeclarationBlock : public OwnedHierarchicalCodeBlock +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Empty Constructor + */ + explicit CPPHeaderClassDeclarationBlock ( CPPHeaderCodeDocument * parentDoc, const QString &start = "", const QString &endText = "}", const QString &comment = ""); + + /** + * Empty Destructor + */ + virtual ~CPPHeaderClassDeclarationBlock ( ); + + /** + * Save the XMI representation of this object + */ + virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ); + + virtual void loadFromXMI ( QDomElement & root ); + +protected: + + /** set the class attributes from a passed object + */ + virtual void setAttributesFromObject (TextBlock * obj); + + /** + * Update the start/end text of this codeblock. + */ + void updateContent ( ); + +private: + + void init (CPPHeaderCodeDocument * parent, const QString &comment); + +}; + +#endif // CPPHEADERCLASSDECLARATIONBLOCK_H diff --git a/umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.cpp b/umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.cpp new file mode 100644 index 00000000..0ab67b85 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.cpp @@ -0,0 +1,170 @@ +/*************************************************************************** + * * + * 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 : Fri Aug 31 2003 + */ + +// own header +#include "cppheadercodeaccessormethod.h" + +// qt/kde includes +#include <kdebug.h> + +// local includes +#include "../attribute.h" +#include "../classifiercodedocument.h" +#include "cppcodegenerator.h" +#include "../umlobject.h" +#include "../umlrole.h" +#include "../uml.h" + +#include "cppsourcecodedocument.h" +#include "cppcodegenerationpolicy.h" +#include "cppcodeclassfield.h" +#include "cppcodedocumentation.h" + +// Constructors/Destructors +// + +CPPHeaderCodeAccessorMethod::CPPHeaderCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type) + : CodeAccessorMethod ( field ) +{ + setType(type); +} + +void CPPHeaderCodeAccessorMethod::update() +{ + updateMethodDeclaration(); + updateContent(); +} + +CPPHeaderCodeAccessorMethod::~CPPHeaderCodeAccessorMethod ( ) { } + +// Other +// + +// we basically want to update the body of this method +void CPPHeaderCodeAccessorMethod::updateContent( ) +{ + CodeClassField * parentField = getParentClassField(); + CPPCodeClassField * cppfield = dynamic_cast<CPPCodeClassField*>(parentField); + CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt(); + CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); + bool isInlineMethod = policy->getAccessorsAreInline( ); + Uml::Visibility scope = parentField->getVisibility(); + QString variableName = cppfield->getFieldName(); + QString itemClassName = cppfield->getTypeName(); + QString text; + + if(isInlineMethod) { + switch(getType()) { + case CodeAccessorMethod::ADD: + text = policy->getVectorMethodAppend(variableName, itemClassName); + break; + case CodeAccessorMethod::REMOVE: + text = policy->getVectorMethodRemove(variableName, itemClassName); + break; + case CodeAccessorMethod::SET: + text = variableName+" = value;"; + break; + case CodeAccessorMethod::LIST: + case CodeAccessorMethod::GET: + default: + text = "return " + variableName + ';'; + break; + } + } + + setText(text); +} + +// we basically want to update the start text of this method +void CPPHeaderCodeAccessorMethod::updateMethodDeclaration() +{ + + CodeClassField * parentField = getParentClassField(); + ClassifierCodeDocument * doc = parentField->getParentDocument(); + CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt(); + CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); + CPPCodeClassField * cppfield = dynamic_cast<CPPCodeClassField*>(parentField); + + bool isInlineMethod = policy->getAccessorsAreInline( ); + + QString vectorClassName = policy->getVectorClassName(); + QString fieldName = cppfield->getFieldName(); + QString fieldType = cppfield->getTypeName(); + QString objectType = cppfield->getListObjectType(); + if(objectType.isEmpty()) + objectType = fieldName; + + QString methodReturnType = "void"; + QString methodName; + QString methodParams; + QString headerText; + QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars(); + + switch(getType()) { + case CodeAccessorMethod::ADD: + methodName = "add_"+fieldType; + methodReturnType = "void"; + methodParams = objectType+" value "; + headerText = "Add a "+fieldName+" object to the "+fieldName+"List"+endLine+getParentObject()->getDoc()+endLine+"@return void"; + break; + case CodeAccessorMethod::REMOVE: + methodName = "remove_"+fieldType; + methodParams = objectType+" value "; + methodReturnType = "void"; + headerText = "Remove a "+fieldName+" object from the "+fieldName+"List"+endLine+getParentObject()->getDoc()+endLine+"@return void"; + break; + case CodeAccessorMethod::LIST: + methodName = "get_"+fieldType+"_list"; + methodReturnType = vectorClassName; + headerText = "Get the "+fieldName+"List"+endLine+getParentObject()->getDoc()+endLine+"@return "+vectorClassName+"with list of objects"; + break; + case CodeAccessorMethod::SET: + methodName = "set_"+fieldName; + methodParams = fieldType+" value "; + methodReturnType = "void"; + headerText = "Set the value of "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@param value the value of "+fieldName; + break; + case CodeAccessorMethod::GET: + default: + methodName = "get_"+fieldName; + methodReturnType = fieldType; + headerText = "Get the value of "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@return the value of "+fieldName; + break; + } + + // set header + CPPCodeDocumentation * header = new CPPCodeDocumentation(doc); + if(!getParentObject()->getDoc().isEmpty()) + header->setText(headerText); + setComment(header); + + // set start/end method text + QString startText = methodReturnType + ' ' + methodName + " (" + methodParams +')'; + if (isInlineMethod) + startText += " {"; + else + startText += ';'; + QString endText = (isInlineMethod ? "}" : ""); + + setStartMethodText(startText); + setEndMethodText(endText); + + setOverallIndentationLevel(1); +} + + + +#include "cppheadercodeaccessormethod.moc" diff --git a/umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.h b/umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.h new file mode 100644 index 00000000..7b39fc6d --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppheadercodeaccessormethod.h @@ -0,0 +1,57 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Fri Aug 31 2003 + */ + +#ifndef CPPHEADERACCESSORMETHOD_H +#define CPPHEADERACCESSORMETHOD_H + +#include "../codeaccessormethod.h" + +#include <qstring.h> + +class CodeClassField; + +class CPPHeaderCodeAccessorMethod : public CodeAccessorMethod +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Empty Constructor + */ + CPPHeaderCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type); + + /** + * Empty Destructor + */ + virtual ~CPPHeaderCodeAccessorMethod ( ); + + /** + * Must be called before this object is usable + */ + void update(); + +protected: + + virtual void updateMethodDeclaration(); + virtual void updateContent(); + +private: + +}; + +#endif // CPPHEADERACCESSORMETHOD_H diff --git a/umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.cpp b/umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.cpp new file mode 100644 index 00000000..0fdfeb0a --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.cpp @@ -0,0 +1,78 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + +#include "cppheadercodeclassfielddeclarationblock.h" + +#include "cppcodeclassfield.h" +#include "cppheadercodedocument.h" + +// Constructors/Destructors +// + +CPPHeaderCodeClassFieldDeclarationBlock::CPPHeaderCodeClassFieldDeclarationBlock ( CodeClassField * parent ) + : CodeClassFieldDeclarationBlock ( parent ) +{ + setOverallIndentationLevel(1); + updateContent(); +} + +CPPHeaderCodeClassFieldDeclarationBlock::~CPPHeaderCodeClassFieldDeclarationBlock ( ) { } + +// +// Methods +// + +// Other methods +// + +/** + */ +void CPPHeaderCodeClassFieldDeclarationBlock::updateContent( ) +{ + UMLObject *umlparent = CodeClassFieldDeclarationBlock::getParentObject(); + if (umlparent == NULL) { + return; + } + + CodeClassField * cf = getParentClassField(); + CPPCodeClassField * hcppcf = dynamic_cast<CPPCodeClassField*>(cf); + + // Set the comment + QString notes = umlparent->getDoc(); + getComment()->setText(notes); + if(notes.isEmpty()) + getComment()->setWriteOutText(false); + else + getComment()->setWriteOutText(true); + + + // Set the body + QString staticValue = umlparent->getStatic() ? "static " : ""; + QString typeName = hcppcf->getTypeName(); + QString fieldName = hcppcf->getFieldName(); + + // Ugh. Sloppy exception. + if (!cf->parentIsAttribute() && !cf->fieldIsSingleValue()) + typeName = hcppcf->getListFieldClassName(); + + QString body = staticValue + ' ' + typeName + ' ' + fieldName + ';'; + + setText(body); + +} + + + +#include "cppheadercodeclassfielddeclarationblock.moc" diff --git a/umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.h b/umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.h new file mode 100644 index 00000000..755507c6 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppheadercodeclassfielddeclarationblock.h @@ -0,0 +1,51 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + +#ifndef CPPHEADERCODECLASSFIELDDECLARATIONBLOCK_H +#define CPPHEADERCODECLASSFIELDDECLARATIONBLOCK_H + +#include <qstring.h> + +#include "../codeclassfielddeclarationblock.h" + +class CPPHeaderCodeClassFieldDeclarationBlock : public CodeClassFieldDeclarationBlock +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructor + */ + CPPHeaderCodeClassFieldDeclarationBlock ( CodeClassField * parent ); + + /** + * Empty Destructor + */ + virtual ~CPPHeaderCodeClassFieldDeclarationBlock ( ); + +protected: + + // this will be called by syncToParent whenever the parent object is "modified" + void updateContent ( ); + +private: + + +}; + +#endif // CPPHEADERCODECLASSFIELDDECLARATIONBLOCK_H diff --git a/umbrello/umbrello/codegenerators/cppheadercodedocument.cpp b/umbrello/umbrello/codegenerators/cppheadercodedocument.cpp new file mode 100644 index 00000000..fe909c5d --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppheadercodedocument.cpp @@ -0,0 +1,813 @@ +/*************************************************************************** + * * + * 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 : Thu Aug 28 2003 + */ + +/** + We carve the CPP document up into 2 documents, "source" and "header". + This one represents the header portion. + The sections of each are as follows: + + * header + * includes + * import statements + * class declaration + * guts of the class (e.g. field decl, accessor methods, operations, dependant classes) +*/ + +// own header +#include "cppheadercodedocument.h" + +// qt/kde includes +#include <qregexp.h> +#include <kdebug.h> + +// local includes +#include "cppcodegenerator.h" +#include "cppcodegenerationpolicy.h" +#include "cppcodedocumentation.h" +#include "cppheadercodeaccessormethod.h" +#include "cppheadercodeoperation.h" +#include "cppheaderclassdeclarationblock.h" +#include "cppheadercodeclassfielddeclarationblock.h" +#include "../umlpackagelist.h" +#include "../package.h" +#include "../umlclassifierlistitemlist.h" +#include "../classifierlistitem.h" +#include "../enum.h" +#include "../uml.h" + +// Constructors/Destructors +// + +CPPHeaderCodeDocument::CPPHeaderCodeDocument ( UMLClassifier * concept ) + : ClassifierCodeDocument (concept) +{ + setFileExtension(".h"); + + //initCodeClassFields(); // this is dubious because it calls down to + // CodeGenFactory::newCodeClassField(this) + // but "this" is still in construction at that time. + + // needed? I doubt it, but it feels good to do it. + classDeclCodeBlock = 0; + publicBlock = 0; + protectedBlock = 0; + privateBlock = 0; + namespaceBlock = 0; + pubConstructorBlock = 0; + protConstructorBlock = 0; + privConstructorBlock = 0; + pubOperationsBlock = 0; + privOperationsBlock = 0; + protOperationsBlock = 0; + + // this will call updateContent() as well as other things that sync our document. + //synchronize(); + +} + +CPPHeaderCodeDocument::~CPPHeaderCodeDocument ( ) { + resetTextBlocks(); +} + +// +// Methods +// + +// Accessor methods +// + +CPPHeaderClassDeclarationBlock * CPPHeaderCodeDocument::getClassDecl() +{ + + if(!classDeclCodeBlock) { + classDeclCodeBlock = new CPPHeaderClassDeclarationBlock (this); // was deleted before our load + classDeclCodeBlock->setTag("classDeclarationBlock"); + } + return classDeclCodeBlock; +} + +// Other methods +// + +// Sigh. NOT optimal. The only reason that we need to have this +// is so we can create the CPPHeaderClassDeclarationBlock. +// would be better if we could create a handler interface that each +// codeblock used so all we have to do here is add the handler +void CPPHeaderCodeDocument::loadChildTextBlocksFromNode ( QDomElement & root) +{ + + QDomNode tnode = root.firstChild(); + QDomElement telement = tnode.toElement(); + bool loadCheckForChildrenOK = false; + while( !telement.isNull() ) { + QString nodeName = telement.tagName(); + + if( nodeName == "textblocks" ) { + + QDomNode node = telement.firstChild(); + QDomElement element = node.toElement(); + + // if there is nothing to begin with, then we don't worry about it + loadCheckForChildrenOK = element.isNull() ? true : false; + + while( !element.isNull() ) { + QString name = element.tagName(); + + if( name == "codecomment" ) { + CodeComment * block = new CPPCodeDocumentation(this); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add codeComment to :"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "codeaccessormethod" || + name == "ccfdeclarationcodeblock" + ) { + QString acctag = element.attribute("tag",""); + // search for our method in the + TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag); + if(!tb || !addTextBlock(tb)) + { + kError()<<"Unable to add codeclassfield child method to:"<<this<<endl; + // DON'T delete + } else + loadCheckForChildrenOK= true; + + } else + if( name == "codeblock" ) { + CodeBlock * block = newCodeBlock(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add codeBlock to :"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "codeblockwithcomments" ) { + CodeBlockWithComments * block = newCodeBlockWithComments(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add codeBlockwithcomments to:"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "header" ) { + // do nothing.. this is treated elsewhere + } else + if( name == "hierarchicalcodeblock" ) { + HierarchicalCodeBlock * block = newHierarchicalCodeBlock(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add hierarchicalcodeBlock to:"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "codeoperation" ) { + // find the code operation by id + QString id = element.attribute("parent_id","-1"); + UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(STR2ID(id)); + UMLOperation * op = dynamic_cast<UMLOperation*>(obj); + if(op) { + CodeOperation * block = new CPPHeaderCodeOperation(this, op); + block->loadFromXMI(element); + if(addTextBlock(block)) + loadCheckForChildrenOK= true; + else + { + kError()<<"Unable to add codeoperation to:"<<this<<endl; + block->deleteLater(); + } + } else + kError()<<"Unable to find operation create codeoperation for:"<<this<<endl; + } + else + if( name == "cppheaderclassdeclarationblock" ) + { + CPPHeaderClassDeclarationBlock * block = getClassDecl(); + block->loadFromXMI(element); + // normally this would be populated by the following syncToparent + // call, but we cant wait for it, so lets just do it now. + namespaceBlock = getHierarchicalCodeBlock("namespace", "Namespace", 0); + + if(!namespaceBlock || !namespaceBlock->addTextBlock(block)) + { + kError()<<"Error:cant add class declaration codeblock"<<endl; + // DON'T delete/release block + // block->release(); + } else + loadCheckForChildrenOK= true; + + } + // only needed for extreme debugging conditions (E.g. making new codeclassdocument loader) + //else + //kDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignorning"<<endl; + + node = element.nextSibling(); + element = node.toElement(); + } + break; + } + + tnode = telement.nextSibling(); + telement = tnode.toElement(); + } + + if(!loadCheckForChildrenOK) + { + CodeDocument * test = dynamic_cast<CodeDocument*>(this); + if(test) + { + kWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<<test->getFileName()<<" "<<this<<endl; + } else { + HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(this); + if(hb) + kWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<<hb->getTag()<<" "<<this<<endl; + else + kDebug()<<" loadChildBlocks : unable to initialize any child blocks in UNKNOWN OBJ:"<<this<<endl; + } + } + +} + +void CPPHeaderCodeDocument::resetTextBlocks() +{ + + // all special pointers need to be zero'd out. + classDeclCodeBlock = 0; + publicBlock = 0; + protectedBlock = 0; + privateBlock = 0; + namespaceBlock = 0; + pubConstructorBlock = 0; + protConstructorBlock = 0; + privConstructorBlock = 0; + pubOperationsBlock = 0; + privOperationsBlock = 0; + protOperationsBlock = 0; + + // now do the traditional release of child text blocks + ClassifierCodeDocument::resetTextBlocks(); + +} + +/** + * @param op + */ +// in the vannilla version, we just tack all operations on the end +// of the document +bool CPPHeaderCodeDocument::addCodeOperation (CodeOperation * op ) +{ + Uml::Visibility scope = op->getParentOperation()->getVisibility(); + if(!op->getParentOperation()->isLifeOperation()) + { + switch (scope) { + default: + case Uml::Visibility::Public: + return pubOperationsBlock->addTextBlock(op); + break; + case Uml::Visibility::Protected: + return protOperationsBlock->addTextBlock(op); + break; + case Uml::Visibility::Private: + return privOperationsBlock->addTextBlock(op); + break; + } + } else { + switch (scope) { + default: + case Uml::Visibility::Public: + return pubConstructorBlock->addTextBlock(op); + break; + case Uml::Visibility::Protected: + return protConstructorBlock->addTextBlock(op); + break; + case Uml::Visibility::Private: + return privConstructorBlock->addTextBlock(op); + break; + } + } +} + + +/** + * Save the XMI representation of this object + * @return bool status of save + */ +/* +void CPPHeaderCodeDocument::saveToXMI ( QDomDocument & doc, QDomElement & root ) +{ + QDomElement docElement = doc.createElement( "" ); + + setAttributesOnNode(doc, docElement); + + root.appendChild( docElement ); +} +*/ + +// This method will cause the class to rebuild its text representation. +// based on the parent classifier object. +// For any situation in which this is called, we are either building the code +// document up, or replacing/regenerating the existing auto-generated parts. As +// such, we will want to insert everything we resonablely will want +// during creation. We can set various parts of the document (esp. the +// comments) to appear or not, as needed. +void CPPHeaderCodeDocument::updateContent( ) +{ + // Gather info on the various fields and parent objects of this class... + UMLClassifier * c = getParentClassifier(); + CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt(); + CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); + + // first, set the global flag on whether or not to show classfield info + CodeClassFieldList * cfList = getCodeClassFieldList(); + for(CodeClassField * field = cfList->first(); field; field = cfList->next()) + field->setWriteOutMethods(policy->getAutoGenerateAccessors()); + + // attribute-based ClassFields + // we do it this way to have the static fields sorted out from regular ones + CodeClassFieldList staticPublicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Public ); + CodeClassFieldList publicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Public ); + CodeClassFieldList staticProtectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Protected ); + CodeClassFieldList protectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Protected ); + CodeClassFieldList staticPrivateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Private ); + CodeClassFieldList privateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Private); + + // association-based ClassFields + // don't care if they are static or not..all are lumped together + CodeClassFieldList publicPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Public); + CodeClassFieldList publicAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Public); + CodeClassFieldList publicCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Public ); + + CodeClassFieldList protPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Protected); + CodeClassFieldList protAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Protected); + CodeClassFieldList protCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Protected); + + CodeClassFieldList privPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Private); + CodeClassFieldList privAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Private); + CodeClassFieldList privCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Private); + + bool hasOperationMethods = c->getOpList().last() ? true : false; + bool hasNamespace = false; + bool isEnumeration = false; + bool isInterface = parentIsInterface(); + bool hasclassFields = hasClassFields(); + bool forcedoc = UMLApp::app()->getCommonPolicy()->getCodeVerboseDocumentComments(); + QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars(); + + UMLClassifierList superclasses = c->findSuperClassConcepts(); + + + // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT + // + + // Write the hash define stuff to prevent multiple parsing/inclusion of header + QString cppClassName = CodeGenerator::cleanName(c->getName()); + QString hashDefine = CodeGenerator::cleanName(c->getName().upper().simplifyWhiteSpace()); + QString defText = "#ifndef "+hashDefine + "_H"+ endLine + "#define "+ hashDefine + "_H"; + addOrUpdateTaggedCodeBlockWithComments("hashDefBlock", defText, "", 0, false); + + // INCLUDE CODEBLOCK + // + // 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 cpp compilers + // don't slow down or anything. (TZ) + QString includeStatement = ""; + bool stringGlobal = policy->stringIncludeIsGlobal(); + QString sStartBrak = stringGlobal ? "<" : "\""; + QString sEndBrak = stringGlobal ? ">" : "\""; + includeStatement.append("#include "+sStartBrak+policy->getStringClassNameInclude()+sEndBrak+endLine); + if ( hasObjectVectorClassFields() ) + { + bool vecGlobal = policy->vectorIncludeIsGlobal(); + QString vStartBrak = vecGlobal ? "<" : "\""; + QString vEndBrak = vecGlobal ? ">" : "\""; + QString value ="#include "+vStartBrak+policy->getVectorClassNameInclude()+vEndBrak; + includeStatement.append(value+endLine); + } + + //only include classes in a different package from this class + UMLPackageList includes; + QMap<UMLPackage *,QString> packageMap; // so we don't repeat packages + + CodeGenerator::findObjectsRelated(c,includes); + for(UMLPackage *con = includes.first(); con ; con = includes.next()) + if (con->getBaseType() != Uml::ot_Datatype && !packageMap.contains(con)) + { + packageMap.insert(con,con->getPackage()); + if(con != getParentClassifier()) + includeStatement.append("#include \""+CodeGenerator::cleanName(con->getName().lower())+".h\""+endLine); + } + // now, add/update the includes codeblock + CodeBlockWithComments * inclBlock = addOrUpdateTaggedCodeBlockWithComments("includes", includeStatement, QString::null, 0, false); + if(includeStatement.isEmpty() && inclBlock->getContentType() == CodeBlock::AutoGenerated) + inclBlock->setWriteOutText(false); + else + inclBlock->setWriteOutText(true); + + // Using + QString usingStatement; + for(UMLClassifier *classifier = superclasses.first(); classifier ; classifier = superclasses.next()) { + if(classifier->getPackage()!=c->getPackage() && !classifier->getPackage().isEmpty()) { + usingStatement.append("using "+CodeGenerator::cleanName(c->getPackage())+"::"+cleanName(c->getName())+';'+endLine); + } + } + CodeBlockWithComments * usingBlock = addOrUpdateTaggedCodeBlockWithComments("using", usingStatement, "", 0, false); + if(usingStatement.isEmpty() && usingBlock->getContentType() == CodeBlock::AutoGenerated) + usingBlock->setWriteOutText(false); + else + usingBlock->setWriteOutText(true); + + // namespace + // This needs special treatment. We cant use "nowriteouttext" for this, as + // that will prevent the class declaration from being written. Instead, we + // check if "hasNamspace" is true or not, and then indent the remaining code + // appropriately as well as set the start/end text of this namespace block. + if (c->getUMLPackage() && policy->getPackageIsNamespace()) + hasNamespace = true; + else + hasNamespace = false; + + // set start/end text of namespace block + namespaceBlock = getHierarchicalCodeBlock("namespace", "Namespace", 0); + if(hasNamespace) { + UMLPackageList pkgList = c->getPackages(); + QString pkgs; + UMLPackage *pkg; + for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) { + pkgs += "namespace " + CodeGenerator::cleanName(pkg->getName()) + " { "; + } + namespaceBlock->setStartText(pkgs); + QString closingBraces; + for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) { + closingBraces += "} "; + } + namespaceBlock->setEndText(closingBraces); + namespaceBlock->getComment()->setWriteOutText(true); + } else { + namespaceBlock->setStartText(""); + namespaceBlock->setEndText(""); + namespaceBlock->getComment()->setWriteOutText(false); + } + + // Enum types for include + if (!isInterface) { + QString enumStatement; + QString indent = UMLApp::app()->getCommonPolicy()->getIndentation(); + UMLEnum* e = dynamic_cast<UMLEnum*>(c); + if (e) { + enumStatement.append(indent + "enum " + cppClassName + " {" + endLine); + + // populate + UMLClassifierListItemList ell = e->getFilteredList(Uml::ot_EnumLiteral); + for (UMLClassifierListItem *el=ell.first(); el ; ) { + enumStatement.append(indent+indent); + enumStatement.append(CodeGenerator::cleanName(el->getName())); + if ((el=ell.next()) != 0) + enumStatement.append(", "+endLine); + else + break; + enumStatement.append(endLine); + } + enumStatement.append(indent+"};"); + isEnumeration = true; + } + namespaceBlock->addOrUpdateTaggedCodeBlockWithComments("enums", enumStatement, "", 0, false); + } + + // CLASS DECLARATION BLOCK + // + + // add the class declaration block to the namespace block. + CPPHeaderClassDeclarationBlock * myClassDeclCodeBlock = getClassDecl(); + namespaceBlock->addTextBlock(myClassDeclCodeBlock); // note: wont add if already present + + // Is this really true?? hmm.. + if(isEnumeration) + myClassDeclCodeBlock->setWriteOutText(false); // not written out IF its an enumeration class + else + myClassDeclCodeBlock->setWriteOutText(true); + + // + // Main Sub-Blocks + // + + // declare public, protected and private methods, attributes (fields). + // set the start text ONLY if this is the first time we created the objects. + bool createdPublicBlock = publicBlock == 0 ? true : false; + publicBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("publicBlock","Public stuff",0); + if (createdPublicBlock) + publicBlock->setStartText("public:"); + + bool createdProtBlock = protectedBlock == 0 ? true : false; + protectedBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("protectedBlock","Protected stuff",0); + if(createdProtBlock) + protectedBlock->setStartText("protected:"); + + bool createdPrivBlock = privateBlock == 0 ? true : false; + privateBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("privateBlock","Private stuff",0); + if(createdPrivBlock) + privateBlock->setStartText("private:"); + + // + // * CLASS FIELD declaration section + // + + // setup/get/create the field declaration code block + // + + // public fields: Update the comment: we only set comment to appear under the following conditions + HierarchicalCodeBlock * publicFieldDeclBlock = publicBlock->getHierarchicalCodeBlock("publicFieldsDecl", "Fields", 1); + CodeComment * pubFcomment = publicFieldDeclBlock->getComment(); + if (!forcedoc && !hasclassFields ) + pubFcomment->setWriteOutText(false); + else + pubFcomment->setWriteOutText(true); + + // protected fields: Update the comment: we only set comment to appear under the following conditions + HierarchicalCodeBlock * protectedFieldDeclBlock = protectedBlock->getHierarchicalCodeBlock("protectedFieldsDecl", "Fields", 1); + CodeComment * protFcomment = protectedFieldDeclBlock->getComment(); + if (!forcedoc && !hasclassFields ) + protFcomment->setWriteOutText(false); + else + protFcomment->setWriteOutText(true); + + // private fields: Update the comment: we only set comment to appear under the following conditions + HierarchicalCodeBlock * privateFieldDeclBlock = privateBlock->getHierarchicalCodeBlock("privateFieldsDecl", "Fields", 1); + CodeComment * privFcomment = privateFieldDeclBlock->getComment(); + if (!forcedoc && !hasclassFields ) + privFcomment->setWriteOutText(false); + else + privFcomment->setWriteOutText(true); + + + // now actually declare the fields within the appropriate HCodeBlock + // + + // public + declareClassFields(staticPublicAttribClassFields, publicFieldDeclBlock); + declareClassFields(publicAttribClassFields, publicFieldDeclBlock); + declareClassFields(publicPlainAssocClassFields, publicFieldDeclBlock); + declareClassFields(publicAggregationClassFields, publicFieldDeclBlock); + declareClassFields(publicCompositionClassFields, publicFieldDeclBlock); + + // protected + declareClassFields(staticProtectedAttribClassFields, protectedFieldDeclBlock); + declareClassFields(protectedAttribClassFields, protectedFieldDeclBlock); + declareClassFields(protPlainAssocClassFields, protectedFieldDeclBlock); + declareClassFields(protAggregationClassFields, protectedFieldDeclBlock); + declareClassFields(protCompositionClassFields, protectedFieldDeclBlock); + + // private + declareClassFields(staticPrivateAttribClassFields, privateFieldDeclBlock); + declareClassFields(privateAttribClassFields, privateFieldDeclBlock); + declareClassFields(privPlainAssocClassFields, privateFieldDeclBlock); + declareClassFields(privAggregationClassFields, privateFieldDeclBlock); + declareClassFields(privCompositionClassFields, privateFieldDeclBlock); + + // + // METHODS section + // + + // get/create the method codeblock + + // public methods + HierarchicalCodeBlock * pubMethodsBlock = publicBlock->getHierarchicalCodeBlock("pubMethodsBlock", "", 1); + CodeComment * pubMethodsComment = pubMethodsBlock->getComment(); + // set conditions for showing this comment + if (!forcedoc && !hasclassFields && !hasOperationMethods) + pubMethodsComment->setWriteOutText(false); + else + pubMethodsComment->setWriteOutText(true); + + // protected methods + HierarchicalCodeBlock * protMethodsBlock = protectedBlock->getHierarchicalCodeBlock("protMethodsBlock", "", 1); + CodeComment * protMethodsComment = protMethodsBlock->getComment(); + // set conditions for showing this comment + if (!forcedoc && !hasclassFields && !hasOperationMethods) + protMethodsComment->setWriteOutText(false); + else + protMethodsComment->setWriteOutText(true); + + // private methods + HierarchicalCodeBlock * privMethodsBlock = privateBlock->getHierarchicalCodeBlock("privMethodsBlock", "", 1); + CodeComment * privMethodsComment = privMethodsBlock->getComment(); + // set conditions for showing this comment + if (!forcedoc && !hasclassFields && !hasOperationMethods) + privMethodsComment->setWriteOutText(false); + else + privMethodsComment->setWriteOutText(true); + + + // METHODS sub-section : constructor methods + // + CodeGenerationPolicy *pol = UMLApp::app()->getCommonPolicy(); + + // setup/get/create the constructor codeblocks + + // public + pubConstructorBlock = pubMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1); + // special condiions for showing comment: only when autogenerateding empty constructors + // Although, we *should* check for other constructor methods too + CodeComment * pubConstComment = pubConstructorBlock->getComment(); + if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors())) + pubConstComment->setWriteOutText(false); + else + pubConstComment->setWriteOutText(true); + + // protected + protConstructorBlock = protMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1); + // special condiions for showing comment: only when autogenerateding empty constructors + // Although, we *should* check for other constructor methods too + CodeComment * protConstComment = protConstructorBlock->getComment(); + if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors())) + protConstComment->setWriteOutText(false); + else + protConstComment->setWriteOutText(true); + + // private + privConstructorBlock = privMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1); + // special condiions for showing comment: only when autogenerateding empty constructors + // Although, we *should* check for other constructor methods too + CodeComment * privConstComment = privConstructorBlock->getComment(); + if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors())) + privConstComment->setWriteOutText(false); + else + privConstComment->setWriteOutText(true); + + // add/get the empty constructor. I guess since there is no + // meta-data to state what the scope of this method is, we will make it + // "public" as a default. This might present problems if the user wants + // to move the block into the "private" or "protected" blocks. + QString emptyConstStatement = cppClassName + " ( ) { }"; + + // search for this first in the entire document. IF not present, put + // it in the public constructor method block + TextBlock * emptyConstTb = findTextBlockByTag("emptyconstructor", true); + CodeBlockWithComments * emptyConstBlock = dynamic_cast<CodeBlockWithComments*>(emptyConstTb); + if(!emptyConstBlock) + emptyConstBlock = pubConstructorBlock->addOrUpdateTaggedCodeBlockWithComments("emptyconstructor", emptyConstStatement, "Empty Constructor", 1, false); + + // Now, as an additional condition we only show the empty constructor block + // IF it was desired to be shown + if(!isInterface && pol->getAutoGenerateConstructors()) + emptyConstBlock->setWriteOutText(true); + else + emptyConstBlock->setWriteOutText(false); + + + // METHODS subsection : ACCESSOR METHODS + // + + // get/create the accessor codeblock + + // public + HierarchicalCodeBlock * pubAccessorBlock = pubMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1); + // set conditions for showing section comment + CodeComment * pubAccessComment = pubAccessorBlock->getComment(); + if (!forcedoc && !hasclassFields) + pubAccessComment->setWriteOutText(false); + else + pubAccessComment->setWriteOutText(true); + + // protected + HierarchicalCodeBlock * protAccessorBlock = protMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1); + // set conditions for showing section comment + CodeComment * protAccessComment = protAccessorBlock->getComment(); + if (!forcedoc && !hasclassFields) + protAccessComment->setWriteOutText(false); + else + protAccessComment->setWriteOutText(true); + + // private + HierarchicalCodeBlock * privAccessorBlock = privMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1); + // set conditions for showing section comment + CodeComment * privAccessComment = privAccessorBlock->getComment(); + // We've to copy the private accessorMethods to the public block + if (!forcedoc && !hasclassFields) + privAccessComment->setWriteOutText(false); + else + privAccessComment->setWriteOutText(true); + + // now, 2 sub-sub sections in accessor block + // add/update accessor methods for attributes + HierarchicalCodeBlock * pubStaticAccessors = pubAccessorBlock->getHierarchicalCodeBlock("pubStaticAccessorMethods", "", 1); + HierarchicalCodeBlock * pubRegularAccessors = pubAccessorBlock->getHierarchicalCodeBlock("pubRegularAccessorMethods", "", 1); + pubStaticAccessors->getComment()->setWriteOutText(false); // never write block comment + pubRegularAccessors->getComment()->setWriteOutText(false); // never write block comment + + HierarchicalCodeBlock * protStaticAccessors = protAccessorBlock->getHierarchicalCodeBlock("protStaticAccessorMethods", "", 1); + HierarchicalCodeBlock * protRegularAccessors = protAccessorBlock->getHierarchicalCodeBlock("protRegularAccessorMethods", "", 1); + protStaticAccessors->getComment()->setWriteOutText(false); // never write block comment + protRegularAccessors->getComment()->setWriteOutText(false); // never write block comment + + HierarchicalCodeBlock * privStaticAccessors = privAccessorBlock->getHierarchicalCodeBlock("privStaticAccessorMethods", "", 1); + HierarchicalCodeBlock * privRegularAccessors = privAccessorBlock->getHierarchicalCodeBlock("privRegularAccessorMethods", "", 1); + privStaticAccessors->getComment()->setWriteOutText(false); // never write block comment + privRegularAccessors->getComment()->setWriteOutText(false); // never write block comment + + // now add in accessors as appropriate + + // public stuff + pubStaticAccessors->addCodeClassFieldMethods(staticPublicAttribClassFields); + pubRegularAccessors->addCodeClassFieldMethods(publicAttribClassFields); + + // generate accessors as public + if (policy && policy->getAccessorsArePublic()) + { + pubRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields); + pubRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields); + } + + pubRegularAccessors->addCodeClassFieldMethods(publicPlainAssocClassFields); + pubRegularAccessors->addCodeClassFieldMethods(publicAggregationClassFields); + pubRegularAccessors->addCodeClassFieldMethods(publicCompositionClassFields); + + // protected stuff + protStaticAccessors->addCodeClassFieldMethods(staticProtectedAttribClassFields); + + // accessors are public so we don't have to create it here + if (policy && !policy->getAccessorsArePublic()) + protRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields); + + protRegularAccessors->addCodeClassFieldMethods(protPlainAssocClassFields); + protRegularAccessors->addCodeClassFieldMethods(protAggregationClassFields); + protRegularAccessors->addCodeClassFieldMethods(protCompositionClassFields); + + // private stuff + privStaticAccessors->addCodeClassFieldMethods(staticPrivateAttribClassFields); + + // accessors are public so we don't have to create it here + if (policy && !policy->getAccessorsArePublic()) + privRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields); + + privRegularAccessors->addCodeClassFieldMethods(privPlainAssocClassFields); + privRegularAccessors->addCodeClassFieldMethods(privAggregationClassFields); + privRegularAccessors->addCodeClassFieldMethods(privCompositionClassFields); + + + // METHODS subsection : Operation methods (e.g. methods derive from operations but which arent constructors) + // + + // setup/get/create the operations codeblock + + // public + pubOperationsBlock = pubMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1); + // set conditions for showing section comment + CodeComment * pubOcomment = pubOperationsBlock->getComment(); + if (!forcedoc && !hasOperationMethods ) + pubOcomment->setWriteOutText(false); + else + pubOcomment->setWriteOutText(true); + + //protected + protOperationsBlock = protMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1); + // set conditions for showing section comment + CodeComment * protOcomment = protOperationsBlock->getComment(); + if (!forcedoc && !hasOperationMethods ) + protOcomment->setWriteOutText(false); + else + protOcomment->setWriteOutText(true); + + //private + privOperationsBlock = privMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1); + // set conditions for showing section comment + CodeComment * privOcomment = privOperationsBlock->getComment(); + if (!forcedoc && !hasOperationMethods ) + privOcomment->setWriteOutText(false); + else + privOcomment->setWriteOutText(true); + + // Operations + // + // nothing to do here.. "updateOperations" in parent class puts things + // in the right place using the "addCodeOperation" method we defined in this class + + // FINISH up with hash def block close + QString defTextEnd = "#endif //"+hashDefine + "_H"; + addOrUpdateTaggedCodeBlockWithComments("hashDefBlockEnd", defTextEnd, "", 0, false); + +} + + +#include "cppheadercodedocument.moc" diff --git a/umbrello/umbrello/codegenerators/cppheadercodedocument.h b/umbrello/umbrello/codegenerators/cppheadercodedocument.h new file mode 100644 index 00000000..ca75627f --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppheadercodedocument.h @@ -0,0 +1,107 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Thu Aug 28 2003 + */ + +#ifndef CPPHEADERCODEDOCUMENT_H +#define CPPHEADERCODEDOCUMENT_H + +#include <qstring.h> + +#include "../codeclassfieldlist.h" +#include "../classifiercodedocument.h" +#include "../hierarchicalcodeblock.h" +#include "classifierinfo.h" + +class CPPHeaderClassDeclarationBlock; + +/** + * class CPPHeaderCodeDocument + * A CPP UMLClassifier Header Code Document. + */ + +class CPPHeaderCodeDocument : public ClassifierCodeDocument +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructor + */ + CPPHeaderCodeDocument (UMLClassifier * classifier); + + /** + * Empty Destructor + */ + virtual ~CPPHeaderCodeDocument ( ); + + /** add a code operation to this cpp classifier code document. + * @return bool which is true IF the code operation was added successfully + */ + bool addCodeOperation (CodeOperation * op ); + + /** + * Save the XMI representation of this object + */ + //virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ); + +protected: + + // reset/clear our inventory of textblocks in this document + void resetTextBlocks(); + + /** + * need to overwrite this for cpp header since we need to pick up the + * header class declaration block. + */ + virtual void loadChildTextBlocksFromNode ( QDomElement & root); + + void addOrUpdateCodeClassFieldMethodsInCodeBlock(CodeClassFieldList &list, CPPHeaderClassDeclarationBlock * codeBlock); + + /** + * create a new code comment. IN this case it is a CPPCodeDocumentation object. + */ + CodeComment * newCodeComment ( ); + + void updateContent(); + +private: + + CPPHeaderClassDeclarationBlock * classDeclCodeBlock; + + HierarchicalCodeBlock * publicBlock; + HierarchicalCodeBlock * privateBlock; + HierarchicalCodeBlock * protectedBlock; + + HierarchicalCodeBlock * namespaceBlock; + + HierarchicalCodeBlock * pubConstructorBlock; + HierarchicalCodeBlock * protConstructorBlock; + HierarchicalCodeBlock * privConstructorBlock; + + HierarchicalCodeBlock * pubOperationsBlock; + HierarchicalCodeBlock * privOperationsBlock; + HierarchicalCodeBlock * protOperationsBlock; + + /** + * + */ + CPPHeaderClassDeclarationBlock * getClassDecl(); + +}; + +#endif // CPPHEADERCODEDOCUMENT_H diff --git a/umbrello/umbrello/codegenerators/cppheadercodeoperation.cpp b/umbrello/umbrello/codegenerators/cppheadercodeoperation.cpp new file mode 100644 index 00000000..ca8ad727 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppheadercodeoperation.cpp @@ -0,0 +1,175 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + +#include "cppheadercodeoperation.h" + +#include "cppcodegenerator.h" +#include "cppcodegenerationpolicy.h" +#include "cppheadercodedocument.h" +#include "cppcodedocumentation.h" +#include "../uml.h" + +// Constructors/Destructors +// + +CPPHeaderCodeOperation::CPPHeaderCodeOperation + ( CPPHeaderCodeDocument * doc, UMLOperation *parent, const QString & body, const QString & comment ) + : CodeOperation (doc, parent, body, comment) +{ + // lets not go with the default comment and instead use + // full-blown cpp documentation object instead + setComment(new CPPCodeDocumentation(doc)); + + // these things never change.. + setOverallIndentationLevel(1); + + setText(""); + setStartMethodText(""); + setEndMethodText(""); + + updateMethodDeclaration(); + updateContent(); + +} + +CPPHeaderCodeOperation::~CPPHeaderCodeOperation ( ) { } + +// Other methods +// + +// we basically just want to know whether or not to print out +// the body of the operation. +// In C++ if the operations are inline, then we DO print out +// the body text. +void CPPHeaderCodeOperation::updateContent( ) +{ + CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt(); + CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); + bool isInlineMethod = policy->getOperationsAreInline( ); + + if(isInlineMethod) + setText(""); // change whatever it is to ""; +} + +// we basically want to update the doc and start text of this method +void CPPHeaderCodeOperation::updateMethodDeclaration() +{ + ClassifierCodeDocument *ccd = dynamic_cast<ClassifierCodeDocument*>(getParentDocument()); + bool isInterface = ccd->parentIsInterface(); + UMLOperation * o = getParentOperation(); + + CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt(); + CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); + bool isInlineMethod = policy->getOperationsAreInline( ); + + QString endLine = getNewLineEndingChars(); + + // first, the comment on the operation, IF its autogenerated/empty + QString comment = o->getDoc(); + if(comment.isEmpty() && getContentType() == CodeBlock::AutoGenerated) + { + UMLAttributeList parameters = o->getParmList(); + for(UMLAttributeListIt iterator(parameters); iterator.current(); ++iterator) { + comment += endLine + "@param " + iterator.current()->getName() + ' '; + comment += iterator.current()->getDoc(); + } + getComment()->setText(comment); + } + + // no return type for constructors + QString methodReturnType = o->getTypeName(); + QString methodName = o->getName(); + QString paramStr = QString(""); + + // assemble parameters + UMLAttributeList list = getParentOperation()->getParmList(); + int nrofParam = list.count(); + int paramNum = 0; + for(UMLAttribute* parm = list.first(); parm; parm=list.next()) + { + QString rType = parm->getTypeName(); + QString paramName = parm->getName(); + QString initialValue = parm->getInitialValue(); + paramStr += rType + ' ' + paramName; + if(!initialValue.isEmpty()) + paramStr += '=' + initialValue; + + paramNum++; + + if (paramNum != nrofParam ) + paramStr += ", "; + } + + // if an operation isn't a constructor or a destructor and it has no return type + if (o->isLifeOperation()) // constructor/destructor has no type + methodReturnType = ""; + else if (methodReturnType.isEmpty()) // this operation should be 'void' + methodReturnType = QString("void"); + + // set start/end method text + QString prototype = methodReturnType+' '+methodName+" ("+paramStr+')'; + + QString startText; + QString endText; + + applyStereotypes (prototype, o, isInlineMethod, isInterface, startText, endText); + + setStartMethodText(prototype+startText); + setEndMethodText(endText); +} + +int CPPHeaderCodeOperation::lastEditableLine() { + ClassifierCodeDocument * doc = dynamic_cast<ClassifierCodeDocument*>(getParentDocument()); + UMLOperation * o = getParentOperation(); + if(doc->parentIsInterface() || o->getAbstract()) + return -1; // very last line is NOT editable as its a one-line declaration w/ no body in + // an interface. + return 0; +} + +void CPPHeaderCodeOperation::applyStereotypes (QString& prototype, UMLOperation * pOp, + bool inlinePolicy, bool interface, + QString& start, QString& end) +{ + // if the class is an interface, all methods will be declared as pure + // virtual functions + start = (inlinePolicy ? " {" : ";"); + end = (inlinePolicy ? "}" : ""); + if (pOp->getConst()) + prototype += " const"; + if (interface || pOp->getAbstract()) { + // constructor can't be virtual or abstract + if (!pOp->isLifeOperation()) { + prototype = "virtual " + prototype + " = 0"; + if (inlinePolicy) { + start = ";"; + end = ""; + } + } + } // constructors could not be declared as static + else if (pOp->getStatic() && !pOp->isLifeOperation()) { + prototype = "static " + prototype; + } + // apply the stereotypes + if (!pOp->getStereotype().isEmpty()) { + if ((pOp->getStereotype() == "friend") || (pOp->getStereotype(false) == "virtual")) { + if (!pOp->isLifeOperation() && !(interface || pOp->getAbstract()) && !pOp->getStatic()) + prototype = pOp->getStereotype() + ' ' + prototype; + } + } +} + +#include "cppheadercodeoperation.moc" diff --git a/umbrello/umbrello/codegenerators/cppheadercodeoperation.h b/umbrello/umbrello/codegenerators/cppheadercodeoperation.h new file mode 100644 index 00000000..1d4fbca7 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppheadercodeoperation.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + + +#ifndef CPPHEADERCODEOPERATION_H +#define CPPHEADERCODEOPERATION_H + +#include <qstring.h> +#include "../codeoperation.h" + +class CPPHeaderCodeDocument; + +class CPPHeaderCodeOperation : virtual public CodeOperation +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructor + */ + CPPHeaderCodeOperation ( CPPHeaderCodeDocument * doc, UMLOperation * op, + const QString & body = "", const QString & comment = ""); + + /** + * Empty Destructor + */ + virtual ~CPPHeaderCodeOperation ( ); + + virtual int lastEditableLine(); + +protected: + + virtual void updateMethodDeclaration(); + virtual void updateContent( ); + + /** + * Check to see if we have a valid stereotype to apply in the operation + */ + virtual void applyStereotypes (QString&, UMLOperation *, bool, bool, QString&, QString&); + +}; + +#endif // CPPHEADERCODEOPERATION_H diff --git a/umbrello/umbrello/codegenerators/cppmakecodedocument.cpp b/umbrello/umbrello/codegenerators/cppmakecodedocument.cpp new file mode 100644 index 00000000..d13152b4 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppmakecodedocument.cpp @@ -0,0 +1,78 @@ + +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Tue Jun 24 2003 + */ + +#include "cppcodegenerator.h" + +#include <qregexp.h> + +const char * CPPMakefileCodeDocument::DOCUMENT_ID_VALUE = "Makefile_DOC"; + +// Constructors/Destructors +// + +CPPMakefileCodeDocument::CPPMakefileCodeDocument ( ) +{ + setFileName("Makefile"); // default name + setFileExtension(""); + setID(DOCUMENT_ID_VALUE); // default id tag for this type of document +} + +CPPMakefileCodeDocument::~CPPMakefileCodeDocument ( ) { } + +// +// Methods +// + +// Other methods +// + +// we add in our code blocks that describe how to generate +// the project here... +void CPPMakefileCodeDocument::updateContent( ) { + // FIX : fill in content +} + +/** + * @return QString + */ +QString CPPMakefileCodeDocument::toString ( ) { + return "# cpp make build document"; +} + +// We overwritten by CPP language implementation to get lowercase path +QString CPPMakefileCodeDocument::getPath ( ) +{ + + QString path = getPackage(); + + // Replace all white spaces with blanks + path.simplifyWhiteSpace(); + + // Replace all blanks with underscore + path.replace(QRegExp(" "), "_"); + + path.replace(QRegExp("\\."),"/"); + path.replace(QRegExp("::"),"/"); + + path.lower(); + + return path; + +} + + +#include "cppmakecodedocument.moc" diff --git a/umbrello/umbrello/codegenerators/cppmakecodedocument.h b/umbrello/umbrello/codegenerators/cppmakecodedocument.h new file mode 100644 index 00000000..98efe272 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppmakecodedocument.h @@ -0,0 +1,67 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Tue Jun 24 2003 + */ + + + +#ifndef CPPMAKECODEDOCUMENT_H +#define CPPMAKECODEDOCUMENT_H + +#include "../codedocument.h" +#include <qstring.h> + +/** + * class CPPMakefileCodeDocument + * Represents + */ + +class CPPMakefileCodeDocument : public CodeDocument +{ + Q_OBJECT +public: + + static const char * DOCUMENT_ID_VALUE; + + // Constructors/Destructors + // + + /** + * Constructor + */ + CPPMakefileCodeDocument ( ); + + /** + * Empty Destructor + */ + virtual ~CPPMakefileCodeDocument ( ); + + /** + * @return QString + */ + QString toString ( ); + + QString getPath ( ); + + void updateContent(); + +protected: + +private: + + + +}; + +#endif // CPPMAKECODEDOCUMENT_H diff --git a/umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.cpp b/umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.cpp new file mode 100644 index 00000000..da2a86cb --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.cpp @@ -0,0 +1,169 @@ +/*************************************************************************** + * * + * 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 : Fri Aug 31 2003 + */ + +// own header +#include "cppsourcecodeaccessormethod.h" + +// qt/kde includes +#include <kdebug.h> + +// local includes +#include "../attribute.h" +#include "../classifiercodedocument.h" +#include "../umlobject.h" +#include "../umlrole.h" +#include "../uml.h" + +#include "cppcodegenerator.h" +#include "cppcodegenerationpolicy.h" +#include "cppcodeclassfield.h" +#include "cppcodedocumentation.h" + +// Constructors/Destructors +// + +CPPSourceCodeAccessorMethod::CPPSourceCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type) + : CodeAccessorMethod ( field ) +{ + setType(type); + setEndMethodText("}"); +} + +void CPPSourceCodeAccessorMethod::update() +{ + updateMethodDeclaration(); + updateContent(); +} + +CPPSourceCodeAccessorMethod::~CPPSourceCodeAccessorMethod ( ) { } + +// Other +// + +// we basically want to update the body of this method +void CPPSourceCodeAccessorMethod::updateContent( ) +{ + CodeClassField * parentField = getParentClassField(); + CPPCodeClassField * cppfield = dynamic_cast<CPPCodeClassField*>(parentField); + CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt(); + CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); + bool isInlineMethod = policy->getAccessorsAreInline( ); + + QString variableName = cppfield->getFieldName(); + QString itemClassName = cppfield->getTypeName(); + QString text; + + if(isInlineMethod) { + switch(getType()) { + case CodeAccessorMethod::ADD: + text = policy->getVectorMethodAppend(variableName, itemClassName); + break; + case CodeAccessorMethod::REMOVE: + text = policy->getVectorMethodRemove(variableName, itemClassName); + break; + case CodeAccessorMethod::SET: + text = variableName+" = value;"; + break; + case CodeAccessorMethod::LIST: + case CodeAccessorMethod::GET: + default: + text = "return "+variableName+';'; + break; + } + } + + setText(text); +} + +// we basically want to update the start text of this method +void CPPSourceCodeAccessorMethod::updateMethodDeclaration() +{ + + CodeClassField * parentField = getParentClassField(); + ClassifierCodeDocument * doc = parentField->getParentDocument(); + CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt(); + CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); + CPPCodeClassField * cppfield = dynamic_cast<CPPCodeClassField*>(parentField); + UMLClassifier * c = doc->getParentClassifier(); + + bool isInlineMethod = policy->getAccessorsAreInline( ); + + QString vectorClassName = policy->getVectorClassName(); + QString fieldName = cppfield->getFieldName(); + QString fieldType = cppfield->getTypeName(); + QString objectType = cppfield->getListObjectType(); + if(objectType.isEmpty()) + objectType = fieldName; + + QString methodReturnType = "void"; + QString methodName; + QString methodParams; + QString headerText; + QString className = CodeGenerator::cleanName(c->getName()); + QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars(); + + switch(getType()) { + case CodeAccessorMethod::ADD: + methodName = "add_"+fieldType; + methodReturnType = "void"; + methodParams = objectType+" value "; + headerText = "Add a "+fieldName+" object to the "+fieldName+"List"+endLine+getParentObject()->getDoc()+endLine+"@return void"; + break; + case CodeAccessorMethod::REMOVE: + methodName = "remove_"+fieldType; + methodParams = objectType+" value "; + methodReturnType = "void"; + headerText = "Remove a "+fieldName+" object from the "+fieldName+"List"+endLine+getParentObject()->getDoc()+endLine+"@return void"; + break; + case CodeAccessorMethod::LIST: + methodName = "get_"+fieldType+"_list"; + methodReturnType = vectorClassName; + headerText = "Get the "+fieldName+"List"+endLine+getParentObject()->getDoc()+endLine+"@return "+vectorClassName+"with list of objects"; + break; + case CodeAccessorMethod::SET: + methodName = "set_"+fieldName; + methodParams = fieldType+" value "; + methodReturnType = "void"; + headerText = "Set the value of "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@param value the value of "+fieldName; + break; + case CodeAccessorMethod::GET: + default: + methodName = "get_"+fieldName; + methodReturnType = fieldType; + headerText = "Get the value of "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@return the value of "+fieldName; + break; + } + + // set header + CPPCodeDocumentation * header = new CPPCodeDocumentation(doc); + if(!getParentObject()->getDoc().isEmpty()) + header->setText(headerText); + setComment(header); + + // set start method text (EndText never changes) + setStartMethodText(methodReturnType+' '+className+"::"+methodName+" ("+methodParams+')' + " {"); + + setOverallIndentationLevel(0); + + // these ONLY appear if they arent inline + if(isInlineMethod) + setWriteOutText(false); + +} + + + +#include "cppsourcecodeaccessormethod.moc" diff --git a/umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.h b/umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.h new file mode 100644 index 00000000..60d9c369 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppsourcecodeaccessormethod.h @@ -0,0 +1,57 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Fri Jun 20 2003 + */ + +#ifndef CPPSOURCECODEACCESSORMETHOD_H +#define CPPSOURCECODEACCESSORMETHOD_H + +#include <qstring.h> + +#include "../codeaccessormethod.h" + +class CodeClassField; + +class CPPSourceCodeAccessorMethod : public CodeAccessorMethod +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Empty Constructor + */ + CPPSourceCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type); + + /** + * Empty Destructor + */ + virtual ~CPPSourceCodeAccessorMethod ( ); + + /** + * Must be called before this object is usable + */ + void update(); + +protected: + + virtual void updateMethodDeclaration(); + virtual void updateContent(); + +private: + +}; + +#endif // CPPSOURCECODEACCESSORMETHOD_H diff --git a/umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.cpp b/umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.cpp new file mode 100644 index 00000000..7d60b1c3 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.cpp @@ -0,0 +1,74 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + +#include "cppsourcecodeclassfielddeclarationblock.h" + +#include "cppcodeclassfield.h" +#include "../model_utils.h" + +// Constructors/Destructors +// + +CPPSourceCodeClassFieldDeclarationBlock::CPPSourceCodeClassFieldDeclarationBlock ( CodeClassField * parent ) + : CodeClassFieldDeclarationBlock ( parent ) +{ + setOverallIndentationLevel(1); + updateContent(); +} + +CPPSourceCodeClassFieldDeclarationBlock::~CPPSourceCodeClassFieldDeclarationBlock ( ) { } + +// +// Methods +// + +// Other methods +// + +/** + */ +void CPPSourceCodeClassFieldDeclarationBlock::updateContent( ) +{ + + /* + CodeClassField * cf = getParentClassField(); + ClassifierCodeDocument * doc = cf->getParentDocument(); + CPPCodeClassField * jcf = dynamic_cast<CPPCodeClassField*>(cf); + CPPClassifierCodeDocument* jdoc = dynamic_cast<CPPClassifierCodeDocument*>(doc); + + // Set the comment + QString notes = getParentObject()->getDoc(); + getComment()->setText(notes); + + // Set the body + QString staticValue = getParentObject()->getStatic() ? "static " : ""; + QString scopeStr = getParentObject()->getVisibility().toString(); + + QString typeName = jcf->getTypeName(); + QString fieldName = jcf->getFieldName(); + QString initialV = jcf->getInitialValue(); + + QString body = staticValue+scopeStr+" "+typeName+" "+fieldName; + if (!initialV.isEmpty()) + body.append(" = " + initialV); + setText(body+";"); + */ + setText("FIX ME;"); + + +} + + + +#include "cppsourcecodeclassfielddeclarationblock.moc" diff --git a/umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.h b/umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.h new file mode 100644 index 00000000..e5b908a0 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppsourcecodeclassfielddeclarationblock.h @@ -0,0 +1,51 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + +#ifndef CPPSOURCECODECLASSFIELDDECLARATIONBLOCK_H +#define CPPSOURCECODECLASSFIELDDECLARATIONBLOCK_H + +#include <qstring.h> + +#include "../codeclassfielddeclarationblock.h" + +class CPPSourceCodeClassFieldDeclarationBlock : public CodeClassFieldDeclarationBlock +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructor + */ + CPPSourceCodeClassFieldDeclarationBlock ( CodeClassField * parent ); + + /** + * Empty Destructor + */ + virtual ~CPPSourceCodeClassFieldDeclarationBlock ( ); + +protected: + + // this will be called by syncToParent whenever the parent object is "modified" + void updateContent ( ); + +private: + + +}; + +#endif // CPPSOURCECODECLASSFIELDDECLARATIONBLOCK_H diff --git a/umbrello/umbrello/codegenerators/cppsourcecodedocument.cpp b/umbrello/umbrello/codegenerators/cppsourcecodedocument.cpp new file mode 100644 index 00000000..be054937 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppsourcecodedocument.cpp @@ -0,0 +1,168 @@ +/*************************************************************************** + * * + * 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) 2003-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Thu Aug 28 2003 + */ + +/** + We carve the CPP document up into 2 documents, "source" and "header". + The sections of each are as follows: + + * header + * includes + * constructor methods + * all other methods + +*/ + +// own header +#include "cppsourcecodedocument.h" +// qt/kde includes +#include <kdebug.h> +#include <qregexp.h> +// app includes +#include "cppcodegenerator.h" +#include "cppcodegenerationpolicy.h" +#include "cppcodedocumentation.h" +#include "cppcodeclassfield.h" +#include "cppsourcecodeclassfielddeclarationblock.h" +#include "../uml.h" + +// Constructors/Destructors +// + +CPPSourceCodeDocument::CPPSourceCodeDocument ( UMLClassifier * concept ) + : ClassifierCodeDocument (concept) { + init ( ); +} + +CPPSourceCodeDocument::~CPPSourceCodeDocument ( ) { } + +// +// Methods +// + +// Accessor methods +// + +// Other methods +// + +QString CPPSourceCodeDocument::getCPPClassName (const QString &name) { + return CodeGenerator::cleanName(name); +} + +// Initialize this cpp classifier code document +void CPPSourceCodeDocument::init ( ) { + + setFileExtension(".cpp"); + + methodsBlock = 0; + constructorBlock = 0; + + //initCodeClassFields(); // this is dubious because it calls down to + // CodeGenFactory::newCodeClassField(this) + // but "this" is still in construction at that time. + + // this will call updateContent() as well as other things that sync our document. + //synchronize(); +} + +/** + * @param op + */ +// in the vannilla version, we just tack all operations on the end +// of the document +bool CPPSourceCodeDocument::addCodeOperation (CodeOperation * op ) { + + if(!op->getParentOperation()->isLifeOperation()) + { + return methodsBlock->addTextBlock(op); + } else + return constructorBlock->addTextBlock(op); +} + + +void CPPSourceCodeDocument::resetTextBlocks() +{ + + // all special pointers need to be zero'd out. + methodsBlock = 0; + constructorBlock = 0; + + // now do the traditional release of child text blocks + ClassifierCodeDocument::resetTextBlocks(); + +} + +// This method will cause the class to rebuild its text representation. +// based on the parent classifier object. +// For any situation in which this is called, we are either building the code +// document up, or replacing/regenerating the existing auto-generated parts. As +// such, we will want to insert everything we reasonably will want +// during creation. We can set various parts of the document (esp. the +// comments) to appear or not, as needed. +void CPPSourceCodeDocument::updateContent( ) +{ + + // Gather info on the various fields and parent objects of this class... + //UMLClassifier * c = getParentClassifier(); + CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt(); + CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); + QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars(); + + // first, set the global flag on whether or not to show classfield info + CodeClassFieldList * cfList = getCodeClassFieldList(); + for(CodeClassField * field = cfList->first(); field; field = cfList->next()) + field->setWriteOutMethods(policy->getAutoGenerateAccessors()); + + // attribute-based ClassFields + // we do it this way to have the static fields sorted out from regular ones + CodeClassFieldList staticAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true); + CodeClassFieldList attribClassFields = getSpecificClassFields (CodeClassField::Attribute, false); + // association-based ClassFields + // don't care if they are static or not..all are lumped together + CodeClassFieldList plainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation ); + CodeClassFieldList aggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation ); + CodeClassFieldList compositionClassFields = getSpecificClassFields ( CodeClassField::Composition ); + + // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT + // + + // INCLUDE CODEBLOCK + QString includeStatement = ""; + // Include own header file + QString myOwnName( getParentClassifier()->getName() ); + includeStatement.append("#include \""+CodeGenerator::cleanName(myOwnName.lower())+".h\""+endLine); + CodeBlockWithComments * iblock = addOrUpdateTaggedCodeBlockWithComments("includes", includeStatement, QString::null, 0, false); + iblock->setWriteOutText(true); + + // After the includes we have just 2 big blocks basically, the "constructor" block and the + // block for the rest of our methods (operations + accessors) + + constructorBlock = getHierarchicalCodeBlock("constructionMethodsBlock", "Constructors/Destructors", 0); + methodsBlock = getHierarchicalCodeBlock("otherMethodsBlock", "Methods", 0); + + // add accessors to the methods block + methodsBlock->addCodeClassFieldMethods(staticAttribClassFields); + methodsBlock->addCodeClassFieldMethods(attribClassFields); + methodsBlock->addCodeClassFieldMethods(plainAssocClassFields); + methodsBlock->addCodeClassFieldMethods(aggregationClassFields); + methodsBlock->addCodeClassFieldMethods(compositionClassFields); + + // constructors and other operations are handled by the "addCodeOperation" method above. + +} + + +#include "cppsourcecodedocument.moc" diff --git a/umbrello/umbrello/codegenerators/cppsourcecodedocument.h b/umbrello/umbrello/codegenerators/cppsourcecodedocument.h new file mode 100644 index 00000000..8ca59c95 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppsourcecodedocument.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Thu Aug 28 2003 + */ + +#ifndef CPPSOURCECODEDOCUMENT_H +#define CPPSOURCECODEDOCUMENT_H + +#include <qstring.h> + +#include "../classifiercodedocument.h" +#include "../hierarchicalcodeblock.h" +#include "classifierinfo.h" + +/** + * class CPPSourceCodeDocument + * A CPP UMLClassifier Source Code Document. + */ + +class CPPSourceCodeDocument : public ClassifierCodeDocument +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructor + */ + CPPSourceCodeDocument (UMLClassifier * classifier); + + /** + * Empty Destructor + */ + virtual ~CPPSourceCodeDocument ( ); + + /** add a code operation to this cpp classifier code document. + * @return bool which is true IF the code operation was added successfully + */ + bool addCodeOperation (CodeOperation * op ); + +protected: + + // reset/clear our inventory of textblocks in this document + void resetTextBlocks(); + + // a little utility method to save us some work + QString getCPPClassName (const QString &name); + + void updateContent(); + +private: + + HierarchicalCodeBlock * constructorBlock; + HierarchicalCodeBlock * methodsBlock; + + void init ( ); + +}; + +#endif // CPPSOURCECODEDOCUMENT_H diff --git a/umbrello/umbrello/codegenerators/cppsourcecodeoperation.cpp b/umbrello/umbrello/codegenerators/cppsourcecodeoperation.cpp new file mode 100644 index 00000000..0d8115b6 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppsourcecodeoperation.cpp @@ -0,0 +1,193 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + +#include "cppsourcecodeoperation.h" + +#include "cppcodegenerator.h" +#include "cppcodegenerationpolicy.h" +#include "cppsourcecodedocument.h" +#include "cppcodedocumentation.h" +#include "../uml.h" + +// Constructors/Destructors +// + +CPPSourceCodeOperation::CPPSourceCodeOperation ( CPPSourceCodeDocument * doc, UMLOperation *parent, const QString & body, const QString & comment ) + : CodeOperation (doc, parent, body, comment) +{ + // lets not go with the default comment and instead use + // full-blown cpp documentation object instead + setComment(new CPPCodeDocumentation(doc)); + + // these things never change.. + setOverallIndentationLevel(0); + setEndMethodText("}"); + + //updateMethodDeclaration(); + CodeGenPolicyExt * pe = UMLApp::app()->getPolicyExt(); + CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); + UMLClassifier * c = doc->getParentClassifier(); + UMLOperation * o = getParentOperation(); + bool isInterface = doc->parentIsInterface(); + bool isInlineMethod = policy->getOperationsAreInline( ); + + // first, the comment on the operation + QString cmnt = o->getDoc(); + getComment()->setText(cmnt); + + QString returnType = o->getTypeName(); + QString methodName = o->getName(); + QString paramStr = QString(""); + QString className = CodeGenerator::cleanName(c->getName()); + + // assemble parameters + UMLAttributeList list = getParentOperation()->getParmList(); + int nrofParam = list.count(); + int paramNum = 0; + for(UMLAttribute* parm = list.first(); parm; parm=list.next()) + { + QString rType = parm->getTypeName(); + QString paramName = parm->getName(); + paramStr += rType + ' ' + paramName; + paramNum++; + + if (paramNum != nrofParam ) + paramStr += ", "; + } + + // no return type for constructors/destructors + if (o->isLifeOperation()) + returnType = ""; + // if an operation isn't a constructor/destructor and it has no return type + // this operation should be void + else if (returnType.isEmpty()) + returnType = QString("void"); + + QString startText = returnType + ' '; + + // if a property has a friend stereotype, the operation should + // not be a class name + if (o->getStereotype() != "friend") + startText += className + "::"; + startText += methodName + " (" + paramStr + ')'; + if (o->getConst()) + startText += " const"; + startText += " {"; + + setStartMethodText(startText); + + // Only write this out if its a child of an interface OR is abstract. + // and its not inline + if(isInterface || o->getAbstract() || isInlineMethod) + { + setWriteOutText(false); + } else { + setWriteOutText(true); + } + + + updateContent(); +} + +CPPSourceCodeOperation::~CPPSourceCodeOperation ( ) { } + +// Other methods +// + +// we basically just want to know whether or not to print out +// the body of the operation. +// In C++ if the operations are inline, then we DONT print out +// the body text. +void CPPSourceCodeOperation::updateContent( ) +{ + CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt(); + CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); + bool isInlineMethod = policy->getOperationsAreInline(); + + if(!isInlineMethod) + setText(""); // change whatever it is to ""; + +} + +// we basically want to update the doc and start text of this method +void CPPSourceCodeOperation::updateMethodDeclaration() +{ + + CPPSourceCodeDocument * doc = dynamic_cast<CPPSourceCodeDocument*>(getParentDocument()); + CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt(); + CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); + UMLClassifier * c = doc->getParentClassifier(); + UMLOperation * o = getParentOperation(); + bool isInterface = doc->parentIsInterface(); + bool isInlineMethod = policy->getOperationsAreInline( ); + + // first, the comment on the operation + QString comment = o->getDoc(); + getComment()->setText(comment); + + QString returnType = o->getTypeName(); + QString methodName = o->getName(); + QString paramStr = QString(""); + QString className = CodeGenerator::cleanName(c->getName()); + + // assemble parameters + UMLAttributeList list = getParentOperation()->getParmList(); + int nrofParam = list.count(); + int paramNum = 0; + for(UMLAttribute* parm = list.first(); parm; parm=list.next()) + { + QString rType = parm->getTypeName(); + QString paramName = parm->getName(); + paramStr += rType + ' ' + paramName; + paramNum++; + + if (paramNum != nrofParam ) + paramStr += ", "; + } + + // no return type for constructors/destructors + if (o->isLifeOperation()) + returnType = ""; + // if an operation isn't a constructor/destructor and it has no return type + // this operation should be void + else if (returnType.isEmpty()) + returnType = QString("void"); + + QString startText = returnType + ' '; + + // if a property has a friend stereotype, the operation should + // not be a class name + if (o->getStereotype() != "friend") + startText += className + "::"; + startText += methodName + " (" + paramStr + ')'; + if (o->getConst()) + startText += " const"; + startText += " {"; + + setStartMethodText(startText); + + // Only write this out if its a child of an interface OR is abstract. + // and its not inline + if(isInterface || o->getAbstract() || isInlineMethod) + { + setWriteOutText(false); + } else { + setWriteOutText(true); + } + +} + +#include "cppsourcecodeoperation.moc" diff --git a/umbrello/umbrello/codegenerators/cppsourcecodeoperation.h b/umbrello/umbrello/codegenerators/cppsourcecodeoperation.h new file mode 100644 index 00000000..e2112178 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppsourcecodeoperation.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 1 2003 + */ + + +#ifndef CPPSOURCECODEOPERATION_H +#define CPPSOURCECODEOPERATION_H + +#include <qstring.h> +#include "../codeoperation.h" + +class CPPSourceCodeDocument; + +class CPPSourceCodeOperation : virtual public CodeOperation +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Empty Constructor + */ + CPPSourceCodeOperation ( CPPSourceCodeDocument * doc, UMLOperation * op, const QString & body = "", const QString & comment = ""); + + /** + * Empty Destructor + */ + virtual ~CPPSourceCodeOperation ( ); + +protected: + + virtual void updateMethodDeclaration(); + virtual void updateContent( ); + +}; + +#endif // CPPSOURCECODEOPERATION_H diff --git a/umbrello/umbrello/codegenerators/cppwriter.cpp b/umbrello/umbrello/codegenerators/cppwriter.cpp new file mode 100644 index 00000000..b24c12b0 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppwriter.cpp @@ -0,0 +1,1283 @@ +/*************************************************************************** + * cppwriter.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 "cppwriter.h" +// qt/kde includes +#include <qfile.h> +#include <qtextstream.h> +#include <qregexp.h> +#include <kdebug.h> +// app includes +#include "classifierinfo.h" +#include "codegen_utils.h" +#include "../uml.h" +#include "../umldoc.h" +#include "../classifier.h" +#include "../operation.h" +#include "../template.h" +#include "../umltemplatelist.h" +#include "../umlclassifierlistitemlist.h" +#include "../classifierlistitem.h" +#include "../model_utils.h" +#include "../codegenerationpolicy.h" + +// 3-14-2003: this code developed from the javawriter with parts of the +// original cppwriter by Luis De la Parra Blum + +CppWriter::CppWriter() +{ + // Probably we could resolve this better through the use of templates, + // but its a quick n dirty fix for the timebeing.. until codegeneration + // template system is in place. + // You can insert code here. 3 general variables exist: "%VARNAME%" + // allows you to specify where the vector variable should be in your code, + // and "%ITEMCLASS%", if needed, where the class of the item is declared. + VECTOR_METHOD_APPEND = "%VARNAME%.push_back(add_object);"; // for std::vector + VECTOR_METHOD_REMOVE = "int i, size = %VARNAME%.size();\nfor ( i = 0; i < size; i++) {\n\t%ITEMCLASS% item = %VARNAME%.at(i);\n\tif(item == remove_object) {\n\t\tvector<%ITEMCLASS%>::iterator it = %VARNAME%.begin() + i;\n\t\t%VARNAME%.erase(it);\n\t\treturn;\n\t}\n }"; // for std::vector + VECTOR_METHOD_INIT = QString(); // nothing to be done + /* + VECTOR_METHOD_APPEND = "%VARNAME%.append(&add_object);"; // Qt lib implementation + VECTOR_METHOD_REMOVE = "%VARNAME%.removeRef(&remove_object);"; // Qt lib implementation + VECTOR_METHOD_INIT = "%VARNAME%.setAutoDelete(false);"; // Qt library + */ + + OBJECT_METHOD_INIT = "%VARNAME% = new %ITEMCLASS%( );"; // Qt library + + // boolean config params + INLINE_ASSOCIATION_METHODS = false; + +} + +CppWriter::~CppWriter() { } + +Uml::Programming_Language CppWriter::getLanguage() { + return Uml::pl_Cpp; +} + +CPPCodeGenerationPolicy *CppWriter::policyExt() { + return static_cast<CPPCodeGenerationPolicy*>(UMLApp::app()->getPolicyExt()); +} + +void CppWriter::writeClass(UMLClassifier *c) +{ + + if (!c) { + kDebug() << "Cannot write class of NULL concept!\n"; + return; + } + + QFile fileh, filecpp; + + // find an appropriate name for our file + QString fileName = findFileName(c, ".h"); + if (fileName.isEmpty()) { + emit codeGenerated(c, false); + return; + } + + // preparations + m_classifierInfo = new ClassifierInfo(c); + m_classifierInfo->fileName = fileName; + m_classifierInfo->className = cleanName(c->getName()); + + if (c->getVisibility() != Uml::Visibility::Implementation) { + if( !openFile(fileh, fileName)) { + emit codeGenerated(c, false); + return; + } + // write Header file + writeHeaderFile(c, fileh); + fileh.close(); + } + + // Determine whether the implementation file is required. + // (It is not required if the class is an enumeration.) + bool need_impl = true; + if (c->getBaseType() == Uml::ot_Enum) { + need_impl = false; + } + if (need_impl) { + fileName.replace( QRegExp(".h$"), ".cpp"); + if( !openFile(filecpp, fileName)) { + emit codeGenerated(c, false); + return; + } + // write Source file + writeSourceFile(c, filecpp); + filecpp.close(); + } + + // Wrap up: free m_classifierInfo, emit done code + m_classifierInfo = 0; + + emit codeGenerated(c, true); + +} + +void CppWriter::writeHeaderFile (UMLClassifier *c, QFile &fileh) { + + // open stream for writing + QTextStream h (&fileh); + + // up the indent level to one + m_indentLevel = 1; + + // write header blurb + QString str = getHeadingFile(".h"); + if(!str.isEmpty()) { + str.replace(QRegExp("%filename%"),m_classifierInfo->fileName + ".h"); + str.replace(QRegExp("%filepath%"),fileh.name()); + h << str<< m_endl; + } + + // Write the hash define stuff to prevent multiple parsing/inclusion of header + QString hashDefine = m_classifierInfo->className.upper().simplifyWhiteSpace().replace(QRegExp(" "), "_"); + writeBlankLine(h); + h << "#ifndef "<< hashDefine + "_H" << m_endl; + h << "#define "<< hashDefine + "_H" << m_endl; + + writeClassDecl(c, h); + + // last thing..close our hashdefine + h << m_endl << "#endif // " << hashDefine + "_H" << m_endl; + +} + +void CppWriter::writeHeaderAccessorMethodDecl(UMLClassifier *c, Uml::Visibility permitScope, QTextStream &stream) +{ + + // attributes + writeHeaderAttributeAccessorMethods(permitScope, true, stream); // write static attributes first + writeHeaderAttributeAccessorMethods(permitScope, false, stream); + + // associations + writeAssociationMethods(m_classifierInfo->plainAssociations, permitScope, + true, INLINE_ASSOCIATION_METHODS, true, c->getID(), stream); + writeAssociationMethods(m_classifierInfo->uniAssociations, permitScope, + true, INLINE_ASSOCIATION_METHODS, true, c->getID(), stream); + writeAssociationMethods(m_classifierInfo->aggregations, permitScope, + true, INLINE_ASSOCIATION_METHODS, true, c->getID(), stream); + writeAssociationMethods(m_classifierInfo->compositions, permitScope, + true, INLINE_ASSOCIATION_METHODS, false, c->getID(), stream); + + writeBlankLine(stream); + +} + +void CppWriter::writeHeaderFieldDecl(UMLClassifier *c, Uml::Visibility permitScope, QTextStream &stream) +{ + // attributes + writeAttributeDecls(permitScope, true, stream); // write static attributes first + writeAttributeDecls(permitScope, false, stream); + + // associations + writeAssociationDecls(m_classifierInfo->plainAssociations, permitScope, c->getID(), stream); + writeAssociationDecls(m_classifierInfo->uniAssociations, permitScope, c->getID(), stream); + writeAssociationDecls(m_classifierInfo->aggregations, permitScope, c->getID(), stream); + writeAssociationDecls(m_classifierInfo->compositions, permitScope, c->getID(), stream); + +} + +void CppWriter::writeSourceFile (UMLClassifier *c, QFile &filecpp ) { + + // open stream for writing + QTextStream cpp (&filecpp); + + // set the starting indentation at zero + m_indentLevel = 0; + + //try to find a heading file (license, coments, etc) + QString str; + str = getHeadingFile(".cpp"); + if(!str.isEmpty()) { + str.replace(QRegExp("%filename%"),m_classifierInfo->fileName + ".cpp"); + str.replace(QRegExp("%filepath%"),filecpp.name()); + cpp << str << m_endl; + } + + // IMPORT statements + // Q: Why all utils? Isnt just List and Vector the only classes we are using? + // Our import *should* also look at operations, and check that objects being + // used arent in another package (and thus need to be explicitly imported here). + cpp << "#include \"" << m_classifierInfo->className << ".h\"" << m_endl; + writeBlankLine(cpp); + + if (c->getVisibility() == Uml::Visibility::Implementation) { + writeClassDecl(c, cpp); + } + + // Start body of class + + // Constructors: anything we more we need to do here ? + // + if(!m_classifierInfo->isInterface) + writeConstructorMethods(cpp); + + // METHODS + // + + // write comment for section IF needed + QString indent = getIndent(); + if (forceDoc() || m_classifierInfo->hasAccessorMethods || m_classifierInfo->hasOperationMethods) + { + + writeComment(" ", indent, cpp); + writeComment("Methods", indent, cpp); + writeComment(" ", indent, cpp); + writeBlankLine(cpp); + writeBlankLine(cpp); + } + + // write comment for sub-section IF needed + if (forceDoc() || m_classifierInfo->hasAccessorMethods ) + { + writeComment("Accessor methods", indent, cpp); + writeComment(" ", indent, cpp); + writeBlankLine(cpp); + } + + // Accessor methods for attributes + const bool bInlineAccessors = policyExt()->getAccessorsAreInline(); + if (!bInlineAccessors && m_classifierInfo->hasAttributes) + { + writeAttributeMethods(&(m_classifierInfo->static_atpub), Uml::Visibility::Public, false, true, !bInlineAccessors, cpp); + writeAttributeMethods(&(m_classifierInfo->atpub), Uml::Visibility::Public, false, false, !bInlineAccessors, cpp); + writeAttributeMethods(&(m_classifierInfo->static_atprot), Uml::Visibility::Protected, false, true, !bInlineAccessors, cpp); + writeAttributeMethods(&(m_classifierInfo->atprot), Uml::Visibility::Protected, false, false, !bInlineAccessors, cpp); + writeAttributeMethods(&(m_classifierInfo->static_atpriv), Uml::Visibility::Private, false, true, !bInlineAccessors, cpp); + writeAttributeMethods(&(m_classifierInfo->atpriv), Uml::Visibility::Private, false, false, !bInlineAccessors, cpp); + } + + // accessor methods for associations + + // public + writeAssociationMethods(m_classifierInfo->plainAssociations, Uml::Visibility::Public, false, + !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp); + writeAssociationMethods(m_classifierInfo->uniAssociations, Uml::Visibility::Public, false, + !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp); + writeAssociationMethods(m_classifierInfo->aggregations, Uml::Visibility::Public, false, + !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp); + writeAssociationMethods(m_classifierInfo->compositions, Uml::Visibility::Public, false, + !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp); + + // protected + writeAssociationMethods(m_classifierInfo->plainAssociations, Uml::Visibility::Protected, false, + !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp); + writeAssociationMethods(m_classifierInfo->uniAssociations, Uml::Visibility::Protected, false, + !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp); + writeAssociationMethods(m_classifierInfo->aggregations, Uml::Visibility::Protected, false, + !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp); + writeAssociationMethods(m_classifierInfo->compositions, Uml::Visibility::Protected, false, + !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp); + + + // private + writeAssociationMethods(m_classifierInfo->plainAssociations, Uml::Visibility::Private, false, + !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp); + writeAssociationMethods(m_classifierInfo->uniAssociations, Uml::Visibility::Private, false, + !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp); + writeAssociationMethods(m_classifierInfo->aggregations, Uml::Visibility::Private, false, + !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp); + writeAssociationMethods(m_classifierInfo->compositions, Uml::Visibility::Private, false, + !INLINE_ASSOCIATION_METHODS, true, c->getID(), cpp); + writeBlankLine(cpp); + + // Other operation methods -- all other operations are now written + // + + // write comment for sub-section IF needed + if (forceDoc() || m_classifierInfo->hasOperationMethods) + { + writeComment("Other methods", indent, cpp); + writeComment(" ", indent, cpp); + writeBlankLine(cpp); + } + + if(!policyExt()->getOperationsAreInline()) + { + writeOperations(c,false,Uml::Visibility::Public,cpp); + writeOperations(c,false,Uml::Visibility::Protected,cpp); + writeOperations(c,false,Uml::Visibility::Private,cpp); + } + + // Yep, bringing up the back of the bus, our initialization method for attributes + writeInitAttibuteMethod (cpp); + + writeBlankLine(cpp); + +} + +void CppWriter::writeClassDecl(UMLClassifier *c, QTextStream &cpp) +{ + UMLClassifierList superclasses = m_classifierInfo->superclasses; + for(UMLClassifier *classifier = superclasses.first(); classifier ;classifier = superclasses.next()) { + QString headerName = findFileName(classifier, ".h"); + if (!headerName.isEmpty()) { + cpp << "#include \"" << headerName << "\"" << m_endl; + } + } + + writeBlankLine(cpp); + cpp << "#include " << policyExt()->getStringClassNameInclude() << m_endl; + if(m_classifierInfo->hasVectorFields) + { + cpp << "#include " << policyExt()->getVectorClassNameInclude() << m_endl; + writeBlankLine(cpp); + } + + if(m_classifierInfo->hasAssociations) + { + // write all includes we need to include other classes, that arent us. + printAssociationIncludeDecl (m_classifierInfo->plainAssociations, c->getID(), cpp); + printAssociationIncludeDecl (m_classifierInfo->uniAssociations, c->getID(), cpp); + printAssociationIncludeDecl (m_classifierInfo->aggregations, c->getID(), cpp); + printAssociationIncludeDecl (m_classifierInfo->compositions, c->getID(), cpp); + + writeBlankLine(cpp); + } + + + for(UMLClassifier *classifier = superclasses.first(); classifier ; classifier = superclasses.next()) { + if(classifier->getPackage()!=c->getPackage() && !classifier->getPackage().isEmpty()) { + cpp << "using " << cleanName(classifier->getPackage()) << "::" << cleanName(classifier->getName()) << ";" << m_endl; + } + } + + if(!c->getPackage().isEmpty() && policyExt()->getPackageIsNamespace()) + cpp << m_endl << "namespace " << cleanName(c->getPackage()) << " {" << m_endl << m_endl; + + //Write class Documentation if there is somthing or if force option + if(forceDoc() || !c->getDoc().isEmpty()) { + cpp << m_endl << "/**" << m_endl; + cpp << " * class " << m_classifierInfo->className << m_endl; + cpp << formatDoc(c->getDoc()," * "); + cpp << " */"; + writeBlankLine(cpp); + writeBlankLine(cpp); + } + + //check if class is abstract and / or has abstract methods + if((c->getAbstract() || m_classifierInfo->isInterface ) + && !hasAbstractOps(c)) + cpp << "/******************************* Abstract Class ****************************" << m_endl + <<m_classifierInfo->className << " does not have any pure virtual methods, but its author" << m_endl + <<" defined it as an abstract class, so you should not use it directly." << m_endl + <<" Inherit from it instead and create only objects from the derived classes" << m_endl + <<"*****************************************************************************/" << m_endl << m_endl; + + if (c->getBaseType() == Uml::ot_Enum) { + UMLClassifierListItemList litList = c->getFilteredList(Uml::ot_EnumLiteral); + uint i = 0; + cpp << "enum " << m_classifierInfo->className << " {" << m_endl; + for (UMLClassifierListItem *lit = litList.first(); lit; lit = litList.next()) { + QString enumLiteral = cleanName(lit->getName()); + cpp << getIndent() << enumLiteral; + if (++i < litList.count()) + cpp << ","; + cpp << m_endl; + } + cpp << m_endl << "};" << m_endl; // end of class header + if(!c->getPackage().isEmpty() && policyExt()->getPackageIsNamespace()) + cpp << "} // end of package namespace" << m_endl; + return; + } + + // Generate template parameters. + UMLTemplateList template_params = c->getTemplateList(); + if (template_params.count()) { + cpp << "template<"; + for (UMLTemplate *t = template_params.first(); t; ) { + QString formalName = t->getName(); + QString typeName = t->getTypeName(); + cpp << typeName << " " << formalName; + if ((t = template_params.next()) != NULL) + cpp << ", "; + } + cpp << ">" << m_endl; + } + + cpp << "class " << m_classifierInfo->className; + if (m_classifierInfo->superclasses.count() > 0) + cpp << " : "; + uint numOfSuperClasses = m_classifierInfo->superclasses.count(); + uint i = 0; + for (UMLClassifier *superClass = m_classifierInfo->superclasses.first(); + superClass ; superClass = m_classifierInfo->superclasses.next()) + { + i++; + if (superClass->getAbstract() || superClass->isInterface()) + cpp << "virtual "; + cpp << "public " << cleanName(superClass->getName()); + if (i < numOfSuperClasses) + cpp << ", "; + } + + cpp << m_endl << "{" << m_endl; // begin the body of the class + + + //declarations of operations + // + + // + // write out field and operations decl grouped by visibility + // + + // PUBLIC attribs/methods + cpp << "public:" << m_endl << m_endl; // print visibility decl. + // for public: constructors are first ops we print out + if(!m_classifierInfo->isInterface) + writeConstructorDecls(cpp); + writeHeaderFieldDecl(c,Uml::Visibility::Public, cpp); + writeHeaderAccessorMethodDecl(c, Uml::Visibility::Public, cpp); + writeOperations(c,true,Uml::Visibility::Public,cpp); + + // PROTECTED attribs/methods + // + cpp << "protected" << ":" << m_endl << m_endl; // print visibility decl. + writeHeaderFieldDecl(c,Uml::Visibility::Protected, cpp); + writeHeaderAccessorMethodDecl(c, Uml::Visibility::Protected, cpp); + writeOperations(c,true,Uml::Visibility::Protected,cpp); + + // PRIVATE attribs/methods + // + cpp << "private" << ":" << m_endl << m_endl; // print visibility decl. + writeHeaderFieldDecl(c,Uml::Visibility::Private, cpp); + writeHeaderAccessorMethodDecl(c, Uml::Visibility::Private, cpp); + writeOperations(c,true,Uml::Visibility::Private,cpp); + writeInitAttibuteDecl(cpp); // this is always private, used by constructors to initialize class + + // end of class header + cpp << m_endl << "};" << m_endl; + + // end of class namespace, if any + if(!c->getPackage().isEmpty() && policyExt()->getPackageIsNamespace()) + cpp << "}; // end of package namespace" << m_endl; + +} + +void CppWriter::writeAttributeDecls (Uml::Visibility visibility, bool writeStatic, QTextStream &stream ) +{ + + if(m_classifierInfo->isInterface) + return; + + UMLAttributeList * list; + switch (visibility) + { + case Uml::Visibility::Private: + if(writeStatic) + list = &(m_classifierInfo->static_atpriv); + else + list = &(m_classifierInfo->atpriv); + break; + + case Uml::Visibility::Protected: + if(writeStatic) + list = &(m_classifierInfo->static_atprot); + else + list = &(m_classifierInfo->atprot); + break; + + case Uml::Visibility::Public: + default: + if(writeStatic) + list = &(m_classifierInfo->static_atpub); + else + list = &(m_classifierInfo->atpub); + break; + } + + //write documentation + if(forceDoc() || list->count() > 0) + { + QString strVis = Codegen_Utils::capitalizeFirstLetter(visibility.toString()); + QString strStatic = writeStatic ? "Static ":""; + writeComment(strStatic + strVis + " attributes",getIndent(), stream); + writeComment(" ",getIndent(), stream); + writeBlankLine(stream); + } + + if (list->count() > 0) { + + // write attrib declarations now + bool isFirstAttrib = true; + QString documentation; + for(UMLAttribute *at=list->first(); at; at=list->next()) + { + + // bool noPriorDocExists = documentation.isEmpty(); + documentation = at->getDoc(); + + // add a line for code clarity IF PRIOR attrib has comment on it + // OR this line has documentation + // if(!isFirstAttrib && (!documentation.isEmpty()||!noPriorDocExists)) + // writeBlankLine(stream); + + isFirstAttrib = false; + + QString varName = getAttributeVariableName(at); + + QString staticValue = at->getStatic() ? "static " : ""; + QString typeName = fixTypeName(at->getTypeName()); + if(!documentation.isEmpty()) + writeComment(documentation, getIndent(), stream); + stream << getIndent() << staticValue << typeName << " " << varName << ";" << m_endl; + + } + + /* + if(list->count() > 0) + writeBlankLine(stream); + */ + + } + +} + +void CppWriter::writeHeaderAttributeAccessorMethods (Uml::Visibility visibility, bool writeStatic, QTextStream &stream ) +{ + // check the current policy about generate accessors as public + UMLAttributeList * list; + switch (visibility) + { + case Uml::Visibility::Private: + if(writeStatic) + list = &(m_classifierInfo->static_atpriv); + else + list = &(m_classifierInfo->atpriv); + break; + + case Uml::Visibility::Protected: + if(writeStatic) + list = &(m_classifierInfo->static_atprot); + else + list = &(m_classifierInfo->atprot); + break; + + case Uml::Visibility::Public: + default: + if(writeStatic) + list = &(m_classifierInfo->static_atpub); + else + list = &(m_classifierInfo->atpub); + break; + } + + // switch to public + if (visibility != Uml::Visibility::Public) + stream << "public:" << m_endl << m_endl; + + // write accessor methods for attribs we found + writeAttributeMethods(list, visibility, true, false, policyExt()->getAccessorsAreInline(), stream); + + // switch back to previous vis. + if (visibility != Uml::Visibility::Public) + stream << visibility.toString() << ":" << m_endl << m_endl; +} + +// this is for writing *source* or *header* file attribute methods +// +void CppWriter::writeAttributeMethods(UMLAttributeList *attribs, + Uml::Visibility visibility, bool isHeaderMethod, + bool isStatic, + bool writeMethodBody, QTextStream &stream) +{ + + if (!policyExt()->getAutoGenerateAccessors()) + return; + + if (forceDoc() || attribs->count() > 0) + { + QString strVis = Codegen_Utils::capitalizeFirstLetter(visibility.toString()); + QString strStatic = (isStatic ? " static" : ""); + writeBlankLine(stream); + writeComment(strVis + strStatic + " attribute accessor methods",getIndent(),stream); + writeComment(" ",getIndent(), stream); + writeBlankLine(stream); + } + + // return now if NO attributes to work on + if (attribs->count() == 0) + return; + + UMLAttribute *at; + for(at=attribs->first(); at; at=attribs->next()) + { + + QString varName = getAttributeVariableName(at); + QString methodBaseName = 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. + methodBaseName = methodBaseName.stripWhiteSpace(); + methodBaseName.replace(0,1,methodBaseName.at(0).upper()); + + writeSingleAttributeAccessorMethods(at->getTypeName(), varName, + methodBaseName, at->getDoc(), Uml::chg_Changeable, isHeaderMethod, + at->getStatic(), writeMethodBody, stream); + } + +} + +void CppWriter::writeComment(const QString &comment, const QString &myIndent, QTextStream &cpp) +{ + // 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"))) { + + QStringList lines = QStringList::split( "\n", comment); + for(uint i= 0; i < lines.count(); i++) + { + cpp << myIndent << "// " << lines[i] << 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 + cpp << myIndent << "// "<< comment << m_endl; + } +} + +void CppWriter::writeDocumentation(QString header, QString body, QString end, QTextStream &cpp) +{ + writeBlankLine(cpp); + QString indent = getIndent(); + + cpp << indent << "/**" << m_endl; + if (!header.isEmpty()) + cpp << formatDoc(header, indent + " * "); + if (!body.isEmpty()) + cpp << formatDoc(body, indent + " * "); + if (!end.isEmpty()) + { + QStringList lines = QStringList::split( "\n", end); + for(uint i= 0; i < lines.count(); i++) + cpp << formatDoc(lines[i], indent + " * "); + } + cpp << indent << " */" << m_endl; +} + +void CppWriter::writeAssociationDecls(UMLAssociationList associations, Uml::Visibility permitScope, Uml::IDType id, QTextStream &h) +{ + + 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 && !a->getRoleName(Uml::B).isEmpty()) + printRoleB = true; + + if (a->getObjectId(Uml::B) == id && !a->getRoleName(Uml::A).isEmpty()) + 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(), getIndent(), h); + + // print RoleB decl + if (printRoleB && a->getVisibility(Uml::B) == permitScope) + { + + QString fieldClassName = cleanName(getUMLObjectName(a->getObject(Uml::B))); + writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::B), a->getMulti(Uml::B), a->getRoleDoc(Uml::B), h); + } + + // print RoleA decl + if (printRoleA && a->getVisibility(Uml::A) == permitScope) + { + QString fieldClassName = cleanName(getUMLObjectName(a->getObject(Uml::A))); + writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::A), a->getMulti(Uml::A), a->getRoleDoc(Uml::A), h); + } + + // reset for next association in our loop + printRoleA = false; + printRoleB = false; + } + } +} + +void CppWriter::writeAssociationRoleDecl(QString fieldClassName, QString roleName, QString multi, + QString doc, QTextStream &stream) +{ + // ONLY write out IF there is a rolename given + // otherwise its not meant to be declared in the code + if (roleName.isEmpty()) + return; + + QString indent = getIndent(); + + // always put space between this and prior decl, if any + writeBlankLine(stream); + + if (!doc.isEmpty()) + writeComment(doc, indent, stream); + + // 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.lower(); + + // record this for later consideration of initialization IF the + // multi value requires 1 of these objects + if(ObjectFieldVariables.findIndex(fieldVarName) == -1 && + multi.contains(QRegExp("^1$")) + ) + { + // ugh. UGLY. Storing variable name and its class in pairs. + ObjectFieldVariables.append(fieldVarName); + ObjectFieldVariables.append(fieldClassName); + } + + stream << indent << fieldClassName << " * " << fieldVarName << ";" << m_endl; + } + else + { + QString fieldVarName = "m_" + roleName.lower() + "Vector"; + + // record unique occurrences for later when we want to check + // for initialization of this vector + if(VectorFieldVariables.findIndex(fieldVarName) == -1) + VectorFieldVariables.append(fieldVarName); + + stream << indent << policyExt()->getVectorClassName() <<"<" << fieldClassName << "*"; + stream << "> " << fieldVarName << ";" << m_endl; + } +} + +// for either source or header files +void CppWriter::writeAssociationMethods (UMLAssociationList associations, + Uml::Visibility permitVisib, + bool isHeaderMethod, + bool writeMethodBody, + bool writePointerVar, + Uml::IDType myID, QTextStream &stream) +{ + 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) == myID && a->getVisibility(Uml::B) == permitVisib) + { + // only write out IF there is a rolename given + if(!a->getRoleName(Uml::B).isEmpty()) { + QString fieldClassName = getUMLObjectName(a->getObject(Uml::B)) + (writePointerVar ? " *":""); + writeAssociationRoleMethod(fieldClassName, + isHeaderMethod, + writeMethodBody, + a->getRoleName(Uml::B), + a->getMulti(Uml::B), a->getRoleDoc(Uml::B), + a->getChangeability(Uml::B), stream); + } + } + + if (a->getObjectId(Uml::B) == myID && a->getVisibility(Uml::A) == permitVisib) + { + // only write out IF there is a rolename given + if(!a->getRoleName(Uml::A).isEmpty()) { + QString fieldClassName = getUMLObjectName(a->getObject(Uml::A)) + (writePointerVar ? " *":""); + writeAssociationRoleMethod(fieldClassName, + isHeaderMethod, + writeMethodBody, + a->getRoleName(Uml::A), + a->getMulti(Uml::A), + a->getRoleDoc(Uml::A), + a->getChangeability(Uml::A), + stream); + } + } + + } + } +} + +void CppWriter::writeAssociationRoleMethod (const QString &fieldClassName, + bool isHeaderMethod, + bool writeMethodBody, + const QString &roleName, const QString &multi, + const QString &description, Uml::Changeability_Type change, + QTextStream &stream) +{ + if(multi.isEmpty() || multi.contains(QRegExp("^[01]$"))) + { + QString fieldVarName = "m_" + roleName.lower(); + writeSingleAttributeAccessorMethods(fieldClassName, fieldVarName, roleName, + description, change, isHeaderMethod, false, writeMethodBody, stream); + } + else + { + QString fieldVarName = "m_" + roleName.lower() + "Vector"; + writeVectorAttributeAccessorMethods(fieldClassName, fieldVarName, roleName, + description, change, isHeaderMethod, writeMethodBody, stream); + } +} + +void CppWriter::writeVectorAttributeAccessorMethods ( + const QString &fieldClassName, const QString &fieldVarName, + const QString &fieldName, const QString &description, + Uml::Changeability_Type changeType, + bool isHeaderMethod, + bool writeMethodBody, + QTextStream &stream) +{ + + QString className = fixTypeName(fieldClassName); + QString fldName = Codegen_Utils::capitalizeFirstLetter(fieldName); + QString indent = getIndent(); + + // ONLY IF changeability is NOT Frozen + if (changeType != Uml::chg_Frozen) + { + writeDocumentation("Add a " + fldName + " object to the " + fieldVarName + " List",description,"",stream); + stream << indent << "void "; + if(!isHeaderMethod) + stream << m_classifierInfo->className << "::"; + stream << "add" << fldName << " ( " << className << " add_object )"; + if (writeMethodBody) { + QString method = VECTOR_METHOD_APPEND; + method.replace(QRegExp("%VARNAME%"),fieldVarName); + method.replace(QRegExp("%VECTORTYPENAME%"), policyExt()->getVectorClassName()); + method.replace(QRegExp("%ITEMCLASS%"),className); + stream << indent << " {" << m_endl; + m_indentLevel++; + printTextAsSeparateLinesWithIndent(method,getIndent(),stream); + m_indentLevel--; + stream << indent << "}" << m_endl; + } else + stream << ";" << m_endl; + } + + // ONLY IF changeability is Changeable + if (changeType == Uml::chg_Changeable) + { + writeDocumentation("Remove a " + fldName + " object from " + fieldVarName + " List", + description, "", stream); + stream << indent << "void "; + if(!isHeaderMethod) + stream << m_classifierInfo->className << "::"; + stream << "remove" << fldName << " ( " << className << " remove_object )"; + if (writeMethodBody) { + QString method = VECTOR_METHOD_REMOVE; + method.replace(QRegExp("%VARNAME%"),fieldVarName); + method.replace(QRegExp("%VECTORTYPENAME%"), policyExt()->getVectorClassName()); + method.replace(QRegExp("%ITEMCLASS%"),className); + stream << indent << " {" << m_endl; + m_indentLevel++; + printTextAsSeparateLinesWithIndent(method,getIndent(),stream); + m_indentLevel--; + stream << indent << "}" << m_endl; + } else + stream << ";" << m_endl; + } + + // always allow getting the list of stuff + QString returnVarName = policyExt()->getVectorClassName() + '<' + className + '>'; + writeDocumentation("Get the list of " + fldName + " objects held by " + fieldVarName, + description, + "@return " + returnVarName + " list of " + fldName + " objects held by " + fieldVarName, + stream); + stream << indent << returnVarName << " "; + if(!isHeaderMethod) + stream << m_classifierInfo->className << "::"; + stream << "get" << fldName << "List ( )"; + if(writeMethodBody) { + stream << indent << " {" << m_endl; + m_indentLevel++; + stream << getIndent() << "return " << fieldVarName << ";" << m_endl; + m_indentLevel--; + stream << indent << "}" << m_endl; + } else + stream << ";" << m_endl; + +} + + +void CppWriter::writeSingleAttributeAccessorMethods( + const QString& fieldClassName, const QString& fieldVarName, + const QString& fieldName, const QString &description, + Uml::Changeability_Type change, + bool isHeaderMethod, + bool isStatic, + bool writeMethodBody, + QTextStream &stream) +{ + + // DON'T write this IF its a source method AND writeMethodBody is "false" + if(!isHeaderMethod && !writeMethodBody) + return; + + QString className = fixTypeName(fieldClassName); + QString fldName = Codegen_Utils::capitalizeFirstLetter(fieldName); + QString indent = getIndent(); + + // set method + if (change == Uml::chg_Changeable && !isStatic) { + writeDocumentation("Set the value of " + fieldVarName,description,"@param new_var the new value of " + fieldVarName,stream); + stream << indent << "void "; + if(!isHeaderMethod) + stream << m_classifierInfo->className << "::"; + stream << "set" << fldName << " ( " << className << " new_var )"; + + if(writeMethodBody) { + stream << indent << " {" << m_endl; + m_indentLevel++; + stream << getIndent() << indent; + m_indentLevel--; + if(isStatic) + stream << m_classifierInfo->className << "::"; + stream << fieldVarName << " = new_var;" << m_endl; + stream << indent << "}" << m_endl; + } else + stream << ";" << m_endl; + } + + // get method + writeDocumentation("Get the value of " + fieldVarName,description,"@return the value of " + fieldVarName,stream); + stream << indent << className << " "; + if(!isHeaderMethod) + stream << m_classifierInfo->className << "::"; + stream << "get" << fldName << " ( )"; + + if(writeMethodBody) { + stream << indent << " {" << m_endl; + m_indentLevel++; + stream << getIndent() << "return "; + m_indentLevel--; + if(isStatic) + stream << m_classifierInfo->className << "::"; + stream << fieldVarName << ";" << m_endl; + stream << indent << "}"; + } else + stream << ";" << m_endl; + + writeBlankLine(stream); +} + +// one day, this should print out non-empty constructor operations too. +void CppWriter::writeConstructorDecls(QTextStream &stream) +{ + const bool generateEmptyConstructors = + UMLApp::app()->getCommonPolicy()->getAutoGenerateConstructors(); + if (forceDoc() || generateEmptyConstructors) + { + writeComment("Constructors/Destructors", getIndent(), stream); + writeComment(" ", getIndent(), stream); + writeBlankLine(stream); + } + if (!generateEmptyConstructors) + return; + + writeDocumentation("", "Empty Constructor", "", stream); + stream << getIndent() << m_classifierInfo->className << " ( );" << m_endl; + writeDocumentation("", "Empty Destructor", "", stream); + stream << getIndent(); + stream << "virtual ~" << m_classifierInfo->className << " ( );" << m_endl; + writeBlankLine(stream); +} + +void CppWriter::writeInitAttibuteDecl (QTextStream &stream) +{ + if (UMLApp::app()->getCommonPolicy()->getAutoGenerateConstructors() && + m_classifierInfo->hasAttributes) + stream << getIndent() << "void initAttributes ( ) ;" << m_endl; +} + +void CppWriter::writeInitAttibuteMethod (QTextStream &stream) +{ + // only need to do this under certain conditions + if (!UMLApp::app()->getCommonPolicy()->getAutoGenerateConstructors() || + !m_classifierInfo->hasAttributes) + return; + + QString className = m_classifierInfo->className; + QString indent = getIndent(); + + stream << indent << "void " << className << "::" << "initAttributes ( ) {" << m_endl; + + m_indentLevel++; + // first, initiation of fields derived from attributes + UMLAttributeList atl = m_classifierInfo->getAttList(); + for(UMLAttribute *at = atl.first(); at ; at = atl.next()) { + if(!at->getInitialValue().isEmpty()) { + QString varName = getAttributeVariableName(at); + stream << getIndent() << varName << " = " << at->getInitialValue() << ";" << m_endl; + } + } + // Now initialize the association related fields (e.g. vectors) + if (!VECTOR_METHOD_INIT.isEmpty()) { + QStringList::Iterator it; + for( it = VectorFieldVariables.begin(); it != VectorFieldVariables.end(); ++it ) { + QString fieldVarName = *it; + QString method = VECTOR_METHOD_INIT; + method.replace(QRegExp("%VARNAME%"),fieldVarName); + method.replace(QRegExp("%VECTORTYPENAME%"), policyExt()->getVectorClassName()); + stream << getIndent() << method << m_endl; + } + } + + if (!OBJECT_METHOD_INIT.isEmpty()) { + QStringList::Iterator it; + for( it = ObjectFieldVariables.begin(); it != ObjectFieldVariables.end(); ++it ) { + QString fieldVarName = *it; + it++; + QString fieldClassName = *it; + QString method = OBJECT_METHOD_INIT; + method.replace(QRegExp("%VARNAME%"),fieldVarName); + method.replace(QRegExp("%ITEMCLASS%"),fieldClassName); + stream << getIndent() << method << m_endl; + } + } + + // clean up + ObjectFieldVariables.clear(); // shouldn't be needed? + VectorFieldVariables.clear(); // shouldn't be needed? + + m_indentLevel--; + + stream << indent << "}" << m_endl; +} + +// one day, this should print out non-empty constructor operations too. +void CppWriter::writeConstructorMethods(QTextStream &stream) +{ + const bool generateEmptyConstructors = + UMLApp::app()->getCommonPolicy()->getAutoGenerateConstructors(); + + if (forceDoc() || generateEmptyConstructors) { + writeComment("Constructors/Destructors", getIndent(), stream); + writeComment(" ", getIndent(), stream); + writeBlankLine(stream); + } + if (!generateEmptyConstructors) + return; + + QString className = m_classifierInfo->className; + // empty constructor + QString indent = getIndent(); + stream << indent << className << "::" << className << " ( ) {" << m_endl; + if(m_classifierInfo->hasAttributes) + stream << indent << indent << "initAttributes();" << m_endl; + stream << indent << "}" << m_endl; + writeBlankLine(stream); + + // empty destructor + stream << getIndent() << className << "::~" << className << " ( ) { }" << m_endl; + writeBlankLine(stream); +} + +// IF the type is "string" we need to declare it as +// the Java Object "String" (there is no string primative in Java). +QString CppWriter::fixTypeName(const QString &string) +{ + if (string.isEmpty()) + return "void"; + if (string == "string") + return policyExt()->getStringClassName(); + return string; +} + +void CppWriter::writeOperations(UMLClassifier *c, bool isHeaderMethod, + Uml::Visibility permitScope, QTextStream &cpp) { + + UMLOperationList oplist; + + //sort operations by scope first and see if there are abstract methods + UMLOperationList inputlist = c->getOpList(); + for (UMLOperation *op = inputlist.first(); op; op = inputlist.next()) { + if (op->getVisibility() == permitScope) { + oplist.append(op); + } + } + + // do people REALLY want these comments? Hmm. + /* + if(forceSections() || oppub.count()) + { + writeComment("public operations",getIndent(),cpp); + writeBlankLine(cpp); + } + */ + writeOperations(oplist,isHeaderMethod, cpp); + +} + +// write operation in either header or +// a source file +void CppWriter::writeOperations(UMLOperationList &oplist, bool isHeaderMethod, QTextStream &cpp) { + QString className = m_classifierInfo->className; + const bool generateEmptyConstructors = + UMLApp::app()->getCommonPolicy()->getAutoGenerateConstructors(); + + // generate method decl for each operation given + for (UMLOperation *op = oplist.first(); op; op = oplist.next()) { + + QString returnStr; // buffer for documentation + QString methodReturnType; + UMLAttributeList atl = op->getParmList(); // method parameters + + if (op->isConstructorOperation()) { + if (generateEmptyConstructors && atl.count() == 0) + continue; // it's already been written, see writeConstructor{Decls,Methods} + } else if (op->isDestructorOperation()) { + if (generateEmptyConstructors) + continue; // it's already been written, see writeConstructor{Decls,Methods} + } else { + methodReturnType = fixTypeName(op->getTypeName()); + if(methodReturnType != "void") + returnStr += "@return " + methodReturnType + '\n'; + } + + QString str; + if (op->getAbstract() || m_classifierInfo->isInterface) { + if (isHeaderMethod) { + // declare abstract method as 'virtual' + str += "virtual "; + } + } + + // static declaration for header file + if (isHeaderMethod && op->getStatic()) + str += "static "; + + // returntype of method + str += methodReturnType + ' '; + + if (!isHeaderMethod) + str += className + "::"; + + str += cleanName(op->getName()) + " ("; + + // generate parameters + uint j = 0; + for (UMLAttribute *at = atl.first(); at; at = atl.next(), j++) { + QString typeName = fixTypeName(at->getTypeName()); + QString atName = cleanName(at->getName()); + str += typeName + ' ' + atName; + const QString initVal = at->getInitialValue(); + if (! initVal.isEmpty()) + str += " = " + initVal; + if (j < atl.count() - 1) + str += ", "; + returnStr += "@param " + atName + ' ' + at->getDoc() + '\n'; + } + str += " )"; + + if (op->getConst()) + str += " const"; + + // method body : only gets IF its not in a header + if (isHeaderMethod && !policyExt()->getOperationsAreInline()) + str += ';'; // terminate now + else + str +=getIndent() + " {\n\n" + getIndent() + '}'; // empty method body + + // write it out + writeDocumentation("", op->getDoc(), returnStr, cpp); + cpp << getIndent() << str << m_endl; + writeBlankLine(cpp); + } +} + +// To prevent circular including when both classifiers on either end +// of an association have roles we need to have forward declaration of +// the other class...but only IF its not THIS class (as could happen +// in self-association relationship). +void CppWriter::printAssociationIncludeDecl (UMLAssociationList list, Uml::IDType myId, QTextStream &stream) +{ + + for (UMLAssociation *a = list.first(); a; a = list.next()) { + UMLClassifier *current = NULL; + bool isFirstClass = true; + + // only use OTHER classes (e.g. we don't need to write includes for ourselves!! + // AND only IF the roleName is defined, otherwise, its not meant to be noticed. + if (a->getObjectId(Uml::A) == myId && !a->getRoleName(Uml::B).isEmpty()) { + current = dynamic_cast<UMLClassifier*>(a->getObject(Uml::B)); + } else if (a->getObjectId(Uml::B) == myId && !a->getRoleName(Uml::A).isEmpty()) { + current = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A)); + isFirstClass = false; + } + + // as header doc for this method indicates, we need to be a bit sophisticated on + // how to declare some associations. + if( current ) + if( !isFirstClass && !a->getRoleName(Uml::A).isEmpty() && !a->getRoleName(Uml::B).isEmpty()) + stream << "class " << current->getName() << ";" << m_endl; // special case: use forward declaration + else + stream << "#include \"" << current->getName() << ".h\"" << m_endl; // just the include statement + } +} + +QString CppWriter::fixInitialStringDeclValue(const QString &value, const QString &type) +{ + QString val = value; + // check for strings only + if (!val.isEmpty() && type == policyExt()->getStringClassName()) { + if (!val.startsWith("\"")) + val.prepend("\""); + if (!val.endsWith("\"")) + val.append("\""); + } + return val; +} + +// methods like this _shouldn't_ be needed IF we properly did things thruought the code. +QString CppWriter::getUMLObjectName(UMLObject *obj) +{ + return(obj!=0)?obj->getName():QString("NULL"); +} + +void CppWriter::writeBlankLine(QTextStream &stream) +{ + stream << m_endl; +} + +void CppWriter::printTextAsSeparateLinesWithIndent (const QString &text, const QString &indent, QTextStream &stream) +{ + if(text.isEmpty()) + return; + + QStringList lines = QStringList::split( "\n", text); + for(uint i= 0; i < lines.count(); i++) + stream << indent << lines[i] << m_endl; +} + +QString CppWriter::getAttributeVariableName (UMLAttribute *at) +{ + QString fieldName = "m_" + cleanName(at->getName()); + return fieldName; +} + +QStringList CppWriter::defaultDatatypes() { + return Codegen_Utils::cppDatatypes(); +} + +const QStringList CppWriter::reservedKeywords() const { + return Codegen_Utils::reservedCppKeywords(); +} + diff --git a/umbrello/umbrello/codegenerators/cppwriter.h b/umbrello/umbrello/codegenerators/cppwriter.h new file mode 100644 index 00000000..8ae58226 --- /dev/null +++ b/umbrello/umbrello/codegenerators/cppwriter.h @@ -0,0 +1,293 @@ +/*************************************************************************** + cppwriter.h - 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 + (C) 2004 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. * + * * + ***************************************************************************/ + +#ifndef CPPWRITER_H +#define CPPWRITER_H + +#include "simplecodegenerator.h" +#include "cppcodegenerationpolicy.h" +#include "../umloperationlist.h" +#include "../umlattributelist.h" +#include "../umlassociationlist.h" + +class QFile; +class ClassifierInfo; + +/** + * class CppWriter is a code generator for UMLClassifier objects. + * Create an instance of this class, and feed it a UMLClassifier when + * calling writeClass and it will generate both a header (.h) and + * source (.cpp) file for that classifier. + */ +class CppWriter : public SimpleCodeGenerator { +public: + + /** + * Constructor, initialises a couple of variables + */ + CppWriter(); + + /** + * Destructor, empty + */ + virtual ~CppWriter(); + + /** + * call this method to generate cpp code for a UMLClassifier + * @param c the class to generate code for + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "C++" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * Add C++ primitives as datatypes + */ + QStringList defaultDatatypes(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +private: + + /** + * Writes class's documentation to the class header + * public abstract class Foo extents { + */ + void writeClassDecl(UMLClassifier *c, QTextStream &cpp); + + /** + * Writes the comment and class constructor declaration or methods + */ + void writeConstructorDecls(QTextStream &h); + void writeConstructorMethods(QTextStream &cpp); + + /** + * write all field declarations, for both attributes and associations for the + * given permitted scope. + */ + void writeFieldDecl(UMLClassifier *c, Uml::Visibility permitScope, QTextStream &stream); + + /** + * write all method declarations, for attributes and associations + * for the given permitted scope. + */ + void writeAccessorMethodDecl(UMLClassifier *c, Uml::Visibility permitScope, QTextStream &stream); + + /** + * write all operations for a given class + * @param c the class for which we are generating code + * @param isHeaderMethod true when writing to a header file, false for body file + * @param permitScope what type of method to write (by Scope) + * @param j the stream associated with the output file + */ + void writeOperations(UMLClassifier *c, bool isHeaderMethod, Uml::Visibility permitScope, QTextStream &j); + + /** + * write a list of operations for a given class + * @param list the list of operations you want to write + * @param isHeaderMethod true when writing to a header file, false for body file + * @param j the stream associated with the output file + */ + void writeOperations(UMLOperationList &list, bool isHeaderMethod, QTextStream &j); + + /** + * write all attributes for a given class + * @param c the class for which we are generating code + * @param j the stream associated with the output file + */ + void writeAttributes(UMLClassifier *c, QTextStream &j); + + /** + * writes the Attribute declarations + * @param visibility the visibility of the attribs to print out + * @param writeStatic whether to write static or non-static attributes out + * @param stream text stream + */ + void writeAttributeDecls (Uml::Visibility visibility, bool writeStatic, QTextStream &stream ); + + /** + * Write out fields and operations for this class selected on a particular + * visibility. + */ + void writeHeaderFieldDecl(UMLClassifier *c, Uml::Visibility permitVisibility, QTextStream &stream); + + void writeHeaderAttributeAccessorMethods (Uml::Visibility visibility, bool writeStatic, QTextStream &stream ); + + void writeHeaderAttributeAccessorMethodDecls(UMLClassifier *c, Uml::Visibility permitVisibility, QTextStream &stream); + void writeHeaderAccessorMethodDecl(UMLClassifier *c, Uml::Visibility permitScope, QTextStream &stream); + + + /** + * Searches a list of associations for appropriate ones to write out as attributes + */ + void writeAssociationDecls(UMLAssociationList associations, Uml::Visibility permit, Uml::IDType id, QTextStream &stream); + + /** + * Writes out an association as an attribute using Vector + */ + void writeAssociationRoleDecl(QString fieldClassName, QString roleName, QString multi, + QString doc, QTextStream &stream); + + /** + * calls @ref writeSingleAttributeAccessorMethods() on each of the attributes in attribs list. + */ + void writeAttributeMethods(UMLAttributeList *attribs, Uml::Visibility visib, bool isHeaderMethod, + bool isStatic, + bool writeMethodBody, QTextStream &stream); + + /** + * calls @ref writeAssociationRoleMethod() on each of the associations in the given list + */ + void writeAssociationMethods(UMLAssociationList associations, Uml::Visibility permitVisib, + bool isHeaderMethod, + bool writeMethodBody, bool writePointerVar, Uml::IDType id, QTextStream &stream); + + /** + * calls @ref writeSingleAttributeAccessorMethods() or @ref + * writeVectorAttributeAccessorMethods() on the association + * role + */ + void writeAssociationRoleMethod(const QString &fieldClassName, bool isHeaderMethod, bool writeMethodBody, + const QString &roleName, const QString &multi, + const QString &description, Uml::Changeability_Type change, + QTextStream &stream); + + /** + * Writes getFoo() and setFoo() accessor methods for the attribute + */ + void writeSingleAttributeAccessorMethods( + const QString &fieldClassName, const QString &Name, + const QString &fieldName, const QString &description, + Uml::Changeability_Type change, + bool isHeaderMethod, + bool isStatic, bool writeMethodBody, QTextStream &cpp); + + /** + * Writes addFoo() and removeFoo() accessor methods for the Vector attribute + */ + void writeVectorAttributeAccessorMethods( + const QString &fieldClassName, const QString &fieldVarName, + const QString &fieldName, const QString &description, + Uml::Changeability_Type change, + bool isHeaderMethod, + bool writeMethodBody, + QTextStream &cpp); + + /** + * Writes a // style comment + */ + void writeComment(const QString &text, const QString &indent, QTextStream &cpp); + + /** + * Writes a documentation comment + */ + void writeDocumentation(QString header, QString body, QString end, QTextStream &cpp); + + + /** + * write the header file for this classifier. + */ + void writeHeaderFile (UMLClassifier *c, QFile &file); + + /** + * write the source code body file for this classifier. + */ + void writeSourceFile (UMLClassifier *c, QFile &file); + + /** + * utility method to break up a block of text, which has embedded newline chars, + * and print them to a stream as separate lines of text, indented as directed. + */ + void printTextAsSeparateLinesWithIndent (const QString &text, const QString &indent, + QTextStream &stream); + + /** + * Intellegently print out header include/forward decl. for associated classes. + */ + void printAssociationIncludeDecl (UMLAssociationList list, Uml::IDType this_id, QTextStream &stream); + + /** + * If needed, write out the method to initialize attributes of our class. + */ + void writeInitAttibuteMethod (QTextStream &stream); + + /** + * If needed, write out the declaration for the method to initialize attributes of our class. + */ + void writeInitAttibuteDecl (QTextStream &stream); + + /** + * Returns the name of the given object (if it exists) + */ + QString getUMLObjectName(UMLObject *obj); + + /** + * Replaces `string' with STRING_TYPENAME. + */ + QString fixTypeName(const QString &string); + + /** + * check that initial values of strings have quotes around them + */ + QString fixInitialStringDeclValue(const QString &value, const QString &type); + + /** + * Determine what the variable name of this attribute should be. + */ + QString getAttributeVariableName (UMLAttribute *at); + + /** + * Write a blank line + */ + void writeBlankLine(QTextStream &stream); + + /** + * Return the policy object + */ + CPPCodeGenerationPolicy *policyExt(); + + /** + * Summary information about current classifier. + */ + ClassifierInfo * m_classifierInfo; + + QString VECTOR_METHOD_APPEND; + QString VECTOR_METHOD_REMOVE; + QString VECTOR_METHOD_INIT; + QString OBJECT_METHOD_INIT; + + /** + * Create association methods for class attributes/associations/operations as inline decl in header. + */ + bool INLINE_ASSOCIATION_METHODS; + + QStringList ObjectFieldVariables; + QStringList VectorFieldVariables; + +}; + + + +#endif // CPPWRITER_H diff --git a/umbrello/umbrello/codegenerators/csharpwriter.cpp b/umbrello/umbrello/codegenerators/csharpwriter.cpp new file mode 100644 index 00000000..73975b48 --- /dev/null +++ b/umbrello/umbrello/codegenerators/csharpwriter.cpp @@ -0,0 +1,725 @@ +/*************************************************************************** + * * + * 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) 2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// +// C++ Implementation: csharpwriter +// +#include "csharpwriter.h" + +#include <kdebug.h> +#include <qregexp.h> +#include <qtextstream.h> + +#include "../uml.h" +#include "../umldoc.h" +#include "../folder.h" +#include "../classifier.h" +#include "../association.h" +#include "../attribute.h" +#include "../operation.h" +#include "../umlnamespace.h" + +static const char *reserved_words[] = { + "abstract", + "as", + "base", + "bool", + "break", + "byte", + "case", + "catch", + "char", + "checked", + "class", + "const", + "continue", + "decimal", + "default", + "delegate", + "do", + "double", + "else", + "enum", + "event", + "explicit", + "extern", + "false", + "finally", + "for", + "foreach", + "goto", + "if", + "implicit", + "in", + "int", + "interface", + "internal", + "is", + "lock", + "long", + "namespace", + "new", + "null", + "object", + "operator", + "out", + "override", + "params", + "private", + "protected", + "public", + "readonly", + "ref", + "return", + "sbyte", + "sealed", + "short", + "sizeof", + "stackalloc", + "static", + "string", + "struct", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "uint", + "ulong", + "unchecked", + "unsafe", + "ushort", + "using", + "virtual", + "void", + "volatile", + "while", + 0 +}; + +CSharpWriter::CSharpWriter() + : SimpleCodeGenerator() +{ +} + + +CSharpWriter::~CSharpWriter() +{ +} + +QStringList CSharpWriter::defaultDatatypes() { + QStringList l; + l.append("bool"); + l.append("byte"); + l.append("char"); + l.append("decimal"); + l.append("double"); + l.append("fixed"); + l.append("float"); + l.append("fixed"); + l.append("float"); + l.append("int"); + l.append("long"); + l.append("object"); + l.append("sbyte"); + l.append("short"); + l.append("string"); + l.append("uint"); + l.append("ulong"); + l.append("ushort"); + return l; +} + +void CSharpWriter::writeClass(UMLClassifier *c) { + if (!c) { + kDebug()<<"Cannot write class of NULL concept!" << endl; + return; + } + + QString classname = cleanName(c->getName()); + //find an appropriate name for our file + QString fileName = findFileName(c, ".cs"); + if (fileName.isEmpty()) { + emit codeGenerated(c, false); + return; + } + + QFile filecs; + if (!openFile(filecs, fileName)) { + emit codeGenerated(c, false); + return; + } + QTextStream cs(&filecs); + + ////////////////////////////// + //Start generating the code!! + ///////////////////////////// + + + //try to find a heading file (license, coments, etc) + QString str; + str = getHeadingFile(".cs"); + if (!str.isEmpty()) { + str.replace(QRegExp("%filename%"),fileName); + str.replace(QRegExp("%filepath%"),filecs.name()); + cs<<str<<m_endl; + } + + UMLDoc *umldoc = UMLApp::app()->getDocument(); + UMLFolder *logicalView = umldoc->getRootFolder(Uml::mt_Logical); + + // write generic includes + cs << "using System;" << m_endl; + cs << "using System.Text;" << m_endl; + cs << "using System.Collections;" << m_endl; + cs << "using System.Collections.Generic;" << m_endl << m_endl; + + //write includes and namespace + + UMLPackage *container = c->getUMLPackage(); + if (container == logicalView) + container = NULL; + + UMLPackageList includes; + findObjectsRelated(c, includes); + m_seenIncludes.clear(); + //m_seenIncludes.append(logicalView); + if (includes.count()) { + UMLPackage *p; + for (UMLPackageListIt it(includes); (p = it.current()) != NULL; ++it) { + UMLClassifier *cl = dynamic_cast<UMLClassifier*>(p); + if (cl) + p = cl->getUMLPackage(); + if (p != logicalView && m_seenIncludes.findRef(p) == -1 && p != container) { + cs << "using " << p->getFullyQualifiedName(".") << ";" << m_endl; + m_seenIncludes.append(p); + } + } + cs << m_endl; + } + + m_container_indent = ""; + + if (container) { + cs << "namespace " << container->getFullyQualifiedName(".") << m_endl; + cs << "{" << m_endl << m_endl; + m_container_indent = m_indentation; + m_seenIncludes.append(container); + } + + //Write class Documentation if there is somthing or if force option + if (forceDoc() || !c->getDoc().isEmpty()) { + cs << m_container_indent << "/// <summary>" << m_endl; + cs << formatDoc(c->getDoc(), m_container_indent + "/// " ); + cs << m_container_indent << "/// </summary>" << m_endl ; + } + + UMLClassifierList superclasses = c->getSuperClasses(); + UMLAssociationList aggregations = c->getAggregations(); + UMLAssociationList compositions = c->getCompositions(); + UMLAssociationList realizations = c->getRealizations(); + bool isInterface = c->isInterface(); + m_unnamedRoles = 1; + + cs << m_container_indent << "public "; + + //check if it is an interface or regular class + if (isInterface) { + cs << "interface " << classname; + } else { + //check if class is abstract and / or has abstract methods + if (c->getAbstract() || c->hasAbstractOps()) + cs << "abstract "; + + cs << "class " << classname << (superclasses.count() > 0 ? " : ":""); + + // write baseclass, ignore interfaces, write error on multiple inheritance + if (superclasses.count() > 0) { + UMLClassifier *obj; + int supers = 0; + for (obj = superclasses.first(); obj; obj = superclasses.next()) { + if (!obj->isInterface()) { + if (supers > 0) { + cs << " // AND "; + } + cs << cleanName(obj->getName()); + supers++; + } + } + if (supers > 1) { + cs << m_endl << "//WARNING: C# does not support multiple inheritance but there is more than 1 superclass defined in your UML model!" << m_endl; + } + } + //check for realizations + UMLAssociationList realizations = c->getRealizations(); + UMLAssociation *a; + + if (!realizations.isEmpty()) { + for (a = realizations.first(); a; a = realizations.next()) { + UMLClassifier *real = (UMLClassifier*)a->getObject(Uml::B); + if(real != c) { + // write list of realizations + cs << ", " << real->getName(); + } + + } + } + } + cs << m_endl << m_container_indent << '{' << m_endl; + + //associations + if (forceSections() || !aggregations.isEmpty()) { + cs << m_endl << m_container_indent << m_indentation << "#region Aggregations" << m_endl << m_endl; + writeAssociatedAttributes(aggregations, c, cs); + cs << m_endl << m_container_indent << m_indentation << "#endregion" << m_endl; + } + + //compositions + if (forceSections() || !compositions.isEmpty()) { + cs << m_endl << m_container_indent << m_indentation << "#region Compositions" << m_endl << m_endl; + writeAssociatedAttributes(compositions, c, cs); + cs << m_endl << m_container_indent << m_indentation << "#endregion" << m_endl; + } + + //attributes + // FIXME: C# allows Properties in interface! + if (!isInterface) + writeAttributes(c, cs); + + //operations + writeOperations(c, cs); + + //finish file + cs << m_endl << m_container_indent << "}" << m_endl << m_endl; // close class + + if (container) { + cs << "} // end of namespace " + << container->getFullyQualifiedName(".") << m_endl << m_endl; + } + + //close files and notfiy we are done + filecs.close(); + emit codeGenerated(c, true); +} + +//////////////////////////////////////////////////////////////////////////////////// +// Helper Methods + +void CSharpWriter::writeOperations(UMLClassifier *c, QTextStream &cs) { + + //Lists to store operations sorted by scope + UMLOperationList oppub,opprot,oppriv; + + bool isInterface = c->isInterface(); + bool generateErrorStub = true; + + oppub.setAutoDelete(false); + opprot.setAutoDelete(false); + oppriv.setAutoDelete(false); + + //sort operations by scope first and see if there are abstract methods + UMLOperationList opl(c->getOpList()); + 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; + } + } + + // write realizations (recursive) + UMLAssociationList realizations = c->getRealizations(); + + if (!isInterface && !realizations.isEmpty()) { + writeRealizationsRecursive(c, &realizations, cs); + } + + // write public operations + if (forceSections() || !oppub.isEmpty()) { + cs << m_endl << m_container_indent << m_indentation << "#region Public methods" << m_endl << m_endl; + writeOperations(oppub,cs,isInterface,false,generateErrorStub); + cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl; + } + + // write protected operations + if (forceSections() || !opprot.isEmpty()) { + cs << m_endl << m_container_indent << m_indentation << "#region Protected methods" << m_endl << m_endl; + writeOperations(opprot,cs,isInterface,false,generateErrorStub); + cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl; + } + + // write private operations + if (forceSections() || !oppriv.isEmpty()) { + cs << m_endl << m_container_indent << m_indentation << "#region Private methods" << m_endl << m_endl; + writeOperations(oppriv,cs,isInterface,false,generateErrorStub); + cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl; + } + + // write superclasses abstract methods + UMLClassifierList superclasses = c->getSuperClasses(); + + if (!isInterface && !c->getAbstract() && !c->hasAbstractOps() + && superclasses.count() > 0) { + writeOverridesRecursive(&superclasses, cs); + } + +} + +void CSharpWriter::writeOverridesRecursive(UMLClassifierList *superclasses, QTextStream &cs) { + // oplist for implemented abstract operations + UMLOperationList opabstract; + opabstract.setAutoDelete(false); + UMLClassifier *obj; + + for (obj = superclasses->first(); obj; obj = superclasses->next()) { + if (!obj->isInterface() && obj->hasAbstractOps()) { + // collect abstract ops + UMLOperationList opl(obj->getOpList()); + for (UMLOperation *op = opl.first(); op ; op = opl.next()) { + if (op->getAbstract()) { + opabstract.append(op); + } + } + + // write abstract implementations + cs << m_endl << m_container_indent << m_indentation << "#region " << obj->getName() << " members" << m_endl << m_endl; + writeOperations(opabstract,cs,false,true,true); + cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl; + + opabstract.clear(); + } + // Recurse to parent superclasses + UMLClassifierList superRecursive = obj->getSuperClasses(); + UMLClassifierList *superRecursivePtr =& superRecursive; + if (superRecursivePtr->count() > 0) { + writeOverridesRecursive(superRecursivePtr, cs); + } + } +} +void CSharpWriter::writeRealizationsRecursive(UMLClassifier *currentClass, UMLAssociationList *realizations, QTextStream &cs) { + + UMLAssociation *a; + for (a = realizations->first(); a; a = realizations->next()) { + + // we know its a classifier if its in the list + UMLClassifier *real = (UMLClassifier*)a->getObject(Uml::B); + + //FIXME: Interfaces realize themselves without this condition!? + if (real == currentClass) + continue; + + // collect operations of one realization + UMLOperationList opreal = real->getOpList(); + + // write realizations + cs << m_endl << m_container_indent << m_indentation << "#region " << real->getName() << " members" << m_endl << m_endl; + writeOperations(opreal,cs,false,false,true); + cs << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl; + + // Recurse to parent realizations + UMLAssociationList parentReal = real->getRealizations(); + if (!parentReal.isEmpty()) { + writeRealizationsRecursive(real, &parentReal, cs); + } + } +} + +void CSharpWriter::writeOperations(UMLOperationList opList, + QTextStream &cs, bool isInterface /* = false */, + bool isOverride /* = false */, + bool generateErrorStub /* = false */) { + + for (UMLOperation *op=opList.first(); op ; op=opList.next()) { + UMLAttributeList atl = op->getParmList(); + UMLAttribute *at; + + //write method doc if we have doc || if at least one of the params has doc + bool writeDoc = forceDoc() || !op->getDoc().isEmpty(); + + for (at = atl.first(); at; at = atl.next()) { + writeDoc |= !at->getDoc().isEmpty(); + } + + //write method documentation + if (writeDoc && !isOverride) + { + cs << m_container_indent << m_indentation << "/// <summary>" << m_endl; + cs << formatDoc(op->getDoc(), m_container_indent + m_indentation + "/// "); + cs << m_container_indent << m_indentation << "/// </summary>" << m_endl; + + //write parameter documentation + for (at = atl.first(); at; at = atl.next()) + { + if (forceDoc() || !at->getDoc().isEmpty()) { + cs << m_container_indent << m_indentation << "/// <param name=\"" << cleanName(at->getName()) << "\">"; + //removing newlines from parameter doc + cs << formatDoc(at->getDoc(), "").replace("\n", " ").remove('\r').replace(QRegExp(" $"), ""); + cs << "</param>" << m_endl; + } + } + + // FIXME: "returns" should contain documentation, not type. + cs << m_container_indent << m_indentation << "/// <returns>"; + if (! op->getTypeName().isEmpty()) { + cs << makeLocalTypeName(op); + } + cs << "</returns>" << m_endl; + + } + + // method visibility + cs << m_container_indent << m_indentation; + if (!isInterface) { + if (!isOverride) { + if (op->getAbstract()) cs << "abstract "; + cs << op->getVisibility().toString() << " "; + if (op->getStatic()) cs << "static "; + } + else { + // method overriding an abstract parent + cs << op->getVisibility().toString() << " override "; + if (op->getStatic()) cs << "static "; + } + } + + // return type (unless constructor, destructor) + if (!op->isLifeOperation()) { + if (op->getTypeName().isEmpty()) { + cs << "void "; + } + else { + cs << makeLocalTypeName(op) << " "; + } + } + + // method name + cs << cleanName(op->getName()) << "("; + + // method parameters + int i= atl.count(); + int j=0; + for (at = atl.first(); at; at = atl.next(), j++) { + + cs << makeLocalTypeName(at) << " " << cleanName(at->getName()); + + // no initial values in C# + //<< (!(at->getInitialValue().isEmpty()) ? + // (QString(" = ")+at->getInitialValue()) : + // QString("")) + cs << ((j < i-1)?", ":""); + } + cs << ")"; + + //FIXME: how to control generation of error stub? + if (!isInterface && (!op->getAbstract() || isOverride)) { + cs << m_endl << m_container_indent << m_indentation << "{" << m_endl; + if (generateErrorStub) { + cs << m_container_indent << m_indentation << m_indentation; + cs << "throw new Exception(\"The method or operation is not implemented.\");" << m_endl; + } + cs << m_container_indent << m_indentation << "}" << m_endl; + } + else { + cs << ';' << m_endl; + } + cs << m_endl; + } +} + +void CSharpWriter::writeAttributes(UMLClassifier *c, QTextStream &cs) { + + UMLAttributeList atpub, atprot, atpriv, atdefval; + atpub.setAutoDelete(false); + atprot.setAutoDelete(false); + atpriv.setAutoDelete(false); + atdefval.setAutoDelete(false); + + //sort attributes by scope and see if they have a default value + UMLAttributeList atl = c->getAttributeList(); + UMLAttribute *at; + + for (at = atl.first(); at ; at = atl.next()) { + if (!at->getInitialValue().isEmpty()) + atdefval.append(at); + switch (at->getVisibility()) { + case Uml::Visibility::Public: + atpub.append(at); + break; + case Uml::Visibility::Protected: + atprot.append(at); + break; + case Uml::Visibility::Private: + atpriv.append(at); + break; + default: + break; + } + } + + if (forceSections() || atl.count()) + cs << m_endl << m_container_indent << m_indentation << "#region Attributes" << m_endl << m_endl; + + // write public attributes + if (forceSections() || atpub.count()) { + writeAttributes(atpub,cs); + } + + // write protected attributes + if (forceSections() || atprot.count()) { + writeAttributes(atprot,cs); + } + + // write private attributes + if (forceSections() || atpriv.count()) { + writeAttributes(atpriv,cs); + } + + if (forceSections() || atl.count()) + cs << m_endl << m_container_indent << m_indentation << "#endregion" << m_endl << m_endl; + +} + + +void CSharpWriter::writeAttributes(UMLAttributeList &atList, QTextStream &cs) { + + for (UMLAttribute *at = atList.first(); at ; at = atList.next()) { + + bool asProperty = true; + if (at->getVisibility() == Uml::Visibility::Private) { + asProperty = false; + } + writeAttribute(at->getDoc(), at->getVisibility(), at->getStatic(), + makeLocalTypeName(at), at->getName(), at->getInitialValue(), asProperty, cs); + + cs << m_endl; + } // end for + return; +} + +void CSharpWriter::writeAssociatedAttributes(UMLAssociationList &associated, UMLClassifier *c, QTextStream &cs) { + + UMLAssociation *a; + for (a = associated.first(); a ; a = associated.next()) { + if (c != a->getObject(Uml::A)) // we need to be at the A side + continue; + + UMLObject *o = a->getObject(Uml::B); + if (o == NULL) { + kError() << "composition role B object is NULL" << endl; + continue; + } + // Take name and documentaton from Role, take type name from the referenced object + QString roleName = cleanName(a->getRoleName(Uml::B)); + QString typeName = cleanName(o->getName()); + if (roleName.isEmpty()) { + roleName = QString("UnnamedRoleB_%1").arg(m_unnamedRoles++); + } + QString roleDoc = a->getRoleDoc(Uml::B); + + //FIXME:is this simple condition enough? + if (a->getMulti(Uml::B).isEmpty() || a->getMulti(Uml::B) == "1") { + // normal attribute + writeAttribute(roleDoc, a->getVisibility(Uml::B), false, typeName, roleName, "", ( a->getVisibility(Uml::B) != Uml::Visibility::Private), cs); + } else { + // array + roleDoc += "\n(Array of " + typeName + ')'; + writeAttribute(roleDoc, a->getVisibility(Uml::B), false, "ArrayList", roleName, "", ( a->getVisibility(Uml::B) != Uml::Visibility::Private), cs); + } + } +} + +void CSharpWriter::writeAttribute(QString doc, Uml::Visibility visibility, bool isStatic, QString typeName, QString name, QString initialValue, bool asProperty, QTextStream &cs) { + + if (forceDoc() || !doc.isEmpty()) { + + cs << m_container_indent << m_indentation << "/// <summary>" << m_endl; + cs << formatDoc(doc, m_container_indent + m_indentation + "/// "); + cs << m_container_indent << m_indentation << "/// </summary>" << m_endl; + + } + cs << m_container_indent << m_indentation; + cs << visibility.toString() << " "; + if (isStatic) cs << "static "; + + //Variable type with/without namespace path + cs << typeName << " "; + + cs << cleanName(name); + + // FIXME: may need a GUI switch to not generate as Property? + + // Generate as Property if not private + if (asProperty) + { + cs << m_endl; + cs << m_container_indent << m_indentation << "{" << m_endl; + cs << m_container_indent << m_indentation << m_indentation << "get" << m_endl; + cs << m_container_indent << m_indentation << m_indentation << "{" << m_endl; + cs << m_container_indent << m_indentation << m_indentation << m_indentation << "return m_" << cleanName(name) << ";" << m_endl; + cs << m_container_indent << m_indentation << m_indentation << "}" << m_endl; + + cs << m_container_indent << m_indentation << m_indentation << "set" << m_endl; + cs << m_container_indent << m_indentation << m_indentation << "{" << m_endl; + cs << m_container_indent << m_indentation << m_indentation << m_indentation << "m_" << cleanName(name) << " = value;" << m_endl; + cs << m_container_indent << m_indentation << m_indentation << "}" << m_endl; + cs << m_container_indent << m_indentation << "}" << m_endl; + cs << m_container_indent << m_indentation << "private "; + if (isStatic) cs << "static "; + cs << typeName << " m_" << cleanName(name); + } + + if (!initialValue.isEmpty()) + cs << " = " << initialValue; + + cs << ";" << m_endl << m_endl; +} + +QString CSharpWriter::makeLocalTypeName(UMLClassifierListItem *cl) { + UMLPackage *p = cl->getType()->getUMLPackage(); + if (m_seenIncludes.findRef(p) != -1) { + return cl->getType()->getName(); + } + else { + return cl->getTypeName(); + } + +} + +/** + * returns "C#" + */ +Uml::Programming_Language CSharpWriter::getLanguage() { + return Uml::pl_CSharp; +} + +const QStringList CSharpWriter::reservedKeywords() const { + + static QStringList keywords; + + if (keywords.isEmpty()) { + for (int i = 0; reserved_words[i]; i++) + keywords.append(reserved_words[i]); + } + + return keywords; +} + +#include "csharpwriter.moc" + diff --git a/umbrello/umbrello/codegenerators/csharpwriter.h b/umbrello/umbrello/codegenerators/csharpwriter.h new file mode 100644 index 00000000..a6d20f2d --- /dev/null +++ b/umbrello/umbrello/codegenerators/csharpwriter.h @@ -0,0 +1,163 @@ +/*************************************************************************** + * * + * 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) 2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// +// C++ Interface: csharpwriter +// +// @author Ferenc Veres +// +#ifndef CSHARPWRITER_H +#define CSHARPWRITER_H + +#include "simplecodegenerator.h" +#include "../umlattributelist.h" +#include "../umloperationlist.h" +#include "../classifierlistitem.h" +#include "../umlassociationlist.h" + + +/** + * class CSharpWriter is a C# code generator for UMLClassifier objects + * Just call writeClass and feed it a UMLClassifier; + */ +class CSharpWriter : public SimpleCodeGenerator +{ + Q_OBJECT +public: + CSharpWriter(); + + virtual ~CSharpWriter(); + /** + * call this method to generate Php code for a UMLClassifier + * @param c the class you want to generate code for. + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "C#" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + + /** + * get list of predefined data types + */ + QStringList defaultDatatypes(); + +private: + + /** + * we do not want to write the comment "Private methods" twice + */ + bool bPrivateSectionCommentIsWritten; + + /** + * Adds extra indenting if the class is in a container (namespace) + */ + QString m_container_indent; + + /** + * Collection of included namespaces, to skip them from variable types. + */ + UMLPackageList m_seenIncludes; + + /** + * Counts associations without a role name for giving a default name. + */ + int m_unnamedRoles; + + /** + * write realizations of a class and recurse to parent classes + + * @param currentClass class to start with + * @param realizations realizations of this class + * @param cs output stream + */ + void writeRealizationsRecursive(UMLClassifier *currentClass, + UMLAssociationList *realizations, + QTextStream &cs); + + /** + * write all operations for a given class + * + * @param c the concept we are generating code for + * @param cs output stream + */ + void writeOperations(UMLClassifier *c, QTextStream &cs); + + /** + * write a list of class operations + * + * @param opList the list of operations + * @param cs output stream + * @param interface indicates if the operation is an interface member + * @param isOverride implementation of an inherited abstract function + */ + void writeOperations(UMLOperationList opList, + QTextStream &cs, + bool interface = false, + bool isOverride = false, + bool generateErrorStub = false); + + /** + * write superclasses' abstract methods + * + * @param superclasses List of superclasses to start recursing on + * @param cs output stream + */ + void writeOverridesRecursive(UMLClassifierList *superclasses, QTextStream &cs); + + /** write all the attributes of a class + * @param c the class we are generating code for + * @param cs output stream + */ + void writeAttributes(UMLClassifier *c, QTextStream &cs); + + /** write a list of class attributes + * @param atList the list of attributes + * @param cs output stream + */ + void writeAttributes(UMLAttributeList &atList, QTextStream &cs); + + /** + * write attributes from associated objects (compositions, aggregations) + * @param associated list of associated objects + * @param c currently written class, to see association direction + * @param cs output stream + */ + void writeAssociatedAttributes(UMLAssociationList &associated, UMLClassifier *c, QTextStream &cs); + + /** + * write a single attribute to the output stream + * @param doc attribute documentation + * @param visibility attribute visibility + * @param isStatic static attribute + * @param typeName class/type of the attribute + * @param name name of the attribute + * @param initialValue initial value given to the attribute at declaration + * @param asProperty true writes as property (get/set), false writes single line variable + * @param cs output stream + */ + void writeAttribute(QString doc, Uml::Visibility visibility, bool isStatic, QString typeName, QString name, QString initialValue, bool asProperty, QTextStream &cs); + + /** find the type in used namespaces, if namespace found return short name, complete otherwise. + * + * @param at Operation or Attribute to check type + */ + QString makeLocalTypeName(UMLClassifierListItem *cl); + +}; + +#endif diff --git a/umbrello/umbrello/codegenerators/dwriter.cpp b/umbrello/umbrello/codegenerators/dwriter.cpp new file mode 100644 index 00000000..3e16b136 --- /dev/null +++ b/umbrello/umbrello/codegenerators/dwriter.cpp @@ -0,0 +1,970 @@ + +/*************************************************************************** + * * + * 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) 2007 Jari-Matti Mäkelä <jmjm@iki.fi> * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/*************************************************************************** + 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. + ***************************************************************************/ + +// own header +#include "dwriter.h" +// qt includes +#include <qfile.h> +#include <qtextstream.h> +#include <qregexp.h> +// kde includes +#include <kdebug.h> +// app includes +#include "../umldoc.h" +#include "../classifier.h" +#include "../operation.h" +#include "../attribute.h" +#include "../association.h" +#include "../template.h" +#include "../umltemplatelist.h" +#include "codegen_utils.h" + +DWriter::DWriter() { + startline = m_endl + m_indentation; +} + +DWriter::~DWriter() {} + +Uml::Programming_Language DWriter::getLanguage() { + return Uml::pl_D; +} + +// FIXME: doesn't work yet +void DWriter::writeModuleDecl(UMLClassifier *c, QTextStream &d) { + if(!c->getPackage().isEmpty()) + d << "module " << c->getPackage() << ";" << m_endl; + + writeBlankLine(d); +} + +void DWriter::writeModuleImports(UMLClassifier *c, QTextStream &d) { + // 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() + associations.count() + + compositions.count() + uniAssociations.count() > 0; + + if (hasAssociations) { + // import tango, if that mode is set + writeBlankLine(d); + } + + //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()) + d << "import " << pkg << "." << cleanName(con->getName()) << ";" + << m_endl; + } + + writeBlankLine(d); +} + +void DWriter::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, ".d"); + 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; + } + + // open text stream to file + QTextStream d(&file); + + //try to find a heading file (license, coments, etc) + QString str; + str = getHeadingFile(".d"); + if(!str.isEmpty()) { + str.replace(QRegExp("%filename%"),fileName); + str.replace(QRegExp("%filepath%"),file.name()); + d<<str<<m_endl; + } + + // source file begins with the module declaration + writeModuleDecl(c, d); + + // imports + writeModuleImports(c, d); + + // write the opening declaration for the class incl any documentation, + // interfaces and/or inheritence issues we have + writeClassDecl(c, d); + + // start body of class + d << " {" << m_endl; + + + // Preparations + // + + // sort attributes by Scope + UMLAttributeList atl; + UMLAttributeList atpub, atprot, atpriv, atpkg, atexport; + UMLAttributeList final_atpub, final_atprot, final_atpriv, final_atpkg, final_atexport; + + atpub.setAutoDelete(false); + final_atpub.setAutoDelete(false); + atprot.setAutoDelete(false); + final_atprot.setAutoDelete(false); + atpriv.setAutoDelete(false); + final_atpriv.setAutoDelete(false); + atpkg.setAutoDelete(false); + final_atpkg.setAutoDelete(false); + atexport.setAutoDelete(false); + final_atexport.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;/* TODO: requires support from the gui & other structures + case Uml::Visibility::Package: + if(at->getStatic()) + final_atpkg.append(at); + else + atpkg.append(at); + break; + case Uml::Visibility::Export: + if(at->getStatic()) + final_atexport.append(at); + else + atexport.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() + associations.count() + compositions.count() + uniAssociations.count() > 0; + bool hasAttributes = atl.count() > 0; + bool hasAccessorMethods = hasAttributes || hasAssociations; + bool hasOperationMethods = c->getOpList().count() > 0; + + // ATTRIBUTES + // + + // write comment for section IF needed + if (forceDoc() || hasAccessorMethods) + { + writeComment("", m_indentation, d); + writeComment("Fields", m_indentation, d); + writeComment("", m_indentation, d); + writeBlankLine(d); + } + + writeAttributeDecls(final_atpub, final_atprot, final_atpriv, d); + writeAttributeDecls(atpub, atprot, atpriv, d); + + writeAssociationDecls(associations, c->getID(), d); + writeAssociationDecls(uniAssociations, c->getID(), d); + writeAssociationDecls(aggregations, c->getID(), d); + writeAssociationDecls(compositions, c->getID(), d); + + //FIXME: find constructors and write them here + + // write constructors + if(!isInterface) writeConstructor(c, d); + + + // METHODS + // + + // write comment for sub-section IF needed + if (forceDoc() || hasAccessorMethods ) { + writeComment("", m_indentation, d); + writeComment("Accessors", m_indentation, d); + writeComment("", m_indentation, d); + writeBlankLine(d); + } + + + // Accessors for attributes + writeAttributeMethods(final_atpub, Uml::Visibility::Public, d); + writeAttributeMethods(final_atprot, Uml::Visibility::Protected, d); + writeAttributeMethods(final_atpriv, Uml::Visibility::Private, d); + writeAttributeMethods(atpub, Uml::Visibility::Public, d); + writeAttributeMethods(atprot, Uml::Visibility::Protected, d); + writeAttributeMethods(atpriv, Uml::Visibility::Private, d); + + // accessor methods for associations + + // first: determine the name of the other class + writeAssociationMethods(associations, c, d); + writeAssociationMethods(uniAssociations, c, d); + writeAssociationMethods(aggregations, c, d); + writeAssociationMethods(compositions, c, d); + + // Other operation methods + // all other operations are now written + + // write comment for sub-section IF needed + if (forceDoc() || hasOperationMethods) { + writeComment("", m_indentation, d); + writeComment("Other methods", m_indentation, d); + writeComment("", m_indentation, d); + writeBlankLine(d); + } + + writeOperations(c, d); + + d << "}" << m_endl; // end class + + file.close(); + emit codeGenerated(c, true); +} + +void DWriter::writeClassDecl(UMLClassifier *c, QTextStream &d) { + + // class documentation + if (!c->getDoc().isEmpty()) { + writeDocumentation("", c->getDoc(), "", "", d); + } + + /* + * Class declaration + * + * (private) class foo(T, ..., Z) : class1, ..., classN, interface1, ..., interfaceN + * a b c d e f g + */ + + // (a) visibility modifier + switch(c->getVisibility()) { + case Uml::Visibility::Private: d << "private "; break; + default: break; + } + + // (b) keyword + // TODO what about structs? + if (isInterface) { + d << "interface "; + } else { + if (c->getAbstract()) { + d << "abstract "; + } + + d << "class "; + } + + // (c) class name + QString classname = cleanName(c->getName()); // our class name + d << classname; + + // (d) template parameters + UMLTemplateList template_params = c->getTemplateList(); + if (template_params.count()) { + d << "("; + + for (UMLTemplate *t = template_params.first(); t; ) { + // TODO: hm, leaving the type blank results in "class" + // so we omit it (also because "class" in this context is illegal) + if (t->getTypeName() != "class") { + d << t->getTypeName(); + d << " "; + } + + d << t->getName(); + + if ((t = template_params.next()) != NULL) + d << ", "; + } + + d << ")"; + } + + // (e) inheritances + UMLClassifierList superclasses = + c->findSuperClassConcepts(UMLClassifier::CLASS); + UMLClassifierList superinterfaces = + c->findSuperClassConcepts(UMLClassifier::INTERFACE); + + int count = superclasses.count() + superinterfaces.count(); + + if (count > 0) { + d << " : "; + + // (f) base classes + for (UMLClassifier * concept= superclasses.first(); concept; concept = superclasses.next()) { + d << cleanName(concept->getName()); + + count--; + + if (count>0) d << ", "; + } + + // (g) interfaces + for (UMLClassifier * concept= superinterfaces.first(); concept; concept = superinterfaces.next()) { + d << cleanName(concept->getName()); + + count--; + + if (count>0) d << ", "; + } + } +} + +void DWriter::writeProtectionMod(Uml::Visibility visibility, QTextStream &d) { + d << m_indentation << scopeToDDecl(visibility) << ":" << m_endl << m_endl; +} + +void DWriter::writeAttributeDecl(Uml::Visibility visibility, UMLAttributeList &atlist, QTextStream &d) { + if (atlist.count()==0) return; + + writeProtectionMod(visibility, d); + + for(UMLAttribute *at=atlist.first(); at; at=atlist.next()) { + // documentation + if (!at->getDoc().isEmpty()) { + writeComment(at->getDoc(), m_indentation, d, true); + } + + d << m_indentation; + + // static attribute? + if (at->getStatic()) d << "static "; + + // method return type + d << fixTypeName(at->getTypeName()) << " "; + + // TODO: find out whether this class has accessors or not + bool hasAccessorMethods = true; + + // attribute name + if (hasAccessorMethods) { + d << "m_"; + } + d << cleanName(at->getName()); + + // initial value + QString initVal = fixInitialStringDeclValue(at->getInitialValue(), at->getTypeName()); + if (!initVal.isEmpty()) d << " = " << initVal; + d << ";" << m_endl << m_endl; + } +} + +void DWriter::writeAttributeDecls(UMLAttributeList &atpub, UMLAttributeList &atprot, + UMLAttributeList &atpriv, QTextStream &d ) { + + writeAttributeDecl(Uml::Visibility::Public, atpub, d); + writeAttributeDecl(Uml::Visibility::Protected, atprot, d); + writeAttributeDecl(Uml::Visibility::Private, atpriv, d); + //TODO: export and package +} + +void DWriter::writeAttributeMethods(UMLAttributeList &atpub, Uml::Visibility visibility, QTextStream &d) { + if (atpub.count()==0) return; + + writeProtectionMod(visibility, d); + + for(UMLAttribute *at=atpub.first(); at; at=atpub.next()) { + QString fieldName = cleanName(at->getName()); + writeSingleAttributeAccessorMethods( + at->getTypeName(), "m_" + fieldName, fieldName, at->getDoc(), + visibility, Uml::chg_Changeable, at->getStatic(), d); + } +} + +void DWriter::writeComment(const QString &comment, const QString &myIndent, + QTextStream &d, bool dDocStyle) { + if(dDocStyle) { + d << myIndent << "/**" << m_endl; + } + + QStringList lines = QStringList::split("\n", comment); + + if (lines.count() == 0) lines << comment; + + for (uint i = 0; i < lines.count(); ++i) { + QString tmp = lines[i]; + + while (tmp.length() > 77) { + uint l = tmp.left(77).findRev(' '); + if (l < 1) l = tmp.find(' ', 77); + if (l < 1 || l > tmp.length()) { + d << myIndent << (dDocStyle ? " * " : "// ") << tmp << m_endl; + break; + } + d << myIndent << (dDocStyle ? " * " : "// ") << tmp.left(l) << m_endl; + tmp = tmp.right(tmp.length() - l); + } + + d << myIndent << (dDocStyle ? " * " : "// ") << tmp << m_endl; + } + + if(dDocStyle) { + d << myIndent << " */" << m_endl; + } +} + +void DWriter::writeDocumentation(QString header, QString body, QString end, QString indent, QTextStream &d) { + d << indent << "/**" << m_endl; + if (!header.isEmpty()) + d << formatDoc(header, indent+" * "); + if (!body.isEmpty()) + d << formatDoc(body, indent+" * "); + if (!end.isEmpty()) + { + QStringList lines = QStringList::split( "\n", end); + for (uint i= 0; i < lines.count(); i++) + d << formatDoc(lines[i], indent + " * "); + } + d<<indent<< " */" << m_endl; +} + +void DWriter::writeAssociationDecls(UMLAssociationList associations, Uml::IDType id, QTextStream &d) { + + 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, d); + + // 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), d); + } + + // 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), d); + } + } + } +} + +void DWriter::writeAssociationRoleDecl(QString fieldClassName, + QString roleName, QString multi, + QString doc, Uml::Visibility /*visib*/, QTextStream &d) { + // ONLY write out IF there is a rolename given + // otherwise its not meant to be declared in the code + if (roleName.isEmpty()) return; + + if (!doc.isEmpty()) { + writeComment(doc, m_indentation, d); + } + + bool hasAccessors = true; + + // 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]$"))) { + d << m_indentation << fieldClassName << " "; + + if (hasAccessors) d << "m_"; + + d << deCapitaliseFirstLetter(roleName) << ";"; + } else { + d << m_indentation << fieldClassName << "[] "; + //TODO: templated containers + + if (hasAccessors) d << "m_"; + + d << pluralize(deCapitaliseFirstLetter(roleName)) << ";"; + // from here we could initialize default values, or put in an init() section + // of the constructors + } + + // always put space between this and following decl, if any + writeBlankLine(d); +} + +void DWriter::writeAssociationMethods (UMLAssociationList associations, UMLClassifier *thisClass, QTextStream &d) { + 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), d); + } + } + + 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), + d); + } + } + } + } +} + +void DWriter::writeAssociationRoleMethod (QString fieldClassName, QString roleName, QString multi, + QString description, Uml::Visibility visib, Uml::Changeability_Type change, + QTextStream &d) { + if(multi.isEmpty() || multi.contains(QRegExp("^[01]$"))) { + QString fieldVarName = "m_" + deCapitaliseFirstLetter(roleName); + + writeSingleAttributeAccessorMethods( + fieldClassName, fieldVarName, roleName, description, visib, change, false, d); + } else { + QString fieldVarName = "m_" + pluralize(deCapitaliseFirstLetter(roleName)); + + writeVectorAttributeAccessorMethods( + fieldClassName, fieldVarName, pluralize(roleName), description, visib, change, d); + } +} + +void DWriter::writeVectorAttributeAccessorMethods (QString fieldClassName, QString fieldVarName, + QString fieldName, QString description, + Uml::Visibility /*visibility*/, Uml::Changeability_Type changeType, + QTextStream &d) { + + fieldClassName = fixTypeName(fieldClassName); + QString fieldNameUP = unPluralize(fieldName); + QString fieldNameUC = Codegen_Utils::capitalizeFirstLetter(fieldNameUP); + + // ONLY IF changeability is NOT Frozen + if (changeType != Uml::chg_Frozen) { + writeDocumentation("Adds a " + fieldNameUP + " to the list of " + + fieldName + '.', description, "", m_indentation, d); + + d << m_indentation << "void add" << fieldNameUC << "("; + d << fieldClassName << " new" << fieldNameUC << ") {"; + d << startline << m_indentation << fieldVarName << " ~= new" << fieldNameUC << ";"; + d << startline << "}" << m_endl << m_endl; + } + + // ONLY IF changeability is Changeable + if (changeType == Uml::chg_Changeable) { + writeDocumentation("Removes a " + fieldNameUP + " from the list of " + + fieldName + '.', description, "", m_indentation, d); + + d << m_indentation << "void remove" << fieldNameUC << "("; + d << fieldClassName << " " << fieldNameUP << ") {" << startline; + d << m_indentation << "int idx = " << fieldVarName << ".length;" << startline; + d << m_indentation << "foreach(i, o; " << fieldVarName << ")" << startline; + d << m_indentation << m_indentation << "if (o && o == " << fieldNameUP << ") {" << startline; + d << m_indentation << m_indentation << m_indentation << "idx = i;" << startline; + d << m_indentation << m_indentation << m_indentation << "break;" << startline; + d << m_indentation << m_indentation << "}" << m_endl << startline; + d << m_indentation << fieldVarName << " = " << fieldVarName; + d << "[0..idx] ~ " << fieldVarName << "[idx..$];" << startline; + d << "}" << m_endl << m_endl; + } + + // always allow getting the list of stuff + writeDocumentation("Returns the list of " + fieldName + '.', + description, "@return List of " + fieldName + '.', + m_indentation, d); + + d << m_indentation << fieldClassName << "[] get" << fieldName << "() {"; + d << startline << m_indentation << "return " << fieldVarName << ";"; + d << startline << "}" << m_endl << m_endl; +} + + +void DWriter::writeSingleAttributeAccessorMethods(QString fieldClassName, + QString fieldVarName, QString fieldName, QString description, Uml::Visibility /*visibility*/, + Uml::Changeability_Type change, bool isFinal, QTextStream &d) { + + fieldClassName = fixTypeName(fieldClassName); + QString fieldNameUC = Codegen_Utils::capitalizeFirstLetter(fieldName); + if (fieldName.left(2) == "m_") fieldName = fieldName.right(fieldName.length()-2); + + // set method + if (change == Uml::chg_Changeable && !isFinal) { + writeDocumentation("Sets the value of " + fieldName + '.', description, + "@param new" + fieldNameUC + " The new value of " + fieldName + '.', + m_indentation, d); + + d << m_indentation << fieldClassName << " " << fieldName << "("; + d << fieldClassName << " new" << fieldNameUC << ") {"; + d << startline << m_indentation << "return " << fieldVarName << " = new" << fieldNameUC << ";"; + d << startline << "}" << m_endl << m_endl; + } + + // get method + writeDocumentation("Returns the value of " + fieldName + '.', description, + "@return The value of " + fieldName + '.', + m_indentation, d); + + d << m_indentation << fieldClassName << " " << fieldName << "() {"; + d << startline << m_indentation << "return " << fieldVarName << ";"; + d << startline << "}" << m_endl << m_endl; +} + +void DWriter::writeConstructor(UMLClassifier *c, QTextStream &d) { + + if (forceDoc()) + { + d<<startline; + writeComment("", m_indentation, d); + writeComment("Constructors", m_indentation, d); + writeComment("", m_indentation, d); + writeBlankLine(d); + } + + // write the first constructor + QString className = cleanName(c->getName()); + d << m_indentation << "public this("<<") { }"; + +} + +// IF the type is "string" we need to declare it as +// the D Object "String" (there is no string primative in D). +// Same thing again for "bool" to "boolean" +QString DWriter::fixTypeName(const QString& string) { + if (string.isEmpty()) + return "void"; + if (string == "string") + return "char[]"; + if (string == "unsigned short") + return "ushort"; + if (string == "unsigned int") + return "uint"; + if (string == "unsigned long") + return "ulong"; + return string; +} + +QStringList DWriter::defaultDatatypes() { + QStringList l; + l << "void" + << "bool" + << "byte" + << "ubyte" + << "short" + << "ushort" + << "int" + << "uint" + << "long" + << "ulong" + << "cent" + << "ucent" + << "float" + << "double" + << "real" + << "ifloat" + << "idouble" + << "ireal" + << "cfloat" + << "cdouble" + << "creal" + << "char" + << "wchar" + << "dchar"; + return l; +} + + +bool DWriter::compareDMethod(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 DWriter::dMethodInList(UMLOperation *umlOp, UMLOperationList &opl) { + for (UMLOperation *op = opl.first(); op; op = opl.next()) { + if (DWriter::compareDMethod(op, umlOp)) { + return true; + } + } + return false; +} + +void DWriter::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 (!DWriter::dMethodInList(op,toBeImplementedOpList)) + toBeImplementedOpList.append(op); + } + else + { + if (!DWriter::dMethodInList(op, yetImplementedOpList)) + yetImplementedOpList.append(op); + } + } + } + +} + +void DWriter::getInterfacesOperationsToBeImplemented(UMLClassifier *c, UMLOperationList &opList ) { + UMLOperationList yetImplementedOpList; + UMLOperationList toBeImplementedOpList; + + getSuperImplementedOperations(c,yetImplementedOpList, toBeImplementedOpList); + for (UMLOperation *op = toBeImplementedOpList.first(); op; op = toBeImplementedOpList.next()) + { + if ( ! DWriter::dMethodInList(op, yetImplementedOpList) && ! DWriter::dMethodInList(op, opList) ) + opList.append(op); + } +} + +void DWriter::writeOperations(UMLClassifier *c, QTextStream &d) { + 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: //TODO: package, export + break; + } + } + + // do people REALLY want these comments? Hmm. + /* + if(forceSections() || oppub.count()) + { + writeComment("public operations",m_indentation,d); + writeBlankLine(d); + } + */ + + if (oppub.count() > 0) { + writeProtectionMod(Uml::Visibility::Public, d); + + writeOperations(oppub,d); + } + + if (opprot.count() > 0) { + writeProtectionMod(Uml::Visibility::Protected, d); + + writeOperations(opprot, d); + } + + if (oppriv.count() > 0) { + writeProtectionMod(Uml::Visibility::Private, d); + + writeOperations(oppriv, d); + } + +} + +void DWriter::writeOperations(UMLOperationList &oplist, QTextStream &d) { + UMLAttributeList atl; + QString str; + + // generate method decl for each operation given + for(UMLOperation *op=oplist.first(); op; op=oplist.next()) { + QString returnStr = ""; + // write documentation + + QString methodReturnType = fixTypeName(op->getTypeName()); + + //TODO: return type comment + if(methodReturnType != "void") { + returnStr += "@return " + methodReturnType + m_endl; + } + + str = ""; // reset for next method + if (op->getAbstract() && !isInterface) str += "abstract "; + if (op->getStatic()) str += "static "; + + str += methodReturnType + ' ' +cleanName(op->getName()) + '('; + + atl = op->getParmList(); + int i = atl.count(); + int j = 0; + for (UMLAttribute *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() + m_endl; + } + + str+= ')'; + + // method only gets a body IF its not abstract + if (op->getAbstract() || isInterface) + str += ';'; // terminate now + else + str += startline + '{' + startline + '}'; // empty method body + + // write it out + writeDocumentation("", op->getDoc(), returnStr, m_indentation, d); + d << m_indentation << str << m_endl << m_endl; + } +} + +QString DWriter::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 DWriter::scopeToDDecl(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: scopeString = "private"; break; + default: break; //TODO: package and export + } + + return scopeString; +} + +// methods like this _shouldn't_ be needed IF we properly did things thruought the code. +QString DWriter::getUMLObjectName(UMLObject *obj) { + return(obj!=0)?obj->getName():QString("NULL"); +} + +QString DWriter::deCapitaliseFirstLetter(QString string) { + string.replace( 0, 1, string[0].lower()); + return string; +} + +QString DWriter::pluralize(QString string) { + return string + (string.right(1) == "s" ? "es" : "s"); +} + +QString DWriter::unPluralize(QString string) { + // does not handle special cases liek datum -> data, etc. + + if (string.length() > 2 && string.right(3) == "ses") { + return string.left(string.length() - 2); + } + + if (string.right(1) == "s") { + return string.left(string.length() - 1); + } + + return string; +} + +void DWriter::writeBlankLine(QTextStream &d) { + d << m_endl; +} + diff --git a/umbrello/umbrello/codegenerators/dwriter.h b/umbrello/umbrello/codegenerators/dwriter.h new file mode 100644 index 00000000..38828359 --- /dev/null +++ b/umbrello/umbrello/codegenerators/dwriter.h @@ -0,0 +1,276 @@ + +/*************************************************************************** + * * + * 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) 2007 Jari-Matti Mäkelä <jmjm@iki.fi> * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/*************************************************************************** + 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. + ***************************************************************************/ + +#ifndef DWRITER_H +#define DWRITER_H + +#include "simplecodegenerator.h" +#include "../umloperationlist.h" +#include "../umlattributelist.h" +#include "../umlassociationlist.h" + +class UMLOperation; + +/** + * class DWriter is a code generator for UMLClassifier objects. + * Create an instance of this class, and feed it a UMLClassifier when + * calling writeClass and it will generate a d source file for + * that concept + */ +class DWriter : public SimpleCodeGenerator { +public: + + /** + * Constructor, initialises a couple of variables + */ + DWriter(); + + /** + * Destructor, empty + */ + virtual ~DWriter(); + + /** + * call this method to generate d code for a UMLClassifier + * @param c the class to generate code for + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "D" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * Overrides method from class CodeGenerator + */ + QStringList defaultDatatypes(); + +private: + + /** + * Writes the module declaration. + */ + void writeModuleDecl(UMLClassifier *c, QTextStream &d); + + /** + * Writes the module imports. + */ + void writeModuleImports(UMLClassifier *c, QTextStream &d); + + /** + * Writes class's documentation then the class header + * public abstract class Foo extents { + */ + void writeClassDecl(UMLClassifier *c, QTextStream &d); + + /** + * Writes the comment and class constructor + */ + void writeConstructor(UMLClassifier *c, QTextStream &d); + + /** + * return true if the two operations have the same name and the same parameters + * @param op1 first operation to be compared + * @param op2 second operation to be compared + */ + static bool compareDMethod(UMLOperation *op1, UMLOperation *op2); + + /** + * return true if the operation is in the list + * @param umlOp operation to be searched + * @param opl list of operations + */ + static bool dMethodInList(UMLOperation *umlOp, UMLOperationList &opl); + + /** + * get all operations which a given class inherit from all its super interfaces and get all operations + * which this given class inherit from all its super classes + * @param c the class for which we are generating code + * @param yetImplementedOpList the list of yet implemented operations + * @param toBeImplementedOpList the list of to be implemented operations + * @param noClassInPath tells if there is a class between the base class and the current interface + */ + void getSuperImplementedOperations(UMLClassifier *c, UMLOperationList &yetImplementedOpList ,UMLOperationList &toBeImplementedOpList, bool noClassInPath = true); + + /** + * get all operations which a given class inherit from all its super interfaces and that should be implemented + * @param c the class for which we are generating code + * @param opl the list of operations used to append the operations + */ + void getInterfacesOperationsToBeImplemented(UMLClassifier *c, UMLOperationList &opl); + + /** + * write all operations for a given class + * @param c the class for which we are generating code + * @param j the stream associated with the output file + */ + void writeOperations(UMLClassifier *c, QTextStream &j); + + /** + * write a list of operations for a given class + * @param list the list of operations you want to write + * @param j the stream associated with the output file + */ + void writeOperations(UMLOperationList &list, QTextStream &j); + + /** + * write all attributes for a given class + * @param c the class for which we are generating code + * @param j the stream associated with the output file + */ + void writeAttributes(UMLClassifier *c, QTextStream &j); + + /** + * Writes the protection modifier line. + * @param visibility protection modifier + * @param d text stream + */ + void writeProtectionMod(Uml::Visibility visibility, QTextStream &d); + + /** + * Writes attribute declarations with a specific + * protection modifier. + * @param prot the protection modifier + * @param atlist attribute list + * @param d text stream + */ + void writeAttributeDecl(Uml::Visibility visibility, UMLAttributeList &atlist, QTextStream &d); + + /** + * writes the Attribute declarations + * @param atpub List of public attributes + * @param atprot list of protected attributes + * @param atpriv list of private attributes + * @param d text stream + */ + void writeAttributeDecls(UMLAttributeList &atpub, UMLAttributeList &atprot, + UMLAttributeList &atpriv, QTextStream &d ); + + /** + * Searches a list of associations for appropriate ones to write out as attributes + */ + void writeAssociationDecls(UMLAssociationList associations, Uml::IDType id, QTextStream &d); + + /** + * Writes out an association as an attribute using Vector + */ + void writeAssociationRoleDecl(QString fieldClassName, QString roleName, QString multi, + QString doc, Uml::Visibility visib, QTextStream &d); + + /** + * calls @ref writeSingleAttributeAccessorMethods() on each of the attributes in atpub + */ + void writeAttributeMethods(UMLAttributeList &atpub, Uml::Visibility visibility, QTextStream &d); + + /** + * calls @ref writeAssociationRoleMethod() on each of the associations in the given list + */ + void writeAssociationMethods(UMLAssociationList associations, UMLClassifier *thisClass, + QTextStream &d); + + /** + * calls @ref writeSingleAttributeAccessorMethods() or @ref + * writeVectorAttributeAccessorMethods() on the assocaition + * role + */ + void writeAssociationRoleMethod(QString fieldClassName, QString roleName, QString multi, + QString description, Uml::Visibility visib, Uml::Changeability_Type change, + QTextStream &d); + + /** + * Writes getFoo() and setFoo() accessor methods for the attribute + */ + void writeSingleAttributeAccessorMethods(QString fieldClassName, QString fieldVarName, + QString fieldName, QString description, + Uml::Visibility visibility, Uml::Changeability_Type change, + bool isFinal, QTextStream &d); + + /** + * Writes addFoo() and removeFoo() accessor methods for the Vector attribute + */ + void writeVectorAttributeAccessorMethods(QString fieldClassName, QString fieldVarName, + QString fieldName, QString description, + Uml::Visibility visibility, Uml::Changeability_Type change, + QTextStream &d); + + /** + * Writes a // style comment + */ + void writeComment(const QString &text, const QString &indent, QTextStream &d, bool dDocStyle=false); + + /** + * Writes a documentation comment + */ + void writeDocumentation(QString header, QString body, QString end, QString indent, QTextStream &d); + + /** + * Returns the name of the given object (if it exists) + */ + QString getUMLObjectName(UMLObject *obj); + + /** + * Lowers the case of the first letter in the given string + */ + QString deCapitaliseFirstLetter(QString string); + + /** + * Returns the plural form of a subject. + */ + QString pluralize(QString string); + + /** + * Returns the non-plural form of a subject. + */ + QString unPluralize(QString string); + + /** + * Replaces `string' with `String' and `bool' with `boolean' + */ + QString fixTypeName(const QString& string); + + /** + * check that initial values of strings have quotes around them + */ + QString fixInitialStringDeclValue(QString value, QString type); + + /** + * Write a blank line + */ + void writeBlankLine(QTextStream& d); + + /** + * a little method for converting scope to string value + */ + QString scopeToDDecl(Uml::Visibility scope); + + /** + * A \n, used at the end of each line + */ + QString startline; + + /** + * Whether or not this concept is an interface. + */ + bool isInterface; + +}; + + +#endif // DWRITER_H + diff --git a/umbrello/umbrello/codegenerators/idlwriter.cpp b/umbrello/umbrello/codegenerators/idlwriter.cpp new file mode 100644 index 00000000..a893acc3 --- /dev/null +++ b/umbrello/umbrello/codegenerators/idlwriter.cpp @@ -0,0 +1,482 @@ +/*************************************************************************** + * copyright (C) 2003-2005 * + * 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. * + * * + ***************************************************************************/ + +#include "idlwriter.h" + +#include <kdebug.h> +#include <kmessagebox.h> +#include <qfile.h> +#include <qregexp.h> +#include <qtextstream.h> + +#include "../umldoc.h" +#include "../classifier.h" +#include "../enum.h" +#include "../classifierlistitem.h" +#include "../umlclassifierlistitemlist.h" +#include "../package.h" +#include "../association.h" +#include "../attribute.h" +#include "../operation.h" +#include "../umlnamespace.h" + +IDLWriter::IDLWriter() : SimpleCodeGenerator(false) { +} + +IDLWriter::~IDLWriter() {} + +bool IDLWriter::isOOClass(UMLClassifier *c) { + QString stype = c->getStereotype(); + if (stype == "CORBAConstant" || stype == "CORBAEnum" || + stype == "CORBAStruct" || stype == "CORBAUnion" || + stype == "CORBASequence" || stype == "CORBAArray" || + stype == "CORBATypedef") + return false; + + // CORBAValue, CORBAInterface, and all empty/unknown stereotypes are + // assumed to be OO classes. + return true; +} + +bool IDLWriter::assocTypeIsMappableToAttribute(Uml::Association_Type at) { + return (at == Uml::at_Aggregation || at == Uml::at_Association || + at == Uml::at_Composition || at == Uml::at_UniAssociation); +} + +/** + * returns "IDL" + */ +Uml::Programming_Language IDLWriter::getLanguage() { + return Uml::pl_IDL; +} + +void IDLWriter::computeAssocTypeAndRole +(UMLAssociation *a, UMLClassifier *c, QString& typeName, QString& roleName) +{ + // Determine which is the "remote" end of the association: + bool IAmRoleA = true; + UMLObject *other = a->getObject(Uml::B); + Uml::Association_Type at = a->getAssocType(); + if (c->getName() == other->getName()) { + if (at == Uml::at_Aggregation || at == Uml::at_Composition || + at == Uml::at_UniAssociation) { + // Assuming unidirectional association, and we are + // at the "wrong" side. + // Returning roleName = QString::null tells caller to + // skip this association at this side. + roleName = QString(); + return; + } + IAmRoleA = false; + other = a->getObject(Uml::A); + } + // Construct the type name: + typeName = cleanName(other->getName()); + QString multiplicity; + if (IAmRoleA) + multiplicity = a->getMulti(Uml::B); + else + multiplicity = a->getMulti(Uml::A); + if (!multiplicity.isEmpty() && multiplicity != "1") + typeName.append("Vector"); + // Construct the member name: + if (IAmRoleA) + roleName = a->getRoleName(Uml::B); + else + roleName = a->getRoleName(Uml::A); + if (roleName.isEmpty()) { + roleName = a->getName(); + if (roleName.isEmpty()) { + roleName = "m_" + typeName; + } + } +} + +void IDLWriter::writeClass(UMLClassifier *c) { + if (!c) { + kDebug() << "Cannot write class of NULL concept!" << endl; + return; + } + + const bool isClass = !c->isInterface(); + QString classname = cleanName(c->getName()); + + //find an appropriate name for our file + QString fileName = findFileName(c, ".idl"); + if (fileName.isEmpty()) { + emit codeGenerated(c, false); + return; + } + + QFile file; + if (!openFile(file, fileName)) { + emit codeGenerated(c, false); + return; + } + + // Start generating the code. + + QTextStream idl(&file); + //try to find a heading file(license, comments, etc) + QString str; + str = getHeadingFile(".idl"); + if (!str.isEmpty()) { + str.replace(QRegExp("%filename%"), fileName); + str.replace(QRegExp("%filepath%"), file.name()); + idl << str << m_endl; + } + + // Write includes. + UMLPackageList includes; + findObjectsRelated(c, includes); + if (includes.count()) { + for (UMLPackage *conc = includes.first(); conc; conc = includes.next()) { + if (conc->getBaseType() == Uml::ot_Datatype) + continue; + QString incName = findFileName(conc, ".idl"); + if (!incName.isEmpty()) + idl << "#include \"" << incName << "\"" << m_endl; + } + idl << m_endl; + } + + // Generate the module declaration(s) for the package(s) in which + // we are embedded. + UMLPackageList pkgList = c->getPackages(); + UMLPackage *pkg; + for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) { + idl << getIndent() << "module " << pkg->getName() << " {" << m_endl << m_endl; + m_indentLevel++; + } + + // Write class Documentation if non-empty or if force option set. + if (forceDoc() || !c->getDoc().isEmpty()) { + idl << "//" << m_endl; + idl << "// class " << classname << m_endl; + idl << formatDoc(c->getDoc(), "// "); + idl << m_endl; + } + + if (c->getBaseType() == Uml::ot_Enum) { + UMLClassifierListItemList litList = c->getFilteredList(Uml::ot_EnumLiteral); + uint i = 0; + idl << getIndent() << "enum " << classname << " {" << m_endl; + m_indentLevel++; + for (UMLClassifierListItem *lit = litList.first(); lit; lit = litList.next()) { + QString enumLiteral = cleanName(lit->getName()); + idl << getIndent() << enumLiteral; + if (++i < litList.count()) + idl << ","; + idl << m_endl; + } + m_indentLevel--; + idl << getIndent() << "};" << m_endl << m_endl; + // Close the modules inside which we might be nested. + for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) { + m_indentLevel--; + idl << getIndent() << "};" << m_endl << m_endl; + } + return; + } + if (! isOOClass(c)) { + QString stype = c->getStereotype(); + if (stype == "CORBAConstant") { + kError() << "The stereotype " << stype << " cannot be applied to " + << c->getName() << ", but only to attributes." << endl; + return; + } + if (!isClass) { + kError() << "The stereotype " << stype + << " cannot be applied to " << c->getName() + << ", but only to classes." << endl; + return; + } + if (stype == "CORBAEnum") { + UMLAttributeList atl = c->getAttributeList(); + UMLAttribute *at; + idl << getIndent() << "enum " << classname << " {" << m_endl; + m_indentLevel++; + uint i = 0; + for (at = atl.first(); at; at = atl.next()) { + QString enumLiteral = cleanName(at->getName()); + idl << getIndent() << enumLiteral; + if (++i < atl.count()) + idl << ","; + idl << m_endl; + } + m_indentLevel--; + idl << getIndent() << "};" << m_endl << m_endl; + } else if (stype == "CORBAStruct") { + UMLAttributeList atl = c->getAttributeList(); + UMLAttribute *at; + idl << getIndent() << "struct " << classname << " {" << m_endl; + m_indentLevel++; + for (at = atl.first(); at; at = atl.next()) { + QString name = cleanName(at->getName()); + idl << getIndent() << at->getTypeName() << " " << name << ";" << m_endl; + // Initial value not possible in IDL. + } + UMLAssociationList compositions = c->getCompositions(); + if (!compositions.isEmpty()) { + idl << getIndent() << "// Compositions." << m_endl; + for (UMLAssociation *a = compositions.first(); a; a = compositions.next()) { + QString memberType, memberName; + computeAssocTypeAndRole(a, c, memberType, memberName); + idl << getIndent() << memberType << " " << memberName << ";" << m_endl; + } + } + UMLAssociationList aggregations = c->getAggregations(); + if (!aggregations.isEmpty()) { + idl << getIndent() << "// Aggregations." << m_endl; + for (UMLAssociation *a = aggregations.first(); a; a = aggregations.next()) { + QString memberType, memberName; + computeAssocTypeAndRole(a, c, memberType, memberName); + idl << getIndent() << memberType << " " << memberName << ";" << m_endl; + } + } + m_indentLevel--; + idl << getIndent() << "};" << m_endl << m_endl; + } else if (stype == "CORBAUnion") { + idl << getIndent() << "// " << stype << " " << c->getName() + << " is Not Yet Implemented" << m_endl << m_endl; + } else if (stype == "CORBATypedef") { + UMLClassifierList superclasses = c->getSuperClasses(); + UMLClassifier* firstParent = superclasses.first(); + idl << getIndent() << "typedef " << firstParent->getName() << " " + << c->getName() << ";" << m_endl << m_endl; + } else { + idl << getIndent() << "// " << stype << ": Unknown stereotype" << m_endl << m_endl; + } + // Close the modules inside which we might be nested. + for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) { + m_indentLevel--; + idl << getIndent() << "};" << m_endl << m_endl; + } + return; + } + + idl << getIndent(); + if (c->getAbstract()) + idl << "abstract "; + bool isValuetype = (c->getStereotype() == "CORBAValue"); + if (isValuetype) + idl << "valuetype "; + else + idl << "interface "; + idl << c->getName(); + UMLClassifierList superclasses = c->getSuperClasses(); + if (! superclasses.isEmpty()) { + idl << " : "; + UMLClassifier *parent = superclasses.first(); + int n_parents = superclasses.count(); + while (n_parents--) { + idl << parent->getFullyQualifiedName("::"); + if (n_parents) + idl << ", "; + parent = superclasses.next(); + } + } + idl << " {" << m_endl << m_endl; + m_indentLevel++; + + // Generate auxiliary declarations for multiplicity of associations + UMLAssociation *a; + bool didComment = false; + UMLAssociationList assocs = c->getAssociations(); + for (a = assocs.first(); a; a = assocs.next()) { + if (! assocTypeIsMappableToAttribute(a->getAssocType())) + continue; + QString multiplicity = a->getMulti(Uml::A); + if (multiplicity.isEmpty() || multiplicity == "1") + continue; + if (!didComment) { + idl << getIndent() << "// Types for association multiplicities" << m_endl << m_endl; + didComment = true; + } + UMLClassifier* other = (UMLClassifier*)a->getObject(Uml::A); + QString bareName = cleanName(other->getName()); + idl << getIndent() << "typedef sequence<" << other->getFullyQualifiedName("::") + << "> " << bareName << "Vector;" << m_endl << m_endl; + } + + // Generate public attributes. + if (isClass) { + UMLAttributeList atl = c->getAttributeList(); + if (forceSections() || atl.count()) { + idl << getIndent() << "// Attributes:" << m_endl << m_endl; + for (UMLAttribute *at = atl.first(); at; at = atl.next()) { + QString attName = cleanName(at->getName()); + Uml::Visibility scope = at->getVisibility(); + idl << getIndent(); + if (isValuetype) { + if (scope == Uml::Visibility::Public) + idl << "public "; + else + idl << "private "; + } else { + if (scope != Uml::Visibility::Public) { + idl << "// visibility should be: " + << scope.toString() + << m_endl; + idl << getIndent(); + } + idl << "attribute "; + } + idl << at->getTypeName() << " " << attName << ";" + << m_endl << m_endl; + } + } + } + + // Generate public operations. + UMLOperationList opl(c->getOpList()); + UMLOperationList oppub; + UMLOperation *op; + for (op = opl.first(); op; op = opl.next()) { + if (op->getVisibility() == Uml::Visibility::Public) + oppub.append(op); + } + if (forceSections() || oppub.count()) { + idl << getIndent() << "// Public methods:" << m_endl << m_endl; + for (op = oppub.first(); op; op = oppub.next()) + writeOperation(op, idl); + idl << m_endl; + } + + + if (forceSections() || !assocs.isEmpty()) { + idl << getIndent() << "// Associations:" << m_endl << m_endl; + for (a = assocs.first(); a; a = assocs.next()) { + Uml::Association_Type at = a->getAssocType(); + if (! assocTypeIsMappableToAttribute(at)) + continue; + QString typeName, roleName; + computeAssocTypeAndRole(a, c, typeName, roleName); + if (roleName.isEmpty()) // presumably because we are at the "wrong" end + continue; + idl << getIndent() << "// " << UMLAssociation::typeAsString(at) << m_endl; + idl << getIndent(); + if (isValuetype) + idl << "public "; + else + idl << "attribute "; + idl << typeName << " " << roleName << ";" << m_endl; + } + idl << m_endl; + } + + m_indentLevel--; + idl << getIndent() << "};" << m_endl << m_endl; + + // Close the modules inside which we might be nested. + for (pkg = pkgList.first(); pkg != NULL; pkg = pkgList.next()) { + m_indentLevel--; + idl << getIndent() << "};" << m_endl << m_endl; + } + file.close(); + emit codeGenerated(c, true); +} + + +void IDLWriter::writeOperation(UMLOperation *op, QTextStream &idl, bool is_comment) { + UMLAttributeList atl = op->getParmList(); + QString rettype = op->getTypeName(); + + if (rettype.isEmpty()) + rettype = "void"; + idl << getIndent(); + if (is_comment) + idl << "// "; + idl << rettype << " " << cleanName(op->getName()) << " ("; + if (atl.count()) { + idl << m_endl; + m_indentLevel++; + uint i = 0; + for (UMLAttribute *at = atl.first(); at; at = atl.next()) { + idl << getIndent(); + if (is_comment) + idl << "// "; + Uml::Parameter_Direction pk = at->getParmKind(); + if (pk == Uml::pd_Out) + idl << "out "; + else if (pk == Uml::pd_InOut) + idl << "inout "; + else + idl << "in "; + idl << at->getTypeName() << " " << cleanName(at->getName()); + if (++i < atl.count()) + idl << "," << m_endl; + } + m_indentLevel--; + } + idl << ");" << m_endl << m_endl; +} + +QStringList IDLWriter::defaultDatatypes() { + QStringList l; + l.append("boolean"); + l.append("char"); + l.append("octet"); + l.append("short"); + l.append("unsigned short"); + l.append("long"); + l.append("unsigned long"); + l.append("float"); + l.append("double"); + l.append("string"); + l.append("any"); + return l; +} + +const QStringList IDLWriter::reservedKeywords() const { + + static QStringList keywords; + + if (keywords.isEmpty()) { + keywords << "any" + << "attribute" + << "boolean" + << "case" + << "char" + << "const" + << "context" + << "default" + << "double" + << "enum" + << "exception" + << "FALSE" + << "float" + << "in" + << "inout" + << "interface" + << "long" + << "module" + << "octet" + << "oneway" + << "out" + << "raises" + << "readonly" + << "sequence" + << "short" + << "string" + << "struct" + << "switch" + << "TRUE" + << "typedef" + << "union" + << "unsigned" + << "void"; + } + + return keywords; +} + + diff --git a/umbrello/umbrello/codegenerators/idlwriter.h b/umbrello/umbrello/codegenerators/idlwriter.h new file mode 100644 index 00000000..c44cabd6 --- /dev/null +++ b/umbrello/umbrello/codegenerators/idlwriter.h @@ -0,0 +1,74 @@ +/*************************************************************************** + idlwriter.h - description + ------------------- + begin : Sat Jan 4 2003 + copyright : (C) 2003 by Oliver Kellogg + email : okellogg@users.sourceforge.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. * + * * + ***************************************************************************/ + +#ifndef IDLWRITER_H +#define IDLWRITER_H + +#include "simplecodegenerator.h" + +class UMLAssociation; +class UMLOperation; + +/** + * Class IDLWriter is a code generator for UMLClassifier objects. + * Create an instance of this class, and feed it a UMLClassifier when + * calling writeClass and it will generate an IDL interface for that + * concept. + */ +class IDLWriter : public SimpleCodeGenerator { +public: + + IDLWriter (); + virtual ~IDLWriter (); + + /** + * call this method to generate IDL code for a UMLClassifier + * @param c the class to generate code for + */ + virtual void writeClass (UMLClassifier *c); + + /** + * returns "IDL" + */ + virtual Uml::Programming_Language getLanguage(); + + QStringList defaultDatatypes(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +private: + + /** + * write one operation + * @param op the class for which we are generating code + * @param idl the stream associated with the output file + */ + void writeOperation(UMLOperation* op, QTextStream& idl, bool is_comment = false); + + void computeAssocTypeAndRole(UMLAssociation* a, UMLClassifier *c, + QString& typeName, QString& roleName); + + static bool isOOClass(UMLClassifier* c); + + static bool assocTypeIsMappableToAttribute(Uml::Association_Type at); + +}; + +#endif // IDLWRITER_H diff --git a/umbrello/umbrello/codegenerators/javaantcodedocument.cpp b/umbrello/umbrello/codegenerators/javaantcodedocument.cpp new file mode 100644 index 00000000..a3a174a3 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javaantcodedocument.cpp @@ -0,0 +1,312 @@ +/*************************************************************************** + * * + * 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 : Tue Jun 24 2003 + */ + +// own header +#include "javaantcodedocument.h" + +// qt/kde includes +#include <qregexp.h> +#include <kdebug.h> + +// local includes +#include "javacodegenerator.h" +#include "xmlcodecomment.h" +#include "xmlelementcodeblock.h" +#include "codegenfactory.h" +#include "../umldoc.h" +#include "../uml.h" + + +// Constructors/Destructors +// + +JavaANTCodeDocument::JavaANTCodeDocument ( ) +{ + setFileName("build"); // default name + setFileExtension(".xml"); + setID("ANTDOC"); // default id tag for this type of document +} + +JavaANTCodeDocument::~JavaANTCodeDocument ( ) { } + +// +// Methods +// + +// Other methods +// + +/** + * create a new CodeBlockWithComments object belonging to this CodeDocument. + * @return CodeBlockWithComments + */ +/* +CodeBlockWithComments * JavaANTCodeDocument::newCodeBlockWithComments ( ) { + return new XMLElementCodeBlock(this,"empty"); +} +*/ + +HierarchicalCodeBlock * JavaANTCodeDocument::newHierarchicalCodeBlock ( ) { + return new XMLElementCodeBlock(this,"empty"); +} + +// Sigh. NOT optimal. The only reason that we need to have this +// is so we can create the XMLNodes, if needed. +// would be better if we could create a handler interface that each +// codeblock used so all we have to do here is add the handler +void JavaANTCodeDocument::loadChildTextBlocksFromNode ( QDomElement & root) +{ + + QDomNode tnode = root.firstChild(); + QDomElement telement = tnode.toElement(); + bool loadCheckForChildrenOK = false; + while( !telement.isNull() ) { + QString nodeName = telement.tagName(); + + if( nodeName == "textblocks" ) { + + QDomNode node = telement.firstChild(); + QDomElement element = node.toElement(); + + // if there is nothing to begin with, then we don't worry about it + loadCheckForChildrenOK = element.isNull() ? true : false; + + while( !element.isNull() ) { + QString name = element.tagName(); + + if( name == "codecomment" ) { + CodeComment * block = new XMLCodeComment(this); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add codeComment to :"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "codeaccessormethod" || + name == "ccfdeclarationcodeblock" + ) { + QString acctag = element.attribute("tag",""); + // search for our method in the + TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag); + if(!tb || !addTextBlock(tb)) + { + kError()<<"Unable to add codeclassfield child method to:"<<this<<endl; + // DON'T delete + } else + loadCheckForChildrenOK= true; + + } else + if( name == "codeblock" ) { + CodeBlock * block = newCodeBlock(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add codeBlock to :"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "codeblockwithcomments" ) { + CodeBlockWithComments * block = newCodeBlockWithComments(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add codeBlockwithcomments to:"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "header" ) { + // do nothing.. this is treated elsewhere + } else + if( name == "hierarchicalcodeblock" ) { + HierarchicalCodeBlock * block = newHierarchicalCodeBlock(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add hierarchicalcodeBlock to:"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "codeoperation" ) { + // find the code operation by id + QString id = element.attribute("parent_id","-1"); + UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(STR2ID(id)); + UMLOperation * op = dynamic_cast<UMLOperation*>(obj); + if(op) { + CodeOperation * block = 0; + kError() << "TODO: implement CodeGenFactory::newCodeOperation() for JavaANTCodeDocument" << endl; + break; // remove when above is implemented + block->loadFromXMI(element); + if(addTextBlock(block)) + loadCheckForChildrenOK= true; + else + { + kError()<<"Unable to add codeoperation to:"<<this<<endl; + block->deleteLater(); + } + } else + kError()<<"Unable to find operation create codeoperation for:"<<this<<endl; + } else + if( name == "xmlelementblock" ) { + QString xmltag = element.attribute("nodeName","UNKNOWN"); + XMLElementCodeBlock * block = new XMLElementCodeBlock(this,xmltag); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add XMLelement to Java ANT document:"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } + /* + // only needed for extreme debugging conditions (E.g. making new codeclassdocument loader) + else + kDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignorning"<<endl; + */ + + node = element.nextSibling(); + element = node.toElement(); + } + break; + } + + tnode = telement.nextSibling(); + telement = tnode.toElement(); + } + + if(!loadCheckForChildrenOK) + { + CodeDocument * test = dynamic_cast<CodeDocument*>(this); + if(test) + { + kWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<<test->getFileName()<<" "<<this<<endl; + } else { + HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(this); + if(hb) + kWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<<hb->getTag()<<" "<<this<<endl; + else + kDebug()<<" loadChildBlocks : unable to initialize any child blocks in UNKNOWN OBJ:"<<this<<endl; + } + } + +} + +/** set the class attributes of this object from + * the passed element node. + */ +void JavaANTCodeDocument::setAttributesFromNode ( QDomElement & root) +{ + + // superclass save + CodeDocument::setAttributesFromNode(root); + + // now set local attributes + // setPackage(root.attribute("package","")); + +} + +/** + * load params from the appropriate XMI element node. + */ +void JavaANTCodeDocument::loadFromXMI ( QDomElement & root ) { + setAttributesFromNode(root); +} + +/** set attributes of the node that represents this class + * in the XMI document. + */ +void JavaANTCodeDocument::setAttributesOnNode ( QDomDocument & doc, QDomElement & docElement) +{ + + // superclass call + CodeDocument::setAttributesOnNode(doc,docElement); + + // now set local attributes/fields + //FIX +} + +/** + * Save the XMI representation of this object + */ +void JavaANTCodeDocument::saveToXMI ( QDomDocument & doc, QDomElement & root ) { + QDomElement docElement = doc.createElement( "codedocument" ); + + setAttributesOnNode(doc, docElement); + + root.appendChild( docElement ); +} + +// we add in our code blocks that describe how to generate +// the project here... +void JavaANTCodeDocument::updateContent( ) { + // FIX : fill in more content based on classes + // which exist + CodeBlockWithComments * xmlDecl = getCodeBlockWithComments("xmlDecl","",0); + xmlDecl->setText("<?xml version=\"1.0\"?>"); + addTextBlock(xmlDecl); + + XMLElementCodeBlock * rootNode = new XMLElementCodeBlock(this, "project", "Java ANT build document"); + rootNode->setTag("projectDecl"); + addTextBlock(rootNode); + + // <project name="XDF" default="help" basedir="."> + //HierarchicalCodeBlock * projDecl = xmlDecl->getHierarchicalCodeBlock("projectDecl", "Java ANT build document", 1); + + // set some global properties for the build + /* + <!-- set global properties for this build --> + <!-- paths --> + <property name="docApi.dir" value="docs/api"/> + <property name="path" value="gov/nasa/gsfc/adc/xdf"/> + <property name="src" value="src/${path}/"/> + <property name="top" value="."/> + <property name="build" value="${top}/gov"/> + <property name="buildDir" value="${path}"/> + <!-- compiler directives --> + <property name="build.compiler" value="modern"/> + <property name="useDeprecation" value="no"/> + <property name="jarname" value="${project}.jar"/> + */ + +} + +// We overwritten by Java language implementation to get lowercase path +QString JavaANTCodeDocument::getPath ( ) +{ + + QString path = getPackage(); + + // Replace all white spaces with blanks + path.simplifyWhiteSpace(); + + // Replace all blanks with underscore + path.replace(QRegExp(" "), "_"); + + path.replace(QRegExp("\\."),"/"); + path.replace(QRegExp("::"), "/"); + + path.lower(); + + return path; + +} + + +#include "javaantcodedocument.moc" diff --git a/umbrello/umbrello/codegenerators/javaantcodedocument.h b/umbrello/umbrello/codegenerators/javaantcodedocument.h new file mode 100644 index 00000000..9d7372f3 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javaantcodedocument.h @@ -0,0 +1,100 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Tue Jun 24 2003 + */ + + + +#ifndef JAVAANTCODEDOCUMENT_H +#define JAVAANTCODEDOCUMENT_H + +#include <qstring.h> +#include <qdom.h> + +#include "../codedocument.h" + +/** + * class JavaANTCodeDocument + * Represents + */ + +class JavaANTCodeDocument : public CodeDocument +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructor + */ + JavaANTCodeDocument ( ); + + /** + * Empty Destructor + */ + virtual ~JavaANTCodeDocument ( ); + + QString getPath ( ); + + void updateContent(); + + /** + * Save the XMI representation of this object + */ + virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ); + + /** + * load params from the appropriate XMI element node. + */ + virtual void loadFromXMI ( QDomElement & root ); + + /** + * create a new HierarchicalCodeBlock object belonging to this CodeDocument. + * @return HierarchicalCodeBlock + */ + virtual HierarchicalCodeBlock * newHierarchicalCodeBlock ( ); + + /** + * create a new CodeBlockWithComments object belonging to this CodeDocument. + * @return CodeBlockWithComments + */ + // virtual CodeBlockWithComments * newCodeBlockWithComments ( ); + +protected: + + /** set attributes of the node that represents this class + * in the XMI document. + */ + virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement); + + /** set the class attributes of this object from + * the passed element node. + */ + virtual void setAttributesFromNode ( QDomElement & element); + + /** + * need to overwrite this for java since we need to pick up the + * xml declaration blocks. + */ + virtual void loadChildTextBlocksFromNode ( QDomElement & root); + +private: + + + +}; + +#endif // JAVAANTCODEDOCUMENT_H diff --git a/umbrello/umbrello/codegenerators/javaclassdeclarationblock.cpp b/umbrello/umbrello/codegenerators/javaclassdeclarationblock.cpp new file mode 100644 index 00000000..0e4ccdbf --- /dev/null +++ b/umbrello/umbrello/codegenerators/javaclassdeclarationblock.cpp @@ -0,0 +1,169 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Wed Jul 16 2003 + */ +#include "javaclassdeclarationblock.h" +#include "javacodedocumentation.h" +#include "../codegenerator.h" +#include "../codegenerationpolicy.h" +#include "../uml.h" + +// Constructors/Destructors +// + +JavaClassDeclarationBlock::JavaClassDeclarationBlock + ( JavaClassifierCodeDocument * parentDoc, const QString &startText, const QString &endText, const QString &comment) + : OwnedHierarchicalCodeBlock(parentDoc->getParentClassifier(), parentDoc, startText, endText, comment) +{ + init(parentDoc, comment); +} + +JavaClassDeclarationBlock::~JavaClassDeclarationBlock ( ) { } + +// +// Methods +// + +/** + * Save the XMI representation of this object + */ +void JavaClassDeclarationBlock::saveToXMI ( QDomDocument & doc, QDomElement & root ) { + QDomElement blockElement = doc.createElement( "javaclassdeclarationblock" ); + + setAttributesOnNode(doc, blockElement); + + root.appendChild( blockElement ); +} + +/** + * load params from the appropriate XMI element node. + */ +void JavaClassDeclarationBlock::loadFromXMI ( QDomElement & root ) +{ + setAttributesFromNode(root); +} + +// Accessor methods +// + +// Other methods +// + +/** + * update the start and end text for this ownedhierarchicalcodeblock. + */ +void JavaClassDeclarationBlock::updateContent ( ) +{ + + JavaClassifierCodeDocument *parentDoc = dynamic_cast<JavaClassifierCodeDocument*>(getParentDocument()); + UMLClassifier *c = parentDoc->getParentClassifier(); + CodeGenerationPolicy *commonPolicy = UMLApp::app()->getCommonPolicy(); + QString endLine = commonPolicy->getNewLineEndingChars(); + bool isInterface = parentDoc->parentIsInterface(); // a little shortcut + QString JavaClassName = parentDoc->getJavaClassName(c->getName()); + + // COMMENT + if(isInterface) + getComment()->setText("Interface "+JavaClassName+endLine+c->getDoc()); + else + getComment()->setText("Class "+JavaClassName+endLine+c->getDoc()); + + bool forceDoc = UMLApp::app()->getCommonPolicy()->getCodeVerboseDocumentComments(); + if(forceDoc || !c->getDoc().isEmpty()) + getComment()->setWriteOutText(true); + else + getComment()->setWriteOutText(false); + + + // Now set START/ENDING Text + QString startText = ""; + // In Java, we need declare abstract only on classes + if (c->getAbstract() && !isInterface) + startText.append("abstract "); + + if (c->getVisibility() != Uml::Visibility::Public) { + // We should probably 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 + startText.append("public "); + + if(parentDoc->parentIsInterface()) + startText.append("interface "); + else + startText.append("class "); + + startText.append(JavaClassName); + + // write inheritances out + UMLClassifierList superclasses = + c->findSuperClassConcepts(UMLClassifier::CLASS); + UMLClassifierList superinterfaces = + c->findSuperClassConcepts(UMLClassifier::INTERFACE); + int nrof_superclasses = superclasses.count(); + int nrof_superinterfaces = superinterfaces.count(); + + // write out inheritance + int i = 0; + if(nrof_superclasses >0) + startText.append(" extends "); + for (UMLClassifier * concept= superclasses.first(); concept; concept = superclasses.next()) + { + startText.append(parentDoc->cleanName(concept->getName())); + if(i != (nrof_superclasses-1)) + startText.append(", "); + i++; + } + + // write out what we 'implement' + i = 0; + if(nrof_superinterfaces >0) + { + // In Java interfaces "extend" other interfaces. Classes "implement" interfaces + if(isInterface) + startText.append(" extends "); + else + startText.append(" implements "); + } + for (UMLClassifier * concept= superinterfaces.first(); concept; concept = superinterfaces.next()) + { + startText.append(parentDoc->cleanName(concept->getName())); + if(i != (nrof_superinterfaces-1)) + startText.append(", "); + i++; + } + + // Set the header and end text for the hier.codeblock + setStartText(startText+" {"); + + // setEndText("}"); // not needed + +} + +void JavaClassDeclarationBlock::init (JavaClassifierCodeDocument *parentDoc, const QString &comment) +{ + + setComment(new JavaCodeDocumentation(parentDoc)); + getComment()->setText(comment); + + setEndText("}"); + + updateContent(); + +} + + +#include "javaclassdeclarationblock.moc" diff --git a/umbrello/umbrello/codegenerators/javaclassdeclarationblock.h b/umbrello/umbrello/codegenerators/javaclassdeclarationblock.h new file mode 100644 index 00000000..136df809 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javaclassdeclarationblock.h @@ -0,0 +1,66 @@ + + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Wed Jul 16 2003 + */ + +#ifndef JAVACLASSDECLARATIONBLOCK_H +#define JAVACLASSDECLARATIONBLOCK_H + +#include <qstring.h> + +#include "javaclassifiercodedocument.h" +#include "../ownedhierarchicalcodeblock.h" + +class JavaClassDeclarationBlock : public OwnedHierarchicalCodeBlock +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Empty Constructor + */ + explicit JavaClassDeclarationBlock ( JavaClassifierCodeDocument * parentDoc, const QString &start = "", const QString &endText = "}", const QString &comment = ""); + + /** + * Empty Destructor + */ + virtual ~JavaClassDeclarationBlock ( ); + + /** + * Save the XMI representation of this object + */ + virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ); + + /** + * load params from the appropriate XMI element node. + */ + virtual void loadFromXMI ( QDomElement & root ); + +protected: + + /** + * Update the start/end text of this codeblock. + */ + void updateContent ( ); + +private: + + void init (JavaClassifierCodeDocument * parent, const QString &comment); + +}; + +#endif // JAVACLASSDECLARATIONBLOCK_H diff --git a/umbrello/umbrello/codegenerators/javaclassifiercodedocument.cpp b/umbrello/umbrello/codegenerators/javaclassifiercodedocument.cpp new file mode 100644 index 00000000..44e6f242 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javaclassifiercodedocument.cpp @@ -0,0 +1,583 @@ +/*************************************************************************** + * * + * 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 : Mon Jun 23 2003 + */ + +/** + We carve the Java document up into sections as follows: + + * header + * package declaration + * import statements + * class declaration + * guts of the class (e.g. field decl, accessor methods, operations, dependant classes) +*/ + +// own header +#include "javaclassifiercodedocument.h" + +// qt/kde includes +#include <kdebug.h> +#include <qregexp.h> + +// local includes +#include "javacodegenerator.h" +#include "javacodecomment.h" +#include "javaclassdeclarationblock.h" +#include "javacodeclassfielddeclarationblock.h" +#include "codegen_utils.h" +#include "../classifier.h" +#include "../codegenerationpolicy.h" +#include "../uml.h" + +// Constructors/Destructors +// + +JavaClassifierCodeDocument::JavaClassifierCodeDocument ( UMLClassifier * concept ) + : ClassifierCodeDocument (concept) { + init(); +} + +JavaClassifierCodeDocument::~JavaClassifierCodeDocument ( ) { } + +// +// Methods +// + +// Accessor methods +// + +// Make it easier on ourselves +JavaCodeGenerationPolicy * JavaClassifierCodeDocument::getJavaPolicy() { + CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt(); + JavaCodeGenerationPolicy * policy = dynamic_cast<JavaCodeGenerationPolicy*>(pe); + return policy; +} + +/** + * Get the dialog widget which allows user interaction with the object parameters. + * @return CodeDocumentDialog + */ +/* +CodeDocumentDialog JavaClassifierCodeDocument::getDialog ( ) { + +} +*/ + +bool JavaClassifierCodeDocument::forceDoc () { + return UMLApp::app()->getCommonPolicy()->getCodeVerboseDocumentComments(); +} + +// We overwritten by Java language implementation to get lowercase path +QString JavaClassifierCodeDocument::getPath ( ) +{ + + QString path = getPackage(); + + // Replace all white spaces with blanks + path.simplifyWhiteSpace(); + + // Replace all blanks with underscore + path.replace(QRegExp(" "), "_"); + + path.replace(QRegExp("\\."),"/"); + path.replace(QRegExp("::"), "/"); + + path.lower(); + + return path; + +} + + +// Other methods +// + +QString JavaClassifierCodeDocument::getJavaClassName (const QString &name) { + return Codegen_Utils::capitalizeFirstLetter(CodeGenerator::cleanName(name)); +} + +// Initialize this java classifier code document +void JavaClassifierCodeDocument::init ( ) { + + setFileExtension(".java"); + + //initCodeClassFields(); // this is dubious because it calls down to + // CodeGenFactory::newCodeClassField(this) + // but "this" is still in construction at that time. + + classDeclCodeBlock = 0; + operationsBlock = 0; + constructorBlock = 0; + + // this will call updateContent() as well as other things that sync our document. + synchronize(); +} + +/** + * @param op + */ +// in the vannilla version, we just tack all operations on the end +// of the document +bool JavaClassifierCodeDocument::addCodeOperation (CodeOperation * op ) { + + if(!op->getParentOperation()->isLifeOperation()) + return operationsBlock->addTextBlock(op); + else + return constructorBlock->addTextBlock(op); +} + +// Sigh. NOT optimal. The only reason that we need to have this +// is so we can create the JavaClassDeclarationBlock. +// would be better if we could create a handler interface that each +// codeblock used so all we have to do here is add the handler +// for "javaclassdeclarationblock" +void JavaClassifierCodeDocument::loadChildTextBlocksFromNode ( QDomElement & root) +{ + + QDomNode tnode = root.firstChild(); + QDomElement telement = tnode.toElement(); + bool loadCheckForChildrenOK = false; + while( !telement.isNull() ) { + QString nodeName = telement.tagName(); + + if( nodeName == "textblocks" ) { + + QDomNode node = telement.firstChild(); + QDomElement element = node.toElement(); + + // if there is nothing to begin with, then we don't worry about it + loadCheckForChildrenOK = element.isNull() ? true : false; + + while( !element.isNull() ) { + QString name = element.tagName(); + + if( name == "codecomment" ) { + CodeComment * block = new JavaCodeComment(this); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"loadFromXMI : unable to add codeComment to :"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "codeaccessormethod" || + name == "ccfdeclarationcodeblock" + ) { + QString acctag = element.attribute("tag",""); + // search for our method in the + TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag); + if(!tb || !addTextBlock(tb)) + { + kError()<<"loadFromXMI : unable to add codeclassfield child method to:"<<this<<endl; + // DON'T delete + } else + loadCheckForChildrenOK= true; + + } else + if( name == "codeblock" ) { + CodeBlock * block = newCodeBlock(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"loadFromXMI : unable to add codeBlock to :"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "codeblockwithcomments" ) { + CodeBlockWithComments * block = newCodeBlockWithComments(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"loadFromXMI : unable to add codeBlockwithcomments to:"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "header" ) { + // do nothing.. this is treated elsewhere + } else + if( name == "hierarchicalcodeblock" ) { + HierarchicalCodeBlock * block = newHierarchicalCodeBlock(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add hierarchicalcodeBlock to:"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "codeoperation" ) { + // find the code operation by id + QString id = element.attribute("parent_id","-1"); + UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(STR2ID(id)); + UMLOperation * op = dynamic_cast<UMLOperation*>(obj); + if(op) { + CodeOperation * block = new JavaCodeOperation(this, op); + block->loadFromXMI(element); + if(addTextBlock(block)) + loadCheckForChildrenOK= true; + else + { + kError()<<"Unable to add codeoperation to:"<<this<<endl; + block->deleteLater(); + } + } else + kError()<<"Unable to find operation create codeoperation for:"<<this<<endl; + } else + if( name == "javaclassdeclarationblock" ) + { + JavaClassDeclarationBlock * block = getClassDecl(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add java code declaration block to:"<<this<<endl; + // DON'T delete. + // block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } + // This last item is only needed for extreme debugging conditions + // (E.g. making new codeclassdocument loader) + // else + // kDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignorning"<<endl; + + node = element.nextSibling(); + element = node.toElement(); + } + break; + } + + tnode = telement.nextSibling(); + telement = tnode.toElement(); + } + + if(!loadCheckForChildrenOK) + { + CodeDocument * test = dynamic_cast<CodeDocument*>(this); + if(test) + { + kWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<<test->getFileName()<<" "<<this<<endl; + } else { + HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(this); + if(hb) + kWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<<hb->getTag()<<" "<<this<<endl; + else + kDebug()<<" loadChildBlocks : unable to initialize any child blocks in UNKNOWN OBJ:"<<this<<endl; + } + } + + +} + +QString JavaClassifierCodeDocument::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: + case Uml::Visibility::Implementation: + default: + scopeString = "private"; + break; + } + return scopeString; +} + +JavaClassDeclarationBlock * JavaClassifierCodeDocument::getClassDecl() +{ + if(!classDeclCodeBlock) + { + classDeclCodeBlock = new JavaClassDeclarationBlock (this); + classDeclCodeBlock->setTag("ClassDeclBlock"); + } + return classDeclCodeBlock; +} + +void JavaClassifierCodeDocument::resetTextBlocks() +{ + + // all special pointers to text blocks need to be zero'd out + operationsBlock = 0; + constructorBlock = 0; + classDeclCodeBlock = 0; + + // now do traditional release of text blocks. + ClassifierCodeDocument::resetTextBlocks(); +} + +// This method will cause the class to rebuild its text representation. +// based on the parent classifier object. +// For any situation in which this is called, we are either building the code +// document up, or replacing/regenerating the existing auto-generated parts. As +// such, we will want to insert everything we resonablely will want +// during creation. We can set various parts of the document (esp. the +// comments) to appear or not, as needed. +void JavaClassifierCodeDocument::updateContent( ) +{ + // Gather info on the various fields and parent objects of this class... + UMLClassifier * c = getParentClassifier(); + CodeGenerationPolicy * commonPolicy = UMLApp::app()->getCommonPolicy(); + CodeGenPolicyExt * pe = UMLApp::app()->getPolicyExt(); + JavaCodeGenerationPolicy * policy = dynamic_cast<JavaCodeGenerationPolicy*>(pe); + + // first, set the global flag on whether or not to show classfield info + // This depends on whether or not we have attribute/association classes + CodeClassFieldList * cfList = getCodeClassFieldList(); + for(CodeClassField * field = cfList->first(); field; field = cfList->next()) + if(field->parentIsAttribute()) + field->setWriteOutMethods(policy->getAutoGenerateAttribAccessors()); + else + field->setWriteOutMethods(policy->getAutoGenerateAssocAccessors()); + + // attribute-based ClassFields + // we do it this way to have the static fields sorted out from regular ones + CodeClassFieldList staticAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true); + CodeClassFieldList attribClassFields = getSpecificClassFields (CodeClassField::Attribute, false); + // association-based ClassFields + // don't care if they are static or not..all are lumped together + CodeClassFieldList plainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation ); + CodeClassFieldList aggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation ); + CodeClassFieldList compositionClassFields = getSpecificClassFields ( CodeClassField::Composition ); + + bool isInterface = parentIsInterface(); + bool hasOperationMethods = c->getOpList().last() ? true : false; + QString endLine = commonPolicy->getNewLineEndingChars(); // a shortcut..so we don't have to call this all the time + + // + // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT + // + + // + // PACKAGE CODE BLOCK + // + QString pkgs = getPackage(); + pkgs.replace(QRegExp("::"), "."); + QString packageText = getPackage().isEmpty() ? "" : "package "+pkgs+';'+endLine; + CodeBlockWithComments * pblock = addOrUpdateTaggedCodeBlockWithComments("packages", packageText, "", 0, false); + if(packageText.isEmpty() && pblock->getContentType() == CodeBlock::AutoGenerated) + pblock->setWriteOutText(false); + else + pblock->setWriteOutText(true); + + // IMPORT CODEBLOCK + // + // 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) + QString importStatement = ""; + if ( hasObjectVectorClassFields() ) + importStatement.append("import java.util.*;"); + + //only import classes in a different package from this class + UMLPackageList imports; + QMap<UMLPackage*, QString> packageMap; // so we don't repeat packages + + CodeGenerator::findObjectsRelated(c,imports); + for(UMLPackage *con = imports.first(); con ; con = imports.next()) + // NO (default) datatypes in the import statement.. use defined + // ones whould be possible, but no idea how to do that...at least for now. + // Dynamic casting is slow..not an optimal way to do this. + if (!packageMap.contains(con) && con->getBaseType() != Uml::ot_Datatype) + { + packageMap.insert(con, con->getPackage()); + + // now, we DON'T need to import classes that are already in our own package + // (that is, IF a package is specified). Otherwise, we should have a declaration. + if (con->getPackage() != c->getPackage() || + (c->getPackage().isEmpty() && con->getPackage().isEmpty())) + { + importStatement.append(endLine+"import "); + if(!con->getPackage().isEmpty()) + importStatement.append(con->getPackage()+'.'); + importStatement.append(CodeGenerator::cleanName(con->getName())+';'); + } + } + // now, add/update the imports codeblock + CodeBlockWithComments * iblock = addOrUpdateTaggedCodeBlockWithComments("imports", importStatement, "", 0, false); + if(importStatement.isEmpty() && iblock->getContentType() == CodeBlock::AutoGenerated) + iblock->setWriteOutText(false); + else + iblock->setWriteOutText(true); + + // CLASS DECLARATION BLOCK + // + + // get the declaration block. If its not already present, add it too + JavaClassDeclarationBlock * myClassDeclCodeBlock = getClassDecl(); + addTextBlock(myClassDeclCodeBlock); // note: wont add if already present + + // NOW create document in sections.. + // now we want to populate the body of our class + // our layout is the following general groupings of code blocks: + + // start java classifier document + + // header comment + + // package code block + + // import code block + + // class declaration + + // section: + // - class field declaration section comment + // - class field declarations (0+ codeblocks) + + // section: + // - methods section comment + + // sub-section: constructor ops + // - constructor method section comment + // - constructor methods (0+ codeblocks) + + // sub-section: accessors + // - accessor method section comment + // - static accessor methods (0+ codeblocks) + // - non-static accessor methods (0+ codeblocks) + + // sub-section: non-constructor ops + // - operation method section comment + // - operations (0+ codeblocks) + + // end class declaration + + // end java classifier document + + + // Q: Why use the more complicated scheme of arranging code blocks within codeblocks? + // A: This will allow us later to preserve the format of our document so that if + // codeblocks are added, they may be easily added in the correct place, rather than at + // the end of the document, or by using a difficult algorithm to find the location of + // the last appropriate code block sibling (which may not exist.. for example user adds + // a constructor operation, but there currently are no constructor code blocks + // within the document). + + // + // * CLASS FIELD declaration section + // + + // get/create the field declaration code block + HierarchicalCodeBlock * fieldDeclBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("fieldsDecl", "Fields", 1); + + // Update the comment: we only set comment to appear under the following conditions + CodeComment * fcomment = fieldDeclBlock->getComment(); + if (isInterface || (!forceDoc() && !hasClassFields()) ) + fcomment->setWriteOutText(false); + else + fcomment->setWriteOutText(true); + + // now actually declare the fields within the appropriate HCodeBlock + declareClassFields(staticAttribClassFields, fieldDeclBlock); + declareClassFields(attribClassFields, fieldDeclBlock); + declareClassFields(plainAssocClassFields, fieldDeclBlock); + declareClassFields(aggregationClassFields, fieldDeclBlock); + declareClassFields(compositionClassFields, fieldDeclBlock); + + // + // METHODS section + // + + // get/create the method codeblock + HierarchicalCodeBlock * methodsBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("methodsBlock", "Methods", 1); + + // Update the section comment + CodeComment * methodsComment = methodsBlock->getComment(); + // set conditions for showing this comment + if (!forceDoc() && !hasClassFields() && !hasOperationMethods) + methodsComment->setWriteOutText(false); + else + methodsComment->setWriteOutText(true); + + // METHODS sub-section : constructor methods + // + + // get/create the constructor codeblock + HierarchicalCodeBlock * constBlock = methodsBlock->getHierarchicalCodeBlock("constructorMethods", "Constructors", 1); + constructorBlock = constBlock; // record this codeblock for later, when operations are updated + + // special condiions for showing comment: only when autogenerateding empty constructors + // Although, we *should* check for other constructor methods too + CodeComment * constComment = constBlock->getComment(); + CodeGenerationPolicy *pol = UMLApp::app()->getCommonPolicy(); + if (!forceDoc() && (isInterface || !pol->getAutoGenerateConstructors())) + constComment->setWriteOutText(false); + else + constComment->setWriteOutText(true); + + // add/get the empty constructor + QString JavaClassName = getJavaClassName(c->getName()); + QString emptyConstStatement = "public "+JavaClassName+" ( ) { }"; + CodeBlockWithComments * emptyConstBlock = + constBlock->addOrUpdateTaggedCodeBlockWithComments("emptyconstructor", emptyConstStatement, "Empty Constructor", 1, false); + // Now, as an additional condition we only show the empty constructor block + // IF it was desired to be shown + if(parentIsClass() && pol->getAutoGenerateConstructors()) + emptyConstBlock->setWriteOutText(true); + else + emptyConstBlock->setWriteOutText(false); + + // METHODS subsection : ACCESSOR METHODS + // + + // get/create the accessor codeblock + HierarchicalCodeBlock * accessorBlock = methodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1); + + // set conditions for showing section comment + CodeComment * accessComment = accessorBlock->getComment(); + if (!forceDoc() && !hasClassFields()) + accessComment->setWriteOutText(false); + else + accessComment->setWriteOutText(true); + + // now, 2 sub-sub sections in accessor block + // add/update accessor methods for attributes + HierarchicalCodeBlock * staticAccessors = accessorBlock->getHierarchicalCodeBlock("staticAccessorMethods", "", 1); + staticAccessors->getComment()->setWriteOutText(false); // never write block comment + staticAccessors->addCodeClassFieldMethods(staticAttribClassFields); + staticAccessors->addCodeClassFieldMethods(attribClassFields); + + // add/update accessor methods for associations + HierarchicalCodeBlock * regularAccessors = accessorBlock->getHierarchicalCodeBlock("regularAccessorMethods", "", 1); + regularAccessors->getComment()->setWriteOutText(false); // never write block comment + regularAccessors->addCodeClassFieldMethods(plainAssocClassFields); + regularAccessors->addCodeClassFieldMethods(aggregationClassFields); + regularAccessors->addCodeClassFieldMethods(compositionClassFields); + + // METHODS subsection : Operation methods (which arent constructors) + // + + // get/create the operations codeblock + operationsBlock = methodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1); + + // set conditions for showing section comment + CodeComment * ocomment = operationsBlock->getComment(); + if (!forceDoc() && !hasOperationMethods ) + ocomment->setWriteOutText(false); + else + ocomment->setWriteOutText(true); + +} + + +#include "javaclassifiercodedocument.moc" diff --git a/umbrello/umbrello/codegenerators/javaclassifiercodedocument.h b/umbrello/umbrello/codegenerators/javaclassifiercodedocument.h new file mode 100644 index 00000000..ddad6e1a --- /dev/null +++ b/umbrello/umbrello/codegenerators/javaclassifiercodedocument.h @@ -0,0 +1,110 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Jun 23 2003 + */ + + + +#ifndef JAVACLASSIFIERCODEDOCUMENT_H +#define JAVACLASSIFIERCODEDOCUMENT_H + +#include <qstring.h> + +#include "../codeclassfieldlist.h" +#include "../classifiercodedocument.h" +#include "../classifier.h" +#include "../hierarchicalcodeblock.h" +#include "classifierinfo.h" +#include "javacodeclassfield.h" +#include "javacodeoperation.h" + +class JavaClassDeclarationBlock; +class JavaCodeGenerationPolicy; + +/** + * class JavaClassifierCodeDocument + * A Java UMLClassifier Code Document. + */ + +class JavaClassifierCodeDocument : public ClassifierCodeDocument +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + + /** + * Constructor + */ + JavaClassifierCodeDocument (UMLClassifier * classifier); + + /** + * Empty Destructor + */ + virtual ~JavaClassifierCodeDocument ( ); + + /** + * Get the dialog widget which allows user interaction with the object parameters. + * @return CodeDocumentDialog + */ + //CodeDocumentDialog getDialog ( ); + + QString scopeToJavaDecl(Uml::Visibility scope); + + // Make it easier on ourselves + JavaCodeGenerationPolicy * getJavaPolicy(); + + QString getJavaClassName (const QString &name); + + QString getPath(); + + /** add a code operation to this java classifier code document. + * @return bool which is true IF the code operation was added successfully + */ + bool addCodeOperation (CodeOperation * op ); + +protected: + + // reset/clear our inventory of textblocks in this document + void resetTextBlocks(); + + /** + * need to overwrite this for java since we need to pick up the + * java class declaration block. + */ + virtual void loadChildTextBlocksFromNode ( QDomElement & root); + + void addOrUpdateCodeClassFieldMethodsInCodeBlock(CodeClassFieldList &list, JavaClassDeclarationBlock * codeBlock); + + bool forceDoc (); + + void updateContent(); + +private: + + JavaClassDeclarationBlock * classDeclCodeBlock; + HierarchicalCodeBlock * constructorBlock; + HierarchicalCodeBlock * operationsBlock; + + ClassifierInfo * info; + + void init ( ); + JavaClassDeclarationBlock * getClassDecl(); + + +}; + +#endif // JAVACLASSIFIERCODEDOCUMENT_H diff --git a/umbrello/umbrello/codegenerators/javacodeaccessormethod.cpp b/umbrello/umbrello/codegenerators/javacodeaccessormethod.cpp new file mode 100644 index 00000000..524e6a48 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodeaccessormethod.cpp @@ -0,0 +1,223 @@ +/*************************************************************************** + * * + * 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 : Fri Jun 20 2003 + */ + +// own header +#include "javacodeaccessormethod.h" + +// qt/kde includes +#include <kdebug.h> + +// local includes +#include "../attribute.h" +#include "../codegenerator.h" +#include "../codegenerationpolicy.h" +#include "../classifiercodedocument.h" +#include "../umlobject.h" +#include "../umlrole.h" +#include "../uml.h" +#include "codegen_utils.h" +#include "javaclassifiercodedocument.h" +#include "javacodegenerationpolicy.h" +#include "javacodeclassfield.h" +#include "javacodedocumentation.h" + +// Constructors/Destructors +// + +JavaCodeAccessorMethod::JavaCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type) + : CodeAccessorMethod ( field ) +{ + setType(type); + + // lets use full-blown comment + JavaClassifierCodeDocument* jccd = dynamic_cast<JavaClassifierCodeDocument*>(field->getParentDocument()); + setComment(new JavaCodeDocumentation(jccd)); +} + +JavaCodeAccessorMethod::~JavaCodeAccessorMethod ( ) { } + +// Other methods +// + +void JavaCodeAccessorMethod::setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement) +{ + + // set super-class attributes + CodeAccessorMethod::setAttributesOnNode(doc, blockElement); + + // set local attributes now +} + +void JavaCodeAccessorMethod::setAttributesFromNode( QDomElement & root) +{ + + // set attributes from superclass method the XMI + CodeAccessorMethod::setAttributesFromNode(root); + + // load local stuff + +} + +void JavaCodeAccessorMethod::updateContent( ) +{ + + CodeClassField * parentField = getParentClassField(); + JavaCodeClassField * javafield = dynamic_cast<JavaCodeClassField*>(parentField); + QString fieldName = javafield->getFieldName(); + + QString text = ""; + switch(getType()) { + case CodeAccessorMethod::ADD: + { + int maxOccurs = javafield->maximumListOccurances(); + QString fieldType = javafield->getTypeName(); + QString indent = getIndentation(); + QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars(); + if(maxOccurs > 0) + text += "if ("+fieldName+".size() < "+ QString::number(maxOccurs)+") {"+endLine+indent; + text += fieldName+".add(value);"; + if(maxOccurs > 0) + { + text += endLine+"} else {"+endLine; + text += indent + "System.err.println(\"ERROR: Cant add"+fieldType+" to "+fieldName+", minimum number of items reached.\");"+endLine+'}'+endLine; + } + break; + } + case CodeAccessorMethod::GET: + text = "return "+fieldName+';'; + break; + case CodeAccessorMethod::LIST: + text = "return (List) "+fieldName+';'; + break; + case CodeAccessorMethod::REMOVE: + { + int minOccurs = javafield->minimumListOccurances(); + QString fieldType = javafield->getTypeName(); + QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars(); + QString indent = getIndentation(); + + if(minOccurs > 0) + text += "if ("+fieldName+".size() >= "+ QString::number(minOccurs)+") {"+endLine+indent; + text += fieldName+".remove(value);"; + if(minOccurs > 0) + { + text += endLine+"} else {"+endLine; + text += indent + "System.err.println(\"ERROR: Cant remove"+fieldType+" from "+fieldName+", minimum number of items reached.\");"+endLine+'}'+endLine; + } + break; + } + case CodeAccessorMethod::SET: + text = fieldName+" = value;"; + break; + default: + // do nothing + break; + } + + setText(text); + +} + +void JavaCodeAccessorMethod::updateMethodDeclaration() +{ + + JavaCodeClassField * javafield = dynamic_cast<JavaCodeClassField*>(getParentClassField()); + JavaClassifierCodeDocument * javadoc = dynamic_cast<JavaClassifierCodeDocument*>(javafield->getParentDocument()); + CodeGenerationPolicy *commonpolicy = UMLApp::app()->getCommonPolicy(); + + // gather defs + CodeGenerationPolicy::ScopePolicy scopePolicy = commonpolicy->getAttributeAccessorScope(); + QString strVis = javadoc->scopeToJavaDecl(javafield->getVisibility()); + QString fieldName = javafield->getFieldName(); + QString fieldType = javafield->getTypeName(); + QString objectType = javafield->getListObjectType(); + if(objectType.isEmpty()) + objectType = fieldName; + QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars(); + + // set scope of this accessor appropriately..if its an attribute, + // we need to be more sophisticated + if(javafield->parentIsAttribute()) + switch (scopePolicy) { + case CodeGenerationPolicy::Public: + case CodeGenerationPolicy::Private: + case CodeGenerationPolicy::Protected: + strVis = javadoc->scopeToJavaDecl((Uml::Visibility::Value) scopePolicy); + break; + default: + case CodeGenerationPolicy::FromParent: + // do nothing..already have taken parent value + break; + } + + // some variables we will need to populate + QString headerText = ""; + QString methodReturnType = ""; + QString methodName = ""; + QString methodParams = ""; + + switch(getType()) { + case CodeAccessorMethod::ADD: + methodName = "add" + Codegen_Utils::capitalizeFirstLetter(fieldType); + methodReturnType = "void"; + methodParams = objectType+" value "; + headerText = "Add an object of type "+objectType+" to the List "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@return void"; + break; + case CodeAccessorMethod::GET: + methodName = "get" + Codegen_Utils::capitalizeFirstLetter(fieldName); + methodReturnType = fieldType; + headerText = "Get the value of "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@return the value of "+fieldName; + break; + case CodeAccessorMethod::LIST: + methodName = "get" + Codegen_Utils::capitalizeFirstLetter(fieldType)+"List"; + methodReturnType = "List"; + headerText = "Get the list of "+fieldName+endLine+getParentObject()->getDoc()+endLine+"@return List of "+fieldName; + break; + case CodeAccessorMethod::REMOVE: + methodName = "remove" + Codegen_Utils::capitalizeFirstLetter(fieldType); + methodReturnType = "void"; + methodParams = objectType+" value "; + headerText = "Remove an object of type "+objectType+" from the List "+fieldName+endLine+getParentObject()->getDoc(); + break; + case CodeAccessorMethod::SET: + methodName = "set" + Codegen_Utils::capitalizeFirstLetter(fieldName); + methodReturnType = "void"; + methodParams = fieldType + " value "; + headerText = "Set the value of "+fieldName+endLine+getParentObject()->getDoc()+endLine; + break; + default: + // do nothing..no idea what this is + kWarning()<<"Warning: cant generate JavaCodeAccessorMethod for type: "<<getType()<<endl; + break; + } + + // set header once. + if(getComment()->getText().isEmpty()) + getComment()->setText(headerText); + + // set start/end method text + setStartMethodText(strVis+' '+methodReturnType+' '+methodName+" ( "+methodParams+" ) {"); + setEndMethodText("}"); + +} + +void JavaCodeAccessorMethod::update() +{ + updateMethodDeclaration(); + updateContent(); +} + +#include "javacodeaccessormethod.moc" diff --git a/umbrello/umbrello/codegenerators/javacodeaccessormethod.h b/umbrello/umbrello/codegenerators/javacodeaccessormethod.h new file mode 100644 index 00000000..5a109b59 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodeaccessormethod.h @@ -0,0 +1,65 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Thu Oct 2 2003 + */ + +#ifndef JAVACODEACCESSORMETHOD_H +#define JAVACODEACCESSORMETHOD_H + +#include <qstring.h> + +#include "../codeaccessormethod.h" + +class CodeClassField; + +class JavaCodeAccessorMethod : public CodeAccessorMethod +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructor + */ + JavaCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type); + + /** + * Empty Destructor + */ + virtual ~JavaCodeAccessorMethod ( ); + + /** + * Must be called before this object is usable + */ + void update(); + +protected: + + /** set attributes of the node that represents this class + * in the XMI document. + */ + virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement); + + /** set the class attributes of this object from + * the passed element node. + */ + virtual void setAttributesFromNode ( QDomElement & element); + + virtual void updateMethodDeclaration(); + virtual void updateContent(); + +}; + +#endif // JAVACODEACCESSORMETHOD_H diff --git a/umbrello/umbrello/codegenerators/javacodeclassfield.cpp b/umbrello/umbrello/codegenerators/javacodeclassfield.cpp new file mode 100644 index 00000000..627b9b3e --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodeclassfield.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + * * + * 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 : Mon Jun 30 2003 + */ + +// own header +#include "javacodeclassfield.h" + +// qt/kde includes +#include <qregexp.h> +#include <kdebug.h> + +// local includes +#include "javacodecomment.h" +#include "javacodegenerator.h" + +#include "../attribute.h" +#include "../umlobject.h" +#include "../umlrole.h" +#include "../uml.h" + +// #include "javacodeaccessormethod.h" +#include "javaclassifiercodedocument.h" + +// Constructors/Destructors +// + +JavaCodeClassField::JavaCodeClassField (ClassifierCodeDocument * parentDoc, UMLRole * role) + : CodeClassField(parentDoc, role) +{ + +} + +JavaCodeClassField::JavaCodeClassField (ClassifierCodeDocument * parentDoc, UMLAttribute * attrib) + : CodeClassField(parentDoc, attrib) +{ + +} + +JavaCodeClassField::~JavaCodeClassField ( ) { } + +// +// Methods +// + +// Other methods +// + +QString JavaCodeClassField::getFieldName() { + if (parentIsAttribute()) + { + UMLAttribute * at = (UMLAttribute*) getParentObject(); + return cleanName(at->getName()); + } + else + { + UMLRole * role = (UMLRole*) getParentObject(); + QString roleName = role->getName(); + if(fieldIsSingleValue()) { + return roleName.replace(0, 1, roleName.left(1).lower()); + } else { + return roleName.lower() + "Vector"; + } + } +} + + +QString JavaCodeClassField::getInitialValue() { + + if (parentIsAttribute()) + { + UMLAttribute * at = dynamic_cast<UMLAttribute*>( getParentObject() ); + if (at) { + return fixInitialStringDeclValue(at->getInitialValue(), getTypeName()); + } else { + kError() << "JavaodeClassField::getInitialValue: parent object is not a UMLAttribute" + << endl; + return ""; + } + return fixInitialStringDeclValue(at->getInitialValue(), getTypeName()); + } + else + { + if(fieldIsSingleValue()) { + // FIX : IF the multiplicity is "1" then we should init a new object here, if its 0 or 1, + // then we can just return 'empty' string (minor problem). + return QString(""); + } else { + return " new "+JavaCodeGenerator::getListFieldClassName()+"( )"; + } + } + +} + +QString JavaCodeClassField::getTypeName ( ) +{ + return JavaCodeGenerator::fixTypeName(CodeClassField::getTypeName()); +} + +#include "javacodeclassfield.moc" diff --git a/umbrello/umbrello/codegenerators/javacodeclassfield.h b/umbrello/umbrello/codegenerators/javacodeclassfield.h new file mode 100644 index 00000000..5ed1cea4 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodeclassfield.h @@ -0,0 +1,59 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Jun 30 2003 + */ + + + +#ifndef JAVACODECLASSFIELD_H +#define JAVACODECLASSFIELD_H + +#include <qstring.h> + +#include "../codeclassfield.h" + +class ClassifierCodeDocument; + +class JavaCodeClassField : public CodeClassField +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructors + */ + JavaCodeClassField (ClassifierCodeDocument * parentDoc, UMLRole * role); + JavaCodeClassField (ClassifierCodeDocument * parentDoc, UMLAttribute * attrib); + + /** + * Empty Destructor + */ + virtual ~JavaCodeClassField ( ); + + QString getFieldType(); + QString getFieldName(); + QString getInitialValue(); + + QString getTypeName ( ); +protected: + +private: + + // void initDeclCodeBlock (); + +}; + +#endif // JAVACODECLASSFIELD_H diff --git a/umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.cpp b/umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.cpp new file mode 100644 index 00000000..87ebf78a --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.cpp @@ -0,0 +1,118 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Fri Jul 25 2003 + */ + +#include "javacodeclassfielddeclarationblock.h" + +#include "javacodeclassfield.h" +#include "javaclassifiercodedocument.h" +#include "javacodegenerationpolicy.h" +#include "../codegenerator.h" +#include "../classifier.h" +#include "../umlrole.h" +#include "../uml.h" + +// Constructors/Destructors +// + +JavaCodeClassFieldDeclarationBlock::JavaCodeClassFieldDeclarationBlock ( CodeClassField * parent ) + : CodeClassFieldDeclarationBlock ( parent ) +{ + setOverallIndentationLevel(1); + updateContent(); +} + +JavaCodeClassFieldDeclarationBlock::~JavaCodeClassFieldDeclarationBlock ( ) { } + +// +// Methods +// + + + +// Other methods +// + +/** + */ +void JavaCodeClassFieldDeclarationBlock::updateContent( ) +{ + + CodeClassField * cf = getParentClassField(); + ClassifierCodeDocument * doc = cf->getParentDocument(); + JavaCodeClassField * jcf = dynamic_cast<JavaCodeClassField*>(cf); + JavaClassifierCodeDocument* jdoc = dynamic_cast<JavaClassifierCodeDocument*>(doc); + CodeGenerationPolicy * commonpolicy = UMLApp::app()->getCommonPolicy(); + + CodeGenerationPolicy::ScopePolicy scopePolicy = commonpolicy->getAssociationFieldScope(); + + // Set the comment + QString notes = getParentObject()->getDoc(); + getComment()->setText(notes); + + // Set the body + QString staticValue = getParentObject()->getStatic() ? "static " : ""; + QString scopeStr = jdoc->scopeToJavaDecl(getParentObject()->getVisibility()); + + // IF this is from an association, then scope taken as appropriate to policy + if(!jcf->parentIsAttribute()) + { + switch (scopePolicy) { + case CodeGenerationPolicy::Public: + case CodeGenerationPolicy::Private: + case CodeGenerationPolicy::Protected: + scopeStr = jdoc->scopeToJavaDecl((Uml::Visibility::Value) scopePolicy); + break; + default: + case CodeGenerationPolicy::FromParent: + // do nothing here... will leave as from parent object + break; + } + } + + QString typeName = jcf->getTypeName(); + QString fieldName = jcf->getFieldName(); + QString initialV = jcf->getInitialValue(); + + if (!cf->parentIsAttribute() && !cf->fieldIsSingleValue()) + typeName = "List"; + + QString body = staticValue+scopeStr+' '+typeName+' '+fieldName; + if (!initialV.isEmpty()) + body.append(" = " + initialV); + else if (!cf->parentIsAttribute()) + { + UMLRole * role = dynamic_cast<UMLRole*>(cf->getParentObject()); + if (role->getObject()->getBaseType() == Uml::ot_Interface) + { + // do nothing.. can't instanciate an interface + } else { + + // FIX?: IF a constructor method exists in the classifiercodedoc + // of the parent Object, then we can use that instead (if its empty). + if(cf->fieldIsSingleValue()) + { + if(!typeName.isEmpty()) + body.append(" = new " + typeName + " ( )"); + } else + body.append(" = new Vector ( )"); + } + } + + setText(body+';'); + +} + +#include "javacodeclassfielddeclarationblock.moc" diff --git a/umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.h b/umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.h new file mode 100644 index 00000000..8166fced --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodeclassfielddeclarationblock.h @@ -0,0 +1,51 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Fri Jul 25 2003 + */ + +#ifndef JAVACODECLASSFIELDDECLARATIONBLOCK_H +#define JAVACODECLASSFIELDDECLARATIONBLOCK_H + +#include <qstring.h> + +#include "../codeclassfielddeclarationblock.h" + +class JavaCodeClassFieldDeclarationBlock : public CodeClassFieldDeclarationBlock +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructor + */ + JavaCodeClassFieldDeclarationBlock ( CodeClassField * parent ); + + /** + * Empty Destructor + */ + virtual ~JavaCodeClassFieldDeclarationBlock ( ); + +protected: + + // this will be called by syncToParent whenever the parent object is "modified" + void updateContent ( ); + +private: + + +}; + +#endif // JAVACODECLASSFIELDDECLARATIONBLOCK_H diff --git a/umbrello/umbrello/codegenerators/javacodecomment.cpp b/umbrello/umbrello/codegenerators/javacodecomment.cpp new file mode 100644 index 00000000..bec0e87b --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodecomment.cpp @@ -0,0 +1,84 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Jun 23 2003 + */ + +#include "javacodecomment.h" +#include <qregexp.h> + +// Constructors/Destructors +// + +JavaCodeComment::JavaCodeComment ( CodeDocument * doc, const QString & text ) + : CodeComment (doc, text) +{ + +} + +JavaCodeComment::~JavaCodeComment ( ) { } + +// +// Methods +// + + +// Accessor methods +// + + +// Public attribute accessor methods +// + +// Other methods +// + +QString JavaCodeComment::getNewEditorLine ( int amount ) { + QString line = getIndentationString(amount) + "// "; + return line; +} + +/** UnFormat a long text string. Typically, this means removing + * the indentaion (linePrefix) and/or newline chars from each line. + */ +QString JavaCodeComment::unformatText ( const QString & text , const QString & indent) +{ + + // remove leading or trailing comment stuff + QString mytext = TextBlock::unformatText(text, indent); + + // now leading slashes + mytext.remove(QRegExp("^\\/\\/\\s*")); + return mytext; +} + +/** + * @return QString + */ +QString JavaCodeComment::toString ( ) +{ + + QString output = ""; + + // simple output method + if(getWriteOutText()) + { + QString indent = getIndentationString(); + QString endLine = getNewLineEndingChars(); + output.append(formatMultiLineText (getText(), indent +"// ", endLine)); + } + + return output; +} + + +#include "javacodecomment.moc" diff --git a/umbrello/umbrello/codegenerators/javacodecomment.h b/umbrello/umbrello/codegenerators/javacodecomment.h new file mode 100644 index 00000000..1f9b1d8d --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodecomment.h @@ -0,0 +1,77 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Jun 23 2003 + */ + + + +#ifndef JAVACODECOMMENT_H +#define JAVACODECOMMENT_H + +#include <qstring.h> +#include "../codecomment.h" + +/** + * class JavaCodeComment + * A Java code comment. There is only a single styles of comments: + * these are simply started with double slash sequence and no terminating + * characters + */ + +class JavaCodeComment : virtual public CodeComment +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + + /** + * Constructors + */ + explicit JavaCodeComment ( CodeDocument * doc, const QString & text = ""); + + /** + * Empty Destructor + */ + virtual ~JavaCodeComment ( ); + + // Public attributes + // + + + // other + + /** + * @return QString + */ + QString toString ( ); + + /** UnFormat a long text string. Typically, this means removing + * the indentaion (linePrefix) and/or newline chars from each line. + */ + virtual QString unformatText ( const QString & text, const QString & indent = "" ); + + /** a special version here because we want to not only indent + * the new line, but to add the "//" sequence as well. + */ + virtual QString getNewEditorLine ( int amount ); + +protected: + +private: + +}; + +#endif // JAVACODECOMMENT_H diff --git a/umbrello/umbrello/codegenerators/javacodedocumentation.cpp b/umbrello/umbrello/codegenerators/javacodedocumentation.cpp new file mode 100644 index 00000000..e831d885 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodedocumentation.cpp @@ -0,0 +1,143 @@ +/*************************************************************************** + * * + * 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 : Mon Jun 23 2003 + */ + +// own header +#include "javacodedocumentation.h" + +// qt/kde includes +#include <qregexp.h> +#include <kdebug.h> + +// local includes +#include "javaclassifiercodedocument.h" +#include "../codegenerationpolicy.h" +#include "../uml.h" + +// Constructors/Destructors +// + +JavaCodeDocumentation::JavaCodeDocumentation ( JavaClassifierCodeDocument * doc, const QString & text ) + : CodeComment(doc, text) +{ + +} + +JavaCodeDocumentation::~JavaCodeDocumentation ( ) { } + +// +// Methods +// + + +// Accessor methods +// + +// Other methods +// + +/** + * Save the XMI representation of this object + */ +void JavaCodeDocumentation::saveToXMI ( QDomDocument & doc, QDomElement & root ) { + QDomElement blockElement = doc.createElement( "javacodedocumentation" ); + setAttributesOnNode(doc, blockElement); // as we added no additional fields to this class we may + // just use parent TextBlock method + root.appendChild( blockElement ); +} + +/** + * @return QString + */ +QString JavaCodeDocumentation::toString ( ) +{ + + QString output = ""; + + // simple output method + if(getWriteOutText()) + { + bool useDoubleDashOutput = true; + + // need to figure out output type from java policy + CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy(); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + useDoubleDashOutput = false; + + QString indent = getIndentationString(); + QString endLine = getNewLineEndingChars(); + QString body = getText(); + if(useDoubleDashOutput) + { + if(!body.isEmpty()) + output.append(formatMultiLineText (body, indent +"// ", endLine)); + } else { + output.append(indent+"/**"+endLine); + output.append(formatMultiLineText (body, indent +" * ", endLine)); + output.append(indent+" */"+endLine); + } + } + + return output; +} + +QString JavaCodeDocumentation::getNewEditorLine ( int amount ) +{ + CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy(); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + return getIndentationString(amount) + " * "; + else + return getIndentationString(amount) + "// "; +} + +int JavaCodeDocumentation::firstEditableLine() { + CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy(); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + return 1; + return 0; +} + +int JavaCodeDocumentation::lastEditableLine() { + CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy(); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + { + return -1; // very last line is NOT editable + } + return 0; +} + +/** UnFormat a long text string. Typically, this means removing + * the indentaion (linePrefix) and/or newline chars from each line. + */ +QString JavaCodeDocumentation::unformatText ( const QString & text , const QString & indent) +{ + + QString mytext = TextBlock::unformatText(text, indent); + CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy(); + // remove leading or trailing comment stuff + mytext.remove(QRegExp('^'+indent)); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + { + mytext.remove(QRegExp("^\\/\\*\\*\\s*\n?")); + mytext.remove(QRegExp("\\s*\\*\\/\\s*\n?$")); + mytext.remove(QRegExp("^\\s*\\*\\s*")); + } else + mytext.remove(QRegExp("^\\/\\/\\s*")); + + return mytext; +} + + +#include "javacodedocumentation.moc" diff --git a/umbrello/umbrello/codegenerators/javacodedocumentation.h b/umbrello/umbrello/codegenerators/javacodedocumentation.h new file mode 100644 index 00000000..246b87a6 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodedocumentation.h @@ -0,0 +1,95 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Jun 23 2003 + */ + + + +#ifndef JAVACODEDOCUMENTATION_H +#define JAVACODEDOCUMENTATION_H + +#include <qstring.h> +#include "../codecomment.h" + +class JavaClassifierCodeDocument; + +/** + * class JavaCodeDocumentation + * A Java code comment. There is only a single styles of comments: + * these are simply started with double slash sequence and no terminating + * characters + */ + +class JavaCodeDocumentation : virtual public CodeComment +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + + /** + * Constructors + */ + explicit JavaCodeDocumentation ( JavaClassifierCodeDocument * doc, const QString & text = ""); + + /** + * Empty Destructor + */ + virtual ~JavaCodeDocumentation ( ); + + // Public attributes + // + + // Other + // + + /** + * Save the XMI representation of this object + */ + virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ); + + /** + * @return QString + */ + QString toString ( ); + + /** UnFormat a long text string. Typically, this means removing + * the indentaion (linePrefix) and/or newline chars from each line. + */ + virtual QString unformatText ( const QString & text, const QString & indent = "" ); + + /** a special version here because we want to not only indent + * the new line, but to add the " * " sequence as well. + */ + virtual QString getNewEditorLine ( int amount ); + + /** Ush. These are terrifically bad and must one day go away. + * Both methods indicate the range of lines in this textblock + * which may be edited by the codeeditor (assuming that any are + * actually editable). The default case is no lines are editable. + * The line numbering starts with '0' and a '-1' means no line + * qualifies. + */ + virtual int firstEditableLine(); + virtual int lastEditableLine(); + + +protected: + +private: + +}; + +#endif // JAVACODEDOCUMENTATION_H diff --git a/umbrello/umbrello/codegenerators/javacodegenerationformbase.ui b/umbrello/umbrello/codegenerators/javacodegenerationformbase.ui new file mode 100644 index 00000000..cd39611a --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodegenerationformbase.ui @@ -0,0 +1,277 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>JavaCodeGenerationFormBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>Form1</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>462</width> + <height>376</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="3" column="0"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Project Generation</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_makeANTDocumentCheckBox</cstring> + </property> + <property name="text"> + <string>Create ANT build document</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QGroupBox" row="2" column="0"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Auto-Generate Methods</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>m_generateConstructors</cstring> + </property> + <property name="text"> + <string>Empty constructor methods</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>m_generateAssocAccessors</cstring> + </property> + <property name="text"> + <string>Association accessor methods</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>m_generateAttribAccessors</cstring> + </property> + <property name="text"> + <string>Attribute accessor methods</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QComboBox" row="0" column="1"> + <item> + <property name="text"> + <string>Public</string> + </property> + </item> + <item> + <property name="text"> + <string>Private</string> + </property> + </item> + <item> + <property name="text"> + <string>Protected</string> + </property> + </item> + <item> + <property name="text"> + <string>From Parent Object</string> + </property> + </item> + <property name="name"> + <cstring>m_accessorScopeCB</cstring> + </property> + <property name="currentItem"> + <number>3</number> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string>Default attribute accessor scope:</string> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget" row="2" column="0"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1_3_2</cstring> + </property> + <property name="text"> + <string>Default association field scope:</string> + </property> + </widget> + <widget class="QComboBox" row="0" column="1"> + <item> + <property name="text"> + <string>Public</string> + </property> + </item> + <item> + <property name="text"> + <string>Private</string> + </property> + </item> + <item> + <property name="text"> + <string>Protected</string> + </property> + </item> + <item> + <property name="text"> + <string>From Parent Role</string> + </property> + </item> + <property name="name"> + <cstring>m_assocFieldScopeCB</cstring> + </property> + <property name="currentItem"> + <number>3</number> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Documentation</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Style:</string> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Slash-Slash (//)</string> + </property> + </item> + <item> + <property name="text"> + <string>Slash-Star (/** */)</string> + </property> + </item> + <property name="name"> + <cstring>m_SelectCommentStyle</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><p align="center">Java Code Generation</p></string> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/umbrello/umbrello/codegenerators/javacodegenerationpolicy.cpp b/umbrello/umbrello/codegenerators/javacodegenerationpolicy.cpp new file mode 100644 index 00000000..2dcc834e --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodegenerationpolicy.cpp @@ -0,0 +1,188 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Jun 23 2003 + */ + +// own header +#include "javacodegenerationpolicy.h" +// qt/kde includes +#include <kconfig.h> +// app includes +#include "javacodegenerationpolicypage.h" +#include "javacodegenerator.h" +#include "../uml.h" + +const bool JavaCodeGenerationPolicy::DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS = true; +const bool JavaCodeGenerationPolicy::DEFAULT_AUTO_GEN_ASSOC_ACCESSORS = true; + +// Constructors/Destructors +/* + +JavaCodeGenerationPolicy::JavaCodeGenerationPolicy(CodeGenerationPolicy *defaults) + : CodeGenerationPolicy(defaults) +{ + init(); + setDefaults(defaults,false); +} + */ + +JavaCodeGenerationPolicy::JavaCodeGenerationPolicy(KConfig *config) + // : CodeGenerationPolicy(config) +{ + init(); + setDefaults(config,false); +} + +JavaCodeGenerationPolicy::~JavaCodeGenerationPolicy ( ) { } + +// +// Methods +// + +// Accessor methods +// + +// Public attribute accessor methods +// + +/** + * Set the value of m_autoGenerateAttribAccessors + * @param new_var the new value + */ +void JavaCodeGenerationPolicy::setAutoGenerateAttribAccessors( bool var ) { + m_autoGenerateAttribAccessors = var; + m_commonPolicy->emitModifiedCodeContentSig(); +} + +/** + * Set the value of m_autoGenerateAssocAccessors + * @param new_var the new value + */ +void JavaCodeGenerationPolicy::setAutoGenerateAssocAccessors( bool var ) { + m_autoGenerateAssocAccessors = var; + m_commonPolicy->emitModifiedCodeContentSig(); +} + +/** + * Get the value of m_autoGenerateAttribAccessors + * @return the value of m_autoGenerateAttribAccessors + */ +bool JavaCodeGenerationPolicy::getAutoGenerateAttribAccessors( ){ + return m_autoGenerateAttribAccessors; +} + +/** + * Get the value of m_autoGenerateAssocAccessors + * @return the value of m_autoGenerateAssocAccessors + */ +bool JavaCodeGenerationPolicy::getAutoGenerateAssocAccessors( ){ + return m_autoGenerateAssocAccessors; +} + +// Other methods +// + +void JavaCodeGenerationPolicy::writeConfig ( KConfig * config ) +{ + + // write ONLY the Java specific stuff + config->setGroup("Java Code Generation"); + + config->writeEntry("autoGenAccessors",getAutoGenerateAttribAccessors()); + config->writeEntry("autoGenAssocAccessors",getAutoGenerateAssocAccessors()); + + CodeGenerator *codegen = UMLApp::app()->getGenerator(); + JavaCodeGenerator *javacodegen = dynamic_cast<JavaCodeGenerator*>(codegen); + if (javacodegen) + config->writeEntry("buildANTDocument", javacodegen->getCreateANTBuildFile()); + +} + +void JavaCodeGenerationPolicy::setDefaults ( CodeGenPolicyExt * clone, bool emitUpdateSignal ) +{ + + JavaCodeGenerationPolicy * jclone; + if (!clone) + return; + + // NOW block signals for java param setting + blockSignals(true); // we need to do this because otherwise most of these + // settors below will each send the modifiedCodeContent() signal + // needlessly (we can just make one call at the end). + + + // now do java-specific stuff IF our clone is also a JavaCodeGenerationPolicy object + if((jclone = dynamic_cast<JavaCodeGenerationPolicy*>(clone))) + { + setAutoGenerateAttribAccessors(jclone->getAutoGenerateAttribAccessors()); + setAutoGenerateAssocAccessors(jclone->getAutoGenerateAssocAccessors()); + } + + blockSignals(false); // "as you were citizen" + + if(emitUpdateSignal) + m_commonPolicy->emitModifiedCodeContentSig(); + +} + +void JavaCodeGenerationPolicy::setDefaults( KConfig * config, bool emitUpdateSignal ) +{ + + if(!config) + return; + + // call method at the common policy to init default stuff + m_commonPolicy->setDefaults(config, false); + + // NOW block signals (because call to super-class method will leave value at "true") + blockSignals(true); // we need to do this because otherwise most of these + // settors below will each send the modifiedCodeContent() signal + // needlessly (we can just make one call at the end). + + // now do java specific stuff + config -> setGroup("Java Code Generation"); + + setAutoGenerateAttribAccessors(config->readBoolEntry("autoGenAccessors",DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS)); + setAutoGenerateAssocAccessors(config->readBoolEntry("autoGenAssocAccessors",DEFAULT_AUTO_GEN_ASSOC_ACCESSORS)); + + CodeGenerator *codegen = UMLApp::app()->getGenerator(); + JavaCodeGenerator *javacodegen = dynamic_cast<JavaCodeGenerator*>(codegen); + if (javacodegen) { + bool mkant = config->readBoolEntry("buildANTDocument", JavaCodeGenerator::DEFAULT_BUILD_ANT_DOC); + javacodegen->setCreateANTBuildFile(mkant); + } + + blockSignals(false); // "as you were citizen" + + if(emitUpdateSignal) + m_commonPolicy->emitModifiedCodeContentSig(); +} + + +/** + * Create a new dialog interface for this object. + * @return dialog object + */ +CodeGenerationPolicyPage * JavaCodeGenerationPolicy::createPage ( QWidget *parent, const char *name ) { + return new JavaCodeGenerationPolicyPage ( parent, name, this ); +} + +void JavaCodeGenerationPolicy::init() { + m_commonPolicy = UMLApp::app()->getCommonPolicy(); + m_autoGenerateAttribAccessors = DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS; + m_autoGenerateAssocAccessors = DEFAULT_AUTO_GEN_ASSOC_ACCESSORS; +} + + +#include "javacodegenerationpolicy.moc" diff --git a/umbrello/umbrello/codegenerators/javacodegenerationpolicy.h b/umbrello/umbrello/codegenerators/javacodegenerationpolicy.h new file mode 100644 index 00000000..2a40cb57 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodegenerationpolicy.h @@ -0,0 +1,116 @@ +/*************************************************************************** + * * + * 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) 2003-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Jun 23 2003 + */ + +#ifndef JAVACODEGENERATIONPOLICY_H +#define JAVACODEGENERATIONPOLICY_H + +#include <qstring.h> +#include "codegenpolicyext.h" +#include "../codegenerationpolicy.h" + +class KConfig; +class CodeGenerationPolicyPage; + +class JavaCodeGenerationPolicy : public CodeGenPolicyExt +{ + Q_OBJECT +public: + + static const bool DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS; + static const bool DEFAULT_AUTO_GEN_ASSOC_ACCESSORS; + + // Constructors/Destructors + // + + /** + * Constructors + */ + //JavaCodeGenerationPolicy (CodeGenerationPolicy * defaults = 0); + JavaCodeGenerationPolicy (KConfig * config = 0); + + /** + * Empty Destructor + */ + virtual ~JavaCodeGenerationPolicy ( ); + + // Public attributes + // + + + // Public attribute accessor methods + // + + /** + * Set the value of m_autoGenerateAttribAccessors + * @param var the new value + */ + void setAutoGenerateAttribAccessors ( bool var ); + + /** + * Get the value of m_autoGenerateAttribAccessors + * @return value the boolean value of m_autoGenerateAttribAccessors + */ + bool getAutoGenerateAttribAccessors( ); + + /** + * Set the value of m_autoGenerateAssocAccessors + * @param var the new value + */ + void setAutoGenerateAssocAccessors ( bool var ); + + /** + * Get the value of m_autoGenerateAssocAccessors + * @return value the boolean value of m_autoGenerateAssocAccessors + */ + bool getAutoGenerateAssocAccessors( ); + + /** + * set the defaults for this code generator from the passed generator. + */ + virtual void setDefaults (CodeGenPolicyExt * defaults, bool emitUpdateSignal = true); + + /** + * set the defaults from a config file for this code generator from the passed KConfig pointer. + */ + virtual void setDefaults(KConfig * config, bool emitUpdateSignal = true); + + /** + * write Default params to passed KConfig pointer. + */ + virtual void writeConfig (KConfig * config); + + /** + * Create a new dialog interface for this object. + * @return dialog object + */ + CodeGenerationPolicyPage * createPage ( QWidget *parent = 0, const char * name = 0); + +protected: + + /** + */ + void init ( ); + +private: + + CodeGenerationPolicy *m_commonPolicy; + bool m_autoGenerateConstructors; + bool m_autoGenerateAttribAccessors; + bool m_autoGenerateAssocAccessors; + +}; + +#endif // JAVACODEGENERATIONPOLICY_H diff --git a/umbrello/umbrello/codegenerators/javacodegenerationpolicypage.cpp b/umbrello/umbrello/codegenerators/javacodegenerationpolicypage.cpp new file mode 100644 index 00000000..fd6d2ae3 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodegenerationpolicypage.cpp @@ -0,0 +1,84 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Wed Jul 30 2003 + */ + +// own header +#include "javacodegenerationpolicypage.h" +// qt/kde includes +#include <qlabel.h> +#include <qcombobox.h> +#include <qcheckbox.h> +#include <kdebug.h> +#include <klocale.h> +// app includes +#include "javacodegenerationformbase.h" +#include "../uml.h" + +JavaCodeGenerationPolicyPage::JavaCodeGenerationPolicyPage( QWidget *parent, const char *name, JavaCodeGenerationPolicy * policy ) + : CodeGenerationPolicyPage(parent, name, policy) +{ + CodeGenerationPolicy *commonPolicy = UMLApp::app()->getCommonPolicy(); + form = new JavaCodeGenerationFormBase(this); + form->m_SelectCommentStyle->setCurrentItem((int)(commonPolicy->getCommentStyle())); + form->m_generateConstructors->setChecked(commonPolicy->getAutoGenerateConstructors()); + form->m_generateAttribAccessors->setChecked(policy->getAutoGenerateAttribAccessors()); + form->m_generateAssocAccessors->setChecked(policy->getAutoGenerateAssocAccessors()); + form->m_accessorScopeCB->setCurrentItem(commonPolicy->getAttributeAccessorScope() - 200); + form->m_assocFieldScopeCB->setCurrentItem(commonPolicy->getAssociationFieldScope() - 200); + + /** + * @todo unclean - CreateANTBuildFile attribute should be in java policy + CodeGenerator *codegen = UMLApp::app()->getGenerator(); + JavaCodeGenerator *javacodegen = dynamic_cast<JavaCodeGenerator*>(codegen); + if (javacodegen) + form->m_makeANTDocumentCheckBox->setChecked(javacodegen->getCreateANTBuildFile()); + */ +} + +JavaCodeGenerationPolicyPage::~JavaCodeGenerationPolicyPage() +{ +} + +void JavaCodeGenerationPolicyPage::apply() +{ + CodeGenerationPolicy *commonPolicy = UMLApp::app()->getCommonPolicy(); + JavaCodeGenerationPolicy * parent = (JavaCodeGenerationPolicy*) m_parentPolicy; + + // block signals so we don't cause too many update content calls to code documents + commonPolicy->blockSignals(true); + + commonPolicy->setCommentStyle((CodeGenerationPolicy::CommentStyle ) form->m_SelectCommentStyle->currentItem()); + commonPolicy->setAttributeAccessorScope((CodeGenerationPolicy::ScopePolicy) (form->m_accessorScopeCB->currentItem()+200)); + commonPolicy->setAssociationFieldScope((CodeGenerationPolicy::ScopePolicy) (form->m_assocFieldScopeCB->currentItem()+200)); + commonPolicy->setAutoGenerateConstructors(form->m_generateConstructors->isChecked()); + parent->setAutoGenerateAttribAccessors(form->m_generateAttribAccessors->isChecked()); + parent->setAutoGenerateAssocAccessors(form->m_generateAssocAccessors->isChecked()); + + /** + * @todo unclean - CreateANTBuildFile attribute should be in java policy + CodeGenerator *codegen = UMLApp::app()->getGenerator(); + JavaCodeGenerator *javacodegen = dynamic_cast<JavaCodeGenerator*>(codegen); + if (javacodegen) + javacodegen->setCreateANTBuildFile(form->m_makeANTDocumentCheckBox->isChecked()); + */ + commonPolicy->blockSignals(false); + + // now send out modified code content signal + commonPolicy->emitModifiedCodeContentSig(); + +} + + +#include "javacodegenerationpolicypage.moc" diff --git a/umbrello/umbrello/codegenerators/javacodegenerationpolicypage.h b/umbrello/umbrello/codegenerators/javacodegenerationpolicypage.h new file mode 100644 index 00000000..3b6f85e0 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodegenerationpolicypage.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * * + * 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) 2003-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Wed Jul 30 2003 + */ + +#ifndef JAVACODEGENERATIONPOLICYPAGE_H +#define JAVACODEGENERATIONPOLICYPAGE_H + +#include "../dialogs/codegenerationpolicypage.h" +#include "javacodegenerationformbase.h" + +#include "javacodegenerationpolicy.h" + +/** + * @author Brian Thomas + */ + +class JavaCodeGenerationPolicyPage : public CodeGenerationPolicyPage { + Q_OBJECT +public: + + explicit JavaCodeGenerationPolicyPage (QWidget *parent=0, const char *name=0, JavaCodeGenerationPolicy * policy = 0); + + virtual ~JavaCodeGenerationPolicyPage(); + +protected: + + JavaCodeGenerationFormBase * form; + +public slots: + + void apply(); + +}; + +#endif + diff --git a/umbrello/umbrello/codegenerators/javacodegenerator.cpp b/umbrello/umbrello/codegenerators/javacodegenerator.cpp new file mode 100644 index 00000000..167804af --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodegenerator.cpp @@ -0,0 +1,339 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Thu Jun 19 2003 + */ + +// own header +#include "javacodegenerator.h" + +// qt/kde includes +#include <qregexp.h> +#include <kconfig.h> +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> + +// local includes +#include "javacodecomment.h" +#include "codeviewerdialog.h" +#include "../uml.h" + +const bool JavaCodeGenerator::DEFAULT_BUILD_ANT_DOC = false; + +// Constructors/Destructors +// + +JavaCodeGenerator::JavaCodeGenerator (QDomElement & elem) + : CodeGenerator(elem) +{ + init(); +} + +JavaCodeGenerator::JavaCodeGenerator () +{ + init(); +} + +JavaCodeGenerator::~JavaCodeGenerator ( ) { } + +// +// Methods +// + +// Accessor methods +// + +// return our language +Uml::Programming_Language JavaCodeGenerator::getLanguage() { + return Uml::pl_Java; +} + +/** + * Set the value of m_createANTBuildFile + * @param new_var the new value of m_createANTBuildFile + */ +void JavaCodeGenerator::setCreateANTBuildFile ( bool buildIt) { + m_createANTBuildFile = buildIt; + CodeDocument * antDoc = findCodeDocumentByID("ANTDOC"); + if (antDoc) + antDoc->setWriteOutCode(buildIt); +} + +/** + * Get the value of m_createANTBuildFile + * @return the value of m_createANTBuildFile + */ +bool JavaCodeGenerator::getCreateANTBuildFile ( ) { + return m_createANTBuildFile; +} + +// In the Java version, we make the ANT build file also available. +CodeViewerDialog * JavaCodeGenerator::getCodeViewerDialog ( QWidget* parent, CodeDocument *doc, + Settings::CodeViewerState state) +{ + CodeViewerDialog *dialog = new CodeViewerDialog(parent, doc, state); + if(getCreateANTBuildFile()) + dialog->addCodeDocument(findCodeDocumentByID("ANTDOC")); + return dialog; +} + + +JavaCodeGenerationPolicy * JavaCodeGenerator::getJavaPolicy() { + return dynamic_cast<JavaCodeGenerationPolicy*>(UMLApp::app()->getPolicyExt()); +} + +bool JavaCodeGenerator::getAutoGenerateAttribAccessors ( ) +{ + return getJavaPolicy()->getAutoGenerateAttribAccessors (); +} + +bool JavaCodeGenerator::getAutoGenerateAssocAccessors ( ) +{ + return getJavaPolicy()->getAutoGenerateAssocAccessors (); +} + +QString JavaCodeGenerator::getListFieldClassName () { + return QString("Vector"); +} + +// Other methods +// + +// 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 JavaCodeGenerator::fixTypeName(const QString &string) +{ + if (string.isEmpty() || string.contains(QRegExp("^\\s+$"))) + return "void"; + if (string == "string") + return "String"; + if (string == "bool") + return "boolean"; + return cleanName(string); +} + +/** + * @return JavaANTCodeDocument + */ +JavaANTCodeDocument * JavaCodeGenerator::newANTCodeDocument ( ) { + return new JavaANTCodeDocument(); +} + +/** + * @return ClassifierCodeDocument + * @param classifier + */ +CodeDocument * JavaCodeGenerator::newClassifierCodeDocument ( UMLClassifier * c) +{ + JavaClassifierCodeDocument * doc = new JavaClassifierCodeDocument(c); + doc->initCodeClassFields(); + return doc; +} + +void JavaCodeGenerator::init() { + // load Classifier documents from parent document + //initFromParentDocument(); + + // add in an ANT document + JavaANTCodeDocument * buildDoc = newANTCodeDocument( ); + addCodeDocument(buildDoc); + + // set our 'writeout' policy for that code document + setCreateANTBuildFile(DEFAULT_BUILD_ANT_DOC); +} + +QStringList JavaCodeGenerator::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; +} + +const QStringList JavaCodeGenerator::reservedKeywords() const { + + static QStringList keywords; + + if (keywords.isEmpty()) { + keywords << "abstract" + << "AbstractMethodError" + << "ArithmeticException" + << "ArrayIndexOutOfBoundsException" + << "ArrayStoreException" + << "assert" + << "AssertionError" + << "auto" + << "boolean" + << "Boolean" + << "break" + << "byte" + << "Byte" + << "catch" + << "char" + << "Character" + << "CharSequence" + << "Class" + << "ClassCastException" + << "ClassCircularityError" + << "ClassFormatError" + << "ClassLoader" + << "ClassNotFoundException" + << "clone" + << "Cloneable" + << "CloneNotSupportedException" + << "Comparable" + << "Compiler" + << "const" + << "continue" + << "default" + << "delete" + << "do" + << "double" + << "Double" + << "else" + << "enum" + << "equals" + << "Error" + << "Exception" + << "ExceptionInInitializerError" + << "extends" + << "extern" + << "false" + << "final" + << "finalize" + << "finally" + << "float" + << "Float" + << "for" + << "friend" + << "getClass" + << "goto" + << "hashCode" + << "if" + << "IllegalAccessError" + << "IllegalAccessException" + << "IllegalArgumentException" + << "IllegalMonitorStateException" + << "IllegalStateException" + << "IllegalThreadStateException" + << "implements" + << "import" + << "IncompatibleClassChangeError" + << "IndexOutOfBoundsException" + << "InheritableThreadLocal" + << "inline" + << "instanceof" + << "InstantiationError" + << "InstantiationException" + << "int" + << "Integer" + << "interface" + << "InternalError" + << "InterruptedException" + << "LinkageError" + << "long" + << "Long" + << "Math" + << "native" + << "NegativeArraySizeException" + << "new" + << "nextgroup=javaUserLabelRef" + << "NoClassDefFoundError" + << "NoSuchFieldError" + << "NoSuchFieldException" + << "NoSuchMethodError" + << "NoSuchMethodException" + << "notify" + << "notifyAll" + << "null" + << "NullPointerException" + << "Number" + << "NumberFormatException" + << "Object" + << "operator" + << "OutOfMemoryError" + << "package" + << "Package" + << "private" + << "Process" + << "protected" + << "public" + << "redeclared" + << "register" + << "return" + << "Runnable" + << "Runtime" + << "RuntimeException" + << "RuntimePermission" + << "SecurityException" + << "SecurityManager" + << "serializable" + << "short" + << "Short" + << "signed" + << "sizeof" + << "skipwhite" + << "StackOverflowError" + << "StackTraceElement" + << "static" + << "strictfp" + << "StrictMath" + << "String" + << "StringBuffer" + << "StringIndexOutOfBoundsException" + << "struct" + << "super" + << "switch" + << "synchronized" + << "template" + << "this" + << "Thread" + << "ThreadDeath" + << "ThreadGroup" + << "ThreadLocal" + << "throw" + << "Throwable" + << "throws" + << "toString" + << "transient" + << "true" + << "try" + << "typedef" + << "union" + << "UnknownError" + << "UnsatisfiedLinkError" + << "unsigned" + << "UnsupportedClassVersionError" + << "UnsupportedOperationException" + << "VerifyError" + << "VirtualMachineError" + << "void" + << "Void" + << "volatile" + << "wait" + << "while"; + } + + return keywords; +} + +#include "javacodegenerator.moc" + diff --git a/umbrello/umbrello/codegenerators/javacodegenerator.h b/umbrello/umbrello/codegenerators/javacodegenerator.h new file mode 100644 index 00000000..29edb16f --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodegenerator.h @@ -0,0 +1,150 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Thu Jun 19 2003 + */ + + + +#ifndef JAVACODEGENERATOR_H +#define JAVACODEGENERATOR_H + +#include <qstring.h> +#include "../codeviewerstate.h" +#include "../codegenerator.h" +#include "../codeblockwithcomments.h" +#include "../umldoc.h" + +#include "classifierinfo.h" +#include "javaclassifiercodedocument.h" +#include "javaantcodedocument.h" + +#include "javacodegenerationpolicy.h" + +class CodeViewerDialog; + +class JavaCodeGenerator : public CodeGenerator +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + static const bool DEFAULT_BUILD_ANT_DOC; + + /** + * Empty Constructor + */ + JavaCodeGenerator (); + JavaCodeGenerator (QDomElement & element); + + /** + * Empty Destructor + */ + virtual ~JavaCodeGenerator ( ); + + // Public attributes + // + + + // Public attribute accessor methods + // + + + /** + * Set the value of m_createANTBuildFile + * @param new_var the new value of m_createANTBuildFile + */ + void setCreateANTBuildFile ( bool new_var ); + + /** + * Get the value of m_createANTBuildFile + * @return the value of m_createANTBuildFile + */ + bool getCreateANTBuildFile ( ); + + /** + * A utility method to get the javaCodeGenerationPolicy()->getAutoGenerateAttribAccessors() value. + */ + bool getAutoGenerateAttribAccessors( ); + + /** + * A utility method to get the javaCodeGenerationPolicy()->getAutoGenerateAssocAccessors() value. + */ + bool getAutoGenerateAssocAccessors( ); + + /** + * Get the list variable class name to use. For Java, we have set this to "Vector". + */ + static QString getListFieldClassName(); + + /** Get the editing dialog for this code document + */ + virtual CodeViewerDialog * getCodeViewerDialog( QWidget* parent, CodeDocument * doc, + Settings::CodeViewerState state); + + // Other methods + // + + /** + * Utility function for getting the java code generation policy. + */ + JavaCodeGenerationPolicy * getJavaPolicy(); + + /** + * @return ClassifierCodeDocument + * @param classifier + */ + CodeDocument * newClassifierCodeDocument (UMLClassifier * classifier); + + // return "Java" + Uml::Programming_Language getLanguage(); + + /** + * Adds Java's primitives as datatypes + */ + virtual QStringList defaultDatatypes(); + + /** + * 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". + */ + static QString fixTypeName(const QString &string); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +protected: + + /** create the codeblock that will represent the class declaration + * for this classifier + */ + CodeBlockWithComments * createClassDecl ( UMLClassifier *c, ClassifierInfo *info, JavaClassifierCodeDocument * doc); + + /** + * @return JavaANTCodeDocument + */ + JavaANTCodeDocument * newANTCodeDocument ( ); + +private: + + void init(); + + bool m_createANTBuildFile; +}; + +#endif // JAVACODEGENERATOR_H diff --git a/umbrello/umbrello/codegenerators/javacodeoperation.cpp b/umbrello/umbrello/codegenerators/javacodeoperation.cpp new file mode 100644 index 00000000..84ce0331 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodeoperation.cpp @@ -0,0 +1,132 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Jun 30 2003 + */ + +#include "javacodeoperation.h" + +#include "javaclassifiercodedocument.h" +#include "javacodedocumentation.h" +#include "javacodegenerator.h" +#include "../uml.h" + +// Constructors/Destructors +// + +JavaCodeOperation::JavaCodeOperation + ( JavaClassifierCodeDocument * doc, UMLOperation *parent, const QString & body, const QString & comment ) + : CodeOperation (doc, parent, body, comment) +{ + // lets not go with the default comment and instead use + // full-blown java documentation object instead + setComment(new JavaCodeDocumentation(doc)); + + // these things never change.. + setOverallIndentationLevel(1); + + updateMethodDeclaration(); + updateContent(); +} + +JavaCodeOperation::~JavaCodeOperation ( ) { } + +// Other methods +// + +// we basically want to update the doc and start text of this method +void JavaCodeOperation::updateMethodDeclaration() +{ + + CodeDocument * doc = getParentDocument(); + JavaClassifierCodeDocument * javadoc = dynamic_cast<JavaClassifierCodeDocument*>(doc); + UMLOperation * o = getParentOperation(); + bool isInterface = javadoc->getParentClassifier()->isInterface(); + QString endLine = getNewLineEndingChars(); + + // now, the starting text. + QString strVis = javadoc->scopeToJavaDecl(o->getVisibility()); + // no return type for constructors + QString fixedReturn = JavaCodeGenerator::fixTypeName(o->getTypeName()); + QString returnType = o->isConstructorOperation() ? QString("") : (fixedReturn + QString(" ")); + QString methodName = o->getName(); + QString paramStr = QString(""); + + // assemble parameters + UMLAttributeList list = getParentOperation()->getParmList(); + int nrofParam = list.count(); + int paramNum = 0; + for(UMLAttribute* parm = list.first(); parm; parm=list.next()) + { + QString rType = parm->getTypeName(); + QString paramName = parm->getName(); + paramStr += rType + ' ' + paramName; + paramNum++; + + if (paramNum != nrofParam ) + paramStr += ", "; + } + QString maybeStatic; + if (o->getStatic()) + maybeStatic = "static "; + QString startText = strVis + ' ' + maybeStatic + returnType + methodName + " (" + paramStr + ')'; + + // IF the parent is an interface, our operations look different + // e.g. they have no body + if(isInterface) { + startText += ';'; + setEndMethodText(""); + } else { + startText += " {"; + setEndMethodText("}"); + } + + setStartMethodText(startText); + + // Lastly, for text content generation, we fix the comment on the + // operation, IF the codeop is autogenerated & currently empty + QString comment = o->getDoc(); + if(comment.isEmpty() && getContentType() == CodeBlock::AutoGenerated) + { + UMLAttributeList parameters = o->getParmList(); + for(UMLAttributeListIt iterator(parameters); iterator.current(); ++iterator) { + comment += endLine + "@param " + iterator.current()->getName() + ' '; + comment += iterator.current()->getDoc(); + } + // add a returns statement too + if(!returnType.isEmpty()) + comment += endLine + "@return " + returnType + ' '; + getComment()->setText(comment); + } + + + // In Java, for interfaces..we DON'T write out non-public + // method declarations. + if(isInterface) + { + UMLOperation * o = getParentOperation(); + if(o->getVisibility() != Uml::Visibility::Public) + setWriteOutText(false); + } + +} + +int JavaCodeOperation::lastEditableLine() { + ClassifierCodeDocument * doc = dynamic_cast<ClassifierCodeDocument*>(getParentDocument()); + if(doc->parentIsInterface()) + return -1; // very last line is NOT editable as its a one-line declaration w/ no body in + // an interface. + return 0; +} + +#include "javacodeoperation.moc" diff --git a/umbrello/umbrello/codegenerators/javacodeoperation.h b/umbrello/umbrello/codegenerators/javacodeoperation.h new file mode 100644 index 00000000..08a555d8 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javacodeoperation.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Jun 30 2003 + */ + + +#ifndef JAVACODEOPERATION_H +#define JAVACODEOPERATION_H + +#include <qstring.h> +#include "../codeoperation.h" + +class JavaClassifierCodeDocument; + +class JavaCodeOperation : virtual public CodeOperation +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Empty Constructor + */ + JavaCodeOperation ( JavaClassifierCodeDocument * doc, UMLOperation * op, const QString & body = "", const QString & comment = ""); + + /** + * Empty Destructor + */ + virtual ~JavaCodeOperation ( ); + + virtual int lastEditableLine(); + +protected: + + void updateMethodDeclaration(); + +}; + +#endif // JAVACODEOPERATION_H 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; +} + diff --git a/umbrello/umbrello/codegenerators/javawriter.h b/umbrello/umbrello/codegenerators/javawriter.h new file mode 100644 index 00000000..2469f6d0 --- /dev/null +++ b/umbrello/umbrello/codegenerators/javawriter.h @@ -0,0 +1,236 @@ +/*************************************************************************** + javawriter.h - 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 + (C) 2004 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. * + * * + ***************************************************************************/ + +#ifndef JAVAWRITER_H +#define JAVAWRITER_H + +#include "simplecodegenerator.h" +#include "../umloperationlist.h" +#include "../umlattributelist.h" +#include "../umlassociationlist.h" + +class UMLOperation; + +/** + * class JavaWriter is a code generator for UMLClassifier objects. + * Create an instance of this class, and feed it a UMLClassifier when + * calling writeClass and it will generate a java source file for + * that concept + */ +class JavaWriter : public SimpleCodeGenerator { +public: + + /** + * Constructor, initialises a couple of variables + */ + JavaWriter(); + + /** + * Destructor, empty + */ + virtual ~JavaWriter(); + + /** + * call this method to generate java code for a UMLClassifier + * @param c the class to generate code for + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "Java" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * Overrides method from class CodeGenerator + */ + QStringList defaultDatatypes(); + +private: + + /** + * Writes class's documentation then the class header + * public abstract class Foo extents { + */ + void writeClassDecl(UMLClassifier *c, QTextStream &java); + + /** + * Writes the comment and class constructor + */ + void writeConstructor(UMLClassifier *c, QTextStream &java); + + /** + * return true if the two operations have the same name and the same parameters + * @param op1 first operation to be compared + * @param op2 second operation to be compared + */ + static bool compareJavaMethod(UMLOperation *op1, UMLOperation *op2); + + /** + * return true if the operation is in the list + * @param umlOp operation to be searched + * @param opl list of operations + */ + static bool javaMethodInList(UMLOperation *umlOp, UMLOperationList &opl); + + /** + * get all operations which a given class inherit from all its super interfaces and get all operations + * which this given class inherit from all its super classes + * @param c the class for which we are generating code + * @param yetImplementedOpList the list of yet implemented operations + * @param toBeImplementedOpList the list of to be implemented operations + * @param noClassInPath tells if there is a class between the base class and the current interface + */ + void getSuperImplementedOperations(UMLClassifier *c, UMLOperationList &yetImplementedOpList ,UMLOperationList &toBeImplementedOpList, bool noClassInPath = true); + + /** + * get all operations which a given class inherit from all its super interfaces and that should be implemented + * @param c the class for which we are generating code + * @param opl the list of operations used to append the operations + */ + void getInterfacesOperationsToBeImplemented(UMLClassifier *c, UMLOperationList &opl); + + /** + * write all operations for a given class + * @param c the class for which we are generating code + * @param j the stream associated with the output file + */ + void writeOperations(UMLClassifier *c, QTextStream &j); + + /** + * write a list of operations for a given class + * @param list the list of operations you want to write + * @param j the stream associated with the output file + */ + void writeOperations(UMLOperationList &list, QTextStream &j); + + /** + * write all attributes for a given class + * @param c the class for which we are generating code + * @param j the stream associated with the output file + */ + void writeAttributes(UMLClassifier *c, QTextStream &j); + + /** + * writes the Attribute declarations + * @param atpub List of public attributes + * @param atprot list of protected attributes + * @param atpriv list of private attributes + * @param java text stream + */ + void writeAttributeDecls(UMLAttributeList &atpub, UMLAttributeList &atprot, + UMLAttributeList &atpriv, QTextStream &java ); + + /** + * Searches a list of associations for appropriate ones to write out as attributes + */ + void writeAssociationDecls(UMLAssociationList associations, Uml::IDType id, QTextStream &java); + + /** + * Writes out an association as an attribute using Vector + */ + void writeAssociationRoleDecl(QString fieldClassName, QString roleName, QString multi, + QString doc, Uml::Visibility visib, QTextStream &java); + + /** + * calls @ref writeSingleAttributeAccessorMethods() on each of the attributes in atpub + */ + void writeAttributeMethods(UMLAttributeList &atpub, Uml::Visibility visibility, QTextStream &java); + + /** + * calls @ref writeAssociationRoleMethod() on each of the associations in the given list + */ + void writeAssociationMethods(UMLAssociationList associations, UMLClassifier *thisClass, + QTextStream &java); + + /** + * calls @ref writeSingleAttributeAccessorMethods() or @ref + * writeVectorAttributeAccessorMethods() on the assocaition + * role + */ + void writeAssociationRoleMethod(QString fieldClassName, QString roleName, QString multi, + QString description, Uml::Visibility visib, Uml::Changeability_Type change, + QTextStream &java); + + /** + * Writes getFoo() and setFoo() accessor methods for the attribute + */ + void writeSingleAttributeAccessorMethods(QString fieldClassName, QString fieldVarName, + QString fieldName, QString description, + Uml::Visibility visibility, Uml::Changeability_Type change, + bool isFinal, QTextStream &java); + + /** + * Writes addFoo() and removeFoo() accessor methods for the Vector attribute + */ + void writeVectorAttributeAccessorMethods(QString fieldClassName, QString fieldVarName, + QString fieldName, QString description, + Uml::Visibility visibility, Uml::Changeability_Type change, + QTextStream &java); + + /** + * Writes a // style comment + */ + void writeComment(const QString &text, const QString &indent, QTextStream &java, bool javaDocStyle=false); + + /** + * Writes a documentation comment + */ + void writeDocumentation(QString header, QString body, QString end, QString indent, QTextStream &java); + + /** + * Returns the name of the given object (if it exists) + */ + QString getUMLObjectName(UMLObject *obj); + + /** + * Replaces `string' with `String' and `bool' with `boolean' + */ + QString fixTypeName(const QString& string); + + /** + * check that initial values of strings have quotes around them + */ + QString fixInitialStringDeclValue(QString value, QString type); + + /** + * Write a blank line + */ + void writeBlankLine(QTextStream& java); + + /** + * a little method for converting scope to string value + */ + QString scopeToJavaDecl(Uml::Visibility scope); + + /** + * A \n, used at the end of each line + */ + QString startline; + + /** + * Whether or not this concept is an interface. + */ + bool isInterface; + +}; + + +#endif // JAVAWRITER_H + diff --git a/umbrello/umbrello/codegenerators/jswriter.cpp b/umbrello/umbrello/codegenerators/jswriter.cpp new file mode 100644 index 00000000..1dbb45d6 --- /dev/null +++ b/umbrello/umbrello/codegenerators/jswriter.cpp @@ -0,0 +1,308 @@ +/*************************************************************************** + begin : Sat Feb 08 2003 + copyright : (C) 2003 by Alexander Blum + email : blum@kewbee.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License js published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "jswriter.h" +#include "../association.h" +#include "../classifier.h" +#include "../operation.h" +#include "../umldoc.h" +#include "../attribute.h" + +#include <kdebug.h> + +#include <qregexp.h> +#include <qtextstream.h> + +JSWriter::JSWriter() { +} + +JSWriter::~JSWriter() {} + + +void JSWriter::writeClass(UMLClassifier *c) +{ + if(!c) + { + kDebug()<<"Cannot write class of NULL concept!" << endl; + return; + } + + QString classname = cleanName(c->getName()); + QString fileName = c->getName().lower(); + + //find an appropriate name for our file + fileName = findFileName(c,".js"); + if (fileName.isEmpty()) + { + emit codeGenerated(c, false); + return; + } + + QFile filejs; + if(!openFile(filejs, fileName)) + { + emit codeGenerated(c, false); + return; + } + QTextStream js(&filejs); + + ////////////////////////////// + //Start generating the code!! + ///////////////////////////// + + + //try to find a heading file (license, coments, etc) + QString str; + str = getHeadingFile(".js"); + if(!str.isEmpty()) + { + str.replace(QRegExp("%filename%"),fileName); + str.replace(QRegExp("%filepath%"),filejs.name()); + js << str << m_endl; + } + + + //write includes + UMLPackageList includes; + findObjectsRelated(c,includes); + for (UMLPackage *conc = includes.first(); conc; conc = includes.next()) + { + QString headerName = findFileName(conc, ".js"); + if ( !headerName.isEmpty() ) + { + js << "#include \"" << headerName << "\"" << m_endl; + } + } + js << m_endl; + + //Write class Documentation if there is somthing or if force option + if(forceDoc() || !c->getDoc().isEmpty()) + { + js << m_endl << "/**" << m_endl; + js << " * class " << classname << m_endl; + js << formatDoc(c->getDoc()," * "); + js << " */" << m_endl << m_endl; + } + + + //check if class is abstract and / or has abstract methods + if(c->getAbstract() && !hasAbstractOps(c)) + js << "/******************************* Abstract Class ****************************" << m_endl << " " + << classname << " does not have any pure virtual methods, but its author" << m_endl + << " defined it as an abstract class, so you should not use it directly." << m_endl + << " Inherit from it instead and create only objects from the derived classes" << m_endl + << "*****************************************************************************/" << m_endl << m_endl; + + js << classname << " = function ()" << m_endl; + js << "{" << m_endl; + js << m_indentation << "this._init ();" << m_endl; + js << "}" << m_endl; + js << m_endl; + + UMLClassifierList superclasses = c->getSuperClasses(); + for (UMLClassifier *obj = superclasses.first(); + obj; obj = superclasses.next()) { + js << classname << ".prototype = new " << cleanName(obj->getName()) << " ();" << m_endl; + } + + js << m_endl; + + if (! c->isInterface()) { + UMLAttributeList atl = c->getAttributeList(); + + js << "/**" << m_endl; + QString temp = "_init sets all " + classname + " attributes to their default value." + " Make sure to call this method within your class constructor"; + js << formatDoc(temp, " * "); + js << " */" << m_endl; + js << classname << ".prototype._init = function ()" << m_endl; + js << "{" << m_endl; + for(UMLAttribute *at = atl.first(); at ; at = atl.next()) + { + if (forceDoc() || !at->getDoc().isEmpty()) + { + js << m_indentation << "/**" << m_endl + << formatDoc(at->getDoc(), m_indentation + " * ") + << m_indentation << " */" << m_endl; + } + if(!at->getInitialValue().isEmpty()) + { + js << m_indentation << "this.m_" << cleanName(at->getName()) << " = " << at->getInitialValue() << ";" << m_endl; + } + else + { + js << m_indentation << "this.m_" << cleanName(at->getName()) << " = \"\";" << m_endl; + } + } + } + + //associations + UMLAssociationList aggregations = c->getAggregations(); + if (forceSections() || !aggregations.isEmpty ()) + { + js << m_endl << m_indentation << "/**Aggregations: */" << m_endl; + writeAssociation(classname, aggregations , js ); + + } + UMLAssociationList compositions = c->getCompositions(); + if( forceSections() || !compositions.isEmpty()) + { + js << m_endl << m_indentation << "/**Compositions: */" << m_endl; + writeAssociation(classname, compositions , js ); + + } + js << m_endl; + js << "}" << m_endl; + js << m_endl; + + //operations + UMLOperationList ops(c->getOpList()); + writeOperations(classname, &ops, js); + + js << m_endl; + + //finish file + + //close files and notfiy we are done + filejs.close(); + emit codeGenerated(c, true); +} + +//////////////////////////////////////////////////////////////////////////////////// +// Helper Methods + +void JSWriter::writeAssociation(QString& classname, UMLAssociationList& assocList , QTextStream &js) +{ + for (UMLAssociation *a = assocList.first(); a; a = assocList.next()) { + // association side + Uml::Role_Type role = (a->getObject(Uml::A)->getName() == classname ? Uml::B : Uml::A); + + QString roleName(cleanName(a->getRoleName(role))); + + if (!roleName.isEmpty()) { + + // association doc + if (forceDoc() || !a->getDoc().isEmpty()) + { + js << m_indentation << "/**" << m_endl + << formatDoc(a->getDoc(), m_indentation + " * ") + << m_indentation << " */" << m_endl; + } + + // role doc + if (forceDoc() || !a->getRoleDoc(role).isEmpty()) + { + js << m_indentation << "/**" << m_endl + << formatDoc(a->getRoleDoc(role), m_indentation + " * ") + << m_indentation << " */" << m_endl; + } + + bool okCvt; + int nMulti = a->getMulti(role).toInt(&okCvt,10); + bool isNotMulti = a->getMulti(role).isEmpty() || (okCvt && nMulti == 1); + + QString typeName(cleanName(a->getObject(role)->getName())); + + if (isNotMulti) + js << m_indentation << "this.m_" << roleName << " = new " << typeName << "();" << m_endl; + else + js << m_indentation << "this.m_" << roleName << " = new Array();" << m_endl; + + // role visibility + } + } +} + +void JSWriter::writeOperations(QString classname, UMLOperationList *opList, QTextStream &js) +{ + UMLOperation *op; + UMLAttribute *at; + + for(op = opList->first(); op; op = opList->next()) + { + UMLAttributeList atl = op->getParmList(); + //write method doc if we have doc || if at least one of the params has doc + bool writeDoc = forceDoc() || !op->getDoc().isEmpty(); + for (at = atl.first(); at; at = atl.next()) + writeDoc |= !at->getDoc().isEmpty(); + + if( writeDoc ) //write method documentation + { + js << "/**" << m_endl << formatDoc(op->getDoc()," * "); + + for (at = atl.first(); at; at = atl.next()) //write parameter documentation + { + if(forceDoc() || !at->getDoc().isEmpty()) + { + js << " * @param " + cleanName(at->getName())<<m_endl; + js << formatDoc(at->getDoc()," * "); + } + }//end for : write parameter documentation + js << " */" << m_endl; + }//end if : write method documentation + + js << classname << ".prototype." << cleanName(op->getName()) << " = function " << "("; + + int i = atl.count(); + int j=0; + for (at = atl.first(); at ;at = atl.next(),j++) + { + js << cleanName(at->getName()) + << (!(at->getInitialValue().isEmpty()) ? (QString(" = ")+at->getInitialValue()) : QString("")) + << ((j < i-1)?", ":""); + } + js << ")" << m_endl << "{" << m_endl << + m_indentation << m_endl << "}" << m_endl; + js << m_endl << m_endl; + }//end for +} + +/** + * returns "JavaScript" + */ +Uml::Programming_Language JSWriter::getLanguage() { + return Uml::pl_JavaScript; +} + +const QStringList JSWriter::reservedKeywords() const { + + static QStringList keywords; + + if (keywords.isEmpty()) { + keywords << "break" + << "case" + << "const" + << "continue" + << "default" + << "else" + << "false" + << "for" + << "function" + << "if" + << "in" + << "new" + << "return" + << "switch" + << "this" + << "true" + << "var" + << "while" + << "with"; + } + + return keywords; +} + +#include "jswriter.moc" diff --git a/umbrello/umbrello/codegenerators/jswriter.h b/umbrello/umbrello/codegenerators/jswriter.h new file mode 100644 index 00000000..a9c5ebde --- /dev/null +++ b/umbrello/umbrello/codegenerators/jswriter.h @@ -0,0 +1,78 @@ +/*************************************************************************** + jswriter.h - description + ------------------- + begin : Sat Feb 08 2003 + copyright : (C) 2003 by Alexander Blum + email : blum@kewbee.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef JSWRITER_H +#define JSWRITER_H + +#include "simplecodegenerator.h" +#include "../umloperationlist.h" +#include "../umlassociationlist.h" + +/** + * class JSWriter is a JavaScript code generator for UMLClassifier objects + * Just call writeClass and feed it a UMLClassifier; + */ +class JSWriter : public SimpleCodeGenerator { + Q_OBJECT +public: + + JSWriter(); + virtual ~JSWriter(); + + /** + * call this method to generate Actionscript code for a UMLClassifier + * @param c the class you want to generate code for. + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "JavaScript" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +private: + + /** + * we do not want to write the comment "Private methods" twice + */ + bool bPrivateSectionCommentIsWritten; + + /** + * write a list of class operations + * + * @param classname the name of the class + * @param opList the list of operations + * @param js output stream for the JS file + */ + void writeOperations(QString classname, UMLOperationList *opList, QTextStream &js); + + /** + * write a list of associations + * + * @param classname the name of the class + * @param assocList the list of associations + * @param as output stream for the AS file + */ + void writeAssociation(QString& classname, UMLAssociationList& assoclist , QTextStream &js); +}; + +#endif //JSWRITER diff --git a/umbrello/umbrello/codegenerators/pascalwriter.cpp b/umbrello/umbrello/codegenerators/pascalwriter.cpp new file mode 100644 index 00000000..92a45bd2 --- /dev/null +++ b/umbrello/umbrello/codegenerators/pascalwriter.cpp @@ -0,0 +1,542 @@ +/*************************************************************************** + * * + * 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) 2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#include "pascalwriter.h" + +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <qfile.h> +#include <qregexp.h> +#include <qtextstream.h> + +#include "../umldoc.h" +#include "../uml.h" +#include "../classifier.h" +#include "../enum.h" +#include "../classifierlistitem.h" +#include "../umlclassifierlistitemlist.h" +#include "../umltemplatelist.h" +#include "../folder.h" +#include "../association.h" +#include "../attribute.h" +#include "../operation.h" +#include "../template.h" +#include "../umlnamespace.h" +#include "classifierinfo.h" + +const QString PascalWriter::defaultPackageSuffix = "_Holder"; + +PascalWriter::PascalWriter() { +} + +PascalWriter::~PascalWriter() {} + +/** + * returns "Pascal" + */ +Uml::Programming_Language PascalWriter::getLanguage() { + return Uml::pl_Pascal; +} + + +bool PascalWriter::isOOClass(UMLClassifier *c) { + Uml::Object_Type ot = c->getBaseType(); + if (ot == Uml::ot_Interface) + return true; + if (ot == Uml::ot_Enum) + return false; + if (ot != Uml::ot_Class) { + kDebug() << "PascalWriter::isOOClass: unknown object type " << ot << endl; + return false; + } + QString stype = c->getStereotype(); + if (stype == "CORBAConstant" || stype == "CORBATypedef" || + stype == "CORBAStruct" || stype == "CORBAUnion") + return false; + // CORBAValue, CORBAInterface, and all empty/unknown stereotypes are + // assumed to be OO classes. + return true; +} + +QString PascalWriter::qualifiedName(UMLPackage *p, bool withType, bool byValue) { + UMLPackage *umlPkg = p->getUMLPackage(); + QString className = cleanName(p->getName()); + QString retval; + + if (umlPkg == UMLApp::app()->getDocument()->getRootFolder(Uml::mt_Logical)) + umlPkg = NULL; + + UMLClassifier *c = dynamic_cast<UMLClassifier*>(p); + if (umlPkg == NULL) { + retval = className; + if (c == NULL || !isOOClass(c)) + retval.append(defaultPackageSuffix); + } else { + retval = umlPkg->getFullyQualifiedName("."); + if (isOOClass(c)) { + retval.append("."); + retval.append(className); + } + } + if (! withType) + return retval; + if (c && isOOClass(c)) { + retval.append(".Object"); + if (! byValue) + retval.append("_Ptr"); + } else { + retval.append("."); + retval.append(className); + } + return retval; +} + +void PascalWriter::computeAssocTypeAndRole +(UMLAssociation *a, QString& typeName, QString& roleName) { + roleName = a->getRoleName(Uml::A); + if (roleName.isEmpty()) { + if (a->getMulti(Uml::A).isEmpty()) { + roleName = "M_"; + roleName.append(typeName); + } else { + roleName = typeName; + roleName.append("_Vector"); + } + } + UMLClassifier* c = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A)); + if (c == NULL) + return; + typeName = cleanName(c->getName()); + if (! a->getMulti(Uml::A).isEmpty()) + typeName.append("_Array_Access"); +} + +void PascalWriter::writeClass(UMLClassifier *c) { + if (!c) { + kDebug() << "Cannot write class of NULL concept!" << endl; + return; + } + + const bool isClass = !c->isInterface(); + QString classname = cleanName(c->getName()); + QString fileName = qualifiedName(c).lower(); + fileName.replace('.', '-'); + + //find an appropriate name for our file + fileName = overwritableName(c, fileName, ".pas"); + if (fileName.isEmpty()) { + emit codeGenerated(c, false); + return; + } + + QFile file; + if (!openFile(file, fileName)) { + emit codeGenerated(c, false); + return; + } + + // Start generating the code. + + QTextStream pas(&file); + //try to find a heading file(license, comments, etc) + QString str; + str = getHeadingFile(".pas"); + if (!str.isEmpty()) { + str.replace(QRegExp("%filename%"), fileName); + str.replace(QRegExp("%filepath%"), file.name()); + pas << str << endl; + } + + QString unit = qualifiedName(c); + pas << "unit " << unit << ";" << m_endl << m_endl; + pas << "INTERFACE" << m_endl << m_endl; + // Use referenced classes. + UMLPackageList imports; + findObjectsRelated(c, imports); + if (imports.count()) { + pas << "uses" << m_endl; + bool first = true; + for (UMLPackage *con = imports.first(); con; con = imports.next()) { + if (con->getBaseType() != Uml::ot_Datatype) { + if (first) + first = false; + else + pas << "," << m_endl; + pas << " " << qualifiedName(con); + } + } + pas << ";" << m_endl << m_endl; + } + + pas << "type" << m_endl; + m_indentLevel++; + if (c->getBaseType() == Uml::ot_Enum) { + UMLEnum *ue = static_cast<UMLEnum*>(c); + UMLClassifierListItemList litList = ue->getFilteredList(Uml::ot_EnumLiteral); + uint i = 0; + pas << getIndent() << classname << " = (" << m_endl; + m_indentLevel++; + for (UMLClassifierListItem *lit = litList.first(); lit; lit = litList.next()) { + QString enumLiteral = cleanName(lit->getName()); + pas << getIndent() << enumLiteral; + if (++i < litList.count()) + pas << "," << m_endl; + } + m_indentLevel--; + pas << ");" << m_endl << m_endl; + m_indentLevel--; + pas << "end." << m_endl << m_endl; + return; + } + UMLAttributeList atl = c->getAttributeList(); + if (! isOOClass(c)) { + QString stype = c->getStereotype(); + if (stype == "CORBAConstant") { + pas << getIndent() << "// " << stype << " is Not Yet Implemented" << m_endl << m_endl; + } else if(stype == "CORBAStruct") { + if (isClass) { + UMLAttribute *at; + pas << getIndent() << classname << " = record" << m_endl; + m_indentLevel++; + for (at = atl.first(); at; at = atl.next()) { + QString name = cleanName(at->getName()); + QString typeName = at->getTypeName(); + pas << getIndent() << name << " : " << typeName; + QString initialVal = at->getInitialValue(); + if (initialVal.latin1() && ! initialVal.isEmpty()) + pas << " := " << initialVal; + pas << ";" << m_endl; + } + m_indentLevel--; + pas << "end;" << m_endl << m_endl; + } + } else if(stype == "CORBAUnion") { + pas << getIndent() << "// " << stype << " is Not Yet Implemented" << m_endl << m_endl; + } else if(stype == "CORBATypedef") { + pas << getIndent() << "// " << stype << " is Not Yet Implemented" << m_endl << m_endl; + } else { + pas << getIndent() << "// " << stype << ": Unknown stereotype" << m_endl << m_endl; + } + m_indentLevel--; + pas << getIndent() << "end." << m_endl << m_endl; + return; + } + + // Write class Documentation if non-empty or if force option set. + if (forceDoc() || !c->getDoc().isEmpty()) { + pas << "//" << m_endl; + pas << "// class " << classname << endl; + pas << formatDoc(c->getDoc(), "// "); + pas << m_endl; + } + + UMLClassifierList superclasses = c->getSuperClasses(); + + pas << getIndent() << classname << " = object"; + if (!superclasses.isEmpty()) { + // FIXME: Multiple inheritance is not yet supported + UMLClassifier* parent = superclasses.first(); + pas << "(" << qualifiedName(parent) << ")"; + } + pas << m_endl; + + ClassifierInfo info(c); + UMLAttributeList atpub = info.atpub; + if (isClass && (forceSections() || atpub.count())) { + pas << getIndent() << "// Public attributes:" << m_endl; + UMLAttribute *at; + for (at = atpub.first(); at; at = atpub.next()) { + // if (at->getStatic()) + // continue; + pas << getIndent() << cleanName(at->getName()) << " : " + << at->getTypeName(); + if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty()) + pas << " := " << at->getInitialValue(); + pas << ";" << m_endl; + } + } + bool haveAttrs = (isClass && atl.count()); + + // Generate public operations. + UMLOperationList opl(c->getOpList()); + UMLOperationList oppub; + oppub.setAutoDelete(false); + UMLOperation *op; + for (op = opl.first(); op; op = opl.next()) { + if (op->getVisibility() == Uml::Visibility::Public) + oppub.append(op); + } + if (forceSections() || oppub.count()) + pas << getIndent() << "// Public methods:" << m_endl << m_endl; + for (op = oppub.first(); op; op = oppub.next()) + writeOperation(op, pas); + + if (info.atprot.count()) { + pas << "protected" << m_endl << m_endl; + UMLAttribute *at; + UMLAttributeList atprot = info.atprot; + for (at = atprot.first(); at; at = atprot.next()) { + // if (at->getStatic()) + // continue; + pas << getIndent() << cleanName(at->getName()) << " : " + << at->getTypeName(); + if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty()) + pas << " := " << at->getInitialValue(); + pas << ";" << m_endl; + } + pas << m_endl; + } + if (info.atpriv.count()) { + pas << "private" << m_endl << m_endl; + UMLAttribute *at; + UMLAttributeList atpriv = info.atpriv; + for (at = atpriv.first(); at; at = atpriv.next()) { + // if (at->getStatic()) + // continue; + pas << getIndent() << cleanName(at->getName()) << " : " + << at->getTypeName(); + if (at && at->getInitialValue().latin1() && ! at->getInitialValue().isEmpty()) + pas << " := " << at->getInitialValue(); + pas << ";" << m_endl; + } + pas << m_endl; + } + pas << getIndent() << "end;" << m_endl << m_endl; + + pas << getIndent() << "P" << classname << " = ^" << classname <<";" << m_endl << m_endl; + + m_indentLevel--; + pas << "end;" << m_endl << m_endl; + file.close(); + emit codeGenerated(c, true); +} + + +void PascalWriter::writeOperation(UMLOperation *op, QTextStream &pas, bool is_comment) { + if (op->getStatic()) { + pas << "// TODO: generate status method " << op->getName() << m_endl; + return; + } + UMLAttributeList atl = op->getParmList(); + QString rettype = op->getTypeName(); + bool use_procedure = (rettype.isEmpty() || rettype == "void"); + + pas << getIndent(); + if (is_comment) + pas << "// "; + if (use_procedure) + pas << "procedure "; + else + pas << "function "; + pas << cleanName(op->getName()) << " "; + if (atl.count()) { + pas << "(" << m_endl; + uint i = 0; + m_indentLevel++; + for (UMLAttribute *at = atl.first(); at; at = atl.next()) { + pas << getIndent(); + if (is_comment) + pas << "// "; + pas << cleanName(at->getName()) << " : "; + Uml::Parameter_Direction pk = at->getParmKind(); + if (pk != Uml::pd_In) + pas << "var "; + pas << at->getTypeName(); + if (! at->getInitialValue().isEmpty()) + pas << " := " << at->getInitialValue(); + if (++i < (uint)atl.count()) + pas << ";" << m_endl; + } + m_indentLevel--; + pas << ")"; + } + if (! use_procedure) + pas << " : " << rettype; + pas << "; virtual; abstract;" << m_endl << m_endl; + // TBH, we make the methods abstract here because we don't have the means + // for generating meaningful implementations. +} + +QStringList PascalWriter::defaultDatatypes() { + QStringList l; + l.append("AnsiString"); + l.append("Boolean"); + l.append("Byte"); + l.append("ByteBool"); + l.append("Cardinal"); + l.append("Character"); + l.append("Currency"); + l.append("Double"); + l.append("Extended"); + l.append("Int64"); + l.append("Integer"); + l.append("Longint"); + l.append("LongBool"); + l.append("Longword"); + l.append("QWord"); + l.append("Real"); + l.append("Shortint"); + l.append("ShortString"); + l.append("Single"); + l.append("Smallint"); + l.append("String"); + l.append("WideString"); + l.append("Word"); + return l; +} + +/** + * Check whether the given string is a reserved word for the + * language of this code generator + * + * @param rPossiblyReservedKeyword The string to check. + */ +bool PascalWriter::isReservedKeyword(const QString & rPossiblyReservedKeyword) { + + const QStringList keywords = reservedKeywords(); + + QStringList::ConstIterator it; + for (it = keywords.begin(); it != keywords.end(); ++it) + if ((*it).lower() == rPossiblyReservedKeyword.lower()) + return true; + + return false; +} + +/** + * get list of reserved keywords + */ +const QStringList PascalWriter::reservedKeywords() const { + + static QStringList keywords; + + if ( keywords.isEmpty() ) { + keywords.append( "absolute" ); + keywords.append( "abstract" ); + keywords.append( "and" ); + keywords.append( "array" ); + keywords.append( "as" ); + keywords.append( "asm" ); + keywords.append( "assembler" ); + keywords.append( "automated" ); + keywords.append( "begin" ); + keywords.append( "case" ); + keywords.append( "cdecl" ); + keywords.append( "class" ); + keywords.append( "const" ); + keywords.append( "constructor" ); + keywords.append( "contains" ); + keywords.append( "default" ); + keywords.append( "deprecated" ); + keywords.append( "destructor" ); + keywords.append( "dispid" ); + keywords.append( "dispinterface" ); + keywords.append( "div" ); + keywords.append( "do" ); + keywords.append( "downto" ); + keywords.append( "dynamic" ); + keywords.append( "else" ); + keywords.append( "end" ); + keywords.append( "except" ); + keywords.append( "export" ); + keywords.append( "exports" ); + keywords.append( "external" ); + keywords.append( "far" ); + keywords.append( "file" ); + keywords.append( "final" ); + keywords.append( "finalization" ); + keywords.append( "finally" ); + keywords.append( "for" ); + keywords.append( "forward" ); + keywords.append( "function" ); + keywords.append( "goto" ); + keywords.append( "if" ); + keywords.append( "implementation" ); + keywords.append( "implements" ); + keywords.append( "in" ); + keywords.append( "index" ); + keywords.append( "inherited" ); + keywords.append( "initialization" ); + keywords.append( "inline" ); + keywords.append( "inline" ); + keywords.append( "interface" ); + keywords.append( "is" ); + keywords.append( "label" ); + keywords.append( "library" ); + keywords.append( "library" ); + keywords.append( "local" ); + keywords.append( "message" ); + keywords.append( "mod" ); + keywords.append( "name" ); + keywords.append( "near" ); + keywords.append( "nil" ); + keywords.append( "nodefault" ); + keywords.append( "not" ); + keywords.append( "object" ); + keywords.append( "of" ); + keywords.append( "or" ); + keywords.append( "out" ); + keywords.append( "overload" ); + keywords.append( "override" ); + keywords.append( "package" ); + keywords.append( "packed" ); + keywords.append( "pascal" ); + keywords.append( "platform" ); + keywords.append( "private" ); + keywords.append( "procedure" ); + keywords.append( "program" ); + keywords.append( "property" ); + keywords.append( "protected" ); + keywords.append( "public" ); + keywords.append( "published" ); + keywords.append( "raise" ); + keywords.append( "read" ); + keywords.append( "readonly" ); + keywords.append( "record" ); + keywords.append( "register" ); + keywords.append( "reintroduce" ); + keywords.append( "repeat" ); + keywords.append( "requires" ); + keywords.append( "resident" ); + keywords.append( "resourcestring" ); + keywords.append( "safecall" ); + keywords.append( "sealed" ); + keywords.append( "set" ); + keywords.append( "shl" ); + keywords.append( "shr" ); + keywords.append( "static" ); + keywords.append( "stdcall" ); + keywords.append( "stored" ); + keywords.append( "string" ); + keywords.append( "then" ); + keywords.append( "threadvar" ); + keywords.append( "to" ); + keywords.append( "try" ); + keywords.append( "type" ); + keywords.append( "unit" ); + keywords.append( "unsafe" ); + keywords.append( "until" ); + keywords.append( "uses" ); + keywords.append( "var" ); + keywords.append( "varargs" ); + keywords.append( "virtual" ); + keywords.append( "while" ); + keywords.append( "with" ); + keywords.append( "write" ); + keywords.append( "writeonly" ); + keywords.append( "xor" ); + } + + return keywords; +} + +#include "pascalwriter.moc" diff --git a/umbrello/umbrello/codegenerators/pascalwriter.h b/umbrello/umbrello/codegenerators/pascalwriter.h new file mode 100644 index 00000000..bc34d762 --- /dev/null +++ b/umbrello/umbrello/codegenerators/pascalwriter.h @@ -0,0 +1,86 @@ +/*************************************************************************** + * * + * 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) 2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef PASCALWRITER_H +#define PASCALWRITER_H + +#include "simplecodegenerator.h" + +class UMLAssociation; +class UMLOperation; + +/** + * Pascal class writer + * @author Oliver Kellogg + * Bugs and comments to uml-devel@lists.sf.net or http://bugs.kde.org + */ +class PascalWriter : public SimpleCodeGenerator { + Q_OBJECT +public: + + /** + * Basic Constructor + */ + PascalWriter (); + + /** + * Empty Destructor + */ + virtual ~PascalWriter (); + + /** + * call this method to generate Ada code for a UMLClassifier + * @param c the class to generate code for + */ + virtual void writeClass (UMLClassifier *c); + + /** + * returns "Pascal" + */ + virtual Uml::Programming_Language getLanguage(); + + QStringList defaultDatatypes(); + + /** + * Check whether the given string is a reserved word for the + * language of this code generator + * + * @param rPossiblyReservedKeyword The string to check. + */ + virtual bool isReservedKeyword(const QString & rPossiblyReservedKeyword); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +private: + + /** + * write one operation + * @param op the class for which we are generating code + * @param ada the stream associated with the output file + */ + void writeOperation (UMLOperation *op, QTextStream &ada, bool is_comment = false); + + void computeAssocTypeAndRole (UMLAssociation *a, QString& typeName, QString& roleName); + + bool isOOClass (UMLClassifier *c); + + QString qualifiedName + (UMLPackage *p, bool withType = false, bool byValue = false); + + static const QString defaultPackageSuffix; + +}; + +#endif // PASCALWRITER_H + diff --git a/umbrello/umbrello/codegenerators/perlwriter.cpp b/umbrello/umbrello/codegenerators/perlwriter.cpp new file mode 100644 index 00000000..7c8360fa --- /dev/null +++ b/umbrello/umbrello/codegenerators/perlwriter.cpp @@ -0,0 +1,716 @@ +/*************************************************************************** + begin : Wed Jan 22 2003 + copyright : (C) 2003 by David Hugh-Jones + (C) 2004-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net> + email : hughjonesd@yahoo.co.uk + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "perlwriter.h" +#include "../classifier.h" +#include "../operation.h" +#include "../umldoc.h" +#include "../association.h" +#include "../attribute.h" +#include "../uml.h" + +#include <kdebug.h> +#include <qregexp.h> +#include <qstring.h> +#include <qdir.h> +#include <qdatetime.h> +#include <qtextstream.h> + +PerlWriter::PerlWriter() +{ +} + +PerlWriter::~PerlWriter() {} + +bool PerlWriter::GetUseStatements(UMLClassifier *c, QString &Ret, + QString &ThisPkgName){ + + if(!c){ + return(false); + } + + UMLPackageList includes; + findObjectsRelated(c,includes); + UMLPackage *conc; + QString AV = "@"; + QString SV = "$"; + QString HV = "%"; + for(conc = includes.first(); conc ;conc = includes.next()) { + if (conc->getBaseType() == Uml::ot_Datatype) + continue; + QString neatName = cleanName(conc->getName()); + if (neatName != AV && neatName != SV && neatName != HV) { + QString OtherPkgName = conc->getPackage("."); + OtherPkgName.replace(QRegExp("\\."),"::"); + QString OtherName = OtherPkgName + "::" + cleanName(conc->getName()); + + // Only print out the use statement if the other package isn't the + // same as the one we are working on. (This happens for the + // "Singleton" design pattern.) + if(OtherName != ThisPkgName){ + Ret += "use "; + Ret += OtherName; + Ret += ';'; + Ret += m_endl; + } + } + } + UMLClassifierList superclasses = c->getSuperClasses(); + if (superclasses.count()) { + Ret += m_endl; + Ret += "use base qw( "; + for (UMLClassifier *obj = superclasses.first(); + obj; obj = superclasses.next()) { + QString packageName = obj->getPackage("."); + packageName.replace(QRegExp("\\."),"::"); + + Ret += packageName + "::" + cleanName(obj->getName()) + ' '; + } + Ret += ");" + m_endl; + } + + return(true); +} + +void PerlWriter::writeClass(UMLClassifier *c) { + + /* if(!c) { + kDebug()<<"Cannot write class of NULL concept!" << endl; + return; + } + */ + QString classname = cleanName(c->getName());// this is fine: cleanName is "::-clean" + QString packageName = c->getPackage("."); + QString fileName; + + // Replace all white spaces with blanks + packageName.simplifyWhiteSpace(); + + // Replace all blanks with underscore + packageName.replace(QRegExp(" "), "_"); + + // Replace all dots (".") with double colon scope resolution operators + // ("::") + packageName.replace(QRegExp("\\."),"::"); + + // Store complete package name + QString ThisPkgName = packageName + "::" + classname; + + fileName = findFileName(c, ".pm"); + // the above lower-cases my nice class names. That is bad. + // correct solution: refactor, + // split massive findFileName up, reimplement + // parts here + // actual solution: shameful ".pm" hack in codegenerator + + CodeGenerationPolicy *pol = UMLApp::app()->getCommonPolicy(); + QString curDir = pol->getOutputDirectory().absPath(); + if (fileName.contains("::")) { + // create new directories for each level + QString newDir; + newDir = curDir; + QString fragment = fileName; + QDir* existing = new QDir (curDir); + QRegExp regEx("(.*)(::)"); + regEx.setMinimal(true); + while (regEx.search(fragment) > -1) { + newDir = regEx.cap(1); + fragment.remove(0, (regEx.pos(2) + 2)); // get round strange minimal matching bug + existing->setPath(curDir + '/' + newDir); + if (! existing->exists()) { + existing->setPath(curDir); + if (! existing->mkdir(newDir)) { + emit codeGenerated(c, false); + return; + } + } + curDir += '/' + newDir; + } + fileName = fragment + ".pm"; + } + if (fileName.isEmpty()) { + emit codeGenerated(c, false); + return; + } + QString oldDir = pol->getOutputDirectory().absPath(); + pol->setOutputDirectory(curDir); + QFile fileperl; + if(!openFile(fileperl, fileName)) { + emit codeGenerated(c, false); + return; + } + QTextStream perl(&fileperl); + pol->setOutputDirectory(oldDir); + + //====================================================================== + // Start generating the code!! + //====================================================================== + + // try to find a heading file (license, comments, etc) + QString str; + bool bPackageDeclared = false; + bool bUseStmsWritten = false; + + str = getHeadingFile(".pm"); // what this mean? + if(!str.isEmpty()) { + str.replace(QRegExp("%filename%"),fileName); + str.replace(QRegExp("%filepath%"),fileperl.name()); + str.replace(QRegExp("%year%"),QDate::currentDate().toString("yyyy")); + str.replace(QRegExp("%date%"),QDate::currentDate().toString()); + str.replace(QRegExp("%time%"),QTime::currentTime().toString()); + str.replace(QRegExp("%package-name%"),ThisPkgName); + if(str.find(QRegExp("%PACKAGE-DECLARE%"))){ + str.replace(QRegExp("%PACKAGE-DECLARE%"), + "package " + ThisPkgName + ';' + + m_endl + m_endl + + "#UML_MODELER_BEGIN_PERSONAL_VARS_" + classname + + m_endl + m_endl + + "#UML_MODELER_END_PERSONAL_VARS_" + classname + + m_endl + ); + bPackageDeclared = true; + } + + if(str.find(QRegExp("%USE-STATEMENTS%"))){ + QString UseStms; + if(GetUseStatements(c,UseStms,ThisPkgName)){ + str.replace(QRegExp("%USE-STATEMENTS%"), UseStms); + bUseStmsWritten = true; + } + } + + perl<<str<<m_endl; + } + + // if the package wasn't declared above during keyword substitution, + // add it now. (At the end of the file.) + if(! bPackageDeclared){ + perl << m_endl << m_endl << "package " <<ThisPkgName << ";" << m_endl + << m_endl; + //write includes + perl << m_endl << "#UML_MODELER_BEGIN_PERSONAL_VARS_" << classname + << m_endl ; + perl << m_endl << "#UML_MODELER_END_PERSONAL_VARS_" << classname + << m_endl << m_endl ; + } + + if(! bUseStmsWritten){ + QString UseStms; + if(GetUseStatements(c,UseStms,ThisPkgName)){ + perl<<UseStms<<m_endl; + } + } + + perl << m_endl; + + // Do we really need these for anything??? + UMLAssociationList aggregations = c->getAggregations(); + UMLAssociationList compositions = c->getCompositions(); + + //Write class Documentation + if(forceDoc() || !c->getDoc().isEmpty()) { + perl << m_endl << "=head1"; + perl << " " << classname.upper() << m_endl << m_endl; + perl << c->getDoc(); + perl << m_endl << m_endl << "=cut" << m_endl << m_endl; + } + + //check if class is abstract and / or has abstract methods + if(c->getAbstract()) + perl << "=head1 ABSTRACT CLASS" << m_endl << m_endl << "=cut" << m_endl; + + //attributes + if (! c->isInterface()) + writeAttributes(c, perl); // keep for documentation's sake + + //operations + writeOperations(c,perl); + + perl << m_endl; + + //finish file + //perl << m_endl << m_endl << "=cut" << m_endl; + perl << m_endl << m_endl << "return 1;" << m_endl; + + //close files and notify we are done + fileperl.close(); + emit codeGenerated(c, true); +} + +/** + * returns "Perl" + */ +Uml::Programming_Language PerlWriter::getLanguage() { + return Uml::pl_Perl; +} + +//////////////////////////////////////////////////////////////////////////////////// +// Helper Methods + +void PerlWriter::writeOperations(UMLClassifier *c, QTextStream &perl) { + + //Lists to store operations sorted by scope + 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 + //keep this for documentation only! + UMLOperationList opl(c->getOpList()); + 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; + } + } + + QString classname(cleanName(c->getName())); + + //write operations to file + if(forceSections() || !oppub.isEmpty()) { + perl << m_endl << "=head1 PUBLIC METHODS" << m_endl << m_endl ; + writeOperations(classname,oppub,perl); + perl << m_endl << m_endl << "=cut" << m_endl << m_endl; + } + + if(forceSections() || !opprot.isEmpty()) { + perl << m_endl << "=head1 METHODS FOR SUBCLASSING" << m_endl << m_endl ; + //perl << "=pod " << m_endl << m_endl << "=head3 " ; + writeOperations(classname,opprot,perl); + perl << m_endl << m_endl << "=cut" << m_endl << m_endl; + } + + if(forceSections() || !oppriv.isEmpty()) { + perl << m_endl << "=head1 PRIVATE METHODS" << m_endl << m_endl ; + //perl << "=pod " << m_endl << m_endl << "=head3 " ; + writeOperations(classname,oppriv,perl); + perl << m_endl << m_endl << "=cut" << m_endl << m_endl; + } + + // moved here for perl + if (!c->isInterface() && hasDefaultValueAttr(c)) { + UMLAttributeList atl = c->getAttributeList(); + + perl << m_endl; + perl << m_endl << "=head2 _init" << m_endl << m_endl << m_endl; + perl << "_init sets all " + classname + " attributes to their default values unless already set" << m_endl << m_endl << "=cut" << m_endl << m_endl; + perl << "sub _init {" << m_endl << m_indentation << "my $self = shift;" << m_endl<<m_endl; + + for(UMLAttribute *at = atl.first(); at ; at = atl.next()) { + if(!at->getInitialValue().isEmpty()) + perl << m_indentation << "defined $self->{" << cleanName(at->getName())<<"}" + << " or $self->{" << cleanName(at->getName()) << "} = " + << at->getInitialValue() << ";" << m_endl; + } + + perl << " }" << m_endl; + } + + perl << m_endl << m_endl; +} + +void PerlWriter::writeOperations(const QString &/* classname */, UMLOperationList &opList, QTextStream &perl) { + UMLOperation *op; + UMLAttribute *at; + + for(op=opList.first(); op ; op=opList.next()) + { + UMLAttributeList atl = op->getParmList(); + //write method doc if we have doc || if at least one of the params has doc + bool writeDoc = forceDoc() || !op->getDoc().isEmpty(); + for (at = atl.first(); at ; at = atl.next()) + writeDoc |= !at->getDoc().isEmpty(); + + if( writeDoc ) //write method documentation + { + perl << "=pod " << m_endl << m_endl << "=head3 " ; + perl << cleanName(op->getName()) << m_endl << m_endl; + + perl << " Parameters :" << m_endl ; + //write parameter documentation + for (at = atl.first(); at ; at = atl.next()) { + if(forceDoc() || !at->getDoc().isEmpty()) { + perl << " " + << cleanName(at->getName()) << " : " + << at->getTypeName() << " : " + << at->getDoc() + << m_endl; + } + }//end for : write parameter documentation + + perl << m_endl; + perl << " Return : " << m_endl; + perl << " " << op->getTypeName(); + perl << m_endl << m_endl; + perl << " Description : " << m_endl; + perl << " " << op->getDoc(); + perl << m_endl << m_endl << "=cut" << m_endl << m_endl; + }//end if : write method documentation + + perl << "sub " << cleanName(op->getName()) << m_endl << "{" << m_endl; + perl << " my($self"; + + bool bStartPrinted = false; + //write parameters + for (at = atl.first(); at; at = atl.next()) { + if (!bStartPrinted) { + bStartPrinted = true; + perl << "," << m_endl; + } + perl << " $"<< cleanName(at->getName()) << ", # " + << at->getTypeName() << " : " << at->getDoc() << m_endl; + } + + perl << " ) = @_;" << m_endl; + + perl << "#UML_MODELER_BEGIN_PERSONAL_CODE_" << cleanName(op->getName()); + perl << m_endl << "#UML_MODELER_END_PERSONAL_CODE_" << cleanName(op->getName()) << m_endl; + perl << "}" << m_endl; + perl << m_endl << m_endl; + }//end for +} + + +void PerlWriter::writeAttributes(UMLClassifier *c, QTextStream &perl) { + UMLAttributeList atpub, atprot, atpriv, atdefval; + atpub.setAutoDelete(false); + atprot.setAutoDelete(false); + atpriv.setAutoDelete(false); + atdefval.setAutoDelete(false); + + //sort attributes by scope and see if they have a default value + UMLAttributeList atl = c->getAttributeList(); + UMLAttribute *at; + for(at = atl.first(); at ; at = atl.next()) { + if(!at->getInitialValue().isEmpty()) + atdefval.append(at); + switch(at->getVisibility()) { + case Uml::Visibility::Public: + atpub.append(at); + break; + case Uml::Visibility::Protected: + atprot.append(at); + break; + case Uml::Visibility::Private: + atpriv.append(at); + break; + default: + break; + } + } + + + if(forceSections() || atpub.count()) { + writeAttributes(atpub,perl); + } + /* not needed as writeAttributes only writes documentation + if(forceSections() || atprot.count()) { + writeAttributes(atprot,perl); + } + + if(forceSections() || atpriv.count()) { + writeAttributes(atpriv,perl); + } + */ +} + + +void PerlWriter::writeAttributes(UMLAttributeList &atList, QTextStream &perl) +{ + perl << m_endl << "=head1 PUBLIC ATTRIBUTES" << m_endl << m_endl; + perl << "=pod " << m_endl << m_endl ; + for (UMLAttribute *at = atList.first(); at ; at = atList.next()) + { + if (forceDoc() || !at->getDoc().isEmpty()) + { + perl << "=head3 " << cleanName(at->getName()) << m_endl << m_endl ; + perl << " Description : " << at->getDoc() << m_endl << m_endl; + } + } // end for + perl << m_endl << m_endl << "=cut" << m_endl << m_endl; + return; +} + +QStringList PerlWriter::defaultDatatypes() { + QStringList l; + l.append("$"); + l.append("@"); + l.append("%"); + return l; +} + +const QStringList PerlWriter::reservedKeywords() const { + + static QStringList keywords; + + if (keywords.isEmpty()) { + keywords << "abs" + << "accept" + << "alarm" + << "and" + << "atan2" + << "BEGIN" + << "bind" + << "binmode" + << "bless" + << "byte" + << "caller" + << "carp" + << "chdir" + << "chmod" + << "chomp" + << "chop" + << "chown" + << "chr" + << "chroot" + << "close" + << "closedir" + << "cmp" + << "confess" + << "connect" + << "continue" + << "cos" + << "croak" + << "crypt" + << "dbmclose" + << "dbmopen" + << "defined" + << "delete" + << "die" + << "do" + << "dump" + << "each" + << "else" + << "elsif" + << "END" + << "endgrent" + << "endhostent" + << "endnetent" + << "endprotoent" + << "endpwent" + << "endservent" + << "eof" + << "eq" + << "eval" + << "exec" + << "exists" + << "exit" + << "exp" + << "fcntl" + << "fileno" + << "flock" + << "for" + << "foreach" + << "fork" + << "format" + << "formline" + << "ge" + << "getc" + << "getgrent" + << "getgrgid" + << "getgrnam" + << "gethostbyaddr" + << "gethostbyname" + << "gethostent" + << "getlogin" + << "getnetbyaddr" + << "getnetbyname" + << "getnetent" + << "getpeername" + << "getpgrp" + << "getppid" + << "getpriority" + << "getprotobyname" + << "getprotobynumber" + << "getprotoent" + << "getpwent" + << "getpwnam" + << "getpwuid" + << "getservbyname" + << "getservbyport" + << "getservent" + << "getsockname" + << "getsockopt" + << "glob" + << "gmtime" + << "goto" + << "grep" + << "gt" + << "hex" + << "if" + << "import" + << "index" + << "int" + << "integer" + << "ioctl" + << "join" + << "keys" + << "kill" + << "last" + << "lc" + << "lcfirst" + << "le" + << "length" + << "lib" + << "link" + << "listen" + << "local" + << "localtime" + << "lock" + << "log" + << "lstat" + << "lt" + << "map" + << "mkdir" + << "msgctl" + << "msgget" + << "msgrcv" + << "msgsnd" + << "my" + << "ne" + << "new" + << "next" + << "no" + << "not" + << "oct" + << "open" + << "opendir" + << "or" + << "ord" + << "our" + << "pack" + << "package" + << "pipe" + << "pop" + << "pos" + << "print" + << "printf" + << "prototype" + << "push" + << "quotemeta" + << "rand" + << "read" + << "readdir" + << "readline" + << "readlink" + << "readpipe" + << "recv" + << "redo" + << "ref" + << "rename" + << "require" + << "reset" + << "return" + << "reverse" + << "rewinddir" + << "rindex" + << "rmdir" + << "scalar" + << "seek" + << "seekdir" + << "select" + << "semctl" + << "semget" + << "semop" + << "send" + << "setgrent" + << "sethostent" + << "setnetent" + << "setpgrp" + << "setpriority" + << "setprotoent" + << "setpwent" + << "setservent" + << "setsockopt" + << "shift" + << "shmctl" + << "shmget" + << "shmread" + << "shmwrite" + << "shutdown" + << "sigtrap" + << "sin" + << "sleep" + << "socket" + << "socketpair" + << "sort" + << "splice" + << "split" + << "sprintf" + << "sqrt" + << "srand" + << "stat" + << "strict" + << "study" + << "sub" + << "subs" + << "substr" + << "switch" + << "symlink" + << "syscall" + << "sysopen" + << "sysread" + << "sysseek" + << "system" + << "syswrite" + << "tell" + << "telldir" + << "tie" + << "tied" + << "time" + << "times" + << "truncate" + << "uc" + << "ucfirst" + << "umask" + << "undef" + << "unless" + << "unlink" + << "unpack" + << "unshift" + << "untie" + << "until" + << "use" + << "utf8" + << "utime" + << "values" + << "vars" + << "vec" + << "wait" + << "waitpid" + << "wantarray" + << "warn" + << "warnings" + << "while" + << "write" + << "xor"; + } + + return keywords; +} + +#include "perlwriter.moc" diff --git a/umbrello/umbrello/codegenerators/perlwriter.h b/umbrello/umbrello/codegenerators/perlwriter.h new file mode 100644 index 00000000..9dac4e56 --- /dev/null +++ b/umbrello/umbrello/codegenerators/perlwriter.h @@ -0,0 +1,101 @@ +/*************************************************************************** + perlwriter.h - description + ------------------- + begin : Wed Jan 22 2003 + copyright : (C) 2003 by David Hugh-Jones + email : hughjonesd@yahoo.co.uk + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef PERLWRITER_H +#define PERLWRITER_H + +#include "simplecodegenerator.h" +#include "../umlattributelist.h" +#include "../umloperationlist.h" + +class UMLOperation; +class UMLAttribute; +class UMLClassifier; + +/** + * class PerlWriter is a Perl code generator for UMLClassifier objects + * Just call writeClass and feed it a UMLClassifier; + */ +class PerlWriter : public SimpleCodeGenerator { + Q_OBJECT +public: + + PerlWriter(); + virtual ~PerlWriter(); + + /** + * call this method to generate Perl code for a UMLClassifier + * @param c the class you want to generate code for. + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "Perl" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + + QStringList defaultDatatypes(); + +private: + + /** + * we do not want to write the comment "Private methods" twice + * not sure whether this is php specific + */ + bool bPrivateSectionCommentIsWritten; + + /** + * write all operations for a given class + * + * @param c the concept we are generating code for + * @param perl output stream for the Perl file + */ + void writeOperations(UMLClassifier *c, QTextStream &perl); + + /** + * write a list of class operations + * + * @param classname the name of the class + * @param opList the list of operations + * @param perl output stream for the Perl file + */ + void writeOperations(const QString &classname, UMLOperationList &opList, + QTextStream &perl); + + /** write all the attributes of a class + * @param c the class we are generating code for + * @param perl output stream for the Perl file + */ + void writeAttributes(UMLClassifier *c, QTextStream &perl); + + /** write a list of class attributes + * @param atList the list of attributes + * @param perl output stream for the Perl file + */ + void writeAttributes(UMLAttributeList &atList, QTextStream &perl); + + bool GetUseStatements(UMLClassifier *c, QString &Ret, + QString &ThisPkgName); + +}; + +#endif //PERLWRITER diff --git a/umbrello/umbrello/codegenerators/php5writer.cpp b/umbrello/umbrello/codegenerators/php5writer.cpp new file mode 100644 index 00000000..044d3afe --- /dev/null +++ b/umbrello/umbrello/codegenerators/php5writer.cpp @@ -0,0 +1,3418 @@ +/*************************************************************************** + begin : Thu Oct 17 2002 + copyright : (C) 2002 by Heiko Nardmann + email : h.nardmann@secunet.de + (C) 2003-2006 Umbrello UML Modeller Authors <uml-devel@uml.sf.net> + php5 version by Thorsten Kunz (tk AT bytecrash DOT 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. * + * * + ***************************************************************************/ + +#include "php5writer.h" + +#include <kdebug.h> +#include <qregexp.h> +#include <qtextstream.h> + +#include "../umldoc.h" +#include "../classifier.h" +#include "../association.h" +#include "../attribute.h" +#include "../operation.h" +#include "../umlnamespace.h" + +static const char *php5words[] = + { + "abs", + "abstract", + "acos", + "acosh", + "add", + "addAction", + "addColor", + "addEntry", + "addFill", + "addShape", + "addString", + "add_namespace", + "addcslashes", + "addslashes", + "addstring", + "aggregate", + "aggregate_info", + "aggregate_methods", + "aggregate_methods_by_list", + "aggregate_methods_by_regexp", + "aggregate_properties", + "aggregate_properties_by_list", + "aggregate_properties_by_regexp", + "aggregation_info", + "align", + "apache_child_terminate", + "apache_lookup_uri", + "apache_note", + "apache_request_headers", + "apache_response_headers", + "apache_setenv", + "append_child", + "append_sibling", + "array", + "array_change_key_case", + "array_chunk", + "array_count_values", + "array_diff", + "array_diff_assoc", + "array_fill", + "array_filter", + "array_flip", + "array_intersect", + "array_intersect_assoc", + "array_key_exists", + "array_keys", + "array_map", + "array_merge", + "array_merge_recursive", + "array_multisort", + "array_pad", + "array_pop", + "array_push", + "array_rand", + "array_reduce", + "array_reverse", + "array_search", + "array_shift", + "array_slice", + "array_splice", + "array_sum", + "array_unique", + "array_unshift", + "array_values", + "array_walk", + "arsort", + "ascii2ebcdic", + "asin", + "asinh", + "asort", + "aspell_check", + "aspell_new", + "aspell_suggest", + "assert", + "assert_options", + "assign", + "atan", + "atan2", + "atanh", + "attreditable", + "attributes", + "base64_decode", + "base64_encode", + "base_convert", + "basename", + "bcadd", + "bccomp", + "bcdiv", + "bcmod", + "bcmul", + "bcpow", + "bcpowmod", + "bcscale", + "bcsqrt", + "bcsub", + "bin2hex", + "bindec", + "bindtextdomain", + "bind_textdomain_codeset", + "bool", + "break", + "bzclose", + "bzcompress", + "bzdecompress", + "bzerrno", + "bzerror", + "bzerrstr", + "bzflush", + "bzopen", + "bzread", + "bzwrite", + "cal_days_in_month", + "cal_from_jd", + "cal_info", + "call_user_func", + "call_user_func_array", + "call_user_method", + "call_user_method_array", + "cal_to_jd", + "ccvs_add", + "ccvs_auth", + "ccvs_command", + "ccvs_count", + "ccvs_delete", + "ccvs_done", + "ccvs_init", + "ccvs_lookup", + "ccvs_new", + "ccvs_report", + "ccvs_return", + "ccvs_reverse", + "ccvs_sale", + "ccvs_status", + "ccvs_textvalue", + "ccvs_void", + "ceil", + "chdir", + "checkdate", + "checkdnsrr", + "checkin", + "checkout", + "chgrp", + "child_nodes", + "children", + "chmod", + "chop", + "chown", + "chr", + "chroot", + "chunk_split", + "class", + "class_exists", + "clearstatcache", + "clone_node", + "closedir", + "closelog", + "com_addref", + "com_get", + "com_invoke", + "com_isenum", + "com_load", + "com_load_typelib", + "compact", + "com_propget", + "com_propput", + "com_propset", + "com_release", + "com_set", + "connection_aborted", + "connection_status", + "connection_timeout", + "constant", + "content", + "continue", + "convert_cyr_string", + "_COOKIE", + "copy", + "cos", + "cosh", + "count", + "count_chars", + "cpdf_add_annotation", + "cpdf_add_outline", + "cpdf_arc", + "cpdf_begin_text", + "cpdf_circle", + "cpdf_clip", + "cpdf_close", + "cpdf_closepath", + "cpdf_closepath_fill_stroke", + "cpdf_closepath_stroke", + "cpdf_continue_text", + "cpdf_curveto", + "cpdf_end_text", + "cpdf_fill", + "cpdf_fill_stroke", + "cpdf_finalize", + "cpdf_finalize_page", + "cpdf_global_set_document_limits", + "cpdf_import_jpeg", + "cpdf_lineto", + "cpdf_moveto", + "cpdf_newpath", + "cpdf_open", + "cpdf_output_buffer", + "cpdf_page_init", + "cpdf_place_inline_image", + "cpdf_rect", + "cpdf_restore", + "cpdf_rlineto", + "cpdf_rmoveto", + "cpdf_rotate", + "cpdf_rotate_text", + "cpdf_save", + "cpdf_save_to_file", + "cpdf_scale", + "cpdf_set_action_url", + "cpdf_set_char_spacing", + "cpdf_set_creator", + "cpdf_set_current_page", + "cpdf_setdash", + "cpdf_setflat", + "cpdf_set_font", + "cpdf_set_font_directories", + "cpdf_set_font_map_file", + "cpdf_setgray", + "cpdf_setgray_fill", + "cpdf_setgray_stroke", + "cpdf_set_horiz_scaling", + "cpdf_set_keywords", + "cpdf_set_leading", + "cpdf_setlinecap", + "cpdf_setlinejoin", + "cpdf_setlinewidth", + "cpdf_setmiterlimit", + "cpdf_set_page_animation", + "cpdf_setrgbcolor", + "cpdf_setrgbcolor_fill", + "cpdf_setrgbcolor_stroke", + "cpdf_set_subject", + "cpdf_set_text_matrix", + "cpdf_set_text_pos", + "cpdf_set_text_rendering", + "cpdf_set_text_rise", + "cpdf_set_title", + "cpdf_set_viewer_preferences", + "cpdf_set_word_spacing", + "cpdf_show", + "cpdf_show_xy", + "cpdf_stringwidth", + "cpdf_stroke", + "cpdf_text", + "cpdf_translate", + "crack_check", + "crack_closedict", + "crack_getlastmessage", + "crack_opendict", + "crc32", + "create_attribute", + "create_cdata_section", + "create_comment", + "create_element", + "create_element_ns", + "create_entity_reference", + "create_function", + "create_processing_instruction", + "create_text_node", + "crypt", + "ctype_alnum", + "ctype_alpha", + "ctype_cntrl", + "ctype_digit", + "ctype_graph", + "ctype_lower", + "ctype_print", + "ctype_punct", + "ctype_space", + "ctype_upper", + "ctype_xdigit", + "curl_close", + "curl_errno", + "curl_error", + "curl_exec", + "curl_getinfo", + "curl_init", + "curl_setopt", + "curl_version", + "current", + "cybercash_base64_decode", + "cybercash_base64_encode", + "cybercash_decr", + "cybercash_encr", + "cybermut_creerformulairecm", + "cybermut_creerreponsecm", + "cybermut_testmac", + "cyrus_authenticate", + "cyrus_bind", + "cyrus_close", + "cyrus_connect", + "cyrus_query", + "cyrus_unbind", + "data", + "date", + "dba_close", + "dba_delete", + "dba_exists", + "dba_fetch", + "dba_firstkey", + "dba_handlers", + "dba_insert", + "dba_list", + "dba_nextkey", + "dba_open", + "dba_optimize", + "dba_popen", + "dba_replace", + "dbase_add_record", + "dbase_close", + "dbase_create", + "dbase_delete_record", + "dbase_get_record", + "dbase_get_record_with_names", + "dbase_numfields", + "dbase_numrecords", + "dbase_open", + "dbase_pack", + "dbase_replace_record", + "dba_sync", + "dblist", + "dbmclose", + "dbmdelete", + "dbmexists", + "dbmfetch", + "dbmfirstkey", + "dbminsert", + "dbmnextkey", + "dbmopen", + "dbmreplace", + "dbplus_add", + "dbplus_aql", + "dbplus_chdir", + "dbplus_close", + "dbplus_curr", + "dbplus_errcode", + "dbplus_errno", + "dbplus_find", + "dbplus_first", + "dbplus_flush", + "dbplus_freealllocks", + "dbplus_freelock", + "dbplus_freerlocks", + "dbplus_getlock", + "dbplus_getunique", + "dbplus_info", + "dbplus_last", + "dbplus_lockrel", + "dbplus_next", + "dbplus_open", + "dbplus_prev", + "dbplus_rchperm", + "dbplus_rcreate", + "dbplus_rcrtexact", + "dbplus_rcrtlike", + "dbplus_resolve", + "dbplus_restorepos", + "dbplus_rkeys", + "dbplus_ropen", + "dbplus_rquery", + "dbplus_rrename", + "dbplus_rsecindex", + "dbplus_runlink", + "dbplus_rzap", + "dbplus_savepos", + "dbplus_setindex", + "dbplus_setindexbynumber", + "dbplus_sql", + "dbplus_tcl", + "dbplus_tremove", + "dbplus_undo", + "dbplus_undoprepare", + "dbplus_unlockrel", + "dbplus_unselect", + "dbplus_update", + "dbplus_xlockrel", + "dbplus_xunlockrel", + "dbstat", + "dbx_close", + "dbx_compare", + "dbx_connect", + "dbx_error", + "dbx_escape_string", + "dbx_query", + "dbx_sort", + "dcgettext", + "dcngettext", + "dcstat", + "deaggregate", + "debug_backtrace", + "debugger_off", + "debugger_on", + "decbin", + "dechex", + "declare", + "decoct", + "DEFAULT_INCLUDE_PATH", + "define", + "defined", + "define_syslog_variables", + "deg2rad", + "delete", + "description", + "dgettext", + "die", + "dio_close", + "dio_fcntl", + "dio_open", + "dio_read", + "dio_seek", + "dio_stat", + "dio_tcsetattr", + "dio_truncate", + "dio_write", + "dir", + "dirname", + "disk_free_space", + "diskfreespace", + "disk_total_space", + "dl", + "dngettext", + "dns_check_record", + "dns_get_mx", + "dns_get_record", + "do", + "doctype", + "document_element", + "DOCUMENT_ROOT", + "domxml_new_doc", + "domxml_open_file", + "domxml_open_mem", + "domxml_version", + "domxml_xmltree", + "domxml_xslt_stylesheet", + "domxml_xslt_stylesheet_doc", + "domxml_xslt_stylesheet_file", + "dotnet_load", + "doubleval", + "drawCurve", + "drawCurveTo", + "drawLine", + "drawLineTo", + "dstanchors", + "dstofsrcanchors", + "dump_file", + "dump_mem", + "dump_node", + "each", + "E_ALL", + "easter_date", + "easter_days", + "ebcdic2ascii", + "echo", + "E_COMPILE_ERROR", + "E_COMPILE_WARNING", + "E_CORE_ERROR", + "E_CORE_WARNING", + "E_ERROR", + "else", + "elseif", + "empty", + "end", + "endfor", + "endforeach", + "endif", + "endswitch", + "endwhile", + "E_NOTICE", + "entities", + "_ENV", + "E_PARSE", + "ereg", + "eregi", + "eregi_replace", + "ereg_replace", + "error_log", + "error_reporting", + "escapeshellarg", + "escapeshellcmd", + "E_USER_ERROR", + "E_USER_NOTICE", + "E_USER_WARNING", + "eval", + "E_WARNING", + "exec", + "exif_imagetype", + "exif_read_data", + "exif_thumbnail", + "exit", + "exp", + "explode", + "expm1", + "extension_loaded", + "extract", + "ezmlm_hash", + "FALSE", + "fbsql_affected_rows", + "fbsql_autocommit", + "fbsql_change_user", + "fbsql_close", + "fbsql_commit", + "fbsql_connect", + "fbsql_create_blob", + "fbsql_create_clob", + "fbsql_create_db", + "fbsql_database", + "fbsql_database_password", + "fbsql_data_seek", + "fbsql_db_query", + "fbsql_db_status", + "fbsql_drop_db", + "fbsql_errno", + "fbsql_error", + "fbsql_fetch_array", + "fbsql_fetch_assoc", + "fbsql_fetch_field", + "fbsql_fetch_lengths", + "fbsql_fetch_object", + "fbsql_fetch_row", + "fbsql_field_flags", + "fbsql_field_len", + "fbsql_field_name", + "fbsql_field_seek", + "fbsql_field_table", + "fbsql_field_type", + "fbsql_free_result", + "fbsql_get_autostart_info", + "fbsql_hostname", + "fbsql_insert_id", + "fbsql_list_dbs", + "fbsql_list_fields", + "fbsql_list_tables", + "fbsql_next_result", + "fbsql_num_fields", + "fbsql_num_rows", + "fbsql_password", + "fbsql_pconnect", + "fbsql_query", + "fbsql_read_blob", + "fbsql_read_clob", + "fbsql_result", + "fbsql_rollback", + "fbsql_select_db", + "fbsql_set_lob_mode", + "fbsql_set_transaction", + "fbsql_start_db", + "fbsql_stop_db", + "fbsql_tablename", + "fbsql_username", + "fbsql_warnings", + "fclose", + "fdf_add_doc_javascript", + "fdf_add_template", + "fdf_close", + "fdf_create", + "fdf_errno", + "fdf_error", + "fdf_get_ap", + "fdf_get_attachment", + "fdf_get_encoding", + "fdf_get_file", + "fdf_get_status", + "fdf_get_value", + "fdf_get_version", + "fdf_header", + "fdf_next_field_name", + "fdf_open", + "fdf_open_string", + "fdf_save", + "fdf_save_string", + "fdf_set_ap", + "fdf_set_encoding", + "fdf_set_file", + "fdf_set_flags", + "fdf_set_javascript_action", + "fdf_set_opt", + "fdf_set_status", + "fdf_set_submit_form_action", + "fdf_set_target_frame", + "fdf_set_value", + "fdf_set_version", + "feof", + "fflush", + "fgetc", + "fgetcsv", + "fgets", + "fgetss", + "file", + "__FILE__", + "fileatime", + "filectime", + "file_exists", + "file_get_contents", + "filegroup", + "fileinode", + "filemtime", + "fileowner", + "fileperms", + "filepro", + "filepro_fieldcount", + "filepro_fieldname", + "filepro_fieldtype", + "filepro_fieldwidth", + "filepro_retrieve", + "filepro_rowcount", + "_FILES", + "filesize", + "filetype", + "find", + "first_child", + "floatval", + "flock", + "floor", + "flush", + "fmod", + "fnmatch", + "fopen", + "for", + "foreach", + "fpassthru", + "fprintf", + "fputs", + "fread", + "frenchtojd", + "fribidi_log2vis", + "fscanf", + "fseek", + "fsockopen", + "fstat", + "ftell", + "ftok", + "ftp_cdup", + "ftp_chdir", + "ftp_close", + "ftp_connect", + "ftp_delete", + "ftp_exec", + "ftp_fget", + "ftp_fput", + "ftp_get", + "ftp_get_option", + "ftp_login", + "ftp_mdtm", + "ftp_mkdir", + "ftp_nb_continue", + "ftp_nb_fget", + "ftp_nb_fput", + "ftp_nb_get", + "ftp_nb_put", + "ftp_nlist", + "ftp_pasv", + "ftp_put", + "ftp_pwd", + "ftp_quit", + "ftp_rawlist", + "ftp_rename", + "ftp_rmdir", + "ftp_set_option", + "ftp_site", + "ftp_size", + "ftp_ssl_connect", + "ftp_systype", + "ftruncate", + "ftstat", + "func_get_arg", + "func_get_args", + "func_num_args", + "function", + "function_exists", + "fwrite", + "GATEWAY_INTERFACE", + "gd_info", + "_GET", + "getallheaders", + "get_attribute", + "get_attribute_node", + "get_browser", + "get_cfg_var", + "get_class", + "get_class_methods", + "get_class_vars", + "get_content", + "get_current_user", + "getcwd", + "getdate", + "get_declared_classes", + "get_defined_constants", + "get_defined_functions", + "get_defined_vars", + "get_element_by_id", + "get_elements_by_tagname", + "getenv", + "get_extension_funcs", + "getHeight", + "gethostbyaddr", + "gethostbyname", + "gethostbynamel", + "get_html_translation_table", + "getimagesize", + "get_included_files", + "get_include_path", + "getlastmod", + "get_loaded_extensions", + "get_magic_quotes_gpc", + "get_magic_quotes_runtime", + "get_meta_tags", + "getmxrr", + "getmygid", + "getmyinode", + "getmypid", + "getmyuid", + "get_object_vars", + "getopt", + "get_parent_class", + "getprotobyname", + "getprotobynumber", + "getrandmax", + "get_required_files", + "get_resource_type", + "getrusage", + "getservbyname", + "getservbyport", + "getshape1", + "getshape2", + "gettext", + "gettimeofday", + "gettype", + "getwidth", + "getWidth", + "glob", + "global", + "GLOBALS", + "gmdate", + "gmmktime", + "gmp_abs", + "gmp_add", + "gmp_and", + "gmp_clrbit", + "gmp_cmp", + "gmp_com", + "gmp_div", + "gmp_divexact", + "gmp_div_q", + "gmp_div_qr", + "gmp_div_r", + "gmp_fact", + "gmp_gcd", + "gmp_gcdext", + "gmp_hamdist", + "gmp_init", + "gmp_intval", + "gmp_invert", + "gmp_jacobi", + "gmp_legendre", + "gmp_mod", + "gmp_mul", + "gmp_neg", + "gmp_or", + "gmp_perfect_square", + "gmp_popcount", + "gmp_pow", + "gmp_powm", + "gmp_prob_prime", + "gmp_random", + "gmp_scan0", + "gmp_scan1", + "gmp_setbit", + "gmp_sign", + "gmp_sqrt", + "gmp_sqrtrm", + "gmp_strval", + "gmp_sub", + "gmp_xor", + "gmstrftime", + "gregoriantojd", + "gzclose", + "gzcompress", + "gzdeflate", + "gzencode", + "gzeof", + "gzfile", + "gzgetc", + "gzgets", + "gzgetss", + "gzinflate", + "gzopen", + "gzpassthru", + "gzputs", + "gzread", + "gzrewind", + "gzseek", + "gztell", + "gzuncompress", + "gzwrite", + "has_attribute", + "has_attributess", + "has_child_nodes", + "header", + "headers_sent", + "hebrev", + "hebrevc", + "hexdec", + "highlight_file", + "highlight_string", + "html_dump_mem", + "htmlentities", + "html_entity_decode", + "htmlspecialchars", + "HTTP_ACCEPT", + "HTTP_ACCEPT_CHARSET", + "HTTP_ACCEPT_LANGUAGE", + "HTTP_CONNECTION", + "HTTP_COOKIE_VARS", + "HTTP_ENCODING", + "HTTP_ENV_VARS", + "HTTP_GET_VARS", + "HTTP_HOST", + "HTTP_POST_FILES", + "HTTP_POST_VARS", + "HTTP_RAW_POST_DATA", + "HTTP_REFERER", + "HTTP_SERVER_VARS", + "HTTP_SESSION_VARS", + "HTTP_STATE_VARS", + "HTTP_USER_AGENT", + "hw_api_attribute", + "hw_api_content", + "hwapi_hgcsp", + "hw_api_object", + "hw_Array2Objrec", + "hw_changeobject", + "hw_Children", + "hw_ChildrenObj", + "hw_Close", + "hw_Connect", + "hw_connection_info", + "hw_Cp", + "hw_Deleteobject", + "hw_DocByAnchor", + "hw_DocByAnchorObj", + "hw_Document_Attributes", + "hw_Document_BodyTag", + "hw_Document_Content", + "hw_Document_SetContent", + "hw_Document_Size", + "hw_dummy", + "hw_EditText", + "hw_Error", + "hw_ErrorMsg", + "hw_Free_Document", + "hw_GetAnchors", + "hw_GetAnchorsObj", + "hw_GetAndLock", + "hw_GetChildColl", + "hw_GetChildCollObj", + "hw_GetChildDocColl", + "hw_GetChildDocCollObj", + "hw_GetObject", + "hw_GetObjectByQuery", + "hw_GetObjectByQueryColl", + "hw_GetObjectByQueryCollObj", + "hw_GetObjectByQueryObj", + "hw_GetParents", + "hw_GetParentsObj", + "hw_getrellink", + "hw_GetRemote", + "hw_GetRemoteChildren", + "hw_GetSrcByDestObj", + "hw_GetText", + "hw_getusername", + "hw_Identify", + "hw_InCollections", + "hw_Info", + "hw_InsColl", + "hw_InsDoc", + "hw_insertanchors", + "hw_InsertDocument", + "hw_InsertObject", + "hw_mapid", + "hw_Modifyobject", + "hw_Mv", + "hw_New_Document", + "hw_Objrec2Array", + "hw_Output_Document", + "hw_pConnect", + "hw_PipeDocument", + "hw_Root", + "hw_setlinkroot", + "hw_stat", + "hwstat", + "hw_Unlock", + "hw_Who", + "hypot", + "ibase_blob_add", + "ibase_blob_cancel", + "ibase_blob_close", + "ibase_blob_create", + "ibase_blob_echo", + "ibase_blob_get", + "ibase_blob_import", + "ibase_blob_info", + "ibase_blob_open", + "ibase_close", + "ibase_commit", + "ibase_connect", + "ibase_errmsg", + "ibase_execute", + "ibase_fetch_object", + "ibase_fetch_row", + "ibase_field_info", + "ibase_free_query", + "ibase_free_result", + "ibase_num_fields", + "ibase_pconnect", + "ibase_prepare", + "ibase_query", + "ibase_rollback", + "ibase_timefmt", + "ibase_trans", + "iconv", + "iconv_get_encoding", + "iconv_set_encoding", + "identify", + "if", + "ifx_affected_rows", + "ifx_blobinfile_mode", + "ifx_byteasvarchar", + "ifx_close", + "ifx_connect", + "ifx_copy_blob", + "ifx_create_blob", + "ifx_create_char", + "ifx_do", + "ifx_error", + "ifx_errormsg", + "ifx_fetch_row", + "ifx_fieldproperties", + "ifx_fieldtypes", + "ifx_free_blob", + "ifx_free_char", + "ifx_free_result", + "ifx_get_blob", + "ifx_get_char", + "ifx_getsqlca", + "ifx_htmltbl_result", + "ifx_nullformat", + "ifx_num_fields", + "ifx_num_rows", + "ifx_pconnect", + "ifx_prepare", + "ifx_query", + "ifx_textasvarchar", + "ifx_update_blob", + "ifx_update_char", + "ifxus_close_slob", + "ifxus_create_slob", + "ifxus_free_slob", + "ifxus_open_slob", + "ifxus_read_slob", + "ifxus_seek_slob", + "ifxus_tell_slob", + "ifxus_write_slob", + "ignore_user_abort", + "image2wbmp", + "imagealphablending", + "imagearc", + "imagechar", + "imagecharup", + "imagecolorallocate", + "imagecolorallocatealpha", + "imagecolorat", + "imagecolorclosest", + "imagecolorclosestalpha", + "imagecolorclosesthwb", + "imagecolordeallocate", + "imagecolorexact", + "imagecolorexactalpha", + "imagecolorresolve", + "imagecolorresolvealpha", + "imagecolorset", + "imagecolorsforindex", + "imagecolorstotal", + "imagecolortransparent", + "imagecopy", + "imagecopymerge", + "imagecopymergegray", + "imagecopyresampled", + "imagecopyresized", + "imagecreate", + "imagecreatefromgd", + "imagecreatefromgd2", + "imagecreatefromgd2part", + "imagecreatefromgif", + "imagecreatefromjpeg", + "imagecreatefrompng", + "imagecreatefromstring", + "imagecreatefromwbmp", + "imagecreatefromxbm", + "imagecreatefromxpm", + "imagecreatetruecolor", + "imagedashedline", + "imagedestroy", + "imageellipse", + "imagefill", + "imagefilledarc", + "imagefilledellipse", + "imagefilledpolygon", + "imagefilledrectangle", + "imagefilltoborder", + "imagefontheight", + "imagefontwidth", + "imageftbbox", + "imagefttext", + "imagegammacorrect", + "imagegd", + "imagegd2", + "imagegif", + "imageinterlace", + "imagejpeg", + "imageline", + "imageloadfont", + "imagepalettecopy", + "imagepng", + "imagepolygon", + "imagepsbbox", + "imagepscopyfont", + "imagepsencodefont", + "imagepsextendfont", + "imagepsfreefont", + "imagepsloadfont", + "imagepsslantfont", + "imagepstext", + "imagerectangle", + "imagerotate", + "imagesetbrush", + "imagesetpixel", + "imagesetstyle", + "imagesetthickness", + "imagesettile", + "imagestring", + "imagestringup", + "imagesx", + "imagesy", + "imagetruecolortopalette", + "imagettfbbox", + "imagettftext", + "imagetypes", + "image_type_to_mime_type", + "imagewbmp", + "imap_8bit", + "imap_alerts", + "imap_append", + "imap_base64", + "imap_binary", + "imap_body", + "imap_bodystruct", + "imap_check", + "imap_clearflag_full", + "imap_close", + "imap_createmailbox", + "imap_delete", + "imap_deletemailbox", + "imap_errors", + "imap_expunge", + "imap_fetchbody", + "imap_fetchheader", + "imap_fetch_overview", + "imap_fetchstructure", + "imap_getmailboxes", + "imap_get_quota", + "imap_get_quotaroot", + "imap_getsubscribed", + "imap_header", + "imap_headerinfo", + "imap_headers", + "imap_last_error", + "imap_list", + "imap_listmailbox", + "imap_listscan", + "imap_listsubscribed", + "imap_lsub", + "imap_mail", + "imap_mailboxmsginfo", + "imap_mail_compose", + "imap_mail_copy", + "imap_mail_move", + "imap_mime_header_decode", + "imap_msgno", + "imap_num_msg", + "imap_num_recent", + "imap_open", + "imap_ping", + "imap_qprint", + "imap_renamemailbox", + "imap_reopen", + "imap_rfc822_parse_adrlist", + "imap_rfc822_parse_headers", + "imap_rfc822_write_address", + "imap_scanmailbox", + "imap_search", + "imap_setacl", + "imap_setflag_full", + "imap_set_quota", + "imap_sort", + "imap_status", + "imap_subscribe", + "imap_thread", + "imap_uid", + "imap_undelete", + "imap_unsubscribe", + "imap_utf7_decode", + "imap_utf7_encode", + "imap_utf8", + "implements", + "implode", + "import_request_variables", + "in_array", + "include", + "include_once", + "info", + "ingres_autocommit", + "ingres_close", + "ingres_commit", + "ingres_connect", + "ingres_fetch_array", + "ingres_fetch_object", + "ingres_fetch_row", + "ingres_field_length", + "ingres_field_name", + "ingres_field_nullable", + "ingres_field_precision", + "ingres_field_scale", + "ingres_field_type", + "ingres_num_fields", + "ingres_num_rows", + "ingres_pconnect", + "ingres_query", + "ingres_rollback", + "ini_alter", + "ini_get", + "ini_get_all", + "ini_restore", + "ini_set", + "insert", + "insertanchor", + "insert_before", + "insertcollection", + "insertdocument", + "int", + "interface", + "internal_subset", + "intval", + "ip2long", + "iptcembed", + "iptcparse", + "ircg_channel_mode", + "ircg_disconnect", + "ircg_fetch_error_msg", + "ircg_get_username", + "ircg_html_encode", + "ircg_ignore_add", + "ircg_ignore_del", + "ircg_is_conn_alive", + "ircg_join", + "ircg_kick", + "ircg_lookup_format_messages", + "ircg_msg", + "ircg_nick", + "ircg_nickname_escape", + "ircg_nickname_unescape", + "ircg_notice", + "ircg_part", + "ircg_pconnect", + "ircg_register_format_messages", + "ircg_set_current", + "ircg_set_file", + "ircg_set_on_die", + "ircg_topic", + "ircg_whois", + "is_a", + "is_array", + "is_blank_node", + "is_bool", + "is_callable", + "is_dir", + "is_double", + "is_executable", + "is_file", + "is_finite", + "is_float", + "is_infinite", + "is_int", + "is_integer", + "is_link", + "is_long", + "is_nan", + "is_null", + "is_numeric", + "is_object", + "is_readable", + "is_real", + "is_resource", + "is_scalar", + "isset", + "is_string", + "is_subclass_of", + "is_uploaded_file", + "is_writable", + "is_writeable", + "java_last_exception_clear", + "java_last_exception_get", + "jddayofweek", + "jdmonthname", + "jdtofrench", + "jdtogregorian", + "jdtojewish", + "jdtojulian", + "jdtounix", + "jewishtojd", + "join", + "jpeg2wbmp", + "juliantojd", + "key", + "krsort", + "ksort", + "langdepvalue", + "last_child", + "lcg_value", + "ldap_8859_to_t61", + "ldap_add", + "ldap_bind", + "ldap_close", + "ldap_compare", + "ldap_connect", + "ldap_count_entries", + "ldap_delete", + "ldap_dn2ufn", + "ldap_err2str", + "ldap_errno", + "ldap_error", + "ldap_explode_dn", + "ldap_first_attribute", + "ldap_first_entry", + "ldap_first_reference", + "ldap_free_result", + "ldap_get_attributes", + "ldap_get_dn", + "ldap_get_entries", + "ldap_get_option", + "ldap_get_values", + "ldap_get_values_len", + "ldap_list", + "ldap_mod_add", + "ldap_mod_del", + "ldap_modify", + "ldap_mod_replace", + "ldap_next_attribute", + "ldap_next_entry", + "ldap_next_reference", + "ldap_parse_reference", + "ldap_parse_result", + "ldap_read", + "ldap_rename", + "ldap_search", + "ldap_set_option", + "ldap_set_rebind_proc", + "ldap_sort", + "ldap_start_tls", + "ldap_t61_to_8859", + "ldap_unbind", + "levenshtein", + "__LINE__", + "link", + "linkinfo", + "list", + "localeconv", + "localtime", + "lock", + "log", + "log10", + "log1p", + "long2ip", + "lstat", + "ltrim", + "mail", + "mailparse_determine_best_xfer_encoding", + "mailparse_msg_create", + "mailparse_msg_extract_part", + "mailparse_msg_extract_part_file", + "mailparse_msg_free", + "mailparse_msg_get_part", + "mailparse_msg_get_part_data", + "mailparse_msg_get_structure", + "mailparse_msg_parse", + "mailparse_msg_parse_file", + "mailparse_rfc822_parse_addresses", + "mailparse_stream_encode", + "mailparse_uudecode_all", + "main", + "max", + "mb_convert_case", + "mb_convert_encoding", + "mb_convert_kana", + "mb_convert_variables", + "mb_decode_mimeheader", + "mb_decode_numericentity", + "mb_detect_encoding", + "mb_detect_order", + "mb_encode_mimeheader", + "mb_encode_numericentity", + "mb_ereg", + "mb_eregi", + "mb_eregi_replace", + "mb_ereg_match", + "mb_ereg_replace", + "mb_ereg_search", + "mb_ereg_search_getpos", + "mb_ereg_search_getregs", + "mb_ereg_search_init", + "mb_ereg_search_pos", + "mb_ereg_search_regs", + "mb_ereg_search_setpos", + "mb_get_info", + "mb_http_input", + "mb_http_output", + "mb_internal_encoding", + "mb_language", + "mb_output_handler", + "mb_parse_str", + "mb_preferred_mime_name", + "mb_regex_encoding", + "mb_regex_set_options", + "mb_send_mail", + "mb_split", + "mb_strcut", + "mb_strimwidth", + "mb_strlen", + "mb_strpos", + "mb_strrpos", + "mb_strtolower", + "mb_strtoupper", + "mb_strwidth", + "mb_substitute_character", + "mb_substr", + "mb_substr_count", + "mcal_append_event", + "mcal_close", + "mcal_create_calendar", + "mcal_date_compare", + "mcal_date_valid", + "mcal_day_of_week", + "mcal_day_of_year", + "mcal_days_in_month", + "mcal_delete_calendar", + "mcal_delete_event", + "mcal_event_add_attribute", + "mcal_event_init", + "mcal_event_set_alarm", + "mcal_event_set_category", + "mcal_event_set_class", + "mcal_event_set_description", + "mcal_event_set_end", + "mcal_event_set_recur_daily", + "mcal_event_set_recur_monthly_mday", + "mcal_event_set_recur_monthly_wday", + "mcal_event_set_recur_none", + "mcal_event_set_recur_weekly", + "mcal_event_set_recur_yearly", + "mcal_event_set_start", + "mcal_event_set_title", + "mcal_expunge", + "mcal_fetch_current_stream_event", + "mcal_fetch_event", + "mcal_is_leap_year", + "mcal_list_alarms", + "mcal_list_events", + "mcal_next_recurrence", + "mcal_open", + "mcal_popen", + "mcal_rename_calendar", + "mcal_reopen", + "mcal_snooze", + "mcal_store_event", + "mcal_time_valid", + "mcal_week_of_year", + "mcrypt_cbc", + "mcrypt_cfb", + "mcrypt_create_iv", + "mcrypt_decrypt", + "mcrypt_ecb", + "mcrypt_enc_get_algorithms_name", + "mcrypt_enc_get_block_size", + "mcrypt_enc_get_iv_size", + "mcrypt_enc_get_key_size", + "mcrypt_enc_get_modes_name", + "mcrypt_enc_get_supported_key_sizes", + "mcrypt_enc_is_block_algorithm", + "mcrypt_enc_is_block_algorithm_mode", + "mcrypt_enc_is_block_mode", + "mcrypt_encrypt", + "mcrypt_enc_self_test", + "mcrypt_generic", + "mcrypt_generic_deinit", + "mcrypt_generic_end", + "mcrypt_generic_init", + "mcrypt_get_block_size", + "mcrypt_get_cipher_name", + "mcrypt_get_iv_size", + "mcrypt_get_key_size", + "mcrypt_list_algorithms", + "mcrypt_list_modes", + "mcrypt_module_close", + "mcrypt_module_get_algo_block_size", + "mcrypt_module_get_algo_key_size", + "mcrypt_module_get_supported_key_sizes", + "mcrypt_module_is_block_algorithm", + "mcrypt_module_is_block_algorithm_mode", + "mcrypt_module_is_block_mode", + "mcrypt_module_open", + "mcrypt_module_self_test", + "mcrypt_ofb", + "mcve_adduser", + "mcve_adduserarg", + "mcve_bt", + "mcve_checkstatus", + "mcve_chkpwd", + "mcve_chngpwd", + "mcve_completeauthorizations", + "mcve_connect", + "mcve_connectionerror", + "mcve_deleteresponse", + "mcve_deletetrans", + "mcve_deleteusersetup", + "mcve_deluser", + "mcve_destroyconn", + "mcve_destroyengine", + "mcve_disableuser", + "mcve_edituser", + "mcve_enableuser", + "mcve_force", + "mcve_getcell", + "mcve_getcellbynum", + "mcve_getcommadelimited", + "mcve_getheader", + "mcve_getuserarg", + "mcve_getuserparam", + "mcve_gft", + "mcve_gl", + "mcve_gut", + "mcve_initconn", + "mcve_initengine", + "mcve_initusersetup", + "mcve_iscommadelimited", + "mcve_liststats", + "mcve_listusers", + "mcve_maxconntimeout", + "mcve_monitor", + "mcve_numcolumns", + "mcve_numrows", + "mcve_override", + "mcve_parsecommadelimited", + "mcve_ping", + "mcve_preauth", + "mcve_preauthcompletion", + "mcve_qc", + "mcve_responseparam", + "mcve_return", + "mcve_returncode", + "mcve_returnstatus", + "mcve_sale", + "mcve_setblocking", + "mcve_setdropfile", + "mcve_setip", + "mcve_setssl", + "mcve_settimeout", + "mcve_settle", + "mcve_text_avs", + "mcve_text_code", + "mcve_text_cv", + "mcve_transactionauth", + "mcve_transactionavs", + "mcve_transactionbatch", + "mcve_transactioncv", + "mcve_transactionid", + "mcve_transactionitem", + "mcve_transactionssent", + "mcve_transactiontext", + "mcve_transinqueue", + "mcve_transnew", + "mcve_transparam", + "mcve_transsend", + "mcve_ub", + "mcve_uwait", + "mcve_verifyconnection", + "mcve_verifysslcert", + "mcve_void", + "md5", + "md5_file", + "mdecrypt_generic", + "memory_get_usage", + "metaphone", + "method_exists", + "mhash", + "mhash_count", + "mhash_get_block_size", + "mhash_get_hash_name", + "mhash_keygen_s2k", + "microtime", + "mime_content_type", + "mimetype", + "min", + "ming_setcubicthreshold", + "ming_setscale", + "ming_useswfversion", + "mkdir", + "mktime", + "money_format", + "move", + "movePen", + "movePenTo", + "moveTo", + "move_uploaded_file", + "msession_connect", + "msession_count", + "msession_create", + "msession_destroy", + "msession_disconnect", + "msession_find", + "msession_get", + "msession_get_array", + "msession_getdata", + "msession_inc", + "msession_list", + "msession_listvar", + "msession_lock", + "msession_plugin", + "msession_randstr", + "msession_set", + "msession_set_array", + "msession_setdata", + "msession_timeout", + "msession_uniq", + "msession_unlock", + "msg_get_queue", + "msg_receive", + "msg_remove_queue", + "msg_send", + "msg_set_queue", + "msg_stat_queue", + "msql", + "msql_affected_rows", + "msql_close", + "msql_connect", + "msql_create_db", + "msql_createdb", + "msql_data_seek", + "msql_dbname", + "msql_drop_db", + "msql_dropdb", + "msql_error", + "msql_fetch_array", + "msql_fetch_field", + "msql_fetch_object", + "msql_fetch_row", + "msql_fieldflags", + "msql_fieldlen", + "msql_fieldname", + "msql_field_seek", + "msql_fieldtable", + "msql_fieldtype", + "msql_free_result", + "msql_freeresult", + "msql_list_dbs", + "msql_listdbs", + "msql_list_fields", + "msql_listfields", + "msql_list_tables", + "msql_listtables", + "msql_num_fields", + "msql_numfields", + "msql_num_rows", + "msql_numrows", + "msql_pconnect", + "msql_query", + "msql_regcase", + "msql_result", + "msql_select_db", + "msql_selectdb", + "msql_tablename", + "mssql_bind", + "mssql_close", + "mssql_connect", + "mssql_data_seek", + "mssql_execute", + "mssql_fetch_array", + "mssql_fetch_assoc", + "mssql_fetch_batch", + "mssql_fetch_field", + "mssql_fetch_object", + "mssql_fetch_row", + "mssql_field_length", + "mssql_field_name", + "mssql_field_seek", + "mssql_field_type", + "mssql_free_result", + "mssql_free_statement", + "mssql_get_last_message", + "mssql_guid_string", + "mssql_init", + "mssql_min_error_severity", + "mssql_min_message_severity", + "mssql_next_result", + "mssql_num_fields", + "mssql_num_rows", + "mssql_pconnect", + "mssql_query", + "mssql_result", + "mssql_rows_affected", + "mssql_select_db", + "mt_getrandmax", + "mt_rand", + "mt_srand", + "multColor", + "muscat_close", + "muscat_get", + "muscat_give", + "muscat_setup", + "muscat_setup_net", + "mysql_affected_rows", + "mysql_change_user", + "mysql_client_encoding", + "mysql_close", + "mysql_connect", + "mysql_create_db", + "mysql_data_seek", + "mysql_db_name", + "mysql_db_query", + "mysql_drop_db", + "mysql_errno", + "mysql_error", + "mysql_escape_string", + "mysql_fetch_array", + "mysql_fetch_assoc", + "mysql_fetch_field", + "mysql_fetch_lengths", + "mysql_fetch_object", + "mysql_fetch_row", + "mysql_field_flags", + "mysql_field_len", + "mysql_field_name", + "mysql_field_seek", + "mysql_field_table", + "mysql_field_type", + "mysql_free_result", + "mysql_get_client_info", + "mysql_get_host_info", + "mysql_get_proto_info", + "mysql_get_server_info", + "mysql_info", + "mysql_insert_id", + "mysql_list_dbs", + "mysql_list_fields", + "mysql_list_processes", + "mysql_list_tables", + "mysql_num_fields", + "mysql_num_rows", + "mysql_pconnect", + "mysql_ping", + "mysql_query", + "mysql_real_escape_string", + "mysql_result", + "mysql_select_db", + "mysql_stat", + "mysql_tablename", + "mysql_thread_id", + "mysql_unbuffered_query", + "name", + "natcasesort", + "natsort", + "ncurses_addch", + "ncurses_addchnstr", + "ncurses_addchstr", + "ncurses_addnstr", + "ncurses_addstr", + "ncurses_assume_default_colors", + "ncurses_attroff", + "ncurses_attron", + "ncurses_attrset", + "ncurses_baudrate", + "ncurses_beep", + "ncurses_bkgd", + "ncurses_bkgdset", + "ncurses_border", + "ncurses_can_change_color", + "ncurses_cbreak", + "ncurses_clear", + "ncurses_clrtobot", + "ncurses_clrtoeol", + "ncurses_color_set", + "ncurses_curs_set", + "ncurses_define_key", + "ncurses_def_prog_mode", + "ncurses_def_shell_mode", + "ncurses_delay_output", + "ncurses_delch", + "ncurses_deleteln", + "ncurses_delwin", + "ncurses_doupdate", + "ncurses_echo", + "ncurses_echochar", + "ncurses_end", + "ncurses_erase", + "ncurses_erasechar", + "ncurses_filter", + "ncurses_flash", + "ncurses_flushinp", + "ncurses_getch", + "ncurses_getmouse", + "ncurses_halfdelay", + "ncurses_has_colors", + "ncurses_has_ic", + "ncurses_has_il", + "ncurses_has_key", + "ncurses_hline", + "ncurses_inch", + "ncurses_init", + "ncurses_init_color", + "ncurses_init_pair", + "ncurses_insch", + "ncurses_insdelln", + "ncurses_insertln", + "ncurses_insstr", + "ncurses_instr", + "ncurses_isendwin", + "ncurses_keyok", + "ncurses_killchar", + "ncurses_longname", + "ncurses_mouseinterval", + "ncurses_mousemask", + "ncurses_move", + "ncurses_mvaddch", + "ncurses_mvaddchnstr", + "ncurses_mvaddchstr", + "ncurses_mvaddnstr", + "ncurses_mvaddstr", + "ncurses_mvcur", + "ncurses_mvdelch", + "ncurses_mvgetch", + "ncurses_mvhline", + "ncurses_mvinch", + "ncurses_mvvline", + "ncurses_mvwaddstr", + "ncurses_napms", + "ncurses_newwin", + "ncurses_nl", + "ncurses_nocbreak", + "ncurses_noecho", + "ncurses_nonl", + "ncurses_noqiflush", + "ncurses_noraw", + "ncurses_putp", + "ncurses_qiflush", + "ncurses_raw", + "ncurses_refresh", + "ncurses_resetty", + "ncurses_savetty", + "ncurses_scr_dump", + "ncurses_scr_init", + "ncurses_scrl", + "ncurses_scr_restore", + "ncurses_scr_set", + "ncurses_slk_attr", + "ncurses_slk_attroff", + "ncurses_slk_attron", + "ncurses_slk_attrset", + "ncurses_slk_clear", + "ncurses_slk_color", + "ncurses_slk_init", + "ncurses_slk_noutrefresh", + "ncurses_slk_refresh", + "ncurses_slk_restore", + "ncurses_slk_touch", + "ncurses_standend", + "ncurses_standout", + "ncurses_start_color", + "ncurses_termattrs", + "ncurses_termname", + "ncurses_timeout", + "ncurses_typeahead", + "ncurses_ungetch", + "ncurses_ungetmouse", + "ncurses_use_default_colors", + "ncurses_use_env", + "ncurses_use_extended_names", + "ncurses_vidattr", + "ncurses_vline", + "ncurses_wrefresh", + "new", + "next", + "nextframe", + "next_sibling", + "ngettext", + "nl2br", + "nl_langinfo", + "node_name", + "node_type", + "node_value", + "notations", + "notes_body", + "notes_copy_db", + "notes_create_db", + "notes_create_note", + "notes_drop_db", + "notes_find_note", + "notes_header_info", + "notes_list_msgs", + "notes_mark_read", + "notes_mark_unread", + "notes_nav_create", + "notes_search", + "notes_unread", + "notes_version", + "NULL", + "number_format", + "ob_clean", + "ob_end_clean", + "ob_end_flush", + "ob_flush", + "ob_get_contents", + "ob_get_length", + "ob_get_level", + "ob_get_status", + "ob_gzhandler", + "ob_iconv_handler", + "ob_implicit_flush", + "object", + "objectbyanchor", + "ob_start", + "ocibindbyname", + "ocicancel", + "OCICollAppend", + "ocicollassign", + "ocicollassignelem", + "ocicollgetelem", + "ocicollmax", + "ocicollsize", + "ocicolltrim", + "ocicolumnisnull", + "ocicolumnname", + "ocicolumnprecision", + "ocicolumnscale", + "ocicolumnsize", + "ocicolumntype", + "ocicolumntyperaw", + "ocicommit", + "ocidefinebyname", + "ocierror", + "ociexecute", + "ocifetch", + "ocifetchinto", + "ocifetchstatement", + "ocifreecollection", + "ocifreecursor", + "OCIFreeDesc", + "ocifreestatement", + "ociinternaldebug", + "ociloadlob", + "ocilogoff", + "ocilogon", + "ocinewcollection", + "ocinewcursor", + "ocinewdescriptor", + "ocinlogon", + "ocinumcols", + "ociparse", + "ociplogon", + "ociresult", + "ocirollback", + "ocirowcount", + "ocisavelob", + "ocisavelobfile", + "ociserverversion", + "ocisetprefetch", + "ocistatementtype", + "ociwritelobtofile", + "octdec", + "odbc_autocommit", + "odbc_binmode", + "odbc_close", + "odbc_close_all", + "odbc_columnprivileges", + "odbc_columns", + "odbc_commit", + "odbc_connect", + "odbc_cursor", + "odbc_data_source", + "odbc_do", + "odbc_error", + "odbc_errormsg", + "odbc_exec", + "odbc_execute", + "odbc_fetch_array", + "odbc_fetch_into", + "odbc_fetch_object", + "odbc_fetch_row", + "odbc_field_len", + "odbc_field_name", + "odbc_field_num", + "odbc_field_precision", + "odbc_field_scale", + "odbc_field_type", + "odbc_foreignkeys", + "odbc_free_result", + "odbc_gettypeinfo", + "odbc_longreadlen", + "odbc_next_result", + "odbc_num_fields", + "odbc_num_rows", + "odbc_pconnect", + "odbc_prepare", + "odbc_primarykeys", + "odbc_procedurecolumns", + "odbc_procedures", + "odbc_result", + "odbc_result_all", + "odbc_rollback", + "odbc_setoption", + "odbc_specialcolumns", + "odbc_statistics", + "odbc_tableprivileges", + "odbc_tables", + "opendir", + "openlog", + "openssl_csr_export", + "openssl_csr_export_to_file", + "openssl_csr_new", + "openssl_csr_sign", + "openssl_error_string", + "openssl_free_key", + "openssl_get_privatekey", + "openssl_get_publickey", + "openssl_open", + "openssl_pkcs7_decrypt", + "openssl_pkcs7_encrypt", + "openssl_pkcs7_sign", + "openssl_pkcs7_verify", + "openssl_pkey_export", + "openssl_pkey_export_to_file", + "openssl_pkey_get_private", + "openssl_pkey_get_public", + "openssl_pkey_new", + "openssl_private_decrypt", + "openssl_private_encrypt", + "openssl_public_decrypt", + "openssl_public_encrypt", + "openssl_seal", + "openssl_sign", + "openssl_verify", + "openssl_x509_check_private_key", + "openssl_x509_checkpurpose", + "openssl_x509_export", + "openssl_x509_export_to_file", + "openssl_x509_free", + "openssl_x509_parse", + "openssl_x509_read", + "ora_bind", + "ora_close", + "ora_columnname", + "ora_columnsize", + "ora_columntype", + "ora_commit", + "ora_commitoff", + "ora_commiton", + "ora_do", + "ora_error", + "ora_errorcode", + "ora_exec", + "ora_fetch", + "ora_fetch_into", + "ora_getcolumn", + "ora_logoff", + "ora_logon", + "ora_numcols", + "ora_numrows", + "ora_open", + "ora_parse", + "ora_plogon", + "ora_rollback", + "ord", + "output", + "overload", + "ovrimos_close", + "ovrimos_commit", + "ovrimos_connect", + "ovrimos_cursor", + "ovrimos_exec", + "ovrimos_execute", + "ovrimos_fetch_into", + "ovrimos_fetch_row", + "ovrimos_field_len", + "ovrimos_field_name", + "ovrimos_field_num", + "ovrimos_field_type", + "ovrimos_free_result", + "ovrimos_longreadlen", + "ovrimos_num_fields", + "ovrimos_num_rows", + "ovrimos_prepare", + "ovrimos_result", + "ovrimos_result_all", + "ovrimos_rollback", + "owner_document", + "pack", + "parent_node", + "parents", + "parse_ini_file", + "parse_str", + "parse_url", + "passthru", + "pathinfo", + "PATH_TRANSLATED", + "pclose", + "pcntl_exec", + "pcntl_fork", + "pcntl_signal", + "pcntl_waitpid", + "pcntl_wexitstatus", + "pcntl_wifexited", + "pcntl_wifsignaled", + "pcntl_wifstopped", + "pcntl_wstopsig", + "pcntl_wtermsig", + "pdf_add_annotation", + "pdf_add_bookmark", + "pdf_add_launchlink", + "pdf_add_locallink", + "pdf_add_note", + "pdf_add_outline", + "pdf_add_pdflink", + "pdf_add_thumbnail", + "pdf_add_weblink", + "pdf_arc", + "pdf_arcn", + "pdf_attach_file", + "pdf_begin_page", + "pdf_begin_pattern", + "pdf_begin_template", + "pdf_circle", + "pdf_clip", + "pdf_close", + "pdf_close_image", + "pdf_closepath", + "pdf_closepath_fill_stroke", + "pdf_closepath_stroke", + "pdf_close_pdi", + "pdf_close_pdi_page", + "pdf_concat", + "pdf_continue_text", + "pdf_curveto", + "pdf_delete", + "pdf_end_page", + "pdf_endpath", + "pdf_end_pattern", + "pdf_end_template", + "pdf_fill", + "pdf_fill_stroke", + "pdf_findfont", + "pdf_get_buffer", + "pdf_get_font", + "pdf_get_fontname", + "pdf_get_fontsize", + "pdf_get_image_height", + "pdf_get_image_width", + "pdf_get_majorversion", + "pdf_get_minorversion", + "pdf_get_parameter", + "pdf_get_pdi_parameter", + "pdf_get_pdi_value", + "pdf_get_value", + "pdf_initgraphics", + "pdf_lineto", + "pdf_makespotcolor", + "pdf_moveto", + "pdf_new", + "pdf_open", + "pdf_open_CCITT", + "pdf_open_file", + "pdf_open_gif", + "pdf_open_image", + "pdf_open_image_file", + "pdf_open_jpeg", + "pdf_open_memory_image", + "pdf_open_pdi", + "pdf_open_pdi_page", + "pdf_open_png", + "pdf_open_tiff", + "pdf_place_image", + "pdf_place_pdi_page", + "pdf_rect", + "pdf_restore", + "pdf_rotate", + "pdf_save", + "pdf_scale", + "pdf_set_border_color", + "pdf_set_border_dash", + "pdf_set_border_style", + "pdf_set_char_spacing", + "pdf_setcolor", + "pdf_setdash", + "pdf_set_duration", + "pdf_setflat", + "pdf_set_font", + "pdf_setfont", + "pdf_setgray", + "pdf_setgray_fill", + "pdf_setgray_stroke", + "pdf_set_horiz_scaling", + "pdf_set_info", + "pdf_set_info_author", + "pdf_set_info_creator", + "pdf_set_info_keywords", + "pdf_set_info_subject", + "pdf_set_info_title", + "pdf_set_leading", + "pdf_setlinecap", + "pdf_setlinejoin", + "pdf_setlinewidth", + "pdf_setmatrix", + "pdf_setmiterlimit", + "pdf_set_parameter", + "pdf_setpolydash", + "pdf_setrgbcolor", + "pdf_setrgbcolor_fill", + "pdf_setrgbcolor_stroke", + "pdf_set_text_matrix", + "pdf_set_text_pos", + "pdf_set_text_rendering", + "pdf_set_text_rise", + "pdf_set_value", + "pdf_set_word_spacing", + "pdf_show", + "pdf_show_boxed", + "pdf_show_xy", + "pdf_skew", + "pdf_stringwidth", + "pdf_stroke", + "pdf_translate", + "PEAR_EXTENSION_DIR", + "PEAR_INSTALL_DIR", + "pfpro_cleanup", + "pfpro_init", + "pfpro_process", + "pfpro_process_raw", + "pfpro_version", + "pfsockopen", + "pg_affected_rows", + "pg_cancel_query", + "pg_client_encoding", + "pg_close", + "pg_connect", + "pg_connection_busy", + "pg_connection_reset", + "pg_connection_status", + "pg_convert", + "pg_copy_from", + "pg_copy_to", + "pg_dbname", + "pg_delete", + "pg_end_copy", + "pg_escape_bytea", + "pg_escape_string", + "pg_fetch_all", + "pg_fetch_array", + "pg_fetch_assoc", + "pg_fetch_object", + "pg_fetch_result", + "pg_fetch_row", + "pg_field_is_null", + "pg_field_name", + "pg_field_num", + "pg_field_prtlen", + "pg_field_size", + "pg_field_type", + "pg_free_result", + "pg_get_notify", + "pg_get_pid", + "pg_get_result", + "pg_host", + "pg_insert", + "pg_last_error", + "pg_last_notice", + "pg_last_oid", + "pg_lo_close", + "pg_lo_create", + "pg_lo_export", + "pg_lo_import", + "pg_lo_open", + "pg_lo_read", + "pg_lo_read_all", + "pg_lo_seek", + "pg_lo_tell", + "pg_lo_unlink", + "pg_lo_write", + "pg_meta_data", + "pg_num_fields", + "pg_num_rows", + "pg_options", + "pg_pconnect", + "pg_ping", + "pg_port", + "pg_put_line", + "pg_query", + "pg_result_error", + "pg_result_seek", + "pg_result_status", + "pg_select", + "pg_send_query", + "pg_set_client_encoding", + "pg_trace", + "pg_tty", + "pg_unescape_bytea", + "pg_untrace", + "pg_update", + "PHP_BINDIR", + "PHP_CONFIG_FILE_PATH", + "phpcredits", + "PHP_DATADIR", + "PHP_ERRMSG", + "PHP_EXTENSION_DIR", + "phpinfo", + "php_ini_scanned_files", + "PHP_LIBDIR", + "PHP_LOCALSTATEDIR", + "php_logo_guid", + "PHP_OS", + "PHP_OUTPUT_HANDLER_CONT", + "PHP_OUTPUT_HANDLER_END", + "PHP_OUTPUT_HANDLER_START", + "php_sapi_name", + "PHP_SELF", + "PHP_SYSCONFDIR", + "php_uname", + "phpversion", + "PHP_VERSION", + "pi", + "png2wbmp", + "popen", + "pos", + "posix_ctermid", + "posix_getcwd", + "posix_getegid", + "posix_geteuid", + "posix_getgid", + "posix_getgrgid", + "posix_getgrnam", + "posix_getgroups", + "posix_getlogin", + "posix_getpgid", + "posix_getpgrp", + "posix_getpid", + "posix_getppid", + "posix_getpwnam", + "posix_getpwuid", + "posix_getrlimit", + "posix_getsid", + "posix_getuid", + "posix_isatty", + "posix_kill", + "posix_mkfifo", + "posix_setegid", + "posix_seteuid", + "posix_setgid", + "posix_setpgid", + "posix_setsid", + "posix_setuid", + "posix_times", + "posix_ttyname", + "posix_uname", + "_POST", + "pow", + "prefix", + "preg_grep", + "preg_match", + "preg_match_all", + "preg_quote", + "preg_replace", + "preg_replace_callback", + "preg_split", + "prev", + "previous_sibling", + "print", + "printer_abort", + "printer_close", + "printer_create_brush", + "printer_create_dc", + "printer_create_font", + "printer_create_pen", + "printer_delete_brush", + "printer_delete_dc", + "printer_delete_font", + "printer_delete_pen", + "printer_draw_bmp", + "printer_draw_chord", + "printer_draw_elipse", + "printer_draw_line", + "printer_draw_pie", + "printer_draw_rectangle", + "printer_draw_roundrect", + "printer_draw_text", + "printer_end_doc", + "printer_end_page", + "printer_get_option", + "printer_list", + "printer_logical_fontheight", + "printer_open", + "printer_select_brush", + "printer_select_font", + "printer_select_pen", + "printer_set_option", + "printer_start_doc", + "printer_start_page", + "printer_write", + "printf", + "print_r", + "private", + "proc_close", + "process", + "proc_open", + "protected", + "pspell_add_to_personal", + "pspell_add_to_session", + "pspell_check", + "pspell_clear_session", + "pspell_config_create", + "pspell_config_ignore", + "pspell_config_mode", + "pspell_config_personal", + "pspell_config_repl", + "pspell_config_runtogether", + "pspell_config_save_repl", + "pspell_new", + "pspell_new_config", + "pspell_new_personal", + "pspell_save_wordlist", + "pspell_store_replacement", + "pspell_suggest", + "public", + "public_id", + "putenv", + "qdom_error", + "qdom_tree", + "QUERY_STRING", + "quoted_printable_decode", + "quotemeta", + "rad2deg", + "rand", + "range", + "rawurldecode", + "rawurlencode", + "read", + "readdir", + "read_exif_data", + "readfile", + "readgzfile", + "readline", + "readline_add_history", + "readline_clear_history", + "readline_completion_function", + "readline_info", + "readline_list_history", + "readline_read_history", + "readline_write_history", + "readlink", + "realpath", + "reason", + "recode", + "recode_file", + "recode_string", + "register_shutdown_function", + "register_tick_function", + "REMOTE_ADDR", + "REMOTE_PORT", + "remove", + "remove_attribute", + "remove_child", + "rename", + "replace", + "replace_child", + "replace_node", + "_REQUEST", + "REQUEST_METHOD", + "REQUEST_URI", + "require", + "require_once", + "reset", + "restore_error_handler", + "restore_include_path", + "result_dump_file", + "result_dump_mem", + "return", + "rewind", + "rewinddir", + "rmdir", + "Rotate", + "rotateTo", + "round", + "rsort", + "rtrim", + "save", + "scale", + "scaleTo", + "SCRIPT_FILENAME", + "SCRIPT_NAME", + "sem_acquire", + "sem_get", + "sem_release", + "sem_remove", + "serialize", + "_SERVER", + "SERVER_ADMIN", + "SERVER_NAME", + "SERVER_PORT", + "SERVER_PROTOCOL", + "SERVER_SIGNATURE", + "SERVER_SOFTWARE", + "sesam_affected_rows", + "sesam_commit", + "sesam_connect", + "sesam_diagnostic", + "sesam_disconnect", + "sesam_errormsg", + "sesam_execimm", + "sesam_fetch_array", + "sesam_fetch_result", + "sesam_fetch_row", + "sesam_field_array", + "sesam_field_name", + "sesam_free_result", + "sesam_num_fields", + "sesam_query", + "sesam_rollback", + "sesam_seek_row", + "sesam_settransaction", + "_SESSION", + "session_cache_expire", + "session_cache_limiter", + "session_decode", + "session_destroy", + "session_encode", + "session_get_cookie_params", + "session_id", + "session_is_registered", + "session_module_name", + "session_name", + "session_readonly", + "session_register", + "session_save_path", + "session_set_cookie_params", + "session_set_save_handler", + "session_start", + "session_unregister", + "session_unset", + "session_write_close", + "setAction", + "set_attribute", + "setbackground", + "setbounds", + "setcolor", + "setColor", + "setcommitedversion", + "set_content", + "setcookie", + "setDepth", + "setdimension", + "setdown", + "set_error_handler", + "set_file_buffer", + "setFont", + "setframes", + "setHeight", + "setHit", + "set_include_path", + "setindentation", + "setLeftFill", + "setLeftMargin", + "setLine", + "setLineSpacing", + "setlocale", + "set_magic_quotes_runtime", + "setMargins", + "set_name", + "setname", + "setName", + "set_namespace", + "setOver", + "setrate", + "setRatio", + "setRightFill", + "setrightMargin", + "setSpacing", + "set_time_limit", + "settype", + "setUp", + "sha1", + "sha1_file", + "shell_exec", + "shm_attach", + "shm_detach", + "shm_get_var", + "shmop_close", + "shmop_delete", + "shmop_open", + "shmop_read", + "shmop_size", + "shmop_write", + "shm_put_var", + "shm_remove", + "shm_remove_var", + "show_source", + "shuffle", + "similar_text", + "sin", + "sinh", + "sizeof", + "skewX", + "skewXTo", + "skewY", + "skewYTo", + "sleep", + "snmpget", + "snmp_get_quick_print", + "snmprealwalk", + "snmpset", + "snmp_set_quick_print", + "snmpwalk", + "snmpwalkoid", + "socket_accept", + "socket_bind", + "socket_clear_error", + "socket_close", + "socket_connect", + "socket_create", + "socket_create_listen", + "socket_create_pair", + "socket_get_option", + "socket_getpeername", + "socket_getsockname", + "socket_get_status", + "socket_iovec_add", + "socket_iovec_alloc", + "socket_iovec_delete", + "socket_iovec_fetch", + "socket_iovec_free", + "socket_iovec_set", + "socket_last_error", + "socket_listen", + "socket_read", + "socket_readv", + "socket_recv", + "socket_recvfrom", + "socket_recvmsg", + "socket_select", + "socket_send", + "socket_sendmsg", + "socket_sendto", + "socket_set_blocking", + "socket_set_nonblock", + "socket_set_option", + "socket_set_timeout", + "socket_shutdown", + "socket_strerror", + "socket_write", + "socket_writev", + "sort", + "soundex", + "specified", + "split", + "spliti", + "sprintf", + "sql_regcase", + "sqrt", + "srand", + "srcanchors", + "srcsofdst", + "sscanf", + "stat", + "static", + "stdClass", + "strcasecmp", + "strchr", + "strcmp", + "strcoll", + "strcspn", + "stream_context_create", + "stream_context_get_options", + "stream_context_set_option", + "stream_context_set_params", + "stream_filter_append", + "stream_filter_prepend", + "stream_get_filters", + "stream_get_meta_data", + "stream_get_wrappers", + "streammp3", + "stream_register_filter", + "stream_register_wrapper", + "stream_select", + "stream_set_blocking", + "stream_set_timeout", + "stream_set_write_buffer", + "strftime", + "stripcslashes", + "stripslashes", + "strip_tags", + "stristr", + "strlen", + "strnatcasecmp", + "strnatcmp", + "strncasecmp", + "strncmp", + "str_pad", + "strpos", + "strrchr", + "str_repeat", + "str_replace", + "strrev", + "str_rot13", + "strrpos", + "str_shuffle", + "strspn", + "strstr", + "strtok", + "strtolower", + "strtotime", + "strtoupper", + "strtr", + "strval", + "str_word_count", + "substr", + "substr_count", + "substr_replace", + "SWFAction", + "swf_actiongeturl", + "swf_actiongotoframe", + "swf_actiongotolabel", + "swf_actionnextframe", + "swf_actionplay", + "swf_actionprevframe", + "swf_actionsettarget", + "swf_actionstop", + "swf_actiontogglequality", + "swf_actionwaitforframe", + "swf_addbuttonrecord", + "swf_addcolor", + "SWFBitmap", + "SWFbutton", + "swfbutton_keypress", + "swf_closefile", + "swf_definebitmap", + "swf_definefont", + "swf_defineline", + "swf_definepoly", + "swf_definerect", + "swf_definetext", + "SWFDisplayItem", + "swf_endbutton", + "swf_enddoaction", + "swf_endshape", + "swf_endsymbol", + "SWFFill", + "SWFFont", + "swf_fontsize", + "swf_fontslant", + "swf_fonttracking", + "swf_getbitmapinfo", + "swf_getfontinfo", + "swf_getframe", + "SWFGradient", + "swf_labelframe", + "swf_lookat", + "swf_modifyobject", + "SWFMorph", + "SWFMovie", + "swf_mulcolor", + "swf_nextid", + "swf_oncondition", + "swf_openfile", + "swf_ortho", + "swf_ortho2", + "swf_perspective", + "swf_placeobject", + "swf_polarview", + "swf_popmatrix", + "swf_posround", + "swf_pushmatrix", + "swf_removeobject", + "swf_rotate", + "swf_scale", + "swf_setfont", + "swf_setframe", + "SWFShape", + "swf_shapearc", + "swf_shapecurveto", + "swf_shapecurveto3", + "swf_shapefillbitmapclip", + "swf_shapefillbitmaptile", + "swf_shapefilloff", + "swf_shapefillsolid", + "swf_shapelinesolid", + "swf_shapelineto", + "swf_shapemoveto", + "swf_showframe", + "SWFSprite", + "swf_startbutton", + "swf_startdoaction", + "swf_startshape", + "swf_startsymbol", + "SWFText", + "SWFTextField", + "swf_textwidth", + "swf_translate", + "swf_viewport", + "switch", + "sybase_affected_rows", + "sybase_close", + "sybase_connect", + "sybase_data_seek", + "sybase_fetch_array", + "sybase_fetch_field", + "sybase_fetch_object", + "sybase_fetch_row", + "sybase_field_seek", + "sybase_free_result", + "sybase_get_last_message", + "sybase_min_client_severity", + "sybase_min_error_severity", + "sybase_min_message_severity", + "sybase_min_server_severity", + "sybase_num_fields", + "sybase_num_rows", + "sybase_pconnect", + "sybase_query", + "sybase_result", + "sybase_select_db", + "symlink", + "syslog", + "system", + "system_id", + "tagname", + "tan", + "tanh", + "target", + "tempnam", + "textdomain", + "time", + "title", + "tmpfile", + "token_get_all", + "token_name", + "touch", + "trigger_error", + "trim", + "TRUE", + "type", + "uasort", + "ucfirst", + "ucwords", + "udm_add_search_limit", + "udm_alloc_agent", + "udm_api_version", + "udm_cat_list", + "udm_cat_path", + "udm_check_charset", + "udm_check_stored", + "udm_clear_search_limits", + "udm_close_stored", + "udm_crc32", + "udm_errno", + "udm_error", + "udm_find", + "udm_free_agent", + "udm_free_ispell_data", + "udm_free_res", + "udm_get_doc_count", + "udm_get_res_field", + "udm_get_res_param", + "udm_load_ispell_data", + "udm_open_stored", + "udm_set_agent_param", + "uksort", + "umask", + "uniqid", + "unixtojd", + "unlink", + "unlink_node", + "unlock", + "unpack", + "unregister_tick_function", + "unserialize", + "unset", + "urldecode", + "urlencode", + "user", + "user_error", + "userlist", + "usleep", + "usort", + "utf8_decode", + "utf8_encode", + "value", + "values", + "var", + "var_dump", + "var_export", + "version_compare", + "virtual", + "vpopmail_add_alias_domain", + "vpopmail_add_alias_domain_ex", + "vpopmail_add_domain", + "vpopmail_add_domain_ex", + "vpopmail_add_user", + "vpopmail_alias_add", + "vpopmail_alias_del", + "vpopmail_alias_del_domain", + "vpopmail_alias_get", + "vpopmail_alias_get_all", + "vpopmail_auth_user", + "vpopmail_del_domain", + "vpopmail_del_domain_ex", + "vpopmail_del_user", + "vpopmail_error", + "vpopmail_passwd", + "vpopmail_set_user_quota", + "vprintf", + "vsprintf", + "w32api_deftype", + "w32api_init_dtype", + "w32api_invoke_function", + "w32api_register_function", + "w32api_set_call_method", + "wddx_add_vars", + "wddx_deserialize", + "wddx_packet_end", + "wddx_packet_start", + "wddx_serialize_value", + "wddx_serialize_vars", + "while", + "wordwrap", + "xinclude", + "xml_error_string", + "xml_get_current_byte_index", + "xml_get_current_column_number", + "xml_get_current_line_number", + "xml_get_error_code", + "xml_parse", + "xml_parse_into_struct", + "xml_parser_create", + "xml_parser_create_ns", + "xml_parser_free", + "xml_parser_get_option", + "xml_parser_set_option", + "xmlrpc_decode", + "xmlrpc_decode_request", + "xmlrpc_encode", + "xmlrpc_encode_request", + "xmlrpc_get_type", + "xmlrpc_parse_method_descriptions", + "xmlrpc_server_add_introspection_data", + "xmlrpc_server_call_method", + "xmlrpc_server_create", + "xmlrpc_server_destroy", + "xmlrpc_server_register_introspection_callback", + "xmlrpc_server_register_method", + "xmlrpc_set_type", + "xml_set_character_data_handler", + "xml_set_default_handler", + "xml_set_element_handler", + "xml_set_end_namespace_decl_handler", + "xml_set_external_entity_ref_handler", + "xml_set_notation_decl_handler", + "xml_set_object", + "xml_set_processing_instruction_handler", + "xml_set_start_namespace_decl_handler", + "xml_set_unparsed_entity_decl_handler", + "xpath_eval", + "xpath_eval_expression", + "xpath_new_context", + "xptr_eval", + "xptr_new_context", + "xslt_create", + "xslt_errno", + "xslt_error", + "xslt_free", + "xslt_output_process", + "xslt_set_base", + "xslt_set_encoding", + "xslt_set_error_handler", + "xslt_set_log", + "xslt_set_sax_handler", + "xslt_set_sax_handlers", + "xslt_set_scheme_handler", + "xslt_set_scheme_handlers", + "yaz_addinfo", + "yaz_ccl_conf", + "yaz_ccl_parse", + "yaz_close", + "yaz_connect", + "yaz_database", + "yaz_element", + "yaz_errno", + "yaz_error", + "yaz_get_option", + "yaz_hits", + "yaz_itemorder", + "yaz_present", + "yaz_range", + "yaz_record", + "yaz_scan", + "yaz_scan_result", + "yaz_schema", + "yaz_search", + "yaz_set_option", + "yaz_sort", + "yaz_syntax", + "yaz_wait", + "yp_all", + "yp_cat", + "yp_errno", + "yp_err_string", + "yp_first", + "yp_get_default_domain", + "yp_master", + "yp_match", + "yp_next", + "yp_order", + "zend_logo_guid", + "zend_version", + "zend_version", + "zip_close", + "zip_entry_close", + "zip_entry_compressedsize", + "zip_entry_compressionmethod", + "zip_entry_filesize", + "zip_entry_name", + "zip_entry_open", + "zip_entry_read", + "zip_open", + "zip_read", + 0 + }; + +Php5Writer::Php5Writer() { +} + +Php5Writer::~Php5Writer() {} + + +void Php5Writer::writeClass(UMLClassifier *c) { + if(!c) { + kDebug()<<"Cannot write class of NULL concept!" << endl; + return; + } + + QString classname = cleanName(c->getName()); + //find an appropriate name for our file + QString fileName = findFileName(c, ".php"); + if (fileName.isEmpty()) { + emit codeGenerated(c, false); + return; + } + + QFile filephp; + if(!openFile(filephp, fileName)) { + emit codeGenerated(c, false); + return; + } + QTextStream php(&filephp); + + ////////////////////////////// + //Start generating the code!! + ///////////////////////////// + + + //try to find a heading file (license, coments, etc) + QString str; + str = getHeadingFile(".php"); + if(!str.isEmpty()) { + str.replace(QRegExp("%filename%"),fileName); + str.replace(QRegExp("%filepath%"),filephp.name()); + php<<str<<m_endl; + } + + + //write includes + UMLPackageList includes; + findObjectsRelated(c,includes); + UMLPackage *conc; + for(conc = includes.first(); conc ;conc = includes.next()) { + QString headerName = findFileName(conc, ".php"); + if (!headerName.isEmpty()) { + php << "require_once '" << headerName << "';" << m_endl; + } + } + php << m_endl; + + //Write class Documentation if there is somthing or if force option + if(forceDoc() || !c->getDoc().isEmpty()) { + php << m_endl << "/**" << m_endl; + php << " * class " << classname << m_endl; + php << formatDoc(c->getDoc()," * "); + php << " */" << m_endl ; + } + + UMLClassifierList superclasses = c->getSuperClasses(); + UMLAssociationList aggregations = c->getAggregations(); + UMLAssociationList compositions = c->getCompositions(); + UMLAssociationList realizations = c->getRealizations(); + UMLAssociation *a; + bool isInterface = c->isInterface(); + + //check if it is an interface or regular class + if(isInterface) { + php << "interface " << classname; + } else { + //check if class is abstract and / or has abstract methods + if(c->getAbstract()) + php << "abstract "; + php << "class " << classname << (superclasses.count() > 0 ? " extends ":""); + if(superclasses.count() > 0) { + //php5 does not support multiple inheritance so only use the first one and print a warning if more are used + UMLClassifier *obj = superclasses.first(); + php << cleanName(obj->getName()); + if(superclasses.count() > 1) + php << m_indentation << "//WARNING: PHP5 does not support multiple inheritance but there is more than 1 superclass defined in your UML model!"; + } + //check for realizations + if( !realizations.isEmpty()) { + int rc = realizations.count(); + int ri = rc; + for (a = realizations.first(); a; a = realizations.next()) { + UMLObject *o = a->getObject(Uml::B); + QString typeName = cleanName(o->getName()); + if(ri == rc) + php << m_endl << m_indentation << m_indentation << m_indentation << "implements "; + php << typeName << (--rc == 0 ? "" : ", "); + } + } + } + php << m_endl << '{' << m_endl; + + //associations + if( forceSections() || !aggregations.isEmpty()) { + php<< m_endl << m_indentation << "/** Aggregations: */" << m_endl; + for (a = aggregations.first(); a; a = aggregations.next()) { + php<< m_endl; + //maybe we should parse the string here and take multiplicity into account to decide + //which container to use. + UMLObject *o = a->getObject(Uml::A); + if (o == NULL) { + kError() << "aggregation role A object is NULL" << endl; + continue; + } + QString typeName = cleanName(o->getName()); + if (a->getMulti(Uml::A).isEmpty()) { + php << m_indentation << "var $m_" << ';' << m_endl; + } else { + php << m_indentation << "var $m_" << "Vector = array();" << m_endl; + } + }//end for + } + + if( forceSections() || !compositions.isEmpty()) { + php<< m_endl << m_indentation << "/** Compositions: */" << m_endl; + for (a = compositions.first(); a ; a = compositions.next()) { + // see comment on Aggregation about multiplicity... + UMLObject *o = a->getObject(Uml::A); + if (o == NULL) { + kError() << "composition role A object is NULL" << endl; + continue; + } + QString typeName = cleanName(o->getName()); + if (a->getMulti(Uml::A).isEmpty()) { + php << m_indentation << "var $m_" << ';' << m_endl; + } else { + php << m_indentation << "var $m_" << "Vector = array();" << m_endl; + } + } + } + + //attributes + if (!isInterface) + writeAttributes(c, php); + + //operations + writeOperations(c,php); + + php << m_endl; + + //finish file + php << m_endl << "} // end of " << classname << m_endl; + php << "?>" << m_endl; + + //close files and notfiy we are done + filephp.close(); + emit codeGenerated(c, true); +} + +//////////////////////////////////////////////////////////////////////////////////// +// Helper Methods + +void Php5Writer::writeOperations(UMLClassifier *c, QTextStream &php) { + + //Lists to store operations sorted by scope + UMLOperationList oppub,opprot,oppriv; + + bool isInterface = c->isInterface(); + bool generateErrorStub = false; + + oppub.setAutoDelete(false); + opprot.setAutoDelete(false); + oppriv.setAutoDelete(false); + + //sort operations by scope first and see if there are abstract methods + UMLOperationList opl(c->getOpList()); + 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; + } + } + + QString classname(cleanName(c->getName())); + + //write operations to file + if(forceSections() || !oppub.isEmpty()) { + php << m_endl; + writeOperations(classname,oppub,php,isInterface,generateErrorStub); + } + + if(forceSections() || !opprot.isEmpty()) { + php << m_endl; + writeOperations(classname,opprot,php,isInterface,generateErrorStub); + } + + if(forceSections() || !oppriv.isEmpty()) { + php << m_endl; + writeOperations(classname,oppriv,php,isInterface,generateErrorStub); + } + + + // build an oplist for all of the realized operations + UMLOperationList opreal; + opreal.setAutoDelete(false); + + // go through each of the realizations, taking each op + UMLAssociationList realizations = c->getRealizations(); + UMLAssociation *a; + + if( !realizations.isEmpty()) { + for (a = realizations.first(); a; a = realizations.next()) { + + // we know its a classifier if its in the list + UMLClassifier *real = (UMLClassifier*)a->getObject(Uml::B); + + UMLOperationList opl(real->getOpList()); + for(UMLOperation *op = opl.first(); op ; op = opl.next()) { + opreal.append(op); + } + } + } + + // write out all the realizations operations + writeOperations(classname,opreal,php,false,true); + +} + +void Php5Writer::writeOperations(const QString &/* classname */, UMLOperationList &opList, + QTextStream &php, bool isInterface /* = false */, + bool generateErrorStub /* = false */) { + for (UMLOperation *op=opList.first(); op ; op=opList.next()) { + UMLAttributeList atl = op->getParmList(); + UMLAttribute *at; + //write method doc if we have doc || if at least one of the params has doc + bool writeDoc = forceDoc() || !op->getDoc().isEmpty(); + for (at = atl.first(); at; at = atl.next()) + writeDoc |= !at->getDoc().isEmpty(); + + if( writeDoc ) //write method documentation + { + php <<m_indentation << "/**" << m_endl <<formatDoc(op->getDoc(),m_indentation + " * "); + php << m_indentation << " *" << m_endl; + + for (at = atl.first(); at; at = atl.next()) //write parameter documentation + { + if(forceDoc() || !at->getDoc().isEmpty()) { + php <<m_indentation << " * @param " + at->getTypeName() + ' ' + cleanName(at->getName()); + php << ' ' + formatDoc(at->getDoc(),"") << m_endl; + } + }//end for : write parameter documentation + php << m_indentation << " * @return " << op->getTypeName() << m_endl; + if (op->getAbstract()) php << m_indentation << " * @abstract" << m_endl; + if (op->getStatic()) php << m_indentation << " * @static" << m_endl; + switch(op->getVisibility()) { + case Uml::Visibility::Public: + php << m_indentation << " * @access public" << m_endl; + break; + case Uml::Visibility::Protected: + php << m_indentation << " * @access protected" << m_endl; + break; + case Uml::Visibility::Private: + php << m_indentation << " * @access private" << m_endl; + break; + default: + break; + } + php <<m_indentation << " */" << m_endl; + }//end if : write method documentation + + php << m_indentation; + if (op->getAbstract()) php << "abstract "; + switch(op->getVisibility()) { + case Uml::Visibility::Public: + php << "public "; + break; + case Uml::Visibility::Protected: + php << "protected "; + break; + case Uml::Visibility::Private: + php << "private "; + break; + default: + break; + } + if (op->getStatic()) php << "static "; + php << "function " << cleanName(op->getName()) << "("; + + int i= atl.count(); + int j=0; + for (at = atl.first(); at; at = atl.next(), j++) { + php << " $" << cleanName(at->getName()) + << (!(at->getInitialValue().isEmpty()) ? + (QString(" = ")+at->getInitialValue()) : + QString("")) + << ((j < i-1)?", ":""); + } + php <<" )"; + if(!isInterface && !op->getAbstract()) { + php << " {" << m_endl << m_indentation << m_indentation; + if(generateErrorStub) { + php << "trigger_error(\"Implement \" . __FUNCTION__);"; + } + php << m_endl << m_indentation << "} // end of member function " + cleanName(op->getName()) + m_endl; + } + else { + php << ';' + m_endl; + } + php << m_endl; + }//end for +} + +void Php5Writer::writeAttributes(UMLClassifier *c, QTextStream &php) { + UMLAttributeList atpub, atprot, atpriv, atdefval; + atpub.setAutoDelete(false); + atprot.setAutoDelete(false); + atpriv.setAutoDelete(false); + atdefval.setAutoDelete(false); + + //sort attributes by scope and see if they have a default value + UMLAttributeList atl = c->getAttributeList(); + UMLAttribute *at; + for(at = atl.first(); at ; at = atl.next()) { + if(!at->getInitialValue().isEmpty()) + atdefval.append(at); + switch(at->getVisibility()) { + case Uml::Visibility::Public: + atpub.append(at); + break; + case Uml::Visibility::Protected: + atprot.append(at); + break; + case Uml::Visibility::Private: + atpriv.append(at); + break; + default: + break; + } + } + + if(forceSections() || atl.count()) + php<< m_endl << m_indentation << " /*** Attributes: ***/" << m_endl <<m_endl; + + if(forceSections() || atpub.count()) { + writeAttributes(atpub,php); + } + + if(forceSections() || atprot.count()) { + writeAttributes(atprot,php); + } + + if(forceSections() || atpriv.count()) { + writeAttributes(atpriv,php); + } +} + + +void Php5Writer::writeAttributes(UMLAttributeList &atList, QTextStream &php) { + for (UMLAttribute *at = atList.first(); at ; at = atList.next()) { + bool isStatic = at->getStatic(); + if (forceDoc() || !at->getDoc().isEmpty()) { + php << m_indentation << "/**" << m_endl << formatDoc(at->getDoc(), m_indentation + " * "); + if(isStatic) php << m_indentation << " * @static" << m_endl; + switch(at->getVisibility()) { + case Uml::Visibility::Public: + php << m_indentation << " * @access public" << m_endl; + break; + case Uml::Visibility::Protected: + php << m_indentation << " * @access protected" << m_endl; + break; + case Uml::Visibility::Private: + php << m_indentation << " * @access private" << m_endl; + break; + default: + break; + } + php << m_indentation << " */" << m_endl; + } + php << m_indentation; + switch(at->getVisibility()) { + case Uml::Visibility::Public: + php << "public "; + break; + case Uml::Visibility::Protected: + php << "protected "; + break; + case Uml::Visibility::Private: + php << "private "; + break; + default: + break; + } + if(isStatic) php << "static "; + php << "$" << cleanName(at->getName()); + if(!at->getInitialValue().isEmpty()) + php << " = " << at->getInitialValue(); + php << ";" << m_endl << m_endl; + } // end for + return; +} + +/** + * returns "PHP" + */ +Uml::Programming_Language Php5Writer::getLanguage() { + return Uml::pl_PHP5; +} + +const QStringList Php5Writer::reservedKeywords() const { + + static QStringList keywords; + + if (keywords.isEmpty()) { + for (int i = 0; php5words[i]; i++) + keywords.append(php5words[i]); + } + + return keywords; +} + +#include "php5writer.moc" + diff --git a/umbrello/umbrello/codegenerators/php5writer.h b/umbrello/umbrello/codegenerators/php5writer.h new file mode 100644 index 00000000..3adc983c --- /dev/null +++ b/umbrello/umbrello/codegenerators/php5writer.h @@ -0,0 +1,95 @@ +/*************************************************************************** + php5writer.h - description + ------------------- + begin : Thu Oct 17 2002 + copyright : (C) 2002 by Heiko Nardmann + email : h.nardmann@secunet.de + + php5 version by Thorsten Kunz (tk AT bytecrash DOT 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. * + * * + ***************************************************************************/ + +#ifndef PHP5WRITER_H +#define PHP5WRITER_H + +#include "simplecodegenerator.h" +#include "../umlattributelist.h" +#include "../umloperationlist.h" + +/** + * class Php5Writer is a PHP code generator for UMLClassifier objects + * Just call writeClass and feed it a UMLClassifier; + */ +class Php5Writer : public SimpleCodeGenerator { + Q_OBJECT +public: + + Php5Writer(); + virtual ~Php5Writer(); + + /** + * call this method to generate Php code for a UMLClassifier + * @param c the class you want to generate code for. + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "PHP" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +private: + + /** + * we do not want to write the comment "Private methods" twice + */ + bool bPrivateSectionCommentIsWritten; + + /** + * write all operations for a given class + * + * @param c the concept we are generating code for + * @param php output stream for the PHP file + */ + void writeOperations(UMLClassifier *c, QTextStream &php); + + /** + * write a list of class operations + * + * @param classname the name of the class + * @param opList the list of operations + * @param php output stream for the PHP file + * @param interface indicates if the operation is an interface member + */ + void writeOperations(const QString &classname, UMLOperationList &opList, + QTextStream &php, + bool interface = false, bool generateErrorStub = false); + + /** write all the attributes of a class + * @param c the class we are generating code for + * @param php output stream for the PHP file + */ + void writeAttributes(UMLClassifier *c, QTextStream &php); + + /** write a list of class attributes + * @param atList the list of attributes + * @param php output stream for the PHP file + */ + void writeAttributes(UMLAttributeList &atList, QTextStream &php); +}; + +#endif //PHP5WRITER + diff --git a/umbrello/umbrello/codegenerators/phpwriter.cpp b/umbrello/umbrello/codegenerators/phpwriter.cpp new file mode 100644 index 00000000..6d71c102 --- /dev/null +++ b/umbrello/umbrello/codegenerators/phpwriter.cpp @@ -0,0 +1,3339 @@ +/*************************************************************************** + begin : Thu Oct 17 2002 + copyright : (C) 2002 by Heiko Nardmann + email : h.nardmann@secunet.de + (C) 2003-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. * + * * + ***************************************************************************/ + +#include "phpwriter.h" + +#include <kdebug.h> +#include <qregexp.h> +#include <qtextstream.h> + +#include "../umldoc.h" +#include "../classifier.h" +#include "../association.h" +#include "../attribute.h" +#include "../operation.h" +#include "../umlnamespace.h" + +static const char *words[] = + { + "abs", + "acos", + "acosh", + "add", + "addAction", + "addColor", + "addcslashes", + "addEntry", + "addFill", + "add_namespace", + "addShape", + "addslashes", + "addstring", + "addString", + "aggregate", + "aggregate_info", + "aggregate_methods", + "aggregate_methods_by_list", + "aggregate_methods_by_regexp", + "aggregate_properties", + "aggregate_properties_by_list", + "aggregate_properties_by_regexp", + "aggregation_info", + "align", + "apache_child_terminate", + "apache_lookup_uri", + "apache_note", + "apache_request_headers", + "apache_response_headers", + "apache_setenv", + "append_child", + "append_sibling", + "array", + "array_change_key_case", + "array_chunk", + "array_count_values", + "array_diff", + "array_diff_assoc", + "array_fill", + "array_filter", + "array_flip", + "array_intersect", + "array_intersect_assoc", + "array_key_exists", + "array_keys", + "array_map", + "array_merge", + "array_merge_recursive", + "array_multisort", + "array_pad", + "array_pop", + "array_push", + "array_rand", + "array_reduce", + "array_reverse", + "array_search", + "array_shift", + "array_slice", + "array_splice", + "array_sum", + "array_unique", + "array_unshift", + "array_values", + "array_walk", + "arsort", + "ascii2ebcdic", + "asin", + "asinh", + "asort", + "aspell_check", + "aspell_new", + "aspell_suggest", + "assert", + "assert_options", + "assign", + "atan", + "atan2", + "atanh", + "attreditable", + "attributes", + "base64_decode", + "base64_encode", + "base_convert", + "basename", + "bcadd", + "bccomp", + "bcdiv", + "bcmod", + "bcmul", + "bcpow", + "bcpowmod", + "bcscale", + "bcsqrt", + "bcsub", + "bin2hex", + "bindec", + "bindtextdomain", + "bind_textdomain_codeset", + "bool", + "break", + "bzclose", + "bzcompress", + "bzdecompress", + "bzerrno", + "bzerror", + "bzerrstr", + "bzflush", + "bzopen", + "bzread", + "bzwrite", + "cal_days_in_month", + "cal_from_jd", + "cal_info", + "call_user_func", + "call_user_func_array", + "call_user_method", + "call_user_method_array", + "cal_to_jd", + "ccvs_add", + "ccvs_auth", + "ccvs_command", + "ccvs_count", + "ccvs_delete", + "ccvs_done", + "ccvs_init", + "ccvs_lookup", + "ccvs_new", + "ccvs_report", + "ccvs_return", + "ccvs_reverse", + "ccvs_sale", + "ccvs_status", + "ccvs_textvalue", + "ccvs_void", + "ceil", + "chdir", + "checkdate", + "checkdnsrr", + "checkin", + "checkout", + "chgrp", + "child_nodes", + "children", + "chmod", + "chop", + "chown", + "chr", + "chroot", + "chunk_split", + "class", + "class_exists", + "clearstatcache", + "clone_node", + "closedir", + "closelog", + "com_addref", + "com_get", + "com_invoke", + "com_isenum", + "com_load", + "com_load_typelib", + "compact", + "com_propget", + "com_propput", + "com_propset", + "com_release", + "com_set", + "connection_aborted", + "connection_status", + "connection_timeout", + "constant", + "content", + "continue", + "convert_cyr_string", + "_COOKIE", + "copy", + "cos", + "cosh", + "count", + "count_chars", + "cpdf_add_annotation", + "cpdf_add_outline", + "cpdf_arc", + "cpdf_begin_text", + "cpdf_circle", + "cpdf_clip", + "cpdf_close", + "cpdf_closepath", + "cpdf_closepath_fill_stroke", + "cpdf_closepath_stroke", + "cpdf_continue_text", + "cpdf_curveto", + "cpdf_end_text", + "cpdf_fill", + "cpdf_fill_stroke", + "cpdf_finalize", + "cpdf_finalize_page", + "cpdf_global_set_document_limits", + "cpdf_import_jpeg", + "cpdf_lineto", + "cpdf_moveto", + "cpdf_newpath", + "cpdf_open", + "cpdf_output_buffer", + "cpdf_page_init", + "cpdf_place_inline_image", + "cpdf_rect", + "cpdf_restore", + "cpdf_rlineto", + "cpdf_rmoveto", + "cpdf_rotate", + "cpdf_rotate_text", + "cpdf_save", + "cpdf_save_to_file", + "cpdf_scale", + "cpdf_set_action_url", + "cpdf_set_char_spacing", + "cpdf_set_creator", + "cpdf_set_current_page", + "cpdf_setdash", + "cpdf_setflat", + "cpdf_set_font", + "cpdf_set_font_directories", + "cpdf_set_font_map_file", + "cpdf_setgray", + "cpdf_setgray_fill", + "cpdf_setgray_stroke", + "cpdf_set_horiz_scaling", + "cpdf_set_keywords", + "cpdf_set_leading", + "cpdf_setlinecap", + "cpdf_setlinejoin", + "cpdf_setlinewidth", + "cpdf_setmiterlimit", + "cpdf_set_page_animation", + "cpdf_setrgbcolor", + "cpdf_setrgbcolor_fill", + "cpdf_setrgbcolor_stroke", + "cpdf_set_subject", + "cpdf_set_text_matrix", + "cpdf_set_text_pos", + "cpdf_set_text_rendering", + "cpdf_set_text_rise", + "cpdf_set_title", + "cpdf_set_viewer_preferences", + "cpdf_set_word_spacing", + "cpdf_show", + "cpdf_show_xy", + "cpdf_stringwidth", + "cpdf_stroke", + "cpdf_text", + "cpdf_translate", + "crack_check", + "crack_closedict", + "crack_getlastmessage", + "crack_opendict", + "crc32", + "create_attribute", + "create_cdata_section", + "create_comment", + "create_element", + "create_element_ns", + "create_entity_reference", + "create_function", + "create_processing_instruction", + "create_text_node", + "crypt", + "ctype_alnum", + "ctype_alpha", + "ctype_cntrl", + "ctype_digit", + "ctype_graph", + "ctype_lower", + "ctype_print", + "ctype_punct", + "ctype_space", + "ctype_upper", + "ctype_xdigit", + "curl_close", + "curl_errno", + "curl_error", + "curl_exec", + "curl_getinfo", + "curl_init", + "curl_setopt", + "curl_version", + "current", + "cybercash_base64_decode", + "cybercash_base64_encode", + "cybercash_decr", + "cybercash_encr", + "cybermut_creerformulairecm", + "cybermut_creerreponsecm", + "cybermut_testmac", + "cyrus_authenticate", + "cyrus_bind", + "cyrus_close", + "cyrus_connect", + "cyrus_query", + "cyrus_unbind", + "data", + "date", + "dba_close", + "dba_delete", + "dba_exists", + "dba_fetch", + "dba_firstkey", + "dba_handlers", + "dba_insert", + "dba_list", + "dba_nextkey", + "dba_open", + "dba_optimize", + "dba_popen", + "dba_replace", + "dbase_add_record", + "dbase_close", + "dbase_create", + "dbase_delete_record", + "dbase_get_record", + "dbase_get_record_with_names", + "dbase_numfields", + "dbase_numrecords", + "dbase_open", + "dbase_pack", + "dbase_replace_record", + "dba_sync", + "dblist", + "dbmclose", + "dbmdelete", + "dbmexists", + "dbmfetch", + "dbmfirstkey", + "dbminsert", + "dbmnextkey", + "dbmopen", + "dbmreplace", + "dbplus_add", + "dbplus_aql", + "dbplus_chdir", + "dbplus_close", + "dbplus_curr", + "dbplus_errcode", + "dbplus_errno", + "dbplus_find", + "dbplus_first", + "dbplus_flush", + "dbplus_freealllocks", + "dbplus_freelock", + "dbplus_freerlocks", + "dbplus_getlock", + "dbplus_getunique", + "dbplus_info", + "dbplus_last", + "dbplus_lockrel", + "dbplus_next", + "dbplus_open", + "dbplus_prev", + "dbplus_rchperm", + "dbplus_rcreate", + "dbplus_rcrtexact", + "dbplus_rcrtlike", + "dbplus_resolve", + "dbplus_restorepos", + "dbplus_rkeys", + "dbplus_ropen", + "dbplus_rquery", + "dbplus_rrename", + "dbplus_rsecindex", + "dbplus_runlink", + "dbplus_rzap", + "dbplus_savepos", + "dbplus_setindex", + "dbplus_setindexbynumber", + "dbplus_sql", + "dbplus_tcl", + "dbplus_tremove", + "dbplus_undo", + "dbplus_undoprepare", + "dbplus_unlockrel", + "dbplus_unselect", + "dbplus_update", + "dbplus_xlockrel", + "dbplus_xunlockrel", + "dbstat", + "dbx_close", + "dbx_compare", + "dbx_connect", + "dbx_error", + "dbx_escape_string", + "dbx_query", + "dbx_sort", + "dcgettext", + "dcngettext", + "dcstat", + "deaggregate", + "debug_backtrace", + "debugger_off", + "debugger_on", + "decbin", + "dechex", + "declare", + "decoct", + "DEFAULT_INCLUDE_PATH", + "define", + "defined", + "define_syslog_variables", + "deg2rad", + "delete", + "description", + "dgettext", + "die", + "dio_close", + "dio_fcntl", + "dio_open", + "dio_read", + "dio_seek", + "dio_stat", + "dio_tcsetattr", + "dio_truncate", + "dio_write", + "dir", + "dirname", + "disk_free_space", + "diskfreespace", + "disk_total_space", + "dl", + "dngettext", + "dns_check_record", + "dns_get_mx", + "dns_get_record", + "do", + "doctype", + "document_element", + "DOCUMENT_ROOT", + "domxml_new_doc", + "domxml_open_file", + "domxml_open_mem", + "domxml_version", + "domxml_xmltree", + "domxml_xslt_stylesheet", + "domxml_xslt_stylesheet_doc", + "domxml_xslt_stylesheet_file", + "dotnet_load", + "doubleval", + "drawCurve", + "drawCurveTo", + "drawLine", + "drawLineTo", + "dstanchors", + "dstofsrcanchors", + "dump_file", + "dump_mem", + "dump_node", + "each", + "E_ALL", + "easter_date", + "easter_days", + "ebcdic2ascii", + "echo", + "E_COMPILE_ERROR", + "E_COMPILE_WARNING", + "E_CORE_ERROR", + "E_CORE_WARNING", + "E_ERROR", + "else", + "elseif", + "empty", + "end", + "endfor", + "endforeach", + "endif", + "endswitch", + "endwhile", + "E_NOTICE", + "entities", + "_ENV", + "E_PARSE", + "ereg", + "eregi", + "eregi_replace", + "ereg_replace", + "error_log", + "error_reporting", + "escapeshellarg", + "escapeshellcmd", + "E_USER_ERROR", + "E_USER_NOTICE", + "E_USER_WARNING", + "eval", + "E_WARNING", + "exec", + "exif_imagetype", + "exif_read_data", + "exif_thumbnail", + "exit", + "exp", + "explode", + "expm1", + "extension_loaded", + "extract", + "ezmlm_hash", + "FALSE", + "fbsql_affected_rows", + "fbsql_autocommit", + "fbsql_change_user", + "fbsql_close", + "fbsql_commit", + "fbsql_connect", + "fbsql_create_blob", + "fbsql_create_clob", + "fbsql_create_db", + "fbsql_database", + "fbsql_database_password", + "fbsql_data_seek", + "fbsql_db_query", + "fbsql_db_status", + "fbsql_drop_db", + "fbsql_errno", + "fbsql_error", + "fbsql_fetch_array", + "fbsql_fetch_assoc", + "fbsql_fetch_field", + "fbsql_fetch_lengths", + "fbsql_fetch_object", + "fbsql_fetch_row", + "fbsql_field_flags", + "fbsql_field_len", + "fbsql_field_name", + "fbsql_field_seek", + "fbsql_field_table", + "fbsql_field_type", + "fbsql_free_result", + "fbsql_get_autostart_info", + "fbsql_hostname", + "fbsql_insert_id", + "fbsql_list_dbs", + "fbsql_list_fields", + "fbsql_list_tables", + "fbsql_next_result", + "fbsql_num_fields", + "fbsql_num_rows", + "fbsql_password", + "fbsql_pconnect", + "fbsql_query", + "fbsql_read_blob", + "fbsql_read_clob", + "fbsql_result", + "fbsql_rollback", + "fbsql_select_db", + "fbsql_set_lob_mode", + "fbsql_set_transaction", + "fbsql_start_db", + "fbsql_stop_db", + "fbsql_tablename", + "fbsql_username", + "fbsql_warnings", + "fclose", + "fdf_add_doc_javascript", + "fdf_add_template", + "fdf_close", + "fdf_create", + "fdf_errno", + "fdf_error", + "fdf_get_ap", + "fdf_get_attachment", + "fdf_get_encoding", + "fdf_get_file", + "fdf_get_status", + "fdf_get_value", + "fdf_get_version", + "fdf_header", + "fdf_next_field_name", + "fdf_open", + "fdf_open_string", + "fdf_save", + "fdf_save_string", + "fdf_set_ap", + "fdf_set_encoding", + "fdf_set_file", + "fdf_set_flags", + "fdf_set_javascript_action", + "fdf_set_opt", + "fdf_set_status", + "fdf_set_submit_form_action", + "fdf_set_target_frame", + "fdf_set_value", + "fdf_set_version", + "feof", + "fflush", + "fgetc", + "fgetcsv", + "fgets", + "fgetss", + "file", + "__FILE__", + "fileatime", + "filectime", + "file_exists", + "file_get_contents", + "filegroup", + "fileinode", + "filemtime", + "fileowner", + "fileperms", + "filepro", + "filepro_fieldcount", + "filepro_fieldname", + "filepro_fieldtype", + "filepro_fieldwidth", + "filepro_retrieve", + "filepro_rowcount", + "_FILES", + "filesize", + "filetype", + "find", + "first_child", + "floatval", + "flock", + "floor", + "flush", + "fmod", + "fnmatch", + "fopen", + "for", + "foreach", + "fpassthru", + "fprintf", + "fputs", + "fread", + "frenchtojd", + "fribidi_log2vis", + "fscanf", + "fseek", + "fsockopen", + "fstat", + "ftell", + "ftok", + "ftp_cdup", + "ftp_chdir", + "ftp_close", + "ftp_connect", + "ftp_delete", + "ftp_exec", + "ftp_fget", + "ftp_fput", + "ftp_get", + "ftp_get_option", + "ftp_login", + "ftp_mdtm", + "ftp_mkdir", + "ftp_nb_continue", + "ftp_nb_fget", + "ftp_nb_fput", + "ftp_nb_get", + "ftp_nb_put", + "ftp_nlist", + "ftp_pasv", + "ftp_put", + "ftp_pwd", + "ftp_quit", + "ftp_rawlist", + "ftp_rename", + "ftp_rmdir", + "ftp_set_option", + "ftp_site", + "ftp_size", + "ftp_ssl_connect", + "ftp_systype", + "ftruncate", + "ftstat", + "func_get_arg", + "func_get_args", + "func_num_args", + "function", + "function_exists", + "fwrite", + "GATEWAY_INTERFACE", + "gd_info", + "_GET", + "getallheaders", + "get_attribute", + "get_attribute_node", + "get_browser", + "get_cfg_var", + "get_class", + "get_class_methods", + "get_class_vars", + "get_content", + "get_current_user", + "getcwd", + "getdate", + "get_declared_classes", + "get_defined_constants", + "get_defined_functions", + "get_defined_vars", + "get_element_by_id", + "get_elements_by_tagname", + "getenv", + "get_extension_funcs", + "getHeight", + "gethostbyaddr", + "gethostbyname", + "gethostbynamel", + "get_html_translation_table", + "getimagesize", + "get_included_files", + "get_include_path", + "getlastmod", + "get_loaded_extensions", + "get_magic_quotes_gpc", + "get_magic_quotes_runtime", + "get_meta_tags", + "getmxrr", + "getmygid", + "getmyinode", + "getmypid", + "getmyuid", + "get_object_vars", + "getopt", + "get_parent_class", + "getprotobyname", + "getprotobynumber", + "getrandmax", + "get_required_files", + "get_resource_type", + "getrusage", + "getservbyname", + "getservbyport", + "getshape1", + "getshape2", + "gettext", + "gettimeofday", + "gettype", + "getwidth", + "getWidth", + "glob", + "global", + "GLOBALS", + "gmdate", + "gmmktime", + "gmp_abs", + "gmp_add", + "gmp_and", + "gmp_clrbit", + "gmp_cmp", + "gmp_com", + "gmp_div", + "gmp_divexact", + "gmp_div_q", + "gmp_div_qr", + "gmp_div_r", + "gmp_fact", + "gmp_gcd", + "gmp_gcdext", + "gmp_hamdist", + "gmp_init", + "gmp_intval", + "gmp_invert", + "gmp_jacobi", + "gmp_legendre", + "gmp_mod", + "gmp_mul", + "gmp_neg", + "gmp_or", + "gmp_perfect_square", + "gmp_popcount", + "gmp_pow", + "gmp_powm", + "gmp_prob_prime", + "gmp_random", + "gmp_scan0", + "gmp_scan1", + "gmp_setbit", + "gmp_sign", + "gmp_sqrt", + "gmp_sqrtrm", + "gmp_strval", + "gmp_sub", + "gmp_xor", + "gmstrftime", + "gregoriantojd", + "gzclose", + "gzcompress", + "gzdeflate", + "gzencode", + "gzeof", + "gzfile", + "gzgetc", + "gzgets", + "gzgetss", + "gzinflate", + "gzopen", + "gzpassthru", + "gzputs", + "gzread", + "gzrewind", + "gzseek", + "gztell", + "gzuncompress", + "gzwrite", + "has_attribute", + "has_attributess", + "has_child_nodes", + "header", + "headers_sent", + "hebrev", + "hebrevc", + "hexdec", + "highlight_file", + "highlight_string", + "html_dump_mem", + "htmlentities", + "html_entity_decode", + "htmlspecialchars", + "HTTP_ACCEPT", + "HTTP_ACCEPT_CHARSET", + "HTTP_ACCEPT_LANGUAGE", + "HTTP_CONNECTION", + "HTTP_COOKIE_VARS", + "HTTP_ENCODING", + "HTTP_ENV_VARS", + "HTTP_GET_VARS", + "HTTP_HOST", + "HTTP_POST_FILES", + "HTTP_POST_VARS", + "HTTP_RAW_POST_DATA", + "HTTP_REFERER", + "HTTP_SERVER_VARS", + "HTTP_SESSION_VARS", + "HTTP_STATE_VARS", + "HTTP_USER_AGENT", + "hw_api_attribute", + "hw_api_content", + "hwapi_hgcsp", + "hw_api_object", + "hw_Array2Objrec", + "hw_changeobject", + "hw_Children", + "hw_ChildrenObj", + "hw_Close", + "hw_Connect", + "hw_connection_info", + "hw_Cp", + "hw_Deleteobject", + "hw_DocByAnchor", + "hw_DocByAnchorObj", + "hw_Document_Attributes", + "hw_Document_BodyTag", + "hw_Document_Content", + "hw_Document_SetContent", + "hw_Document_Size", + "hw_dummy", + "hw_EditText", + "hw_Error", + "hw_ErrorMsg", + "hw_Free_Document", + "hw_GetAnchors", + "hw_GetAnchorsObj", + "hw_GetAndLock", + "hw_GetChildColl", + "hw_GetChildCollObj", + "hw_GetChildDocColl", + "hw_GetChildDocCollObj", + "hw_GetObject", + "hw_GetObjectByQuery", + "hw_GetObjectByQueryColl", + "hw_GetObjectByQueryCollObj", + "hw_GetObjectByQueryObj", + "hw_GetParents", + "hw_GetParentsObj", + "hw_getrellink", + "hw_GetRemote", + "hw_GetRemoteChildren", + "hw_GetSrcByDestObj", + "hw_GetText", + "hw_getusername", + "hw_Identify", + "hw_InCollections", + "hw_Info", + "hw_InsColl", + "hw_InsDoc", + "hw_insertanchors", + "hw_InsertDocument", + "hw_InsertObject", + "hw_mapid", + "hw_Modifyobject", + "hw_Mv", + "hw_New_Document", + "hw_Objrec2Array", + "hw_Output_Document", + "hw_pConnect", + "hw_PipeDocument", + "hw_Root", + "hw_setlinkroot", + "hw_stat", + "hwstat", + "hw_Unlock", + "hw_Who", + "hypot", + "ibase_blob_add", + "ibase_blob_cancel", + "ibase_blob_close", + "ibase_blob_create", + "ibase_blob_echo", + "ibase_blob_get", + "ibase_blob_import", + "ibase_blob_info", + "ibase_blob_open", + "ibase_close", + "ibase_commit", + "ibase_connect", + "ibase_errmsg", + "ibase_execute", + "ibase_fetch_object", + "ibase_fetch_row", + "ibase_field_info", + "ibase_free_query", + "ibase_free_result", + "ibase_num_fields", + "ibase_pconnect", + "ibase_prepare", + "ibase_query", + "ibase_rollback", + "ibase_timefmt", + "ibase_trans", + "iconv", + "iconv_get_encoding", + "iconv_set_encoding", + "identify", + "if", + "ifx_affected_rows", + "ifx_blobinfile_mode", + "ifx_byteasvarchar", + "ifx_close", + "ifx_connect", + "ifx_copy_blob", + "ifx_create_blob", + "ifx_create_char", + "ifx_do", + "ifx_error", + "ifx_errormsg", + "ifx_fetch_row", + "ifx_fieldproperties", + "ifx_fieldtypes", + "ifx_free_blob", + "ifx_free_char", + "ifx_free_result", + "ifx_get_blob", + "ifx_get_char", + "ifx_getsqlca", + "ifx_htmltbl_result", + "ifx_nullformat", + "ifx_num_fields", + "ifx_num_rows", + "ifx_pconnect", + "ifx_prepare", + "ifx_query", + "ifx_textasvarchar", + "ifx_update_blob", + "ifx_update_char", + "ifxus_close_slob", + "ifxus_create_slob", + "ifxus_free_slob", + "ifxus_open_slob", + "ifxus_read_slob", + "ifxus_seek_slob", + "ifxus_tell_slob", + "ifxus_write_slob", + "ignore_user_abort", + "image2wbmp", + "imagealphablending", + "imagearc", + "imagechar", + "imagecharup", + "imagecolorallocate", + "imagecolorallocatealpha", + "imagecolorat", + "imagecolorclosest", + "imagecolorclosestalpha", + "imagecolorclosesthwb", + "imagecolordeallocate", + "imagecolorexact", + "imagecolorexactalpha", + "imagecolorresolve", + "imagecolorresolvealpha", + "imagecolorset", + "imagecolorsforindex", + "imagecolorstotal", + "imagecolortransparent", + "imagecopy", + "imagecopymerge", + "imagecopymergegray", + "imagecopyresampled", + "imagecopyresized", + "imagecreate", + "imagecreatefromgd", + "imagecreatefromgd2", + "imagecreatefromgd2part", + "imagecreatefromgif", + "imagecreatefromjpeg", + "imagecreatefrompng", + "imagecreatefromstring", + "imagecreatefromwbmp", + "imagecreatefromxbm", + "imagecreatefromxpm", + "imagecreatetruecolor", + "imagedashedline", + "imagedestroy", + "imageellipse", + "imagefill", + "imagefilledarc", + "imagefilledellipse", + "imagefilledpolygon", + "imagefilledrectangle", + "imagefilltoborder", + "imagefontheight", + "imagefontwidth", + "imageftbbox", + "imagefttext", + "imagegammacorrect", + "imagegd", + "imagegd2", + "imagegif", + "imageinterlace", + "imagejpeg", + "imageline", + "imageloadfont", + "imagepalettecopy", + "imagepng", + "imagepolygon", + "imagepsbbox", + "imagepscopyfont", + "imagepsencodefont", + "imagepsextendfont", + "imagepsfreefont", + "imagepsloadfont", + "imagepsslantfont", + "imagepstext", + "imagerectangle", + "imagerotate", + "imagesetbrush", + "imagesetpixel", + "imagesetstyle", + "imagesetthickness", + "imagesettile", + "imagestring", + "imagestringup", + "imagesx", + "imagesy", + "imagetruecolortopalette", + "imagettfbbox", + "imagettftext", + "imagetypes", + "image_type_to_mime_type", + "imagewbmp", + "imap_8bit", + "imap_alerts", + "imap_append", + "imap_base64", + "imap_binary", + "imap_body", + "imap_bodystruct", + "imap_check", + "imap_clearflag_full", + "imap_close", + "imap_createmailbox", + "imap_delete", + "imap_deletemailbox", + "imap_errors", + "imap_expunge", + "imap_fetchbody", + "imap_fetchheader", + "imap_fetch_overview", + "imap_fetchstructure", + "imap_getmailboxes", + "imap_get_quota", + "imap_get_quotaroot", + "imap_getsubscribed", + "imap_header", + "imap_headerinfo", + "imap_headers", + "imap_last_error", + "imap_list", + "imap_listmailbox", + "imap_listscan", + "imap_listsubscribed", + "imap_lsub", + "imap_mail", + "imap_mailboxmsginfo", + "imap_mail_compose", + "imap_mail_copy", + "imap_mail_move", + "imap_mime_header_decode", + "imap_msgno", + "imap_num_msg", + "imap_num_recent", + "imap_open", + "imap_ping", + "imap_qprint", + "imap_renamemailbox", + "imap_reopen", + "imap_rfc822_parse_adrlist", + "imap_rfc822_parse_headers", + "imap_rfc822_write_address", + "imap_scanmailbox", + "imap_search", + "imap_setacl", + "imap_setflag_full", + "imap_set_quota", + "imap_sort", + "imap_status", + "imap_subscribe", + "imap_thread", + "imap_uid", + "imap_undelete", + "imap_unsubscribe", + "imap_utf7_decode", + "imap_utf7_encode", + "imap_utf8", + "implode", + "import_request_variables", + "in_array", + "include", + "include_once", + "info", + "ingres_autocommit", + "ingres_close", + "ingres_commit", + "ingres_connect", + "ingres_fetch_array", + "ingres_fetch_object", + "ingres_fetch_row", + "ingres_field_length", + "ingres_field_name", + "ingres_field_nullable", + "ingres_field_precision", + "ingres_field_scale", + "ingres_field_type", + "ingres_num_fields", + "ingres_num_rows", + "ingres_pconnect", + "ingres_query", + "ingres_rollback", + "ini_alter", + "ini_get", + "ini_get_all", + "ini_restore", + "ini_set", + "insert", + "insertanchor", + "insert_before", + "insertcollection", + "insertdocument", + "int", + "internal_subset", + "intval", + "ip2long", + "iptcembed", + "iptcparse", + "ircg_channel_mode", + "ircg_disconnect", + "ircg_fetch_error_msg", + "ircg_get_username", + "ircg_html_encode", + "ircg_ignore_add", + "ircg_ignore_del", + "ircg_is_conn_alive", + "ircg_join", + "ircg_kick", + "ircg_lookup_format_messages", + "ircg_msg", + "ircg_nick", + "ircg_nickname_escape", + "ircg_nickname_unescape", + "ircg_notice", + "ircg_part", + "ircg_pconnect", + "ircg_register_format_messages", + "ircg_set_current", + "ircg_set_file", + "ircg_set_on_die", + "ircg_topic", + "ircg_whois", + "is_a", + "is_array", + "is_blank_node", + "is_bool", + "is_callable", + "is_dir", + "is_double", + "is_executable", + "is_file", + "is_finite", + "is_float", + "is_infinite", + "is_int", + "is_integer", + "is_link", + "is_long", + "is_nan", + "is_null", + "is_numeric", + "is_object", + "is_readable", + "is_real", + "is_resource", + "is_scalar", + "isset", + "is_string", + "is_subclass_of", + "is_uploaded_file", + "is_writable", + "is_writeable", + "java_last_exception_clear", + "java_last_exception_get", + "jddayofweek", + "jdmonthname", + "jdtofrench", + "jdtogregorian", + "jdtojewish", + "jdtojulian", + "jdtounix", + "jewishtojd", + "join", + "jpeg2wbmp", + "juliantojd", + "key", + "krsort", + "ksort", + "langdepvalue", + "last_child", + "lcg_value", + "ldap_8859_to_t61", + "ldap_add", + "ldap_bind", + "ldap_close", + "ldap_compare", + "ldap_connect", + "ldap_count_entries", + "ldap_delete", + "ldap_dn2ufn", + "ldap_err2str", + "ldap_errno", + "ldap_error", + "ldap_explode_dn", + "ldap_first_attribute", + "ldap_first_entry", + "ldap_first_reference", + "ldap_free_result", + "ldap_get_attributes", + "ldap_get_dn", + "ldap_get_entries", + "ldap_get_option", + "ldap_get_values", + "ldap_get_values_len", + "ldap_list", + "ldap_mod_add", + "ldap_mod_del", + "ldap_modify", + "ldap_mod_replace", + "ldap_next_attribute", + "ldap_next_entry", + "ldap_next_reference", + "ldap_parse_reference", + "ldap_parse_result", + "ldap_read", + "ldap_rename", + "ldap_search", + "ldap_set_option", + "ldap_set_rebind_proc", + "ldap_sort", + "ldap_start_tls", + "ldap_t61_to_8859", + "ldap_unbind", + "levenshtein", + "__LINE__", + "link", + "linkinfo", + "list", + "localeconv", + "localtime", + "lock", + "log", + "log10", + "log1p", + "long2ip", + "lstat", + "ltrim", + "mail", + "mailparse_determine_best_xfer_encoding", + "mailparse_msg_create", + "mailparse_msg_extract_part", + "mailparse_msg_extract_part_file", + "mailparse_msg_free", + "mailparse_msg_get_part", + "mailparse_msg_get_part_data", + "mailparse_msg_get_structure", + "mailparse_msg_parse", + "mailparse_msg_parse_file", + "mailparse_rfc822_parse_addresses", + "mailparse_stream_encode", + "mailparse_uudecode_all", + "main", + "max", + "mb_convert_case", + "mb_convert_encoding", + "mb_convert_kana", + "mb_convert_variables", + "mb_decode_mimeheader", + "mb_decode_numericentity", + "mb_detect_encoding", + "mb_detect_order", + "mb_encode_mimeheader", + "mb_encode_numericentity", + "mb_ereg", + "mb_eregi", + "mb_eregi_replace", + "mb_ereg_match", + "mb_ereg_replace", + "mb_ereg_search", + "mb_ereg_search_getpos", + "mb_ereg_search_getregs", + "mb_ereg_search_init", + "mb_ereg_search_pos", + "mb_ereg_search_regs", + "mb_ereg_search_setpos", + "mb_get_info", + "mb_http_input", + "mb_http_output", + "mb_internal_encoding", + "mb_language", + "mb_output_handler", + "mb_parse_str", + "mb_preferred_mime_name", + "mb_regex_encoding", + "mb_regex_set_options", + "mb_send_mail", + "mb_split", + "mb_strcut", + "mb_strimwidth", + "mb_strlen", + "mb_strpos", + "mb_strrpos", + "mb_strtolower", + "mb_strtoupper", + "mb_strwidth", + "mb_substitute_character", + "mb_substr", + "mb_substr_count", + "mcal_append_event", + "mcal_close", + "mcal_create_calendar", + "mcal_date_compare", + "mcal_date_valid", + "mcal_day_of_week", + "mcal_day_of_year", + "mcal_days_in_month", + "mcal_delete_calendar", + "mcal_delete_event", + "mcal_event_add_attribute", + "mcal_event_init", + "mcal_event_set_alarm", + "mcal_event_set_category", + "mcal_event_set_class", + "mcal_event_set_description", + "mcal_event_set_end", + "mcal_event_set_recur_daily", + "mcal_event_set_recur_monthly_mday", + "mcal_event_set_recur_monthly_wday", + "mcal_event_set_recur_none", + "mcal_event_set_recur_weekly", + "mcal_event_set_recur_yearly", + "mcal_event_set_start", + "mcal_event_set_title", + "mcal_expunge", + "mcal_fetch_current_stream_event", + "mcal_fetch_event", + "mcal_is_leap_year", + "mcal_list_alarms", + "mcal_list_events", + "mcal_next_recurrence", + "mcal_open", + "mcal_popen", + "mcal_rename_calendar", + "mcal_reopen", + "mcal_snooze", + "mcal_store_event", + "mcal_time_valid", + "mcal_week_of_year", + "mcrypt_cbc", + "mcrypt_cfb", + "mcrypt_create_iv", + "mcrypt_decrypt", + "mcrypt_ecb", + "mcrypt_enc_get_algorithms_name", + "mcrypt_enc_get_block_size", + "mcrypt_enc_get_iv_size", + "mcrypt_enc_get_key_size", + "mcrypt_enc_get_modes_name", + "mcrypt_enc_get_supported_key_sizes", + "mcrypt_enc_is_block_algorithm", + "mcrypt_enc_is_block_algorithm_mode", + "mcrypt_enc_is_block_mode", + "mcrypt_encrypt", + "mcrypt_enc_self_test", + "mcrypt_generic", + "mcrypt_generic_deinit", + "mcrypt_generic_end", + "mcrypt_generic_init", + "mcrypt_get_block_size", + "mcrypt_get_cipher_name", + "mcrypt_get_iv_size", + "mcrypt_get_key_size", + "mcrypt_list_algorithms", + "mcrypt_list_modes", + "mcrypt_module_close", + "mcrypt_module_get_algo_block_size", + "mcrypt_module_get_algo_key_size", + "mcrypt_module_get_supported_key_sizes", + "mcrypt_module_is_block_algorithm", + "mcrypt_module_is_block_algorithm_mode", + "mcrypt_module_is_block_mode", + "mcrypt_module_open", + "mcrypt_module_self_test", + "mcrypt_ofb", + "mcve_adduser", + "mcve_adduserarg", + "mcve_bt", + "mcve_checkstatus", + "mcve_chkpwd", + "mcve_chngpwd", + "mcve_completeauthorizations", + "mcve_connect", + "mcve_connectionerror", + "mcve_deleteresponse", + "mcve_deletetrans", + "mcve_deleteusersetup", + "mcve_deluser", + "mcve_destroyconn", + "mcve_destroyengine", + "mcve_disableuser", + "mcve_edituser", + "mcve_enableuser", + "mcve_force", + "mcve_getcell", + "mcve_getcellbynum", + "mcve_getcommadelimited", + "mcve_getheader", + "mcve_getuserarg", + "mcve_getuserparam", + "mcve_gft", + "mcve_gl", + "mcve_gut", + "mcve_initconn", + "mcve_initengine", + "mcve_initusersetup", + "mcve_iscommadelimited", + "mcve_liststats", + "mcve_listusers", + "mcve_maxconntimeout", + "mcve_monitor", + "mcve_numcolumns", + "mcve_numrows", + "mcve_override", + "mcve_parsecommadelimited", + "mcve_ping", + "mcve_preauth", + "mcve_preauthcompletion", + "mcve_qc", + "mcve_responseparam", + "mcve_return", + "mcve_returncode", + "mcve_returnstatus", + "mcve_sale", + "mcve_setblocking", + "mcve_setdropfile", + "mcve_setip", + "mcve_setssl", + "mcve_settimeout", + "mcve_settle", + "mcve_text_avs", + "mcve_text_code", + "mcve_text_cv", + "mcve_transactionauth", + "mcve_transactionavs", + "mcve_transactionbatch", + "mcve_transactioncv", + "mcve_transactionid", + "mcve_transactionitem", + "mcve_transactionssent", + "mcve_transactiontext", + "mcve_transinqueue", + "mcve_transnew", + "mcve_transparam", + "mcve_transsend", + "mcve_ub", + "mcve_uwait", + "mcve_verifyconnection", + "mcve_verifysslcert", + "mcve_void", + "md5", + "md5_file", + "mdecrypt_generic", + "memory_get_usage", + "metaphone", + "method_exists", + "mhash", + "mhash_count", + "mhash_get_block_size", + "mhash_get_hash_name", + "mhash_keygen_s2k", + "microtime", + "mime_content_type", + "mimetype", + "min", + "ming_setcubicthreshold", + "ming_setscale", + "ming_useswfversion", + "mkdir", + "mktime", + "money_format", + "move", + "movePen", + "movePenTo", + "moveTo", + "move_uploaded_file", + "msession_connect", + "msession_count", + "msession_create", + "msession_destroy", + "msession_disconnect", + "msession_find", + "msession_get", + "msession_get_array", + "msession_getdata", + "msession_inc", + "msession_list", + "msession_listvar", + "msession_lock", + "msession_plugin", + "msession_randstr", + "msession_set", + "msession_set_array", + "msession_setdata", + "msession_timeout", + "msession_uniq", + "msession_unlock", + "msg_get_queue", + "msg_receive", + "msg_remove_queue", + "msg_send", + "msg_set_queue", + "msg_stat_queue", + "msql", + "msql_affected_rows", + "msql_close", + "msql_connect", + "msql_create_db", + "msql_createdb", + "msql_data_seek", + "msql_dbname", + "msql_drop_db", + "msql_dropdb", + "msql_error", + "msql_fetch_array", + "msql_fetch_field", + "msql_fetch_object", + "msql_fetch_row", + "msql_fieldflags", + "msql_fieldlen", + "msql_fieldname", + "msql_field_seek", + "msql_fieldtable", + "msql_fieldtype", + "msql_free_result", + "msql_freeresult", + "msql_list_dbs", + "msql_listdbs", + "msql_list_fields", + "msql_listfields", + "msql_list_tables", + "msql_listtables", + "msql_num_fields", + "msql_numfields", + "msql_num_rows", + "msql_numrows", + "msql_pconnect", + "msql_query", + "msql_regcase", + "msql_result", + "msql_select_db", + "msql_selectdb", + "msql_tablename", + "mssql_bind", + "mssql_close", + "mssql_connect", + "mssql_data_seek", + "mssql_execute", + "mssql_fetch_array", + "mssql_fetch_assoc", + "mssql_fetch_batch", + "mssql_fetch_field", + "mssql_fetch_object", + "mssql_fetch_row", + "mssql_field_length", + "mssql_field_name", + "mssql_field_seek", + "mssql_field_type", + "mssql_free_result", + "mssql_free_statement", + "mssql_get_last_message", + "mssql_guid_string", + "mssql_init", + "mssql_min_error_severity", + "mssql_min_message_severity", + "mssql_next_result", + "mssql_num_fields", + "mssql_num_rows", + "mssql_pconnect", + "mssql_query", + "mssql_result", + "mssql_rows_affected", + "mssql_select_db", + "mt_getrandmax", + "mt_rand", + "mt_srand", + "multColor", + "muscat_close", + "muscat_get", + "muscat_give", + "muscat_setup", + "muscat_setup_net", + "mysql_affected_rows", + "mysql_change_user", + "mysql_client_encoding", + "mysql_close", + "mysql_connect", + "mysql_create_db", + "mysql_data_seek", + "mysql_db_name", + "mysql_db_query", + "mysql_drop_db", + "mysql_errno", + "mysql_error", + "mysql_escape_string", + "mysql_fetch_array", + "mysql_fetch_assoc", + "mysql_fetch_field", + "mysql_fetch_lengths", + "mysql_fetch_object", + "mysql_fetch_row", + "mysql_field_flags", + "mysql_field_len", + "mysql_field_name", + "mysql_field_seek", + "mysql_field_table", + "mysql_field_type", + "mysql_free_result", + "mysql_get_client_info", + "mysql_get_host_info", + "mysql_get_proto_info", + "mysql_get_server_info", + "mysql_info", + "mysql_insert_id", + "mysql_list_dbs", + "mysql_list_fields", + "mysql_list_processes", + "mysql_list_tables", + "mysql_num_fields", + "mysql_num_rows", + "mysql_pconnect", + "mysql_ping", + "mysql_query", + "mysql_real_escape_string", + "mysql_result", + "mysql_select_db", + "mysql_stat", + "mysql_tablename", + "mysql_thread_id", + "mysql_unbuffered_query", + "name", + "natcasesort", + "natsort", + "ncurses_addch", + "ncurses_addchnstr", + "ncurses_addchstr", + "ncurses_addnstr", + "ncurses_addstr", + "ncurses_assume_default_colors", + "ncurses_attroff", + "ncurses_attron", + "ncurses_attrset", + "ncurses_baudrate", + "ncurses_beep", + "ncurses_bkgd", + "ncurses_bkgdset", + "ncurses_border", + "ncurses_can_change_color", + "ncurses_cbreak", + "ncurses_clear", + "ncurses_clrtobot", + "ncurses_clrtoeol", + "ncurses_color_set", + "ncurses_curs_set", + "ncurses_define_key", + "ncurses_def_prog_mode", + "ncurses_def_shell_mode", + "ncurses_delay_output", + "ncurses_delch", + "ncurses_deleteln", + "ncurses_delwin", + "ncurses_doupdate", + "ncurses_echo", + "ncurses_echochar", + "ncurses_end", + "ncurses_erase", + "ncurses_erasechar", + "ncurses_filter", + "ncurses_flash", + "ncurses_flushinp", + "ncurses_getch", + "ncurses_getmouse", + "ncurses_halfdelay", + "ncurses_has_colors", + "ncurses_has_ic", + "ncurses_has_il", + "ncurses_has_key", + "ncurses_hline", + "ncurses_inch", + "ncurses_init", + "ncurses_init_color", + "ncurses_init_pair", + "ncurses_insch", + "ncurses_insdelln", + "ncurses_insertln", + "ncurses_insstr", + "ncurses_instr", + "ncurses_isendwin", + "ncurses_keyok", + "ncurses_killchar", + "ncurses_longname", + "ncurses_mouseinterval", + "ncurses_mousemask", + "ncurses_move", + "ncurses_mvaddch", + "ncurses_mvaddchnstr", + "ncurses_mvaddchstr", + "ncurses_mvaddnstr", + "ncurses_mvaddstr", + "ncurses_mvcur", + "ncurses_mvdelch", + "ncurses_mvgetch", + "ncurses_mvhline", + "ncurses_mvinch", + "ncurses_mvvline", + "ncurses_mvwaddstr", + "ncurses_napms", + "ncurses_newwin", + "ncurses_nl", + "ncurses_nocbreak", + "ncurses_noecho", + "ncurses_nonl", + "ncurses_noqiflush", + "ncurses_noraw", + "ncurses_putp", + "ncurses_qiflush", + "ncurses_raw", + "ncurses_refresh", + "ncurses_resetty", + "ncurses_savetty", + "ncurses_scr_dump", + "ncurses_scr_init", + "ncurses_scrl", + "ncurses_scr_restore", + "ncurses_scr_set", + "ncurses_slk_attr", + "ncurses_slk_attroff", + "ncurses_slk_attron", + "ncurses_slk_attrset", + "ncurses_slk_clear", + "ncurses_slk_color", + "ncurses_slk_init", + "ncurses_slk_noutrefresh", + "ncurses_slk_refresh", + "ncurses_slk_restore", + "ncurses_slk_touch", + "ncurses_standend", + "ncurses_standout", + "ncurses_start_color", + "ncurses_termattrs", + "ncurses_termname", + "ncurses_timeout", + "ncurses_typeahead", + "ncurses_ungetch", + "ncurses_ungetmouse", + "ncurses_use_default_colors", + "ncurses_use_env", + "ncurses_use_extended_names", + "ncurses_vidattr", + "ncurses_vline", + "ncurses_wrefresh", + "new", + "next", + "nextframe", + "next_sibling", + "ngettext", + "nl2br", + "nl_langinfo", + "node_name", + "node_type", + "node_value", + "notations", + "notes_body", + "notes_copy_db", + "notes_create_db", + "notes_create_note", + "notes_drop_db", + "notes_find_note", + "notes_header_info", + "notes_list_msgs", + "notes_mark_read", + "notes_mark_unread", + "notes_nav_create", + "notes_search", + "notes_unread", + "notes_version", + "NULL", + "number_format", + "ob_clean", + "ob_end_clean", + "ob_end_flush", + "ob_flush", + "ob_get_contents", + "ob_get_length", + "ob_get_level", + "ob_get_status", + "ob_gzhandler", + "ob_iconv_handler", + "ob_implicit_flush", + "object", + "objectbyanchor", + "ob_start", + "ocibindbyname", + "ocicancel", + "OCICollAppend", + "ocicollassign", + "ocicollassignelem", + "ocicollgetelem", + "ocicollmax", + "ocicollsize", + "ocicolltrim", + "ocicolumnisnull", + "ocicolumnname", + "ocicolumnprecision", + "ocicolumnscale", + "ocicolumnsize", + "ocicolumntype", + "ocicolumntyperaw", + "ocicommit", + "ocidefinebyname", + "ocierror", + "ociexecute", + "ocifetch", + "ocifetchinto", + "ocifetchstatement", + "ocifreecollection", + "ocifreecursor", + "OCIFreeDesc", + "ocifreestatement", + "ociinternaldebug", + "ociloadlob", + "ocilogoff", + "ocilogon", + "ocinewcollection", + "ocinewcursor", + "ocinewdescriptor", + "ocinlogon", + "ocinumcols", + "ociparse", + "ociplogon", + "ociresult", + "ocirollback", + "ocirowcount", + "ocisavelob", + "ocisavelobfile", + "ociserverversion", + "ocisetprefetch", + "ocistatementtype", + "ociwritelobtofile", + "octdec", + "odbc_autocommit", + "odbc_binmode", + "odbc_close", + "odbc_close_all", + "odbc_columnprivileges", + "odbc_columns", + "odbc_commit", + "odbc_connect", + "odbc_cursor", + "odbc_data_source", + "odbc_do", + "odbc_error", + "odbc_errormsg", + "odbc_exec", + "odbc_execute", + "odbc_fetch_array", + "odbc_fetch_into", + "odbc_fetch_object", + "odbc_fetch_row", + "odbc_field_len", + "odbc_field_name", + "odbc_field_num", + "odbc_field_precision", + "odbc_field_scale", + "odbc_field_type", + "odbc_foreignkeys", + "odbc_free_result", + "odbc_gettypeinfo", + "odbc_longreadlen", + "odbc_next_result", + "odbc_num_fields", + "odbc_num_rows", + "odbc_pconnect", + "odbc_prepare", + "odbc_primarykeys", + "odbc_procedurecolumns", + "odbc_procedures", + "odbc_result", + "odbc_result_all", + "odbc_rollback", + "odbc_setoption", + "odbc_specialcolumns", + "odbc_statistics", + "odbc_tableprivileges", + "odbc_tables", + "opendir", + "openlog", + "openssl_csr_export", + "openssl_csr_export_to_file", + "openssl_csr_new", + "openssl_csr_sign", + "openssl_error_string", + "openssl_free_key", + "openssl_get_privatekey", + "openssl_get_publickey", + "openssl_open", + "openssl_pkcs7_decrypt", + "openssl_pkcs7_encrypt", + "openssl_pkcs7_sign", + "openssl_pkcs7_verify", + "openssl_pkey_export", + "openssl_pkey_export_to_file", + "openssl_pkey_get_private", + "openssl_pkey_get_public", + "openssl_pkey_new", + "openssl_private_decrypt", + "openssl_private_encrypt", + "openssl_public_decrypt", + "openssl_public_encrypt", + "openssl_seal", + "openssl_sign", + "openssl_verify", + "openssl_x509_check_private_key", + "openssl_x509_checkpurpose", + "openssl_x509_export", + "openssl_x509_export_to_file", + "openssl_x509_free", + "openssl_x509_parse", + "openssl_x509_read", + "ora_bind", + "ora_close", + "ora_columnname", + "ora_columnsize", + "ora_columntype", + "ora_commit", + "ora_commitoff", + "ora_commiton", + "ora_do", + "ora_error", + "ora_errorcode", + "ora_exec", + "ora_fetch", + "ora_fetch_into", + "ora_getcolumn", + "ora_logoff", + "ora_logon", + "ora_numcols", + "ora_numrows", + "ora_open", + "ora_parse", + "ora_plogon", + "ora_rollback", + "ord", + "output", + "overload", + "ovrimos_close", + "ovrimos_commit", + "ovrimos_connect", + "ovrimos_cursor", + "ovrimos_exec", + "ovrimos_execute", + "ovrimos_fetch_into", + "ovrimos_fetch_row", + "ovrimos_field_len", + "ovrimos_field_name", + "ovrimos_field_num", + "ovrimos_field_type", + "ovrimos_free_result", + "ovrimos_longreadlen", + "ovrimos_num_fields", + "ovrimos_num_rows", + "ovrimos_prepare", + "ovrimos_result", + "ovrimos_result_all", + "ovrimos_rollback", + "owner_document", + "pack", + "parent_node", + "parents", + "parse_ini_file", + "parse_str", + "parse_url", + "passthru", + "pathinfo", + "PATH_TRANSLATED", + "pclose", + "pcntl_exec", + "pcntl_fork", + "pcntl_signal", + "pcntl_waitpid", + "pcntl_wexitstatus", + "pcntl_wifexited", + "pcntl_wifsignaled", + "pcntl_wifstopped", + "pcntl_wstopsig", + "pcntl_wtermsig", + "pdf_add_annotation", + "pdf_add_bookmark", + "pdf_add_launchlink", + "pdf_add_locallink", + "pdf_add_note", + "pdf_add_outline", + "pdf_add_pdflink", + "pdf_add_thumbnail", + "pdf_add_weblink", + "pdf_arc", + "pdf_arcn", + "pdf_attach_file", + "pdf_begin_page", + "pdf_begin_pattern", + "pdf_begin_template", + "pdf_circle", + "pdf_clip", + "pdf_close", + "pdf_close_image", + "pdf_closepath", + "pdf_closepath_fill_stroke", + "pdf_closepath_stroke", + "pdf_close_pdi", + "pdf_close_pdi_page", + "pdf_concat", + "pdf_continue_text", + "pdf_curveto", + "pdf_delete", + "pdf_end_page", + "pdf_endpath", + "pdf_end_pattern", + "pdf_end_template", + "pdf_fill", + "pdf_fill_stroke", + "pdf_findfont", + "pdf_get_buffer", + "pdf_get_font", + "pdf_get_fontname", + "pdf_get_fontsize", + "pdf_get_image_height", + "pdf_get_image_width", + "pdf_get_majorversion", + "pdf_get_minorversion", + "pdf_get_parameter", + "pdf_get_pdi_parameter", + "pdf_get_pdi_value", + "pdf_get_value", + "pdf_initgraphics", + "pdf_lineto", + "pdf_makespotcolor", + "pdf_moveto", + "pdf_new", + "pdf_open", + "pdf_open_CCITT", + "pdf_open_file", + "pdf_open_gif", + "pdf_open_image", + "pdf_open_image_file", + "pdf_open_jpeg", + "pdf_open_memory_image", + "pdf_open_pdi", + "pdf_open_pdi_page", + "pdf_open_png", + "pdf_open_tiff", + "pdf_place_image", + "pdf_place_pdi_page", + "pdf_rect", + "pdf_restore", + "pdf_rotate", + "pdf_save", + "pdf_scale", + "pdf_set_border_color", + "pdf_set_border_dash", + "pdf_set_border_style", + "pdf_set_char_spacing", + "pdf_setcolor", + "pdf_setdash", + "pdf_set_duration", + "pdf_setflat", + "pdf_set_font", + "pdf_setfont", + "pdf_setgray", + "pdf_setgray_fill", + "pdf_setgray_stroke", + "pdf_set_horiz_scaling", + "pdf_set_info", + "pdf_set_info_author", + "pdf_set_info_creator", + "pdf_set_info_keywords", + "pdf_set_info_subject", + "pdf_set_info_title", + "pdf_set_leading", + "pdf_setlinecap", + "pdf_setlinejoin", + "pdf_setlinewidth", + "pdf_setmatrix", + "pdf_setmiterlimit", + "pdf_set_parameter", + "pdf_setpolydash", + "pdf_setrgbcolor", + "pdf_setrgbcolor_fill", + "pdf_setrgbcolor_stroke", + "pdf_set_text_matrix", + "pdf_set_text_pos", + "pdf_set_text_rendering", + "pdf_set_text_rise", + "pdf_set_value", + "pdf_set_word_spacing", + "pdf_show", + "pdf_show_boxed", + "pdf_show_xy", + "pdf_skew", + "pdf_stringwidth", + "pdf_stroke", + "pdf_translate", + "PEAR_EXTENSION_DIR", + "PEAR_INSTALL_DIR", + "pfpro_cleanup", + "pfpro_init", + "pfpro_process", + "pfpro_process_raw", + "pfpro_version", + "pfsockopen", + "pg_affected_rows", + "pg_cancel_query", + "pg_client_encoding", + "pg_close", + "pg_connect", + "pg_connection_busy", + "pg_connection_reset", + "pg_connection_status", + "pg_convert", + "pg_copy_from", + "pg_copy_to", + "pg_dbname", + "pg_delete", + "pg_end_copy", + "pg_escape_bytea", + "pg_escape_string", + "pg_fetch_all", + "pg_fetch_array", + "pg_fetch_assoc", + "pg_fetch_object", + "pg_fetch_result", + "pg_fetch_row", + "pg_field_is_null", + "pg_field_name", + "pg_field_num", + "pg_field_prtlen", + "pg_field_size", + "pg_field_type", + "pg_free_result", + "pg_get_notify", + "pg_get_pid", + "pg_get_result", + "pg_host", + "pg_insert", + "pg_last_error", + "pg_last_notice", + "pg_last_oid", + "pg_lo_close", + "pg_lo_create", + "pg_lo_export", + "pg_lo_import", + "pg_lo_open", + "pg_lo_read", + "pg_lo_read_all", + "pg_lo_seek", + "pg_lo_tell", + "pg_lo_unlink", + "pg_lo_write", + "pg_meta_data", + "pg_num_fields", + "pg_num_rows", + "pg_options", + "pg_pconnect", + "pg_ping", + "pg_port", + "pg_put_line", + "pg_query", + "pg_result_error", + "pg_result_seek", + "pg_result_status", + "pg_select", + "pg_send_query", + "pg_set_client_encoding", + "pg_trace", + "pg_tty", + "pg_unescape_bytea", + "pg_untrace", + "pg_update", + "PHP_BINDIR", + "PHP_CONFIG_FILE_PATH", + "phpcredits", + "PHP_DATADIR", + "PHP_ERRMSG", + "PHP_EXTENSION_DIR", + "phpinfo", + "php_ini_scanned_files", + "PHP_LIBDIR", + "PHP_LOCALSTATEDIR", + "php_logo_guid", + "PHP_OS", + "PHP_OUTPUT_HANDLER_CONT", + "PHP_OUTPUT_HANDLER_END", + "PHP_OUTPUT_HANDLER_START", + "php_sapi_name", + "PHP_SELF", + "PHP_SYSCONFDIR", + "php_uname", + "phpversion", + "PHP_VERSION", + "pi", + "png2wbmp", + "popen", + "pos", + "posix_ctermid", + "posix_getcwd", + "posix_getegid", + "posix_geteuid", + "posix_getgid", + "posix_getgrgid", + "posix_getgrnam", + "posix_getgroups", + "posix_getlogin", + "posix_getpgid", + "posix_getpgrp", + "posix_getpid", + "posix_getppid", + "posix_getpwnam", + "posix_getpwuid", + "posix_getrlimit", + "posix_getsid", + "posix_getuid", + "posix_isatty", + "posix_kill", + "posix_mkfifo", + "posix_setegid", + "posix_seteuid", + "posix_setgid", + "posix_setpgid", + "posix_setsid", + "posix_setuid", + "posix_times", + "posix_ttyname", + "posix_uname", + "_POST", + "pow", + "prefix", + "preg_grep", + "preg_match", + "preg_match_all", + "preg_quote", + "preg_replace", + "preg_replace_callback", + "preg_split", + "prev", + "previous_sibling", + "print", + "printer_abort", + "printer_close", + "printer_create_brush", + "printer_create_dc", + "printer_create_font", + "printer_create_pen", + "printer_delete_brush", + "printer_delete_dc", + "printer_delete_font", + "printer_delete_pen", + "printer_draw_bmp", + "printer_draw_chord", + "printer_draw_elipse", + "printer_draw_line", + "printer_draw_pie", + "printer_draw_rectangle", + "printer_draw_roundrect", + "printer_draw_text", + "printer_end_doc", + "printer_end_page", + "printer_get_option", + "printer_list", + "printer_logical_fontheight", + "printer_open", + "printer_select_brush", + "printer_select_font", + "printer_select_pen", + "printer_set_option", + "printer_start_doc", + "printer_start_page", + "printer_write", + "printf", + "print_r", + "private", + "proc_close", + "process", + "proc_open", + "protected", + "pspell_add_to_personal", + "pspell_add_to_session", + "pspell_check", + "pspell_clear_session", + "pspell_config_create", + "pspell_config_ignore", + "pspell_config_mode", + "pspell_config_personal", + "pspell_config_repl", + "pspell_config_runtogether", + "pspell_config_save_repl", + "pspell_new", + "pspell_new_config", + "pspell_new_personal", + "pspell_save_wordlist", + "pspell_store_replacement", + "pspell_suggest", + "public", + "public_id", + "putenv", + "qdom_error", + "qdom_tree", + "QUERY_STRING", + "quoted_printable_decode", + "quotemeta", + "rad2deg", + "rand", + "range", + "rawurldecode", + "rawurlencode", + "read", + "readdir", + "read_exif_data", + "readfile", + "readgzfile", + "readline", + "readline_add_history", + "readline_clear_history", + "readline_completion_function", + "readline_info", + "readline_list_history", + "readline_read_history", + "readline_write_history", + "readlink", + "realpath", + "reason", + "recode", + "recode_file", + "recode_string", + "register_shutdown_function", + "register_tick_function", + "REMOTE_ADDR", + "REMOTE_PORT", + "remove", + "remove_attribute", + "remove_child", + "rename", + "replace", + "replace_child", + "replace_node", + "_REQUEST", + "REQUEST_METHOD", + "REQUEST_URI", + "require", + "require_once", + "reset", + "restore_error_handler", + "restore_include_path", + "result_dump_file", + "result_dump_mem", + "return", + "rewind", + "rewinddir", + "rmdir", + "Rotate", + "rotateTo", + "round", + "rsort", + "rtrim", + "save", + "scale", + "scaleTo", + "SCRIPT_FILENAME", + "SCRIPT_NAME", + "sem_acquire", + "sem_get", + "sem_release", + "sem_remove", + "serialize", + "_SERVER", + "SERVER_ADMIN", + "SERVER_NAME", + "SERVER_PORT", + "SERVER_PROTOCOL", + "SERVER_SIGNATURE", + "SERVER_SOFTWARE", + "sesam_affected_rows", + "sesam_commit", + "sesam_connect", + "sesam_diagnostic", + "sesam_disconnect", + "sesam_errormsg", + "sesam_execimm", + "sesam_fetch_array", + "sesam_fetch_result", + "sesam_fetch_row", + "sesam_field_array", + "sesam_field_name", + "sesam_free_result", + "sesam_num_fields", + "sesam_query", + "sesam_rollback", + "sesam_seek_row", + "sesam_settransaction", + "_SESSION", + "session_cache_expire", + "session_cache_limiter", + "session_decode", + "session_destroy", + "session_encode", + "session_get_cookie_params", + "session_id", + "session_is_registered", + "session_module_name", + "session_name", + "session_readonly", + "session_register", + "session_save_path", + "session_set_cookie_params", + "session_set_save_handler", + "session_start", + "session_unregister", + "session_unset", + "session_write_close", + "setAction", + "set_attribute", + "setbackground", + "setbounds", + "setcolor", + "setColor", + "setcommitedversion", + "set_content", + "setcookie", + "setDepth", + "setdimension", + "setdown", + "set_error_handler", + "set_file_buffer", + "setFont", + "setframes", + "setHeight", + "setHit", + "set_include_path", + "setindentation", + "setLeftFill", + "setLeftMargin", + "setLine", + "setLineSpacing", + "setlocale", + "set_magic_quotes_runtime", + "setMargins", + "set_name", + "setname", + "setName", + "set_namespace", + "setOver", + "setrate", + "setRatio", + "setRightFill", + "setrightMargin", + "setSpacing", + "set_time_limit", + "settype", + "setUp", + "sha1", + "sha1_file", + "shell_exec", + "shm_attach", + "shm_detach", + "shm_get_var", + "shmop_close", + "shmop_delete", + "shmop_open", + "shmop_read", + "shmop_size", + "shmop_write", + "shm_put_var", + "shm_remove", + "shm_remove_var", + "show_source", + "shuffle", + "similar_text", + "sin", + "sinh", + "sizeof", + "skewX", + "skewXTo", + "skewY", + "skewYTo", + "sleep", + "snmpget", + "snmp_get_quick_print", + "snmprealwalk", + "snmpset", + "snmp_set_quick_print", + "snmpwalk", + "snmpwalkoid", + "socket_accept", + "socket_bind", + "socket_clear_error", + "socket_close", + "socket_connect", + "socket_create", + "socket_create_listen", + "socket_create_pair", + "socket_get_option", + "socket_getpeername", + "socket_getsockname", + "socket_get_status", + "socket_iovec_add", + "socket_iovec_alloc", + "socket_iovec_delete", + "socket_iovec_fetch", + "socket_iovec_free", + "socket_iovec_set", + "socket_last_error", + "socket_listen", + "socket_read", + "socket_readv", + "socket_recv", + "socket_recvfrom", + "socket_recvmsg", + "socket_select", + "socket_send", + "socket_sendmsg", + "socket_sendto", + "socket_set_blocking", + "socket_set_nonblock", + "socket_set_option", + "socket_set_timeout", + "socket_shutdown", + "socket_strerror", + "socket_write", + "socket_writev", + "sort", + "soundex", + "specified", + "split", + "spliti", + "sprintf", + "sql_regcase", + "sqrt", + "srand", + "srcanchors", + "srcsofdst", + "sscanf", + "stat", + "static", + "stdClass", + "strcasecmp", + "strchr", + "strcmp", + "strcoll", + "strcspn", + "stream_context_create", + "stream_context_get_options", + "stream_context_set_option", + "stream_context_set_params", + "stream_filter_append", + "stream_filter_prepend", + "stream_get_filters", + "stream_get_meta_data", + "stream_get_wrappers", + "streammp3", + "stream_register_filter", + "stream_register_wrapper", + "stream_select", + "stream_set_blocking", + "stream_set_timeout", + "stream_set_write_buffer", + "strftime", + "stripcslashes", + "stripslashes", + "strip_tags", + "stristr", + "strlen", + "strnatcasecmp", + "strnatcmp", + "strncasecmp", + "strncmp", + "str_pad", + "strpos", + "strrchr", + "str_repeat", + "str_replace", + "strrev", + "str_rot13", + "strrpos", + "str_shuffle", + "strspn", + "strstr", + "strtok", + "strtolower", + "strtotime", + "strtoupper", + "strtr", + "strval", + "str_word_count", + "substr", + "substr_count", + "substr_replace", + "SWFAction", + "swf_actiongeturl", + "swf_actiongotoframe", + "swf_actiongotolabel", + "swf_actionnextframe", + "swf_actionplay", + "swf_actionprevframe", + "swf_actionsettarget", + "swf_actionstop", + "swf_actiontogglequality", + "swf_actionwaitforframe", + "swf_addbuttonrecord", + "swf_addcolor", + "SWFBitmap", + "SWFbutton", + "swfbutton_keypress", + "swf_closefile", + "swf_definebitmap", + "swf_definefont", + "swf_defineline", + "swf_definepoly", + "swf_definerect", + "swf_definetext", + "SWFDisplayItem", + "swf_endbutton", + "swf_enddoaction", + "swf_endshape", + "swf_endsymbol", + "SWFFill", + "SWFFont", + "swf_fontsize", + "swf_fontslant", + "swf_fonttracking", + "swf_getbitmapinfo", + "swf_getfontinfo", + "swf_getframe", + "SWFGradient", + "swf_labelframe", + "swf_lookat", + "swf_modifyobject", + "SWFMorph", + "SWFMovie", + "swf_mulcolor", + "swf_nextid", + "swf_oncondition", + "swf_openfile", + "swf_ortho", + "swf_ortho2", + "swf_perspective", + "swf_placeobject", + "swf_polarview", + "swf_popmatrix", + "swf_posround", + "swf_pushmatrix", + "swf_removeobject", + "swf_rotate", + "swf_scale", + "swf_setfont", + "swf_setframe", + "SWFShape", + "swf_shapearc", + "swf_shapecurveto", + "swf_shapecurveto3", + "swf_shapefillbitmapclip", + "swf_shapefillbitmaptile", + "swf_shapefilloff", + "swf_shapefillsolid", + "swf_shapelinesolid", + "swf_shapelineto", + "swf_shapemoveto", + "swf_showframe", + "SWFSprite", + "swf_startbutton", + "swf_startdoaction", + "swf_startshape", + "swf_startsymbol", + "SWFText", + "SWFTextField", + "swf_textwidth", + "swf_translate", + "swf_viewport", + "switch", + "sybase_affected_rows", + "sybase_close", + "sybase_connect", + "sybase_data_seek", + "sybase_fetch_array", + "sybase_fetch_field", + "sybase_fetch_object", + "sybase_fetch_row", + "sybase_field_seek", + "sybase_free_result", + "sybase_get_last_message", + "sybase_min_client_severity", + "sybase_min_error_severity", + "sybase_min_message_severity", + "sybase_min_server_severity", + "sybase_num_fields", + "sybase_num_rows", + "sybase_pconnect", + "sybase_query", + "sybase_result", + "sybase_select_db", + "symlink", + "syslog", + "system", + "system_id", + "tagname", + "tan", + "tanh", + "target", + "tempnam", + "textdomain", + "time", + "title", + "tmpfile", + "token_get_all", + "token_name", + "touch", + "trigger_error", + "trim", + "TRUE", + "type", + "uasort", + "ucfirst", + "ucwords", + "udm_add_search_limit", + "udm_alloc_agent", + "udm_api_version", + "udm_cat_list", + "udm_cat_path", + "udm_check_charset", + "udm_check_stored", + "udm_clear_search_limits", + "udm_close_stored", + "udm_crc32", + "udm_errno", + "udm_error", + "udm_find", + "udm_free_agent", + "udm_free_ispell_data", + "udm_free_res", + "udm_get_doc_count", + "udm_get_res_field", + "udm_get_res_param", + "udm_load_ispell_data", + "udm_open_stored", + "udm_set_agent_param", + "uksort", + "umask", + "uniqid", + "unixtojd", + "unlink", + "unlink_node", + "unlock", + "unpack", + "unregister_tick_function", + "unserialize", + "unset", + "urldecode", + "urlencode", + "user", + "user_error", + "userlist", + "usleep", + "usort", + "utf8_decode", + "utf8_encode", + "value", + "values", + "var", + "var_dump", + "var_export", + "version_compare", + "virtual", + "vpopmail_add_alias_domain", + "vpopmail_add_alias_domain_ex", + "vpopmail_add_domain", + "vpopmail_add_domain_ex", + "vpopmail_add_user", + "vpopmail_alias_add", + "vpopmail_alias_del", + "vpopmail_alias_del_domain", + "vpopmail_alias_get", + "vpopmail_alias_get_all", + "vpopmail_auth_user", + "vpopmail_del_domain", + "vpopmail_del_domain_ex", + "vpopmail_del_user", + "vpopmail_error", + "vpopmail_passwd", + "vpopmail_set_user_quota", + "vprintf", + "vsprintf", + "w32api_deftype", + "w32api_init_dtype", + "w32api_invoke_function", + "w32api_register_function", + "w32api_set_call_method", + "wddx_add_vars", + "wddx_deserialize", + "wddx_packet_end", + "wddx_packet_start", + "wddx_serialize_value", + "wddx_serialize_vars", + "while", + "wordwrap", + "xinclude", + "xml_error_string", + "xml_get_current_byte_index", + "xml_get_current_column_number", + "xml_get_current_line_number", + "xml_get_error_code", + "xml_parse", + "xml_parse_into_struct", + "xml_parser_create", + "xml_parser_create_ns", + "xml_parser_free", + "xml_parser_get_option", + "xml_parser_set_option", + "xmlrpc_decode", + "xmlrpc_decode_request", + "xmlrpc_encode", + "xmlrpc_encode_request", + "xmlrpc_get_type", + "xmlrpc_parse_method_descriptions", + "xmlrpc_server_add_introspection_data", + "xmlrpc_server_call_method", + "xmlrpc_server_create", + "xmlrpc_server_destroy", + "xmlrpc_server_register_introspection_callback", + "xmlrpc_server_register_method", + "xmlrpc_set_type", + "xml_set_character_data_handler", + "xml_set_default_handler", + "xml_set_element_handler", + "xml_set_end_namespace_decl_handler", + "xml_set_external_entity_ref_handler", + "xml_set_notation_decl_handler", + "xml_set_object", + "xml_set_processing_instruction_handler", + "xml_set_start_namespace_decl_handler", + "xml_set_unparsed_entity_decl_handler", + "xpath_eval", + "xpath_eval_expression", + "xpath_new_context", + "xptr_eval", + "xptr_new_context", + "xslt_create", + "xslt_errno", + "xslt_error", + "xslt_free", + "xslt_output_process", + "xslt_set_base", + "xslt_set_encoding", + "xslt_set_error_handler", + "xslt_set_log", + "xslt_set_sax_handler", + "xslt_set_sax_handlers", + "xslt_set_scheme_handler", + "xslt_set_scheme_handlers", + "yaz_addinfo", + "yaz_ccl_conf", + "yaz_ccl_parse", + "yaz_close", + "yaz_connect", + "yaz_database", + "yaz_element", + "yaz_errno", + "yaz_error", + "yaz_get_option", + "yaz_hits", + "yaz_itemorder", + "yaz_present", + "yaz_range", + "yaz_record", + "yaz_scan", + "yaz_scan_result", + "yaz_schema", + "yaz_search", + "yaz_set_option", + "yaz_sort", + "yaz_syntax", + "yaz_wait", + "yp_all", + "yp_cat", + "yp_errno", + "yp_err_string", + "yp_first", + "yp_get_default_domain", + "yp_master", + "yp_match", + "yp_next", + "yp_order", + "zend_logo_guid", + "zend_version", + "zend_version", + "zip_close", + "zip_entry_close", + "zip_entry_compressedsize", + "zip_entry_compressionmethod", + "zip_entry_filesize", + "zip_entry_name", + "zip_entry_open", + "zip_entry_read", + "zip_open", + "zip_read", + 0 + }; + +PhpWriter::PhpWriter() { +} + +PhpWriter::~PhpWriter() {} + + +void PhpWriter::writeClass(UMLClassifier *c) { + if(!c) { + kDebug()<<"Cannot write class of NULL concept!" << endl; + return; + } + + QString classname = cleanName(c->getName()); + //find an appropriate name for our file + QString fileName = findFileName(c, ".php"); + if (fileName.isEmpty()) { + emit codeGenerated(c, false); + return; + } + + QFile filephp; + if(!openFile(filephp, fileName)) { + emit codeGenerated(c, false); + return; + } + QTextStream php(&filephp); + + ////////////////////////////// + //Start generating the code!! + ///////////////////////////// + + + //try to find a heading file (license, coments, etc) + QString str; + str = getHeadingFile(".php"); + if(!str.isEmpty()) { + str.replace(QRegExp("%filename%"),fileName); + str.replace(QRegExp("%filepath%"),filephp.name()); + php<<str<<m_endl; + } + + + //write includes + UMLPackageList includes; + findObjectsRelated(c,includes); + UMLPackage *conc; + for(conc = includes.first(); conc ;conc = includes.next()) { + QString headerName = findFileName(conc, ".php"); + if (headerName.isEmpty()) { + php << "include '" << headerName << "';" << m_endl; + } + } + php << m_endl; + + //Write class Documentation if there is somthing or if force option + if(forceDoc() || !c->getDoc().isEmpty()) { + php << m_endl << "/**" << m_endl; + php << " * class " << classname << m_endl; + php << formatDoc(c->getDoc()," * "); + php << " */" << m_endl ; + } + + UMLClassifierList superclasses = c->getSuperClasses(); + UMLAssociationList aggregations = c->getAggregations(); + UMLAssociationList compositions = c->getCompositions(); + UMLAssociation *a; + + //check if class is abstract and / or has abstract methods + //FG if(c->getAbstract() && !hasAbstractOps(c)) + if(c->getAbstract()) + php << "/******************************* Abstract Class ****************************" << m_endl << " " + << classname << " does not have any pure virtual methods, but its author" << m_endl + << " defined it as an abstract class, so you should not use it directly." << m_endl + << " Inherit from it instead and create only objects from the derived classes" << m_endl + << "*****************************************************************************/" << m_endl << m_endl; + + php << "class " << classname << (superclasses.count() > 0 ? " extends ":""); + for (UMLClassifier *obj = superclasses.first(); + obj; obj = superclasses.next()) { + php<<cleanName(obj->getName()); + } + php<< m_endl << "{" << m_endl; + + //associations + if( forceSections() || !aggregations.isEmpty()) { + php<< m_endl << m_indentation << "/** Aggregations: */" << m_endl; + for (a = aggregations.first(); a; a = aggregations.next()) { + php<< m_endl; + //maybe we should parse the string here and take multiplicity into account to decide + //which container to use. + UMLObject *o = a->getObject(Uml::A); + QString typeName = cleanName(o->getName()); + if (a->getMulti(Uml::A).isEmpty()) { + php << m_indentation << "var $m_" << ";" << m_endl; + } else { + php << m_indentation << "var $m_" << "Vector = array();" << m_endl; + } + }//end for + } + + if( forceSections() || !compositions.isEmpty()) { + php<< m_endl << m_indentation << "/** Compositions: */" << m_endl; + for (a = compositions.first(); a ; a = compositions.next()) { + // see comment on Aggregation about multiplicity... + UMLObject *o = a->getObject(Uml::A); + QString typeName = cleanName(o->getName()); + if (a->getMulti(Uml::A).isEmpty()) { + php << m_indentation << "var $m_" << ";" << m_endl; + } else { + php << m_indentation << "var $m_" << "Vector = array();" << m_endl; + } + } + } + + const bool isClass = !c->isInterface(); + + //attributes + if (isClass) + writeAttributes(c, php); + + //operations + writeOperations(c,php); + + if (isClass && hasDefaultValueAttr(c)) { + UMLAttributeList atl = c->getAttributeList(); + php << m_endl; + + php << m_indentation << "/**" << m_endl; + QString temp = "initAttributes sets all " + classname + " attributes to its default value." + " Make sure to call this method within your class constructor"; + php << formatDoc(temp,m_indentation + " * "); + php << m_indentation << " */" << m_endl; + php << m_indentation << "function "<<"initAttributes( )" << m_endl; + php << m_indentation << "{" << m_endl; + for(UMLAttribute* at = atl.first(); at; at = atl.next()) { + if(!at->getInitialValue().isEmpty()) { + php << m_indentation << m_indentation << "$this->" << cleanName(at->getName()) << " = " << + at->getInitialValue() << ";" << m_endl; + } + } + php << m_indentation << "}" << m_endl; + } + + php << m_endl; + + //finish file + php << m_endl << "} // end of " << classname << m_endl; + php << "?>" << m_endl; + + //close files and notfiy we are done + filephp.close(); + emit codeGenerated(c, true); +} + +//////////////////////////////////////////////////////////////////////////////////// +// Helper Methods + +void PhpWriter::writeOperations(UMLClassifier *c, QTextStream &php) { + + //Lists to store operations sorted by scope + 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 + UMLOperationList opl(c->getOpList()); + 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; + } + } + + QString classname(cleanName(c->getName())); + + //write operations to file + if(forceSections() || !oppub.isEmpty()) { + php << m_endl; + writeOperations(classname,oppub,php); + } + + if(forceSections() || !opprot.isEmpty()) { + php << m_endl; + writeOperations(classname,opprot,php); + } + + if(forceSections() || !oppriv.isEmpty()) { + php << m_endl; + writeOperations(classname,oppriv,php); + } +} + +void PhpWriter::writeOperations(QString /* classname */, UMLOperationList &opList, QTextStream &php) { + UMLOperation *op; + UMLAttribute *at; + + for(op=opList.first(); op ; op=opList.next()) { + UMLAttributeList atl = op->getParmList(); + //write method doc if we have doc || if at least one of the params has doc + bool writeDoc = forceDoc() || !op->getDoc().isEmpty(); + for (at = atl.first(); at; at = atl.next()) + writeDoc |= !at->getDoc().isEmpty(); + + if( writeDoc ) //write method documentation + { + php <<m_indentation << "/**" << m_endl <<formatDoc(op->getDoc(),m_indentation + " * "); + php << m_indentation << " *" << m_endl; + + for (at = atl.first(); at; at = atl.next()) //write parameter documentation + { + if(forceDoc() || !at->getDoc().isEmpty()) { + php <<m_indentation << " * @param " + at->getTypeName() + " " + cleanName(at->getName()); + php << " " + formatDoc(at->getDoc(),""); + } + }//end for : write parameter documentation + php << m_indentation << " * @return " << op->getTypeName() << m_endl; + if (op->getAbstract()) php << m_indentation << " * @abstract" << m_endl; + if (op->getStatic()) php << m_indentation << " * @static" << m_endl; + switch(op->getVisibility()) { + case Uml::Visibility::Public: + php << m_indentation << " * @access public" << m_endl; + break; + case Uml::Visibility::Protected: + php << m_indentation << " * @access protected" << m_endl; + break; + case Uml::Visibility::Private: + php << m_indentation << " * @access private" << m_endl; + break; + default: + break; + } + php <<m_indentation << " */" << m_endl; + }//end if : write method documentation + + php << m_indentation << "function " << cleanName(op->getName()) << "("; + + int i= atl.count(); + int j=0; + for (at = atl.first(); at; at = atl.next(), j++) { + php << " $" << cleanName(at->getName()) + << (!(at->getInitialValue().isEmpty()) ? + (QString(" = ")+at->getInitialValue()) : + QString("")) + << ((j < i-1)?", ":""); + } + php <<" )" << m_endl << m_indentation << "{" << m_endl << m_indentation << m_indentation << m_endl << m_indentation << "} // end of member function " + cleanName(op->getName()) + m_endl; + php << m_endl; + }//end for +} + +void PhpWriter::writeAttributes(UMLClassifier *c, QTextStream &php) { + UMLAttributeList atpub, atprot, atpriv, atdefval; + atpub.setAutoDelete(false); + atprot.setAutoDelete(false); + atpriv.setAutoDelete(false); + atdefval.setAutoDelete(false); + + //sort attributes by scope and see if they have a default value + UMLAttributeList atl = c->getAttributeList(); + UMLAttribute *at; + for(at = atl.first(); at ; at = atl.next()) { + if(!at->getInitialValue().isEmpty()) + atdefval.append(at); + switch(at->getVisibility()) { + case Uml::Visibility::Public: + atpub.append(at); + break; + case Uml::Visibility::Protected: + atprot.append(at); + break; + case Uml::Visibility::Private: + atpriv.append(at); + break; + default: + break; + } + } + + if(forceSections() || atl.count()) + php<< m_endl << m_indentation << " /*** Attributes: ***/" << m_endl <<m_endl; + + if(forceSections() || atpub.count()) { + writeAttributes(atpub,php); + } + + if(forceSections() || atprot.count()) { + writeAttributes(atprot,php); + } + + if(forceSections() || atpriv.count()) { + writeAttributes(atpriv,php); + } +} + + +void PhpWriter::writeAttributes(UMLAttributeList &atList, QTextStream &php) { + for (UMLAttribute *at = atList.first(); at ; at = atList.next()) { + if (forceDoc() || !at->getDoc().isEmpty()) { + php << m_indentation << "/**" << m_endl << formatDoc(at->getDoc(), m_indentation + " * "); + switch(at->getVisibility()) { + case Uml::Visibility::Public: + php << m_indentation << " * @access public" << m_endl; + break; + case Uml::Visibility::Protected: + php << m_indentation << " * @access protected" << m_endl; + break; + case Uml::Visibility::Private: + php << m_indentation << " * @access private" << m_endl; + break; + default: + break; + } + + php << m_indentation << " */" << m_endl; + } + php << m_indentation << "var " << "$" << cleanName(at->getName()) << ";" << m_endl; + + } // end for + return; +} + +/** + * returns "PHP" + */ +Uml::Programming_Language PhpWriter::getLanguage() { + return Uml::pl_PHP; +} + +const QStringList PhpWriter::reservedKeywords() const { + + static QStringList keywords; + + if (keywords.isEmpty()) { + for (int i = 0; words[i]; i++) + keywords.append(words[i]); + } + + return keywords; +} + +#include "phpwriter.moc" + diff --git a/umbrello/umbrello/codegenerators/phpwriter.h b/umbrello/umbrello/codegenerators/phpwriter.h new file mode 100644 index 00000000..a3acb68b --- /dev/null +++ b/umbrello/umbrello/codegenerators/phpwriter.h @@ -0,0 +1,90 @@ +/*************************************************************************** + phpwriter.h - description + ------------------- + begin : Thu Oct 17 2002 + copyright : (C) 2002 by Heiko Nardmann + email : h.nardmann@secunet.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef PHPWRITER_H +#define PHPWRITER_H + +#include "simplecodegenerator.h" +#include "../umlattributelist.h" +#include "../umloperationlist.h" + +/** + * class PhpWriter is a PHP code generator for UMLClassifier objects + * Just call writeClass and feed it a UMLClassifier; + */ +class PhpWriter : public SimpleCodeGenerator { + Q_OBJECT +public: + + PhpWriter(); + virtual ~PhpWriter(); + + /** + * call this method to generate Php code for a UMLClassifier + * @param c the class you want to generate code for. + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "PHP" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +private: + + /** + * we do not want to write the comment "Private methods" twice + */ + bool bPrivateSectionCommentIsWritten; + + /** + * write all operations for a given class + * + * @param c the concept we are generating code for + * @param php output stream for the PHP file + */ + void writeOperations(UMLClassifier *c, QTextStream &php); + + /** + * write a list of class operations + * + * @param classname the name of the class + * @param opList the list of operations + * @param php output stream for the PHP file + */ + void writeOperations(QString classname, UMLOperationList &opList, + QTextStream &php); + + /** write all the attributes of a class + * @param c the class we are generating code for + * @param php output stream for the PHP file + */ + void writeAttributes(UMLClassifier *c, QTextStream &php); + + /** write a list of class attributes + * @param atList the list of attributes + * @param php output stream for the PHP file + */ + void writeAttributes(UMLAttributeList &atList, QTextStream &php); +}; + +#endif //PHPWRITER diff --git a/umbrello/umbrello/codegenerators/pythonwriter.cpp b/umbrello/umbrello/codegenerators/pythonwriter.cpp new file mode 100644 index 00000000..a5ac2b28 --- /dev/null +++ b/umbrello/umbrello/codegenerators/pythonwriter.cpp @@ -0,0 +1,438 @@ +/*************************************************************************** + pythonwriter.h - description + ------------------- + begin : Sat Dec 21 2002 + copyright : Vincent Decorges + email : vincent.decorges@eivd.ch + (C) 2003-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. * + * * + ***************************************************************************/ + +#include "pythonwriter.h" + +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qregexp.h> + +#include "../umldoc.h" +#include "../umlattributelist.h" +#include "../association.h" +#include "../attribute.h" +#include "../classifier.h" +#include "../attribute.h" +#include "../operation.h" +#include "../umlnamespace.h" + +PythonWriter::PythonWriter() : m_bNeedPass(true) { +} + +PythonWriter::~PythonWriter() {} + +void PythonWriter::writeClass(UMLClassifier *c) { + if(!c) { + kDebug()<<"Cannot write class of NULL concept!" << endl; + return; + } + + QString classname = cleanName(c->getName()); + + UMLClassifierList superclasses = c->getSuperClasses(); + UMLAssociationList aggregations = c->getAggregations(); + UMLAssociationList compositions = c->getCompositions(); + + m_bNeedPass = true; + + //find an appropriate name for our file + QString fileName = findFileName(c, ".py"); + if (fileName.isEmpty()) { + emit codeGenerated(c, false); + return; + } + + QChar first = fileName.at(0); + //Replace the first letter of the filename because + //python class begin with an upper caracter (convention) + first = first.upper(); + fileName = fileName.replace(0, 1, first); + + QFile fileh; + if( !openFile(fileh, fileName) ) { + emit codeGenerated(c, false); + return; + } + QTextStream h(&fileh); + + ////////////////////////////// + //Start generating the code!! + ///////////////////////////// + + + //try to find a heading file (license, coments, etc) + QString str; + + str = getHeadingFile(".py"); + if(!str.isEmpty()) { + str.replace(QRegExp("%filename%"), fileName); + str.replace(QRegExp("%filepath%"), fileh.name()); + h<<str<<m_endl; + } + + // generate import statement for superclasses and take packages into account + str = cleanName(c->getName()); + QString pkg = cleanName(c->getPackage()); + if (!pkg.isEmpty()) + str.prepend(pkg + '.'); + QStringList includesList = QStringList(str); //save imported classes + int i = superclasses.count(); + for (UMLClassifier *classifier = superclasses.first(); + classifier && i; classifier = superclasses.next(), i--) { + str = cleanName(classifier->getName()); + pkg = cleanName(classifier->getPackage()); + if (!pkg.isEmpty()) + str.prepend(pkg + '.'); + includesList.append(str); + h << "from " + str + " import *" << m_endl; + } + + //write includes and take namespaces into account + UMLPackageList includes; + findObjectsRelated(c,includes); + UMLPackage* conc; + for(conc = includes.first(); conc ;conc = includes.next()) { + QString headerName = findFileName(conc, ".py"); + if ( !headerName.isEmpty() ) { + headerName.remove(QRegExp(".py$")); + first = headerName.at(0); + first = first.upper(); + headerName = headerName.replace(0, 1, first); + str = headerName.replace(QChar('/'),QChar('.')); + if (includesList.findIndex(str) < 0) // not yet imported + h << "from " << str << " import *" << m_endl; + } + } + h<<m_endl; + + h << "class " << classname << (superclasses.count() > 0 ? " (" : "(object)"); + i = superclasses.count(); + + for (UMLClassifier *obj = superclasses.first(); + obj && i; obj = superclasses.next(), i--) { + + h<<cleanName(obj->getName())<<(i>1?", ":""); + } + + + h<<(superclasses.count() > 0 ? ")":"")<<":"<<m_endl<<m_endl; + + if (forceDoc() || !c->getDoc().isEmpty()) { + h << m_indentation << "\"\"\"" << m_endl; + h << formatDoc(c->getDoc(), m_indentation + ' ') << m_endl; + h << m_indentation << ":version:" << m_endl; + h << m_indentation << ":author:" << m_endl; + h << m_indentation << "\"\"\"" << m_endl << m_endl; + m_bNeedPass = false; + } + + // attributes + writeAttributes(c->getAttributeList(), h); + + //operations + writeOperations(c,h); + + if (m_bNeedPass) + h << m_indentation << "pass" << m_endl; + + //finish files + h<<m_endl<<m_endl; + + //close files and notfiy we are done + fileh.close(); + emit codeGenerated(c, true); +} + + +//////////////////////////////////////////////////////////////////////////////////// +// Helper Methods + +void PythonWriter::writeAttributes(UMLAttributeList atList, QTextStream &py) { + if (!forceDoc() || atList.count() == 0) + return; + py << m_indentation << "\"\"\" ATTRIBUTES" << m_endl << m_endl; + for (UMLAttribute *at = atList.first(); at; at = atList.next()) { + py << formatDoc(at->getDoc(), m_indentation + ' ') << m_endl; + Uml::Visibility vis = at->getVisibility(); + py << m_indentation << cleanName(at->getName()) << " (" + << vis.toString() << ")" << m_endl << m_endl ; + } // end for + py << m_indentation << "\"\"\"" << m_endl << m_endl; +} + +void PythonWriter::writeOperations(UMLClassifier *c, QTextStream &h) { + + //Lists to store operations sorted by scope + 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 + UMLOperationList opl(c->getOpList()); + 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; + } + } + + QString classname(cleanName(c->getName())); + + //write operations to file + if(forceSections() || !oppub.isEmpty()) { + writeOperations(classname,oppub,h,PUBLIC); + } + + if(forceSections() || !opprot.isEmpty()) { + writeOperations(classname,opprot,h,PROTECTED); + } + + if(forceSections() || !oppriv.isEmpty()) { + writeOperations(classname,oppriv,h,PRIVATE); + } + +} + +void PythonWriter::writeOperations(const QString& /*classname*/, UMLOperationList &opList, + QTextStream &h, Access access) { + UMLOperation *op; + UMLAttribute *at; + + QString sAccess; + + switch (access) { + + case PUBLIC: + sAccess = QString(""); + break; + case PRIVATE: + sAccess = QString("__"); + break; + case PROTECTED: + sAccess = QString("_"); + break; + } + + + for(op=opList.first(); op ; op=opList.next()) { + UMLAttributeList atl = op->getParmList(); + //write method doc if we have doc || if at least one of the params has doc + bool writeDoc = forceDoc() || !op->getDoc().isEmpty(); + for (at = atl.first(); at; at = atl.next()) + writeDoc |= !at->getDoc().isEmpty(); + + h<< m_indentation << "def "<< sAccess + cleanName(op->getName()) << "(self"; + + int j=0; + for (at = atl.first(); at; at = atl.next(), j++) { + h << ", " << cleanName(at->getName()) + << (!(at->getInitialValue().isEmpty()) ? + (QString(" = ")+at->getInitialValue()) : + QString("")); + } + + h<<"):"<<m_endl; + + if( writeDoc ) //write method documentation + { + h << m_indentation << m_indentation << "\"\"\"" << m_endl; + h << formatDoc(op->getDoc(), m_indentation + m_indentation + ' ') << m_endl; + + for (at = atl.first(); at; at = atl.next()) //write parameter documentation + { + if(forceDoc() || !at->getDoc().isEmpty()) { + h<<m_indentation<<m_indentation<<"@param "<<at->getTypeName()<< + " " << cleanName(at->getName()); + h<<" : "<<at->getDoc()<<m_endl; + } + }//end for : write parameter documentation + h<<m_indentation<<m_indentation<<"@return " + op->getTypeName()<<" :"<<m_endl; + h<<m_indentation<<m_indentation<<"@author"<<m_endl; + h<<m_indentation<<m_indentation<<"\"\"\""<<m_endl; + } + h<<m_indentation<<m_indentation<<"pass"<<m_endl<<m_endl; + m_bNeedPass = false; + }//end for +} + +/** + * returns "Python" + */ +Uml::Programming_Language PythonWriter::getLanguage() { + return Uml::pl_Python; +} + +const QStringList PythonWriter::reservedKeywords() const { + + static QStringList keywords; + + if (keywords.isEmpty()) { + keywords << "abs" + << "and" + << "apply" + << "ArithmeticError" + << "assert" + << "AssertionError" + << "AttributeError" + << "break" + << "buffer" + << "callable" + << "chr" + << "class" + << "classmethod" + << "cmp" + << "coerce" + << "compile" + << "complex" + << "continue" + << "def" + << "del" + << "delattr" + << "DeprecationWarning" + << "dict" + << "dir" + << "divmod" + << "elif" + << "Ellipsis" + << "else" + << "EnvironmentError" + << "EOFError" + << "eval" + << "except" + << "Exception" + << "exec" + << "execfile" + << "file" + << "filter" + << "finally" + << "float" + << "FloatingPointError" + << "for" + << "from" + << "getattr" + << "global" + << "globals" + << "hasattr" + << "hash" + << "hex" + << "id" + << "if" + << "import" + << "__import__" + << "ImportError" + << "in" + << "IndentationError" + << "IndexError" + << "input" + << "int" + << "intern" + << "IOError" + << "is" + << "isinstance" + << "issubclass" + << "iter" + << "KeyboardInterrupt" + << "KeyError" + << "lambda" + << "len" + << "list" + << "locals" + << "long" + << "LookupError" + << "map" + << "max" + << "MemoryError" + << "min" + << "NameError" + << "None" + << "not" + << "NotImplemented" + << "NotImplementedError" + << "object" + << "oct" + << "open" + << "or" + << "ord" + << "OSError" + << "OverflowError" + << "OverflowWarning" + << "pass" + << "pow" + << "print" + << "property" + << "raise" + << "range" + << "raw_input" + << "reduce" + << "ReferenceError" + << "reload" + << "repr" + << "return" + << "round" + << "RuntimeError" + << "RuntimeWarning" + << "setattr" + << "slice" + << "StandardError" + << "staticmethod" + << "StopIteration" + << "str" + << "super" + << "SyntaxError" + << "SyntaxWarning" + << "SystemError" + << "SystemExit" + << "TabError" + << "try" + << "tuple" + << "type" + << "TypeError" + << "UnboundLocalError" + << "unichr" + << "unicode" + << "UnicodeError" + << "UserWarning" + << "ValueError" + << "vars" + << "Warning" + << "while" + << "WindowsError" + << "xrange" + << "yield" + << "ZeroDivisionError" + << "zip"; + } + + return keywords; +} + +#include "pythonwriter.moc" diff --git a/umbrello/umbrello/codegenerators/pythonwriter.h b/umbrello/umbrello/codegenerators/pythonwriter.h new file mode 100644 index 00000000..f9e5b31a --- /dev/null +++ b/umbrello/umbrello/codegenerators/pythonwriter.h @@ -0,0 +1,86 @@ +/*************************************************************************** + pythonwriter.h - description + ------------------- + begin : Sat Dec 21 2002 + author : Vincent Decorges + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2003-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef PYTHONWRITER_H +#define PYTHONWRITER_H + +#include "simplecodegenerator.h" +#include "../umlattributelist.h" +#include "../umloperationlist.h" + +enum Access {PRIVATE, PUBLIC, PROTECTED}; + +/** + * class PythonWriter is a python code generator for UMLClassifier objects + * Just call writeClass and feed it a UMLClassifier; + */ +class PythonWriter : public SimpleCodeGenerator { + Q_OBJECT +public: + + PythonWriter(); + virtual ~PythonWriter(); + + /** + * call this method to generate C++ code for a UMLClassifier + * @param c the class you want to generate code for. + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "Python" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +private: + + /** + * write all attributes for a given class + * + * @param c the concept we are generating code for + * @param py output stream for the header file + */ + void writeAttributes(UMLAttributeList atList, QTextStream &py); + + /** + * write all operations for a given class + * + * @param c the concept we are generating code for + * @param h output stream for the header file + */ + void writeOperations(UMLClassifier *c, QTextStream &h); + + /** + * write a list of class operations + * + * @param classname the name of the class + * @param opList the list of operations + * @param h output stream for the header file + */ + void writeOperations(const QString& classname, UMLOperationList &opList, + QTextStream &h, Access access); + + bool m_bNeedPass; ///< True as long as no "pass" has been written +}; + +#endif //PYTHONWRITER diff --git a/umbrello/umbrello/codegenerators/rubyclassdeclarationblock.cpp b/umbrello/umbrello/codegenerators/rubyclassdeclarationblock.cpp new file mode 100644 index 00000000..cae5d322 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubyclassdeclarationblock.cpp @@ -0,0 +1,147 @@ +/*************************************************************************** + rubyclassdeclarationblock.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#include "rubyclassdeclarationblock.h" +#include "rubycodedocumentation.h" +#include "rubycodegenerator.h" +#include "../uml.h" + +// Constructors/Destructors +// + +RubyClassDeclarationBlock::RubyClassDeclarationBlock + ( RubyClassifierCodeDocument * parentDoc, const QString &startText, const QString &endText, const QString &comment) + : OwnedHierarchicalCodeBlock(parentDoc->getParentClassifier(), parentDoc, startText, endText, comment) +{ + init(parentDoc, comment); +} + +RubyClassDeclarationBlock::~RubyClassDeclarationBlock ( ) { } + +// +// Methods +// + +/** + * Save the XMI representation of this object + */ +void RubyClassDeclarationBlock::saveToXMI ( QDomDocument & doc, QDomElement & root ) { + QDomElement blockElement = doc.createElement( "rubyclassdeclarationblock" ); + + setAttributesOnNode(doc, blockElement); + + root.appendChild( blockElement ); +} + +/** + * load params from the appropriate XMI element node. + */ +void RubyClassDeclarationBlock::loadFromXMI ( QDomElement & root ) +{ + setAttributesFromNode(root); +} + +// Accessor methods +// + +// Other methods +// + +/** + * update the start and end text for this ownedhierarchicalcodeblock. + */ +void RubyClassDeclarationBlock::updateContent ( ) +{ + + RubyClassifierCodeDocument *parentDoc = dynamic_cast<RubyClassifierCodeDocument*>(getParentDocument()); + UMLClassifier *c = parentDoc->getParentClassifier(); + CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy(); + QString endLine = p->getNewLineEndingChars(); + bool isInterface = parentDoc->parentIsInterface(); // a little shortcut + QString RubyClassName = parentDoc->getRubyClassName(c->getName()); + bool forceDoc = p->getCodeVerboseDocumentComments(); + + // COMMENT + QString comment = c->getDoc(); + comment.replace("@ref ", ""); + comment.replace("@see", "_See_"); + comment.replace("@short", "_Summary_"); + comment.replace("@author", "_Author_"); + + if (isInterface) + getComment()->setText("Module " + RubyClassName + endLine + comment); + else + getComment()->setText("Class " + RubyClassName + endLine + comment); + + if(forceDoc || !c->getDoc().isEmpty()) + getComment()->setWriteOutText(true); + else + getComment()->setWriteOutText(false); + + + // Now set START/ENDING Text + QString startText = ""; + + if (parentDoc->parentIsInterface()) { + startText.append("module "); + } else { + startText.append("class "); + } + + UMLClassifierList superclasses = c->findSuperClassConcepts(UMLClassifier::CLASS); + UMLClassifierList superinterfaces = c->findSuperClassConcepts(UMLClassifier::INTERFACE); + + // write out inheritance + startText.append(RubyClassName); + + int i = 0; + for (UMLClassifier * concept= superclasses.first(); concept; concept = superclasses.next()) { + if (i == 0) { + startText.append(QString(" < ") + RubyCodeGenerator::cppToRubyType(concept->getName()) + endLine); + } else { + // After the first superclass name in the list, assume the classes + // are ruby modules that can be mixed in, + startText.append("include " + RubyCodeGenerator::cppToRubyType(concept->getName()) + endLine); + } + i++; + } + + // Write out the interfaces we 'implement'. Are these modules to be mixed in, in Ruby? + for (UMLClassifier * concept= superinterfaces.first(); concept; concept = superinterfaces.next()) { + startText.append(QString("include ") + RubyCodeGenerator::cppToRubyType(concept->getName()) + endLine); + } + + // Set the header and end text for the hier.codeblock + setStartText(startText); +} + +void RubyClassDeclarationBlock::init (RubyClassifierCodeDocument *parentDoc, const QString &comment) +{ + + setComment(new RubyCodeDocumentation(parentDoc)); + getComment()->setText(comment); + + setEndText("end"); + + updateContent(); + +} + + +#include "rubyclassdeclarationblock.moc" diff --git a/umbrello/umbrello/codegenerators/rubyclassdeclarationblock.h b/umbrello/umbrello/codegenerators/rubyclassdeclarationblock.h new file mode 100644 index 00000000..a7732662 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubyclassdeclarationblock.h @@ -0,0 +1,74 @@ + + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Wed Jul 16 2003 + */ + +#ifndef RUBYCLASSDECLARATIONBLOCK_H +#define RUBYCLASSDECLARATIONBLOCK_H + +#include <qstring.h> + +/*************************************************************************** + rubyclassdeclarationblock.h + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +#include "rubyclassifiercodedocument.h" +#include "../ownedhierarchicalcodeblock.h" + +class RubyClassDeclarationBlock : public OwnedHierarchicalCodeBlock +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Empty Constructor + */ + explicit RubyClassDeclarationBlock ( RubyClassifierCodeDocument * parentDoc, const QString &start = "", const QString &endText = "end", const QString &comment = ""); + + /** + * Empty Destructor + */ + virtual ~RubyClassDeclarationBlock ( ); + + /** + * Save the XMI representation of this object + */ + virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ); + + /** + * load params from the appropriate XMI element node. + */ + virtual void loadFromXMI ( QDomElement & root ); + +protected: + + /** + * Update the start/end text of this codeblock. + */ + void updateContent ( ); + +private: + + void init (RubyClassifierCodeDocument * parent, const QString &comment); + +}; + +#endif // RUBYCLASSDECLARATIONBLOCK_H diff --git a/umbrello/umbrello/codegenerators/rubyclassifiercodedocument.cpp b/umbrello/umbrello/codegenerators/rubyclassifiercodedocument.cpp new file mode 100644 index 00000000..1c136df8 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubyclassifiercodedocument.cpp @@ -0,0 +1,646 @@ +/*************************************************************************** + rubyclassifiercodedocument.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/** + We carve the Ruby document up into sections as follows: + + * header + * class declaration + * guts of the class (e.g. accessor methods, operations, dependant classes) +*/ + +// own header +#include "rubyclassifiercodedocument.h" + +// qt/kde includes +#include <qregexp.h> +#include <kdebug.h> + +// local includes +#include "rubycodegenerator.h" +#include "rubycodecomment.h" +#include "rubyclassdeclarationblock.h" +#include "rubycodeclassfielddeclarationblock.h" +#include "rubycodeoperation.h" +#include "codegen_utils.h" +#include "../classifier.h" +#include "../uml.h" + +// Constructors/Destructors +// + +RubyClassifierCodeDocument::RubyClassifierCodeDocument ( UMLClassifier * concept ) + : ClassifierCodeDocument (concept) { + init(); +} + +RubyClassifierCodeDocument::~RubyClassifierCodeDocument ( ) { } + +// +// Methods +// + +// Accessor methods +// + +// Make it easier on ourselves +RubyCodeGenerationPolicy * RubyClassifierCodeDocument::getRubyPolicy() { + CodeGenPolicyExt *pe = UMLApp::app()->getPolicyExt(); + RubyCodeGenerationPolicy * policy = dynamic_cast<RubyCodeGenerationPolicy*>(pe); + return policy; +} + +/** + * Get the dialog widget which allows user interaction with the object parameters. + * @return CodeDocumentDialog + */ +/* +CodeDocumentDialog RubyClassifierCodeDocument::getDialog ( ) { + +} +*/ + +// We overwritten by Ruby language implementation to get lowercase path +QString RubyClassifierCodeDocument::getPath ( ) +{ + + QString path = getPackage(); + + // Replace all white spaces with blanks + path.simplifyWhiteSpace(); + + // Replace all blanks with underscore + path.replace(QRegExp(" "), "_"); + + path.replace(QRegExp("\\."),"/"); + path.replace(QRegExp("::"), "/"); + + path.lower(); + + return path; + +} + + +// Other methods +// + +QString RubyClassifierCodeDocument::getRubyClassName (const QString &name) { + CodeGenerator *g = UMLApp::app()->getGenerator(); + return Codegen_Utils::capitalizeFirstLetter(g->cleanName(name)); +} + +// Initialize this ruby classifier code document +void RubyClassifierCodeDocument::init ( ) { + + setFileExtension(".rb"); + + //initCodeClassFields(); // this is dubious because it calls down to + // CodeGenFactory::newCodeClassField(this) + // but "this" is still in construction at that time. + + classDeclCodeBlock = 0; + publicBlock = 0; + protectedBlock = 0; + privateBlock = 0; + pubConstructorBlock = 0; + protConstructorBlock = 0; + privConstructorBlock = 0; + pubOperationsBlock = 0; + privOperationsBlock = 0; + protOperationsBlock = 0; + + // this will call updateContent() as well as other things that sync our document. + synchronize(); +} + +/** + * @param op + */ +// in the vanilla version, we just tack all operations on the end +// of the document +bool RubyClassifierCodeDocument::addCodeOperation (CodeOperation * op ) +{ + Uml::Visibility scope = op->getParentOperation()->getVisibility(); + if(!op->getParentOperation()->isConstructorOperation()) + { + switch (scope) { + default: + case Uml::Visibility::Public: + return pubOperationsBlock->addTextBlock(op); + break; + case Uml::Visibility::Protected: + return protOperationsBlock->addTextBlock(op); + break; + case Uml::Visibility::Private: + return privOperationsBlock->addTextBlock(op); + break; + } + } else { + switch (scope) { + default: + case Uml::Visibility::Public: + return pubConstructorBlock->addTextBlock(op); + break; + case Uml::Visibility::Protected: + return protConstructorBlock->addTextBlock(op); + break; + case Uml::Visibility::Private: + return privConstructorBlock->addTextBlock(op); + break; + } + } +} + +// Sigh. NOT optimal. The only reason that we need to have this +// is so we can create the RubyClassDeclarationBlock. +// would be better if we could create a handler interface that each +// codeblock used so all we have to do here is add the handler +// for "rubyclassdeclarationblock" +void RubyClassifierCodeDocument::loadChildTextBlocksFromNode ( QDomElement & root) +{ + + QDomNode tnode = root.firstChild(); + QDomElement telement = tnode.toElement(); + bool loadCheckForChildrenOK = false; + while( !telement.isNull() ) { + QString nodeName = telement.tagName(); + + if( nodeName == "textblocks" ) { + + QDomNode node = telement.firstChild(); + QDomElement element = node.toElement(); + + // if there is nothing to begin with, then we don't worry about it + loadCheckForChildrenOK = element.isNull() ? true : false; + + while( !element.isNull() ) { + QString name = element.tagName(); + + if( name == "codecomment" ) { + CodeComment * block = new RubyCodeComment(this); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"loadFromXMI : unable to add codeComment to :"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "codeaccessormethod" || + name == "ccfdeclarationcodeblock" + ) { + QString acctag = element.attribute("tag",""); + // search for our method in the + TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag); + if(!tb || !addTextBlock(tb)) + { + kError()<<"loadFromXMI : unable to add codeclassfield child method to:"<<this<<endl; + // DON'T delete + } else + loadCheckForChildrenOK= true; + + } else + if( name == "codeblock" ) { + CodeBlock * block = newCodeBlock(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"loadFromXMI : unable to add codeBlock to :"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "codeblockwithcomments" ) { + CodeBlockWithComments * block = newCodeBlockWithComments(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"loadFromXMI : unable to add codeBlockwithcomments to:"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "header" ) { + // do nothing.. this is treated elsewhere + } else + if( name == "hierarchicalcodeblock" ) { + HierarchicalCodeBlock * block = newHierarchicalCodeBlock(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add hierarchicalcodeBlock to:"<<this<<endl; + block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } else + if( name == "codeoperation" ) { + // find the code operation by id + QString id = element.attribute("parent_id","-1"); + UMLObject * obj = UMLApp::app()->getDocument()->findObjectById(STR2ID(id)); + UMLOperation * op = dynamic_cast<UMLOperation*>(obj); + if(op) { + CodeOperation * block = new RubyCodeOperation(this, op); + block->loadFromXMI(element); + if(addTextBlock(block)) + loadCheckForChildrenOK= true; + else + { + kError()<<"Unable to add codeoperation to:"<<this<<endl; + block->deleteLater(); + } + } else + kError()<<"Unable to find operation create codeoperation for:"<<this<<endl; + } else + if( name == "rubyclassdeclarationblock" ) + { + RubyClassDeclarationBlock * block = getClassDecl(); + block->loadFromXMI(element); + if(!addTextBlock(block)) + { + kError()<<"Unable to add ruby code declaration block to:"<<this<<endl; + // DON'T delete. + // block->deleteLater(); + } else + loadCheckForChildrenOK= true; + } + // This last item is only needed for extreme debugging conditions + // (E.g. making new codeclassdocument loader) + // else + // kDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignorning"<<endl; + + node = element.nextSibling(); + element = node.toElement(); + } + break; + } + + tnode = telement.nextSibling(); + telement = tnode.toElement(); + } + + if(!loadCheckForChildrenOK) + { + CodeDocument * test = dynamic_cast<CodeDocument*>(this); + if(test) + { + kWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<<test->getFileName()<<" "<<this<<endl; + } else { + HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(this); + if(hb) + kWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<<hb->getTag()<<" "<<this<<endl; + else + kDebug()<<" loadChildBlocks : unable to initialize any child blocks in UNKNOWN OBJ:"<<this<<endl; + } + } + + +} + +QString RubyClassifierCodeDocument::scopeToRubyDecl(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; +} + +RubyClassDeclarationBlock * RubyClassifierCodeDocument::getClassDecl() +{ + if(!classDeclCodeBlock) + { + classDeclCodeBlock = new RubyClassDeclarationBlock (this); + classDeclCodeBlock->setTag("ClassDeclBlock"); + } + return classDeclCodeBlock; +} + +void RubyClassifierCodeDocument::resetTextBlocks() +{ + + // all special pointers to text blocks need to be zero'd out + operationsBlock = 0; + constructorBlock = 0; + classDeclCodeBlock = 0; + + // now do traditional release of text blocks. + ClassifierCodeDocument::resetTextBlocks(); +} + +// This method will cause the class to rebuild its text representation. +// based on the parent classifier object. +// For any situation in which this is called, we are either building the code +// document up, or replacing/regenerating the existing auto-generated parts. As +// such, we will want to insert everything we resonablely will want +// during creation. We can set various parts of the document (esp. the +// comments) to appear or not, as needed. +void RubyClassifierCodeDocument::updateContent( ) +{ + // Gather info on the various fields and parent objects of this class... + UMLClassifier * c = getParentClassifier(); + RubyCodeGenerator * gen = dynamic_cast<RubyCodeGenerator*>(UMLApp::app()->getGenerator()); + + // first, set the global flag on whether or not to show classfield info + // This depends on whether or not we have attribute/association classes + CodeClassFieldList * cfList = getCodeClassFieldList(); + for(CodeClassField * field = cfList->first(); field; field = cfList->next()) + if(field->parentIsAttribute()) + field->setWriteOutMethods(gen->getAutoGenerateAttribAccessors()); + else + field->setWriteOutMethods(gen->getAutoGenerateAssocAccessors()); + + // attribute-based ClassFields + // we do it this way to have the static fields sorted out from regular ones + CodeClassFieldList staticPublicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Public ); + CodeClassFieldList publicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Public ); + CodeClassFieldList staticProtectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Protected ); + CodeClassFieldList protectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Protected ); + CodeClassFieldList staticPrivateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Private ); + CodeClassFieldList privateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Private); + + // association-based ClassFields + // don't care if they are static or not..all are lumped together + CodeClassFieldList publicPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Public); + CodeClassFieldList publicAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Public); + CodeClassFieldList publicCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Public ); + + CodeClassFieldList protPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Protected); + CodeClassFieldList protAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Protected); + CodeClassFieldList protCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Protected); + + CodeClassFieldList privPlainAssocClassFields = getSpecificClassFields ( CodeClassField::PlainAssociation , Uml::Visibility::Private); + CodeClassFieldList privAggregationClassFields = getSpecificClassFields ( CodeClassField::Aggregation, Uml::Visibility::Private); + CodeClassFieldList privCompositionClassFields = getSpecificClassFields ( CodeClassField::Composition, Uml::Visibility::Private); + + bool isInterface = parentIsInterface(); + bool hasOperationMethods = c->getOpList().last() ? true : false; + CodeGenerationPolicy *pol = UMLApp::app()->getCommonPolicy(); + QString endLine = pol->getNewLineEndingChars(); // a shortcut..so we don't have to call this all the time + + // + // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT + // + + + // CLASS DECLARATION BLOCK + // + + // get the declaration block. If its not already present, add it too + RubyClassDeclarationBlock * myClassDeclCodeBlock = getClassDecl(); + addTextBlock(myClassDeclCodeBlock); // note: wont add if already present + + // declare public, protected and private methods, attributes (fields). + // set the start text ONLY if this is the first time we created the objects. + bool createdPublicBlock = publicBlock == 0 ? true : false; + publicBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("publicBlock","Public Items",0); + if (createdPublicBlock) + publicBlock->setStartText("public"); + + bool createdProtBlock = protectedBlock == 0 ? true : false; + protectedBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("protectedBlock","Protected Items",0); + if(createdProtBlock) + protectedBlock->setStartText("protected"); + + bool createdPrivBlock = privateBlock == 0 ? true : false; + privateBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock("privateBlock","Private Items",0); + if(createdPrivBlock) + privateBlock->setStartText("private"); + + // NOW create document in sections.. + // now we want to populate the body of our class + // our layout is the following general groupings of code blocks: + + // start ruby classifier document + + // header comment + + // class declaration + + // section: + + // section: + // - methods section comment + + // sub-section: constructor ops + // - constructor method section comment + // - constructor methods (0+ codeblocks) + + // sub-section: accessors + // - accessor method section comment + // - static accessor methods (0+ codeblocks) + // - non-static accessor methods (0+ codeblocks) + + // sub-section: non-constructor ops + // - operation method section comment + // - operations (0+ codeblocks) + + // end class declaration + + // end ruby classifier document + + + // Q: Why use the more complicated scheme of arranging code blocks within codeblocks? + // A: This will allow us later to preserve the format of our document so that if + // codeblocks are added, they may be easily added in the correct place, rather than at + // the end of the document, or by using a difficult algorithm to find the location of + // the last appropriate code block sibling (which may not exist.. for example user adds + // a constructor operation, but there currently are no constructor code blocks + // within the document). + + + // + // METHODS section + // + + // get/create the method codeblock + // public methods + HierarchicalCodeBlock * pubMethodsBlock = publicBlock->getHierarchicalCodeBlock("pubMethodsBlock", "", 1); + CodeComment * pubMethodsComment = pubMethodsBlock->getComment(); + bool forceDoc = pol->getCodeVerboseDocumentComments(); + // set conditions for showing this comment + if (!forceDoc && !hasClassFields() && !hasOperationMethods) + pubMethodsComment->setWriteOutText(false); + else + pubMethodsComment->setWriteOutText(true); + + // protected methods + HierarchicalCodeBlock * protMethodsBlock = protectedBlock->getHierarchicalCodeBlock("protMethodsBlock", "", 1); + CodeComment * protMethodsComment = protMethodsBlock->getComment(); + // set conditions for showing this comment + if (!forceDoc && !hasClassFields() && !hasOperationMethods) + protMethodsComment->setWriteOutText(false); + else + protMethodsComment->setWriteOutText(true); + + // private methods + HierarchicalCodeBlock * privMethodsBlock = privateBlock->getHierarchicalCodeBlock("privMethodsBlock", "", 1); + CodeComment * privMethodsComment = privMethodsBlock->getComment(); + // set conditions for showing this comment + if (!forceDoc && !hasClassFields() && !hasOperationMethods) + privMethodsComment->setWriteOutText(false); + else + privMethodsComment->setWriteOutText(true); + + // METHODS sub-section : constructor methods + // + + // public + pubConstructorBlock = pubMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1); + // special condiions for showing comment: only when autogenerateding empty constructors + // Although, we *should* check for other constructor methods too + CodeComment * pubConstComment = pubConstructorBlock->getComment(); + if (!forceDoc && (isInterface || !pol->getAutoGenerateConstructors())) + pubConstComment->setWriteOutText(false); + else + pubConstComment->setWriteOutText(true); + + // protected + protConstructorBlock = protMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1); + // special condiions for showing comment: only when autogenerateding empty constructors + // Although, we *should* check for other constructor methods too + CodeComment * protConstComment = protConstructorBlock->getComment(); + if (!forceDoc && (isInterface || !pol->getAutoGenerateConstructors())) + protConstComment->setWriteOutText(false); + else + protConstComment->setWriteOutText(true); + + // private + privConstructorBlock = privMethodsBlock->getHierarchicalCodeBlock("constructionMethods", "Constructors", 1); + // special condiions for showing comment: only when autogenerateding empty constructors + // Although, we *should* check for other constructor methods too + CodeComment * privConstComment = privConstructorBlock->getComment(); + if (!forceDoc && (isInterface || !pol->getAutoGenerateConstructors())) + privConstComment->setWriteOutText(false); + else + privConstComment->setWriteOutText(true); + + // get/create the accessor codeblock + // public + HierarchicalCodeBlock * pubAccessorBlock = pubMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1); + // set conditions for showing section comment + CodeComment * pubAccessComment = pubAccessorBlock->getComment(); + if (!forceDoc && !hasClassFields()) + pubAccessComment->setWriteOutText(false); + else + pubAccessComment->setWriteOutText(true); + + // protected + HierarchicalCodeBlock * protAccessorBlock = protMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1); + // set conditions for showing section comment + CodeComment * protAccessComment = protAccessorBlock->getComment(); + if (!forceDoc && !hasClassFields()) + protAccessComment->setWriteOutText(false); + else + protAccessComment->setWriteOutText(true); + + // private + HierarchicalCodeBlock * privAccessorBlock = privMethodsBlock->getHierarchicalCodeBlock("accessorMethods", "Accessor Methods", 1); + // set conditions for showing section comment + CodeComment * privAccessComment = privAccessorBlock->getComment(); + if (!forceDoc && !hasClassFields()) + privAccessComment->setWriteOutText(false); + else + privAccessComment->setWriteOutText(true); + + // now, 2 sub-sub sections in accessor block + // add/update accessor methods for attributes + HierarchicalCodeBlock * pubStaticAccessors = pubAccessorBlock->getHierarchicalCodeBlock("pubStaticAccessorMethods", "", 1); + HierarchicalCodeBlock * pubRegularAccessors = pubAccessorBlock->getHierarchicalCodeBlock("pubRegularAccessorMethods", "", 1); + pubStaticAccessors->getComment()->setWriteOutText(false); // never write block comment + pubRegularAccessors->getComment()->setWriteOutText(false); // never write block comment + + HierarchicalCodeBlock * protStaticAccessors = protAccessorBlock->getHierarchicalCodeBlock("protStaticAccessorMethods", "", 1); + HierarchicalCodeBlock * protRegularAccessors = protAccessorBlock->getHierarchicalCodeBlock("protRegularAccessorMethods", "", 1); + protStaticAccessors->getComment()->setWriteOutText(false); // never write block comment + protRegularAccessors->getComment()->setWriteOutText(false); // never write block comment + + HierarchicalCodeBlock * privStaticAccessors = privAccessorBlock->getHierarchicalCodeBlock("privStaticAccessorMethods", "", 1); + HierarchicalCodeBlock * privRegularAccessors = privAccessorBlock->getHierarchicalCodeBlock("privRegularAccessorMethods", "", 1); + privStaticAccessors->getComment()->setWriteOutText(false); // never write block comment + privRegularAccessors->getComment()->setWriteOutText(false); // never write block comment + // now add in accessors as appropriate + + // public stuff + pubStaticAccessors->addCodeClassFieldMethods(staticPublicAttribClassFields); + pubRegularAccessors->addCodeClassFieldMethods(publicAttribClassFields); + pubRegularAccessors->addCodeClassFieldMethods(publicPlainAssocClassFields); + pubRegularAccessors->addCodeClassFieldMethods(publicAggregationClassFields); + pubRegularAccessors->addCodeClassFieldMethods(publicCompositionClassFields); + + // protected stuff + protStaticAccessors->addCodeClassFieldMethods(staticProtectedAttribClassFields); + protRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields); + protRegularAccessors->addCodeClassFieldMethods(protPlainAssocClassFields); + protRegularAccessors->addCodeClassFieldMethods(protAggregationClassFields); + protRegularAccessors->addCodeClassFieldMethods(protCompositionClassFields); + + // private stuff + privStaticAccessors->addCodeClassFieldMethods(staticPrivateAttribClassFields); + privRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields); + privRegularAccessors->addCodeClassFieldMethods(privPlainAssocClassFields); + privRegularAccessors->addCodeClassFieldMethods(privAggregationClassFields); + privRegularAccessors->addCodeClassFieldMethods(privCompositionClassFields); + + // METHODS subsection : Operation methods (which aren't constructors) + // + + // setup/get/create the operations codeblock + + // public + pubOperationsBlock = pubMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1); + // set conditions for showing section comment + CodeComment * pubOcomment = pubOperationsBlock->getComment(); + if (!forceDoc && !hasOperationMethods ) + pubOcomment->setWriteOutText(false); + else + pubOcomment->setWriteOutText(true); + + //protected + protOperationsBlock = protMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1); + // set conditions for showing section comment + CodeComment * protOcomment = protOperationsBlock->getComment(); + if (!forceDoc && !hasOperationMethods ) + protOcomment->setWriteOutText(false); + else + protOcomment->setWriteOutText(true); + + //private + privOperationsBlock = privMethodsBlock->getHierarchicalCodeBlock("operationMethods", "Operations", 1); + // set conditions for showing section comment + CodeComment * privOcomment = privOperationsBlock->getComment(); + if (!forceDoc && !hasOperationMethods ) + privOcomment->setWriteOutText(false); + else + privOcomment->setWriteOutText(true); + +} + + +#include "rubyclassifiercodedocument.moc" diff --git a/umbrello/umbrello/codegenerators/rubyclassifiercodedocument.h b/umbrello/umbrello/codegenerators/rubyclassifiercodedocument.h new file mode 100644 index 00000000..c5f89d07 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubyclassifiercodedocument.h @@ -0,0 +1,126 @@ +/*************************************************************************** + rubyclassdeclarationblock.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + + +#ifndef RUBYCLASSIFIERCODEDOCUMENT_H +#define RUBYCLASSIFIERCODEDOCUMENT_H + +#include <qstring.h> + +#include "../codeclassfieldlist.h" +#include "../classifiercodedocument.h" +#include "../classifier.h" +#include "../hierarchicalcodeblock.h" +#include "classifierinfo.h" +#include "rubycodeclassfield.h" +#include "rubycodeoperation.h" + +class RubyClassDeclarationBlock; +class RubyCodeGenerationPolicy; + +/** + * class RubyClassifierCodeDocument + * A Ruby UMLClassifier Code Document. + */ + +class RubyClassifierCodeDocument : public ClassifierCodeDocument +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + + /** + * Constructor + */ + RubyClassifierCodeDocument (UMLClassifier * classifier); + + /** + * Empty Destructor + */ + virtual ~RubyClassifierCodeDocument ( ); + + /** + * Get the dialog widget which allows user interaction with the object parameters. + * @return CodeDocumentDialog + */ + //CodeDocumentDialog getDialog ( ); + + QString scopeToRubyDecl(Uml::Visibility scope); + + // Make it easier on ourselves + RubyCodeGenerationPolicy * getRubyPolicy(); + + QString getRubyClassName (const QString &name); + + QString getPath(); + + /** add a code operation to this ruby classifier code document. + * @return bool which is true IF the code operation was added successfully + */ + bool addCodeOperation (CodeOperation * op ); + +protected: + + // reset/clear our inventory of textblocks in this document + void resetTextBlocks(); + + /** + * need to overwrite this for ruby since we need to pick up the + * ruby class declaration block. + */ + virtual void loadChildTextBlocksFromNode ( QDomElement & root); + + void addOrUpdateCodeClassFieldMethodsInCodeBlock(CodeClassFieldList &list, RubyClassDeclarationBlock * codeBlock); + + bool forceDoc (); + + void updateContent(); + +private: + + RubyClassDeclarationBlock * classDeclCodeBlock; + HierarchicalCodeBlock * constructorBlock; + HierarchicalCodeBlock * operationsBlock; + + HierarchicalCodeBlock * publicBlock; + HierarchicalCodeBlock * privateBlock; + HierarchicalCodeBlock * protectedBlock; + +// HierarchicalCodeBlock * namespaceBlock; + + HierarchicalCodeBlock * pubConstructorBlock; + HierarchicalCodeBlock * protConstructorBlock; + HierarchicalCodeBlock * privConstructorBlock; + + HierarchicalCodeBlock * pubOperationsBlock; + HierarchicalCodeBlock * privOperationsBlock; + HierarchicalCodeBlock * protOperationsBlock; + + ClassifierInfo * info; + + void init ( ); + RubyClassDeclarationBlock * getClassDecl(); + + +}; + +#endif // RUBYCLASSIFIERCODEDOCUMENT_H diff --git a/umbrello/umbrello/codegenerators/rubycodeaccessormethod.cpp b/umbrello/umbrello/codegenerators/rubycodeaccessormethod.cpp new file mode 100644 index 00000000..a3f55c44 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodeaccessormethod.cpp @@ -0,0 +1,233 @@ +/*************************************************************************** + rubycodeaccessormethod.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// own header +#include "rubycodeaccessormethod.h" + +// qt/kde includes +#include <qregexp.h> +#include <kdebug.h> + +// local includes +#include "../attribute.h" +#include "../codegenerator.h" +#include "../classifiercodedocument.h" +#include "../umlobject.h" +#include "../umlrole.h" +#include "../uml.h" +#include "codegen_utils.h" +#include "rubyclassifiercodedocument.h" +#include "rubycodegenerationpolicy.h" +#include "rubycodegenerator.h" +#include "rubycodeclassfield.h" +#include "rubycodedocumentation.h" + +// Constructors/Destructors +// + +RubyCodeAccessorMethod::RubyCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type) + : CodeAccessorMethod ( field ) +{ + setType(type); + + // lets use full-blown comment + RubyClassifierCodeDocument *rccd = dynamic_cast<RubyClassifierCodeDocument*>(field->getParentDocument()); + setComment(new RubyCodeDocumentation(rccd)); +} + +RubyCodeAccessorMethod::~RubyCodeAccessorMethod ( ) { } + +// Other methods +// + +void RubyCodeAccessorMethod::setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement) +{ + + // set super-class attributes + CodeAccessorMethod::setAttributesOnNode(doc, blockElement); + + // set local attributes now +} + +void RubyCodeAccessorMethod::setAttributesFromNode( QDomElement & root) +{ + + // set attributes from superclass method the XMI + CodeAccessorMethod::setAttributesFromNode(root); + + // load local stuff + +} + +void RubyCodeAccessorMethod::updateContent( ) +{ + + CodeClassField * parentField = getParentClassField(); + RubyCodeClassField * rubyfield = dynamic_cast<RubyCodeClassField*>(parentField); + QString fieldName = rubyfield->getFieldName(); + QString endLine = UMLApp::app()->getCommonPolicy()->getNewLineEndingChars(); + + QString text = ""; + switch(getType()) { + case CodeAccessorMethod::ADD: + { + int maxOccurs = rubyfield->maximumListOccurances(); + QString fieldType = rubyfield->getTypeName(); + QString indent = getIndentation(); + if(maxOccurs > 0) + text += "if "+fieldName+".size() < "+ QString::number(maxOccurs)+' '+endLine+indent; + text += fieldName+".push(value)"; + if(maxOccurs > 0) + { + text += endLine+"else"+endLine; + text += indent + "puts(\"ERROR: Can't add"+fieldType+" to "+fieldName+", minimum number of items reached.\")"+endLine+"end"+endLine; + } + break; + } + case CodeAccessorMethod::GET: +// text = "return "+fieldName; + break; + case CodeAccessorMethod::LIST: + text = "return "+fieldName; + break; + case CodeAccessorMethod::REMOVE: + { + int minOccurs = rubyfield->minimumListOccurances(); + RubyClassifierCodeDocument * rubydoc = dynamic_cast<RubyClassifierCodeDocument*>(rubyfield->getParentDocument()); + QString fieldType = rubyfield->getTypeName(); + QString indent = getIndentation(); + + if(minOccurs > 0) + text += "if "+fieldName+".size() >= "+ QString::number(minOccurs)+endLine+indent; + text += fieldName+".delete(value)"; + if(minOccurs > 0) + { + text += endLine+"else"+endLine; + text += indent + "puts(\"ERROR: Cant remove"+fieldType+" from "+fieldName+", minimum number of items reached.\")"+endLine+"end"+endLine; + } + break; + } + case CodeAccessorMethod::SET: +// text = fieldName+" = value"; + break; + default: + // do nothing + break; + } + + setText(text); + +} + +void RubyCodeAccessorMethod::updateMethodDeclaration() +{ + + RubyCodeClassField * rubyfield = dynamic_cast<RubyCodeClassField*>(getParentClassField()); + RubyClassifierCodeDocument * rubydoc = dynamic_cast<RubyClassifierCodeDocument*>(rubyfield->getParentDocument()); + + // gather defs + CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy(); + CodeGenerationPolicy::ScopePolicy scopePolicy = p->getAttributeAccessorScope(); + QString strVis = rubydoc->scopeToRubyDecl(rubyfield->getVisibility()); + QString fieldName = RubyCodeGenerator::cppToRubyName(rubyfield->getFieldName()); + QString fieldType = RubyCodeGenerator::cppToRubyType(rubyfield->getTypeName()); + QString objectType = rubyfield->getListObjectType(); + if(objectType.isEmpty()) + objectType = fieldName; + QString endLine = p->getNewLineEndingChars(); + + QString description = getParentObject()->getDoc(); + description.replace(QRegExp("m_[npb](?=[A-Z])"), ""); + description.replace("m_", ""); + description.replace(QRegExp("[\\n\\r]+[\\t ]*"), endLine); + + // set scope of this accessor appropriately..if its an attribute, + // we need to be more sophisticated + if(rubyfield->parentIsAttribute()) + switch (scopePolicy) { + case CodeGenerationPolicy::Public: + case CodeGenerationPolicy::Private: + case CodeGenerationPolicy::Protected: + strVis = rubydoc->scopeToRubyDecl((Uml::Visibility::Value) scopePolicy); + break; + default: + case CodeGenerationPolicy::FromParent: + // do nothing..already have taken parent value + break; + } + + // some variables we will need to populate + QString headerText = ""; + QString methodReturnType = ""; + QString methodName = ""; + QString methodParams = ""; + + switch(getType()) { + case CodeAccessorMethod::ADD: + methodName = "add" + Codegen_Utils::capitalizeFirstLetter(fieldType); + methodReturnType = ""; + methodParams = objectType+" value "; + headerText = "Add an object of type "+objectType+" to the Array "+fieldName+endLine+description+endLine+"@return nil"; + setStartMethodText("def "+ methodName + '(' + methodParams + ')'); + setEndMethodText("end"); + break; + case CodeAccessorMethod::GET: + headerText = "Get the value of " + fieldName + endLine + description; + setStartMethodText(QString("attr_reader :") + fieldName); + setEndMethodText(""); + break; + case CodeAccessorMethod::LIST: + methodName = "get" + Codegen_Utils::capitalizeFirstLetter(fieldType)+"List"; + methodReturnType = ""; + headerText = "Get the list of "+fieldName+endLine+description+endLine+"_returns_ List of "+fieldName; + setStartMethodText("def "+ methodName + '(' + methodParams + ')'); + setEndMethodText("end"); + break; + case CodeAccessorMethod::REMOVE: + methodName = "remove" + Codegen_Utils::capitalizeFirstLetter(fieldType); + methodReturnType = ""; + methodParams = objectType+" value "; + headerText = "Remove an object of type "+objectType+" from the List "+fieldName+endLine+description; + setStartMethodText("def "+ methodName + '(' + methodParams + ')'); + setEndMethodText("end"); + break; + case CodeAccessorMethod::SET: + headerText = "Set the value of " + fieldName + endLine + description; + setStartMethodText(QString("attr_writer :") + fieldName); + setEndMethodText(""); + break; + default: + // do nothing..no idea what this is + kWarning()<<"Warning: can't generate RubyCodeAccessorMethod for type: "<<getType()<<endl; + break; + } + + // set header once. + if (getComment()->getText().isEmpty()) + getComment()->setText(headerText); + +} + +void RubyCodeAccessorMethod::update() +{ + updateMethodDeclaration(); + updateContent(); +} + +#include "rubycodeaccessormethod.moc" diff --git a/umbrello/umbrello/codegenerators/rubycodeaccessormethod.h b/umbrello/umbrello/codegenerators/rubycodeaccessormethod.h new file mode 100644 index 00000000..7eb9c892 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodeaccessormethod.h @@ -0,0 +1,73 @@ +/*************************************************************************** + rubycodeaccessormethod.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Thu Oct 2 2003 + */ + +#ifndef RUBYCODEACCESSORMETHOD_H +#define RUBYCODEACCESSORMETHOD_H + +#include <qstring.h> + +#include "../codeaccessormethod.h" +#include "rubycodeclassfield.h" + +class RubyCodeAccessorMethod : public CodeAccessorMethod +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructor + */ + RubyCodeAccessorMethod ( CodeClassField * field, CodeAccessorMethod::AccessorType type); + + /** + * Empty Destructor + */ + virtual ~RubyCodeAccessorMethod ( ); + + /** + * Must be called before this object is usable + */ + void update(); + +protected: + + /** set attributes of the node that represents this class + * in the XMI document. + */ + virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement); + + /** set the class attributes of this object from + * the passed element node. + */ + virtual void setAttributesFromNode ( QDomElement & element); + + virtual void updateMethodDeclaration(); + virtual void updateContent(); + +private: + +}; + +#endif // RUBYCODEACCESSORMETHOD_H diff --git a/umbrello/umbrello/codegenerators/rubycodeclassfield.cpp b/umbrello/umbrello/codegenerators/rubycodeclassfield.cpp new file mode 100644 index 00000000..35438abd --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodeclassfield.cpp @@ -0,0 +1,113 @@ +/*************************************************************************** + rubycodeclassfield.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// own header +#include "rubycodeclassfield.h" + +// qt/kde includes +#include <qregexp.h> +#include <kdebug.h> + +// local includes +#include "rubycodecomment.h" +#include "rubycodegenerator.h" + +#include "../attribute.h" +#include "../umlobject.h" +#include "../umlrole.h" +#include "../uml.h" + +#include "rubyclassifiercodedocument.h" + +// Constructors/Destructors +// + +RubyCodeClassField::RubyCodeClassField (ClassifierCodeDocument * parentDoc, UMLRole * role) + : CodeClassField(parentDoc, role) +{ + +} + +RubyCodeClassField::RubyCodeClassField (ClassifierCodeDocument * parentDoc, UMLAttribute * attrib) + : CodeClassField(parentDoc, attrib) +{ + +} + +RubyCodeClassField::~RubyCodeClassField ( ) { } + +// +// Methods +// + +// Other methods +// + +QString RubyCodeClassField::getFieldName() { + if (parentIsAttribute()) + { + UMLAttribute * at = (UMLAttribute*) getParentObject(); + return cleanName(at->getName()); + } + else + { + UMLRole * role = (UMLRole*) getParentObject(); + QString roleName = role->getName(); + if(fieldIsSingleValue()) { + return roleName.replace(0, 1, roleName.left(1).lower()); + } else { + return roleName.lower() + "Array"; + } + } +} + + +QString RubyCodeClassField::getInitialValue() { + + if (parentIsAttribute()) + { + UMLAttribute * at = dynamic_cast<UMLAttribute*>( getParentObject() ); + if (at) { + return fixInitialStringDeclValue(at->getInitialValue(), getTypeName()); + } else { + kError() << "RubyodeClassField::getInitialValue: parent object is not a UMLAttribute" + << endl; + return ""; + } + return fixInitialStringDeclValue(at->getInitialValue(), getTypeName()); + } + else + { + if(fieldIsSingleValue()) { + // FIX : IF the multiplicity is "1" then we should init a new object here, if its 0 or 1, + // then we can just return 'empty' string (minor problem). + return QString(""); + } else { + return RubyCodeGenerator::getListFieldClassName()+".new()"; + } + } + +} + +QString RubyCodeClassField::getTypeName ( ) +{ + return RubyCodeGenerator::cppToRubyType(CodeClassField::getTypeName()); +} + +#include "rubycodeclassfield.moc" diff --git a/umbrello/umbrello/codegenerators/rubycodeclassfield.h b/umbrello/umbrello/codegenerators/rubycodeclassfield.h new file mode 100644 index 00000000..384f0b5d --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodeclassfield.h @@ -0,0 +1,61 @@ +/*************************************************************************** + rubycodeclassfield.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef RUBYCODECLASSFIELD_H +#define RUBYCODECLASSFIELD_H + +#include <qstring.h> + +#include "../codeclassfield.h" + +class ClassifierCodeDocument; + +class RubyCodeClassField : public CodeClassField +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructors + */ + RubyCodeClassField (ClassifierCodeDocument * parentDoc, UMLRole * role); + RubyCodeClassField (ClassifierCodeDocument * parentDoc, UMLAttribute * attrib); + + /** + * Empty Destructor + */ + virtual ~RubyCodeClassField ( ); + + QString getFieldType(); + QString getFieldName(); + QString getInitialValue(); + + QString getTypeName ( ); +protected: + +private: + + // void initDeclCodeBlock (); + +}; + +#endif // RUBYCODECLASSFIELD_H diff --git a/umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.cpp b/umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.cpp new file mode 100644 index 00000000..380c05e0 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.cpp @@ -0,0 +1,112 @@ +/*************************************************************************** + * * + * 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) 2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#include "rubycodeclassfielddeclarationblock.h" + +#include "rubycodeclassfield.h" +#include "rubyclassifiercodedocument.h" +#include "rubycodegenerationpolicy.h" +#include "../classifier.h" +#include "../umlrole.h" +#include "../codegenerator.h" +#include "../uml.h" + +// Constructors/Destructors +// + +RubyCodeClassFieldDeclarationBlock::RubyCodeClassFieldDeclarationBlock ( CodeClassField * parent ) + : CodeClassFieldDeclarationBlock ( parent ) +{ + setOverallIndentationLevel(1); + updateContent(); +} + +RubyCodeClassFieldDeclarationBlock::~RubyCodeClassFieldDeclarationBlock ( ) { } + +// +// Methods +// + + + +// Other methods +// + +/** + */ +void RubyCodeClassFieldDeclarationBlock::updateContent( ) +{ + + CodeClassField * cf = getParentClassField(); + ClassifierCodeDocument * doc = cf->getParentDocument(); + RubyCodeClassField * rcf = dynamic_cast<RubyCodeClassField*>(cf); + RubyClassifierCodeDocument* rdoc = dynamic_cast<RubyClassifierCodeDocument*>(doc); + CodeGenerationPolicy * p = UMLApp::app()->getCommonPolicy(); + CodeGenerationPolicy::ScopePolicy scopePolicy = p->getAssociationFieldScope(); + + // Set the comment + QString notes = getParentObject()->getDoc(); + getComment()->setText(notes); + + // Set the body + QString staticValue = getParentObject()->getStatic() ? "static " : ""; + QString scopeStr = rdoc->scopeToRubyDecl(getParentObject()->getVisibility()); + + // IF this is from an association, then scope taken as appropriate to policy + if(!rcf->parentIsAttribute()) + { + switch (scopePolicy) { + case CodeGenerationPolicy::Public: + case CodeGenerationPolicy::Private: + case CodeGenerationPolicy::Protected: + scopeStr = rdoc->scopeToRubyDecl((Uml::Visibility::Value) scopePolicy); + break; + default: + case CodeGenerationPolicy::FromParent: + // do nothing here... will leave as from parent object + break; + } + } + + QString typeName = rcf->getTypeName(); + QString fieldName = rcf->getFieldName(); + QString initialV = rcf->getInitialValue(); + + if (!cf->parentIsAttribute() && !cf->fieldIsSingleValue()) + typeName = "Array"; + + QString body = staticValue+scopeStr+' '+typeName+' '+fieldName; + if (!initialV.isEmpty()) + body.append(" = " + initialV); + else if (!cf->parentIsAttribute()) + { + UMLRole * role = dynamic_cast<UMLRole*>(cf->getParentObject()); + if (role->getObject()->getBaseType() == Uml::ot_Interface) + { + // do nothing.. can't instanciate an interface + } else { + + // FIX?: IF a constructor method exists in the classifiercodedoc + // of the parent Object, then we can use that instead (if its empty). + if(cf->fieldIsSingleValue()) + { + if(!typeName.isEmpty()) + body.append(" = " + typeName + ".new()"); + } else + body.append(" = []"); + } + } + + setText(body); + +} + +#include "rubycodeclassfielddeclarationblock.moc" diff --git a/umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.h b/umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.h new file mode 100644 index 00000000..c3e18a68 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodeclassfielddeclarationblock.h @@ -0,0 +1,55 @@ +/*************************************************************************** + rubycodeclassfielddeclarationblock.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef RUBYCODECLASSFIELDDECLARATIONBLOCK_H +#define RUBYCODECLASSFIELDDECLARATIONBLOCK_H + +#include <qstring.h> + +#include "../codeclassfielddeclarationblock.h" + +class RubyCodeClassFieldDeclarationBlock : public CodeClassFieldDeclarationBlock +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Constructor + */ + RubyCodeClassFieldDeclarationBlock ( CodeClassField * parent ); + + /** + * Empty Destructor + */ + virtual ~RubyCodeClassFieldDeclarationBlock ( ); + +protected: + + // this will be called by syncToParent whenever the parent object is "modified" + void updateContent ( ); + +private: + + +}; + +#endif // RUBYCODECLASSFIELDDECLARATIONBLOCK_H diff --git a/umbrello/umbrello/codegenerators/rubycodecomment.cpp b/umbrello/umbrello/codegenerators/rubycodecomment.cpp new file mode 100644 index 00000000..46374128 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodecomment.cpp @@ -0,0 +1,85 @@ +/*************************************************************************** + rubycodecomment.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#include "rubycodecomment.h" +#include <qregexp.h> + +// Constructors/Destructors +// + +RubyCodeComment::RubyCodeComment(CodeDocument * doc, const QString & text) + : CodeComment(doc, text) +{ + +} + +RubyCodeComment::~RubyCodeComment( ) { } + +// +// Methods +// + + +// Accessor methods +// + + +// Public attribute accessor methods +// + +// Other methods +// + +QString RubyCodeComment::getNewEditorLine( int amount ) { + QString line = getIndentationString(amount) + "# "; + return line; +} + +/** UnFormat a long text string. Typically, this means removing + * the indentaion (linePrefix) and/or newline chars from each line. + */ +QString RubyCodeComment::unformatText(const QString & text, const QString & indent) +{ + // remove leading or trailing comment stuff + QString mytext = TextBlock::unformatText(text, indent); + + // now leading hash + mytext.remove(QRegExp("^#\\s*")); + return mytext; +} + +/** + * @return QString + */ +QString RubyCodeComment::toString( ) +{ + QString output = ""; + + // simple output method + if (getWriteOutText()) { + QString indent = getIndentationString(); + QString endLine = getNewLineEndingChars(); + output.append(formatMultiLineText(getText(), indent + "# ", endLine + endLine)); + } + + return output; +} + + +#include "rubycodecomment.moc" diff --git a/umbrello/umbrello/codegenerators/rubycodecomment.h b/umbrello/umbrello/codegenerators/rubycodecomment.h new file mode 100644 index 00000000..35fb87a8 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodecomment.h @@ -0,0 +1,69 @@ +/*************************************************************************** + rubycodecomment.h + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef RUBYCODECOMMENT_H +#define RUBYCODECOMMENT_H + +#include <qstring.h> +#include "../codecomment.h" + +/** + * class RubyCodeComment + * A Ruby code comment. There are two styles of comments: + * these are simply started with a hash and no terminating + * characters, or delimited by '=begin' and '=end' tags at the + * start of lines + */ + +class RubyCodeComment : virtual public CodeComment +{ + Q_OBJECT +public: + /** + * Constructors + */ + explicit RubyCodeComment ( CodeDocument * doc, const QString & text = ""); + + /** + * Empty Destructor + */ + virtual ~RubyCodeComment ( ); + + /** + * @return QString + */ + QString toString ( ); + + /** UnFormat a long text string. Typically, this means removing + * the indentaion (linePrefix) and/or newline chars from each line. + */ + virtual QString unformatText ( const QString & text, const QString & indent = "" ); + + /** a special version here because we want to not only indent + * the new line, but to add the "#" as well. + */ + virtual QString getNewEditorLine ( int amount ); + +protected: + +private: + +}; + +#endif // RUBYCODECOMMENT_H diff --git a/umbrello/umbrello/codegenerators/rubycodedocumentation.cpp b/umbrello/umbrello/codegenerators/rubycodedocumentation.cpp new file mode 100644 index 00000000..6c69530a --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodedocumentation.cpp @@ -0,0 +1,145 @@ +/*************************************************************************** + rubycodedocumentation.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// own header +#include "rubycodedocumentation.h" + +// qt/kde includes +#include <qregexp.h> +#include <kdebug.h> + +// local includes +#include "rubyclassifiercodedocument.h" +#include "rubycodegenerationpolicy.h" +#include "../uml.h" + +// Constructors/Destructors +// + +RubyCodeDocumentation::RubyCodeDocumentation ( RubyClassifierCodeDocument * doc, const QString & text ) + : CodeComment ((CodeDocument*) doc, text) +{ + +} + +RubyCodeDocumentation::~RubyCodeDocumentation ( ) { } + +// +// Methods +// + + +// Accessor methods +// + +// Other methods +// + +/** + * Save the XMI representation of this object + */ +void RubyCodeDocumentation::saveToXMI ( QDomDocument & doc, QDomElement & root ) { + QDomElement blockElement = doc.createElement( "rubycodedocumentation" ); + setAttributesOnNode(doc, blockElement); // as we added no additional fields to this class we may + // just use parent TextBlock method + root.appendChild( blockElement ); +} + +/** + * @return QString + */ +QString RubyCodeDocumentation::toString ( ) +{ + + QString output = ""; + + // simple output method + if(getWriteOutText()) + { + bool useHashOutput = true; + + // need to figure out output type from ruby policy + CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy(); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + useHashOutput = false; + + QString indent = getIndentationString(); + QString endLine = getNewLineEndingChars(); + QString body = getText(); + if( useHashOutput) + { + if(!body.isEmpty()) + output.append(formatMultiLineText (body, indent +"# ", endLine)); + } else { + output.append("=begin rdoc"+endLine); + output.append(formatMultiLineText (body, indent +' ', endLine)); + output.append("=end"+endLine); + } + } + + return output; +} + +QString RubyCodeDocumentation::getNewEditorLine ( int amount ) +{ + CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy(); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + return getIndentationString(amount) + ' '; + else + return getIndentationString(amount) + "# "; +} + +int RubyCodeDocumentation::firstEditableLine() { + CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy(); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + return 1; + return 0; +} + +int RubyCodeDocumentation::lastEditableLine() { + CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy(); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + { + return -1; // very last line is NOT editable + } + return 0; +} + +/** UnFormat a long text string. Typically, this means removing + * the indentaion (linePrefix) and/or newline chars from each line. + */ +QString RubyCodeDocumentation::unformatText ( const QString & text , const QString & indent) +{ + + QString mytext = TextBlock::unformatText(text, indent); + CodeGenerationPolicy *p = UMLApp::app()->getCommonPolicy(); + // remove leading or trailing comment stuff + mytext.remove(QRegExp('^'+indent)); + if(p->getCommentStyle() == CodeGenerationPolicy::MultiLine) + { + mytext.remove(QRegExp("^=begin\\s*(rdoc)?\\s*\n?")); + mytext.remove(QRegExp("^=end\\s*\n?$")); + } else + mytext.remove(QRegExp("^#\\s*")); + + return mytext; +} + + +#include "rubycodedocumentation.moc" diff --git a/umbrello/umbrello/codegenerators/rubycodedocumentation.h b/umbrello/umbrello/codegenerators/rubycodedocumentation.h new file mode 100644 index 00000000..72908f78 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodedocumentation.h @@ -0,0 +1,97 @@ +/*************************************************************************** + rubycodedocumentation.h + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef RUBYCODEDOCUMENTATION_H +#define RUBYCODEDOCUMENTATION_H + +#include <qstring.h> +#include "../codecomment.h" + +class RubyClassifierCodeDocument; + +/** + * class RubyCodeDocumentation + * A Ruby code comment. There is only a single styles of comments: + * these are simply started with a hash and no terminating + * characters + */ + +class RubyCodeDocumentation : virtual public CodeComment +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + + /** + * Constructors + */ + explicit RubyCodeDocumentation ( RubyClassifierCodeDocument * doc, const QString & text = ""); + + /** + * Empty Destructor + */ + virtual ~RubyCodeDocumentation ( ); + + // Public attributes + // + + // Other + // + + /** + * Save the XMI representation of this object + */ + virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ); + + /** + * @return QString + */ + QString toString ( ); + + /** UnFormat a long text string. Typically, this means removing + * the indentaion (linePrefix) and/or newline chars from each line. + */ + virtual QString unformatText ( const QString & text, const QString & indent = "" ); + + /** a special version here because we want to not only indent + * the new line, but to add the "# " sequence as well. + */ + virtual QString getNewEditorLine ( int amount ); + + /** Ush. These are terrifically bad and must one day go away. + * Both methods indicate the range of lines in this textblock + * which may be edited by the codeeditor (assuming that any are + * actually editable). The default case is no lines are editable. + * The line numbering starts with '0' and a '-1' means no line + * qualifies. + */ + virtual int firstEditableLine(); + virtual int lastEditableLine(); + + +protected: + +private: + +}; + +#endif // RUBYCODEDOCUMENTATION_H diff --git a/umbrello/umbrello/codegenerators/rubycodegenerationformbase.ui b/umbrello/umbrello/codegenerators/rubycodegenerationformbase.ui new file mode 100644 index 00000000..14bcf0f2 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodegenerationformbase.ui @@ -0,0 +1,248 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>RubyCodeGenerationFormBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>Form1</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>462</width> + <height>376</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="2" column="0"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Auto-Generate Methods</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>m_generateConstructors</cstring> + </property> + <property name="text"> + <string>Empty constructor methods</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>m_generateAssocAccessors</cstring> + </property> + <property name="text"> + <string>Association accessor methods</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>m_generateAttribAccessors</cstring> + </property> + <property name="text"> + <string>Attribute accessor methods</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QComboBox" row="0" column="1"> + <item> + <property name="text"> + <string>Public</string> + </property> + </item> + <item> + <property name="text"> + <string>Private</string> + </property> + </item> + <item> + <property name="text"> + <string>Protected</string> + </property> + </item> + <item> + <property name="text"> + <string>From Parent Object</string> + </property> + </item> + <property name="name"> + <cstring>m_accessorScopeCB</cstring> + </property> + <property name="currentItem"> + <number>3</number> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string>Default attribute accessor scope:</string> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget" row="2" column="0"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1_3_2</cstring> + </property> + <property name="text"> + <string>Default association field scope:</string> + </property> + </widget> + <widget class="QComboBox" row="0" column="1"> + <item> + <property name="text"> + <string>Public</string> + </property> + </item> + <item> + <property name="text"> + <string>Private</string> + </property> + </item> + <item> + <property name="text"> + <string>Protected</string> + </property> + </item> + <item> + <property name="text"> + <string>From Parent Role</string> + </property> + </item> + <property name="name"> + <cstring>m_assocFieldScopeCB</cstring> + </property> + <property name="currentItem"> + <number>3</number> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Documentation</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Style:</string> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Hash (#)</string> + </property> + </item> + <item> + <property name="text"> + <string>Begin-End (=begin =end)</string> + </property> + </item> + <property name="name"> + <cstring>m_SelectCommentStyle</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><p align="center">Ruby Code Generation</p></string> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/umbrello/umbrello/codegenerators/rubycodegenerationpolicy.cpp b/umbrello/umbrello/codegenerators/rubycodegenerationpolicy.cpp new file mode 100644 index 00000000..1a01421a --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodegenerationpolicy.cpp @@ -0,0 +1,170 @@ +/*************************************************************************** + rubycodegenerationpolicy.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// own header +#include "rubycodegenerationpolicy.h" +// qt/kde includes +#include <kconfig.h> +// app includes +#include "rubycodegenerationpolicypage.h" +#include "rubycodegenerator.h" +#include "../uml.h" + +const bool RubyCodeGenerationPolicy::DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS = true; +const bool RubyCodeGenerationPolicy::DEFAULT_AUTO_GEN_ASSOC_ACCESSORS = true; + +// Constructors/Destructors +// + +RubyCodeGenerationPolicy::RubyCodeGenerationPolicy(KConfig *config) +{ + init(); + setDefaults(config,false); +} + +RubyCodeGenerationPolicy::~RubyCodeGenerationPolicy ( ) { } + +// +// Methods +// + +// Accessor methods +// + +// Public attribute accessor methods +// + +/** + * Set the value of m_autoGenerateAttribAccessors + * @param new_var the new value + */ +void RubyCodeGenerationPolicy::setAutoGenerateAttribAccessors( bool var ) { + m_autoGenerateAttribAccessors = var; + m_commonPolicy->emitModifiedCodeContentSig(); +} + +/** + * Set the value of m_autoGenerateAssocAccessors + * @param new_var the new value + */ +void RubyCodeGenerationPolicy::setAutoGenerateAssocAccessors( bool var ) { + m_autoGenerateAssocAccessors = var; + m_commonPolicy->emitModifiedCodeContentSig(); +} + +/** + * Get the value of m_autoGenerateAttribAccessors + * @return the value of m_autoGenerateAttribAccessors + */ +bool RubyCodeGenerationPolicy::getAutoGenerateAttribAccessors( ){ + return m_autoGenerateAttribAccessors; +} + +/** + * Get the value of m_autoGenerateAssocAccessors + * @return the value of m_autoGenerateAssocAccessors + */ +bool RubyCodeGenerationPolicy::getAutoGenerateAssocAccessors( ){ + return m_autoGenerateAssocAccessors; +} + +// Other methods +// + +void RubyCodeGenerationPolicy::writeConfig ( KConfig * config ) +{ + // @todo do we need to call CodeGenerationPolicy::writeConfig ??? + + // write ONLY the Ruby specific stuff + config->setGroup("Ruby Code Generation"); + + config->writeEntry("autoGenAccessors",getAutoGenerateAttribAccessors()); + config->writeEntry("autoGenAssocAccessors",getAutoGenerateAssocAccessors()); +} + +void RubyCodeGenerationPolicy::setDefaults ( CodeGenPolicyExt * clone, bool emitUpdateSignal ) +{ + + RubyCodeGenerationPolicy * rclone; + if (!clone) + return; + + // NOW block signals for ruby param setting + blockSignals(true); // we need to do this because otherwise most of these + // settors below will each send the modifiedCodeContent() signal + // needlessly (we can just make one call at the end). + + + // now do ruby-specific stuff IF our clone is also a RubyCodeGenerationPolicy object + if((rclone = dynamic_cast<RubyCodeGenerationPolicy*>(clone))) + { + setAutoGenerateAttribAccessors(rclone->getAutoGenerateAttribAccessors()); + setAutoGenerateAssocAccessors(rclone->getAutoGenerateAssocAccessors()); + } + + blockSignals(false); // "as you were citizen" + + if(emitUpdateSignal) + m_commonPolicy->emitModifiedCodeContentSig(); + +} + +void RubyCodeGenerationPolicy::setDefaults( KConfig * config, bool emitUpdateSignal ) +{ + + if(!config) + return; + + // call the superclass to init default stuff + m_commonPolicy->setDefaults(config, false); + + // NOW block signals (because call to super-class method will leave value at "true") + blockSignals(true); // we need to do this because otherwise most of these + // settors below will each send the modifiedCodeContent() signal + // needlessly (we can just make one call at the end). + + // now do ruby specific stuff + config -> setGroup("Ruby Code Generation"); + + setAutoGenerateAttribAccessors(config->readBoolEntry("autoGenAccessors",DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS)); + setAutoGenerateAssocAccessors(config->readBoolEntry("autoGenAssocAccessors",DEFAULT_AUTO_GEN_ASSOC_ACCESSORS)); + + blockSignals(false); // "as you were citizen" + + if(emitUpdateSignal) + m_commonPolicy->emitModifiedCodeContentSig(); +} + + +/** + * Create a new dialog interface for this object. + * @return dialog object + */ +CodeGenerationPolicyPage * RubyCodeGenerationPolicy::createPage ( QWidget *parent, const char *name ) { + return new RubyCodeGenerationPolicyPage ( parent, name, this ); +} + +void RubyCodeGenerationPolicy::init() { + m_commonPolicy = UMLApp::app()->getCommonPolicy(); + m_autoGenerateAttribAccessors = DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS; + m_autoGenerateAssocAccessors = DEFAULT_AUTO_GEN_ASSOC_ACCESSORS; +} + + +#include "rubycodegenerationpolicy.moc" diff --git a/umbrello/umbrello/codegenerators/rubycodegenerationpolicy.h b/umbrello/umbrello/codegenerators/rubycodegenerationpolicy.h new file mode 100644 index 00000000..aa1a7146 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodegenerationpolicy.h @@ -0,0 +1,117 @@ +/*************************************************************************** + rubycodegenerationpolicy.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2005-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef RUBYCODEGENERATIONPOLICY_H +#define RUBYCODEGENERATIONPOLICY_H + +#include <qstring.h> +#include "codegenpolicyext.h" +#include "../codegenerationpolicy.h" + +class KConfig; +class CodeGenerationPolicyPage; + +class RubyCodeGenerationPolicy : public CodeGenPolicyExt +{ + Q_OBJECT +public: + + static const bool DEFAULT_AUTO_GEN_ATTRIB_ACCESSORS; + static const bool DEFAULT_AUTO_GEN_ASSOC_ACCESSORS; + + // Constructors/Destructors + // + + /** + * Constructors + */ + RubyCodeGenerationPolicy (KConfig * config = 0); + + /** + * Empty Destructor + */ + virtual ~RubyCodeGenerationPolicy ( ); + + // Public attributes + // + + + // Public attribute accessor methods + // + + /** + * Set the value of m_autoGenerateAttribAccessors + * @param var the new value + */ + void setAutoGenerateAttribAccessors ( bool var ); + + /** + * Get the value of m_autoGenerateAttribAccessors + * @return value the boolean value of m_autoGenerateAttribAccessors + */ + bool getAutoGenerateAttribAccessors( ); + + /** + * Set the value of m_autoGenerateAssocAccessors + * @param var the new value + */ + void setAutoGenerateAssocAccessors ( bool var ); + + /** + * Get the value of m_autoGenerateAssocAccessors + * @return value the boolean value of m_autoGenerateAssocAccessors + */ + bool getAutoGenerateAssocAccessors( ); + + /** + * set the defaults for this code generator from the passed generator. + */ + virtual void setDefaults (CodeGenPolicyExt * defaults, bool emitUpdateSignal = true); + + /** + * set the defaults from a config file for this code generator from the passed KConfig pointer. + */ + virtual void setDefaults(KConfig * config, bool emitUpdateSignal = true); + + /** + * write Default params to passed KConfig pointer. + */ + virtual void writeConfig (KConfig * config); + + /** + * Create a new dialog interface for this object. + * @return dialog object + */ + CodeGenerationPolicyPage * createPage ( QWidget *parent = 0, const char * name = 0); + +protected: + + /** + */ + void init ( ); + +private: + + CodeGenerationPolicy *m_commonPolicy; + bool m_autoGenerateAttribAccessors; + bool m_autoGenerateAssocAccessors; + +}; + +#endif // RUBYCODEGENERATIONPOLICY_H diff --git a/umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.cpp b/umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.cpp new file mode 100644 index 00000000..1e9080c9 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.cpp @@ -0,0 +1,75 @@ +/*************************************************************************** + rubycodegenerationpolicypage.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// own header +#include "rubycodegenerationpolicypage.h" +// qt/kde includes +#include <qlabel.h> +#include <qcombobox.h> +#include <qcheckbox.h> +#include <kdebug.h> +#include <klocale.h> +// app includes +#include "rubycodegenerationformbase.h" +#include "../codegenerationpolicy.h" +#include "../uml.h" + +RubyCodeGenerationPolicyPage::RubyCodeGenerationPolicyPage( QWidget *parent, const char *name, RubyCodeGenerationPolicy * policy ) + : CodeGenerationPolicyPage(parent, name, policy) +{ + CodeGenerationPolicy *common = UMLApp::app()->getCommonPolicy(); + form = new RubyCodeGenerationFormBase(this); + form->m_SelectCommentStyle->setCurrentItem((int)(common->getCommentStyle())); + form->m_generateConstructors->setChecked(common->getAutoGenerateConstructors()); + form->m_generateAttribAccessors->setChecked(policy->getAutoGenerateAttribAccessors()); + form->m_generateAssocAccessors->setChecked(policy->getAutoGenerateAssocAccessors()); + form->m_accessorScopeCB->setCurrentItem((common->getAttributeAccessorScope() - 200)); + form->m_assocFieldScopeCB->setCurrentItem((common->getAssociationFieldScope() - 200)); +} + +RubyCodeGenerationPolicyPage::~RubyCodeGenerationPolicyPage() +{ +} + +void RubyCodeGenerationPolicyPage::apply() +{ + CodeGenerationPolicy *common = UMLApp::app()->getCommonPolicy(); + + // now do our ruby-specific configs + RubyCodeGenerationPolicy * parent = (RubyCodeGenerationPolicy*) m_parentPolicy; + + // block signals so we don't cause too many update content calls to code documents + parent->blockSignals(true); + + common->setCommentStyle((CodeGenerationPolicy::CommentStyle) form->m_SelectCommentStyle->currentItem()); + common->setAttributeAccessorScope((CodeGenerationPolicy::ScopePolicy) (form->m_accessorScopeCB->currentItem()+200)); + common->setAssociationFieldScope((CodeGenerationPolicy::ScopePolicy) (form->m_assocFieldScopeCB->currentItem()+200)); + common->setAutoGenerateConstructors(form->m_generateConstructors->isChecked()); + parent->setAutoGenerateAttribAccessors(form->m_generateAttribAccessors->isChecked()); + parent->setAutoGenerateAssocAccessors(form->m_generateAssocAccessors->isChecked()); + + parent->blockSignals(false); + + // now send out modified code content signal + common->emitModifiedCodeContentSig(); + +} + + +#include "rubycodegenerationpolicypage.moc" diff --git a/umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.h b/umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.h new file mode 100644 index 00000000..6fc06aed --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodegenerationpolicypage.h @@ -0,0 +1,51 @@ +/*************************************************************************** + rubycodegenerationpolicypage.h + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2005-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef RUBYCODEGENERATIONPOLICYPAGE_H +#define RUBYCODEGENERATIONPOLICYPAGE_H + +#include "../dialogs/codegenerationpolicypage.h" +#include "rubycodegenerationformbase.h" + +#include "rubycodegenerationpolicy.h" + +/** + * @author Brian Thomas + */ + +class RubyCodeGenerationPolicyPage : public CodeGenerationPolicyPage { + Q_OBJECT +public: + + explicit RubyCodeGenerationPolicyPage (QWidget *parent=0, const char *name=0, RubyCodeGenerationPolicy * policy = 0); + + virtual ~RubyCodeGenerationPolicyPage(); + +protected: + + RubyCodeGenerationFormBase * form; + +public slots: + + void apply(); + +}; + +#endif + diff --git a/umbrello/umbrello/codegenerators/rubycodegenerator.cpp b/umbrello/umbrello/codegenerators/rubycodegenerator.cpp new file mode 100644 index 00000000..3e20ce50 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodegenerator.cpp @@ -0,0 +1,186 @@ +/*************************************************************************** + rubycodegenerator.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// own header +#include "rubycodegenerator.h" + +// qt/kde includes +#include <qregexp.h> +#include <kconfig.h> +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> + +// local includes +#include "rubycodecomment.h" +#include "codeviewerdialog.h" +#include "../uml.h" + +// Constructors/Destructors +// + +RubyCodeGenerator::RubyCodeGenerator (QDomElement & elem ) + : CodeGenerator(elem) +{ +} + +RubyCodeGenerator::RubyCodeGenerator () +{ +} + +RubyCodeGenerator::~RubyCodeGenerator ( ) { } + +// +// Methods +// + +// Accessor methods +// + +// return our language +Uml::Programming_Language RubyCodeGenerator::getLanguage() { + return Uml::pl_Ruby; +} + +// In the Java version, we make the ANT build file also available. +CodeViewerDialog * RubyCodeGenerator::getCodeViewerDialog ( QWidget* parent, CodeDocument *doc, + Settings::CodeViewerState state) +{ + CodeViewerDialog *dialog = new CodeViewerDialog(parent, doc, state); + return dialog; +} + + +RubyCodeGenerationPolicy * RubyCodeGenerator::getRubyPolicy() { + return dynamic_cast<RubyCodeGenerationPolicy*>(UMLApp::app()->getPolicyExt()); +} + +bool RubyCodeGenerator::getAutoGenerateAttribAccessors ( ) +{ + return getRubyPolicy()->getAutoGenerateAttribAccessors (); +} + +bool RubyCodeGenerator::getAutoGenerateAssocAccessors ( ) +{ + return getRubyPolicy()->getAutoGenerateAssocAccessors (); +} + +QString RubyCodeGenerator::getListFieldClassName () { + return QString("Array"); +} + +// Other methods +// + +QString RubyCodeGenerator::cppToRubyType(const QString &typeStr) { + QString type = cleanName(typeStr); + type.replace("const ", ""); + type.replace(QRegExp("[*&\\s]"), ""); + type.replace(QRegExp("[<>]"), "_"); + type.replace("QStringList", "Array"); + type.replace(QRegExp("^string$"),"String"); + type.replace("QString", "String"); + type.replace("bool", "true|false"); + type.replace(QRegExp("^(uint|int|ushort|short|ulong|long)$"), "Integer"); + type.replace(QRegExp("^(float|double)$"), "Float"); + type.replace(QRegExp("^Q(?=[A-Z])"), "Qt::"); + type.replace(QRegExp("^K(?!(DE|Parts|IO)"), "KDE::"); + + return type; +} + +QString RubyCodeGenerator::cppToRubyName(const QString &nameStr) { + QString name = cleanName(nameStr); + name.replace(QRegExp("^m_"), ""); + name.replace(QRegExp("^[pbn](?=[A-Z])"), ""); + name = name.mid(0, 1).lower() + name.mid(1); + return name; +} + +/** + * @return ClassifierCodeDocument + * @param classifier + */ +CodeDocument * RubyCodeGenerator::newClassifierCodeDocument ( UMLClassifier * c) +{ + RubyClassifierCodeDocument * doc = new RubyClassifierCodeDocument(c); + doc->initCodeClassFields(); + return doc; +} + +/* These initializations are done in CodeGenFactory::createObject() +void RubyCodeGenerator::initFields() { + UMLApp::app()->setPolicyExt ( new RubyCodeGenerationPolicy(UMLApp::app()->getConfig()) ); + // load Classifier documents from parent document + initFromParentDocument(); +} + */ + +const QStringList RubyCodeGenerator::reservedKeywords() const { + + static QStringList keywords; + + if (keywords.isEmpty()) { + keywords << "__FILE__" + << "__LINE__" + << "BEGIN" + << "END" + << "alias" + << "and" + << "begin" + << "break" + << "case" + << "class" + << "def" + << "defined?" + << "do" + << "else" + << "elsif" + << "end" + << "ensure" + << "false" + << "for" + << "if" + << "in" + << "module" + << "next" + << "nil" + << "not" + << "or" + << "redo" + << "rescue" + << "retry" + << "return" + << "self" + << "super" + << "then" + << "true" + << "undef" + << "unless" + << "until" + << "when" + << "while" + << "yield"; + } + + return keywords; +} + +#include "rubycodegenerator.moc" + diff --git a/umbrello/umbrello/codegenerators/rubycodegenerator.h b/umbrello/umbrello/codegenerators/rubycodegenerator.h new file mode 100644 index 00000000..9cc878f0 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodegenerator.h @@ -0,0 +1,129 @@ +/*************************************************************************** + rubycodegenerator.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef RUBYCODEGENERATOR_H +#define RUBYCODEGENERATOR_H + +#include <qstring.h> +#include "../codeviewerstate.h" +#include "../codegenerator.h" +#include "../codeblockwithcomments.h" +#include "../umldoc.h" + +#include "classifierinfo.h" +#include "rubyclassifiercodedocument.h" + +#include "rubycodegenerationpolicy.h" + +class CodeViewerDialog; + +class RubyCodeGenerator : public CodeGenerator +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Empty Constructor + */ + RubyCodeGenerator (); + RubyCodeGenerator (QDomElement & element); + + /** + * Empty Destructor + */ + virtual ~RubyCodeGenerator ( ); + + // Public attributes + // + + + // Public attribute accessor methods + // + + /** + * A utility method to get the rubyCodeGenerationPolicy()->getAutoGenerateAttribAccessors() value. + */ + bool getAutoGenerateAttribAccessors( ); + + /** + * A utility method to get the rubyCodeGenerationPolicy()->getAutoGenerateAssocAccessors() value. + */ + bool getAutoGenerateAssocAccessors( ); + + /** + * Get the list variable class name to use. For Ruby, we have set this to "Array". + */ + static QString getListFieldClassName(); + + /** Get the editing dialog for this code document + */ + virtual CodeViewerDialog * getCodeViewerDialog( QWidget* parent, CodeDocument * doc, + Settings::CodeViewerState state); + + // Other methods + // + + /** + * Utility function for getting the ruby code generation policy. + */ + RubyCodeGenerationPolicy * getRubyPolicy(); + + /** + * @return ClassifierCodeDocument + * @param classifier + */ + CodeDocument * newClassifierCodeDocument (UMLClassifier * classifier); + + // return "Ruby" + Uml::Programming_Language getLanguage(); + + /** + * Convert a C++ type such as 'int' or 'QWidget' to + * ruby types Integer and Qt::Widget + * + * @param cppType the C++ type to be converted + */ + static QString cppToRubyType(const QString &cppType); + + /** + * Convert C++ names such as 'm_foobar' or pFoobar to + * just 'foobar' for ruby + * + * @param cppName the C++ name to be converted + */ + static QString cppToRubyName(const QString &cppName); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +protected: + + /** create the codeblock that will represent the class declaration + * for this classifier + */ + CodeBlockWithComments * createClassDecl ( UMLClassifier *c, ClassifierInfo *info, RubyClassifierCodeDocument * doc); + +}; + +#endif // RUBYCODEGENERATOR_H diff --git a/umbrello/umbrello/codegenerators/rubycodeoperation.cpp b/umbrello/umbrello/codegenerators/rubycodeoperation.cpp new file mode 100644 index 00000000..6f16fb96 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodeoperation.cpp @@ -0,0 +1,226 @@ +/*************************************************************************** + rubycodeoperation.cpp + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +// own header +#include "rubycodeoperation.h" + +// qt/kde includes +#include <qregexp.h> + +// local includes +#include "rubyclassifiercodedocument.h" +#include "rubycodedocumentation.h" +#include "rubycodegenerator.h" +#include "../uml.h" + +// Constructors/Destructors +// + +RubyCodeOperation::RubyCodeOperation ( RubyClassifierCodeDocument * doc, UMLOperation *parent, const QString & body, const QString & comment ) + : CodeOperation (doc, parent, body, comment) +{ + // lets not go with the default comment and instead use + // full-blown ruby documentation object instead + setComment(new RubyCodeDocumentation(doc)); + + // these things never change.. + setOverallIndentationLevel(1); + + updateMethodDeclaration(); + updateContent(); + +} + +RubyCodeOperation::~RubyCodeOperation ( ) { } + +// Other methods +// + +// we basically want to update the doc and start text of this method +void RubyCodeOperation::updateMethodDeclaration() +{ + + CodeDocument * doc = getParentDocument(); + RubyClassifierCodeDocument * rubydoc = dynamic_cast<RubyClassifierCodeDocument*>(doc); + UMLClassifier *c = rubydoc->getParentClassifier(); + UMLOperation * o = getParentOperation(); + bool isInterface = rubydoc->getParentClassifier()->isInterface(); + QString endLine = getNewLineEndingChars(); + + // now, the starting text. + QString strVis = rubydoc->scopeToRubyDecl(o->getVisibility()); + // no return type for constructors + QString fixedReturn = RubyCodeGenerator::cppToRubyType(o->getTypeName()); + QString returnType = o->isConstructorOperation() ? QString("") : (fixedReturn + QString(" ")); + QString methodName = o->getName(); + + QString RubyClassName = rubydoc->getRubyClassName(c->getName()); + + // Skip destructors, and operator methods which + // can't be defined in ruby + if ( methodName.startsWith("~") + || QRegExp("operator\\s*(=|--|\\+\\+|!=)$").exactMatch(methodName) ) + { + getComment()->setText(""); + return; + } + + if (RubyClassName == methodName) { + methodName = "initialize"; + } + + methodName.replace(QRegExp("operator\\s*"), ""); + methodName = methodName.mid(0, 1).lower() + methodName.mid(1); + + QString paramStr = QString(""); + QStringList commentedParams; + + // assemble parameters + UMLAttributeList list = getParentOperation()->getParmList(); + int nrofParam = list.count(); + int paramNum = 0; + for(UMLAttribute* parm = list.first(); parm; parm = list.next()) + { + QString paramName = RubyCodeGenerator::cppToRubyName(parm->getName()); + paramStr += paramName; + if (! parm->getInitialValue().isEmpty()) { + paramStr += QString(" = ") + RubyCodeGenerator::cppToRubyType(parm->getInitialValue()); + } + paramNum++; + + if (paramNum != nrofParam ) + paramStr += ", "; + } + + QString startText; + if (isInterface) { + // Assume 'isInterface' means a module in Ruby, so + // generate module methods + startText = "def "+ RubyClassName + '.' + methodName + '(' + paramStr +')'; + } else { + startText = "def "+ methodName + '(' + paramStr +')'; + } + + startText += ""; + setEndMethodText("end"); + + setStartMethodText(startText); + + // Lastly, for text content generation, we fix the comment on the + // operation, IF the codeop is autogenerated & currently empty + QString comment = o->getDoc(); + + if (comment.isEmpty()) { + if (getContentType() == CodeBlock::AutoGenerated) { + UMLAttributeList parameters = o->getParmList(); + for(UMLAttributeListIt iterator(parameters); iterator.current(); ++iterator) { + comment += endLine + "* _" + iterator.current()->getName() + "_ "; + comment += (' ' + iterator.current()->getDoc().replace( QRegExp("[\\n\\r]+[\\t ]*"), + endLine + " " ) ); + } + // add a returns statement too + if(!returnType.isEmpty() && !QRegExp("^void\\s*$").exactMatch(returnType)) + comment += endLine + "* _returns_ " + returnType + ' '; + getComment()->setText(comment); + } + } else { + comment.replace(QRegExp("[\\n\\r]+ *"), endLine); + comment.replace(QRegExp("[\\n\\r]+\\t*"), endLine); + + comment.replace(" m_", " "); + comment.replace(QRegExp("\\s[npb](?=[A-Z])"), " "); + QRegExp re_params("@param (\\w)(\\w*)"); + int pos = re_params.search(comment); + while (pos != -1) { + comment.replace( re_params.cap(0), + QString("@param _") + re_params.cap(1).lower() + re_params.cap(2) + '_' ); + commentedParams.append(re_params.cap(1).lower() + re_params.cap(2)); + + pos += re_params.matchedLength() + 3; + pos = re_params.search(comment, pos); + } + + UMLAttributeList parameters = o->getParmList(); + for (UMLAttributeListIt iterator(parameters); iterator.current(); ++iterator) { + // Only write an individual @param entry if one hasn't been found already + // in the main doc comment + if (commentedParams.contains(RubyCodeGenerator::cppToRubyName(iterator.current()->getName())) == 0) { + comment += (endLine + "@param _" + RubyCodeGenerator::cppToRubyName(iterator.current()->getName()) + '_'); + if (iterator.current()->getDoc().isEmpty()) { + comment += (' ' + RubyCodeGenerator::cppToRubyType(iterator.current()->getTypeName())); + } else { + comment += (' ' + iterator.current()->getDoc().replace(QRegExp("[\\n\\r]+[\\t ]*"), endLine + " ")); + } + } + } + + comment.replace("@ref ", ""); + comment.replace("@param", "*"); + comment.replace("@return", "* _returns_"); + + // All lines after the first one starting with '*' in the doc comment + // must be indented correctly. If they aren't a list + // item starting with '*', then indent the text with + // two spaces, ' ', to line up with the list item. + pos = comment.find(endLine + '*'); + if (pos != -1) { + pos += endLine.length() + 1; + pos = comment.find(endLine, pos); + } + + while (pos > 0) { + pos += endLine.length(); + if (comment[pos] != '*') { + comment.insert(pos, " "); + pos += 2; + } + + pos = comment.find(endLine, pos); + } + + QString typeStr = RubyCodeGenerator::cppToRubyType(o->getTypeName()); + if ( !typeStr.isEmpty() + && !QRegExp("^void\\s*$").exactMatch(typeStr) + && comment.contains("_returns_") == 0 ) + { + comment += endLine + "* _returns_ " + typeStr; + } + + getComment()->setText(comment); + } + + // In Java, for interfaces..we DONT write out non-public + // method declarations. And for Ruby modules? + if (isInterface) { + UMLOperation * o = getParentOperation(); + if(o->getVisibility() != Uml::Visibility::Public) + setWriteOutText(false); + } + +} + +int RubyCodeOperation::lastEditableLine() { + ClassifierCodeDocument * doc = dynamic_cast<ClassifierCodeDocument*>(getParentDocument()); + if(doc->parentIsInterface()) + return -1; // very last line is NOT editable as its a one-line declaration w/ no body in + // an interface. + return 0; +} + +#include "rubycodeoperation.moc" diff --git a/umbrello/umbrello/codegenerators/rubycodeoperation.h b/umbrello/umbrello/codegenerators/rubycodeoperation.h new file mode 100644 index 00000000..c8e8cea4 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubycodeoperation.h @@ -0,0 +1,54 @@ +/*************************************************************************** + rubycodeoperation.h + Derived from the Java code generator by thomas + + begin : Thur Jul 21 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef RUBYCODEOPERATION_H +#define RUBYCODEOPERATION_H + +#include <qstring.h> +#include "../codeoperation.h" + +class RubyClassifierCodeDocument; + +class RubyCodeOperation : virtual public CodeOperation +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Empty Constructor + */ + RubyCodeOperation ( RubyClassifierCodeDocument * doc, UMLOperation * op, const QString & body = "", const QString & comment = ""); + + /** + * Empty Destructor + */ + virtual ~RubyCodeOperation ( ); + + virtual int lastEditableLine(); + +protected: + + void updateMethodDeclaration(); + +}; + +#endif // RUBYCODEOPERATION_H diff --git a/umbrello/umbrello/codegenerators/rubywriter.cpp b/umbrello/umbrello/codegenerators/rubywriter.cpp new file mode 100644 index 00000000..aa9a5271 --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubywriter.cpp @@ -0,0 +1,448 @@ +/*************************************************************************** + rubywriter.h - description + ------------------- + begin : Sat Dec 21 2002 + copyright : Vincent Decorges + email : vincent.decorges@eivd.ch + (C) 2003-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. * + * * + ***************************************************************************/ + +#include "rubywriter.h" + +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qregexp.h> + +#include "classifierinfo.h" +#include "../umldoc.h" +#include "../umlattributelist.h" +#include "../association.h" +#include "../attribute.h" +#include "../classifier.h" +#include "../operation.h" +#include "../umlnamespace.h" + +RubyWriter::RubyWriter() { +} + +RubyWriter::~RubyWriter() {} + +void RubyWriter::writeClass(UMLClassifier *c) { + if(!c) { + kDebug()<<"Cannot write class of NULL concept!" << endl; + return; + } + + QString classname = cleanName(c->getName()); + + UMLClassifierList superclasses = c->getSuperClasses(); + UMLAssociationList aggregations = c->getAggregations(); + UMLAssociationList compositions = c->getCompositions(); + + //find an appropriate name for our file + QString fileName = findFileName(c, ".rb"); + if (fileName.isEmpty()) { + emit codeGenerated(c, false); + return; + } + + QFile fileh; + if( !openFile(fileh, fileName) ) { + emit codeGenerated(c, false); + return; + } + QTextStream h(&fileh); + + // preparations + classifierInfo = new ClassifierInfo(c); + classifierInfo->fileName = fileName; + classifierInfo->className = cleanName(c->getName()); + + ////////////////////////////// + //Start generating the code!! + ///////////////////////////// + + + //try to find a heading file (license, coments, etc) + QString str; + + str = getHeadingFile(".rb"); + if(!str.isEmpty()) { + str.replace(QRegExp("%filename%"), fileName); + str.replace(QRegExp("%filepath%"), fileh.name()); + h<<str<<m_endl; + } + + if(forceDoc() || !c->getDoc().isEmpty()) { + QString docStr = c->getDoc(); + docStr.replace(QRegExp("\\n"), "\n# "); + docStr.replace("@ref ", ""); + docStr.replace("@see", "_See_"); + docStr.replace("@short", "_Summary_"); + docStr.replace("@author", "_Author_"); + h<<"#"<<m_endl; + h<<"# "<<docStr<<m_endl; + h<<"#"<<m_endl<<m_endl; + } + + // write inheritances out + UMLClassifier *concept; + + h<< "class " << cppToRubyType(classname) << (superclasses.count() > 0 ? " < ":""); + + int i = 0; + for (concept = superclasses.first(); concept; concept = superclasses.next()) { + if (i == 0) { + h << cppToRubyType(concept->getName()) << m_endl; + } else { + // Assume ruby modules that can be mixed in, after the first + // superclass name in the list + h << m_indentation << "include "<< cppToRubyType(concept->getName()) << m_endl; + } + i++; + } + + h << m_endl; + + // write comment for sub-section IF needed + if (forceDoc() || classifierInfo->hasAccessorMethods) { + h << m_indentation << "#" << m_endl; + h << m_indentation << "# Accessor Methods" << m_endl; + h << m_indentation << "#" << m_endl << m_endl; + + // Accessor methods for attributes + writeAttributeMethods(&(classifierInfo->atpub), Uml::Visibility::Public, h); + writeAttributeMethods(&(classifierInfo->atprot), Uml::Visibility::Protected, h); + writeAttributeMethods(&(classifierInfo->atpriv), Uml::Visibility::Private, h); + h << m_endl; + } + + //operations + writeOperations(c, h); + + //finish files + h << "end" << m_endl << m_endl; + + //close files and notfiy we are done + fileh.close(); + emit codeGenerated(c, true); +} + + +//////////////////////////////////////////////////////////////////////////////////// +// Helper Methods + +QString RubyWriter::cppToRubyType(const QString &typeStr) { + QString type = cleanName(typeStr); + type.replace("const ", ""); + type.replace(QRegExp("[*&\\s]"), ""); + type.replace(QRegExp("[<>]"), "_"); + type.replace("QStringList", "Array"); + type.replace("QString", "String"); + type.replace("bool", "true|false"); + type.replace(QRegExp("^(uint|int|ushort|short|ulong|long)$"), "Integer"); + type.replace(QRegExp("^(float|double)$"), "Float"); + type.replace(QRegExp("^Q(?=[A-Z])"), "Qt::"); + type.replace(QRegExp("^K(?!(DE|Parts|IO)"), "KDE::"); + + return type; +} + +QString RubyWriter::cppToRubyName(const QString &nameStr) { + QString name = cleanName(nameStr); + name.replace(QRegExp("^m_"), ""); + name.replace(QRegExp("^[pbn](?=[A-Z])"), ""); + name = name.mid(0, 1).lower() + name.mid(1); + return name; +} + +void RubyWriter::writeOperations(UMLClassifier *c,QTextStream &h) { + + //Lists to store operations sorted by scope + 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 + UMLOperationList opl(c->getOpList()); + 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; + } + } + + QString classname(cleanName(c->getName())); + + //write operations to file + if(forceSections() || !oppub.isEmpty()) { + writeOperations(classname, oppub, Uml::Visibility::Public, h); + } + + if(forceSections() || !opprot.isEmpty()) { + writeOperations(classname, opprot, Uml::Visibility::Protected, h); + } + + if(forceSections() || !oppriv.isEmpty()) { + writeOperations(classname, oppriv, Uml::Visibility::Private, h); + } + +} + +void RubyWriter::writeOperations(const QString &classname, UMLOperationList &opList, + Uml::Visibility permitScope, QTextStream &h) +{ + UMLOperation *op; + UMLAttribute *at; + + switch (permitScope) { + case Uml::Visibility::Public: + h << m_indentation << "public" << m_endl << m_endl; + break; + case Uml::Visibility::Protected: + h << m_indentation << "protected" << m_endl << m_endl; + break; + case Uml::Visibility::Private: + h << m_indentation << "private" << m_endl << m_endl; + break; + default: + break; + } + + for (op=opList.first(); op ; op=opList.next()) { + QString methodName = cleanName(op->getName()); + QStringList commentedParams; + + // Skip destructors, and operator methods which + // can't be defined in ruby + if ( methodName.startsWith("~") + || methodName == "operator =" + || methodName == "operator --" + || methodName == "operator ++" + || methodName == "operator !=" ) + { + continue; + } + + if (methodName == classname) { + methodName = "initialize"; + } + + methodName.replace("operator ", ""); + methodName = methodName.mid(0, 1).lower() + methodName.mid(1); + + UMLAttributeList atl = op->getParmList(); + //write method doc if we have doc || if at least one of the params has doc + bool writeDoc = forceDoc() || !op->getDoc().isEmpty(); + // Always write out the docs for ruby as the type of the + // arguments and return value of the methods is useful + writeDoc = true; +// for (at = atl.first(); at; at = atl.next()) +// writeDoc |= !at->getDoc().isEmpty(); + + if (writeDoc) { + h << m_indentation << "#" << m_endl; + QString docStr = op->getDoc(); + + docStr.replace(QRegExp("[\\n\\r]+ *"), m_endl); + docStr.replace(QRegExp("[\\n\\r]+\\t*"), m_endl); + + docStr.replace(" m_", " "); + docStr.replace(QRegExp("\\s[npb](?=[A-Z])"), " "); + QRegExp re_params("@param (\\w)(\\w*)"); + int pos = re_params.search(docStr); + while (pos != -1) { + docStr.replace( re_params.cap(0), + QString("@param _") + re_params.cap(1).lower() + re_params.cap(2) + '_' ); + commentedParams.append(re_params.cap(1).lower() + re_params.cap(2)); + + pos += re_params.matchedLength() + 3; + pos = re_params.search(docStr, pos); + } + + docStr.replace("\n", QString("\n") + m_indentation + "# "); + + // Write parameter documentation + for (at = atl.first(); at ; at = atl.next()) { + // Only write an individual @param entry if one hasn't been found already + // in the main doc comment + if (commentedParams.contains(cppToRubyName(at->getName())) == 0) { + docStr += (m_endl + m_indentation + "# @param _" + cppToRubyName(at->getName()) + '_'); + if (at->getDoc().isEmpty()) { + docStr += (' ' + cppToRubyType(at->getTypeName())); + } else { + docStr += (' ' + at->getDoc().replace(QRegExp("[\\n\\r]+[\\t ]*"), m_endl + " ")); + } + } + } + + docStr.replace("@ref ", ""); + docStr.replace("@param", "*"); + docStr.replace("@return", "* _returns_"); + + // All lines after the first '# *' in the doc comment + // must be indented correctly. If they aren't a list + // item starting with '# *', then indent the text with + // three spaces, '# ', to line up with the list item. + pos = docStr.find("# *"); + QRegExp re_linestart("# (?!\\*)"); + pos = re_linestart.search(docStr, pos); + while (pos > 0) { + docStr.insert(pos + 1, " "); + + pos += re_linestart.matchedLength() + 2; + pos = re_linestart.search(docStr, pos); + } + + h << m_indentation << "# "<< docStr << m_endl; + + QString typeStr = cppToRubyType(op->getTypeName()); + if (!typeStr.isEmpty() && typeStr != "void" && docStr.contains("_returns_") == 0) { + h << m_indentation << "# * _returns_ " << typeStr << m_endl; + } + } + + h<< m_indentation << "def " + methodName << "("; + + int j=0; + for (at = atl.first(); at; at = atl.next(), j++) { + QString nameStr = cppToRubyName(at->getName()); + if (j > 0) { + h << ", " << nameStr; + } else { + h << nameStr; + } + h << (!(at->getInitialValue().isEmpty()) ? + (QString(" = ") + cppToRubyType(at->getInitialValue())) : + QString("")); + } + + h <<")" << m_endl; + + h << m_indentation << m_indentation << m_endl; + + h << m_indentation << "end" << m_endl << m_endl; + + }//end for + +} + +// this is for writing file attribute methods +// +void RubyWriter::writeAttributeMethods(UMLAttributeList *attribs, + Uml::Visibility visibility, QTextStream &stream) +{ + // return now if NO attributes to work on + if (attribs->count() == 0 || visibility == Uml::Visibility::Private) + return; + + UMLAttribute *at; + for(at=attribs->first(); at; at=attribs->next()) + { + QString varName = cppToRubyName(cleanName(at->getName())); + + writeSingleAttributeAccessorMethods(varName, at->getDoc(), stream); + } + +} + +void RubyWriter::writeSingleAttributeAccessorMethods( + const QString &fieldName, + const QString &descr, + QTextStream &h) +{ + QString description = descr; + description.replace(QRegExp("m_[npb](?=[A-Z])"), ""); + description.replace("m_", ""); + description.replace("\n", QString("\n") + m_indentation + "# "); + + if (!description.isEmpty()) { + h << m_indentation << "# " << description << m_endl; + } + + h << m_indentation << "attr_accessor :" << fieldName << m_endl << m_endl; + + return; +} + +/** + * returns "Ruby" + */ +Uml::Programming_Language RubyWriter::getLanguage() { + return Uml::pl_Ruby; +} + +const QStringList RubyWriter::reservedKeywords() const { + + static QStringList keywords; + + if (keywords.isEmpty()) { + keywords << "__FILE__" + << "__LINE__" + << "BEGIN" + << "END" + << "alias" + << "and" + << "begin" + << "break" + << "case" + << "class" + << "def" + << "defined?" + << "do" + << "else" + << "elsif" + << "end" + << "ensure" + << "false" + << "for" + << "if" + << "in" + << "module" + << "next" + << "nil" + << "not" + << "or" + << "redo" + << "rescue" + << "retry" + << "return" + << "self" + << "super" + << "then" + << "true" + << "undef" + << "unless" + << "until" + << "when" + << "while" + << "yield"; + } + + return keywords; +} + +#include "rubywriter.moc" diff --git a/umbrello/umbrello/codegenerators/rubywriter.h b/umbrello/umbrello/codegenerators/rubywriter.h new file mode 100644 index 00000000..8f1547ad --- /dev/null +++ b/umbrello/umbrello/codegenerators/rubywriter.h @@ -0,0 +1,113 @@ +/*************************************************************************** + rubywriter.h - description + ------------------- + begin : Mon Jul 18 2005 + author : Richard Dale + ***************************************************************************/ + +/*************************************************************************** + * * + * 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) 2006-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef RUBYWRITER_H +#define RUBYWRITER_H + +#include "simplecodegenerator.h" +#include "../umloperationlist.h" +#include "../umlattributelist.h" + +#include <qstringlist.h> + +class ClassifierInfo; + +/** + * class RubyWriter is a ruby code generator for UMLClassifier objects + * Just call writeClass and feed it a UMLClassifier; + */ +class RubyWriter : public SimpleCodeGenerator { + Q_OBJECT +public: + + RubyWriter(); + virtual ~RubyWriter(); + + /** + * call this method to generate C++ code for a UMLClassifier + * @param c the class you want to generate code for. + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "Ruby" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +private: + /** + * Convert a C++ type such as 'int' or 'QWidget' to + * ruby types Integer and Qt::Widget + * + * @param cppType the C++ type to be converted + */ + QString cppToRubyType(const QString &cppType); + + /** + * Convert C++ names such as 'm_foobar' or pFoobar to + * just 'foobar' for ruby + * + * @param cppName the C++ name to be converted + */ + QString cppToRubyName(const QString &cppName); + + /** + * calls @ref writeSingleAttributeAccessorMethods() on each of the attributes in attribs list. + */ + void writeAttributeMethods(UMLAttributeList *attribs, + Uml::Visibility visibility, QTextStream &stream); + + + /** + * write all method declarations, for attributes and associations + * for the given permitted scope. + */ + void writeSingleAttributeAccessorMethods(const QString &fieldName, + const QString &description, + QTextStream &h); + + /** + * write all operations for a given class + * + * @param c the concept we are generating code for + * @param h output stream for the header file + */ + void writeOperations(UMLClassifier *c, QTextStream &h); + + /** + * write a list of class operations + * + * @param classname the name of the class + * @param opList the list of operations + * @param h output stream for the header file + */ + void writeOperations(const QString &classname, UMLOperationList &opList, + Uml::Visibility permitScope, QTextStream &h); + + /** + * Summary information about current classifier. + */ + ClassifierInfo * classifierInfo; +}; + +#endif //RUBYWRITER diff --git a/umbrello/umbrello/codegenerators/simplecodegenerator.cpp b/umbrello/umbrello/codegenerators/simplecodegenerator.cpp new file mode 100644 index 00000000..98477f15 --- /dev/null +++ b/umbrello/umbrello/codegenerators/simplecodegenerator.cpp @@ -0,0 +1,292 @@ +/*************************************************************************** + * * + * 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-2006 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Sep Mon 1 2003 + */ + +// own header +#include "simplecodegenerator.h" +// system includes +#include <cstdlib> //to get the user name +// qt includes +#include <qdatetime.h> +#include <qregexp.h> +#include <qdir.h> +// kde includes +#include <klocale.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <kdialog.h> +#include <kapplication.h> +// app includes +#include "../dialogs/overwritedialogue.h" +#include "../model_utils.h" +#include "../attribute.h" +#include "../umloperationlist.h" +#include "../umlattributelist.h" +#include "../classifier.h" +#include "../codedocument.h" +#include "../codegenerationpolicy.h" +#include "../operation.h" +#include "../umldoc.h" +#include "../uml.h" + +// Constructors/Destructors +// + +SimpleCodeGenerator::SimpleCodeGenerator (bool createDirHierarchyForPackages /* =true */) +{ + m_indentLevel = 0; + UMLDoc * parentDoc = UMLApp::app()->getDocument(); + parentDoc->disconnect(this); // disconnect from UMLDoc.. we arent planning to be synced at all + m_createDirHierarchyForPackages = createDirHierarchyForPackages; + initFields(parentDoc); +} + +SimpleCodeGenerator::~SimpleCodeGenerator ( ) { } + +// +// Methods +// + +// Accessor methods +// + + +// Other methods +// + +QString SimpleCodeGenerator::getIndent () +{ + QString myIndent; + for (int i = 0 ; i < m_indentLevel ; i++) + myIndent.append(m_indentation); + return myIndent; +} + +QString SimpleCodeGenerator::findFileName(UMLPackage* concept, const QString &ext) { + + //if we already know to which file this class was written/should be written, just return it. + if (m_fileMap.contains(concept)) + return m_fileMap[concept]; + + //else, determine the "natural" file name + QString name; + // Get the package name + QString package = concept->getPackage("."); + + // Replace all white spaces with blanks + package.simplifyWhiteSpace(); + + // Replace all blanks with underscore + package.replace(QRegExp(" "), "_"); + + // Convert all "::" to "/" : Platform-specific path separator + // package.replace(QRegExp("::"), "/"); + + // if package is given add this as a directory to the file name + if (!package.isEmpty() && m_createDirHierarchyForPackages) { + name = package + '.' + concept->getName(); + name.replace(QRegExp("\\."),"/"); + package.replace(QRegExp("\\."), "/"); + package = '/' + package; + } else { + name = concept->getFullyQualifiedName("-"); + } + + if (! UMLApp::app()->activeLanguageIsCaseSensitive()) { + package = package.lower(); + name = name.lower(); + } + + // if a package name exists check the existence of the package directory + if (!package.isEmpty() && m_createDirHierarchyForPackages) { + QDir pathDir(UMLApp::app()->getCommonPolicy()->getOutputDirectory().absPath() + package); + // does our complete output directory exist yet? if not, try to create it + if (!pathDir.exists()) + { + QStringList dirs = QStringList::split("/",pathDir.absPath()); + QString currentDir = ""; + + QStringList::iterator end(dirs.end()); + for (QStringList::iterator dir(dirs.begin()); dir != end; ++dir) + { + currentDir += '/' + *dir; + if (! (pathDir.exists(currentDir) + || pathDir.mkdir(currentDir) ) ) + { + KMessageBox::error(0, i18n("Cannot create the folder:\n") + + pathDir.absPath() + i18n("\nPlease check the access rights"), + i18n("Cannot Create Folder")); + return NULL; + } + } + } + } + + + name.simplifyWhiteSpace(); + name.replace(QRegExp(" "),"_"); + + QString extension = ext.simplifyWhiteSpace(); + extension.replace(' ', '_'); + + return overwritableName(concept, name, extension); +} + +QString SimpleCodeGenerator::overwritableName(UMLPackage* concept, const QString &name, const QString &ext) { + //check if a file named "name" with extension "ext" already exists + CodeGenerationPolicy *commonPolicy = UMLApp::app()->getCommonPolicy(); + QDir outputDir = commonPolicy->getOutputDirectory(); + QString filename = name + ext; + if(!outputDir.exists(filename)) { + m_fileMap.insert(concept,filename); + return filename; //if not, "name" is OK and we have not much to to + } + + int suffix; + OverwriteDialogue overwriteDialogue( filename, outputDir.absPath(), + m_applyToAllRemaining, kapp -> mainWidget() ); + switch(commonPolicy->getOverwritePolicy()) { //if it exists, check the OverwritePolicy we should use + case CodeGenerationPolicy::Ok: //ok to overwrite file + break; + case CodeGenerationPolicy::Ask: //ask if we can overwrite + switch(overwriteDialogue.exec()) { + case KDialogBase::Yes: //overwrite file + if ( overwriteDialogue.applyToAllRemaining() ) { + commonPolicy->setOverwritePolicy(CodeGenerationPolicy::Ok); + } else { + m_applyToAllRemaining = false; + } + break; + case KDialogBase::No: //generate similar name + suffix = 1; + while (1) { + filename = name + "__" + QString::number(suffix) + ext; + if (!outputDir.exists(filename)) + break; + suffix++; + } + if ( overwriteDialogue.applyToAllRemaining() ) { + commonPolicy->setOverwritePolicy(CodeGenerationPolicy::Never); + } else { + m_applyToAllRemaining = false; + } + break; + case KDialogBase::Cancel: //don't output anything + if ( overwriteDialogue.applyToAllRemaining() ) { + commonPolicy->setOverwritePolicy(CodeGenerationPolicy::Cancel); + } else { + m_applyToAllRemaining = false; + } + return NULL; + break; + } + + break; + case CodeGenerationPolicy::Never: //generate similar name + suffix = 1; + while (1) { + filename = name + "__" + QString::number(suffix) + ext; + if (!outputDir.exists(filename)) + break; + suffix++; + } + break; + case CodeGenerationPolicy::Cancel: //don't output anything + return NULL; + break; + } + + m_fileMap.insert(concept, filename); + return filename; +} + + +bool SimpleCodeGenerator::hasDefaultValueAttr(UMLClassifier *c) { + UMLAttributeList atl = c->getAttributeList(); + for(UMLAttribute *at = atl.first(); at; at = atl.next()) + if(!at->getInitialValue().isEmpty()) + return true; + return false; +} + +bool SimpleCodeGenerator::hasAbstractOps(UMLClassifier *c) { + UMLOperationList opl(c->getOpList()); + for(UMLOperation *op = opl.first(); op ; op = opl.next()) + if(op->getAbstract()) + return true; + return false; +} + +/** + * @return ClassifierCodeDocument + * @param classifier + * @param this This package generator object. + */ +CodeDocument * SimpleCodeGenerator::newClassifierCodeDocument(UMLClassifier* /*classifier*/) +{ + return (CodeDocument*)NULL; +} + +// write all concepts in project to file +void SimpleCodeGenerator::writeCodeToFile ( ) { + m_fileMap.clear(); // need to do this, else just keep getting same directory to write to. + UMLClassifierList concepts = m_doc->getClassesAndInterfaces(); + for (UMLClassifier *c = concepts.first(); c; c = concepts.next()) { + if (! Model_Utils::isCommonDataType(c->getName())) + this->writeClass(c); // call the writer for each class. + } +} + +// write only selected concepts to file +void SimpleCodeGenerator::writeCodeToFile ( UMLClassifierList & concepts) { + m_fileMap.clear(); // ?? + for (UMLClassifier *c = concepts.first(); c; c = concepts.next()) + this->writeClass(c); // call the writer for each class. +} + +void SimpleCodeGenerator::initFields ( UMLDoc * parentDoc ) { + + // load Classifier documents from parent document + // initFromParentDocument(); + + m_fileMap.clear(); + m_applyToAllRemaining = true; + m_doc = parentDoc; + + // this really is just being used to sync the internal params + // to the codegenpolicy as there are no code documents to really sync. + syncCodeToDocument(); +} + +// a little method to provide some compatability between +// the newer codegenpolicy object and the older class fields. +void SimpleCodeGenerator::syncCodeToDocument() { + + CodeGenerationPolicy *policy = UMLApp::app()->getCommonPolicy(); + + m_indentation = policy->getIndentation(); + m_endl = policy->getNewLineEndingChars(); + +} + + +// override parent method +void SimpleCodeGenerator::initFromParentDocument( ) +{ + // Do nothing +} + + +#include "simplecodegenerator.moc" diff --git a/umbrello/umbrello/codegenerators/simplecodegenerator.h b/umbrello/umbrello/codegenerators/simplecodegenerator.h new file mode 100644 index 00000000..d75a0660 --- /dev/null +++ b/umbrello/umbrello/codegenerators/simplecodegenerator.h @@ -0,0 +1,120 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Sep Mon 1 2003 + * + * copyright (C) 2004 + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> + */ + + +#ifndef SIMPLECODEGENERATOR_H +#define SIMPLECODEGENERATOR_H + +#include <qstringlist.h> +#include <qstring.h> +#include <qmap.h> + +#include "../codegenerator.h" +#include "../umlnamespace.h" + +class UMLDoc; + +/** + * A simple code generator interface designed to work with + * the existing codewriters. + */ +class SimpleCodeGenerator : public CodeGenerator +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Empty Constructor + */ + SimpleCodeGenerator (bool createDirHierarchyForPackages = true); + + /** + * Empty Destructor + */ + virtual ~SimpleCodeGenerator ( ); + + // Public attribute accessor methods + // + + void writeCodeToFile ( UMLClassifierList & concepts); + void writeCodeToFile ( ); + + /** + * call this method to generate code for a UMLClassifier + * @param c the class you want to generate code for. + */ + virtual void writeClass(UMLClassifier *c) = 0; + + /** + * This is implemented only because we HAVE to. + * @return ClassifierCodeDocument + * @param classifier + */ + CodeDocument * newClassifierCodeDocument (UMLClassifier * classifier); + +protected: + + // compatability methods.. + QString findFileName(UMLPackage* concept, const QString &ext); + QString overwritableName(UMLPackage* concept, const QString &name, const QString &ext); + bool hasDefaultValueAttr(UMLClassifier *c); + bool hasAbstractOps(UMLClassifier *c); + + /** + * Returns the current indent string based on m_indentLevel and m_indentation. + */ + QString getIndent (); + + /** + * Maps UMLObjects to filenames. Used for finding out which file + * each class was written to. + */ + QMap<UMLPackage*,QString> m_fileMap; + + // the parent document + UMLDoc *m_doc; + + /** + * For some code generators, it does not make much sense to create a + * directory for each package because that would lead to a rather + * sparsely populated directory tree (maximum of just one source file + * per directory.) + */ + bool m_createDirHierarchyForPackages; + + /* Old Attributes writers will look for */ + QString m_indentation; + int m_indentLevel; + QString m_endl; + + // override parent method..we need special handling + void initFromParentDocument( ); + +private: + + void initFields ( UMLDoc * doc) ; + +public slots: + + void syncCodeToDocument ( ); + +}; + +#endif // SIMPLECODEGENERATOR_H diff --git a/umbrello/umbrello/codegenerators/sqlwriter.cpp b/umbrello/umbrello/codegenerators/sqlwriter.cpp new file mode 100644 index 00000000..f01e8bbe --- /dev/null +++ b/umbrello/umbrello/codegenerators/sqlwriter.cpp @@ -0,0 +1,394 @@ +/*************************************************************************** + begin : 10.02.2003 + copyright : (C) 2003 Nikolaus Gradwohl + email : guru@local-guru.net + (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. * + * * + ***************************************************************************/ + +#include "sqlwriter.h" + +#include <kdebug.h> + +#include <klocale.h> +#include <kmessagebox.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qregexp.h> + +#include "../classifier.h" +#include "../operation.h" +#include "../umlnamespace.h" +#include "../association.h" +#include "../attribute.h" + +SQLWriter::SQLWriter() { +} + +SQLWriter::~SQLWriter() {} + +void SQLWriter::writeClass(UMLClassifier *c) { + + if(!c) { + kDebug()<<"Cannot write class of NULL concept!" << endl; + return; + } + + const bool isClass = !c->isInterface(); + QString classname = cleanName(c->getName()); + + //find an appropriate name for our file + QString fileName = findFileName(c, ".sql"); + if (fileName.isEmpty()) { + emit codeGenerated(c, false); + return; + } + + QFile file; + if( !openFile(file, fileName) ) { + emit codeGenerated(c, false); + return; + } + + //Start generating the code!! + + QTextStream sql(&file); + //try to find a heading file (license, coments, etc) + QString str; + str = getHeadingFile(".sql"); + if(!str.isEmpty()) { + str.replace(QRegExp("%filename%"),fileName); + str.replace(QRegExp("%filepath%"),file.name()); + sql<<str<<m_endl; + } + + //Write class Documentation if there is somthing or if force option + if(forceDoc() || !c->getDoc().isEmpty()) { + sql << m_endl << "--" << m_endl; + sql<<"-- TABLE: "<<classname<<m_endl; + sql<<formatDoc(c->getDoc(),"-- "); + sql << "-- " << m_endl << m_endl; + } + + sql << "CREATE TABLE "<< classname << " ( " << m_endl; + + if (isClass) + writeAttributes(c, sql); + + sql << m_endl << ");" << m_endl; + + QMap<UMLAssociation*,UMLAssociation*> constraintMap; // so we don't repeat constraint + UMLAssociationList aggregations = c->getAggregations(); + if( forceSections() || !aggregations.isEmpty() ) { + for(UMLAssociation* a = aggregations.first(); a; a = aggregations.next()) { + UMLObject *objA = a->getObject(Uml::A); + UMLObject *objB = a->getObject(Uml::B); + if (objA->getID() == c->getID() && objB->getID() != c->getID()) + continue; + constraintMap[a] = a; + } + } + + QMap<UMLAssociation*,UMLAssociation*>::Iterator itor = constraintMap.begin(); + for (;itor != constraintMap.end();itor++) { + UMLAssociation* a = itor.data(); + sql << "ALTER TABLE "<< classname + << " ADD CONSTRAINT " << a->getName() << " FOREIGN KEY (" + << a->getRoleName(Uml::B) << ") REFERENCES " + << a->getObject(Uml::A)->getName() + << " (" << a->getRoleName(Uml::A) << ");" << m_endl; + } + + + file.close(); + emit codeGenerated(c, true); +} + + +void SQLWriter::writeAttributes(UMLClassifier *c, QTextStream &sql) { + UMLAttributeList atpub, atprot, atpriv, atimp; + atpub.setAutoDelete(false); + atprot.setAutoDelete(false); + atpriv.setAutoDelete(false); + atimp.setAutoDelete(false); + + //sort attributes by scope and see if they have a default value + UMLAttributeList atl = c->getAttributeList(); + for(UMLAttribute* at=atl.first(); at ; at=atl.next()) { + switch(at->getVisibility()) { + case Uml::Visibility::Public: + atpub.append(at); + break; + case Uml::Visibility::Protected: + atprot.append(at); + break; + case Uml::Visibility::Private: + atpriv.append(at); + break; + case Uml::Visibility::Implementation: + atimp.append(at); + break; + } + } + + // now print the attributes; they are sorted by there scope + // in front of the first attribute shouldn't be a , -> so we need to find + // out, when the first attribute was added + bool first = true; + + if (atpub.count() > 0) + { + printAttributes(sql, atpub, first); + first = false; + } + + if (atprot.count() > 0) + { + printAttributes(sql, atprot, first); + first = false; + } + + if (atpriv.count() > 0) + { + printAttributes(sql, atpriv, first); + first = false; + } + + if (atimp.count() > 0) + { + printAttributes(sql, atimp, first); + first = false; + } + + return; +} + +void SQLWriter::printAttributes(QTextStream& sql, UMLAttributeList attributeList, bool first) { + QString attrDoc = ""; + UMLAttribute* at; + + for (at=attributeList.first();at;at=attributeList.next()) + { + // print , after attribute + if (first == false) { + sql <<","; + } else { + first = false; + } + + // print documentation/comment of last attribute at end of line + if (attrDoc.isEmpty() == false) + { + sql << " -- " << attrDoc << m_endl; + } else { + sql << m_endl; + } + + // write the attribute + sql << m_indentation << cleanName(at->getName()) << " " << at->getTypeName() << " " + << (at->getInitialValue().isEmpty()?QString(""):QString(" DEFAULT ")+at->getInitialValue()); + + // now get documentation/comment of current attribute + attrDoc = at->getDoc(); + } + + // print documentation/comment at end of line + if (attrDoc.isEmpty() == false) + { + sql << " -- " << attrDoc << m_endl; + } else { + sql << m_endl; + } + + return; +} + +Uml::Programming_Language SQLWriter::getLanguage() { + return Uml::pl_SQL; +} + +QStringList SQLWriter::defaultDatatypes() { + QStringList l; + l.append("varchar"); + l.append("tinyint"); + l.append("smallint"); + l.append("mediumint"); + l.append("bigint"); + l.append("float"); + l.append("double"); + l.append("decimal"); + l.append("date"); + l.append("datetime"); + l.append("time"); + l.append("timestamp"); + l.append("year"); + l.append("char"); + l.append("tinyblob"); + l.append("blob"); + l.append("mediumblob"); + l.append("longblob"); + l.append("tinytext"); + l.append("text"); + l.append("mediumtext"); + l.append("longtext"); + l.append("enum"); + l.append("set"); + return l; +} + +const QStringList SQLWriter::reservedKeywords() const { + + static QStringList keywords; + + if (keywords.isEmpty()) { + keywords << "access" + << "add" + << "all" + << "alter" + << "analyze" + << "and" + << "any" + << "as" + << "asc" + << "audit" + << "begin" + << "between" + << "boolean" + << "by" + << "char" + << "character" + << "check" + << "cluster" + << "column" + << "comment" + << "commit" + << "compress" + << "connect" + << "create" + << "current" + << "cursor" + << "date" + << "decimal" + << "default" + << "delete" + << "desc" + << "distinct" + << "drop" + << "else" + << "elsif" + << "end" + << "escape" + << "exception" + << "exclusive" + << "execute" + << "exists" + << "explain" + << "false" + << "file" + << "float" + << "for" + << "from" + << "function" + << "grant" + << "group" + << "having" + << "identified" + << "if" + << "immediate" + << "in" + << "increment" + << "index" + << "initial" + << "insert" + << "integer" + << "intersect" + << "into" + << "is" + << "level" + << "like" + << "lock" + << "long" + << "loop" + << "maxextents" + << "minus" + << "mlslabel" + << "mode" + << "modify" + << "noaudit" + << "nocompress" + << "not" + << "nowait" + << "null" + << "number" + << "of" + << "offline" + << "on" + << "online" + << "option" + << "or" + << "order" + << "out" + << "pctfree" + << "prior" + << "privileges" + << "procedure" + << "public" + << "raw" + << "rename" + << "resource" + << "return" + << "revoke" + << "rollback" + << "row" + << "rowid" + << "rowlabel" + << "rownum" + << "rows" + << "savepoint" + << "select" + << "session" + << "set" + << "share" + << "size" + << "smallint" + << "some" + << "start" + << "successful" + << "synonym" + << "sysdate" + << "table" + << "then" + << "to" + << "trigger" + << "true" + << "truncate" + << "type" + << "uid" + << "union" + << "unique" + << "update" + << "user" + << "using" + << "validate" + << "values" + << "varchar" + << "varchar2" + << "varray" + << "view" + << "whenever" + << "where" + << "with"; + } + + return keywords; +} + +#include "sqlwriter.moc" diff --git a/umbrello/umbrello/codegenerators/sqlwriter.h b/umbrello/umbrello/codegenerators/sqlwriter.h new file mode 100644 index 00000000..c500e2e7 --- /dev/null +++ b/umbrello/umbrello/codegenerators/sqlwriter.h @@ -0,0 +1,77 @@ +/*************************************************************************** + sqlwriter.h - description + ------------------- + begin : 10.02.2003 + copyright : (C) 2003 by Nikolaus Gradwohl + email : guru@local-guru.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. * + * * + ***************************************************************************/ + +#ifndef SQLWRITER_H +#define SQLWRITER_H + +#include "simplecodegenerator.h" +#include "../umlattributelist.h" + +/** + * class SQLWriter is a code generator for UMLClassifier objects. + * Create an instance of this class, and feed it a UMLClassifier when + * calling writeClass and it will generate a sql source file for + * that concept + */ +class SQLWriter : public SimpleCodeGenerator { + Q_OBJECT +public: + + SQLWriter(); + virtual ~SQLWriter(); + + /** + * call this method to generate sql code for a UMLClassifier + * @param c the class to generate code for + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "SQL" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * Reimplement method from CodeGenerator. + */ + virtual QStringList defaultDatatypes(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +private: + + /** + * write all attributes for a given class + * @param c the class for which we are generating code + * @param j the stream associated with the output file + */ + void writeAttributes(UMLClassifier *c, QTextStream &j); + + /** + * Prints out attributes as columns in the table + * + * @param sql the stream we should print to + * @param attributeList the attributes to be printed + * @param first if the attributes are the first one + */ + void printAttributes(QTextStream& sql, UMLAttributeList attributeList, bool first); +}; + +#endif // SQLWRITER_H diff --git a/umbrello/umbrello/codegenerators/tclwriter.cpp b/umbrello/umbrello/codegenerators/tclwriter.cpp new file mode 100644 index 00000000..d8607aa7 --- /dev/null +++ b/umbrello/umbrello/codegenerators/tclwriter.cpp @@ -0,0 +1,951 @@ +/*************************************************************************** + begin : Thu Jul 26 2005 + copyright : (C) 2005 by Rene Meyer + email : rene.meyer@sturmit.de + (C) 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 "tclwriter.h" +// qt/kde includes +#include <qfile.h> +#include <qtextstream.h> +#include <qregexp.h> +#include <kdebug.h> +// app includes +#include "classifierinfo.h" +#include "codegen_utils.h" +#include "../umldoc.h" +#include "../classifier.h" +#include "../operation.h" +#include "../template.h" +#include "../umltemplatelist.h" +#include "../umlclassifierlistitemlist.h" +#include "../classifierlistitem.h" +#include "../model_utils.h" + +static const char *tclwords[] = { + "body", + "break", + "case", + "class", + "common", + "concat", + "configbody", + "constructor", + "continue", + "default", + "destructor", + "else", + "elseif", + "for", + "foreach", + "global", + "if", + "incr", + "lappend", + "lindex", + "list", + "llength", + "load", + "lrange", + "lreplace", + "method", + "namespace", + "private", + "proc", + "protected", + "public", + "return", + "set", + "source", + "switch", + "then", + "upvar", + "variable", + "virtual", + "while", + 0 + }; + +TclWriter::TclWriter() +{ +} + +TclWriter::~TclWriter() +{ +} + +Uml::Programming_Language +TclWriter::getLanguage() +{ + return Uml::pl_Tcl; +} + +void +TclWriter::writeClass(UMLClassifier * c) +{ + + if (!c) { + kDebug() << "Cannot write class of NULL concept!\n"; + return; + } + QFile fileh, filetcl; + + // find an appropriate name for our file + QString fileName = findFileName(c, ".tcl"); + if (fileName.isEmpty()) { + emit codeGenerated(c, false); + return; + } + + if (!openFile(fileh, fileName)) { + emit codeGenerated(c, false); + return; + } + // preparations + classifierInfo = new ClassifierInfo(c); + classifierInfo->fileName = fileName; + classifierInfo->className = cleanName(c->getName()); + mClass = cleanName(c->getName()); + if (!c->getPackage().isEmpty()) { + mNamespace = "::" + cleanName(c->getPackage()); + mClassGlobal = mNamespace + "::" + mClass; + } else { + mNamespace = "::"; + mClassGlobal = "::" + mClass; + } + + // write Header file + writeHeaderFile(c, fileh); + fileh.close(); + + // Determine whether the implementation file is required. + // (It is not required if the class is an enumeration.) + bool need_impl = true; + if (!classifierInfo->isInterface) { + if (c->getBaseType() == Uml::ot_Enum) + need_impl = false; + } + if (need_impl) { + if (!openFile(filetcl, fileName + "body")) { + emit codeGenerated(c, false); + return; + } + // write Source file + writeSourceFile(c, filetcl); + filetcl.close(); + } + // Wrap up: free classifierInfo, emit done code + classifierInfo = 0; + + emit codeGenerated(c, true); + +} + +void +TclWriter::writeHeaderFile(UMLClassifier * c, QFile & fileh) +{ + // open stream for writing + QTextStream stream(&fileh); + mStream = &stream; + + // reset the indent level + m_indentLevel = 0; + + // write header blurb + QString str = getHeadingFile(".tcl"); + if (!str.isEmpty()) { + str.replace(QRegExp("%filename%"), classifierInfo->fileName); + str.replace(QRegExp("%filepath%"), fileh.name()); + writeCode(str); + } + // set current namespace + writeCode("namespace eval " + mNamespace + " {"); + m_indentLevel++; + + // check on already existing + writeComm("Do not load twice"); + writeCode("if {[namespace exist " + mClass + "]} return"); + + // source used superclass files + UMLClassifierList superclasses = classifierInfo->superclasses; + if (superclasses.count() > 0) { + writeComm + ("Source found and used class files and import class command if necessary"); + + for (UMLClassifier * classifier = superclasses.first(); classifier; + classifier = superclasses.next()) { + writeUse(classifier); + } + } + // write all "source" we need to include other classes, that arent us. + if (classifierInfo->hasAssociations) { + writeAssociationIncl(classifierInfo->plainAssociations, c->getID(), + "Associations"); + writeAssociationIncl(classifierInfo->aggregations, c->getID(), + "Aggregations"); + writeAssociationIncl(classifierInfo->compositions, c->getID(), + "Compositions"); + } + //Write class Documentation + writeDocu("\n@class\t" + mClass + m_endl + c->getDoc()); + + //check if class is abstract and / or has abstract methods + if ((c->getAbstract() || classifierInfo->isInterface) + && !hasAbstractOps(c)) { + writeComm("TODO abstract class" + mClass + + "\nInherit from it and create only objects from the derived classes"); + } + // check on enum classes + if (!classifierInfo->isInterface) { + // use tcl-list for enum's + if (c->getBaseType() == Uml::ot_Enum) { + UMLClassifierListItemList litList = + c->getFilteredList(Uml::ot_EnumLiteral); + writeCode("set enum_" + mClass + " [list\\"); + m_indentLevel++; + for (UMLClassifierListItem * lit = litList.first(); lit; + lit = litList.next()) { + QString enumLiteral = cleanName(lit->getName()); + writeCode(enumLiteral + "\\"); + } + m_indentLevel--; + writeCode("];# end of enum"); + m_indentLevel--; + writeCode("};# end of namespace"); + return; + } + } + // Generate template parameters. + UMLTemplateList template_params = c->getTemplateList(); + if (template_params.count()) { + writeCode("#TODO template<"); + for (UMLTemplate * t = template_params.first(); t; + t = template_params.next()) { + QString formalName = t->getName(); + QString typeName = t->getTypeName(); + writeCode(typeName + "# " + formalName); + } + } + // start my own class + writeCode("class " + mClass + " {"); + m_indentLevel++; + if (classifierInfo->superclasses.count() > 0) { + QString code = "inherit"; + for (UMLClassifier * superClass = classifierInfo->superclasses.first(); + superClass; superClass = classifierInfo->superclasses.next()) { + /* + if (superClass->getAbstract() || superClass->isInterface()) + stream << getIndent() << "virtual "; + */ + if (superClass->getPackage().isEmpty()) { + code += " ::" + cleanName(superClass->getName()); + } else { + code += + " ::" + cleanName(superClass->getPackage()) + "::" + + cleanName(superClass->getName()); + } + } + writeCode(code); + } + // + //declarations of operations + // + // write out field and operations decl grouped by visibility + // + + // PUBLIC attribs/methods + // for public: constructors are first ops we print out + if (!classifierInfo->isInterface) { + writeConstructorHeader(); + writeDestructorHeader(); + } + // attributes + writeAttributeDecl(Uml::Visibility::Public, true); // write static attributes first + writeAttributeDecl(Uml::Visibility::Public, false); + // associations + writeAssociationDecl(classifierInfo->plainAssociations, Uml::Visibility::Public, + c->getID(), "Associations"); + writeAssociationDecl(classifierInfo->aggregations, Uml::Visibility::Public, c->getID(), + "Aggregations"); + writeAssociationDecl(classifierInfo->compositions, Uml::Visibility::Public, c->getID(), + "Compositions"); + //TODO writeHeaderAccessorMethodDecl(c, Uml::Visibility::Public, stream); + writeOperationHeader(c, Uml::Visibility::Public); + + // PROTECTED attribs/methods + // + // attributes + writeAttributeDecl(Uml::Visibility::Protected, true); // write static attributes first + writeAttributeDecl(Uml::Visibility::Protected, false); + // associations + writeAssociationDecl(classifierInfo->plainAssociations, Uml::Visibility::Protected, + c->getID(), "Association"); + writeAssociationDecl(classifierInfo->aggregations, Uml::Visibility::Protected, + c->getID(), "Aggregation"); + writeAssociationDecl(classifierInfo->compositions, Uml::Visibility::Protected, + c->getID(), "Composition"); + //TODO writeHeaderAccessorMethodDecl(c, Uml::Visibility::Protected, stream); + writeOperationHeader(c, Uml::Visibility::Protected); + + // PRIVATE attribs/methods + // + // attributes + writeAttributeDecl(Uml::Visibility::Private, true); // write static attributes first + writeAttributeDecl(Uml::Visibility::Private, false); + // associations + writeAssociationDecl(classifierInfo->plainAssociations, Uml::Visibility::Private, + c->getID(), "Associations"); + writeAssociationDecl(classifierInfo->aggregations, Uml::Visibility::Private, c->getID(), + "Aggregations"); + writeAssociationDecl(classifierInfo->compositions, Uml::Visibility::Private, c->getID(), + "Compositions"); + //TODO writeHeaderAccessorMethodDecl(c, Uml::Visibility::Public, stream); + writeOperationHeader(c, Uml::Visibility::Private); + writeInitAttributeHeader(); // this is always private, used by constructors to initialize class + + // end of class header + m_indentLevel--; + writeCode("};# end of class"); + + // end of class namespace, if any + m_indentLevel--; + writeCode("};# end of namespace"); +} + +void +TclWriter::writeSourceFile(UMLClassifier * c, QFile & filetcl) +{ + // open stream for writing + QTextStream stream(&filetcl); + mStream = &stream; + + // set the starting indentation at zero + m_indentLevel = 0; + + //try to find a heading file (license, coments, etc) + QString str; + str = getHeadingFile(".tclbody"); + if (!str.isEmpty()) { + str.replace(QRegExp("%filename%"), classifierInfo->fileName + "body"); + str.replace(QRegExp("%filepath%"), filetcl.name()); + writeCode(str); + } + // Start body of class + + // constructors are first ops we print out + if (!classifierInfo->isInterface) { + writeConstructorSource(); + writeDestructorSource(); + } + // Public attributes have in tcl a configbody method + writeAttributeSource(); + // Association access functions + writeAssociationSource(classifierInfo->plainAssociations, c->getID()); + writeAssociationSource(classifierInfo->aggregations, c->getID()); + writeAssociationSource(classifierInfo->compositions, c->getID()); + // Procedures and methods + writeOperationSource(c, Uml::Visibility::Public); + writeOperationSource(c, Uml::Visibility::Protected); + writeOperationSource(c, Uml::Visibility::Private); + // Yep, bringing up the back of the bus, our initialization method for attributes + writeInitAttributeSource(); +} + +void +TclWriter::writeCode(const QString &text) +{ + *mStream << getIndent() << text << m_endl; +} + +void +TclWriter::writeComm(const QString &text) +{ + QStringList lines = QStringList::split("\n", text, true); + for (uint i = 0; i < lines.count(); i++) { + *mStream << getIndent() << "# " << lines[i] << m_endl; + } +} + +void +TclWriter::writeDocu(const QString &text) +{ + QStringList lines = QStringList::split("\n", text, true); + for (uint i = 0; i < lines.count(); i++) { + *mStream << getIndent() << "## " << lines[i] << m_endl; + } +} + +// To prevent circular including when both classifiers on either end +// of an association have roles we need to have forward declaration of +// the other class...but only IF its not THIS class (as could happen +// in self-association relationship). +void +TclWriter::writeAssociationIncl(UMLAssociationList list, Uml::IDType myId, + const QString &type) +{ + for (UMLAssociation * a = list.first(); a; a = list.next()) { + UMLClassifier *classifier = NULL; + + writeComm(m_endl + type + m_endl + a->toString() + m_endl + a->getDoc()); + // only use OTHER classes (e.g. we don't need to write includes for ourselves!! + // AND only IF the roleName is defined, otherwise, its not meant to be noticed. + if (a->getObjectId(Uml::A) == myId && !a->getRoleName(Uml::B).isEmpty()) { + classifier = dynamic_cast < UMLClassifier * >(a->getObject(Uml::B)); + writeUse(classifier); + } else if (a->getObjectId(Uml::B) == myId + && !a->getRoleName(Uml::A).isEmpty()) { + classifier = dynamic_cast < UMLClassifier * >(a->getObject(Uml::A)); + if (classifier->getPackage().isEmpty()) + writeCode("namespace eval " + cleanName(classifier->getName()) + + " {}"); + } else { + // CHECK: This crashes (classifier still NULL from above) + /* + writeCode("namespace eval " + cleanName(classifier->getPackage()) + + "::" + cleanName(classifier->getName()) + " {}"); + */ + } + } +} + +void +TclWriter::writeUse(UMLClassifier * c) +{ + QString myNs; + + if (!c->getPackage().isEmpty()) { + myNs = cleanName(c->getPackage()); + } else { + myNs = ""; + } + // if different package + if (("::"+myNs) != mNamespace) { + if (c->getPackage().isEmpty()) { + writeCode("source " + findFileName(c, ".tcl")); + writeCode("namespace import ::" + cleanName(c->getName())); + } else { + writeCode("package require " + myNs); + writeCode("namespace import ::" + myNs + "::" + + cleanName(c->getName())); + } + } else { + // source the file + writeCode("source " + findFileName(c, ".tcl")); + } +} + +void +TclWriter::writeConstructorHeader() +{ + + writeDocu + (m_endl + "@func constructor" + m_endl + + "@par args contain all configuration parameters" + m_endl); + + writeCode("constructor {args} {}" + m_endl); +} + +void +TclWriter::writeConstructorSource() +{ + writeComm(mClassGlobal + "::constructor"); + writeCode(mClassGlobal + "::constructor {args} {"); + m_indentLevel++; + if (classifierInfo->hasAttributes) { + writeCode("initAttributes"); + } + writeCode("eval configure $args"); + m_indentLevel--; + writeCode('}' + m_endl); +} + +void +TclWriter::writeDestructorHeader() +{ + + writeDocu(m_endl + "@func destructor" + m_endl); + + writeCode("destructor {} {}"); +} + +void +TclWriter::writeDestructorSource() +{ + writeComm(mClassGlobal + "::destructor"); + writeCode(mClassGlobal + "::destructor {} {" + m_endl + '}' + m_endl); +} + +void +TclWriter::writeAttributeDecl(Uml::Visibility visibility, bool writeStatic) +{ + if (classifierInfo->isInterface) + return; + + QString scope = visibility.toString(); + QString type; + if (writeStatic) { + type = "common"; + } else { + type = "variable"; + } + UMLAttributeList *list = NULL; + switch (visibility) { + case Uml::Visibility::Private: + if (writeStatic) { + list = &(classifierInfo->static_atpriv); + } else { + list = &(classifierInfo->atpriv); + } + break; + + case Uml::Visibility::Protected: + if (writeStatic) { + list = &(classifierInfo->static_atprot); + } else { + list = &(classifierInfo->atprot); + } + break; + + case Uml::Visibility::Public: + if (writeStatic) { + list = &(classifierInfo->static_atpub); + } else { + list = &(classifierInfo->atpub); + } + break; + default: + break; + } + + if (list && list->count() > 0) { + writeComm(m_endl + scope + ' ' + type + " attributes" + m_endl); + // write attrib declarations now + QString documentation; + for (UMLAttribute * at = list->first(); at; at = list->next()) { + documentation = at->getDoc(); + QString varName = cleanName(at->getName()); + QString typeName = fixTypeName(at->getTypeName()); + writeDocu(m_endl + "@var " + scope + ' ' + type + ' ' + typeName + ' ' + + varName + m_endl + documentation); + writeCode(scope + ' ' + type + ' ' + varName + m_endl); + } + } +} + +void +TclWriter::writeAssociationDecl(UMLAssociationList associations, + Uml::Visibility permitScope, Uml::IDType id, + const QString &/*type*/) +{ + 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 && !a->getRoleName(Uml::B).isEmpty()) + printRoleB = true; + + if (a->getObjectId(Uml::B) == id && !a->getRoleName(Uml::A).isEmpty()) + printRoleA = true; + + // First: we insert documentaion for association IF it has either role AND some documentation (!) + // print RoleB decl + if (printRoleB && a->getVisibility(Uml::B) == permitScope) { + + QString fieldClassName = + cleanName(getUMLObjectName(a->getObject(Uml::B))); + writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::B), + a->getMulti(Uml::B), a->getRoleDoc(Uml::B), + permitScope.toString()); + } + // print RoleA decl + if (printRoleA && a->getVisibility(Uml::A) == permitScope) { + QString fieldClassName = + cleanName(getUMLObjectName(a->getObject(Uml::A))); + writeAssociationRoleDecl(fieldClassName, a->getRoleName(Uml::A), + a->getMulti(Uml::A), a->getRoleDoc(Uml::A), + permitScope.toString()); + } + // reset for next association in our loop + printRoleA = false; + printRoleB = false; + } + } +} + +void +TclWriter::writeAssociationRoleDecl(const QString &fieldClassName, const QString &roleName, + const QString &multi, const QString &doc, const QString &scope) +{ + // ONLY write out IF there is a rolename given + // otherwise its not meant to be declared in the code + if (roleName.isEmpty()) + return; + + + // 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 = roleName.lower(); + + // record this for later consideration of initialization IF the + // multi value requires 1 of these objects + if (ObjectFieldVariables.findIndex(fieldVarName) == -1 && + multi.contains(QRegExp("^1$")) + ) { + // ugh. UGLY. Storing variable name and its class in pairs. + ObjectFieldVariables.append(fieldVarName); + ObjectFieldVariables.append(fieldClassName); + } + writeDocu(m_endl + "@var " + scope + " variable <" + fieldClassName + + "> " + fieldVarName + m_endl + doc); + writeCode(scope + " variable " + fieldVarName + m_endl); + } else { + QString fieldVarName = roleName.lower(); + + // record unique occurrences for later when we want to check + // for initialization of this vector + if (VectorFieldVariables.findIndex(fieldVarName) == -1) + VectorFieldVariables.append(fieldVarName); + writeDocu(m_endl + "@var" + scope + " variable <" + fieldClassName + + "*> " + fieldVarName + m_endl + doc); + writeCode(scope + " variable " + fieldVarName + m_endl); + } +} + +void +TclWriter::writeInitAttributeHeader() +{ + if (classifierInfo->hasAttributes) { + writeDocu("@method private initAttributes" + m_endl + + "Initialize all internal variables"); + writeCode("private method initAttributes {}"); + } +} + +void +TclWriter::writeInitAttributeSource() +{ + // only need to do this under certain conditions + if (classifierInfo->hasAttributes) { + QString varName; + + writeComm(mClassGlobal + "::initAttributes"); + writeCode("body " + mClassGlobal + "::initAttributes {} {"); + m_indentLevel++; + + // first, initiation of fields derived from attributes + UMLAttributeList atl = classifierInfo->getAttList(); + for (UMLAttribute * at = atl.first(); at; at = atl.next()) { + if (!at->getInitialValue().isEmpty()) { + varName = cleanName(at->getName()); + writeCode("set " + varName + ' ' + at->getInitialValue()); + } + } + // Now initialize the association related fields (e.g. vectors) + QStringList::Iterator it; + for (it = VectorFieldVariables.begin(); + it != VectorFieldVariables.end(); ++it) { + varName = *it; + writeCode("set " + varName + " [list]"); + } + + for (it = ObjectFieldVariables.begin(); + it != ObjectFieldVariables.end(); ++it) { + varName = *it; + it++; + QString fieldClassName = *it; + writeCode("set " + varName + " [list]"); + } + // clean up + ObjectFieldVariables.clear(); // shouldn't be needed? + VectorFieldVariables.clear(); // shouldn't be needed? + + m_indentLevel--; + writeCode('}' + m_endl); + } +} + +void +TclWriter::writeOperationHeader(UMLClassifier * c, Uml::Visibility permitScope) +{ + + UMLOperationList oplist; + UMLOperation *op; + UMLAttribute *at; + int j; + + //sort operations by scope first and see if there are abstract methods + UMLOperationList inputlist = c->getOpList(); + for (UMLOperation * op = inputlist.first(); op; op = inputlist.next()) { + switch (op->getVisibility()) { + case Uml::Visibility::Public: + if (permitScope == Uml::Visibility::Public) + oplist.append(op); + break; + case Uml::Visibility::Protected: + if (permitScope == Uml::Visibility::Protected) + oplist.append(op); + break; + case Uml::Visibility::Private: + if (permitScope == Uml::Visibility::Private) + oplist.append(op); + break; + default: + break; + } + } + + // generate method decl for each operation given + if (oplist.count() > 0) { + writeComm("Operations"); + } + for (op = oplist.first(); op; op = oplist.next()) { + QString doc = ""; + QString code = ""; + QString methodReturnType = fixTypeName(op->getTypeName()); + QString name = cleanName(op->getName()); + QString scope = permitScope.toString(); + if (op->getAbstract() || classifierInfo->isInterface) { + //TODO declare abstract method as 'virtual' + // str += "virtual "; + } + // declaration for header file + if (op->getStatic()) { + doc = m_endl + "@fn " + scope + " proc " + name + m_endl; + code = scope + " proc " + name + " {"; + } else { + doc = m_endl + "@fn " + scope + " method " + name + m_endl; + code = scope + " method " + name + " {"; + } + // method parameters + UMLAttributeList atl = op->getParmList(); + j = 0; + for (at = atl.first(); at; at = atl.next(), j++) { + QString typeName = fixTypeName(at->getTypeName()); + QString atName = cleanName(at->getName()); + if (at->getInitialValue().isEmpty()) { + doc += + "@param " + typeName + ' ' + atName + m_endl + at->getDoc() + + m_endl; + code += ' ' + atName; + } else { + doc += + "@param " + typeName + ' ' + atName + " (default=" + + at->getInitialValue() + ") " + m_endl + at->getDoc() + m_endl; + code += " {" + atName + ' ' + at->getInitialValue() + "} "; + } + } + if (methodReturnType != "void") { + doc += "@return " + methodReturnType + m_endl; + } + writeDocu(doc + op->getDoc()); + writeCode(code + "} {}" + m_endl); + } +} + +void +TclWriter::writeOperationSource(UMLClassifier * c, Uml::Visibility permitScope) +{ + + UMLOperationList oplist; + UMLOperation *op; + UMLAttribute *at; + int j; + + //sort operations by scope first and see if there are abstract methods + UMLOperationList inputlist = c->getOpList(); + for (UMLOperation * op = inputlist.first(); op; op = inputlist.next()) { + switch (op->getVisibility()) { + case Uml::Visibility::Public: + if (permitScope == Uml::Visibility::Public) + oplist.append(op); + break; + case Uml::Visibility::Protected: + if (permitScope == Uml::Visibility::Protected) + oplist.append(op); + break; + case Uml::Visibility::Private: + if (permitScope == Uml::Visibility::Private) + oplist.append(op); + break; + default: + break; + } + } + + // generate source for each operation given + for (op = oplist.first(); op; op = oplist.next()) { + QString code = ""; + QString methodReturnType = fixTypeName(op->getTypeName()); + QString name; + // no code needed + if (op->getAbstract() || classifierInfo->isInterface) { + continue; + } + name = mClassGlobal + "::" + cleanName(op->getName()); + writeComm(name); + code = "body " + name + " {"; + // parameters + UMLAttributeList atl = op->getParmList(); + j = 0; + for (at = atl.first(); at; at = atl.next(), j++) { + QString atName = cleanName(at->getName()); + if (at->getInitialValue().isEmpty()) { + code += ' ' + atName; + } else { + code += " {" + atName + ' ' + at->getInitialValue() + "} "; + } + } + writeCode(code += "} {"); + m_indentLevel++; + if (methodReturnType != "void") { + writeCode("return " + methodReturnType); + } else { + writeCode("return"); + } + m_indentLevel--; + writeCode('}' + m_endl); + } +} + +void +TclWriter::writeAttributeSource() +{ + UMLAttributeList *list = &(classifierInfo->atpub); + UMLAttribute *at; + for (at = list->first(); at; at = list->next()) { + QString name = mClassGlobal + "::" + cleanName(at->getName()); + + writeComm(name); + writeCode("configbody " + name + " {} {" + m_endl + '}' + m_endl); + } +} + +void +TclWriter::writeAssociationSource(UMLAssociationList associations, + Uml::IDType id) +{ + if (associations.isEmpty()) { + return; + } + + 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 && !a->getRoleName(Uml::B).isEmpty()) + printRoleB = true; + + if (a->getObjectId(Uml::B) == id && !a->getRoleName(Uml::A).isEmpty()) + printRoleA = true; + + // print RoleB source + if (printRoleB && a->getVisibility(Uml::B) == Uml::Visibility::Public) { + + QString fieldClassName = + cleanName(getUMLObjectName(a->getObject(Uml::B))); + writeAssociationRoleSource(fieldClassName, a->getRoleName(Uml::B), + a->getMulti(Uml::B)); + } + // print RoleA source + if (printRoleA && a->getVisibility(Uml::A) == Uml::Visibility::Public) { + QString fieldClassName = + cleanName(getUMLObjectName(a->getObject(Uml::A))); + writeAssociationRoleSource(fieldClassName, a->getRoleName(Uml::A), + a->getMulti(Uml::A)); + } + // reset for next association in our loop + printRoleA = false; + printRoleB = false; + } +} + +void +TclWriter::writeAssociationRoleSource(const QString &fieldClassName, + const QString &roleName, const QString &multi) +{ + // ONLY write out IF there is a rolename given + // otherwise its not meant to be declared in the code + if (roleName.isEmpty()) + return; + + // 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 = roleName.lower(); + + writeCode("configbody " + mClassGlobal + "::" + fieldVarName + " {} {"); + m_indentLevel++; + writeCode("if {![$" + fieldVarName + " isa " + fieldClassName + "]} {"); + m_indentLevel++; + writeCode("return -code error \"expected object of class: " + + fieldClassName + "\""); + m_indentLevel--; + writeCode("}"); + m_indentLevel--; + + } else { + QString fieldVarName = roleName.lower(); + + writeCode("configbody " + mClassGlobal + "::" + fieldVarName + " {} {"); + m_indentLevel++; + writeCode("foreach myObj $" + fieldVarName + " {"); + m_indentLevel++; + writeCode("if {![$myObj isa " + fieldClassName + "]} {"); + m_indentLevel++; + writeCode("return -code error \"expected object of class: " + + fieldClassName + "\""); + m_indentLevel--; + writeCode("}"); + m_indentLevel--; + writeCode("}"); + m_indentLevel--; + } + writeCode('}' + m_endl); +} + +QString +TclWriter::fixTypeName(const QString &string) +{ + if (string.isEmpty()) + return "void"; + return string; +} + +// methods like this _shouldn't_ be needed IF we properly did things thruought the code. +QString +TclWriter::getUMLObjectName(UMLObject * obj) +{ + return (obj != 0) ? obj->getName() : QString("NULL"); +} + +const QStringList +TclWriter::reservedKeywords() const +{ + static QStringList keywords; + + if (keywords.isEmpty()) + { + for (int i = 0; tclwords[i]; i++) + keywords.append(tclwords[i]); + } + return keywords; +} + diff --git a/umbrello/umbrello/codegenerators/tclwriter.h b/umbrello/umbrello/codegenerators/tclwriter.h new file mode 100644 index 00000000..0c4d71c5 --- /dev/null +++ b/umbrello/umbrello/codegenerators/tclwriter.h @@ -0,0 +1,174 @@ +/*************************************************************************** + tclwriter.h - description + ------------------- + begin : Thu Jul 26 2005 + copyright : (C) 2005 by Rene Meyer + email : rene.meyer@sturmit.de + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef TCLWRITER_H +#define TCLWRITER_H + +#include <qstringlist.h> +#include "simplecodegenerator.h" +#include "../umloperationlist.h" +#include "../umlattributelist.h" +#include "../umlassociationlist.h" + +class QFile; +class QTextStream; +class ClassifierInfo; + +/** + * class TclWriter is a code generator for UMLClassifier objects. + * Create an instance of this class, and feed it a UMLClassifier when + * calling writeClass and it will generate both a header (.h) and + * source (.tcl) file for that classifier. + */ +class TclWriter : public SimpleCodeGenerator +{ +public: + + /** + * Constructor, initialises a couple of variables + */ + TclWriter(); + + /** + * Destructor, empty + */ + virtual ~ TclWriter(); + + /** + * call this method to generate tcl code for a UMLClassifier + * @param c the class to generate code for + */ + virtual void writeClass(UMLClassifier * c); + + /** + * returns "Tcl" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +private: + /** + * Current output stream. + */ + QTextStream * mStream; + /** + * write the header file for this classifier. + */ + void writeHeaderFile(UMLClassifier * c, QFile & file); + + /** + * write the source code body file for this classifier. + */ + void writeSourceFile(UMLClassifier * c, QFile & file); + + /** + * write the source codei text. + */ + void writeCode(const QString &text); + + /** + * write comment text. + */ + void writeComm(const QString &text); + + /** + * write documentation text. + */ + void writeDocu(const QString &text); + + void writeConstructorDecl(); + + void writeDestructorDecl(); + + /** + * Summary information about current classifier. + */ + ClassifierInfo *classifierInfo; + QString mNamespace; + QString mClass; + QString mClassGlobal; + + /** + * writes the Attribute declarations + * @param visibility the visibility of the attribs to print out + * @param writeStatic whether to write static or non-static attributes out + * @param stream text stream + */ + void writeAttributeDecl(Uml::Visibility visibility, bool writeStatic); + + void writeAssociationIncl(UMLAssociationList list, + Uml::IDType myId, const QString &type); + /** + * Searches a list of associations for appropriate ones to write out as attributes + */ + void writeAssociationDecl(UMLAssociationList associations, + Uml::Visibility permit, Uml::IDType id, + const QString &type); + + /** + * Writes out an association as an attribute using Vector + */ + void writeAssociationRoleDecl(const QString &fieldClassName, + const QString &roleName, const QString &multi, const QString &doc, const QString &docname); + + /** + * If needed, write out the declaration for the method to initialize attributes of our class. + */ + void writeInitAttributeHeader(); + void writeInitAttributeSource(); + + void writeConstructorHeader(); + void writeConstructorSource(); + void writeDestructorHeader(); + void writeDestructorSource(); + void writeOperationHeader(UMLClassifier * c, + Uml::Visibility permitScope); + void writeOperationSource(UMLClassifier * c, + Uml::Visibility permitScope); + void writeAttributeSource(); + void writeAssociationSource(UMLAssociationList associations, + Uml::IDType id); + void writeAssociationRoleSource(const QString &fieldClassName, + const QString &roleName, + const QString &multi); + void writeUse(UMLClassifier * c); + + + + /** + * Returns the name of the given object (if it exists) + */ + QString getUMLObjectName(UMLObject * obj); + + /** + * Replaces `string' with STRING_TYPENAME. + */ + QString fixTypeName(const QString &string); + + QStringList ObjectFieldVariables; + QStringList VectorFieldVariables; + +}; + + + +#endif // TCLWRITER_H diff --git a/umbrello/umbrello/codegenerators/xmlcodecomment.cpp b/umbrello/umbrello/codegenerators/xmlcodecomment.cpp new file mode 100644 index 00000000..5f44620b --- /dev/null +++ b/umbrello/umbrello/codegenerators/xmlcodecomment.cpp @@ -0,0 +1,67 @@ +/*************************************************************************** + * * + * 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 : Mon Sep 26 2003 + */ + +#include "xmlcodecomment.h" + +#include <kdebug.h> + +// Constructors/Destructors +// + +XMLCodeComment::XMLCodeComment ( CodeDocument * doc, const QString & text ) + : CodeComment (doc, text) +{ + +} + +XMLCodeComment::~XMLCodeComment ( ) { } + +// +// Methods +// + + +// Accessor methods +// + +// Other methods +// + +/** + * @return QString + */ +QString XMLCodeComment::toString ( ) +{ + + QString output = ""; + + // simple output method + if(getWriteOutText()) + { + QString indent = getIndentationString(); + QString endLine = getNewLineEndingChars(); + QString body = getText(); + output.append(indent+"<!-- "); + if(!body.isEmpty()) + output.append(formatMultiLineText (body, indent, endLine)); + output.append(indent+"-->"+endLine); + } + + return output; +} + + +#include "xmlcodecomment.moc" diff --git a/umbrello/umbrello/codegenerators/xmlcodecomment.h b/umbrello/umbrello/codegenerators/xmlcodecomment.h new file mode 100644 index 00000000..a30bcbab --- /dev/null +++ b/umbrello/umbrello/codegenerators/xmlcodecomment.h @@ -0,0 +1,68 @@ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Mon Sep 26 2003 + */ + + + +#ifndef XMLCODECOMMENT_H +#define XMLCODECOMMENT_H + +#include <qstring.h> +#include "../codecomment.h" + +class CodeDocument; + +/** + * class XMLCodeDocumentation + * A XML (code) comment. + */ + +class XMLCodeComment: virtual public CodeComment +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + + /** + * Constructors + */ + explicit XMLCodeComment ( CodeDocument * doc, const QString & text = "" ); + + /** + * Empty Destructor + */ + virtual ~XMLCodeComment( ); + + // Public attributes + // + + // Other + // + + /** + * @return QString + */ + QString toString ( ); + + +protected: + +private: + +}; + +#endif // XMLCODECOMMENT_H diff --git a/umbrello/umbrello/codegenerators/xmlelementcodeblock.cpp b/umbrello/umbrello/codegenerators/xmlelementcodeblock.cpp new file mode 100644 index 00000000..7e702619 --- /dev/null +++ b/umbrello/umbrello/codegenerators/xmlelementcodeblock.cpp @@ -0,0 +1,166 @@ + +/*************************************************************************** + * * + * 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 Sep 26 2003 + */ + +// own header +#include "xmlelementcodeblock.h" + +// qt/kde includes +#include <kdebug.h> + +// local includes +#include "xmlcodecomment.h" +#include "../attribute.h" +#include "../codedocument.h" + +// Constructors/Destructors +// + +XMLElementCodeBlock::XMLElementCodeBlock ( CodeDocument * parentDoc, const QString & nodeName, const QString & comment) + : HierarchicalCodeBlock(parentDoc) +{ + init(parentDoc, nodeName, comment); +} + +XMLElementCodeBlock::~XMLElementCodeBlock ( ) { } + +// +// Methods +// + +/** + * Save the XMI representation of this object + */ +void XMLElementCodeBlock::saveToXMI ( QDomDocument & doc, QDomElement & root ) { + QDomElement blockElement = doc.createElement( "xmlelementblock" ); + + setAttributesOnNode(doc, blockElement); + + root.appendChild( blockElement ); +} + +/** + * load params from the appropriate XMI element node. + */ +void XMLElementCodeBlock::loadFromXMI ( QDomElement & root ) +{ + setAttributesFromNode(root); +} + +/** set attributes of the node that represents this class + * in the XMI document. + */ +void XMLElementCodeBlock::setAttributesOnNode ( QDomDocument & doc, QDomElement & docElement) +{ + + // superclass call + HierarchicalCodeBlock::setAttributesOnNode(doc,docElement); + + // now set local attributes/fields + docElement.setAttribute("nodeName",getNodeName()); + +} + +/** set the class attributes of this object from + * the passed element node. + */ +void XMLElementCodeBlock::setAttributesFromNode ( QDomElement & root) { + + // superclass call + HierarchicalCodeBlock::setAttributesFromNode(root); + + // now set local attributes + setNodeName(root.attribute("nodeName","UNKNOWN")); + +} + +// Accessor methods +// + +void XMLElementCodeBlock::setNodeName (const QString &name) { + m_nodeName = name; +} + +QString XMLElementCodeBlock::getNodeName () { + return m_nodeName; +} + +void XMLElementCodeBlock::addAttribute (UMLAttribute * at) { + m_attList.append(at); +} + +UMLAttributeList * XMLElementCodeBlock::getAttributeList() { + return & m_attList; +} + + +// Other methods +// + +/** + * update the start and end text for this ownedhierarchicalcodeblock. + */ +void XMLElementCodeBlock::updateContent ( ) +{ + + QString endLine = getNewLineEndingChars(); + + QString nodeName = getNodeName(); + + // Now update START/ENDING Text + QString startText = '<' + nodeName; + QString endText = ""; + + UMLAttributeList * alist = getAttributeList(); + for (UMLAttribute *at = alist->first(); at; at=alist->next()) + { + if(at->getInitialValue().isEmpty()) + kWarning()<<" XMLElementCodeBlock : cant print out attribute that lacks an initial value"<<endl; + else { + startText.append(" " +at->getName()+"=\""); + startText.append(at->getInitialValue()+"\""); + } + } + + // now set close of starting/ending node, the style depending on whether we have child text or not + if(getTextBlockList()->count()) + { + startText.append(">"); + endText = "</" + nodeName + '>'; + } else { + startText.append("/>"); + endText = ""; + } + + setStartText(startText); + setEndText(endText); + +} + +void XMLElementCodeBlock::init (CodeDocument *parentDoc, const QString &nodeName, const QString &comment) +{ + + setComment(new XMLCodeComment(parentDoc)); + getComment()->setText(comment); + + m_nodeName = nodeName; + + updateContent(); + +} + + +#include "xmlelementcodeblock.moc" diff --git a/umbrello/umbrello/codegenerators/xmlelementcodeblock.h b/umbrello/umbrello/codegenerators/xmlelementcodeblock.h new file mode 100644 index 00000000..b0acd277 --- /dev/null +++ b/umbrello/umbrello/codegenerators/xmlelementcodeblock.h @@ -0,0 +1,88 @@ + + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* This code generated by: + * Author : thomas + * Date : Wed Sep 26 2003 + */ + +#ifndef XMLELEMENTCODEBLOCK_H +#define XMLELEMENTCODEBLOCK_H + +#include <qstring.h> + +#include "../umlattributelist.h" +#include "../hierarchicalcodeblock.h" + +class CodeDocument; +class UMLAttribute; + +class XMLElementCodeBlock : public HierarchicalCodeBlock +{ + Q_OBJECT +public: + + // Constructors/Destructors + // + + /** + * Empty Constructor + */ + XMLElementCodeBlock ( CodeDocument * parentDoc, const QString & nodeName, const QString & comment = ""); + + /** + * Empty Destructor + */ + virtual ~XMLElementCodeBlock ( ); + + /** + * Save the XMI representation of this object + */ + virtual void saveToXMI ( QDomDocument & doc, QDomElement & root ); + + /** + * load params from the appropriate XMI element node. + */ + virtual void loadFromXMI ( QDomElement & root ); + + virtual UMLAttributeList * getAttributeList(); + + virtual void setNodeName (const QString &name); + virtual QString getNodeName (); + + void addAttribute (UMLAttribute * at); + +protected: + + /** set attributes of the node that represents this class + * in the XMI document. + */ + virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement); + + /** set the class attributes of this object from + * the passed element node. + */ + virtual void setAttributesFromNode ( QDomElement & element); + + /** + * Update the start/end text of this codeblock. + */ + void updateContent ( ); + +private: + + UMLAttributeList m_attList; + QString m_nodeName; + void init (CodeDocument * parent, const QString &nodeName, const QString &comment); + +}; + +#endif // XMLELEMENTCODEBLOCK_H diff --git a/umbrello/umbrello/codegenerators/xmlschemawriter.cpp b/umbrello/umbrello/codegenerators/xmlschemawriter.cpp new file mode 100644 index 00000000..303d3230 --- /dev/null +++ b/umbrello/umbrello/codegenerators/xmlschemawriter.cpp @@ -0,0 +1,809 @@ +/*************************************************************************** + 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. * + * * + ***************************************************************************/ + +#include "xmlschemawriter.h" + +#include <kdebug.h> + +#include <klocale.h> +#include <kmessagebox.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qregexp.h> + +#include "../umldoc.h" +#include "../classifier.h" +#include "../operation.h" +#include "../umlnamespace.h" + +// Constructor +XMLSchemaWriter::XMLSchemaWriter() +{ + + packageNamespaceTag = "tns"; + packageNamespaceURI = "http://foo.example.com/"; + schemaNamespaceTag = "xs"; + schemaNamespaceURI = "http://www.w3.org/2001/XMLSchema"; +} + +// form of..."the Destructor"!! +XMLSchemaWriter::~XMLSchemaWriter() { +} + +/** + * returns "XMLSchema" + */ +Uml::Programming_Language XMLSchemaWriter::getLanguage() { + return Uml::pl_XMLSchema; +} + +// main method for invoking.. +void XMLSchemaWriter::writeClass(UMLClassifier *c) +{ + + if (!c) { + kDebug()<<"Cannot write class of NULL classifier!\n"; + return; + } + + // find an appropriate name for our file + QString fileName = findFileName(c,".xsd"); + + 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; + } + + QTextStream XMLschema(&file); + + // set package namespace tag appropriately + if(!c->getPackage().isEmpty()) + packageNamespaceTag = c->getPackage(); + + // START WRITING + + // 0. FIRST THING: open the xml processing instruction. This MUST be + // the first thing in the file + XMLschema<<"<?xml version=\"1.0\"?>"<<m_endl; + + // 1. create the header + QString headerText = getHeadingFile(".xsd"); + if(!headerText.isEmpty()) { + headerText.replace(QRegExp("%filename%"),fileName); + headerText.replace(QRegExp("%filepath%"),file.name()); + } + if(!headerText.isEmpty()) + XMLschema<<headerText<<m_endl; + + // 2. Open schema element node with appropriate namespace decl + XMLschema<<"<"<<makeSchemaTag("schema"); + // common namespaces we know will be in the file.. + XMLschema<<" targetNamespace=\""<<packageNamespaceURI+packageNamespaceTag<<"\""<<m_endl; + XMLschema<<" xmlns:"<<schemaNamespaceTag<<"=\""<<schemaNamespaceURI<<"\""; + XMLschema<<" xmlns:"<<packageNamespaceTag<<"=\""<<packageNamespaceURI+packageNamespaceTag<<"\""; + + XMLschema<<">"<<m_endl; // close opening declaration + + m_indentLevel++; + + // 3? IMPORT statements -- do we need to do anything here? I suppose if + // our document has more than one package, which is possible, we are missing + // the correct import statements. Leave that for later at this time. + /* + //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->getPackage() != c->getPackage()) + XMLschema<<"import "<<con->getPackage()<<"."<<cleanName(con->getName())<<";"<<m_endl; + */ + + // 4. BODY of the schema. + // start the writing by sending this classifier, the "root" for this particular + // schema, to writeClassifier method, which will subsequently call itself on all + // related classifiers and thus populate the schema. + writeClassifier(c, XMLschema); + + // 5. What remains is to make the root node declaration + XMLschema<<m_endl; + writeElementDecl(getElementName(c), getElementTypeName(c), XMLschema); + + // 6. Finished: now we may close schema decl + m_indentLevel--; + XMLschema<<getIndent()<<"</"<<makeSchemaTag("schema")<<">"<<m_endl; // finished.. close schema node + + // bookeeping for code generation + emit codeGenerated(c, true); + + // tidy up. no dangling open files please.. + file.close(); + + // need to clear HERE, NOT in the destructor because we want each + // schema that we write to have all related classes. + writtenClassifiers.clear(); +} + +void XMLSchemaWriter::writeElementDecl( const QString &elementName, const QString &elementTypeName, QTextStream &XMLschema) +{ + if(forceDoc()) + writeComment(elementName+" is the root element, declared here.", XMLschema); + + XMLschema<<getIndent()<<"<"<<makeSchemaTag("element") + <<" name=\""<<elementName<<"\"" + <<" type=\""<<makePackageTag(elementTypeName)<<"\"" + <<"/>"<<m_endl; + +} + +void XMLSchemaWriter::writeClassifier (UMLClassifier *c, QTextStream &XMLschema) +{ + + // NO doing this 2 or more times. + if(hasBeenWritten(c)) + return; + + XMLschema<<m_endl; + + // write documentation for class, if any, first + if(forceDoc() || !c->getDoc().isEmpty()) + writeComment(c->getDoc(),XMLschema); + + if(c->getAbstract() || c->isInterface() ) + writeAbstractClassifier(c,XMLschema); // if its an interface or abstract class + else + writeConcreteClassifier(c,XMLschema); + +} + +UMLAttributeList XMLSchemaWriter::findAttributes (UMLClassifier *c) +{ + // sort attributes by Scope + UMLAttributeList attribs; + attribs.setAutoDelete(false); + + if (!c->isInterface()) { + UMLAttributeList atl = c->getAttributeList(); + for(UMLAttribute *at=atl.first(); at ; at=atl.next()) { + switch(at->getVisibility()) + { + case Uml::Visibility::Public: + case Uml::Visibility::Protected: + attribs.append(at); + break; + case Uml::Visibility::Private: + // DO NOTHING! no way to print in the schema + break; + default: + break; + } + } + } + return attribs; +} + +// We have to do 2 things with abstract classifiers (e.g. abstract classes and interfaces) +// which is to: +// 1) declare it as a complexType so it may be inherited (I can see an option here: to NOT write +// this complexType declaration IF the classifier itself isnt inherited by or is inheriting +// from anything because no other element will use this complexType). +// 2) Create a group so that elements, which obey the abstract class /interface may be placed in +// aggregation with other elements (again, and option here to NOT write the group if no other +// element use the interface in element aggregation) +// + +void XMLSchemaWriter::writeAbstractClassifier (UMLClassifier *c, QTextStream &XMLschema) +{ + + // preparations + UMLClassifierList subclasses = c->findSubClassConcepts(); // list of what inherits from us + UMLClassifierList superclasses = c->findSuperClassConcepts(); // list of what we inherit from + + // write the main declaration + writeConcreteClassifier (c, XMLschema); + writeGroupClassifierDecl (c, subclasses, XMLschema); + + markAsWritten(c); + + // now go back and make sure all sub-classing nodes are declared + if(subclasses.count() > 0) + { + + QString elementName = getElementName(c); + UMLAttributeList attribs = findAttributes(c); + QStringList attribGroups = findAttributeGroups(c); + + writeAttributeGroupDecl(elementName, attribs, XMLschema); + + // now write out inheriting classes, as needed + for(UMLClassifier * classifier = subclasses.first(); classifier; classifier = subclasses.next()) + writeClassifier(classifier, XMLschema); + } + + // write out any superclasses as needed + for(UMLClassifier *classifier = superclasses.first(); classifier; classifier = superclasses.next()) + writeClassifier(classifier, XMLschema); + +} + +void XMLSchemaWriter::writeGroupClassifierDecl (UMLClassifier *c, + UMLClassifierList subclasses, + QTextStream &XMLschema) +{ + + // name of class, subclassing classifiers + QString elementTypeName = getElementGroupTypeName(c); + + // start Writing node but only if it has subclasses? Nah..right now put in empty group + XMLschema<<getIndent()<<"<"<<makeSchemaTag("group")<<" name=\""<<elementTypeName<<"\">"<<m_endl; + m_indentLevel++; + + XMLschema<<getIndent()<<"<"<<makeSchemaTag("choice")<<">"<<m_endl; + m_indentLevel++; + + for(UMLClassifier *classifier = subclasses.first(); classifier; classifier = subclasses.next()) { + writeAssociationRoleDecl(classifier, "1", XMLschema); + } + + m_indentLevel--; + XMLschema<<getIndent()<<"</"<<makeSchemaTag("choice")<<">"<<m_endl; + + m_indentLevel--; + + // finish node + XMLschema<<getIndent()<<"</"<<makeSchemaTag("group")<<">"<<m_endl; + +} + +void XMLSchemaWriter::writeComplexTypeClassifierDecl (UMLClassifier *c, + UMLAssociationList associations, + UMLAssociationList aggregations, + UMLAssociationList compositions, + UMLClassifierList superclasses, + QTextStream &XMLschema) +{ + + // Preparations + // + + // sort attributes by Scope + UMLAttributeList attribs = findAttributes(c); + QStringList attribGroups = findAttributeGroups(c); + + // test for relevant associations + bool hasAssociations = determineIfHasChildNodes(c); + bool hasSuperclass = superclasses.count()> 0; + bool hasAttributes = attribs.count() > 0 || attribGroups.count() > 0; + + // START WRITING + + // start body of element + QString elementTypeName = getElementTypeName(c); + + XMLschema<<getIndent()<<"<"<<makeSchemaTag("complexType")<<" name=\""<<elementTypeName<<"\""; + + if(hasAssociations || hasAttributes || hasSuperclass) + { + + XMLschema<<">"<<m_endl; + + m_indentLevel++; + + if(hasSuperclass) + { + QString superClassName = getElementTypeName(superclasses.first()); + XMLschema<<getIndent()<<"<"<<makeSchemaTag("complexContent")<<">"<<m_endl; + + //PROBLEM: we only treat ONE superclass for inheritence.. bah. + m_indentLevel++; + XMLschema<<getIndent()<<"<"<<makeSchemaTag("extension")<<" base=\""<<makePackageTag(superClassName) + <<"\""; + if(hasAssociations || hasAttributes ) + XMLschema<<">"<<m_endl; + else + XMLschema<<"/>"<<m_endl; + + m_indentLevel++; + } + + if(hasAssociations) + { + // Child Elements (from most associations) + // + bool didFirstOne = false; + didFirstOne = writeAssociationDecls(associations, true, didFirstOne, c->getID(), XMLschema); + didFirstOne = writeAssociationDecls(aggregations, false, didFirstOne, c->getID(), XMLschema); + didFirstOne = writeAssociationDecls(compositions, false, didFirstOne, c->getID(), XMLschema); + + if (didFirstOne) { + m_indentLevel--; + XMLschema<<getIndent()<<"</"<<makeSchemaTag("sequence")<<">"<<m_endl; + } + } + + // ATTRIBUTES + // + if(hasAttributes) + { + writeAttributeDecls(attribs, XMLschema); + for(uint i= 0; i < attribGroups.count(); i++) + XMLschema<<getIndent()<<"<"<<makeSchemaTag("attributeGroup")<<" ref=\"" + <<makePackageTag(attribGroups[i])<<"\"/>"<<m_endl; + } + + if(hasSuperclass) + { + m_indentLevel--; + + if(hasAssociations || hasAttributes ) + XMLschema<<getIndent()<<"</"<<makeSchemaTag("extension")<<">"<<m_endl; + + m_indentLevel--; + XMLschema<<getIndent()<<"</"<<makeSchemaTag("complexContent")<<">"<<m_endl; + } + + // close this element decl + m_indentLevel--; + XMLschema<<getIndent()<<"</"<<makeSchemaTag("complexType")<<">"<<m_endl; + + } else + XMLschema<<"/>"<<m_endl; // empty node. just close this element decl + +} + +void XMLSchemaWriter::writeConcreteClassifier (UMLClassifier *c, QTextStream &XMLschema) +{ + + // preparations.. gather information about this classifier + // + UMLClassifierList superclasses = c->findSuperClassConcepts(); // list of what inherits from us + UMLClassifierList subclasses = c->findSubClassConcepts(); // list of what we inherit from + UMLAssociationList aggregations = c->getAggregations(); + UMLAssociationList compositions = c->getCompositions(); + // BAD! only way to get "general" associations. + UMLAssociationList associations = c->getSpecificAssocs(Uml::at_Association); + + // write the main declaration + writeComplexTypeClassifierDecl(c, associations, aggregations, compositions, superclasses, XMLschema); + + markAsWritten(c); + + // Now write out any child def's + writeChildObjsInAssociation(c, associations, XMLschema); + writeChildObjsInAssociation(c, aggregations, XMLschema); + writeChildObjsInAssociation(c, compositions, XMLschema); + + // write out any superclasses as needed + for(UMLClassifier *classifier = superclasses.first(); classifier; classifier = superclasses.next()) + writeClassifier(classifier, XMLschema); + + // write out any subclasses as needed + for(UMLClassifier *classifier = subclasses.first(); classifier; classifier = subclasses.next()) + writeClassifier(classifier, XMLschema); +} + +// these exist for abstract classes only (which become xs:group nodes) +QStringList XMLSchemaWriter::findAttributeGroups (UMLClassifier *c) +{ + // we need to look for any class we inherit from. IF these + // have attributes, then we need to notice + QStringList list; + UMLClassifierList superclasses = c->findSuperClassConcepts(); // list of what inherits from us + for(UMLClassifier *classifier = superclasses.first(); classifier; classifier = superclasses.next()) + { + if(classifier->getAbstract()) + { + // only classes have attributes.. + if (!classifier->isInterface()) { + UMLAttributeList attribs = c->getAttributeList(); + if (attribs.count() > 0) + list.append(getElementName(classifier)+"AttribGroupType"); + } + } + } + return list; +} + +bool XMLSchemaWriter::determineIfHasChildNodes( UMLClassifier *c) +{ + UMLObjectList aggList = findChildObjsInAssociations (c, c->getAggregations()); + UMLObjectList compList = findChildObjsInAssociations (c, c->getCompositions()); + UMLAssociationList associations = c->getSpecificAssocs(Uml::at_Association); // BAD! only way to get "general" associations. + UMLObjectList assocList = findChildObjsInAssociations (c, associations); + return aggList.count() > 0 || compList.count() > 0 || assocList.count() > 0; +} + +void XMLSchemaWriter::writeChildObjsInAssociation (UMLClassifier *c, + UMLAssociationList assoc, + QTextStream &XMLschema) +{ + + UMLObjectList list = findChildObjsInAssociations (c, assoc); + for(UMLObject * obj = list.first(); obj; obj = list.next()) + { + UMLClassifier * thisClassifier = dynamic_cast<UMLClassifier*>(obj); + if(thisClassifier) + writeClassifier(thisClassifier, XMLschema); + } +} + +bool XMLSchemaWriter::hasBeenWritten(UMLClassifier *c) { + if (writtenClassifiers.contains(c)) + return true; + else + return false; +} + +void XMLSchemaWriter::markAsWritten(UMLClassifier *c) { + writtenClassifiers.append(c); +} + +void XMLSchemaWriter::writeAttributeDecls(UMLAttributeList &attribs, QTextStream &XMLschema ) +{ + + UMLAttribute *at; + for(at=attribs.first(); at; at=attribs.next()) + { + writeAttributeDecl(at,XMLschema); + } + +} + +void XMLSchemaWriter::writeAttributeDecl(UMLAttribute *attrib, QTextStream &XMLschema ) +{ + + QString documentation = attrib->getDoc(); + QString typeName = fixTypeName(attrib->getTypeName()); + bool isStatic = attrib->getStatic(); + QString initialValue = fixInitialStringDeclValue(attrib->getInitialValue(), typeName); + + if(!documentation.isEmpty()) + writeComment(documentation, XMLschema); + + XMLschema<<getIndent()<<"<"<<makeSchemaTag("attribute") + <<" name=\""<<cleanName(attrib->getName())<<"\"" + <<" type=\""<<typeName<<"\""; + + // default value? + if(!initialValue.isEmpty()) + { + // IF its static, then we use "fixed", otherwise, we use "default" decl. + // For the default decl, we _must_ use "optional" decl + if(isStatic) + XMLschema<<" use=\"required\" fixed=\""<<initialValue<<"\""; + else + XMLschema<<" use=\"optional\" default=\""<<initialValue<<"\""; + } + + // finish decl + XMLschema<<"/>"<<m_endl; + +} + +void XMLSchemaWriter::writeAttributeGroupDecl (const QString &elementName, UMLAttributeList &attribs, QTextStream &XMLschema ) +{ + + if (attribs.count()> 0) { + + // write a little documentation + writeComment("attributes for element "+elementName,XMLschema); + + // open attribute group + XMLschema<<getIndent()<<"<"<<makeSchemaTag("attributeGroup")<<" name=\""<<elementName+"AttribGroupType"<<"\">"<<m_endl; + + m_indentLevel++; + + for( UMLAttribute *at=attribs.first(); at; at=attribs.next()) + { + writeAttributeDecl(at,XMLschema); + } + + m_indentLevel--; + + // close attrib group node + XMLschema<<getIndent()<<"</"<<makeSchemaTag("attributeGroup")<<">"<<m_endl; + } +} + +void XMLSchemaWriter::writeComment( const QString &comment, QTextStream &XMLschema ) +{ + // 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 + QString indent = getIndent(); + XMLschema<<indent<<"<!-- "; + if (comment.contains(QRegExp("\n"))) { + XMLschema<<m_endl; + QStringList lines = QStringList::split( "\n", comment); + for(uint i= 0; i < lines.count(); i++) + XMLschema<<indent<<" "<<lines[i]<<m_endl; + + XMLschema<<indent<<"-->"<<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 + XMLschema<<comment<<" -->"<<m_endl; + } +} + +// all that matters here is roleA, the role served by the children of this class +// in any composition or aggregation association. In full associations, I have only +// considered the case of "self" association, so it shouldn't matter if we use role A or +// B to find the child class as long as we don't use BOTH roles. I bet this will fail +// badly for someone using a plain association between 2 different classes. THAT should +// be done, but isnt yet (this is why I have left role b code in for now). -b.t. +bool XMLSchemaWriter::writeAssociationDecls(UMLAssociationList associations, + bool noRoleNameOK, bool didFirstOne, Uml::IDType id, QTextStream &XMLschema) +{ + + if( !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 && a->getVisibility(Uml::B) != Uml::Visibility::Private) + printRoleB = true; + + if (a->getObjectId(Uml::B) == id && a->getVisibility(Uml::A) != Uml::Visibility::Private) + 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(), XMLschema); + + // opening for sequence + if(!didFirstOne && (printRoleA || printRoleB)) + { + didFirstOne = true; + XMLschema<<getIndent()<<"<"<<makeSchemaTag("sequence")<<">"<<m_endl; + m_indentLevel++; + } + + // print RoleB decl + /* + // As mentioned in the header comment for this method: this block of code is + // commented out for now as it will only be needed if/when plain associations + // between different classes are to be treated + if (printRoleB) + { + UMLClassifier *classifierB = dynamic_cast<UMLClassifier*>(a->getObjectB()); + if (classifierB) { + // ONLY write out IF there is a rolename given + // otherwise its not meant to be declared + if (!a->getRoleNameB().isEmpty() || noRoleNameOK) + writeAssociationRoleDecl(classifierB, a->getMultiB(), XMLschema); + } + } + */ + + // print RoleA decl + if (printRoleA) + { + UMLClassifier *classifierA = dynamic_cast<UMLClassifier*>(a->getObject(Uml::A)); + if (classifierA) { + // ONLY write out IF there is a rolename given + // otherwise its not meant to be declared + if (!a->getRoleName(Uml::A).isEmpty() || noRoleNameOK ) + writeAssociationRoleDecl(classifierA, a->getMulti(Uml::A), XMLschema); + } + } + } + + } + + return didFirstOne; +} + +UMLObjectList XMLSchemaWriter::findChildObjsInAssociations (UMLClassifier *c, UMLAssociationList associations) +{ + Uml::IDType id = c->getID(); + UMLObjectList list; + for(UMLAssociation *a = associations.first(); a; a = associations.next()) + { + if (a->getObjectId(Uml::A) == id + && a->getVisibility(Uml::B) != Uml::Visibility::Private + && !a->getRoleName(Uml::B).isEmpty() + ) + list.append(a->getObject(Uml::B)); + + if (a->getObjectId(Uml::B) == id + && a->getVisibility(Uml::A) != Uml::Visibility::Private + && !a->getRoleName(Uml::A).isEmpty() + ) + list.append(a->getObject(Uml::A)); + } + return list; +} + +void XMLSchemaWriter::writeAssociationRoleDecl( UMLClassifier *c, const QString &multi, QTextStream &XMLschema) +{ + + bool isAbstract = c->getAbstract(); + bool isInterface = c->isInterface(); + + QString elementName = getElementName(c); + QString doc = c->getDoc(); + + if (!doc.isEmpty()) + writeComment(doc, XMLschema); + + + // Min/Max Occurs is based on whether it is this a single element + // or a List (maxoccurs>1). One day this will be done correctly with special + // multiplicity object that we don't have to figure out what it means via regex. + QString minOccurs = "0"; + QString maxOccurs = "unbounded"; + if (multi.isEmpty()) + { + // in this case, association will only specify ONE element can exist + // as a child + minOccurs = "1"; + maxOccurs = "1"; + } + else + { + QStringList values = QStringList::split( QRegExp("[^\\d{1,}|\\*]"), multi); + + // could use some improvement here.. for sequences like "0..1,3..5,10" we + // don't capture the whole "richness" of the multi. Instead we translate it + // now to minOccurs="0" maxOccurs="10" + if (values.count() > 0) + { + // populate both with the actual value as long as our value isnt an asterix + // In that case, use special value (from above) + if(values[0].contains(QRegExp("\\d{1,}"))) + minOccurs = values[0]; // use first number in sequence + + if(values[values.count()-1].contains(QRegExp("\\d{1,}"))) + maxOccurs = values[values.count()-1]; // use only last number in sequence + } + } + + // Now declare the class in the association as an element or group. + // + // In a semi-arbitrary way, we have decided to make abstract classes into + // "groups" and concrete classes into "complexTypes". + // + // This is because about the only thing you can do with an abstract + // class (err. node) is inherit from it with a "concrete" element. Therefore, + // in this manner, we need a group node for abstract classes to lay out the child + // element choices so that the child, concrete class may be plugged into whatever spot + // it parent could go. The tradeoff is that "group" nodes may not be extended, so the + // choices that you lay out here are it (e.g. no more nodes may inherit" from this group) + // + // The flipside for concrete classes is that we want to use them as elements in our document. + // Unfortunately, about all you can do with complexTypes in terms of inheritance, is to + // use these as the basis for a new node type. This is NOT full inheritence because the new + // class (err. element node) wont be able to go into the document where it parent went without + // you heavily editing the schema. + // + // Therefore, IF a group is abstract, but has no inheriting sub-classes, there are no choices, and its nigh + // on pointless to declare it as a group, in this special case, abstract classes get declared + // as complexTypes. + // + // Of course, in OO methodology, you should be able to inherit from + // any class, but schema just don't allow use to have full inheritence using either groups + // or complexTypes. Thus we have taken a middle rode. If someone wants to key me into a + // better way to represent this, I'd be happy to listen. =b.t. + // + // UPDATE: partial solution to the above: as of 13-Mar-2003 we now write BOTH a complexType + // AND a group declaration for interfaces AND classes which are inherited from. + // + if ((isAbstract || isInterface ) && c->findSubClassConcepts().count() > 0) + XMLschema<<getIndent()<<"<"<<makeSchemaTag("group") + <<" ref=\""<<makePackageTag(getElementGroupTypeName(c))<<"\""; + else + XMLschema<<getIndent()<<"<"<<makeSchemaTag("element") + <<" name=\""<<getElementName(c)<<"\"" + <<" type=\""<<makePackageTag(getElementTypeName(c))<<"\""; + + // min/max occurs + if (minOccurs != "1") + XMLschema<<" minOccurs=\""<<minOccurs<<"\""; + + if (maxOccurs != "1") + XMLschema<<" maxOccurs=\""<<maxOccurs<<"\""; + + // tidy up the node + XMLschema<<"/>"<<m_endl; + +} + +// IF the type is "string" we need to declare it as +// the XMLSchema Object "String" (there is no string primative in XMLSchema). +// Same thing again for "bool" to "boolean" +QString XMLSchemaWriter::fixTypeName(const QString& string) +{ + // string.replace(QRegExp("^string$"),schemaNamespaceTag+":string"); + // string.replace(QRegExp("^bool$"),schemaNamespaceTag+":boolean"); + return schemaNamespaceTag + ':' + string; +} + +QString XMLSchemaWriter::fixInitialStringDeclValue(QString value, const QString &type) +{ + // check for strings only + if (!value.isEmpty() && type == "xs:string") { + if (!value.startsWith("\"")) + value.remove(0,1); + if (!value.endsWith("\"")) + value.remove(value.length(),1); + } + return value; +} + +QString XMLSchemaWriter::getElementName(UMLClassifier *c) +{ + return cleanName(c->getName()); +} + +QString XMLSchemaWriter::getElementTypeName(UMLClassifier *c) +{ + QString elementName = getElementName(c); + return elementName + "ComplexType"; +} + +QString XMLSchemaWriter::getElementGroupTypeName(UMLClassifier *c) +{ + QString elementName = getElementName(c); + return elementName + "GroupType"; +} + +QString XMLSchemaWriter::makePackageTag (QString tagName) { + tagName.prepend( packageNamespaceTag + ':'); + return tagName; +} + +QString XMLSchemaWriter::makeSchemaTag (QString tagName) { + tagName.prepend( schemaNamespaceTag + ':'); + return tagName; +} + +const QStringList XMLSchemaWriter::reservedKeywords() const { + + static QStringList keywords; + + if (keywords.isEmpty()) { + keywords << "ATTLIST" + << "CDATA" + << "DOCTYPE" + << "ELEMENT" + << "ENTITIES" + << "ENTITY" + << "ID" + << "IDREF" + << "IDREFS" + << "NMTOKEN" + << "NMTOKENS" + << "NOTATION" + << "PUBLIC" + << "SHORTREF" + << "SYSTEM" + << "USEMAP"; + } + + return keywords; +} + +#include "xmlschemawriter.moc" diff --git a/umbrello/umbrello/codegenerators/xmlschemawriter.h b/umbrello/umbrello/codegenerators/xmlschemawriter.h new file mode 100644 index 00000000..caf9f906 --- /dev/null +++ b/umbrello/umbrello/codegenerators/xmlschemawriter.h @@ -0,0 +1,249 @@ +/*************************************************************************** + * * + * 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) 2003 Brian Thomas <brian.thomas@gsfc.nasa.gov> * + * copyright (C) 2004-2007 * + * Umbrello UML Modeller Authors <uml-devel@uml.sf.net> * + ***************************************************************************/ + +#ifndef XMLSCHEMAWRITER_H +#define XMLSCHEMAWRITER_H + +#include "../codegenerator.h" +#include "../attribute.h" +#include "../association.h" +#include "../umlclassifierlist.h" +#include "../umlattributelist.h" +#include "../umlobjectlist.h" +#include "../umlassociationlist.h" +#include "simplecodegenerator.h" + +/** + * Class XMLSchemaWriter is a code generator for UMLClassifier objects. + * Create an instance of this class, and feed it a UMLClassifier when + * calling writeClass and it will generate a XMLschema source file for + * that concept + * + * Our basic approach is to map UMLClassifiers (classes/interfaces) into + * XML elements (or nodes). We declare these element in the schema either + * as complexType or as groups based on whether they are concrete or abstract + * in nature. This is not a perfect decision, but thats life with XML Schema... + * you cant fully represent Objects in the XML world ..yet. -b.t. + */ + +class XMLSchemaWriter : public SimpleCodeGenerator +{ + Q_OBJECT +public: + + /** + * Constructor, initialises a couple of variables + */ + XMLSchemaWriter(); + + /** + * Destructor, empty + */ + virtual ~XMLSchemaWriter(); + + /** + * call this method to generate XMLschema code for a UMLClassifier + * @param c the class to generate code for + */ + virtual void writeClass(UMLClassifier *c); + + /** + * returns "XMLSchema" + */ + virtual Uml::Programming_Language getLanguage(); + + /** + * get list of reserved keywords + */ + virtual const QStringList reservedKeywords() const; + +private: + + /** + * Writes concept's documentation then guts + */ + void writeClassifier(UMLClassifier *c, QTextStream &XMLSchema); + void writeAbstractClassifier(UMLClassifier *c, QTextStream &XMLSchema); + void writeConcreteClassifier(UMLClassifier *c, QTextStream &XMLSchema); + + /** + * write a <complexType> declaration for this classifier + */ + void writeComplexTypeClassifierDecl(UMLClassifier *c, + UMLAssociationList associations, + UMLAssociationList aggregations, + UMLAssociationList compositions, + UMLClassifierList superclassifiers, + QTextStream &XMLSchema); + + /** + * write a <group> declaration for this classifier. Used for interfaces to classes with + * inheriting children. + */ + void writeGroupClassifierDecl(UMLClassifier *c, + UMLClassifierList superclassifiers, + QTextStream &XMLSchema); + + /** + * find if the classifier would have any Child elements. + */ + bool determineIfHasChildNodes( UMLClassifier *c); + + /** + * write all attributes for a given class + * @param c the class for which we are generating code + * @param j the stream associated with the output file + */ + void writeAttributes(UMLClassifier *c, QTextStream &j); + + /** + * write an element declaration. + */ + void writeElementDecl( const QString &elementName, const QString &elementTypeName, QTextStream &XMLschema); + + /** + * writes the Attribute declarations + * @param attribs List of attributes + * @param XMLschema text stream + */ + void writeAttributeDecls(UMLAttributeList &attribs, QTextStream &XMLschema ); + + /** + * write an element attribute. + */ + void writeAttributeDecl(UMLAttribute *attrib, QTextStream &XMLschema ); + + /** + * Find all attributes for this concept. + */ + UMLAttributeList findAttributes (UMLClassifier *c); + + /** + * Discover the string name of all the attribute groups (which are child nodes) + * of this concept (err.. element) + */ + QStringList findAttributeGroups (UMLClassifier *c); + + /** + * Searches a list of associations for appropriate ones to write out as attributes. + * This works well for compositions, aggregations and self-associations but will + * not work right for plain associations between 2 different classes. + */ + bool writeAssociationDecls(UMLAssociationList associations, bool noRoleOK, bool didOne, + Uml::IDType id, QTextStream &XMLschema); + + /** + * Find all attributes that belong in group + */ + void writeAttributeGroupDecl(const QString &elementName, UMLAttributeList &attribs, QTextStream &XMLschema ); + + /** + * Writes out an association as an attribute using Vector + */ + void writeAssociationRoleDecl(UMLClassifier *c, const QString &multi, QTextStream &XMLschema); + + /** + * Construct an element tag with the schema namespace + */ + QString makeSchemaTag ( QString tagName ); + + /** + * Construct an element tag with the package namespace + */ + QString makePackageTag ( QString tagName ); + + /** + * Writes a comment + */ + void writeComment(const QString &text, QTextStream &XMLschema); + + /** + * Find and return a list of child UMLObjects pointed to by the associations + * in this UMLClassifier. + */ + UMLObjectList findChildObjsInAssociations (UMLClassifier *c, UMLAssociationList associations); + + /** + * Replaces `string' with `String' and `bool' with `boolean' + */ + QString fixTypeName(const QString& string); + + /** + * check that initial values of strings DONT have quotes around them + * (we get double quoting then!! + */ + QString fixInitialStringDeclValue( QString value, const QString &type); + + /** + * Find the element node name for this concept. + */ + QString getElementName(UMLClassifier *c); + + /** + * Find the element node "type" name. Used in the "complexType" which + * might define that element node. + */ + QString getElementTypeName(UMLClassifier *c); + + /** + * Find the group node "type" name. Used for elements which define an interface/are abstract. + */ + QString getElementGroupTypeName(UMLClassifier *c); + + /** + * Find all the child objects in this association and make sure they get + * written out (if they havent already been) + */ + void writeChildObjsInAssociation (UMLClassifier *c, UMLAssociationList assoc, QTextStream &s); + + /** + * Quick check to see if we have written the declaration for this concept yet. + */ + bool hasBeenWritten(UMLClassifier *c); + + /** + * mark a concept as written, so it is not repeatedly re-declared in the schema + */ + void markAsWritten(UMLClassifier *c); + + /** + * The basic schemaNamespace tag + */ + QString schemaNamespaceTag; + + /** + * The basic schemaNamespace tag + */ + QString packageNamespaceTag; + + /* + * The basic schemaNamespace URI + */ + QString schemaNamespaceURI; + + /** + * The basic schemaNamespace URI + */ + QString packageNamespaceURI; + + /** + * A \n, used at the end of each line + */ + QString startline; + + /** + * a list of UMLClassifiers we have already written + */ + UMLClassifierList writtenClassifiers; +}; + +#endif // XMLSCHEMAWRITER_H |