-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcodegen.cpp
201 lines (157 loc) · 4.52 KB
/
codegen.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/**
RIGHT TO USE, DISTRIBUTE AND MODIFY
===================================
Copyright (C) 2015 Ganesh Prasad Sahoo - All Rights Reserved
You may use, distribute and modify this code under the Terms
of GNU GPL V3 License. You should have received a copy of the
GNU GPL v3 License with this file. If not please write to
or visit
http://www.gnu.org/licenses/gpl.txt
*****************************************************************************
DOCUMENTATION
=============
This file contains functions that generate code in Graphviz Dot
syntax from the ER Diagram represented in memory. The structure
of the representation is described and implemented in structure.hpp .
The headfile where the void generateCode(const char *outFileName) is
declared in parser.hpp . This function is a method of the Parser class.
Important Points
----------------
1. All nodes of the graph are named as 'node_X' where X is an unique
integer. Each unique node has a 32 bit node_no_ associated with it.
2. The code generated is Dot language is targetted towards the Graphviz
fdp and sfdp engines. The optimal layout of the diagram is possible
while using the above mentioned engines only.
*/
#include "parser.hpp"
using namespace std;
// For keeping track of numbering/naming of nodes in the generated code.
int nodeCounter=1;
//
void Parser::generateCode(const char *outFileName){
ofstream fout;
fout.open(outFileName);
fout<<"graph G{maxiter=1000000;overlap=scale;"
<<"ordering=out;splines=true; label=\""<<diagram_.name_
<<"\"; node[fontsize=14, fontname=\"Consolas\"];"<<endl
<<"edge[fontsize=14, fontname=\"Consolas\"];"<<endl;
for(map<string,Entity>::iterator it=entTbl_.table_.begin();
it!=entTbl_.table_.end(); ++it)
it->second.printDot(fout);
for(size_t i=0; i<diagram_.graph_.size(); ++i)
diagram_.graph_[i].printDot(fout);
fout<<"}";
return;
}
void Entity::printDot(ofstream &fout){
sstream nodeName("node_");
nodeName<<node_no_;
fout<<nodeName.str()<<"[shape=box, label=\""<<name_<<"\""
<<(weak_?",peripheries=2":"")<<"];"<<endl;
for(size_t i=0; i<attr_.size(); ++i)
attr_[i].printDot(fout,node_no_);
return;
}
void Attribute::printDot(ofstream &fout, int parent){
sstream nodeName("node_");
sstream parName("node_");
node_no_=nodeCounter++;
nodeName<<node_no_;
parName<<parent;
bool underline = false;
bool composite = false;
fout<<nodeName.str()<<"[";
for(size_t i=0; i<type_.size(); ++i){
switch(type_[i]){
case _MULTI:
fout<<"peripheries=2,";
break;
case _COMPOSITE:
composite = true;
break;
case _KEY:
underline = true;
break;
case _DERIVED:
fout<<"style=dashed,";
break;
default:
break;
}
}
fout<<"label="<<(underline?"<<u>":"\"")<<name_<<(underline?"</u>>":"\"")
<<"];"<<endl;
fout<<nodeName.str()<<"--"<<parName.str()<<";"<<endl;
if(composite)
for(size_t i=0; i<attr_.size(); ++i)
attr_[i].printDot(fout,node_no_);
return;
}
void Relation::printDot(ofstream &fout){
sstream nodeName("node_");
nodeName<<node_no_;
fout<<nodeName.str()<<"[shape=diamond,regular=1,"
<<(weak_?"peripheries=2,":"")
<<"label=\""<<name_<<"\"];"<<endl;
for(size_t i=0; i<from_.size(); ++i)
from_[i].printDot(fout, node_no_);
for(size_t i=0; i<to_.size(); ++i)
to_[i].printDot(fout, node_no_);
return;
}
void Edge::printDot(ofstream &fout, int parent){
sstream parName("node_");
sstream nodeName("node_");
parName<<parent;
string n(ent_);
if(entTbl_.table_.count(n)==1)
nodeName<<entTbl_.table_[n].node_no_;
else{
cout<<"CODE GENERATOR ERROR : Entity "<<ent_
<<" not defined but used"<<endl;
return;
}
fout<<nodeName.str()<<"--"<<parName.str();
if(weak_){
if(complete_){
if(!normal_){
if(many_)
fout<<"[style=dashed, penwidth=4, label=\"N\"];"<<endl;
else
fout<<"[style=dashed, penwidth=4, label=\"1\"];"<<endl;
}
else fout<<"[style=dashed, penwidth=4];"<<endl;
}
else{// fout<<"[style=dashed];"<<endl;
if(!normal_){
if(many_)
fout<<"[style=dashed,label=\"N\"];"<<endl;
else
fout<<"[style=dashed,label=\"1\"];"<<endl;
}
else fout<<"[style=dashed];"<<endl;
}
}
else{
if(complete_){
if(!normal_){
if(many_)
fout<<"[penwidth=4, label=\"N\"];"<<endl;
else
fout<<"[penwidth=4, label=\"1\"];"<<endl;
}
else fout<<"[penwidth=4];"<<endl;
}
else{// fout<<";"<<endl;
if(!normal_){
if(many_)
fout<<"[label=\"N\"];"<<endl;
else
fout<<"[label=\"1\"];"<<endl;
}
else fout<<";"<<endl;
}
}
return;
}