// 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(QLatin1String("xmlDecl"), QString(), 0); xmlDecl->setText(QLatin1String("<?xml version=\"1.0\"?>")); addTextBlock(xmlDecl); XMLElementCodeBlock * rootNode = new XMLElementCodeBlock(this, QLatin1String("project"), QLatin1String("Java ANT build document")); rootNode->setTag(QLatin1String("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"/> */ }
void CPPSourceCodeDocument::updateContent( ) { // Gather info on the various fields and parent objects of this class... //UMLClassifier * c = getParentClassifier(); CodeGenPolicyExt *pe = UMLApp::app()->policyExt(); CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); QString endLine = UMLApp::app()->commonPolicy()->getNewLineEndingChars(); // first, set the global flag on whether or not to show classfield info const CodeClassFieldList * cfList = getCodeClassFieldList(); CodeClassFieldList::const_iterator it = cfList->begin(); CodeClassFieldList::const_iterator end = cfList->end(); for( ; it != end; ++it ) (*it)->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()->name() ); includeStatement.append("#include \""+CodeGenerator::cleanName(myOwnName.toLower())+".h\""+endLine); CodeBlockWithComments * iblock = addOrUpdateTaggedCodeBlockWithComments("includes", includeStatement, QString(), 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) m_constructorBlock = getHierarchicalCodeBlock("constructionMethodsBlock", "Constructors/Destructors", 0); m_methodsBlock = getHierarchicalCodeBlock("otherMethodsBlock", "Methods", 0); // add accessors to the methods block m_methodsBlock->addCodeClassFieldMethods(staticAttribClassFields); m_methodsBlock->addCodeClassFieldMethods(attribClassFields); m_methodsBlock->addCodeClassFieldMethods(plainAssocClassFields); m_methodsBlock->addCodeClassFieldMethods(aggregationClassFields); m_methodsBlock->addCodeClassFieldMethods(compositionClassFields); // constructors and other operations are handled by the "addCodeOperation" method above. }
/** * Need to overwrite this for ruby since we need to pick up the * ruby class declaration block. * 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 == QLatin1String("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 == QLatin1String("codecomment")) { CodeComment * block = new RubyCodeComment(this); block->loadFromXMI(element); if (!addTextBlock(block)) { uError()<<"loadFromXMI : unable to add codeComment to :"<<this; delete block; } else { loadCheckForChildrenOK= true; } } else if (name == QLatin1String("codeaccessormethod") || name == QLatin1String("ccfdeclarationcodeblock")) { QString acctag = element.attribute(QLatin1String("tag")); // search for our method in the TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag); if (!tb || !addTextBlock(tb)) { uError()<<"loadFromXMI : unable to add codeclassfield child method to:"<<this; // DON'T delete } else { loadCheckForChildrenOK= true; } } else if (name == QLatin1String("codeblock")) { CodeBlock * block = newCodeBlock(); block->loadFromXMI(element); if (!addTextBlock(block)) { uError()<<"loadFromXMI : unable to add codeBlock to :"<<this; delete block; } else { loadCheckForChildrenOK= true; } } else if (name == QLatin1String("codeblockwithcomments")) { CodeBlockWithComments * block = newCodeBlockWithComments(); block->loadFromXMI(element); if (!addTextBlock(block)) { uError()<<"loadFromXMI : unable to add codeBlockwithcomments to:"<<this; delete block; } else { loadCheckForChildrenOK= true; } } else if (name == QLatin1String("header")) { // do nothing.. this is treated elsewhere } else if (name == QLatin1String("hierarchicalcodeblock")) { HierarchicalCodeBlock * block = newHierarchicalCodeBlock(); block->loadFromXMI(element); if (!addTextBlock(block)) { uError()<<"Unable to add hierarchicalcodeBlock to:"<<this; delete block; } else { loadCheckForChildrenOK= true; } } else if (name == QLatin1String("codeoperation")) { // find the code operation by id QString id = element.attribute(QLatin1String("parent_id"), QLatin1String("-1")); UMLObject * obj = UMLApp::app()->document()->findObjectById(Uml::ID::fromString(id)); UMLOperation * op = dynamic_cast<UMLOperation*>(obj); if (op) { CodeOperation * block = new RubyCodeOperation(this, op); block->loadFromXMI(element); if (addTextBlock(block)) { loadCheckForChildrenOK= true; } else { uError()<<"Unable to add codeoperation to:"<<this; block->deleteLater(); } } else { uError()<<"Unable to find operation create codeoperation for:"<<this; } } else if (name == QLatin1String("rubyclassdeclarationblock")) { RubyClassDeclarationBlock * block = getClassDecl(); block->loadFromXMI(element); if (!addTextBlock(block)) { uError()<<"Unable to add ruby code declaration block to:"<<this; // DON'T delete. // block->deleteLater(); } else { loadCheckForChildrenOK= true; } } else { uDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignoring"; } node = element.nextSibling(); element = node.toElement(); } break; } tnode = telement.nextSibling(); telement = tnode.toElement(); } if (!loadCheckForChildrenOK) { CodeDocument * test = dynamic_cast<CodeDocument*>(this); if (test) { uWarning()<<" loadChildBlocks : unable to initialize any child blocks in doc: "<<test->getFileName()<<" "<<this; } else { HierarchicalCodeBlock * hb = dynamic_cast<HierarchicalCodeBlock*>(this); if (hb) uWarning()<<" loadChildBlocks : unable to initialize any child blocks in Hblock: "<<hb->getTag()<<" "<<this; else uDebug()<<" loadChildBlocks : unable to initialize any child blocks in UNKNOWN OBJ:"<<this; } } }
// 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 == QLatin1String("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 == QLatin1String("codecomment")) { CodeComment * block = new CPPCodeDocumentation(this); block->loadFromXMI(element); if(!addTextBlock(block)) { uError()<<"Unable to add codeComment to :"<<this; delete block; } else loadCheckForChildrenOK= true; } else if(name == QLatin1String("codeaccessormethod") || name == QLatin1String("ccfdeclarationcodeblock")) { QString acctag = element.attribute(QLatin1String("tag")); // search for our method in the TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag); if(!tb || !addTextBlock(tb)) { uError()<<"Unable to add codeclassfield child method to:"<<this; // DON'T delete } else loadCheckForChildrenOK= true; } else if(name == QLatin1String("codeblock")) { CodeBlock * block = newCodeBlock(); block->loadFromXMI(element); if(!addTextBlock(block)) { uError()<<"Unable to add codeBlock to :"<<this; delete block; } else loadCheckForChildrenOK= true; } else if(name == QLatin1String("codeblockwithcomments")) { CodeBlockWithComments * block = newCodeBlockWithComments(); block->loadFromXMI(element); if(!addTextBlock(block)) { uError()<<"Unable to add codeBlockwithcomments to:"<<this; delete block; } else loadCheckForChildrenOK= true; } else if(name == QLatin1String("header")) { // do nothing.. this is treated elsewhere } else if(name == QLatin1String("hierarchicalcodeblock")) { HierarchicalCodeBlock * block = newHierarchicalCodeBlock(); block->loadFromXMI(element); if(!addTextBlock(block)) { uError()<<"Unable to add hierarchicalcodeBlock to:"<<this; delete block; } else loadCheckForChildrenOK= true; } else if(name == QLatin1String("codeoperation")) { // find the code operation by id QString id = element.attribute(QLatin1String("parent_id"),QLatin1String("-1")); UMLObject * obj = UMLApp::app()->document()->findObjectById(Uml::ID::fromString(id)); UMLOperation * op = dynamic_cast<UMLOperation*>(obj); if(op) { CodeOperation * block = new CPPHeaderCodeOperation(this, op); block->updateMethodDeclaration(); block->updateContent(); block->loadFromXMI(element); if(addTextBlock(block)) loadCheckForChildrenOK= true; else { uError()<<"Unable to add codeoperation to:"<<this; block->deleteLater(); } } else uError()<<"Unable to find operation create codeoperation for:"<<this; } else if(name == QLatin1String("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. m_namespaceBlock = getHierarchicalCodeBlock(QLatin1String("namespace"), QLatin1String("Namespace"), 0); if(!m_namespaceBlock || !m_namespaceBlock->addTextBlock(block)) { uError()<<"Error:cant add class declaration codeblock"; // DON'T delete/release block // block->release(); } else loadCheckForChildrenOK= true; } // only needed for extreme debugging conditions (E.g. making new codeclassdocument loader) //else //uDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignorning"; node = element.nextSibling(); element = node.toElement(); } break; } tnode = telement.nextSibling(); telement = tnode.toElement(); } if(!loadCheckForChildrenOK) { uWarning() << "loadChildBlocks : unable to initialize any child blocks in doc: " << getFileName() << " " << this; } }
// 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(); Q_ASSERT(c != NULL); CodeGenPolicyExt *pe = UMLApp::app()->policyExt(); CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe); // first, set the global flag on whether or not to show classfield info const CodeClassFieldList * cfList = getCodeClassFieldList(); CodeClassFieldList::const_iterator it = cfList->begin(); CodeClassFieldList::const_iterator end = cfList->end(); for(; it != end; ++it) (*it)->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 = false; UMLOperationList list = c->getOpList(); hasOperationMethods = ! list.isEmpty(); bool hasNamespace = false; bool isEnumeration = false; bool isInterface = parentIsInterface(); bool hasclassFields = hasClassFields(); bool forcedoc = UMLApp::app()->commonPolicy()->getCodeVerboseDocumentComments(); QString endLine = UMLApp::app()->commonPolicy()->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->name()); QString hashDefine = CodeGenerator::cleanName(c->name().toUpper().simplified()); QString defText = QLatin1String("#ifndef ") + hashDefine + QLatin1String("_H") + endLine + QLatin1String("#define ") + hashDefine + QLatin1String("_H"); addOrUpdateTaggedCodeBlockWithComments(QLatin1String("hashDefBlock"), defText, QString(), 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 ? QLatin1String("<") : QLatin1String("\""); QString sEndBrak = stringGlobal ? QLatin1String(">") : QLatin1String("\""); includeStatement.append(QLatin1String("#include ") + sStartBrak + policy->getStringClassNameInclude() + sEndBrak + endLine); if (hasObjectVectorClassFields()) { bool vecGlobal = policy->vectorIncludeIsGlobal(); QString vStartBrak = vecGlobal ? QLatin1String("<") : QLatin1String("\""); QString vEndBrak = vecGlobal ? QLatin1String(">") : QLatin1String("\""); QString value =QLatin1String("#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); foreach(UMLPackage* con, includes) { if (con->baseType() != UMLObject::ot_Datatype && !packageMap.contains(con)) { packageMap.insert(con, con->package()); if(con != getParentClassifier()) includeStatement.append(QLatin1String("#include \"") + CodeGenerator::cleanName(con->name().toLower()) + QLatin1String(".h\"") + endLine); } } // now, add/update the includes codeblock CodeBlockWithComments * inclBlock = addOrUpdateTaggedCodeBlockWithComments(QLatin1String("includes"), includeStatement, QString(), 0, false); if(includeStatement.isEmpty() && inclBlock->contentType() == CodeBlock::AutoGenerated) inclBlock->setWriteOutText(false); else inclBlock->setWriteOutText(true); // Using QString usingStatement; foreach(UMLClassifier* classifier, superclasses) { if(classifier->package()!=c->package() && !classifier->package().isEmpty()) { usingStatement.append(QLatin1String("using ") + CodeGenerator::cleanName(c->package()) + QLatin1String("::") + cleanName(c->name()) + QLatin1Char(';') + endLine); } } CodeBlockWithComments * usingBlock = addOrUpdateTaggedCodeBlockWithComments(QLatin1String("using"), usingStatement, QString(), 0, false); if(usingStatement.isEmpty() && usingBlock->contentType() == 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->umlPackage() && policy->getPackageIsNamespace()) hasNamespace = true; else hasNamespace = false; // set start/end text of namespace block m_namespaceBlock = getHierarchicalCodeBlock(QLatin1String("namespace"), QLatin1String("Namespace"), 0); if(hasNamespace) { UMLPackageList pkgList = c->packages(); QString pkgs; UMLPackage *pkg; foreach (pkg, pkgList) { pkgs += QLatin1String("namespace ") + CodeGenerator::cleanName(pkg->name()) + QLatin1String(" { "); } m_namespaceBlock->setStartText(pkgs); QString closingBraces; foreach (pkg, pkgList) { closingBraces += QLatin1String("} "); }
// 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); }
// 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 == QLatin1String("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 == QLatin1String("codecomment")) { CodeComment * block = new XMLCodeComment(this); block->loadFromXMI(element); if (!addTextBlock(block)) { uError()<<"Unable to add codeComment to :"<<this; delete block; } else loadCheckForChildrenOK= true; } else if (name == QLatin1String("codeaccessormethod") || name == QLatin1String("ccfdeclarationcodeblock")) { QString acctag = element.attribute(QLatin1String("tag")); // search for our method in the TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag); if (!tb || !addTextBlock(tb)) { uError()<<"Unable to add codeclassfield child method to:"<<this; // DON'T delete } else { loadCheckForChildrenOK= true; } } else if (name == QLatin1String("codeblock")) { CodeBlock * block = newCodeBlock(); block->loadFromXMI(element); if (!addTextBlock(block)) { uError()<<"Unable to add codeBlock to :"<<this; delete block; } else { loadCheckForChildrenOK= true; } } else if (name == QLatin1String("codeblockwithcomments")) { CodeBlockWithComments * block = newCodeBlockWithComments(); block->loadFromXMI(element); if (!addTextBlock(block)) { uError()<<"Unable to add codeBlockwithcomments to:"<<this; delete block; } else { loadCheckForChildrenOK= true; } } else if (name == QLatin1String("header")) { // do nothing.. this is treated elsewhere } else if (name == QLatin1String("hierarchicalcodeblock")) { HierarchicalCodeBlock * block = newHierarchicalCodeBlock(); block->loadFromXMI(element); if (!addTextBlock(block)) { uError()<<"Unable to add hierarchicalcodeBlock to:"<<this; delete block; } else { loadCheckForChildrenOK= true; } } else if (name == QLatin1String("codeoperation")) { // find the code operation by id QString id = element.attribute(QLatin1String("parent_id"),QLatin1String("-1")); UMLObject * obj = UMLApp::app()->document()->findObjectById(Uml::ID::fromString(id)); UMLOperation * op = obj->asUMLOperation(); if (op) { CodeOperation * block = 0; uError() << "TODO: implement CodeGenFactory::newCodeOperation() for JavaANTCodeDocument"; break; // remove when above is implemented block->loadFromXMI(element); if (addTextBlock(block)) { loadCheckForChildrenOK= true; } else { uError()<<"Unable to add codeoperation to:"<<this; block->deleteLater(); } } else { uError()<<"Unable to find operation create codeoperation for:"<<this; } } else if (name == QLatin1String("xmlelementblock")) { QString xmltag = element.attribute(QLatin1String("nodeName"),QLatin1String("UNKNOWN")); XMLElementCodeBlock * block = new XMLElementCodeBlock(this, xmltag); block->loadFromXMI(element); if (!addTextBlock(block)) { uError()<<"Unable to add XMLelement to Java ANT document:"<<this; delete block; } else { loadCheckForChildrenOK= true; } } else { uDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignoring"; } node = element.nextSibling(); element = node.toElement(); } break; } tnode = telement.nextSibling(); telement = tnode.toElement(); } if (!loadCheckForChildrenOK) { uWarning() << " loadChildBlocks : unable to initialize any child blocks in doc: " << getFileName() << " " << this; } }
// 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 DClassifierCodeDocument::updateContent() { // Gather info on the various fields and parent objects of this class... UMLClassifier * c = getParentClassifier(); Q_ASSERT(c != 0); CodeGenerationPolicy * commonPolicy = UMLApp::app()->commonPolicy(); CodeGenPolicyExt * pe = UMLApp::app()->policyExt(); DCodeGenerationPolicy * policy = dynamic_cast<DCodeGenerationPolicy*>(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 const CodeClassFieldList * cfList = getCodeClassFieldList(); CodeClassFieldList::const_iterator it = cfList->begin(); CodeClassFieldList::const_iterator end = cfList->end(); for (; it != end; ++it) { CodeClassField * field = *it; 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 = false; UMLOperationList list = c->getOpList(); hasOperationMethods = ! list.isEmpty(); 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(QLatin1String("::")), QLatin1String(".")); QString packageText = getPackage().isEmpty() ? QString() : QString(QLatin1String("package ")+pkgs+QLatin1Char(';')+endLine); CodeBlockWithComments * pblock = addOrUpdateTaggedCodeBlockWithComments(QLatin1String("packages"), packageText, QString(), 0, false); if (packageText.isEmpty() && pblock->contentType() == CodeBlock::AutoGenerated) pblock->setWriteOutText(false); else pblock->setWriteOutText(true); // IMPORT CODEBLOCK // // Q: Why all utils? Aren't just List and Vector the only classes we are using? // A: doesn't matter at all; it is more readable to just include '*' and d compilers // don't slow down or anything. (TZ) QString importStatement; if (hasObjectVectorClassFields()) importStatement.append(QLatin1String("import d.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 (UMLPackageListIt importsIt(imports); importsIt.hasNext();) { UMLPackage *con = importsIt.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->isUMLDatatype()) { packageMap.insert(con, con->package()); // 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->package() != c->package() || (c->package().isEmpty() && con->package().isEmpty())) { importStatement.append(endLine+QLatin1String("import ")); if (!con->package().isEmpty()) importStatement.append(con->package()+QLatin1Char('.')); importStatement.append(CodeGenerator::cleanName(con->name())+QLatin1Char(';')); } } } // now, add/update the imports codeblock CodeBlockWithComments * iblock = addOrUpdateTaggedCodeBlockWithComments(QLatin1String("imports"), importStatement, QString(), 0, false); if (importStatement.isEmpty() && iblock->contentType() == CodeBlock::AutoGenerated) iblock->setWriteOutText(false); else iblock->setWriteOutText(true); // CLASS DECLARATION BLOCK // // get the declaration block. If it is not already present, add it too DClassDeclarationBlock * 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 d 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 d 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(QLatin1String("fieldsDecl"), QLatin1String("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(QLatin1String("methodsBlock"), QLatin1String("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(QLatin1String("constructorMethods"), QLatin1String("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()->commonPolicy(); if (!forceDoc() && (isInterface || !pol->getAutoGenerateConstructors())) constComment->setWriteOutText(false); else constComment->setWriteOutText(true); // add/get the empty constructor QString DClassName = getDClassName(c->name()); QString emptyConstStatement = QLatin1String("public ")+DClassName+QLatin1String(" () { }"); CodeBlockWithComments * emptyConstBlock = constBlock->addOrUpdateTaggedCodeBlockWithComments(QLatin1String("emptyconstructor"), emptyConstStatement, QLatin1String("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(QLatin1String("accessorMethods"), QLatin1String("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(QLatin1String("staticAccessorMethods"), QString(), 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(QLatin1String("regularAccessorMethods"), QString(), 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(QLatin1String("operationMethods"), QLatin1String("Operations"), 1); // set conditions for showing section comment CodeComment * ocomment = operationsBlock->getComment(); if (!forceDoc() && !hasOperationMethods) ocomment->setWriteOutText(false); else ocomment->setWriteOutText(true); }