I have encountered some code from another developer who tries to validate an object FooBar
against other objects BooFar
, and the code does something like this:
// 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)
]
// ...
}
// ...
}
So, this validator tries to access the "classpath" and loads all exported BOOFAR
objects to do the validation.
Now my question is: Is this even allowed?
It is obviously not good, because
resourceSetProvider
creates a new ResourceSet
for each BOOFAR
EObjectDescription
EObjectDescription
, a Resource
is loaded and parsed to resolve the EObject
I know (at least I think I know) that the more (most?) optimal way to cross-validate is to include all information needed for the validation in the EObjectDescription
of the BooFar
object and thus, not to resolve the object but validate against the EObjectDescription
.
My question is: Is the above allowed and does the code have any disadvantages other than being slow?
Also - Bonus Question - I have also seen code which resolves against the resourceSet
of the validated resource. So in the example code above replace the line in question with
allObjects.add(EcoreUtil.resolve(boofar.EObjectOrProxy, foobar.eResource.resourceSet) as BooFar)
Is this allowed? My thoughts are that this could cause problems because this code interferes with the XtextBuilder
's ResourceSet
and if we use a ParallelResourceLoader
then it might even cause race conditions?
So to summarize: I would like to know if the two variants above are only bad or even forbidden.
Other than being slow, the code is fine (in theory). Though it always depends on what is going to happen with the objects in allObjects. Let's say two exported objects come from the same resource, the list will contain two objects from two different resources and operations like equality checks or comparisons become unnecessarily hard.
Doing the same operation in the context of the own resource set is usually fine. The builder will load in parallel before the validation is triggered. Nevertheless - depending on your project structure - loading all objects may exceed the memory limit of the JVM. Usually the XtextBuilder tries to free memory if things are getting close the Xmx. If a validation loads all resources, this mechanism cannot kick in.
Long story short: Making the validation based on the IEObjectDescriptions is certainly the recommended way. The variant with the own resource set per objects is very bad. The second variant is only bad. Both are allowed but discouraged.