1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2026-07-05 07:10:48 +02:00
lodel2_mirror/EditorialModel/backend/graphviz.py

129 lines
5.4 KiB
Python

# -*- coding: utf-8 -*-
import datetime
import EditorialModel
from EditorialModel.classtypes import EmClassType
from EditorialModel.types import EmType
from EditorialModel.fields import EmField
from Lodel.utils.mlstring import MlString
from EditorialModel.backend.dummy_backend import EmBackendDummy
class EmBackendGraphviz(EmBackendDummy):
## @brief Constructor
# @param dot_fname str : The filename where we want to save the dot repr of the EM
def __init__(self, dot_fname):
self.edges = ""
self.dot_fname = dot_fname
#with open(dot_file, 'w+') as dot_fp:
## @brief Not implementend
# @warning Not implemented
def load(self):
raise NotImplementedError(self.__class__.__name__+' cannot load an EM')
## @brief Save an EM in a dot file
# @param em model : The EM to save
# @warning hardcoded classtype
def save(self, em):
self.edges = ""
with open(self.dot_fname, 'w') as dotfp:
dotfp.write("digraph G {\n\trankdir = BT\n")
dotfp.write('subgraph cluster_classtype {\nstyle="invis"\n')
for ct in [ 'entity', 'entry', 'person' ]:
dotfp.write('\n\nct%s [ label="classtype %s" shape="tripleoctagon" ]\n'%(ct, ct))
dotfp.write("}\n")
dotfp.write('subgraph cluster_class {\nstyle="invis"\n')
for c in em.classes():
dotfp.write(self._component_node(c, em))
cn = c.__class__.__name__
cid = self._component_id(c)
self.edges += cid+' -> ct%s [ style="dashed" ]\n'%c.classtype
dotfp.write("}\n")
#dotfp.write('subgraph cluster_type {\nstyle="invis"\n')
for c in em.components(EmType):
dotfp.write(self._component_node(c, em))
cn = c.__class__.__name__
cid = self._component_id(c)
self.edges += cid+' -> '+self._component_id(c.em_class)+' [ style="dotted" ]\n'
for nat, sups in c.superiors().items():
for sup in sups:
self.edges += cid+' -> '+self._component_id(sup)+' [ label="%s" color="green" ]\n'%nat
#dotfp.write("}\n")
"""
for rf in [ f for f in em.components(EmField) if f.fieldtype == 'rel2type']:
dotfp.write(self._component_node(rf, em))
cid = self._component_id(rf)
self.edges += cid+' -> '+self._component_id(rf.em_class)+'\n'
self.edges += cid+' -> '+self._component_id(em.component(rf.rel_to_type_id))+'\n'
"""
dotfp.write(self.edges)
dotfp.write("\n}")
pass
@staticmethod
def _component_id(c):
return 'emcomp%d'%c.uid
def _component_node(self, c, em):
ret = "\t"+EmBackendGraphviz._component_id(c)
cn = c.__class__.__name__
rel_field = ""
if cn == 'EmClass':
ret += '[ label="EmClass %s", shape="%s" ]'%(c.name.replace('"','\\"'), 'doubleoctagon')
elif cn == 'EmField':
str_def = '[ label="Rel2Type {fname}|{{{records}}}", shape="record"]'
records = ' | '.join([f.name for f in em.components('EmField') if f.rel_field_id == c.uid])
ret += str_def.format(fname=c.name.replace('"','\\"'), records=records)
elif cn == 'EmType':
ret += '[ label="%s %s '%(cn, c.name.replace('"','\\"'))
cntref = 0
first = True
for f in [ f for f in c.fields() if f.name not in c.em_class.default_fields_list().keys()]:
if f.rel_field_id is None:
if f.fieldtype == 'rel2type':
rel_node_id = '%s%s%s'%(EmBackendGraphviz._component_id(c), EmBackendGraphviz._component_id(em.component(f.rel_to_type_id)), f.uid)
rel_node = '\t%s [ label="rel2type %s'% (rel_node_id, f.name)
if len(f.rel_to_type_fields()) > 0:
#rel_node += '| {'
first = True
for rf in f.rel_to_type_fields():
rel_node += ' | '
if first:
rel_node += '{ '
first = False
rel_node += rf.name
rel_node += '}' if len(f.rel_to_type_fields()) > 0 else ''
rel_node += '" shape="record"]\n'
rel_field += rel_node
ref_node = EmBackendGraphviz._component_id(em.component(f.rel_to_type_id))
self.edges += '%s:f%d -> %s [ color="purple" dir="both" ]\n'%(EmBackendGraphviz._component_id(c), cntref, rel_node_id)
self.edges += '%s -> %s [color="purple" dir="both" ]\n'%(rel_node_id, ref_node)
ret += '|'
if first:
ret += ' { '
first = False
if f.fieldtype == 'rel2type':
ret += '<f%d> '%cntref
cntref += 1
ret += f.name
ret += '}" shape="record" color="%s" ]'%('blue' if cn == 'EmType' else 'red')
else:
return ""
ret +="\n"+rel_field
return ret