2015-03-31 66 views
2

请考虑这个最小的Xtext语法。XText交叉引用非DSL资源

Model: 
    "As a" stackeholder=Stakeholder "I want" want=Want; 

Stakeholder: 
    'client' | 'developer' | 'manager'; 

Want: 
    'everything' | 'cookies' | 'fame'; 

现在我需要做的,是将利益相关者的定义(让我们忘掉want)至一些外部数据源。这个“外部数据源”可能是一个CSV文件,可能是一个数据库,也可能是一个Web服务。但是,我非常不可能成为一些Xtext文件或者使用EMF模型。但是我仍然想交叉引用它,就像在DSL中交叉引用java类型一样。

像手动分析和缓存(为了表现)不考虑的问题:这甚至是可行的吗?

我已经挖掘了一些范围和资源提供者的主题,但我发现一切都需要外部源至少是另一个DSL的一部分。

我会非常高兴的一个粗略的大纲需要做什么。

+0

你会基本上适应全球范围内供应商对你的外部的东西创造eobjects那里。手动解析和缓存问题不能为一般usacase回答,它是非常具体的每个用例(分贝vs文件与其他)以及这些资源如何以及何时改变以及它们如何检测其变化 – 2015-03-31 10:32:20

+0

Thx Christian。是的,我故意忽略了“特定”部分。我明天会尝试你的建议。仍然不知道如何将EObjects连接到我的xtext文件中,但至少现在我知道要在哪里深入挖掘...... – agschaid 2015-04-01 22:52:21

回答

1

对不起,我花了这么长时间回应。我尝试了基督徒的建议,并不是非常满意,而且优先级转移了。现在,我将再次探讨这个问题,并且为了记录其他人(并清除我的头),我会记下我迄今为止所做的事情,因为这并不是那么简单并且需要大量的实验。

我不会发布完整的课程,但只有相关的部分。如果您需要更多细节,请随时咨询。

我的语法,定义现在看起来是这样的:

Model: 
    stakeholders+=StakeholderDecl* 
    requirements+=Requirement*; 

Requirement: 
    'As a' stakeholder=[Stakeholder] 'I want' want=('everything' | 'cookies' | 'results') 
; 

StakeholderDecl returns Stakeholder : 
    'Stakeholder' Stakeholder 
; 

Stakeholder: 
    name=ID 
; 

让大家注意的是,下面的一切需要在.ui包来完成。

首先,我创建StakeholdersProvider.xtend

class StakeholdersProvider extends AbstractResourceDescription { 

    // this is the dummy for an "external source". Just raw data. 
    val nameList = newArrayList("buddy", "boss") 

    val cache = nameList.map[it.toDescription] 

    private val uri = org.eclipse.emf.common.util.URI.createPlatformResourceURI("neverland", true) 

    def public List<IEObjectDescription> loadAdditionalStakeholders() { 
     cache 
    } 

    def private IEObjectDescription toDescription(String name) { 

    ExternalFactoryImpl.init() 
    val ExternalFactory factory = new ExternalFactoryImpl() 

    val Stakeholder obj = factory.createStakeholder as StakeholderImpl 
    obj.setName(name) 


    new StakeholderDescription(name, obj, uri) 
    } 

. . . 

    override getURI() { 
    uri 
    } 

    def public boolean isProvided(EObject object) { 
    if(object.eClass.classifierID != ExternalPackageImpl.STAKEHOLDER) { 
     false 
    } 
    else { 
     val stakeholder = object as Stakeholder 
     nameList.exists[it == stakeholder.name] 
    } 
    } 

} 

注意,供应商也是resourceDescription及其课程的URI是无稽之谈。

有了这个提供商,我写了ScopeWrapper.xtend

class ScopeWrapper implements IScope { 

    private var IScope scope; 
    private var StakeholdersProvider provider 

    new(IScope scopeParam, StakeholdersProvider providerParam) { 
    scope=scopeParam 
    provider = providerParam 
    } 

    override getAllElements() { 
    val elements = scope.allElements.toList 

    val ret = provider.loadAdditionalStakeholders() 
    ret.addAll(elements) 

    ret 
    } 

    override getSingleElement(QualifiedName name) { 
     allElements.filter[it.name == name].head 
    } 

. . . 

} 

ResourceDescriptionWrapper.xtend

class ResourceDescriptionsWrapper implements IResourceDescriptions { 

    private StakeholdersProvider provider; 
    private IResourceDescriptions descriptions; 

    new(IResourceDescriptions descriptionsParam, StakeholdersProvider providerParam) { 
    descriptions = descriptionsParam 
    provider = providerParam 
    } 

