Извините, мне потребовалось столько времени, чтобы ответить. Я попробовал христианское предложение, был не очень доволен, а приоритеты сдвинулись. Теперь у меня будет другая проблема, и для того, чтобы документировать для других (и очистить голову), я напишу, что я сделал до сих пор, так как это было не так просто и требовало достаточного количества экспериментов.
Я не буду публиковать полные классы, но только соответствующие части. Не стесняйтесь спрашивать больше, если вам это нужно.
My Синтаксис-Definition теперь выглядит следующим образом:
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 и его УИР конечно нонсенс.
С этим провайдером я написал 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;
}
Пока все хорошо. Теперь я получаю boss
и buddy
, предлагаемые в качестве заинтересованных сторон. Однако, когда я использую один из этих двух, я получаю сообщение об ошибке в редакторе, жалующемся на оборванную ссылку и сообщение об ошибке на консоли, которое заинтересовало 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.
EDIT: У меня исправлена проблема «оборванных ссылок». loadAdditionalStakeholders()
функция StakeholdersProvider.xtend
теперь выглядит следующим образом:
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)
}
вы в основном адаптировать мировой поставщик области действия и создать eobjects для внешнего материала там. проблема синтаксического анализа и кеширования вручную не может быть отвечена для общей usacase, она очень специфична для каждой usecase (db vs file vs whatever) и того, как и когда эти ресурсы меняются и как их изменения могут быть обнаружены –
Thx Christian. Да, я специально упустил «конкретную» часть. Я попробую ваши предложения завтра. Все еще не уверен, как подключить EObjects к моему файлу xtext, но по крайней мере теперь я знаю, где копать глубже ... – agschaid