/*************************************************************************** * * * 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 * ***************************************************************************/ /* This code generated by: * Author : thomas * Date : Thu Jun 19 2003 */ // own header #include "cppcodegenerator.h" // qt/kde includes #include #include #include // 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 ) { TQString 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 ) { TQString 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 ( TQWidget* parent, CodeDocument *doc, Settings::CodeViewerState state) { ClassifierCodeDocument * cdoc = dynamic_cast(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. TQString CPPCodeGenerator::fixTypeName(const TQString &string) { return cleanName(string); } // special method needed so that we write out the header code documents void CPPCodeGenerator::saveToXMI ( TQDomDocument & doc, TQDomElement & root ) { TQDomElement 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(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(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(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(); } TQStringList CPPCodeGenerator::defaultDatatypes() { return Codegen_Utils::cppDatatypes(); } const TQStringList CPPCodeGenerator::reservedKeywords() const { return Codegen_Utils::reservedCppKeywords(); } void CPPCodeGenerator::createDefaultStereotypes (){ Codegen_Utils::createCppStereotypes(); } #include "cppcodegenerator.moc"