ZahirJS commited on
Commit
a025aee
·
verified ·
1 Parent(s): 1120e3c

Update entity_relationship_generator.py

Browse files
Files changed (1) hide show
  1. entity_relationship_generator.py +421 -79
entity_relationship_generator.py CHANGED
@@ -4,6 +4,385 @@ from tempfile import NamedTemporaryFile
4
  import os
5
 
6
  def generate_entity_relationship_diagram(json_input: str, output_format: str) -> str:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  try:
8
  if not json_input.strip():
9
  return "Error: Empty input"
@@ -25,33 +404,12 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
25
  dot.attr('node', fontname='Arial', fontsize='10', color='#404040')
26
  dot.attr('edge', fontname='Arial', fontsize='9', color='#4a4a4a')
27
 
28
- # Base color system - much lighter grays starting from #BEBEBE
29
- base_color = '#BEBEBE' # Much lighter base color
30
- lightening_factor = 0.08 # Smaller factor for subtle gradations
 
31
 
32
- def get_gradient_color(depth, base_hex_color, lightening_factor=0.08):
33
- """Get lightened color based on depth - much lighter grays"""
34
- if not isinstance(base_hex_color, str) or not base_hex_color.startswith('#') or len(base_hex_color) != 7:
35
- base_hex_color = '#BEBEBE' # Light gray fallback
36
-
37
- base_r = int(base_hex_color[1:3], 16)
38
- base_g = int(base_hex_color[3:5], 16)
39
- base_b = int(base_hex_color[5:7], 16)
40
-
41
- current_r = base_r + int((255 - base_r) * depth * lightening_factor)
42
- current_g = base_g + int((255 - base_g) * depth * lightening_factor)
43
- current_b = base_b + int((255 - base_b) * depth * lightening_factor)
44
-
45
- current_r = min(255, current_r)
46
- current_g = min(255, current_g)
47
- current_b = min(255, current_b)
48
-
49
- return f'#{current_r:02x}{current_g:02x}{current_b:02x}'
50
-
51
- def get_font_color_for_background(depth, lightening_factor=0.08):
52
- """Get appropriate font color based on background lightness"""
53
- # With lighter base colors, we'll use black text for better readability
54
- return 'black'
55
 
56
  entities = data.get('entities', [])
57
  relationships = data.get('relationships', [])
@@ -65,18 +423,14 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
65
  if not entity_name:
66
  continue
67
 
68
- # Entity colors - depth 1 for entities
69
- entity_color = get_gradient_color(1, base_color, lightening_factor)
70
- entity_font_color = get_font_color_for_background(1, lightening_factor)
71
-
72
  if entity_type == 'weak':
73
  dot.node(
74
  entity_name,
75
  entity_name,
76
  shape='box',
77
- style='filled,rounded', # KEY CHANGE: rounded borders like your other generators
78
- fillcolor=entity_color,
79
- fontcolor=entity_font_color,
80
  color='#404040',
81
  penwidth='3',
82
  width='1.8',
@@ -88,9 +442,9 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
88
  entity_name,
89
  entity_name,
90
  shape='box',
91
- style='filled,rounded', # KEY CHANGE: rounded borders
92
- fillcolor=entity_color,
93
- fontcolor=entity_font_color,
94
  color='#404040',
95
  penwidth='1',
96
  width='1.8',
@@ -98,23 +452,20 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
98
  fontsize='12'
99
  )
100
 
101
- # Process attributes with gradient colors - depth 2 for attributes
102
  for i, attr in enumerate(attributes):
103
  attr_name = attr.get('name', '')
104
  attr_type = attr.get('type', 'regular')
105
 
106
  attr_id = f"{entity_name}_attr_{i}"
107
- attr_color = get_gradient_color(2, base_color, lightening_factor)
108
- attr_font_color = get_font_color_for_background(2, lightening_factor)
109
 
110
  if attr_type == 'primary_key':
