我该如何使用Java加载Papyrus UML模型?

4

我使用Papyrus创建了一个类图并得到了一个*.uml模型,现在我想通过编写一些Java代码来遍历*.uml元素。

我尝试了以下代码:

URI uri = URI.createURI("*.uml");

ResourceSet set = new ResourceSetImpl();

set.getPackageRegistry().put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);
set.getResourceFactoryRegistry().getExtensionToFactoryMap()
       .put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE);
EPackage.Registry.INSTANCE.put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap()
       .put("uml", UMLResource.Factory.INSTANCE);

set.getResourceFactoryRegistry().getExtensionToFactoryMap()
       .put("xmi", new XMIResourceFactoryImpl());
//set.createResource(uri);
Resource res = set.getResource(URI.createURI(new URL("*.uml").toString(),true),true);

但我遇到了异常:

主线程中的异常:“main”java.lang.NoSuchMethodError: org.eclipse.emf.ecore.resource.URIConverter.createInputStream( Lorg/eclipse/emf/common/util/URI;Ljava/util/Map;)Ljava/io/InputStream;

我该如何使用Java加载papyrus uml模型?

1个回答

7
你已经几乎具备了所有的要素,只需要再加上一些细节并删除一些行。
首先,`.uml` 文件与 Papyrus 并没有直接关联。Papyrus 能够生成 `.uml` 文件,但这些文件不仅限于 Papyrus。该文件扩展名由 UML 插件管理,该插件提供了 UML 元模型(在 Ecore 中定义)、其实现以及处理这些文件的不同工具。
如果我们看一下你的代码:
ResourceSet set = new ResourceSetImpl();
set.getPackageRegistry().put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);
set.getResourceFactoryRegistry().getExtensionToFactoryMap()
   .put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE);
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap()
   .put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE);

这部分足以将UML元模型及其工厂注册到您的ResourceSet中。

这一行:

EPackage.Registry.INSTANCE.put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);

只要使用set加载您的模型,就无需使用xmi工厂注册。 包含在ResourceSetImpl中的Registry包是分层的:如果它无法找到与元模型URI链接的元模型包实例,则尝试在全局EPackage.Registry中查找。 因此,您可以将绑定(URI字符串,EPackage实例)在全局注册表中注册,也可以将其在您的ResourceSet实例中注册。这两个都不是必需的。 最后,使用ResourcetSet中的getResource进行资源加载几乎是好的,这是修改后的版本:
Resource res = set.getResource(URI.createFileURI("/path/to/my_model.uml"), true);

这段代码创建了一个 URI,指向磁盘上的文件并加载它。从你的资源中,可以使用 getContents() 方法访问你的元素。

res.getContents().get(0); // For example to get the root of your model.

此外,尽可能多地使用UMLUtilUML2UtilEcoreUtil静态类,它们提供了许多功能来查找/复制/过滤元素。

这是我使用的最终片段:

ResourceSet set = new ResourceSetImpl();
set.getPackageRegistry().put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);
set.getResourceFactoryRegistry().getExtensionToFactoryMap()
   .put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE);
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap()
   .put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE);

Resource res = set.getResource(URI.createFileURI("/path/to/my_model.uml"), true);

编辑>问题的大部分原因是使用的EMF版本。从EMF 2.3升级到>2.4可以解决异常抛出的问题。其余答案仍然有效,以便清理不必要的代码。


非常感谢,还有一个问题。我如何遍历模型元素并了解每个元素的类型? - Ahmadkt
您可以像测试普通Java对象一样测试每个EObject:例如:if (myobj instanceof org.eclipse.uml2.uml.Class) {...}。作为另一种选择,您还可以通过eClass()方法检查元类:例如:if (myobj.eClass() == UMLPackage.eInstance.getClass_()) {...}。如果您需要过滤元素,则可以使用UMLUtil.findEObject(...)方法来操作它,该方法接受一个集合和一个过滤器(此类中还有很多其他方法)。 - Vincent Aranega
@Ahmadkt,这个问题问得有点晚了,但我想提醒你,你忘记接受正确的答案了。 - Ruli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接