欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

eclipse emf_构建一个Eclipse插件来浏览EMF模型中的内容

程序员文章站 2024-02-11 12:49:52
...

通常,EMF项目资源(例如EMF Ecore模型)在查看器中显示为单个对象(请参见图1的左侧)。 这样做的局限性在于,如果不打开关联的编辑器就无法浏览模型。 当开发依赖于领域模型时,这可能尤其有害。 解决此问题的一种方法是建立一个自定义视图,该视图将提供对所需域模型内容的访问。 我们可以从头开始构建此插件,也可以使用现有框架来简化开发工作。 以下概述并详细介绍了创建此类插件的过程。 在本文的最后,我们将提供一个查看器插件,该插件可用于导航Ecore模型(请参见图1的右侧)。

图1.导航器的类型
eclipse emf_构建一个Eclipse插件来浏览EMF模型中的内容

背景

我们知道从这个ModelNavigator插件中可以获得什么,但是在继续进行开发之前,我们需要对将要使用的Eclipse组件有基本的了解。 我们想要构建一个显示模型层次结构的树查看器。 树查看器的详细信息不在本文讨论范围之内; 有关更多详细信息,请参见参考资料 要注意的一个重要方面是,树查看器通过称为内容提供程序的适配器访问模型对象,并确定应如何通过标签提供程序将对象可视化。 以下各节详细介绍了如何访问内容和标签提供者的数据,以及如何显示模型导航器。

EMF.Edit框架

EMF.Edit框架通常用于构建EMF模型的编辑器。 为了构建这些编辑器,该框架提供了命令代码生成功能和其他类,以提供对模型的编程访问。 该框架提供的另一组功能(对我们而言最重要)是方便使用的类,这些类允许在查看器中显示EMF模型。 该框架通过通用内容和标签提供程序提供此访问,这些内容和标签提供程序使用特定类型的EMF对象的适配器来显示模型。 这些是AdapterFactoryContentProviderAdapterFactoryLabelProvider类,它们通过委派给知道如何导航EMF模型的项目提供程序适配器来向EMF对象的查看器提供对象,标签和图像。 此方案如图2所示。它对我们的项目特别有用,因为它使我们不必知道如何使模型适应视图。 我们只是委托给这些通用提供程序。

图2.改编自Eclipse帮助的EMF.Edit
eclipse emf_构建一个Eclipse插件来浏览EMF模型中的内容

该框架包含用于各种EMF模型类型的这些项目提供程序。 但是,我们大多数人都不想为每种模型类型构建单独的导航器。 我们想要从同一导航器访问所有模型内容。 这是组成适配器工厂的地方。它将通过提供一个适配器工厂来显示来自多个EMF模型的对象,该适配器工厂能够适应来自多个模型的对象的并集。

ComposedAdapterFactory类是EMF.Edit便利类中的另一个,它充当与其他适配器工厂的公共接口。 正如我们稍后将看到的那样,这样做的优点是,导航器只需要包含我们感兴趣的模型类型的项目提供程序,即可作为组合适配器工厂的一部分。 然后,组成的适配器工厂仅将其实现委派给这些其他提供程序。 例如,我们可以使导航器显示生成器模型,Ecore模型,UML模型等。当我们的查看器尝试显示这些模型时,内容和标签提供者将仅委托给适配器工厂,然后委托给适配器工厂。适当的项目提供者,这使我们的开发工作更加轻松,并使ModelNavigator得以扩展以支持多个领域模型。

通用导航器框架

现在,我们有了一个完整的框架,可以在ModelNavigator中访问模型内​​容,我们需要的另一个组件是将放置导航器的实际查看器。 可以扩展视图插件并实现我们自己的视图部分,该部分将在树形视图中显示所需的内容。 但是,已经存在一个框架,用于将来自各个域的内容组合到单个视图中,从而允许用户在查看器中操纵和导航编辑器模型。 该框架在Eclipse V3.2中作为CNF org.eclipse.ui.navigator引入,并允许开发人员为单个导航器贡献内容,标签,操作,过滤器和其他功能。 它提供了一种集成导航查看器并提供统一用户体验的方法。

