1 /*
2 This file is part of dia2code. It generates code from an UML Dia Diagram.
3 Copyright (C) 2000-2014 Javier O'Hara - Oliver Kellogg
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
20 /* NB: If you use CORBA stereotypes, you will need the file p_orb.h
21 found in the runtime/cpp directory. */
22
23 #include "config.h"
24
25 #include <iostream>
26 #include <cassert>
27 #include <algorithm>
28
29 #if defined(_WIN32) || defined(_WIN64)
30 #include <direct.h>
31 #else
32 #include <sys/stat.h>
33 #endif
34
35 #include "GenerateCode.hpp"
36 #include "scan_tree.hpp"
37 #include "string2.hpp"
38
39 #define eq !strcmp
40
GenerateCode(DiaGram & diagram,const char * ext,uint8_t version_,bool handleIncludePackage_,bool noLoopSupport_)41 GenerateCode::GenerateCode (DiaGram & diagram,
42 const char * ext,
43 uint8_t version_,
44 bool handleIncludePackage_,
45 bool noLoopSupport_) :
46 dia (diagram),
47 license (),
48 outdir ("."),
49 file_ext (ext),
50 file (),
51 version (version_),
52 indent (4),
53 indentlevel (0),
54 overwrite (true),
55 buildtree (false),
56 bOpenBraceOnNewline (false),
57 oneClassOneHeader (false),
58 handleIncludePackage (handleIncludePackage_),
59 noLoopSupport (noLoopSupport_)
60 #ifdef ENABLE_CORBA
61 , isCorba (false)
62 #endif
63 {
64 }
65
66
67 DiaGram &
getDia()68 GenerateCode::getDia () {
69 return dia;
70 }
71
72
73 const std::string &
getLicense() const74 GenerateCode::getLicense () const {
75 return license;
76 }
77
78
79 void
setLicense(const char * lic)80 GenerateCode::setLicense (const char * lic) {
81 license.assign (lic);
82 }
83
84
85 const char *
getOutdir() const86 GenerateCode::getOutdir () const {
87 return outdir.c_str ();
88 }
89
90
91 const std::string *
getOutdirS() const92 GenerateCode::getOutdirS () const {
93 return &outdir;
94 }
95
96
97 void
setOutdir(const char * dir)98 GenerateCode::setOutdir (const char * dir) {
99 outdir.assign (dir);
100 }
101
102
103 bool
getOverwrite() const104 GenerateCode::getOverwrite () const {
105 return overwrite;
106 }
107
108
109 void
setOverwrite(bool over)110 GenerateCode::setOverwrite (bool over) {
111 overwrite = over;
112 }
113
114
115 bool
getBuildTree() const116 GenerateCode::getBuildTree () const {
117 return buildtree;
118 }
119
120
121 void
setBuildTree(bool build)122 GenerateCode::setBuildTree (bool build) {
123 if (build) {
124 oneClassOneHeader = true;
125 }
126 buildtree = build;
127
128 return;
129 }
130
131
132 bool
getOpenBraceOnNewline() const133 GenerateCode::getOpenBraceOnNewline () const {
134 return bOpenBraceOnNewline;
135 }
136
137
138 void
setOpenBraceOnNewline(bool newline)139 GenerateCode::setOpenBraceOnNewline (bool newline) {
140 bOpenBraceOnNewline = newline;
141 }
142
143 bool
getOneClass() const144 GenerateCode::getOneClass () const {
145 return oneClassOneHeader;
146 }
147
148
149 void
setOneClass(bool value)150 GenerateCode::setOneClass (bool value) {
151 oneClassOneHeader = value;
152 }
153
154 void
setHandleIncludePackage(bool val)155 GenerateCode::setHandleIncludePackage (bool val) {
156 handleIncludePackage = val;
157 }
158
159
160 #ifdef ENABLE_CORBA
161 bool
getCorba() const162 GenerateCode::getCorba () const {
163 return isCorba;
164 }
165 #endif
166
167 void
openOutfile(const std::string & filename,declaration & d)168 GenerateCode::openOutfile (const std::string & filename, declaration & d) {
169 static std::string outfilename;
170 std::string tmpname;
171
172 outfilename.assign (outdir);
173 outfilename.append (1, SEPARATOR);
174 outfilename.append (filename);
175 outfilename.append (".");
176 outfilename.append (getFileExt ());
177
178 std::ifstream f (outfilename.c_str ());
179
180 if ((f.good ()) && (!overwrite)) {
181 f.close();
182 throw std::string ("Overwrite " + outfilename + " is forbidden.\n");
183 }
184 else {
185 f.close();
186 }
187
188 file.push_back (new std::ofstream ());
189 file.back ()->open (outfilename.c_str ());
190 if (!file.back ()->is_open ()) {
191 file.back ()->close ();
192 throw std::string ("Failed to create " + outfilename + ".\n");
193 }
194
195 tmpname = strtoupper (filename);
196 assert (indentlevel == 0);
197 writeStartHeader (tmpname);
198
199 writeLicense ();
200
201 getDia ().cleanIncludes ();
202 getDia ().determineIncludes (d, !handleIncludePackage, noLoopSupport);
203 #ifdef ENABLE_CORBA
204 if (getDia ().getUseCorba ()) {
205 writeInclude ("p_orb.h");
206 getFile () << "\n";
207 }
208 #endif
209
210 if (d.decl_kind == dk_class) {
211 writeBeforeInclude (d.u.this_class);
212 }
213 writeInclude (getDia ().getIncludes ());
214 if (d.decl_kind == dk_class) {
215 writeAfterInclude (d.u.this_class);
216 }
217
218 return;
219 }
220
221 void
closeOutfile()222 GenerateCode::closeOutfile () {
223 writeEndHeader ();
224 assert (indentlevel == 0);
225 file.back ()->close ();
226 delete file.back ();
227 file.pop_back ();
228 }
229
230 void
generate_code()231 GenerateCode::generate_code () {
232 std::list <declaration>::iterator it2;
233 std::list <umlClassNode *> tmplist = getDia ().getUml ();
234
235 for (umlClassNode * it : tmplist) {
236 if (!it->isPushed ()) {
237 getDia ().push (it);
238 }
239 }
240
241 // Generate a file for each outer declaration.
242 it2 = getDia ().getDeclBegin ();
243 while (it2 != getDia ().getDeclEnd ()) {
244 if (it2->decl_kind == dk_class) {
245 if ((getDia ().getGenClasses ().empty ()) ||
246 (isPresent (getDia ().getGenClasses (),
247 it2->u.this_class->getName ().c_str ()) ^
248 getDia ().getInvertSel ())) {
249 genDecl (*it2, true);
250 }
251 }
252 else {
253 genDecl (*it2, true);
254 }
255
256 ++it2;
257 }
258 }
259
260 const char *
getFileExt() const261 GenerateCode::getFileExt () const {
262 return file_ext.c_str ();
263 }
264
265
266 void
setFileExt(const char * ext)267 GenerateCode::setFileExt (const char * ext) {
268 file_ext.assign (ext);
269 }
270
271
272 const char *
getBodyFileExt() const273 GenerateCode::getBodyFileExt () const {
274 return body_file_ext.c_str ();
275 }
276
277
278 void
setBodyFileExt(const char * ext)279 GenerateCode::setBodyFileExt (const char * ext) {
280 body_file_ext.assign (ext);
281 }
282
283
284 std::ofstream &
getFile()285 GenerateCode::getFile () {
286 return *file.back ();
287 }
288
289 char *
subst(char * str,const char search,char replace)290 subst (char *str, const char search, char replace) {
291 char *p;
292 while ((p = strchr (str, search)) != NULL) {
293 *p = replace;
294 }
295 return str;
296 }
297
298 char *
nospc(char * str)299 nospc (char *str) {
300 return subst (str, ' ', '_');
301 }
302
303 bool
passByReference(umlClass & cl) const304 GenerateCode::passByReference (umlClass & cl) const {
305 if (cl.isStereotypeTypedef ()) {
306 umlClassNode *ref = findByName (dia.getUml (),
307 cl.getName ().c_str ());
308 if (ref == NULL) {
309 return false;
310 }
311 return passByReference (*ref);
312 }
313 return (!cl.isStereotypeConst () &&
314 !cl.isStereotypeEnum ());
315 }
316
317 #ifdef ENABLE_CORBA
318 static bool
isOoClass(umlClass & cl)319 isOoClass (umlClass &cl) {
320 const char *st;
321 st = cl.getStereotype ().c_str ();
322 if (strlen (st) == 0) {
323 return true;
324 }
325 return (!isConstStereo (st) &&
326 !isTypedefStereo (st) &&
327 !isEnumStereo (st) &&
328 !isStructStereo (st) &&
329 !eq (st, "CORBAUnion") &&
330 !eq (st, "CORBAException"));
331 }
332 #endif
333
334 const char *
cppName(std::string name)335 GenerateCode::cppName (std::string name) {
336 static std::string buf;
337 #ifdef ENABLE_CORBA
338 if (dia.getUseCorba ()) {
339 if (name.compare ("boolean") == 0 || name.compare ("char") == 0 || name.compare ("octet") == 0 ||
340 name.compare ("short") == 0 ||
341 name.compare ("long") == 0 ||
342 name.compare ("float") == 0 ||
343 name.compare ("double") == 0 ||
344 name.compare ("string") == 0 ||
345 name.compare ("any") == 0) {
346 buf.assign (strPackage ("CORBA"));
347 buf.append (nospc (const_cast <char *> (
348 strtoupperfirst (name).c_str ())));
349 }
350 else if (name.compare ("long long") == 0) {
351 buf.assign (strPackage ("CORBA"));
352 buf.append ("LongLong");
353 }
354 else if (name.compare ("unsigned short") == 0) {
355 buf.assign (strPackage ("CORBA"));
356 buf.append ("UShort");
357 }
358 else if (name.compare ("unsigned long") == 0) {
359 buf.assign (strPackage ("CORBA"));
360 buf.append ("ULong");
361 }
362 else if (name.compare ("unsigned long long") == 0) {
363 buf.assign (strPackage ("CORBA"));
364 buf.append ("ULongLong");
365 }
366 else {
367 buf.assign (name);
368 }
369 } else
370 #endif
371 {
372 buf.assign (name);
373 }
374 return buf.c_str ();
375 }
376
377 const char *
fqname(const umlClassNode & node,bool use_ref_type) const378 GenerateCode::fqname (const umlClassNode &node, bool use_ref_type) const {
379 static std::string buf;
380
381 buf.clear ();
382 if (node.getPackage () != NULL) {
383 std::list <umlPackage *> pkglist;
384
385 umlPackage::makePackageList (node.getPackage (), pkglist);
386 for (const umlPackage * it : pkglist) {
387 buf.append (strPackage (it->getName ().c_str ()));
388 }
389 }
390 if (use_ref_type) {
391 buf.append (strPointer (node.getName ()));
392 }
393 else {
394 buf.append (node.getName ());
395 }
396 return buf.c_str ();
397 }
398
399 void
genClass(const umlClassNode & node)400 GenerateCode::genClass (const umlClassNode & node) {
401 #ifdef ENABLE_CORBA
402 const char *name = node.getName ().c_str ();
403 #endif
404 Visibility tmpv = Visibility::IMPLEMENTATION;
405
406 if (node.getName ().empty ()) {
407 std::cerr << "A class have an empty name.\n";
408 }
409
410 #ifdef ENABLE_CORBA
411 isCorba = node.isStereotypeCorba ();
412 #endif
413
414 // Check that if class is abstract, at least one class are abstract.
415 if (node.isAbstract ()) {
416 bool absok = false;
417
418 for (const umlOperation & umlo : node.getOperations ()) {
419 if (umlo.getInheritance () == Inheritance::ABSTRACT) {
420 absok = true;
421 }
422 }
423
424 if ((!absok) && (!node.getOperations ().empty ())) {
425 std::cerr << "Class " << fqname (node, false)
426 << " is abstract but no operation is defined as abstract.\n";
427 }
428 }
429
430 writeClassComment (node.getComment ());
431 writeClassStart (node);
432 incIndentLevel ();
433
434 if (!node.getAssociations ().empty ()) {
435 writeComment ("Associations");
436 for (const umlassoc & assoc : node.getAssociations ()) {
437 writeAssociation (node, assoc, tmpv);
438 }
439 }
440
441 if (!node.getAttributes ().empty ()) {
442 #ifdef ENABLE_CORBA
443 if (isCorba) {
444 writeComment ("Public state members");
445 getFile () << spc () << "public:\n";
446 incIndentLevel ();
447 for (const umlAttribute & umla : node.getAttributes ()) {
448 const char *member = umla.getName ().c_str ();
449 umlClassNode *ref;
450 if (umla.getVisibility () != '0') {
451 continue;
452 }
453 if (umla.isStatic ()) {
454 std::cerr << "CORBAValue " << name << "/" << member
455 << ": static not supported.\n",
456 }
457 ref = findByName (dia.getUml (), umla.getType ().c_str ());
458 if (ref != NULL) {
459 getFile () << spc () << fqname (*ref, true);
460 }
461 else {
462 getFile () << spc () << cppName (umla.getType ());
463 }
464 if (!bOpenBraceOnNewline) {
465 getFile () << " " << member << " () { return _" << member
466 << "; }\n";
467 }
468 else {
469 getFile () << " " << member << " ()\n" << spc () << "{\n";
470 incIndentLevel ();
471 getFile () << spc () << "return _" << member << ";\n";
472 decIndentLevel ();
473 getFile () << spc () << "}\n";
474 }
475 getFile () << spc () << "void " << member << " (";
476 if (ref != NULL) {
477 int by_ref = passByReference (*ref);
478 if (by_ref) {
479 getFile () << "const ";
480 }
481 getFile () << fqname (*ref, true);
482 if (by_ref) {
483 getFile () << "&";
484 }
485 }
486 else {
487 getFile () << cppName (umla.getType ());
488 }
489 if (!bOpenBraceOnNewline) {
490 getFile () << " value_) { _" << member << " = value_; }\n";
491 }
492 else {
493 getFile () << " value_)\n" << spc () << "{\n";
494 incIndentLevel ();
495 getFile () << spc () << "_" << member << " = value_;";
496 decIndentLevel ();
497 getFile () << spc () << "}\n";
498 }
499 }
500 decIndentLevel ();
501 }
502 else
503 #endif
504 {
505 writeComment ("Attributes");
506 for (const umlAttribute & umla : node.getAttributes ()) {
507 if (umla.getName ().empty ()) {
508 std::cerr << "An attribute of the "
509 << fqname (node, false)
510 << " class have an empty name.\n";
511 }
512 if (umla.getType ().empty ()) {
513 std::cerr << "An attribute of the " << fqname (node, false)
514 << " class have an empty type.\n";
515 }
516 writeAttribute (node, umla, tmpv);
517 }
518 }
519 }
520
521 if (!node.getOperations ().empty ()) {
522 writeComment ("Operations");
523 #ifdef ENABLE_CORBA
524 if (isCorba) {
525 getFile () << spc () << "public :\n";
526 }
527 #endif
528 for (const umlOperation & umlo : node.getOperations ()) {
529 if (umlo.isStereotypeGetSet ()) {
530 writeFunctionGetSet (node, umlo, tmpv);
531 }
532 else {
533 writeFunction (node, umlo, tmpv);
534 }
535 }
536 }
537
538 #ifdef ENABLE_CORBA
539 if ((!node.getAttributes ().empty ()) && (isCorba)) {
540 getFile () << "\n";
541 decIndentLevel ();
542 writeComment ("State member implementation");
543 getFile () << spc () << "private :\n";
544 incIndentLevel ();
545 for (const umlAttribute & umla : node.getAttributes ()) {
546 umlClassNode *ref = findByName (dia.getUml (),
547 umla.getType ().c_str ());
548 getFile () << spc ();
549 if (ref != NULL) {
550 getFile () << fqname (*ref, isOoClass (*ref));
551 /*
552 * FIXME: Find a better way to decide whether to use
553 * a pointer.
554 */
555 }
556 else {
557 getFile () << cppName (umla.getType ());
558 }
559 getFile () << " _" << umla.getName () << ";\n";
560 }
561 }
562 #endif
563
564 decIndentLevel ();
565 writeClassEnd ();
566 }
567
568 const char *
dirName(umlPackage * pkg,char separator)569 dirName (umlPackage * pkg, char separator) {
570 static std::string buf;
571 std::list <umlPackage *>::const_iterator it;
572 std::list <umlPackage *> pkglist;
573
574 buf.clear ();
575 umlPackage::makePackageList (pkg, pkglist);
576 it = pkglist.begin ();
577 while (it != pkglist.end ()) {
578 buf.append ((*it)->getName ());
579 ++it;
580 if (it != pkglist.end ()) {
581 buf.append (1, separator);
582 }
583 }
584 return buf.c_str ();
585 }
586
587 void
genDecl(declaration & d,bool forceOpen)588 GenerateCode::genDecl (declaration &d,
589 bool forceOpen) {
590 #ifdef ENABLE_CORBA
591 const char *name;
592 std::list <umlAttribute>::const_iterator umla;
593 #endif
594 const umlClassNode *node;
595
596 if ((d.decl_kind == dk_class) && (d.u.this_class->isStereotypeExtern ())) {
597 return;
598 }
599 if ((d.decl_kind == dk_module) &&
600 (d.u.this_module->pkg->isStereotypeExtern ())) {
601 return;
602 }
603
604 if ((buildtree) && (d.decl_kind == dk_module)) {
605 std::string folder;
606
607 folder.assign (outdir);
608 folder.append (1, SEPARATOR);
609 folder.append (dirName (d.u.this_module->pkg, SEPARATOR));
610
611 if (
612 #if defined(_WIN32) || defined(_WIN64)
613 _mkdir (folder.c_str ()) != 0
614 #else
615 mkdir (folder.c_str (), 0777) != 0
616 #endif
617 ) {
618 if (errno != EEXIST) {
619 throw std::string (std::string ("Fail to create folder ") +
620 folder + std::string (".\n"));
621 }
622 }
623 }
624
625 if (forceOpen && (!oneClassOneHeader || !d.decl_kind == dk_module)) {
626 std::string name_;
627
628 if (d.decl_kind == dk_module) {
629 if (buildtree) {
630 name_ = dirName (d.u.this_module->pkg, SEPARATOR);
631 }
632 else {
633 name_ = dirName (d.u.this_module->pkg, '-');
634 }
635 } else {
636 if (d.u.this_class->getPackage () != NULL) {
637 if (buildtree) {
638 name_.assign (dirName (d.u.this_class->getPackage (),
639 SEPARATOR));
640 name_.append (1, SEPARATOR);
641 }
642 else {
643 name_.assign (dirName (d.u.this_class->getPackage (),
644 '-'));
645 name_.append (1, '-');
646 }
647 }
648 name_.append (d.u.this_class->getName ());
649 }
650
651 openOutfile (name_, d);
652 }
653
654 if (d.decl_kind == dk_module) {
655 for (declaration & it : d.u.this_module->contents) {
656 genDecl (it, oneClassOneHeader);
657 }
658 if (forceOpen && !oneClassOneHeader) {
659 closeOutfile ();
660 }
661 return;
662 }
663
664 node = d.u.this_class;
665
666 writeNameSpaceStart (node);
667 #ifdef ENABLE_CORBA
668 name = node->getName ().c_str ();
669 umla = node->getAttributes ().begin ();
670 #endif
671
672 #ifdef ENABLE_CORBA
673 if (eq (stype, "CORBANative")) {
674 writeComment (std::string ("CORBANative: ") +
675 node->getName () +
676 std::string ("\n"));
677 }
678 else
679 #endif
680 if (node->isStereotypeEnum ()) {
681 if (!node->getOperations ().empty ()) {
682 std::cerr << "Class \"" << node->getName ()
683 << "\" is enum. All operations are ignored.\n";
684 }
685 if (!node->getTemplates ().empty ()) {
686 std::cerr << "Class \"" << node->getName ()
687 << "\" is enum. All templates are ignored.\n";
688 }
689 if (node->isAbstract ()) {
690 std::cerr << "Class \"" << node->getName ()
691 << "\" is abstact. Ignored.\n";
692 }
693 writeEnum (*node);
694 }
695 else if (node->isStereotypeStruct ()) {
696 writeStruct (*node);
697 }
698 #ifdef ENABLE_CORBA
699 else if (eq (stype, "CORBAException")) {
700 std::cerr << name << ": CORBAException not yet implemented.\n";
701
702 }
703 else if (eq (stype, "CORBAUnion")) {
704 if (umla == node->getAttributes ().end ()) {
705 throw std::string ("Attributes not set at union " + name + "\n");
706 }
707 std::cerr << name << ": CORBAUnion not yet fully implemented.\n";
708 if (bOpenBraceOnNewline) {
709 writeComment ("CORBAUnion");
710 getFile () << spc () << "class " << name << "\n";
711 getFile () << spc () << "{\n";
712 }
713 else {
714 writeComment ("CORBAUnion");
715 getFile () << spc () << "class " << name << " {\n";
716 }
717 getFile () << spc () << "public :\n";
718 incIndentLevel ();
719 getFile () << spc () << (*umla).getType () << " _d();\n\n";
720 ++umla;
721 while (umla != node->getAttributes ().end ()) {
722 (*umla).check (name);
723 getFile () << spc () << cppName ((*umla).getType ()) << " "
724 << (*umla).getName () << " ();\n";
725 getFile () << spc () << "void " << (*umla).getName () << " ("
726 << cppName ((*umla).getType ())
727 << " _value);\n\n";
728 ++umla;
729 }
730 decIndentLevel ();
731 getFile () << spc () << "};\n\n";
732
733 }
734 #endif
735 else if (node->isStereotypeTypedef ()) {
736 writeTypedef (*node);
737 }
738 else {
739 genClass (*node);
740 }
741
742 writeNameSpaceEnd (d.u.this_class);
743
744 if (forceOpen) {
745 closeOutfile ();
746 }
747 }
748
749
750 std::string &
spc() const751 GenerateCode::spc () const {
752 static std::string spcbuf;
753
754 spcbuf.assign (indent * indentlevel, ' ');
755
756 return spcbuf;
757 }
758
759 uint8_t
getVersion() const760 GenerateCode::getVersion () const {
761 return version;
762 }
763
764 void
setVersion(uint8_t version_)765 GenerateCode::setVersion (uint8_t version_) {
766 version = version_;
767 }
768
769 uint32_t
getIndent() const770 GenerateCode::getIndent () const {
771 return indent;
772 }
773
774
775 void
setIndent(uint8_t spaces)776 GenerateCode::setIndent (uint8_t spaces) {
777 if ((spaces < 1) || (spaces > 8)) {
778 return;
779 }
780
781 indent = spaces & 15;
782
783 return;
784 }
785
786
787 void
incIndentLevel()788 GenerateCode::incIndentLevel () {
789 indentlevel++;
790 }
791
792
793 void
decIndentLevel()794 GenerateCode::decIndentLevel () {
795 assert (indentlevel != 0);
796 indentlevel--;
797 }
798
799 void
writeFile()800 GenerateCode::writeFile () {
801 #if defined(_WIN32) || defined(_WIN64)
802 FILE * licensefile;
803 if ((fopen_s (&licensefile, license.c_str (), "r") != 0) ||
804 (licensefile == NULL)) {
805 throw std::string ("Can't open the license file " + license + ".\n");
806 }
807 #else
808 FILE * licensefile = fopen (license.c_str (), "r");
809
810 if (!licensefile) {
811 throw std::string ("Can't open the license file " + license + ".\n");
812 }
813 #endif
814
815 int lc;
816 rewind (licensefile);
817 while ((lc = fgetc (licensefile)) != EOF) {
818 getFile () << static_cast <char> (lc);
819 }
820
821 fclose (licensefile);
822 }
823
824
825 const char *
comment(const std::string & comment_,const std::string & startFirstLine,const std::string & startOtherLines,const char * endLastLine)826 GenerateCode::comment (const std::string & comment_,
827 const std::string & startFirstLine,
828 const std::string & startOtherLines,
829 const char * endLastLine) {
830 static std::string buf;
831 size_t start = 0;
832 size_t end;
833
834 buf.clear ();
835
836 end = comment_.find ("\n", start);
837 while (end != std::string::npos)
838 {
839 if (start == 0) {
840 buf.append (startFirstLine);
841 }
842 else {
843 buf.append (startOtherLines);
844 }
845 buf.append (comment_.substr (start, end-start));
846 buf.append ("\n");
847 start = end + 1;
848 end = comment_.find ("\n", start);
849 }
850
851 if (start == 0) {
852 buf.append (startFirstLine);
853 }
854 else {
855 buf.append (startOtherLines);
856 }
857 buf.append (comment_.substr (start, end-start));
858 buf.append (endLastLine);
859
860 return buf.c_str ();
861 }
862
863 void
writeLicense1(const char * start,const char * end)864 GenerateCode::writeLicense1 (const char * start, const char * end) {
865 if (getLicense ().empty ()) {
866 return;
867 }
868
869 getFile () << start << "\n";
870 writeFile ();
871 getFile () << end << "\n\n";
872 }
873
874 const char *
visibility1(std::string desc,const Visibility & vis)875 GenerateCode::visibility1 (std::string desc,
876 const Visibility & vis) {
877 switch (vis) {
878 case Visibility::PUBLIC :
879 return "public";
880 case Visibility::PRIVATE :
881 return "private";
882 case Visibility::PROTECTED :
883 return "protected";
884 case Visibility::IMPLEMENTATION :
885 std::cerr << desc + ": implementation not applicable. Default: public.\n";
886 return "public";
887 default :
888 throw std::string ("Unknown visibility.\n");
889 }
890 }
891
892 void
writeFunctionGetSet1(const umlClassNode & node,const umlOperation & ope,Visibility & curr_visibility)893 GenerateCode::writeFunctionGetSet1 (const umlClassNode & node,
894 const umlOperation & ope,
895 Visibility & curr_visibility) {
896 std::string tmpname;
897
898 if ((!ope.getType ().compare ("bool")) ||
899 (!ope.getType ().compare ("boolean")) ||
900 (!ope.getType ().compare ("Boolean"))) {
901 tmpname.assign ("is");
902 }
903 else {
904 tmpname.assign ("get");
905 }
906 tmpname.append (strtoupperfirst (ope.getName ()));
907 umlOperation ope2 (tmpname,
908 ope.getType (),
909 "",
910 ope.getVisibility (),
911 ope.getInheritance (),
912 ope.isStatic (),
913 true,
914 false,
915 false,
916 false);
917 writeFunction (node,ope2, curr_visibility);
918
919 umlAttribute parameter ("value",
920 "",
921 ope.getType (),
922 "",
923 ope.getVisibility (),
924 ope.getInheritance (),
925 ope.isStatic (),
926 ope.isConstant (),
927 Kind::IN);
928 tmpname.assign ("set");
929 tmpname.append (strtoupperfirst (ope.getName ()));
930 ope2 = umlOperation (tmpname,
931 "void",
932 "",
933 ope.getVisibility (),
934 ope.getInheritance (),
935 ope.isStatic (),
936 false,
937 false,
938 false,
939 false);
940 ope2.addParameter (parameter);
941 writeFunction (node, ope2, curr_visibility);
942 }
943
944 bool
writeInclude1(const std::list<std::pair<std::list<umlPackage * >,const umlClassNode * >> & name,const char * startIncludeSystem,const char * endIncludeSystem,const char * startIncludeFile,const char * endIncludeFile,bool forceExtExtern)945 GenerateCode::writeInclude1 (const std::list <std::pair <
946 std::list <umlPackage *>,
947 const umlClassNode *> > & name,
948 const char * startIncludeSystem,
949 const char * endIncludeSystem,
950 const char * startIncludeFile,
951 const char * endIncludeFile,
952 bool forceExtExtern) {
953 bool ret = false;
954 // List of include then if (true) the class is system and should not be
955 // generated.
956 std::list <std::pair <std::string, bool> > incs;
957
958 for (const std::pair <std::list <umlPackage *>,
959 const umlClassNode *> & it : name) {
960 std::string include;
961 std::pair <std::string, bool> add;
962
963 if (it.second == NULL) {
964 continue;
965 }
966
967 ret = true;
968
969 if (getBuildTree () || it.second->isStereotypeExtern ()) {
970 if (!it.first.empty ()) {
971 for (const umlPackage * pack : it.first) {
972 include.append (pack->getName ());
973 include.append (1, SEPARATOR);
974 }
975 }
976 include.append (it.second->getName ());
977 }
978 else if (getOneClass ()) {
979 if (!it.first.empty ()) {
980 for (const umlPackage * pack : it.first) {
981 include.append (pack->getName ());
982 include.append ("-");
983 }
984 }
985 include.append (it.second->getName ());
986 }
987 else {
988 if (!it.first.empty ()) {
989 include.append ((*it.first.begin ())->getName ());
990 }
991 else {
992 include.append (it.second->getName ());
993 }
994 }
995 if ((forceExtExtern) || (!it.second->isStereotypeExtern ())) {
996 include.append (".");
997 include.append (getFileExt ());
998 }
999 add.first = include;
1000 add.second = it.second->isStereotypeExtern ();
1001 if (std::find (incs.begin (),
1002 incs.end (),
1003 add) == incs.end ()) {
1004 if (add.second) {
1005 incs.push_front (add);
1006 }
1007 else {
1008 incs.push_back (add);
1009 }
1010 }
1011 }
1012
1013 for (const std::pair <std::string, bool> & add : incs) {
1014 if (add.second) {
1015 getFile () << spc () << startIncludeSystem << add.first
1016 << endIncludeSystem;
1017 }
1018 else {
1019 getFile () << spc () << startIncludeFile << add.first
1020 << endIncludeFile;
1021 }
1022 }
1023 if (!incs.empty ()) {
1024 getFile () << "\n";
1025 }
1026
1027 return ret;
1028 }
1029
1030 void
writeBeforeInclude(umlClassNode *)1031 GenerateCode::writeBeforeInclude (umlClassNode *) {
1032 }
1033
1034 void
writeAfterInclude(umlClassNode *)1035 GenerateCode::writeAfterInclude (umlClassNode *) {
1036 }
1037
~GenerateCode()1038 GenerateCode::~GenerateCode () {
1039 }
1040
1041 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1042