37
37
"""
38
38
from enum import Enum , auto
39
39
from pathlib import Path
40
- from typing import Any , List , Dict
40
+ from typing import Any , List , Dict , Union , Optional as Nullable
41
41
42
42
from pyTooling .Decorators import export
43
43
from pyTooling .MetaClasses import ExtendedType
44
- from pyTooling .Graph import Graph as pyToolingGraph
44
+ from pyTooling .Graph import Graph as pyToolingGraph , Subgraph as pyToolingSubgraph
45
45
from pyTooling .Tree import Node as pyToolingNode
46
46
47
47
@@ -289,7 +289,7 @@ def ToStringLines(self, indent: int = 2) -> List[str]:
289
289
290
290
291
291
@export
292
- class Graph (BaseWithData ):
292
+ class BaseGraph (BaseWithData ):
293
293
_subgraphs : Dict [str , 'Subgraph' ]
294
294
_nodes : Dict [str , Node ]
295
295
_edges : Dict [str , Edge ]
@@ -340,6 +340,9 @@ def AddEdge(self, edge: Edge) -> Edge:
340
340
self ._edges [edge ._id ] = edge
341
341
return edge
342
342
343
+ def GetEdge (self , edgeName : str ) -> Edge :
344
+ return self ._edges [edgeName ]
345
+
343
346
def OpeningTag (self , indent : int = 1 ) -> str :
344
347
return f"""\
345
348
{ ' ' * indent } <graph id="{ self ._id } "
@@ -368,13 +371,49 @@ def ToStringLines(self, indent: int = 1) -> List[str]:
368
371
369
372
370
373
@export
371
- class Subgraph (Node , Graph ):
374
+ class Graph (BaseGraph ):
375
+ _document : 'GraphMLDocument'
376
+ _ids : Dict [str , Union [Node , Edge , 'Subgraph' ]]
377
+
378
+ def __init__ (self , document : 'GraphMLDocument' , identifier : str ):
379
+ super ().__init__ (identifier )
380
+ self ._document = document
381
+ self ._ids = {}
382
+
383
+ def GetByID (self , identifier : str ) -> Union [Node , Edge , 'Subgraph' ]:
384
+ return self ._ids [identifier ]
385
+
386
+ def AddSubgraph (self , subgraph : 'Subgraph' ) -> 'Subgraph' :
387
+ result = super ().AddSubgraph (subgraph )
388
+ self ._ids [subgraph ._subgraphID ] = subgraph
389
+ subgraph ._root = self
390
+ return result
391
+
392
+ def AddNode (self , node : Node ) -> Node :
393
+ result = super ().AddNode (node )
394
+ self ._ids [node ._id ] = node
395
+ return result
396
+
397
+ def AddEdge (self , edge : Edge ) -> Edge :
398
+ result = super ().AddEdge (edge )
399
+ self ._ids [edge ._id ] = edge
400
+ return result
401
+
402
+
403
+ @export
404
+ class Subgraph (Node , BaseGraph ):
372
405
_subgraphID : str
406
+ _root : Nullable [Graph ]
373
407
374
408
def __init__ (self , nodeIdentifier : str , graphIdentifier : str ):
375
409
super ().__init__ (nodeIdentifier )
376
410
377
411
self ._subgraphID = graphIdentifier
412
+ self ._root = None
413
+
414
+ @property
415
+ def RootGraph (self ) -> Graph :
416
+ return self ._root
378
417
379
418
@property
380
419
def SubgraphID (self ) -> str :
@@ -384,6 +423,16 @@ def SubgraphID(self) -> str:
384
423
def HasClosingTag (self ) -> bool :
385
424
return True
386
425
426
+ def AddNode (self , node : Node ) -> Node :
427
+ result = super ().AddNode (node )
428
+ self ._root ._ids [node ._id ] = node
429
+ return result
430
+
431
+ def AddEdge (self , edge : Edge ) -> Edge :
432
+ result = super ().AddEdge (edge )
433
+ self ._root ._ids [edge ._id ] = edge
434
+ return result
435
+
387
436
def Tag (self , indent : int = 2 ) -> str :
388
437
raise NotImplementedError ()
389
438
@@ -399,7 +448,7 @@ def OpeningTag(self, indent: int = 1) -> str:
399
448
"""
400
449
401
450
def ClosingTag (self , indent : int = 2 ) -> str :
402
- return Graph .ClosingTag (self , indent )
451
+ return BaseGraph .ClosingTag (self , indent )
403
452
404
453
def ToStringLines (self , indent : int = 2 ) -> List [str ]:
405
454
lines = [super ().OpeningTag (indent )]
@@ -435,11 +484,11 @@ class GraphMLDocument(Base):
435
484
def __init__ (self , identifier : str = "G" ):
436
485
super ().__init__ ()
437
486
438
- self ._graph = Graph (identifier )
487
+ self ._graph = Graph (self , identifier )
439
488
self ._keys = {}
440
489
441
490
@property
442
- def Graph (self ) -> Graph :
491
+ def Graph (self ) -> BaseGraph :
443
492
return self ._graph
444
493
445
494
@property
@@ -457,37 +506,91 @@ def HasKey(self, keyName: str) -> bool:
457
506
return keyName in self ._keys
458
507
459
508
def FromGraph (self , graph : pyToolingGraph ):
509
+ document = self
460
510
self ._graph ._id = graph ._name
461
511
462
512
nodeValue = self .AddKey (Key ("nodeValue" , AttributeContext .Node , "value" , AttributeTypes .String ))
463
513
edgeValue = self .AddKey (Key ("edgeValue" , AttributeContext .Edge , "value" , AttributeTypes .String ))
464
514
465
- for vertex in graph .IterateVertices ():
466
- newNode = Node (vertex ._id )
467
- newNode .AddData (Data (nodeValue , vertex ._value ))
468
- for key , value in vertex ._dict .items ():
469
- if self .HasKey (str (key )):
470
- nodeKey = self .GetKey (f"node{ key !s} " )
471
- else :
472
- nodeKey = self .AddKey (Key (f"node{ key !s} " , AttributeContext .Node , str (key ), AttributeTypes .String ))
473
- newNode .AddData (Data (nodeKey , value ))
474
-
475
- self ._graph .AddNode (newNode )
476
-
477
- for edge in graph .IterateEdges ():
478
- source = self ._graph .GetNode (edge ._source ._id )
479
- target = self ._graph .GetNode (edge ._destination ._id )
480
-
481
- newEdge = Edge (edge ._id , source , target )
482
- newEdge .AddData (Data (edgeValue , edge ._value ))
483
- for key , value in edge ._dict .items ():
484
- if self .HasKey (str (key )):
485
- edgeKey = self .GetKey (f"edge{ key !s} " )
486
- else :
487
- edgeKey = self .AddKey (Key (f"edge{ key !s} " , AttributeContext .Edge , str (key ), AttributeTypes .String ))
488
- newEdge .AddData (Data (edgeKey , value ))
489
-
490
- self ._graph .AddEdge (newEdge )
515
+ def translateGraph (rootGraph : Graph , pyTGraph : pyToolingGraph ):
516
+ for vertex in pyTGraph .IterateVertices ():
517
+ newNode = Node (vertex ._id )
518
+ newNode .AddData (Data (nodeValue , vertex ._value ))
519
+ for key , value in vertex ._dict .items ():
520
+ if document .HasKey (str (key )):
521
+ nodeKey = document .GetKey (f"node{ key !s} " )
522
+ else :
523
+ nodeKey = document .AddKey (Key (f"node{ key !s} " , AttributeContext .Node , str (key ), AttributeTypes .String ))
524
+ newNode .AddData (Data (nodeKey , value ))
525
+
526
+ rootGraph .AddNode (newNode )
527
+
528
+ for edge in pyTGraph .IterateEdges ():
529
+ source = rootGraph .GetByID (edge ._source ._id )
530
+ target = rootGraph .GetByID (edge ._destination ._id )
531
+
532
+ newEdge = Edge (edge ._id , source , target )
533
+ newEdge .AddData (Data (edgeValue , edge ._value ))
534
+ for key , value in edge ._dict .items ():
535
+ if self .HasKey (str (key )):
536
+ edgeKey = self .GetBy (f"edge{ key !s} " )
537
+ else :
538
+ edgeKey = self .AddKey (Key (f"edge{ key !s} " , AttributeContext .Edge , str (key ), AttributeTypes .String ))
539
+ newEdge .AddData (Data (edgeKey , value ))
540
+
541
+ rootGraph .AddEdge (newEdge )
542
+
543
+ for link in pyTGraph .IterateLinks ():
544
+ source = rootGraph .GetByID (link ._source ._id )
545
+ target = rootGraph .GetByID (link ._destination ._id )
546
+
547
+ newEdge = Edge (link ._id , source , target )
548
+ newEdge .AddData (Data (edgeValue , link ._value ))
549
+ for key , value in link ._dict .items ():
550
+ if self .HasKey (str (key )):
551
+ edgeKey = self .GetKey (f"link{ key !s} " )
552
+ else :
553
+ edgeKey = self .AddKey (Key (f"link{ key !s} " , AttributeContext .Edge , str (key ), AttributeTypes .String ))
554
+ newEdge .AddData (Data (edgeKey , value ))
555
+
556
+ rootGraph .AddEdge (newEdge )
557
+
558
+ def translateSubgraph (nodeGraph : Subgraph , pyTSubgraph : pyToolingSubgraph ):
559
+ rootGraph = nodeGraph .RootGraph
560
+
561
+ for vertex in pyTSubgraph .IterateVertices ():
562
+ newNode = Node (vertex ._id )
563
+ newNode .AddData (Data (nodeValue , vertex ._value ))
564
+ for key , value in vertex ._dict .items ():
565
+ if self .HasKey (str (key )):
566
+ nodeKey = self .GetKey (f"node{ key !s} " )
567
+ else :
568
+ nodeKey = self .AddKey (Key (f"node{ key !s} " , AttributeContext .Node , str (key ), AttributeTypes .String ))
569
+ newNode .AddData (Data (nodeKey , value ))
570
+
571
+ nodeGraph .AddNode (newNode )
572
+
573
+ for edge in pyTSubgraph .IterateEdges ():
574
+ source = nodeGraph .GetNode (edge ._source ._id )
575
+ target = nodeGraph .GetNode (edge ._destination ._id )
576
+
577
+ newEdge = Edge (edge ._id , source , target )
578
+ newEdge .AddData (Data (edgeValue , edge ._value ))
579
+ for key , value in edge ._dict .items ():
580
+ if self .HasKey (str (key )):
581
+ edgeKey = self .GetKey (f"edge{ key !s} " )
582
+ else :
583
+ edgeKey = self .AddKey (Key (f"edge{ key !s} " , AttributeContext .Edge , str (key ), AttributeTypes .String ))
584
+ newEdge .AddData (Data (edgeKey , value ))
585
+
586
+ nodeGraph .AddEdge (newEdge )
587
+
588
+ for subgraph in graph .Subgraphs :
589
+ nodeGraph = Subgraph (subgraph .Name , "sg" + subgraph .Name )
590
+ self ._graph .AddSubgraph (nodeGraph )
591
+ translateSubgraph (nodeGraph , subgraph )
592
+
593
+ translateGraph (self ._graph , graph )
491
594
492
595
def FromTree (self , tree : pyToolingNode ):
493
596
self ._graph ._id = tree ._id
0 commit comments