def build(self, tree): self.diagram = Diagram() diagram = self.instantiate(self.diagram, tree) self.bind_edges(diagram) if len(self.diagram.lanes) == 0: self.diagram.lanes.append(NodeGroup.get(None)) for node in self.diagram.nodes: if node.lane is None: edges = DiagramEdge.find(None, node) parents = [e.node1 for e in edges if e.node1.lane] parents.sort(key=lambda x: x.order) if parents: node.lane = parents[0].lane node.lane.nodes.append(node) else: node.lane = self.diagram.lanes[0] node.lane.nodes.append(node) for lane in diagram.lanes: if len(lane.nodes) == 0: diagram.lanes.remove(lane) return diagram
class DiagramTreeBuilder(object): def build(self, tree): self.diagram = Diagram() diagram = self.instantiate(self.diagram, tree) self.bind_edges(diagram) if len(self.diagram.lanes) == 0: self.diagram.lanes.append(NodeGroup.get(None)) for node in self.diagram.nodes: if node.lane is None: edges = DiagramEdge.find(None, node) parents = [e.node1 for e in edges if e.node1.lane] parents.sort(key=lambda x: x.order) if parents: node.lane = parents[0].lane node.lane.nodes.append(node) else: node.lane = self.diagram.lanes[0] node.lane.nodes.append(node) for lane in diagram.lanes: if len(lane.nodes) == 0: diagram.lanes.remove(lane) return diagram def belong_to(self, node, lane): if lane and node.lane and node.lane != lane: print(node, node.lane, lane) msg = "DiagramNode could not belong to two lanes" raise RuntimeError(msg) node.group = self.diagram if lane: node.lane = lane lane.nodes.append(node) if node not in self.diagram.nodes: self.diagram.nodes.append(node) def instantiate(self, group, tree, lane=None): for stmt in tree.stmts: if isinstance(stmt, parser.Node): node = DiagramNode.get(stmt.id) node.set_attributes(stmt.attrs) self.belong_to(node, lane) elif isinstance(stmt, parser.Edge): from_nodes = [DiagramNode.get(n) for n in stmt.from_nodes] to_nodes = [DiagramNode.get(n) for n in stmt.to_nodes] for node in from_nodes + to_nodes: self.belong_to(node, lane) for node1 in from_nodes: for node2 in to_nodes: edge = DiagramEdge.get(node1, node2) edge.set_dir(stmt.edge_type) edge.set_attributes(stmt.attrs) elif isinstance(stmt, parser.Lane): _lane = NodeGroup.get(stmt.id) if _lane not in self.diagram.lanes: self.diagram.lanes.append(_lane) self.instantiate(group, stmt, _lane) elif isinstance(stmt, parser.Attr): if lane: lane.set_attribute(stmt) else: self.diagram.set_attribute(stmt) elif isinstance(stmt, parser.Extension): if stmt.type == 'class': name = unquote(stmt.name) Diagram.classes[name] = stmt if stmt.type == 'plugin': self.diagram.set_plugin(stmt.name, stmt.attrs) elif isinstance(stmt, parser.Statements): self.instantiate(group, stmt, lane) group.update_order() return group def bind_edges(self, group): for node in group.nodes: if isinstance(node, DiagramNode): group.edges += DiagramEdge.find(node) else: self.bind_edges(node)