1 /*
2     SPDX-License-Identifier: GPL-2.0-or-later
3 
4     SPDX-FileCopyrightText: 2003 Brian Thomas <thomas@mail630.gsfc.nasa.gov>
5     SPDX-FileCopyrightText: 2004-2020 Umbrello UML Modeller Authors <umbrello-devel@kde.org>
6 */
7 
8 // own header
9 #include "cppheadercodedocument.h"
10 
11 // local includes
12 #include "cppcodegenerator.h"
13 #include "cppcodegenerationpolicy.h"
14 #include "cppcodedocumentation.h"
15 #include "cppheadercodeaccessormethod.h"
16 #include "cppheadercodeoperation.h"
17 #include "cppheaderclassdeclarationblock.h"
18 #include "cppheadercodeclassfielddeclarationblock.h"
19 #include "debug_utils.h"
20 #include "umlpackagelist.h"
21 #include "package.h"
22 #include "umlclassifierlistitemlist.h"
23 #include "classifierlistitem.h"
24 #include "enum.h"
25 #include "uml.h"
26 
27 // qt includes
28 #include <QRegExp>
29 
30 /**
31  * Constructor.
32  */
CPPHeaderCodeDocument(UMLClassifier * concept)33 CPPHeaderCodeDocument::CPPHeaderCodeDocument(UMLClassifier* concept)
34   : ClassifierCodeDocument(concept)
35 {
36     setFileExtension(QLatin1String(".h"));
37 
38     //initCodeClassFields(); // this is dubious because it calls down to
39                              // CodeGenFactory::newCodeClassField(this)
40                              // but "this" is still in construction at that time.
41 
42     m_classDeclCodeBlock = 0;
43     m_publicBlock = 0;
44     m_protectedBlock = 0;
45     m_privateBlock = 0;
46     m_namespaceBlock = 0;
47     m_pubConstructorBlock = 0;
48     m_protConstructorBlock = 0;
49     m_privConstructorBlock = 0;
50     m_pubOperationsBlock = 0;
51     m_privOperationsBlock = 0;
52     m_protOperationsBlock = 0;
53 
54     // this will call updateContent() as well as other things that sync our document.
55     //synchronize();
56 }
57 
58 /**
59  * Destructor.
60  */
~CPPHeaderCodeDocument()61 CPPHeaderCodeDocument::~CPPHeaderCodeDocument()
62 {
63     resetTextBlocks();
64 }
65 
getClassDecl()66 CPPHeaderClassDeclarationBlock * CPPHeaderCodeDocument::getClassDecl()
67 {
68     if(!m_classDeclCodeBlock) {
69         m_classDeclCodeBlock = new CPPHeaderClassDeclarationBlock (this); // was deleted before our load
70         m_classDeclCodeBlock->updateContent();
71         m_classDeclCodeBlock->setTag(QLatin1String("classDeclarationBlock"));
72     }
73     return m_classDeclCodeBlock;
74 }
75 
76 // Sigh. NOT optimal. The only reason that we need to have this
77 // is so we can create the CPPHeaderClassDeclarationBlock.
78 // would be better if we could create a handler interface that each
79 // codeblock used so all we have to do here is add the handler
loadChildTextBlocksFromNode(QDomElement & root)80 void CPPHeaderCodeDocument::loadChildTextBlocksFromNode (QDomElement & root)
81 {
82     QDomNode tnode = root.firstChild();
83     QDomElement telement = tnode.toElement();
84     bool loadCheckForChildrenOK = false;
85     while(!telement.isNull()) {
86         QString nodeName = telement.tagName();
87 
88         if(nodeName == QLatin1String("textblocks")) {
89 
90             QDomNode node = telement.firstChild();
91             QDomElement element = node.toElement();
92 
93             // if there is nothing to begin with, then we don't worry about it
94             loadCheckForChildrenOK = element.isNull() ? true : false;
95 
96             while(!element.isNull()) {
97                 QString name = element.tagName();
98 
99                 if(name == QLatin1String("codecomment")) {
100                     CodeComment * block = new CPPCodeDocumentation(this);
101                     block->loadFromXMI1(element);
102                     if(!addTextBlock(block))
103                     {
104                         uError()<<"Unable to add codeComment to :"<<this;
105                         delete block;
106                     } else
107                         loadCheckForChildrenOK= true;
108                 } else
109                     if(name == QLatin1String("codeaccessormethod") ||
110                             name == QLatin1String("ccfdeclarationcodeblock")) {
111                         QString acctag = element.attribute(QLatin1String("tag"));
112                         // search for our method in the
113                         TextBlock * tb = findCodeClassFieldTextBlockByTag(acctag);
114                         if(!tb || !addTextBlock(tb))
115                         {
116                             uError()<<"Unable to add codeclassfield child method to:"<<this;
117                             // DON'T delete
118                         } else
119                             loadCheckForChildrenOK= true;
120 
121                     } else
122                         if(name == QLatin1String("codeblock")) {
123                             CodeBlock * block = newCodeBlock();
124                             block->loadFromXMI1(element);
125                             if(!addTextBlock(block))
126                             {
127                                 uError()<<"Unable to add codeBlock to :"<<this;
128                                 delete block;
129                             } else
130                                 loadCheckForChildrenOK= true;
131                         } else
132                             if(name == QLatin1String("codeblockwithcomments")) {
133                                 CodeBlockWithComments * block = newCodeBlockWithComments();
134                                 block->loadFromXMI1(element);
135                                 if(!addTextBlock(block))
136                                 {
137                                     uError()<<"Unable to add codeBlockwithcomments to:"<<this;
138                                     delete block;
139                                 } else
140                                     loadCheckForChildrenOK= true;
141                             } else
142                                 if(name == QLatin1String("header")) {
143                                     // do nothing.. this is treated elsewhere
144                                 } else
145                                     if(name == QLatin1String("hierarchicalcodeblock")) {
146                                         HierarchicalCodeBlock * block = newHierarchicalCodeBlock();
147                                         block->loadFromXMI1(element);
148                                         if(!addTextBlock(block))
149                                         {
150                                             uError()<<"Unable to add hierarchicalcodeBlock to:"<<this;
151                                             delete block;
152                                         } else
153                                             loadCheckForChildrenOK= true;
154                                     } else
155                                         if(name == QLatin1String("codeoperation")) {
156                                             // find the code operation by id
157                                             QString id = element.attribute(QLatin1String("parent_id"),QLatin1String("-1"));
158                                             UMLObject * obj = UMLApp::app()->document()->findObjectById(Uml::ID::fromString(id));
159                                             UMLOperation * op = obj->asUMLOperation();
160                                             if(op) {
161                                                 CodeOperation * block = new CPPHeaderCodeOperation(this, op);
162                                                 block->updateMethodDeclaration();
163                                                 block->updateContent();
164                                                 block->loadFromXMI1(element);
165                                                 if(addTextBlock(block))
166                                                     loadCheckForChildrenOK= true;
167                                                 else
168                                                 {
169                                                     uError()<<"Unable to add codeoperation to:"<<this;
170                                                     block->deleteLater();
171                                                 }
172                                             } else
173                                                 uError()<<"Unable to find operation create codeoperation for:"<<this;
174                                         }
175                                         else
176                                             if(name == QLatin1String("cppheaderclassdeclarationblock"))
177                                             {
178                                                 CPPHeaderClassDeclarationBlock * block = getClassDecl();
179                                                 block->loadFromXMI1(element);
180                                                 // normally this would be populated by the following syncToparent
181                                                 // call, but we cant wait for it, so lets just do it now.
182                                                 m_namespaceBlock = getHierarchicalCodeBlock(QLatin1String("namespace"), QLatin1String("Namespace"), 0);
183 
184                                                 if(!m_namespaceBlock || !m_namespaceBlock->addTextBlock(block))
185                                                 {
186                                                     uError()<<"Error:cant add class declaration codeblock";
187                                                     // DON'T delete/release block
188                                                     // block->release();
189                                                 } else
190                                                     loadCheckForChildrenOK= true;
191 
192                                             }
193                 // only needed for extreme debugging conditions (E.g. making new codeclassdocument loader)
194                 //else
195                 //uDebug()<<" LoadFromXMI: Got strange tag in text block stack:"<<name<<", ignoring";
196 
197                 node = element.nextSibling();
198                 element = node.toElement();
199             }
200             break;
201         }
202 
203         tnode = telement.nextSibling();
204         telement = tnode.toElement();
205     }
206 
207     if(!loadCheckForChildrenOK)
208     {
209         uWarning() << "loadChildBlocks : unable to initialize any child blocks in doc: " << getFileName() << " " << this;
210     }
211 
212 }
213 
resetTextBlocks()214 void CPPHeaderCodeDocument::resetTextBlocks()
215 {
216     // all special pointers need to be zero'd out.
217     if (m_classDeclCodeBlock) {
218         delete m_classDeclCodeBlock;
219         m_classDeclCodeBlock = 0;
220     }
221     if (m_publicBlock) {
222         delete m_publicBlock;
223         m_publicBlock = 0;
224     }
225     if (m_protectedBlock) {
226         delete m_protectedBlock;
227         m_protectedBlock = 0;
228     }
229     if (m_privateBlock) {
230         delete m_privateBlock;
231         m_privateBlock = 0;
232     }
233     if (m_namespaceBlock) {
234         delete m_namespaceBlock;
235         m_namespaceBlock = 0;
236     }
237     if (m_pubConstructorBlock) {
238         delete m_pubConstructorBlock;
239         m_pubConstructorBlock = 0;
240     }
241     if (m_protConstructorBlock) {
242         delete m_protConstructorBlock;
243         m_protConstructorBlock = 0;
244     }
245     if (m_privConstructorBlock) {
246         delete m_privConstructorBlock;
247         m_privConstructorBlock = 0;
248     }
249     if (m_pubOperationsBlock) {
250         delete m_pubOperationsBlock;
251         m_pubOperationsBlock = 0;
252     }
253     if (m_privOperationsBlock) {
254         delete m_privOperationsBlock;
255         m_privOperationsBlock = 0;
256     }
257     if (m_protOperationsBlock) {
258         delete m_protOperationsBlock;
259         m_protOperationsBlock = 0;
260     }
261 
262     // now do the traditional release of child text blocks
263     ClassifierCodeDocument::resetTextBlocks();
264 }
265 
266 /**
267  * Add a code operation to this cpp classifier code document.
268  * In the vanilla version, we just tack all operations on the end
269  * of the document.
270  * @param op   the code operation
271  * @return bool which is true IF the code operation was added successfully
272  */
addCodeOperation(CodeOperation * op)273 bool CPPHeaderCodeDocument::addCodeOperation(CodeOperation* op)
274 {
275     if (op == 0) {
276         uDebug() << "CodeOperation is null!";
277         return false;;
278     }
279     Uml::Visibility::Enum scope = op->getParentOperation()->visibility();
280     if(!op->getParentOperation()->isLifeOperation())
281     {
282         switch (scope) {
283         default:
284         case Uml::Visibility::Public:
285             return (m_pubOperationsBlock == 0 ? false : m_pubOperationsBlock->addTextBlock(op));
286             break;
287         case Uml::Visibility::Protected:
288             return (m_protOperationsBlock == 0 ? false : m_protOperationsBlock->addTextBlock(op));
289             break;
290         case Uml::Visibility::Private:
291             return (m_privOperationsBlock == 0 ? false : m_privOperationsBlock->addTextBlock(op));
292             break;
293         }
294     } else {
295         switch (scope) {
296         default:
297         case Uml::Visibility::Public:
298             return (m_pubConstructorBlock == 0 ? false : m_pubConstructorBlock->addTextBlock(op));
299             break;
300         case Uml::Visibility::Protected:
301             return (m_protConstructorBlock == 0 ? false : m_protConstructorBlock->addTextBlock(op));
302             break;
303         case Uml::Visibility::Private:
304             return (m_privConstructorBlock == 0 ? false : m_privConstructorBlock->addTextBlock(op));
305             break;
306         }
307     }
308 }
309 
310 /**
311  * Save the XMI representation of this object
312  * @return      bool    status of save
313  */
314 /*
315 void CPPHeaderCodeDocument::saveToXMI1(QXmlStreamWriter& writer)
316 {
317         writer.writeEmptyStartElement();
318 
319         setAttributesOnNode(writer);
320 
321         writer.writeEndElement();
322 }
323 */
324 
325 // This method will cause the class to rebuild its text representation.
326 // based on the parent classifier object.
327 // For any situation in which this is called, we are either building the code
328 // document up, or replacing/regenerating the existing auto-generated parts. As
329 // such, we will want to insert everything we reasonably will want
330 // during creation. We can set various parts of the document (esp. the
331 // comments) to appear or not, as needed.
updateContent()332 void CPPHeaderCodeDocument::updateContent()
333 {
334     // Gather info on the various fields and parent objects of this class...
335     UMLClassifier * c = getParentClassifier();
336     Q_ASSERT(c != 0);
337     CodeGenPolicyExt *pe = UMLApp::app()->policyExt();
338     CPPCodeGenerationPolicy * policy = dynamic_cast<CPPCodeGenerationPolicy*>(pe);
339 
340     // first, set the global flag on whether or not to show classfield info
341     const CodeClassFieldList * cfList = getCodeClassFieldList();
342     CodeClassFieldList::const_iterator it = cfList->begin();
343     CodeClassFieldList::const_iterator end = cfList->end();
344     for(; it != end; ++it)
345         (*it)->setWriteOutMethods(policy->getAutoGenerateAccessors());
346 
347     // attribute-based ClassFields
348     // we do it this way to have the static fields sorted out from regular ones
349     CodeClassFieldList staticPublicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Public);
350     CodeClassFieldList publicAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Public);
351     CodeClassFieldList staticProtectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Protected);
352     CodeClassFieldList protectedAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Protected);
353     CodeClassFieldList staticPrivateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, true, Uml::Visibility::Private);
354     CodeClassFieldList privateAttribClassFields = getSpecificClassFields (CodeClassField::Attribute, false, Uml::Visibility::Private);
355 
356     // association-based ClassFields
357     // don't care if they are static or not..all are lumped together
358     CodeClassFieldList publicPlainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation, Uml::Visibility::Public);
359     CodeClassFieldList publicAggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation, Uml::Visibility::Public);
360     CodeClassFieldList publicCompositionClassFields = getSpecificClassFields (CodeClassField::Composition, Uml::Visibility::Public);
361 
362     CodeClassFieldList protPlainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation, Uml::Visibility::Protected);
363     CodeClassFieldList protAggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation, Uml::Visibility::Protected);
364     CodeClassFieldList protCompositionClassFields = getSpecificClassFields (CodeClassField::Composition, Uml::Visibility::Protected);
365 
366     CodeClassFieldList privPlainAssocClassFields = getSpecificClassFields (CodeClassField::PlainAssociation, Uml::Visibility::Private);
367     CodeClassFieldList privAggregationClassFields = getSpecificClassFields (CodeClassField::Aggregation, Uml::Visibility::Private);
368     CodeClassFieldList privCompositionClassFields = getSpecificClassFields (CodeClassField::Composition, Uml::Visibility::Private);
369 
370     bool hasOperationMethods = false;
371     UMLOperationList list = c->getOpList();
372     hasOperationMethods = ! list.isEmpty();
373 
374     bool hasNamespace = false;
375     bool isEnumeration = false;
376     bool isInterface = parentIsInterface();
377     bool hasclassFields = hasClassFields();
378     bool forcedoc = UMLApp::app()->commonPolicy()->getCodeVerboseDocumentComments();
379     QString endLine = UMLApp::app()->commonPolicy()->getNewLineEndingChars();
380 
381     UMLClassifierList superclasses = c->findSuperClassConcepts();
382 
383 
384     // START GENERATING CODE/TEXT BLOCKS and COMMENTS FOR THE DOCUMENT
385     //
386 
387     // Write the hash define stuff to prevent multiple parsing/inclusion of header
388     QString cppClassName = CodeGenerator::cleanName(c->name());
389     QString hashDefine = CodeGenerator::cleanName(c->name().toUpper().simplified());
390     QString defText = QLatin1String("#ifndef ") + hashDefine + QLatin1String("_H") + endLine + QLatin1String("#define ") + hashDefine + QLatin1String("_H");
391     addOrUpdateTaggedCodeBlockWithComments(QLatin1String("hashDefBlock"), defText, QString(), 0, false);
392 
393     // INCLUDE CODEBLOCK
394     //
395     // Q: Why all utils? Isnt just List and Vector the only classes we are using?
396     // A: doesn't matter at all; its more readable to just include '*' and cpp compilers
397     //    don't slow down or anything. (TZ)
398     QString includeStatement;
399     bool stringGlobal = policy->stringIncludeIsGlobal();
400     QString sStartBrak = stringGlobal ? QLatin1String("<") : QLatin1String("\"");
401     QString sEndBrak = stringGlobal ? QLatin1String(">") : QLatin1String("\"");
402     includeStatement.append(QLatin1String("#include ") + sStartBrak + policy->getStringClassNameInclude() + sEndBrak + endLine);
403     if (hasObjectVectorClassFields())
404     {
405         bool vecGlobal = policy->vectorIncludeIsGlobal();
406         QString vStartBrak = vecGlobal ? QLatin1String("<") : QLatin1String("\"");
407         QString vEndBrak = vecGlobal ? QLatin1String(">") : QLatin1String("\"");
408         QString value =QLatin1String("#include ") + vStartBrak + policy->getVectorClassNameInclude() + vEndBrak;
409         includeStatement.append(value + endLine);
410     }
411 
412     //only include classes in a different package from this class
413     UMLPackageList includes;
414     QMap<UMLPackage *, QString> packageMap; // so we don't repeat packages
415 
416     CodeGenerator::findObjectsRelated(c, includes);
417     foreach(UMLPackage* con, includes) {
418         if (!con->isUMLDatatype() && !packageMap.contains(con)) {
419             packageMap.insert(con, con->package());
420             if(con != getParentClassifier())
421                 includeStatement.append(QLatin1String("#include \"") + CodeGenerator::cleanName(con->name().toLower()) + QLatin1String(".h\"") + endLine);
422         }
423     }
424     // now, add/update the includes codeblock
425     CodeBlockWithComments * inclBlock = addOrUpdateTaggedCodeBlockWithComments(QLatin1String("includes"), includeStatement, QString(), 0, false);
426     if(includeStatement.isEmpty() && inclBlock->contentType() == CodeBlock::AutoGenerated)
427         inclBlock->setWriteOutText(false);
428     else
429         inclBlock->setWriteOutText(true);
430 
431     // Using
432     QString usingStatement;
433     foreach(UMLClassifier* classifier, superclasses) {
434         if(classifier->package()!=c->package() && !classifier->package().isEmpty()) {
435             usingStatement.append(QLatin1String("using ") + CodeGenerator::cleanName(c->package()) + QLatin1String("::") + cleanName(c->name()) + QLatin1Char(';') + endLine);
436         }
437     }
438     CodeBlockWithComments * usingBlock = addOrUpdateTaggedCodeBlockWithComments(QLatin1String("using"), usingStatement, QString(), 0, false);
439     if(usingStatement.isEmpty() && usingBlock->contentType() == CodeBlock::AutoGenerated)
440         usingBlock->setWriteOutText(false);
441     else
442         usingBlock->setWriteOutText(true);
443 
444     // namespace
445     // This needs special treatment. We cant use "nowriteouttext" for this, as
446     // that will prevent the class declaration from being written. Instead, we
447     // check if "hasNamspace" is true or not, and then indent the remaining code
448     // appropriately as well as set the start/end text of this namespace block.
449     if (c->umlPackage() && policy->getPackageIsNamespace())
450         hasNamespace = true;
451     else
452         hasNamespace = false;
453 
454     // set start/end text of namespace block
455     m_namespaceBlock = getHierarchicalCodeBlock(QLatin1String("namespace"), QLatin1String("Namespace"), 0);
456     if(hasNamespace) {
457         UMLPackageList pkgList = c->packages();
458         QString pkgs;
459         UMLPackage *pkg;
460         foreach (pkg, pkgList) {
461             pkgs += QLatin1String("namespace ") + CodeGenerator::cleanName(pkg->name()) + QLatin1String(" { ");
462         }
463         m_namespaceBlock->setStartText(pkgs);
464         QString closingBraces;
465         foreach (pkg, pkgList) {
466             closingBraces += QLatin1String("} ");
467         }
468         m_namespaceBlock->setEndText(closingBraces);
469         m_namespaceBlock->getComment()->setWriteOutText(true);
470     } else {
471         m_namespaceBlock->setStartText(QString());
472         m_namespaceBlock->setEndText(QString());
473         m_namespaceBlock->getComment()->setWriteOutText(false);
474     }
475 
476     // Enum types for include
477     if (!isInterface) {
478         QString enumStatement;
479         QString indent = UMLApp::app()->commonPolicy()->getIndentation();
480         UMLEnum* e = c->asUMLEnum();
481         if (e) {
482             enumStatement.append(indent + QLatin1String("enum ") + cppClassName + QLatin1String(" {") + endLine);
483 
484             // populate
485             UMLClassifierListItemList ell = e->getFilteredList(UMLObject::ot_EnumLiteral);
486             for (UMLClassifierListItemListIt elit(ell) ; elit.hasNext() ;) {
487                 UMLClassifierListItem* el = elit.next();
488                 enumStatement.append(indent + indent);
489                 enumStatement.append(CodeGenerator::cleanName(el->name()));
490                 if (elit.hasNext()) {
491                     el=elit.next();
492                     enumStatement.append(QLatin1String(", ") + endLine);
493                 } else {
494                     break;
495                 }
496                 enumStatement.append(endLine);
497             }
498             enumStatement.append(indent + QLatin1String("};"));
499             isEnumeration = true;
500         }
501         m_namespaceBlock->addOrUpdateTaggedCodeBlockWithComments(QLatin1String("enums"), enumStatement, QString(), 0, false);
502     }
503 
504     // CLASS DECLARATION BLOCK
505     //
506 
507     // add the class declaration block to the namespace block.
508     CPPHeaderClassDeclarationBlock * myClassDeclCodeBlock = getClassDecl();
509     m_namespaceBlock->addTextBlock(myClassDeclCodeBlock); // note: wont add if already present
510 
511     // Is this really true?? hmm..
512     if(isEnumeration)
513         myClassDeclCodeBlock->setWriteOutText(false); // not written out IF its an enumeration class
514     else
515         myClassDeclCodeBlock->setWriteOutText(true);
516 
517     //
518     // Main Sub-Blocks
519     //
520 
521     // declare public, protected and private methods, attributes (fields).
522     // set the start text ONLY if this is the first time we created the objects.
523     bool createdPublicBlock = m_publicBlock == 0 ? true : false;
524     m_publicBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock(QLatin1String("publicBlock"),QLatin1String("Public stuff"), 0);
525     if (createdPublicBlock)
526         m_publicBlock->setStartText(QLatin1String("public:"));
527 
528     bool createdProtBlock = m_protectedBlock == 0 ? true : false;
529     m_protectedBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock(QLatin1String("protectedBlock"),QLatin1String("Protected stuff"), 0);
530     if(createdProtBlock)
531         m_protectedBlock->setStartText(QLatin1String("protected:"));
532 
533     bool createdPrivBlock = m_privateBlock == 0 ? true : false;
534     m_privateBlock = myClassDeclCodeBlock->getHierarchicalCodeBlock(QLatin1String("privateBlock"),QLatin1String("Private stuff"), 0);
535     if(createdPrivBlock)
536         m_privateBlock->setStartText(QLatin1String("private:"));
537 
538     //
539     // * CLASS FIELD declaration section
540     //
541 
542     // setup/get/create the field declaration code block
543     //
544 
545     // public fields: Update the comment: we only set comment to appear under the following conditions
546     HierarchicalCodeBlock * publicFieldDeclBlock = m_publicBlock->getHierarchicalCodeBlock(QLatin1String("publicFieldsDecl"), QLatin1String("Fields"), 1);
547     CodeComment * pubFcomment = publicFieldDeclBlock->getComment();
548     if (!forcedoc && !hasclassFields)
549         pubFcomment->setWriteOutText(false);
550     else
551         pubFcomment->setWriteOutText(true);
552 
553     // protected fields: Update the comment: we only set comment to appear under the following conditions
554     HierarchicalCodeBlock * protectedFieldDeclBlock = m_protectedBlock->getHierarchicalCodeBlock(QLatin1String("protectedFieldsDecl"), QLatin1String("Fields"), 1);
555     CodeComment * protFcomment = protectedFieldDeclBlock->getComment();
556     if (!forcedoc && !hasclassFields)
557         protFcomment->setWriteOutText(false);
558     else
559         protFcomment->setWriteOutText(true);
560 
561     // private fields: Update the comment: we only set comment to appear under the following conditions
562     HierarchicalCodeBlock * privateFieldDeclBlock = m_privateBlock->getHierarchicalCodeBlock(QLatin1String("privateFieldsDecl"), QLatin1String("Fields"), 1);
563     CodeComment * privFcomment = privateFieldDeclBlock->getComment();
564     if (!forcedoc && !hasclassFields)
565         privFcomment->setWriteOutText(false);
566     else
567         privFcomment->setWriteOutText(true);
568 
569 
570     // now actually declare the fields within the appropriate HCodeBlock
571     //
572 
573     // public
574     declareClassFields(staticPublicAttribClassFields, publicFieldDeclBlock);
575     declareClassFields(publicAttribClassFields, publicFieldDeclBlock);
576     declareClassFields(publicPlainAssocClassFields, publicFieldDeclBlock);
577     declareClassFields(publicAggregationClassFields, publicFieldDeclBlock);
578     declareClassFields(publicCompositionClassFields, publicFieldDeclBlock);
579 
580     // protected
581     declareClassFields(staticProtectedAttribClassFields, protectedFieldDeclBlock);
582     declareClassFields(protectedAttribClassFields, protectedFieldDeclBlock);
583     declareClassFields(protPlainAssocClassFields, protectedFieldDeclBlock);
584     declareClassFields(protAggregationClassFields, protectedFieldDeclBlock);
585     declareClassFields(protCompositionClassFields, protectedFieldDeclBlock);
586 
587     // private
588     declareClassFields(staticPrivateAttribClassFields, privateFieldDeclBlock);
589     declareClassFields(privateAttribClassFields, privateFieldDeclBlock);
590     declareClassFields(privPlainAssocClassFields, privateFieldDeclBlock);
591     declareClassFields(privAggregationClassFields, privateFieldDeclBlock);
592     declareClassFields(privCompositionClassFields, privateFieldDeclBlock);
593 
594     //
595     // METHODS section
596     //
597 
598     // get/create the method codeblock
599 
600     // public methods
601     HierarchicalCodeBlock * pubMethodsBlock = m_publicBlock->getHierarchicalCodeBlock(QLatin1String("pubMethodsBlock"), QString(), 1);
602     CodeComment * pubMethodsComment = pubMethodsBlock->getComment();
603     // set conditions for showing this comment
604     if (!forcedoc && !hasclassFields && !hasOperationMethods)
605         pubMethodsComment->setWriteOutText(false);
606     else
607         pubMethodsComment->setWriteOutText(true);
608 
609     // protected methods
610     HierarchicalCodeBlock * protMethodsBlock = m_protectedBlock->getHierarchicalCodeBlock(QLatin1String("protMethodsBlock"), QString(), 1);
611     CodeComment * protMethodsComment = protMethodsBlock->getComment();
612     // set conditions for showing this comment
613     if (!forcedoc && !hasclassFields && !hasOperationMethods)
614         protMethodsComment->setWriteOutText(false);
615     else
616         protMethodsComment->setWriteOutText(true);
617 
618     // private methods
619     HierarchicalCodeBlock * privMethodsBlock = m_privateBlock->getHierarchicalCodeBlock(QLatin1String("privMethodsBlock"), QString(), 1);
620     CodeComment * privMethodsComment = privMethodsBlock->getComment();
621     // set conditions for showing this comment
622     if (!forcedoc && !hasclassFields && !hasOperationMethods)
623         privMethodsComment->setWriteOutText(false);
624     else
625         privMethodsComment->setWriteOutText(true);
626 
627 
628     // METHODS sub-section : constructor methods
629     //
630     CodeGenerationPolicy *pol = UMLApp::app()->commonPolicy();
631 
632     // setup/get/create the constructor codeblocks
633 
634     // public
635     m_pubConstructorBlock = pubMethodsBlock->getHierarchicalCodeBlock(QLatin1String("constructionMethods"), QLatin1String("Constructors"), 1);
636     // special conditions for showing comment: only when autogenerateding empty constructors
637     // Although, we *should* check for other constructor methods too
638     CodeComment * pubConstComment = m_pubConstructorBlock->getComment();
639     if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors()))
640         pubConstComment->setWriteOutText(false);
641     else
642         pubConstComment->setWriteOutText(true);
643 
644     // protected
645     m_protConstructorBlock = protMethodsBlock->getHierarchicalCodeBlock(QLatin1String("constructionMethods"), QLatin1String("Constructors"), 1);
646     // special conditions for showing comment: only when autogenerateding empty constructors
647     // Although, we *should* check for other constructor methods too
648     CodeComment * protConstComment = m_protConstructorBlock->getComment();
649     if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors()))
650         protConstComment->setWriteOutText(false);
651     else
652         protConstComment->setWriteOutText(true);
653 
654     // private
655     m_privConstructorBlock = privMethodsBlock->getHierarchicalCodeBlock(QLatin1String("constructionMethods"), QLatin1String("Constructors"), 1);
656     // special conditions for showing comment: only when autogenerateding empty constructors
657     // Although, we *should* check for other constructor methods too
658     CodeComment * privConstComment = m_privConstructorBlock->getComment();
659     if (!forcedoc && (isInterface || !pol->getAutoGenerateConstructors()))
660         privConstComment->setWriteOutText(false);
661     else
662         privConstComment->setWriteOutText(true);
663 
664     // add/get the empty constructor. I guess since there is no
665     // meta-data to state what the scope of this method is, we will make it
666     // "public" as a default. This might present problems if the user wants
667     // to move the block into the "private" or "protected" blocks.
668     QString emptyConstStatement = cppClassName + QLatin1String(" () { }");
669 
670     // search for this first in the entire document. IF not present, put
671     // it in the public constructor method block
672     TextBlock * emptyConstTb = findTextBlockByTag(QLatin1String("emptyconstructor"), true);
673     CodeBlockWithComments * emptyConstBlock = dynamic_cast<CodeBlockWithComments*>(emptyConstTb);
674     if(!emptyConstBlock)
675         emptyConstBlock = m_pubConstructorBlock->addOrUpdateTaggedCodeBlockWithComments(QLatin1String("emptyconstructor"), emptyConstStatement, QLatin1String("Empty Constructor"), 1, false);
676 
677     // Now, as an additional condition we only show the empty constructor block
678     // IF it was desired to be shown
679     if(!isInterface && pol->getAutoGenerateConstructors())
680         emptyConstBlock->setWriteOutText(true);
681     else
682         emptyConstBlock->setWriteOutText(false);
683 
684 
685     // METHODS subsection : ACCESSOR METHODS
686     //
687 
688     // get/create the accessor codeblock
689 
690     // public
691     HierarchicalCodeBlock * pubAccessorBlock = pubMethodsBlock->getHierarchicalCodeBlock(QLatin1String("accessorMethods"), QLatin1String("Accessor Methods"), 1);
692     // set conditions for showing section comment
693     CodeComment * pubAccessComment = pubAccessorBlock->getComment();
694     if (!forcedoc && !hasclassFields)
695         pubAccessComment->setWriteOutText(false);
696     else
697         pubAccessComment->setWriteOutText(true);
698 
699     // protected
700     HierarchicalCodeBlock * protAccessorBlock = protMethodsBlock->getHierarchicalCodeBlock(QLatin1String("accessorMethods"), QLatin1String("Accessor Methods"), 1);
701     // set conditions for showing section comment
702     CodeComment * protAccessComment = protAccessorBlock->getComment();
703     if (!forcedoc && !hasclassFields)
704         protAccessComment->setWriteOutText(false);
705     else
706         protAccessComment->setWriteOutText(true);
707 
708     // private
709     HierarchicalCodeBlock * privAccessorBlock = privMethodsBlock->getHierarchicalCodeBlock(QLatin1String("accessorMethods"), QLatin1String("Accessor Methods"), 1);
710     // set conditions for showing section comment
711     CodeComment * privAccessComment = privAccessorBlock->getComment();
712     // We've to copy the private accessorMethods to the public block
713     if (!forcedoc && !hasclassFields)
714         privAccessComment->setWriteOutText(false);
715     else
716         privAccessComment->setWriteOutText(true);
717 
718     // now, 2 sub-sub sections in accessor block
719     // add/update accessor methods for attributes
720     HierarchicalCodeBlock * pubStaticAccessors = pubAccessorBlock->getHierarchicalCodeBlock(QLatin1String("pubStaticAccessorMethods"), QString(), 1);
721     HierarchicalCodeBlock * pubRegularAccessors = pubAccessorBlock->getHierarchicalCodeBlock(QLatin1String("pubRegularAccessorMethods"), QString(), 1);
722     pubStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
723     pubRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
724 
725     HierarchicalCodeBlock * protStaticAccessors = protAccessorBlock->getHierarchicalCodeBlock(QLatin1String("protStaticAccessorMethods"), QString(), 1);
726     HierarchicalCodeBlock * protRegularAccessors = protAccessorBlock->getHierarchicalCodeBlock(QLatin1String("protRegularAccessorMethods"), QString(), 1);
727     protStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
728     protRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
729 
730     HierarchicalCodeBlock * privStaticAccessors = privAccessorBlock->getHierarchicalCodeBlock(QLatin1String("privStaticAccessorMethods"), QString(), 1);
731     HierarchicalCodeBlock * privRegularAccessors = privAccessorBlock->getHierarchicalCodeBlock(QLatin1String("privRegularAccessorMethods"), QString(), 1);
732     privStaticAccessors->getComment()->setWriteOutText(false); // never write block comment
733     privRegularAccessors->getComment()->setWriteOutText(false); // never write block comment
734 
735     // now add in accessors as appropriate
736 
737     // public stuff
738     pubStaticAccessors->addCodeClassFieldMethods(staticPublicAttribClassFields);
739     pubRegularAccessors->addCodeClassFieldMethods(publicAttribClassFields);
740 
741     // generate accessors as public
742     if (policy && policy->getAccessorsArePublic())
743     {
744         pubRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields);
745         pubRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields);
746     }
747 
748     pubRegularAccessors->addCodeClassFieldMethods(publicPlainAssocClassFields);
749     pubRegularAccessors->addCodeClassFieldMethods(publicAggregationClassFields);
750     pubRegularAccessors->addCodeClassFieldMethods(publicCompositionClassFields);
751 
752     // protected stuff
753     protStaticAccessors->addCodeClassFieldMethods(staticProtectedAttribClassFields);
754 
755     // accessors are public so we don't have to create it here
756     if (policy && !policy->getAccessorsArePublic())
757         protRegularAccessors->addCodeClassFieldMethods(protectedAttribClassFields);
758 
759     protRegularAccessors->addCodeClassFieldMethods(protPlainAssocClassFields);
760     protRegularAccessors->addCodeClassFieldMethods(protAggregationClassFields);
761     protRegularAccessors->addCodeClassFieldMethods(protCompositionClassFields);
762 
763     // private stuff
764     privStaticAccessors->addCodeClassFieldMethods(staticPrivateAttribClassFields);
765 
766     // accessors are public so we don't have to create it here
767     if (policy && !policy->getAccessorsArePublic())
768         privRegularAccessors->addCodeClassFieldMethods(privateAttribClassFields);
769 
770     privRegularAccessors->addCodeClassFieldMethods(privPlainAssocClassFields);
771     privRegularAccessors->addCodeClassFieldMethods(privAggregationClassFields);
772     privRegularAccessors->addCodeClassFieldMethods(privCompositionClassFields);
773 
774 
775     // METHODS subsection : Operation methods (e.g. methods derive from operations but which arent constructors)
776     //
777 
778     // setup/get/create the operations codeblock
779 
780     // public
781     m_pubOperationsBlock = pubMethodsBlock->getHierarchicalCodeBlock(QLatin1String("operationMethods"), QLatin1String("Operations"), 1);
782     // set conditions for showing section comment
783     CodeComment * pubOcomment = m_pubOperationsBlock->getComment();
784     if (!forcedoc && !hasOperationMethods)
785         pubOcomment->setWriteOutText(false);
786     else
787         pubOcomment->setWriteOutText(true);
788 
789     //protected
790     m_protOperationsBlock = protMethodsBlock->getHierarchicalCodeBlock(QLatin1String("operationMethods"), QLatin1String("Operations"), 1);
791     // set conditions for showing section comment
792     CodeComment * protOcomment = m_protOperationsBlock->getComment();
793     if (!forcedoc && !hasOperationMethods)
794         protOcomment->setWriteOutText(false);
795     else
796         protOcomment->setWriteOutText(true);
797 
798     //private
799     m_privOperationsBlock = privMethodsBlock->getHierarchicalCodeBlock(QLatin1String("operationMethods"), QLatin1String("Operations"), 1);
800     // set conditions for showing section comment
801     CodeComment * privOcomment = m_privOperationsBlock->getComment();
802     if (!forcedoc && !hasOperationMethods)
803         privOcomment->setWriteOutText(false);
804     else
805         privOcomment->setWriteOutText(true);
806 
807     // Operations
808     //
809     // nothing to do here.. "updateOperations" in parent class puts things
810     // in the right place using the "addCodeOperation" method we defined in this class
811 
812     // FINISH up with hash def block close
813     QString defTextEnd = QLatin1String("#endif //") + hashDefine + QLatin1String("_H");
814     addOrUpdateTaggedCodeBlockWithComments(QLatin1String("hashDefBlockEnd"), defTextEnd, QString(), 0, false);
815 }
816 
817