111
  dot.node(
112
  attr_id,
113
  f'{attr_name} (PK)',
114
  shape='ellipse',
115
- style='filled,rounded', # KEY CHANGE: rounded borders
116
- fillcolor=attr_color,
117
- fontcolor=attr_font_color,
118
  color='#404040',
119
  width='1.2',
120
  height='0.6',
@@ -125,9 +476,9 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
125
  attr_id,
126
  f'{attr_name} (Partial)',
127
  shape='ellipse',
128
- style='filled,rounded,dashed', # KEY CHANGE: rounded borders
129
- fillcolor=attr_color,
130
- fontcolor=attr_font_color,
131
  color='#404040',
132
  width='1.2',
133
  height='0.6',
@@ -138,9 +489,9 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
138
  attr_id,
139
  attr_name,
140
  shape='ellipse',
141
- style='filled,rounded', # KEY CHANGE: rounded borders
142
- fillcolor=attr_color,
143
- fontcolor=attr_font_color,
144
  color='#404040',
145
  penwidth='3',
146
  width='1.2',
@@ -152,9 +503,9 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
152
  attr_id,
153
  f'/{attr_name}/',
154
  shape='ellipse',
155
- style='filled,rounded,dashed', # KEY CHANGE: rounded borders
156
- fillcolor=attr_color,
157
- fontcolor=attr_font_color,
158
  color='#404040',
159
  width='1.2',
160
  height='0.6',
@@ -165,22 +516,22 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
165
  attr_id,
166
  attr_name,
167
  shape='ellipse',
168
- style='filled,rounded', # KEY CHANGE: rounded borders
169
- fillcolor=attr_color,
170
- fontcolor=attr_font_color,
171
  color='#404040',
172
  width='1.2',
173
  height='0.6',
174
  fontsize='10'
175
  )
