ZahirJS commited on
Commit
ea2df3b
·
verified ·
1 Parent(s): 1d7fa74

Update entity_relationship_generator.py

Browse files
Files changed (1) hide show
  1. entity_relationship_generator.py +686 -229
entity_relationship_generator.py CHANGED
@@ -1,3 +1,650 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import graphviz
2
  import json
3
  from tempfile import NamedTemporaryFile
@@ -143,120 +790,6 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
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": [
@@ -279,103 +812,6 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
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
  }
@@ -404,17 +840,31 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
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', [])
416
 
417
- # Process entities with new styling
418
  for entity in entities:
419
  entity_name = entity.get('name')
420
  entity_type = entity.get('type', 'strong')
@@ -423,13 +873,15 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
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',
@@ -443,7 +895,7 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
443
  entity_name,
444
  shape='box',
445
  style='filled,rounded',
446
- fillcolor=entity_color,
447
  fontcolor=font_color,
448
  color='#404040',
449
  penwidth='1',
@@ -457,6 +909,7 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
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(
@@ -464,7 +917,7 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
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',
@@ -477,7 +930,7 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
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',
@@ -490,7 +943,7 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
490
  attr_name,
491
  shape='ellipse',
492
  style='filled,rounded',
493
- fillcolor=attribute_color,
494
  fontcolor=font_color,
495
  color='#404040',
496
  penwidth='3',
@@ -504,7 +957,7 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
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',
@@ -517,20 +970,20 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
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',
@@ -556,13 +1009,14 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
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',
@@ -577,13 +1031,15 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
577
  dot.edge(isa_id, child, color='#4a4a4a', len='2.0')
578
 
579
  elif len(entities_involved) >= 2:
 
 
580
  if rel_type == 'identifying':
581
  dot.node(
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',
@@ -597,7 +1053,7 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
597
  rel_name,
598
  shape='diamond',
599
  style='filled,rounded',
600
- fillcolor=relationship_color,
601
  fontcolor=font_color,
602
  color='#404040',
603
  penwidth='1',
@@ -609,13 +1065,14 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
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',
 
1
+ # import graphviz
2
+ # import json
3
+ # from tempfile import NamedTemporaryFile
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"
389
+
390
+ # data = json.loads(json_input)
391
+
392
+ # if 'entities' not in data:
393
+ # raise ValueError("Missing required field: entities")
394
+
395
+ # dot = graphviz.Graph(comment='ER Diagram', engine='neato')
396
+ # dot.attr(
397
+ # bgcolor='white',
398
+ # pad='1.5',
399
+ # overlap='false',
400
+ # splines='true',
401
+ # sep='+25',
402
+ # esep='+15'
403
+ # )
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', [])
416
+
417
+ # # Process entities with new styling
418
+ # for entity in entities:
419
+ # entity_name = entity.get('name')
420
+ # entity_type = entity.get('type', 'strong')
421
+ # attributes = entity.get('attributes', [])
422
+
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',
437
+ # height='0.8',
438
+ # fontsize='12'
439
+ # )
440
+ # else:
441
+ # dot.node(
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',
451
+ # height='0.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',
472
+ # fontsize='10'
473
+ # )
474
+ # elif attr_type == 'partial_key':
475
+ # dot.node(
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',
485
+ # fontsize='10'
486
+ # )
487
+ # elif attr_type == 'multivalued':
488
+ # dot.node(
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',
498
+ # height='0.6',
499
+ # fontsize='10'
500
+ # )
501
+ # elif attr_type == 'derived':
502
+ # dot.node(
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',
512
+ # fontsize='10'
513
+ # )
514
+ # elif attr_type == 'composite':
515
+ # dot.node(
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',
538
+ # fontsize='10'
539
+ # )
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')
546
+ # entities_involved = relationship.get('entities', [])
547
+ # cardinalities = relationship.get('cardinalities', {})
548
+ # rel_attributes = relationship.get('attributes', [])
549
+
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',
570
+ # height='0.8',
571
+ # fontsize='10'
572
+ # )
573
+
574
+ # dot.edge(parent, isa_id, color='#4a4a4a', len='2.0')
575
+
576
+ # for child in children:
577
+ # dot.edge(isa_id, child, color='#4a4a4a', len='2.0')
578
+
579
+ # elif len(entities_involved) >= 2:
580
+ # if rel_type == 'identifying':
581
+ # dot.node(
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',
591
+ # height='1.0',
592
+ # fontsize='11'
593
+ # )
594
+ # else:
595
+ # dot.node(
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',
605
+ # height='1.0',
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',
623
+ # fontsize='9'
624
+ # )
625
+ # dot.edge(rel_name, attr_id, color='#4a4a4a', len='1.0')
626
+
627
+ # for entity in entities_involved:
628
+ # cardinality = cardinalities.get(entity, '1')
629
+ # dot.edge(
630
+ # entity,
631
+ # rel_name,
632
+ # label=f' {cardinality} ',
633
+ # color='#4a4a4a',
634
+ # len='2.5',
635
+ # fontcolor='#4a4a4a',
636
+ # fontsize='10'
637
+ # )
638
+
639
+ # with NamedTemporaryFile(delete=False, suffix=f'.{output_format}') as tmp:
640
+ # dot.render(tmp.name, format=output_format, cleanup=True)
641
+ # return f"{tmp.name}.{output_format}"
642
+
643
+ # except json.JSONDecodeError:
644
+ # return "Error: Invalid JSON format"
645
+ # except Exception as e:
646
+ # return f"Error: {str(e)}"
647
+
648
  import graphviz
649
  import json
650
  from tempfile import NamedTemporaryFile
 
790
  "type": "derived"
791
  }
792
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
793
  }
