如何在Eclipse插件项目中程序化应用Papyrus Designer构造型?
问题分析与解决
问题背景
开发了一个基于Eclipse UML2的Java程序,负责加载.uml文件并执行模型转换,核心逻辑是应用Papyrus Designer的Codegen和C_Cpp Profile构造型,生成的模型可被Papyrus Designer识别并生成C++代码。该程序在标准Java项目中依赖插件JAR运行正常,但转为Eclipse插件项目后出现异常。
核心代码片段
Profile codegenProfile = loadProfile(codegenProfileUri); // 从插件JAR加载Profile资源并返回org.eclipse.uml2.uml.Profile codegenProfile.define(); ... model.applyProfile(codegenProfile); ... final Stereotype listHint = codegenProfile.getOwnedStereotype("ListHint"); model.applyStereotype(listHint); // 其他构造型应用逻辑
遇到的异常
- 普通Java项目中必须调用
define(),否则会抛出:
java.lang.IllegalArgumentException: profile "C_Cpp" has no Ecore definition
- 转为插件项目后,Profile能正常加载,但应用构造型时抛出:
java.lang.IllegalArgumentException: org.eclipse.uml2.uml.internal.impl.StereotypeImpl@540dcfba (name: ListHint, visibility: <unset>) (isLeaf: false, isAbstract: false, isFinalSpecialization: false) (isActive: false) at org.eclipse.uml2.uml.internal.operations.ElementOperations.setValue(ElementOperations.java:667) at org.eclipse.uml2.uml.internal.impl.ElementImpl.setValue(ElementImpl.java:307)
查看ElementOperations源码,问题根源在于:
EObject eObject = element.getStereotypeApplication(stereotype); if (eObject == null) { throw new IllegalArgumentException(String.valueOf(stereotype)); }
说明Profile未被正确初始化,导致构造型应用后无法找到对应的实例。
解决方案
1. 完善插件项目的依赖声明
在插件的MANIFEST.MF中,显式添加以下依赖:
org.eclipse.uml2.uml- Papyrus Designer的Profile相关插件(如
org.eclipse.papyrus.designer.languages.cpp.profile、org.eclipse.papyrus.designer.codegen.profile) - 确保依赖插件的版本与加载的Profile版本完全匹配,避免版本冲突。
2. 使用UML2标准机制加载Profile
插件环境下不要用自定义loadProfile方法读取JAR资源,改用UML2提供的注册式加载:
// 通过Profile的URI加载,插件环境会自动处理资源上下文 URI profileUri = URI.createURI("http://www.eclipse.org/papyrus/designer/codegen/Codegen"); Profile codegenProfile = UMLUtil.getProfile(profileUri, model); model.applyProfile(codegenProfile);
或直接通过Qualified Name加载:
Profile codegenProfile = UMLUtil.getProfile("http://www.eclipse.org/papyrus/designer/codegen/Codegen", model); model.applyProfile(codegenProfile);
此方式无需手动调用define(),UML2会自动完成Profile的定义与初始化。
3. 确保Profile资源与EMF注册表配置正确
- 在
plugin.xml中注册UML资源工厂:
<extension point="org.eclipse.emf.ecore.extension_parser"> <parser type="uml" class="org.eclipse.uml2.uml.resource.UMLResourceFactoryImpl"/> </extension>
- 在
build.properties的bin.includes中添加Profile的.uml文件路径,确保打包时资源被正确包含。
4. 配置正确的ResourceSet上下文
插件环境中加载模型时,需为ResourceSet配置对应的资源工厂与包注册表:
ResourceSet resourceSet = new ResourceSetImpl(); // 注册UML资源工厂 resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap() .put(UMLResource.FILE_EXTENSION, UMLResource.Factory.INSTANCE); // 注册UML包到EMF注册表 resourceSet.getPackageRegistry().put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE); // 加载模型资源 Resource modelResource = resourceSet.getResource(modelUri, true); Model model = (Model) modelResource.getContents().get(0);
5. 移除手动define()调用
插件环境下UML2会自动处理Profile的Ecore定义生成,手动调用define()可能导致上下文冲突,建议移除该调用。
内容的提问来源于stack exchange,提问作者Graham L
相关产品推荐
相关产品推荐

