是否允许访问Xtext验证器中的另一个资源?

时间:2020-07-03 16:21:52

标签: java validation xtext xtend

我遇到了另一个开发人员的一些代码,这些开发人员试图针对其他对象FooBar验证对象BooFar,并且代码执行以下操作:

// Xtend code

@Inject IContainer.Manager containerManager
@Inject IResourceDescriptions resourceDescriptions
@Inject Provider<XtextResourceSet> resourceSetProvider

@Check
def validate(FooBar foobar) {
  var desc = resourceDescriptions.getResourceDescription(foobar.eResource.URI)
  var visibleContainers = containerManager.getVisibleContainers(desc, resourceDescriptions)

  for (visibleContainer : visibleContainers) {
    var exported = visibleContainer.getExportedObjectsByType(ModelPackage.Literals.BOOFAR)
    var allObjects = newArrayList

    exported.forEach [boofar |  
      // this is the line I'm interested about -->  
      allObjects.add(resourceSetProvider.get.getEObject(boofar.EObjectURI, true) as BooFar)
    ]
    // ...
  }
  // ...
}

因此,此验证器尝试访问“类路径”并加载所有导出的BOOFAR对象以进行验证。

现在我的问题是:甚至允许这样做吗?

显然不好,因为

  1. 我猜想resourceSetProvider为每个ResourceSet BOOFAR创建一个新的EObjectDescription
  2. 对于每个EObjectDescription,将加载并解析Resource来解析EObject

我知道(至少我想我知道),交叉验证的更多(最?最优)方法是将验证所需的所有信息都包含在EObjectDescription对象的BooFar中因此,不是解决对象,而是针对EObjectDescription进行验证。

我的问题是:上面的内容是否被允许?除了运行缓慢之外,代码是否还有其他缺点?

也-奖金问题-我还看到了针对已验证资源的resourceSet进行解析的代码。因此,在上面的示例代码中,将相关行替换为

  allObjects.add(EcoreUtil.resolve(boofar.EObjectOrProxy, foobar.eResource.resourceSet) as BooFar)

可以吗?我的想法是,这可能会引起问题,因为此代码会干扰XtextBuilder的{​​{1}},如果我们使用ResourceSet,那么它甚至可能导致竞争情况?

总结一下:我想知道上面的两个变体是不好的还是被禁止的。

1 个答案:

答案 0 :(得分:1)

除了运行缓慢之外,代码还不错(理论上)。尽管它始终取决于allObjects中的对象将要发生的情况。假设两个导出的对象来自同一资源,则列表将包含来自两个不同资源的两个对象,并且诸如相等性检查或比较之类的操作变得不必要地困难。

通常在自己的资源集中执行相同的操作。构建器将在触发验证之前并行加载。但是,根据您的项目结构,加载所有对象可能会超出JVM的内存限制。通常,如果情况越来越接近Xmx,则XtextBuilder会尝试释放内存。如果验证加载了所有资源,则该机制将无法启动。

长话短说:基于IEObjectDescriptions进行验证无疑是推荐的方法。每个对象都有自己的资源集的变体非常糟糕。第二个变种是不好的。两者都允许但不鼓励。