794
  ],
795
  "relationships": [
 
812
  "OrderItem": "M"
813
  },
814
  "attributes": []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
815
  }
816
  ]
817
  }
 
840
  dot.attr('node', fontname='Arial', fontsize='10', color='#404040')
841
  dot.attr('edge', fontname='Arial', fontsize='9', color='#4a4a4a')
842
 
843
+ entity_colors = {
844
+ 'strong': '#BEBEBE',
845
+ 'weak': '#FFF9C4'
846
+ }
847
+
848
+ attribute_colors = {
849
+ 'primary_key': '#A8E6CF',
850
+ 'partial_key': '#FFB3BA',
851
+ 'multivalued': '#B8D4F1',
852
+ 'derived': '#F0F8FF',
853
+ 'composite': '#E8E8E8',
854
+ 'regular': '#D4D4D4'
855
+ }
856
+
857
+ relationship_colors = {
858
+ 'regular': '#E8E8E8',
859
+ 'identifying': '#B8D4F1',
860
+ 'isa': '#F0F0F0'
861
+ }
862
 
863
  font_color = 'black'
864
 
865
  entities = data.get('entities', [])
866
  relationships = data.get('relationships', [])
867
 
 
868
  for entity in entities:
869
  entity_name = entity.get('name')
870
  entity_type = entity.get('type', 'strong')
 
873
  if not entity_name:
874
  continue
875
 
876
+ entity_color = entity_colors.get(entity_type, entity_colors['strong'])
877
+
878
  if entity_type == 'weak':
879
  dot.node(
880
  entity_name,
881
  entity_name,
882
  shape='box',
883
  style='filled,rounded',
884
+ fillcolor=entity_color,
885
  fontcolor=font_color,
886
  color='#404040',
887
  penwidth='3',
 
895
  entity_name,
896
  shape='box',
897
  style='filled,rounded',
898
+ fillcolor=entity_color,
899
  fontcolor=font_color,
900
  color='#404040',
901
  penwidth='1',
 
909
  attr_type = attr.get('type', 'regular')
910
 
911
  attr_id = f"{entity_name}_attr_{i}"
912
+ attr_color = attribute_colors.get(attr_type, attribute_colors['regular'])
913
 
914
  if attr_type == 'primary_key':
915
  dot.node(
 
917
  f'{attr_name} (PK)',
918
  shape='ellipse',
919
  style='filled,rounded',
920
+ fillcolor=attr_color,
921
  fontcolor=font_color,
922
  color='#404040',
923
  width='1.2',
 
930
  f'{attr_name} (Partial)',
931
  shape='ellipse',
932
  style='filled,rounded,dashed',
933
+ fillcolor=attr_color,
934
  fontcolor=font_color,
935
  color='#404040',
936
  width='1.2',
 
943
  attr_name,
944
  shape='ellipse',
945
  style='filled,rounded',
946
+ fillcolor=attr_color,
947
  fontcolor=font_color,
948
  color='#404040',
949
  penwidth='3',
 
957
  f'/{attr_name}/',
958
  shape='ellipse',
959
  style='filled,rounded,dashed',
960
+ fillcolor=attr_color,
961
  fontcolor=font_color,
962
  color='#404040',
963
  width='1.2',
 
970
  attr_name,
971
  shape='ellipse',
972
  style='filled,rounded',
973
+ fillcolor=attr_color,
974
  fontcolor=font_color,
975
  color='#404040',
976
  width='1.2',
977
  height='0.6',
978
  fontsize='10'
979
  )
980
+ else:
981
  dot.node(
982
  attr_id,
983
  attr_name,
984
  shape='ellipse',
985
  style='filled,rounded',
986
+ fillcolor=attr_color,
987
  fontcolor=font_color,
988
  color='#404040',
989
  width='1.2',
 
1009
 
1010
  if parent and children:
1011
  isa_id = f"isa_{rel_name}"
1012
+ isa_color = relationship_colors.get('isa', relationship_colors['regular'])
1013
 
1014
  dot.node(
1015
  isa_id,
1016
  'ISA',
1017
  shape='triangle',
1018
  style='filled,rounded',
1019
+ fillcolor=isa_color,
1020
  fontcolor=font_color,
1021
  color='#404040',
1022
  penwidth='2',
 
1031
  dot.edge(isa_id, child, color='#4a4a4a', len='2.0')
1032
 
1033
  elif len(entities_involved) >= 2:
1034
+ rel_color = relationship_colors.get(rel_type, relationship_colors['regular'])
1035
+
1036
  if rel_type == 'identifying':
1037
  dot.node(
1038
  rel_name,
1039
  rel_name,
1040
  shape='diamond',
1041
  style='filled,rounded',
1042
+ fillcolor=rel_color,
1043
  fontcolor=font_color,
1044
  color='#404040',
1045
  penwidth='3',
 
1053
  rel_name,
1054
  shape='diamond',
1055
  style='filled,rounded',
1056
+ fillcolor=rel_color,
1057
  fontcolor=font_color,
1058
  color='#404040',
1059
  penwidth='1',
 
1065
  for j, attr in enumerate(rel_attributes):
1066
  attr_name = attr.get('name', '')
1067
  attr_id = f"{rel_name}_attr_{j}"
1068
+ attr_color = attribute_colors['regular']
1069
 
1070
  dot.node(
1071
  attr_id,
1072
  attr_name,
1073
  shape='ellipse',
1074
  style='filled,rounded',
1075
+ fillcolor=attr_color,
1076
  fontcolor=font_color,
1077
  color='#404040',
1078
  width='1.0',