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