    override getAllResourceDescriptions() { 
    val resources = descriptions.allResourceDescriptions.toList 
    resources.add(provider) 
    resources 
    } 

    override getResourceDescription(URI uri) { 
    if(uri == provider.URI) provider 
    else descriptions.getResourceDescription(uri) 
    } 
    override getExportedObjects() { 
    val descriptions = descriptions.exportedObjects.toList 

    descriptions.addAll(provider.exportedObjects) 

    descriptions 

    } 

    . . . some overrides for getExportedObjects-functions 

} 

所有这一切都是连接在一起MyGlobalScopeProvider.xtend

class MyGlobalScopeProvider extends TypesAwareDefaultGlobalScopeProvider { 

    val provider = new StakeholdersProvider() 

    override getScope(Resource context, EReference reference, Predicate<IEObjectDescription> filter) { 
    val scope = super.getScope(context, reference, filter) 
    return new ScopeWrapper(scope, provider) 
    } 

    override public IResourceDescriptions getResourceDescriptions(Resource resource) { 
    val superDescr = super.getResourceDescriptions(resource) 
    return new ResourceDescriptionsWrapper(superDescr, provider) 
    } 

} 
这是在MyDslUiModule.java

注册

public Class<? extends IGlobalScopeProvider> bindIGlobalScopeProvider() { 
    return MyGlobalScopeProvider.class; 
} 

到目前为止好。我现在得到bossbuddy作为利益相关者。但是,当我使用其中一个2时,编辑器中出现错误,抱怨悬挂引用和控制台中的错误日志记录,利益相关方cannot be exported as the target is not contained in a resource。搞清楚这些2可能都跟我试图修复错误记录,创造了MyresourceDescriptionStrategy.xtend

class MyResourcesDescriptionStrategy extends DefaultResourceDescriptionStrategy { 

    val provider = new StakeholdersProvider() 

    override isResolvedAndExternal(EObject from, EObject to) { 
    if (provider.isProvided(to)) { 
     // The object is a stakeholder that was originally provided by 
     // our StakeholdersProvider. So we mark it as resolved. 
     true 
    } else { 
     super.isResolvedAndExternal(from, to) 
    } 
    } 
} 

,并在UiModule线它:

public Class<? extends IDefaultResourceDescriptionStrategy> bindDefaultResourceDescriptionStrategy() { 
    return MyResourcesDescriptionStrategy.class; 
} 

这修复记录错误,但“悬参考”的问题遗迹。我寻找解决方案,most prominent result建议定义一个IResourceServiceProvider本来是解决我的问题的最佳方法。 我会花更多时间在当前的方法上,并尝试使用ResourceProvider。

编辑:我得到了“悬挂参考”问题修复。在StakeholdersProvider.xtendloadAdditionalStakeholders()函数现在看起来是这样的:

override loadAdditionalStakeholders() { 

    val injector = Guice.createInjector(new ExternalRuntimeModule()); 
    val rs = injector.getInstance(ResourceSet) 
    val resource = rs.createResource(uri) 
    nameList.map[it.toDescription(resource)] 
} 

def private IEObjectDescription toDescription(String name, Resource resource) { 

    ExternalFactoryImpl.init() 
    val ExternalFactory factory = new ExternalFactoryImpl() 

    val Stakeholder obj = factory.createStakeholder as StakeholderImpl 

    obj.setName(name) 
    // not sure why or how but when adding the obj to the resource, the 
    // the resource will be set in obj . . . thus no more dangling ref 
    resource.contents += obj 


    new StakeholderDescription(name, obj, uri) 
} 
+0

如果您说外部的东西,如果基于emf我会建议您首先编写resourceserviceprovider。但你说它是csv或db,因此不太可能是基于emf的。 - 在全局范围提供程序中加载并添加它们到一个面部资源(一次)将会在您的解决方案中完成这项工作 – 2015-04-28 04:19:49

+0

我只是在阅读“书”并且只是浏览文档。所以我仍然不完全确定基于EMF的实际意义。对不起,如果提供了一个误导性的信息。 – agschaid 2015-04-28 05:30:35

+0

我正在阅读“书”,只是浏览文档。所以我仍然不完全确定基于EMF的实际意义。当我写出最初的帖子时,我想这意味着要让文件中的实体符合定义的语法。对不起,如果提供了一个误导性的信息。但事实上,我仍在谈论从数据库或文件派生的一些原始信息。我在'StakeholdersProvider.xtend'中有一个名字列表。是的,它是硬编码的。但在我的实验阶段,它构成了一个外部数据源的模拟。这是否改变了某种东西? – agschaid 2015-04-28 05:40:17