1

我目前正在玩 XText 和 EMF,但我已经走到了死胡同。

我有一个使用图表编辑器创建的 ecore 模型。我不提供 XML 表示;从例子中应该很清楚。有些关系是相互对立的(如父子关系)。

当我以编程方式创建实例时,此绑定工作得非常好。下面,我展示一个成功通过的测试用例。

但是,当我使用 XText 解析模型时,并没有设置这些相反的关系。我找不到解决此问题的方法。这些关系在输入文件中出现时是严格单向的。有没有办法强制 Xtext 设置这些?还是我应该手动解决这些问题?

通过测试

WordsFactory factory = WordsFactory.eINSTANCE;

// Prepare a simple dictionary hierarchy

Dictionary d = factory.createDictionary();

Synset s = factory.createAdjectiveSynset();

s.setDescription("A brief statement");
s.setExample("He didn't say a word.");

WordSense ws = factory.createAdjectiveWordSense();
Word w = factory.createWord();
w.setName("word");
ws.setWord(w);      
s.getWordSenses().add(ws);
d.getWords().add(w);
d.getSynsets().add(s);

// Now check the bidirectional links
Assert.assertTrue(ws.getSynset() == s);
Assert.assertTrue(w.getSenses().get(0) == ws);  

此示例的 XMI 表示

<?xml version="1.0" encoding="ASCII"?>
<words:Dictionary xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:words="http://www.example.com/dstahr">
  <words senses="//@synsets.0/@wordSenses.0" name="word"/>
  <synsets xsi:type="words:AdjectiveSynset" description="A brief statement" example="He didn't say a word.">
    <wordSenses xsi:type="words:AdjectiveWordSense" word="//@words.0"/>
  </synsets>
</words:Dictionary>

语法定义(删除了一些不重要的规则)

grammar ocs_assignment.dsl.DSL with org.eclipse.xtext.common.Terminals

import "platform:/resource/ocs_assignment.model/model/words.ecore"
import "http://www.eclipse.org/emf/2002/Ecore" as ecore

Dictionary returns Dictionary:
    {Dictionary}
    'dict' name=EString
    ('add words' '[' words+=Word* ( "," words+=Word)* ']')?  
    synsets+=Synset*    
    ;

Synset returns Synset:
    AdjectiveSynset | NounSynset | VerbSynset;

WordSense returns WordSense:
    AdjectiveWordSense | NounWordSense | VerbWordSense; 

Word returns Word:
    name=EString;

EString returns ecore::EString:
    STRING | ID;

NounWordSense returns NounWordSense:
    word=[Word|EString];

NounSynset returns NounSynset:
    {NounSynset}
    '(N)' name=EString
    '{'
        'content' '[' (wordSenses+=NounWordSense ( "," wordSenses+=NounWordSense)*)? ']'
        'description' description=EString
        'example' example=EString
        ('hyponym' hyponym=[Synset|EString])?
        ('hypernym' hypernym=[Synset|EString])?
        ('similarTo' '(' similarTo+=[Synset|EString] ( "," similarTo+=[Synset|EString])* ')' )?
    '}';

解析文件

dict dict
add words test1 test2 test3

(N) test1
{
    content [ test1 test2 ]
    description "test1"
    example "test1"
}

(N) test2
{
    content [ test3 ]
    description "test2"
    example "test2"
    hypernym test1
}

已解析文件的 XMI 表示(缺少 Words 的引用)

<?xml version="1.0" encoding="ASCII"?>
<words:Dictionary xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:words="http://www.example.com/dstahr">
  <words name="test1"/>
  <words name="test2"/>
  <words name="test3"/>
  <synsets xsi:type="words:NounSynset" description="test1" example="test1" name="test1">
    <wordSenses xsi:type="words:NounWordSense">
      <word href="importedFile1.wdsl#xtextLink_::0.1.0.2.0::1::/0"/>
    </wordSenses>
  </synsets>
  <synsets xsi:type="words:NounSynset" description="test2" example="test2" name="test2">
    <hypernym xsi:type="words:AdjectiveSynset" href="importedFile1.wdsl#xtextLink_::0.1.1::1::/21"/>
    <wordSenses xsi:type="words:NounWordSense">
      <word href="importedFile1.wdsl#xtextLink_::0.1.1.2.0::1::/0"/>
    </wordSenses>
  </synsets>
</words:Dictionary>
4

1 回答 1

2

Xtext 不支持内置的反向关系。如果您从语法生成元模型,您会看到没有为对应关系设置逆。但是,如果您的 Ecore 模型设置了反向关系属性,Xtext 将保持该属性。

有两种方法可以使用这样的元模型:

  1. 创建您自己的 Ecore 模型并引用它。
  2. 您可以定义一个 IXtext2EcorePostProcessor 实例,该实例可以在序列化之前更新您生成的元模型。详情请参阅Christian Dietrich 的相应博文

第一个解决方案非常简单,但您会丢失自动生成的 EMF 模型。在第二种情况下,您必须编写代码来更新 Ecore(元)模型,然后再对其进行序列化,这可能很难实现。我们已经为EMF-IncQuery完成了第二种方法(用于另一种定制),因为那时自动生成非常重要,但是从那以后定制器变得非常难以理解。

于 2014-01-14T20:21:22.653 回答