176
- else: # regular
177
  dot.node(
178
  attr_id,
179
  attr_name,
180
  shape='ellipse',
181
- style='filled,rounded', # KEY CHANGE: rounded borders
182
- fillcolor=attr_color,
183
- fontcolor=attr_font_color,
184
  color='#404040',
185
  width='1.2',
186
  height='0.6',
@@ -189,7 +540,6 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
189
 
190
  dot.edge(entity_name, attr_id, color='#4a4a4a', len='1.5')
191
 
192
- # Process relationships with gradient colors - depth 1.5 for relationships
193
  for relationship in relationships:
194
  rel_name = relationship.get('name')
195
  rel_type = relationship.get('type', 'regular')
@@ -200,25 +550,20 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
200
  if not rel_name:
201
  continue
202
 
203
- rel_color = get_gradient_color(1.5, base_color, lightening_factor)
204
- rel_font_color = get_font_color_for_background(1.5, lightening_factor)
205
-
206
  if rel_type == 'isa':
207
  parent = relationship.get('parent')
208
  children = relationship.get('children', [])
209
 
210
  if parent and children:
211
  isa_id = f"isa_{rel_name}"
212
- isa_color = get_gradient_color(1.2, base_color, lightening_factor)
213
- isa_font_color = get_font_color_for_background(1.2, lightening_factor)
214
 
215
  dot.node(
216
  isa_id,
217
  'ISA',
218
  shape='triangle',
219
- style='filled,rounded', # KEY CHANGE: rounded borders
220
- fillcolor=isa_color,
221
- fontcolor=isa_font_color,
222
  color='#404040',
223
  penwidth='2',
224
  width='1.0',
@@ -237,9 +582,9 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
237
  rel_name,
238
  rel_name,
239
  shape='diamond',
240
- style='filled,rounded', # KEY CHANGE: rounded borders
241
- fillcolor=rel_color,
242
- fontcolor=rel_font_color,
243
  color='#404040',
244
  penwidth='3',
245
  width='1.8',
@@ -251,9 +596,9 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
251
  rel_name,
252
  rel_name,
253
  shape='diamond',
254
- style='filled,rounded', # KEY CHANGE: rounded borders
255
- fillcolor=rel_color,
256
- fontcolor=rel_font_color,
257
  color='#404040',
258
  penwidth='1',
259
  width='1.8',
@@ -261,20 +606,17 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
261
  fontsize='11'
262
  )
263
 
264
- # Relationship attributes - depth 2.5
265
  for j, attr in enumerate(rel_attributes):
266
  attr_name = attr.get('name', '')
267
  attr_id = f"{rel_name}_attr_{j}"
268
- rel_attr_color = get_gradient_color(2.5, base_color, lightening_factor)
269
- rel_attr_font_color = get_font_color_for_background(2.5, lightening_factor)
270
 
271
  dot.node(
272
  attr_id,
273
  attr_name,
274
  shape='ellipse',
275
- style='filled,rounded', # KEY CHANGE: rounded borders
276
- fillcolor=rel_attr_color,
277
- fontcolor=rel_attr_font_color,
278
  color='#404040',
279
  width='1.0',
280
  height='0.5',
 
4
  import os
5
 
6
  def generate_entity_relationship_diagram(json_input: str, output_format: str) -> str:
7
+ """
8
+ Generates an Entity Relationship (ER) diagram from JSON input.
9
+
10
+ Args:
11
+ json_input (str): A JSON string describing the ER diagram structure.
12
+ It must follow the Expected JSON Format Example below.
13
+
14
+ Expected JSON Format Example:
15
+ {
16
+ "entities": [
17
+ {
18
+ "name": "User",
19
+ "type": "strong",
20
+ "attributes": [
21
+ {
22
+ "name": "user_id",
23
+ "type": "primary_key"
24
+ },
25
+ {
26
+ "name": "username",
27
+ "type": "regular"
28
+ },
29
+ {
30
+ "name": "email",
31
+ "type": "regular"
32
+ },
33
+ {
34
+ "name": "password_hash",
35
+ "type": "regular"
36
+ },
37
+ {
38
+ "name": "full_name",
39
+ "type": "composite"
40
+ },
41
+ {
42
+ "name": "phone_numbers",
43
+ "type": "multivalued"
44
+ },
45
+ {
46
+ "name": "age",
47
+ "type": "derived"
48
+ }
49
+ ]
50
+ },
51
+ {
52
+ "name": "Product",
53
+ "type": "strong",
54
+ "attributes": [
55
+ {
56
+ "name": "product_id",
57
+ "type": "primary_key"
58
+ },
59
+ {
60
+ "name": "name",
61
+ "type": "regular"
62
+ },
63
+ {
64
+ "name": "description",
65
+ "type": "regular"
66
+ },
67
+ {
68
+ "name": "price",
69
+ "type": "regular"
70
+ },
71
+ {
72
+ "name": "stock_quantity",
73
+ "type": "regular"
74
+ },
75
+ {
76
+ "name": "tags",
77
+ "type": "multivalued"
78
+ }
79
+ ]
80
+ },
81
+ {
82
+ "name": "Category",
83
+ "type": "strong",
84
+ "attributes": [
85
+ {
86
+ "name": "category_id",
87
+ "type": "primary_key"
88
+ },
89
+ {
90
+ "name": "name",
91
+ "type": "regular"
92
+ },
93
+ {
94
+ "name": "description",
95
+ "type": "regular"
96
+ }
97
+ ]
98
+ },
99
+ {
100
+ "name": "Order",
101
+ "type": "strong",
102
+ "attributes": [
103
+ {
104
+ "name": "order_id",
105
+ "type": "primary_key"
106
+ },
107
+ {
108
+ "name": "order_date",
109
+ "type": "regular"
110
+ },
111
+ {
112
+ "name": "status",
113
+ "type": "regular"
114
+ },
115
+ {
116
+ "name": "total_amount",
117
+ "type": "derived"
118
+ },
119
+ {
120
+ "name": "shipping_address",
121
+ "type": "composite"
122
+ }
123
+ ]
124
+ },
125
+ {
126
+ "name": "OrderItem",
127
+ "type": "weak",
128
+ "attributes": [
129
+ {
130
+ "name": "line_number",
131
+ "type": "partial_key"
132
+ },
133
+ {
134
+ "name": "quantity",
135
+ "type": "regular"
136
+ },
137
+ {
138
+ "name": "unit_price",
139
+ "type": "regular"
140
+ },
141
+ {
142
+ "name": "subtotal",
143
+ "type": "derived"
144
+ }
145
+ ]
146
+ },
147
+ {
148
+ "name": "Payment",
149
+ "type": "strong",
150
+ "attributes": [
151
+ {
152
+ "name": "payment_id",
153
+ "type": "primary_key"
154
+ },
155
+ {
156
+ "name": "amount",
157
+ "type": "regular"
158
+ },
159
+ {
160
+ "name": "payment_method",
161
+ "type": "regular"
162
+ },
163
+ {
164
+ "name": "payment_date",
165
+ "type": "regular"
166
+ },
167
+ {
168
+ "name": "status",
169
+ "type": "regular"
170
+ }
171
+ ]
172
+ },
173
+ {
174
+ "name": "Review",
175
+ "type": "strong",
176
+ "attributes": [
177
+ {
178
+ "name": "review_id",
179
+ "type": "primary_key"
180
+ },
181
+ {
182
+ "name": "rating",
183
+ "type": "regular"
184
+ },
185
+ {
186
+ "name": "comment",
187
+ "type": "regular"
188
+ },
189
+ {
190
+ "name": "review_date",
191
+ "type": "regular"
192
+ }
193
+ ]
194
+ },
195
+ {
196
+ "name": "Vendor",
197
+ "type": "strong",
198
+ "attributes": [
199
+ {
200
+ "name": "vendor_id",
201
+ "type": "primary_key"
202
+ },
203
+ {
204
+ "name": "company_name",
205
+ "type": "regular"
206
+ },
207
+ {
208
+ "name": "contact_person",
209
+ "type": "regular"
210
+ },
211
+ {
212
+ "name": "contact_emails",
213
+ "type": "multivalued"
214
+ },
215
+ {
216
+ "name": "business_address",
217
+ "type": "composite"
218
+ }
219
+ ]
220
+ },
221
+ {
222
+ "name": "ShoppingCart",
223
+ "type": "strong",
224
+ "attributes": [
225
+ {
226
+ "name": "cart_id",
227
+ "type": "primary_key"
228
+ },
229
+ {
230
+ "name": "created_date",
231
+ "type": "regular"
232
+ },
233
+ {
234
+ "name": "last_updated",
235
+ "type": "regular"
236
+ },
237
+ {
238
+ "name": "total_items",
239
+ "type": "derived"
240
+ }
241
+ ]
242
+ },
243
+ {
244
+ "name": "CartItem",
245
+ "type": "weak",
246
+ "attributes": [
247
+ {
248
+ "name": "item_position",
249
+ "type": "partial_key"
250
+ },
251
+ {
252
+ "name": "quantity",
253
+ "type": "regular"
254
+ },
255
+ {
256
+ "name": "added_date",
257
+ "type": "regular"
258
+ }
259
+ ]
260
+ }
261
+ ],
262
+ "relationships": [
263
+ {
264
+ "name": "PlacesOrder",
265
+ "type": "regular",
266
+ "entities": ["User", "Order"],
267
+ "cardinalities": {
268
+ "User": "1",
269
+ "Order": "M"
270
+ },
271
+ "attributes": []
272
+ },
273
+ {
274
+ "name": "Contains",
275
+ "type": "identifying",
276
+ "entities": ["Order", "OrderItem"],
277
+ "cardinalities": {
278
+ "Order": "1",
279
+ "OrderItem": "M"
280
+ },
281
+ "attributes": []
282
+ },
283
+ {
284
+ "name": "OrdersProduct",
285
+ "type": "regular",
286
+ "entities": ["OrderItem", "Product"],
287
+ "cardinalities": {
288
+ "OrderItem": "M",
289
+ "Product": "1"
290
+ },
291
+ "attributes": []
292
+ },
293
+ {
294
+ "name": "BelongsTo",
295
+ "type": "regular",
296
+ "entities": ["Product", "Category"],
297
+ "cardinalities": {
298
+ "Product": "M",
299
+ "Category": "1"
300
+ },
301
+ "attributes": []
302
+ },
303
+ {
304
+ "name": "ProcessesPayment",
305
+ "type": "regular",
306
+ "entities": ["Order", "Payment"],
307
+ "cardinalities": {
308
+ "Order": "1",
309
+ "Payment": "M"
310
+ },
311
+ "attributes": []
312
+ },
313
+ {
314
+ "name": "WritesReview",
315
+ "type": "regular",
316
+ "entities": ["User", "Review"],
317
+ "cardinalities": {
318
+ "User": "1",
319
+ "Review": "M"
320
+ },
321
+ "attributes": []
322
+ },
323
+ {
324
+ "name": "ReviewsProduct",
325
+ "type": "regular",
326
+ "entities": ["Review", "Product"],
327
+ "cardinalities": {
328
+ "Review": "M",
329
+ "Product": "1"
330
+ },
331
+ "attributes": []
332
+ },
333
+ {
334
+ "name": "Supplies",
335
+ "type": "regular",
336
+ "entities": ["Vendor", "Product"],
337
+ "cardinalities": {
338
+ "Vendor": "M",
339
+ "Product": "M"
340
+ },
341
+ "attributes": [
342
+ {
343
+ "name": "supply_price"
344
+ },
345
+ {
346
+ "name": "lead_time"
347
+ }
348
+ ]
349
+ },
350
+ {
351
+ "name": "HasCart",
352
+ "type": "regular",
353
+ "entities": ["User", "ShoppingCart"],
354
+ "cardinalities": {
355
+ "User": "1",
356
+ "ShoppingCart": "1"
357
+ },
358
+ "attributes": []
359
+ },
360
+ {
361
+ "name": "CartContains",
362
+ "type": "identifying",
363
+ "entities": ["ShoppingCart", "CartItem"],
364
+ "cardinalities": {
365
+ "ShoppingCart": "1",
366
+ "CartItem": "M"
367
+ },
368
+ "attributes": []
369
+ },
370
+ {
371
+ "name": "CartHasProduct",
372
+ "type": "regular",
373
+ "entities": ["CartItem", "Product"],
374
+ "cardinalities": {
375
+ "CartItem": "M",
376
+ "Product": "1"
377
+ },
378
+ "attributes": []
379
+ }
380
+ ]
381
+ }
382
+
383
+ Returns:
384
+ str: The filepath to the generated PNG image file.
385
+ """
386
  try:
387
  if not json_input.strip():
388
  return "Error: Empty input"
 
404
  dot.attr('node', fontname='Arial', fontsize='10', color='#404040')
405
  dot.attr('edge', fontname='Arial', fontsize='9', color='#4a4a4a')
406
 
407
+ entity_color = '#BEBEBE'
408
+ attribute_color = '#D4D4D4'
409
+ relationship_color = '#E8E8E8'
410
+ isa_color = '#F0F0F0'
411
 
412
+ font_color = 'black'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
413
 
414
  entities = data.get('entities', [])
415
  relationships = data.get('relationships', [])
 
423
  if not entity_name:
424
  continue
425
 
 
 
 
 
426
  if entity_type == 'weak':
427
  dot.node(
428
  entity_name,
429
  entity_name,
430
  shape='box',
431
+ style='filled,rounded',
432
+ fillcolor=entity_color,
433
+ fontcolor=font_color,
434
  color='#404040',
435
  penwidth='3',
436
  width='1.8',
 
442
  entity_name,
443
  entity_name,
444
  shape='box',
445
+ style='filled,rounded',
446
+ fillcolor=entity_color,
447
+ fontcolor=font_color,
448
  color='#404040',
449
  penwidth='1',
450
  width='1.8',
 
452
  fontsize='12'
453
  )
454
 
 
455
  for i, attr in enumerate(attributes):
456
  attr_name = attr.get('name', '')
457
  attr_type = attr.get('type', 'regular')
458
 
459
  attr_id = f"{entity_name}_attr_{i}"
 
 
460
 
461
  if attr_type == 'primary_key':
462
  dot.node(
463
  attr_id,
464
  f'{attr_name} (PK)',
465
  shape='ellipse',
466
+ style='filled,rounded',
467
+ fillcolor=attribute_color,
468
+ fontcolor=font_color,
469
  color='#404040',
470
  width='1.2',
471
  height='0.6',
 
476
  attr_id,
477
  f'{attr_name} (Partial)',
478
  shape='ellipse',
479
+ style='filled,rounded,dashed',
480
+ fillcolor=attribute_color,
481
+ fontcolor=font_color,
482
  color='#404040',
483
  width='1.2',
484
  height='0.6',
 
489
  attr_id,
490
  attr_name,
491
  shape='ellipse',
492
+ style='filled,rounded',
493
+ fillcolor=attribute_color,
494
+ fontcolor=font_color,
495
  color='#404040',
496
  penwidth='3',
497
  width='1.2',
 
503
  attr_id,
504
  f'/{attr_name}/',
505
  shape='ellipse',
506
+ style='filled,rounded,dashed',
507
+ fillcolor=attribute_color,
508
+ fontcolor=font_color,
509
  color='#404040',
510
  width='1.2',
511
  height='0.6',
 
516
  attr_id,
517
  attr_name,
518
  shape='ellipse',
519
+ style='filled,rounded',
520
+ fillcolor=attribute_color,
521
+ fontcolor=font_color,
522
  color='#404040',
523
  width='1.2',
524
  height='0.6',
525
  fontsize='10'
526
  )
527
+ else:
528
  dot.node(
529
  attr_id,
530
  attr_name,
531
  shape='ellipse',
532
+ style='filled,rounded',
533
+ fillcolor=attribute_color,
534
+ fontcolor=font_color,
535
  color='#404040',
536
  width='1.2',
537
  height='0.6',
 
540
 
541
  dot.edge(entity_name, attr_id, color='#4a4a4a', len='1.5')
542
 
 
543
  for relationship in relationships:
544
  rel_name = relationship.get('name')
545
  rel_type = relationship.get('type', 'regular')
 
550
  if not rel_name:
551
  continue
552
 
 
 
 
553
  if rel_type == 'isa':
554
  parent = relationship.get('parent')
555
  children = relationship.get('children', [])
556
 
557
  if parent and children:
558
  isa_id = f"isa_{rel_name}"
 
 
559
 
560
  dot.node(
561
  isa_id,
562
  'ISA',
563
  shape='triangle',
564
+ style='filled,rounded',
565
+ fillcolor=isa_color,
566
+ fontcolor=font_color,
567
  color='#404040',
568
  penwidth='2',
569
  width='1.0',
 
582
  rel_name,
583
  rel_name,
584
  shape='diamond',
585
+ style='filled,rounded',
586
+ fillcolor=relationship_color,
587
+ fontcolor=font_color,
588
  color='#404040',
589
  penwidth='3',
590
  width='1.8',
 
596
  rel_name,
597
  rel_name,
598
  shape='diamond',
599
+ style='filled,rounded',
600
+ fillcolor=relationship_color,
601
+ fontcolor=font_color,
602
  color='#404040',
603
  penwidth='1',
604
  width='1.8',
 
606
  fontsize='11'
607
  )
608
 
 
609
  for j, attr in enumerate(rel_attributes):
610
  attr_name = attr.get('name', '')
611
  attr_id = f"{rel_name}_attr_{j}"
 
 
612
 
613
  dot.node(
614
  attr_id,
615
  attr_name,
616
  shape='ellipse',
617
+ style='filled,rounded',
618
+ fillcolor=attribute_color,
619
+ fontcolor=font_color,
620
  color='#404040',
621
  width='1.0',
622
  height='0.5',