CNF为所有编辑器模型集成商支持一个查看器,允许非资源驱动的模型内容,并允许用户选择要在其集成的查看器中查看的内容。 org.eclipse.ui.navigator.resources插件是该框架在运行的示例,我们以Project Explorer视图的形式对其进行了演示。 它为IResource模型提供了声明式查看器扩展。 该框架为我们提供了构建查看器的最快方法,它处理了查看器实现的细节,仅要求我们为模型实现内容和标签提供程序。 它还提供了将插件扩展到其他模型内容的空间,并可以利用查看器中框架的更高级功能(例如,排序器,过滤器,拖放操作等)。

现在,我们准备好查看这些组件的运行情况,并开始创建模型导航插件。

简单的导航器

要创建我们的ModelNavigator,我们将采用两步法。 首先,我们设置插件的基本结构并定义其行为。 然后,我们将扩展这个简单的插件以显示EMF模型内容。

ModelNavigator项目

创建我们的ModelNavigator的第一步是创建一个插件项目。 为此,我们使用新的项目向导: File> New> Project ,选择Plug-in Project ,然后单击Next

我们将命名我们的插件项目ModelNavigator ,将插件ID设置为com.ibm.navigator.example.modelnavigator ,将**器设置为com.ibm.navigator.example.modelnavigator.ModelNavigatorPlugin ,然后单击Finish

图3.创建插件项目
eclipse emf_构建一个Eclipse插件来浏览EMF模型中的内容

创建视图

我们准备开始开发我们的插件。 第一步是创建将容纳我们的导航器的视图。 为此,我们在插件中进行了必要的扩展,以创建视图部件和将在其中显示视图的类别。 在插件xml文件中,我们添加了视图扩展。

在扩展标签中:

  • 点击添加
  • 扩展点选项卡下,选择org.eclipse.ui.views
  • 创建类别:
    • 右键单击org.eclipse.ui.views扩展
    • 选择新建>类别
    • 将名称设置为com.ibm.navigator.example.modelnavigator.mncategory
    • 将ID设置为Model Navigator
  • 创建视图部分:
    • 右键单击org.eclipse.ui.views扩展
    • 选择新建>查看
    • 将标识设置为com.ibm.navigator.example.modelnavigator.mnview
    • 将名称设置为Model Navigator View
    • 将类设置为org.eclipse.ui.navigator.CommonNavigator
    • 将类别设置为com.ibm.navigator.example.modelnavigator.mncategory
  • 将修改保存到项目

如上所述,我们正在将一些实施负担转移给CNF。 关于设置视图方式的重要注意事项是,我们没有创建自己的类来扩展视图的ViewPart ,而是这样做了,因此视图使用了通用的导航器类。 这也意味着我们需要将在类字段中指向的通用导航器类添加到插件的类路径中。 因此,继续并将org.eclipse.ui.navigator添加到Dependencies选项卡上所需的插件中。

设置默认行为并将其合并到CNF

下一步是为我们的插件配置CNF属性,这将决定导航器的默认行为。

