示例:Gaphor服务

在此示例中,我们将演示一个较为复杂的实现:Gaphor中的服务组件通过入口点定义。每个服务均为独立类,其构造函数参数通过名称自动匹配其他服务实例,从而实现服务间的依赖注入。

其实现方式如下所示:

# entry point name: my_service
class MyService:
    ...

# entry point name: my_other_service
class MyOtherService:
    def __init__(self, my_service):
        ...

首先加载入口点配置。

from gaphor.entrypoint import load_entry_points

entry_points = load_entry_points("gaphor.services")

entry_points
{'auto_layout': gaphor.plugins.autolayout.pydot.AutoLayoutService,
 'component_registry': gaphor.services.componentregistry.ComponentRegistry,
 'console_window': gaphor.plugins.console.consolewindow.ConsoleWindow,
 'diagram_align': gaphor.ui.diagramalign.DiagramAlign,
 'diagram_export': gaphor.plugins.diagramexport.export.DiagramExport,
 'diagrams': gaphor.ui.diagrams.Diagrams,
 'element_dispatcher': gaphor.core.modeling.elementdispatcher.ElementDispatcher,
 'element_editor': gaphor.ui.elementeditor.ElementEditor,
 'element_factory': gaphor.core.modeling.elementfactory.ElementFactory,
 'event_manager': gaphor.core.eventmanager.EventManager,
 'export_menu': gaphor.ui.menufragment.MenuFragment,
 'file_manager': gaphor.ui.filemanager.FileManager,
 'html_report': gaphor.plugins.htmlreport.report.HtmlReportExport,
 'main_window': gaphor.ui.mainwindow.MainWindow,
 'model_browser': gaphor.ui.modelbrowser.ModelBrowser,
 'model_changed': gaphor.ui.modelchanged.ModelChanged,
 'modeling_language': gaphor.services.modelinglanguage.ModelingLanguageService,
 'properties': gaphor.services.properties.Properties,
 'recent_files': gaphor.ui.recentfiles.RecentFiles,
 'recovery': gaphor.storage.recovery.Recovery,
 'sanitizer': gaphor.UML.sanitizerservice.SanitizerService,
 'toolbox': gaphor.ui.toolbox.Toolbox,
 'tools_menu': gaphor.ui.menufragment.MenuFragment,
 'undo_actions': gaphor.ui.undoactions.UndoActions,
 'undo_manager': gaphor.services.undomanager.UndoManager}

现在为每个服务在模型中创建对应的组件。

from gaphor import UML
from gaphor.core.modeling import ElementFactory

element_factory = ElementFactory()

def create_component(name):
    c = element_factory.create(UML.Component)
    c.name = name
    return c

components = {name: create_component(name) for name in entry_points}
components
{'auto_layout': <gaphor.UML.uml.Component element 1325c732-4653-11f1-8e0f-3a5143801441>,
 'component_registry': <gaphor.UML.uml.Component element 1325ca5c-4653-11f1-8e0f-3a5143801441>,
 'console_window': <gaphor.UML.uml.Component element 1325cbb0-4653-11f1-8e0f-3a5143801441>,
 'diagram_align': <gaphor.UML.uml.Component element 1325cc96-4653-11f1-8e0f-3a5143801441>,
 'diagram_export': <gaphor.UML.uml.Component element 1325cd5e-4653-11f1-8e0f-3a5143801441>,
 'diagrams': <gaphor.UML.uml.Component element 1325ce44-4653-11f1-8e0f-3a5143801441>,
 'element_dispatcher': <gaphor.UML.uml.Component element 1325cf16-4653-11f1-8e0f-3a5143801441>,
 'element_editor': <gaphor.UML.uml.Component element 1325cfca-4653-11f1-8e0f-3a5143801441>,
 'element_factory': <gaphor.UML.uml.Component element 1325d074-4653-11f1-8e0f-3a5143801441>,
 'event_manager': <gaphor.UML.uml.Component element 1325d11e-4653-11f1-8e0f-3a5143801441>,
 'export_menu': <gaphor.UML.uml.Component element 1325d1be-4653-11f1-8e0f-3a5143801441>,
 'file_manager': <gaphor.UML.uml.Component element 1325d286-4653-11f1-8e0f-3a5143801441>,
 'html_report': <gaphor.UML.uml.Component element 1325d330-4653-11f1-8e0f-3a5143801441>,
 'main_window': <gaphor.UML.uml.Component element 1325d3da-4653-11f1-8e0f-3a5143801441>,
 'model_browser': <gaphor.UML.uml.Component element 1325d47a-4653-11f1-8e0f-3a5143801441>,
 'model_changed': <gaphor.UML.uml.Component element 1325d524-4653-11f1-8e0f-3a5143801441>,
 'modeling_language': <gaphor.UML.uml.Component element 1325d5c4-4653-11f1-8e0f-3a5143801441>,
 'properties': <gaphor.UML.uml.Component element 1325d664-4653-11f1-8e0f-3a5143801441>,
 'recent_files': <gaphor.UML.uml.Component element 1325d754-4653-11f1-8e0f-3a5143801441>,
 'recovery': <gaphor.UML.uml.Component element 1325d808-4653-11f1-8e0f-3a5143801441>,
 'sanitizer': <gaphor.UML.uml.Component element 1325d8a8-4653-11f1-8e0f-3a5143801441>,
 'toolbox': <gaphor.UML.uml.Component element 1325d952-4653-11f1-8e0f-3a5143801441>,
 'tools_menu': <gaphor.UML.uml.Component element 1325d9fc-4653-11f1-8e0f-3a5143801441>,
 'undo_actions': <gaphor.UML.uml.Component element 1325daec-4653-11f1-8e0f-3a5143801441>,
 'undo_manager': <gaphor.UML.uml.Component element 1325db8c-4653-11f1-8e0f-3a5143801441>}

当所有组件完成映射后,系统将根据构造函数参数名称自动建立组件间的依赖关系。

import inspect

for name, cls in entry_points.items():
    for param_name in inspect.signature(cls).parameters:
        if param_name not in components:
            continue

        dep = element_factory.create(UML.Usage)
        dep.client = components[name]
        dep.supplier = components[param_name]

当模型中所有元素就绪后,即可创建图表。将组件及其依赖关系拖放至图表中,系统将通过自动布局功能智能排版。

为使依赖关系呈现更佳视觉效果,需添加样式表。若通过图形界面新建图表,该元素将自动加载。

from gaphor.core.modeling import StyleSheet
from gaphor.diagram.drop import drop

element_factory.create(StyleSheet)
diagram = element_factory.create(UML.Diagram)

for element in element_factory.lselect():
    drop(element, diagram, x=0, y=0)

最后一步是图表布局与绘制。

from gaphor.extensions.ipython import auto_layout, draw

auto_layout(diagram)

draw(diagram, format="svg")
_images/5e71946d1453e91356ca25d3f7ffaa5a72430f93b0833b8ad6d17560dd211846.svg

至此完成。如图所示,很多服务组件都依赖于EventManager事件管理器。