【问题标题】:Meshing Acceleo with Xtext使用 Xtext 网格化 Acceleo
【发布时间】:2012-08-11 14:24:33
【问题描述】:

我正在进行一项旨在从输入 UML 模型生成代码(即 Java)的 Acceleo 转换。

这个 UML 模型的一些元素(即活动不透明操作)包含一些符合 Xtext 语法的文本,我想在 Acceleo 转换中获得等效的 AST Ecore 表示。

为此,我开发了一个 Java 类,其方法将包含 DSL 摘录的字符串作为输入,并生成符合它的 Ecore 模型(有关详细信息,请参阅http://www.eclipse.org/forums/index.php/m/901947/#msg_901947)。我已经在一个单独的 Java 应用程序中对其进行了测试,它似乎可以正常工作。

因此,我编写了一个简单的 Acceleo 模块(即 getDSLModel),包装了该 java 类,使我能够从 DSL 文本表示中获取 Ecore 模型。

假设我的 DSL(和等效的 Ecore)由一个名为 DSLModel 的根元素组成,其中包含 (0..*) 数量的 DSLStatements(这是一种简化)。 在 Acceleo 中,我从包含正确 DSL 脚本的字符串调用包装器时,我注意到它正确返回了 ModelImpl

    ['statement1;statement2'.getDSLModel()/]

所以 Java 服务和 Xtext 解析正在工作。

但是,如果我尝试获取模型语句,即:

  ['statement1;statement2'.getDSLModel().statements/]

它返回一个 "invalid" 字符串。所以我不能在for循环中使用它

因此,我尝试从模型实例调用 eAllContents() OCL 服务,即:

  ['statement1;statement2'.getDSLModel().eAllContents()/]

它实际上返回语句列表。我不明白为什么从 Xtext 解析器返回的 Ecore 实体的功能不能正常工作。


这是将字符串转换为我的 DSL 模型 (Ecore AST) 实例的 Java 服务。我已经用一个独立的 Java 应用程序对其进行了测试,它运行良好!

 public class GetDSLModel {
 public DSLModel getDSLModel(String expression){    
    DSLStandaloneSetupGenerated dslsas = new DSLStandaloneSetupGenerated();
    Injector injector = dslsas.createInjectorAndDoEMFRegistration();
    XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
    resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
    Resource resource = resourceSet.createResource(URI.createURI("dummy:/example.dsl"));
    InputStream in = new ByteArrayInputStream(expression.getBytes());
    try {
        resource.load(in, resourceSet.getLoadOptions());
        DSLModel model = (DSLModel) resource.getContents().get(0);
        return model;
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;

}

}

现在我需要主 Acceleo (UML2Text) 转换中的 AST,因此这里是 Acceleo 包装器

 [query public getDSLModel(str:String): DSLModel =  (invoke('sfg.baleno.src.mloaders.GetDSLModel','getDSLModel(java.lang.String)',Sequence{str})).oclAsType(DSLModel)/]

这就是运行它得到的结果

  input: ['statement1;statement2'.getDSLModel()/]
  output: mypackage.dsl.impl.DSLModelImpl@a1c7a

  input: ['statement1;statement2'.getDSLModel().statements/]  (Syntactically VALID)
  output: invalid

  input: ['statement1;statement2'.getDSLModel().eAllContents()/]
  output: mypackage.dsl.impl.DSLStatement@e53202 (......

更新

在主 Acceleo 模块的 Java 类中,我添加了以下几行

 @Override
 public void initialize(EObject element, File folder, java.util.List<? extends Object> arguments) throws IOException {    preInitialize();
    super.initialize(element, folder, arguments);
}
@Override
public void initialize(URI modelURI, File folder, java.util.List<?> arguments) throws IOException {
    preInitialize();
    super.initialize(modelURI, folder, arguments);
}

protected void preInitialize() {
   DSLStandaloneSetup.doSetup();
}

  @Override
 public void registerPackages(ResourceSet resourceSet) {
    super.registerPackages(resourceSet);
   if (!isInWorkspace(org.eclipse.uml2.uml.UMLPackage.class)) {
         resourceSet.getPackageRegistry().put(org.eclipse.uml2.uml.UMLPackage.eINSTANCE.getNsURI(), org.eclipse.uml2.uml.UMLPackage.eINSTANCE);
    }
    if (!isInWorkspace(mypackages.DSLPackage.class)) {
        resourceSet.getPackageRegistry().put(mypackages.DSLPackage.eINSTANCE.getNsURI(), mypackages.DSLPackage.eINSTANCE);
     }
   EcoreUtil.resolveAll(resourceSet);
}

但它的行为仍然相同。

更新

在此链接中,您临时可以找到一个示例 EMF 工作区的压缩文件,其中包含一个 Acceleo 和一个重现该问题的 XText 项目。奇怪的是,如果您将它作为 Java 应用程序运行,它可以工作,但如果您将它作为 Acceleo 应用程序运行,它就不能...

https://docs.google.com/open?id=0B2_ovo8IiZaZaXdNdFdPMTI4Yjg

在左上角,您应该找到一个文件菜单,您可以从中下载 zip 文件。

【问题讨论】:

  • 您是否正确注册了 DSL 的元模型?您是否在模块的定义中使用它?
  • 我想我做到了,我已经更新了问题。封装 java 服务的 Acceleo 模块只使用 DSLEcore,而主 Acceleo 模块同时使用 UML 和 DSLEcore
  • 问题可能是我正在利用两个不同的资源集:一个在 Java 服务中检索 Xtext 文件,另一个在 Acceleo 中?有没有办法从 Java 服务中检索 Acceleo 当前资源集?
  • 只是为了检查这是否可能是问题,我已将静态 ReousceSet 变量添加到主加速模块 java 类。因此,我从 XText java 服务中检索了它并使用它而不是实例化一个新的。不幸的是,它的行为仍然相同,Acceleo 似乎没有将实现与相关的 ECORE 实体相关联
  • 嗨,我已经更新了问题,其中包含一个 zip 文件的链接,该文件包含一个 ezample EMF 工作区,可重现该问题。距离 50 分还有 6 天时间。

标签: eclipse eclipse-emf xtext acceleo


【解决方案1】:

不幸的是,我对 Xtext 不太熟悉……但我相信您的问题在于您从 java 服务中加载 dsl 的方式:您正在运行的 Eclipse(“acceleo 应用程序”)的上下文中生成,然而你加载你的模型就像你是在独立的:new DSLStandaloneSetup, createInjector...

我相信这种加载模型的方式会为您提供 Xtext 元模型和工厂的两个实例,从而使 OCL 在您尝试获取其值时无法检索功能“语句”。

我能想到的绕过此问题的一种可能方法是将您的服务更改为将任何类型的 EObject 作为参数并使用其资源集来加载您的 dsl(因此使用您在启动器中初始化的资源集,Acceleo 使用的那个,而不是你自己的):

public DSLModel getDSLModel(String expression, EObject eObj){
    ResourceSet rSet = eObj.eResource().getResourceSet();
    [...]
}

这样,您应该不需要从服务中进行的第二次 Xtext 初始化......如果它不起作用,除了去 Xtext 论坛并在那里询问之外,我真的没有建议的解决方案如何制作一个可以加载 DSL 并在独立和插件化环境中工作的应用程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多