首先,我们将视图关联到通用导航器查看器。 在扩展标签中:

  • 点击添加
  • 扩展点选项卡下,选择org.eclipse.ui.navigator.viewer并单击完成
  • 创建查看器:
    • 右键单击org.eclipse.ui.navigator.viewer扩展
    • 选择新建>查看器
    • viewerid设置为我们上面定义的视图的ID( com.ibm.navigator.example.modelnavigator.mnview

导航器插件的行为将由我们绑定到它的内容,绑定到它的动作以及在使用CNF时在插件中设置的其他选项(过滤器,排序器等)决定。 在插件中,包含元素选择查看者可见的扩展名。 内容扩展告诉框架如何在视图中显示内容,操作扩展告诉框架哪些选项可用于视图(上下文菜单等)。 为了使该导航器的基本版本启动并运行,我们将从IResource模型中添加内容和动作绑定,使该插件具有Package Explorer的熟悉感觉。 为此,我们为导航器创建一个viewerContentBinding以添加资源内容扩展,并创建一个viewerActionBinding以添加资源操作扩展。

要添加IResource内容扩展,请从“扩展”选项卡中:

  • 右键单击org.eclipse.ui.navigator.viewer扩展
  • 选择“ 新建”>“ viewerContentBinding”
  • viewerid设置为我们插件的viewpart的ID( com.ibm.navigator.example.modelnavigator.mnview
  • 添加内容绑定:
    • 右键单击我们刚刚创建的viewerContentBinding
    • 选择新建>包含
    • 右键单击我们刚刚创建的include元素
    • 选择新建> contentExtension
    • 将模式设置为org.eclipse.ui.navigator.resourceContent

要绑定IResource操作扩展,请从“扩展”选项卡中:

  • 右键单击org.eclipse.ui.navigator.viewer扩展
  • 选择“ 新建”>“ viewerActionBinding”
  • viewerid设置为我们插件的viewpart的ID( com.ibm.navigator.example.modelnavigator.mnview
  • 添加操作绑定:
    • 右键单击我们刚刚创建的viewerContentBinding
    • 选择新建>包含
    • 右键单击我们刚刚创建的include元素
    • 选择新建> actionExtension
    • 将模式设置为org.eclipse.ui.navigator.resources.*

至此,我们已经建立了导航器的结构。 我们看到了如何告诉导航器框架我们要显示的内容的类型以及如何使导航器起作用。 尽管我们不一定需要添加这些扩展,但是通过添加IResource模型的内容和操作,我们有一个更有用的视图。 现在,我们还知道如何将内容绑定到查看器,甚至可以扩展它以添加自定义或预定义的过滤器。 请参阅相关主题有关这些功能的更多信息。 该导航器仍然不是我们想要的,因此我们需要添加在查看器中显示EMF模型的功能。

添加EMF域内容

为了使EMF域模型内容在我们的导航器中显示,我们需要告知框架您感兴趣的模型,如何从该模型中获取信息以及如何/何时显示它。 这涉及创建内容扩展,导航内容服务可使用该扩展来显示EMF域模型。 通过创建org.eclipse.ui.navigator.navigatorContent插件的扩展来完成这项工作。

导航器内容扩展定义了一个内容提供程序和标签提供程序,可用于为EMF模型的元素提供子对象和父对象。 它还定义了何时可以调用此扩展以提供子级(称为triggerPoints )或父对象(称为possibleChildren triggerPoints 我们还可以修改导航器内容的许多其他属性,以更改插件的行为,例如动作提供程序,通用向导,过滤器等。但是,这些是我们无需创建的额外功能我们的ModelNavigator插件。

首先,我们需要创建一个新的内容扩展,可以在其中指定要由通用导航器使用的内容和标签提供程序,然后我们将实现这些类。

要添加navigatorContent扩展,请从“扩展”选项卡中:

  • 点击添加
  • 扩展点选项卡下,选择org.eclipse.ui.navigator.navigatorContent并单击完成
  • 创建导航器内容:
    • 右键单击org.eclipse.ui.navigator.navigatorContent扩展
    • 选择新建> navigatorContent
    • 将标识设置为com.ibm.navigator.example.modelnavigator.emfModelContent
    • 将名称设置为EMF Model Content
    • 将内容提供者设置为com.ibm.navigator.example.modelnavigator.MNViewContentProvider
    • 将标签提供程序设置为com.ibm.navigator.example.modelnavigator.MNViewLabelProvider
    • 将优先级设置为normal
    • 将activeByDefault设置为true

接下来,我们实现将用作导航器内容的内容和标签提供程序的类。

组成适配器厂

我们将使用EMF.Edit框架执行内容和标签提供程序的实际工作。 因此,我们需要从EMF编辑框架中将内容和标签提供者类创建为适配器工厂的子类。 在创建分别委托给AdapterFactoryContentProviderAdapterFactoryLabelProvider的content和label-provider类之前,我们应该记住,这些适配器工厂已使用不同EMF模型的项目提供者列表实例化。 这意味着我们需要首先创建此提供程序列表,作为组合的适配器工厂。 创建一个名为MNComposedAdapterFactory的新类(“ 文件”>“新建”>“类” )。

图4.创建实现类
eclipse emf_构建一个Eclipse插件来浏览EMF模型中的内容

我们还需要在Dependencies选项卡上将org.eclipse.emf.codegen.ecore.ui添加到所需的插件中。 这将使ComposedAdapterFactory项目提供者可以使用不同的EMF模型类型和其他EMF.Edit便利类。 然后, MNComposedAdapterFactory类的实现类似于清单1。

清单1.我们的ComposedAdapterFactory类
...
public class MNComposedAdapterFactory
{
    private static ComposedAdapterFactory mnCompAdapterFactory;

    public final static ComposedAdapterFactory getAdapterFactory()
    {
        if (mnCompAdapterFactory == null)
            mnCompAdapterFactory = new ComposedAdapterFactory(createFactoryList());
        return mnCompAdapterFactory;
    }

    public final static ArrayList<AdapterFactory> createFactoryList()
    {
        ArrayList<AdapterFactory> factories = new ArrayList<AdapterFactory>();
        factories.add(new ResourceItemProviderAdapterFactory());
        factories.add(new EcoreItemProviderAdapterFactory());
        factories.add(new ReflectiveItemProviderAdapterFactory());
        return factories;
    }
}

需要注意的重要部分是我们正在创建一个静态方法来创建项目提供者列表。 在这些项目提供程序中, EcoreItemProviderAdapterFactory将是我们希望适配器工厂委托给的对象,以便为Ecore模型提供内容和标签。

内容和标签提供者

以类似的方式,创建我们在navigatorContent扩展详细信息中指定的content和label-provider类。

从内容提供者( MNViewContentProvider )开始,通过在扩展详细信息面板中单击提供者名称旁边的链接,或在“ 文件”>“新建”>“类”对话框中创建 代替为内容提供者实现ITreeContentProvider接口,我们使用EMF.Edit类。 为此,请更改MNViewContentProvider类以扩展AdapterFactoryContentProvider类。 AdapterFactoryContentProvider类已经知道如何处理ITreeContentProvider接口的实现,它实际上是通过委派给向查看器提供内容的适当项提供程序来完成的。

AdapterFactoryContentProvider类在其构造函数中需要适配器工厂。 因此,我们不能为内容提供者使用隐式构造函数。 我们必须显式声明我们的内容提供程序构造函数,并使用期望的参数调用超类构造函数。 声明构造函数后,添加super(MNComposedAdapterFactory.getAdapterFactory()); 对此。 我们将在此类中重点关注的其他方法是getChildrengetParenthasChildrengetElements

当查看者需要显示域对象的子元素时,将调用getChildren方法。 它返回作为参数元素的子级的域对象的数组。 类似地,调用getElements方法以获得参数元素的域对象。 两者的功能相似。 他们只是在不同的时间被呼唤。 要实现getChildren方法,我们仅要求AdapterFactoryContentProvider返回给定父级URI的子级。 清单2中显示了getChildren方法。对于getElements方法,我们只需将调用返回到此getChildren方法。

清单2. getChildren实现
...
public Object[] getChildren(Object parentElement) 
{
    if (parentElement instanceof IFile)
    {
        String path = ((IFile)parentElement).getFullPath().toString();
        URI uri = URI.createPlatformResourceURI(path, true);
        parentElement = resourceSet.getResource(uri, true);
    }
    return super.getChildren(parentElement);
}
...

在树视图中显示内容的接下来的两个重要步骤是能够确定视图中的对象何时具有需要显示的子对象,并能够将一组子对象与父对象相关联。 这使查看者可以控制域对象的状态,无论它们是展开还是折叠。 在我们的示例中,这可以转换为具有一组子程序包的Ecore模型。 在那些包中是与同一父包关联的类对象。 我们在清单3中实现了这一点。

清单3. getParent实现
...
public Object getParent(Object element)
{
    if (element instanceof IFile)
        return ((IResource)element).getParent();
    return super.getParent(element);
}

public boolean hasChildren(Object element) 
{
    if (element instanceof IFile)
        return true;
    return super.hasChildren(element);
}
...

我们可能会在此处看到一些有关无法解析我们正在使用的资源的错误。 要解决此问题,请将org.eclipse.core.resources添加到Dependencies选项卡上的所需插件中。 同样,为了允许内容提供者在视图中获取文件资源的URI,我们需要使用平台中的资源集。 我们创建一个静态资源集实现,可以通过添加private static ResourceSetImpl resourceSet = new ResourceSetImpl();来获取这些资源private static ResourceSetImpl resourceSet = new ResourceSetImpl(); MNViewContentProvider类。

标签提供者遵循与内容提供者相同的格式,因为我们将简单地将工作委托给EMF.Edit框架中的AdapterFactoryLabelProvider类。 与内容提供者一样,标签提供者接受域对象作为其参数,但是它返回应在查看器中与此对象相关联的ImageString 为了使我们的查看器更具定制性,我们可以以编程方式控制何时要委派获取名称和图标的任务以及何时要为对象提供自己的图标。 为了我们的目的,我们选择不进行任何自定义。 我们只需要EMF模型提供的图像和文本。 为了实现标签提供者,我们用与内容提供者相同的项目提供者列表调用超类,然后将对对象的图像或描述的所有调用委托给AdapterFactoryLabelProvider超类。

清单4.标签提供者
...
public MNViewLabelProvider() 
{
    super(MNComposedAdapterFactory.getAdapterFactory());
}

public Image getImage(Object element) 
{
    return super.getImage(element);
}

public String getText(Object element) 
{
    return super.getText(element);
}
...

绑在一起

至此,我们已经完成了在插件中实现内容扩展的工作。 为了使我们的视图能够利用此内容扩展,是另外两个步骤。 首先,我们必须定义事件,以指示使用此特定内容扩展。 其次,我们必须将导航器内容绑定到视图。

通过将<possibleChildren /><triggerPoints />元素添加到导航器内容扩展中,我们将在何时能够显示在类中描述的域模型时发出CNF信号。 这两个元素很容易在插件xml文件中定义为Eclipse核心表达式。 在我们的案例中,当查看器包含作为EMF模型实例的对象时,将调用导航器内容。 由于我们当前仅想导航Ecore模型,因此我们可以使它成为一个简单的表达式,该表达式将检查资源的扩展名是否为Ecore。 可能的child元素指示我们的扩展何时可以为查看器中的对象提供父对象,在我们的情况下,这些对象是EMF模型对象或资源的实例。

清单5.触发点和可能的子元素
<triggerPoints> 
    <or>
        <and> 
            <instanceof value="org.eclipse.core.resources.IResource"/> 
            <test 
                forcePluginActivation="true" 
                property="org.eclipse.core.resources.extension" 
                value="ecore"/> 
        </and> 
    </or>
</triggerPoints> 
<possibleChildren> 
    <or> 
        <instanceof value="org.eclipse.emf.ecore.resource.Resource"/>
        <instanceof value="org.eclipse.emf.ecore.EObject"/>  
    </or> 
</possibleChildren>

最后,要将我们创建的导航器内容绑定到视图,我们将使用与之前相同的方法将IResource模型内容扩展包括到查看器内容绑定中。

要将导航器内容com.ibm.navigator.example.modelnavigator.emfModelContent绑定到实际视图,请从“扩展”选项卡:

  • 展开org.eclipse.ui.navigator.viewer元素
  • 展开viewerContentBinding元素
  • 创建一个新的内容扩展名:
    • 右键单击include元素
    • 选择新建> contentExtension
    • 将模式设置为我们定义的navigatorContentcom.ibm.navigator.example.modelnavigator.emfModelContent
  • 点击保存

这几乎完成了将EMF模型内容添加到通用导航器所需的步骤。 我们应该有一个ModelNavigator插件,该插件可以显示IResource模型和EMF Ecore模型的对象。

测试导航器

我们需要运行项目并在新视图中显示Ecore模型,以确保我们的ModelNavigator正常运行。 对于此测试,我们需要创建一个将在Model导航器中显示的EMF项目。 我们将使用基于例子SchoolLibrary UML文件(请参阅相关的主题 )。

作为Eclipse应用程序运行ModelNavigator项目,然后:

  • 在新工作台中,通过单击窗口>显示视图>其他来显示ModelNavigator视图。
  • 找到“ 模型导航器”类别,然后单击“ 模型导航器”视图
  • 点击确定

在运行时工作区中创建EMF项目:

  • 通过单击文件>新建>项目来创建一个新项目
  • 展开Eclipse Modeling Framework元素
  • 单击EMF项目,然后选择下一步。
  • 将项目命名为SchoolLibrary并选择Next
  • 选择Rose类模型作为模型导入器,然后选择Next。
  • 对于模型URI,浏览到下载schoollibrary.mdl文件的位置。
  • 点击下一步
  • 选择SchoolLibrary包,如图5所示。
  • 点击完成
图5.创建EMF测试项目
eclipse emf_构建一个Eclipse插件来浏览EMF模型中的内容

如果一切按计划进行,我们应该在“模型导航器”视图中看到新的SchoolLibrary项目。 更重要的是,如果我们的导航器内容能够按预期运行,则我们应该能够扩展项目的models目录,并能够在导航器视图中浏览librarySchoolLibrary Ecore文件的内容。 导航器应类似于图6中的导航器。

图6.测试ModelNavigator
eclipse emf_构建一个Eclipse插件来浏览EMF模型中的内容

更新同步

我们已经完成了要做的工作:使EMF模型内容在查看器中显示。 当我们实际上在编辑器中打开Ecore文件并开始进行更改时会发生什么? 现在,什么也没有发生。 我们的ModelNavigator忽略了对其显示的模型所做的更改,并且不会刷新它们。 除非我们使查看者知道编辑器中所做的更改并强制其刷新,否则它不会刷新它们。 创建同步的一种方法是向我们的内容提供程序添加资源更改侦听器。 以下各节概述了所需的步骤。

资源变更监听器

我们允许内容提供者通过侦听模型文件资源(在本例中为Ecore文件)中的更改来对模型中的更改做出React。 为此,我们需要在MNViewContentProvider类中实现IResourceChangeListenerIResourceDeltaVisitor接口。

资源更改并传递描述资源更改的事件集时,将调用resourceChanged(IResourceChangeEvent event)方法。 这组更改为我们提供了资源树之间的差异(时间差)。 我们可以使用它来浏览资源树中的更改,并根据更改的资源类型确定需要采取的措施。 我们实现了resourceChanged(IResourceChangeEvent event)方法,如清单6所示,它为我们提供了已更改的资源集,并允许我们访问资源增量。

清单6.资源更改的方法
...
try 
{
    IResourceDelta delta = event.getDelta();
    delta.accept(this);
} 
catch (CoreException e) 
{
...

在增量接受访问者之后,将调用visit(IResourceDelta delta)方法。 对于我们的插件,我们仅关心更改后的资源是否是具有Ecore扩展名的IResource文件。 如果发生这种情况,则更改的资源是Ecore模型,则需要刷新ModelNavigator以反映这些更改。 为此,我们获取更改后的文件,获取其资源,然后重新加载该资源表示的模型。

清单7.访问方法
...
IResource changedResource = delta.getResource();
if (changedResource.getType() == IResource.FILE 
   && changedResource.getFileExtension().equals("ecore"))
{
    try
    {
        String path = ((IFile)changedResource).getFullPath().toString();
        URI uri = URI.createPlatformResourceURI(path, true);
        Resource res = resourceSet.getResource(uri, true);
        res.unload();
        res.load(resourceSet.getLoadOptions());
    }
    catch(IOException ie)
    {
        System.out.println("Error reloading resource - " + ie.toString());
    }	
    return false;
}
return true;
...

要使用此资源更改侦听器,我们需要将其添加到内容提供程序中,并在适当时将其删除。 MNContentProvider类中,通过插入ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);添加侦听器ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); 在构造函数中。 另外,插入ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); 在该类的dispose方法中。 尽管这应该处理对资源更改的更新,但是请记住,这是处理更改的简单方法。 通过简单地在我们的内容提供者中更新受影响的模型,我们就不会遍历该模型的依赖关系来更新那些元素。 这是保持导航器更新的基本方法。

测试模型更新

为了测试查看器中是否反映了Ecore模型中的更改,我们将简单地重新运行我们的应用程序并开始进行一些更改。

作为Eclipse应用程序运行ModelNavigator项目,然后:

  • 导航到model目录下的schoollibrary.ecore
  • 在其编辑器中打开schoollibrary.ecore文件
  • 展开schoollibrary.ecore节点
  • 右键单击SchoolLibrary包节点
  • 选择新孩子> EClass
  • 在“ 属性”选项卡上,为这个新类命名( Test
  • 保存文件

此更改应该触发了资源更改侦听器代码的执行,并强制我们的ModelNavigator更新模型。 我们应该看到ModelNavigator视图重新加载自身。 如果展开树并导航到schoollibrary.ecore文件,我们应该看到所做的更改,如图7所示。

图7.带有资源更新的ModelNavigator
eclipse emf_构建一个Eclipse插件来浏览EMF模型中的内容

进一步的步骤

我们可以对ModelNavigator进行的最后一个(也是相当容易的)扩展是利用组合适配器工厂。 我们创建的导航器将显示Ecore模型,但是其他类型的EMF模型呢? 由于EMF.Edit框架的实现方式,这实际上是一个相当简单的任务。 通过将适当的适配器工厂添加到ComposedAdapterFactory并设置这些新模型的触发器,我们可以以最小的更改添加对更多域模型的支持。

扩大组合适配器工厂

例如,要将genmodel对象添加到导航器中,只需将生成器模型项提供程序添加到适配器工厂列表中,我们的内容和标签提供程序将使用该提供程序。 MNComposedAdapterFactory类中,添加factories.add(new GenModelItemProviderAdapterFactory()); createFactoryList()方法。 模型导航器中唯一需要更改的其他部分是告诉导航器内容何时可以触发此内容提供者。 我们使用相同的策略来检查资源扩展作为触发点,如下所示。

清单8. genmodel的触发点
<and> 
    <instanceof value="org.eclipse.core.resources.IResource"/> 
    <test 
        forcePluginActivation="true" 
        property="org.eclipse.core.resources.extension" 
        value="genmodel"/> 
</and>

通过右键我们目前的触发下加入这个新的触发表达,我们正在导航的内容的情况下,如果相关的对象实例IResource和具有的Ecore的延伸或者是实例IResource和延伸genmodel 如果如上所述再次运行此项目,我们将看到现在可以浏览Ecore和Generator EMF模型(参见图8)。 但是,这不是我们在简单的资源更新方案中计划的内容,因此更新不会在ModelNavigator视图中的不同模型之间同步。

图8.具有多个模型的ModelNavigator
eclipse emf_构建一个Eclipse插件来浏览EMF模型中的内容

结论

我们已经完成了创建插件的任务,该插件将在查看器中显示EMF模型内容。 我们演示了如何通过使用Eclipse提供的框架来简化此过程,甚至在向插件中添加一些简单功能方面走得更远。 我们仅探讨了这些框架提供的一些功能,并且我强烈建议每个人对这些Eclipse组件进行更深入的了解。


翻译自: https://www.ibm.com/developerworks/opensource/library/os-eclipse-emf/index.html