ECP Trigger Validation [message #1482145] |
Fri, 21 November 2014 09:29  |
Eclipse User |
|
|
|
Hi,
I have defined some validation rules for my model and validation is working so far.
However it seems that changes to an element do not trigger re-validation of the entire model but only along the hierarchy branch of the modified element (along the direct path to the top level element).
I need to re-validate everything after any change. For example I have a rule which checks for duplicate names in all children of an element. If there are duplicate names and this is fixed for one child the other one should be marked valid as well but this does not happen.
How can I enforce re-validation of the entire model after any change?
Thx,
chris
|
|
|
|
|
|
|
|
|
Re: ECP Trigger Validation [message #1490573 is a reply to message #1489850] |
Fri, 28 November 2014 03:52   |
Eclipse User |
|
|
|
Hi Christian,
to be honest, I still have a bad feeling with your use case, as I
believe this solution can conceptually not scale well.
Anyways, I do not quite understand, why your suggested code snippet is
better than validating everything. You navigate to the root of your
model (I guess "Project" is a domain specific object) and then validate
all contents, which is in my understanding validating everything.
The editor (i.e. EMF Forms) does not rely on the ECPObserverBus, it is
completly independant of ECP. Controls are revaildated if there is a
change on the model. To trigger that, another validation service is
registered directly on the objects which are opened in the editor.
So you would need to:
- Create proper change notifications
or
- Adapt the EMF Forms validation service
Best regards
Jonas
Am 27.11.2014 19:47, schrieb Christian Reuter:
> Hi Jonas,
>
> I meanwhile found out that there is a much better solution for my problem.
> As I said I register a ECPProjectContentChangedObserver during the
> startup phase of my "addons" plugin. The Observer uses the following code:
>
>
> private class ValidationObserver implements
> ECPProjectContentChangedObserver {
>
> /** {@inheritDoc} **/
> public Collection<Object> objectsChanged(ECPProject project,
> Collection<Object> objects) {
>
> // check if first object is a model object (not a project or
> something else)
> Object object = objects.iterator().next();
> if (!(object instanceof EObject)) {
> return new HashSet<Object>();
> }
>
> // step up the tree and get the top level element
> EObject topLevelElement = (EObject) object;
> while (!(topLevelElement.eContainer() instanceof Project)) {
> if (topLevelElement.eContainer() == null) {
> return new HashSet<Object>(); // just for safety =>
> should never happen
> }
> topLevelElement = topLevelElement.eContainer();
> }
>
> // create a list with all children of the object's top-level
> ancestor
> Collection<EObject> allElements = new HashSet<EObject>();
> TreeIterator<Object> iterator =
> EcoreUtil.getAllContents(topLevelElement, true);
> while (iterator.hasNext()) {
> EObject obj = (EObject)iterator.next();
> allElements.add(obj);
> }
>
> // (re-) validate the top level element and all it's
> children => get a list of updated elements
> Collection<EObject> updatedElements =
> getValidationService(project).validate(allElements);
>
> // return list of updated elements => this triggers update
> of their decorators in the Model Explorer tree
> return new HashSet<Object>(updatedElements);
> }
> }
>
>
> This works well and quite fast so I can even trigger it on each change
> of a model element without even sending it to another thread in the
> background.
>
> The only remaining problem is that the open editors do not get notified
> and therefore do not update their validation decorations.
> The update does happen for the objects that get validated normally (via
> upward propagation from the changed element) but not for the objects
> which have been validated by my observer.
> I tried to notify them like this:
>
> ECPProjectManagerImpl projectManager = (ECPProjectManagerImpl)
> ECPUtil.getECPProjectManager();
> projectManager.notifyObjectsChanged(project, objects, false);
>
> and like this:
>
> ECPUtil.getECPObserverBus().notify(ECPProjectContentTouchedObserver.class)
> .contentTouched(project, toUpdate, structural);
>
> but neither method works.
>
> Could you please enlighten me how I can notify the open editors to
> update themselves or where to find the code which does this?
>
> Thx,
>
> chris
--
Get professional Eclipse developer support:
http://eclipsesource.com/en/services/developer-support/
|
|
|
Re: ECP Trigger Validation [message #1490696 is a reply to message #1490573] |
Fri, 28 November 2014 06:05  |
Eclipse User |
|
|
|
Hi Jonas,
thanks again for your quick reply.
browsing the code of org.eclipse.com.view.internal.validation I found the class ValidationNotification which comes in handy at this point.
I just had to trigger a ValidationNotification for each object to get the open editors updated. So here is the piece of code which finally works (at least for the size of models my application usually has to deal with):
/**
* Project change observer that validates all (!) objects.
*/
private class ValidationObserver implements ECPProjectContentChangedObserver {
/** {@inheritDoc} **/
public Collection<Object> objectsChanged(ECPProject project, Collection<Object> objects) {
// check if first object is a model object (not a project or something else)
Object object = objects.iterator().next();
if (!(object instanceof EObject)) {
return new HashSet<Object>();
}
// step up the tree and get the top level element
EObject topLevelElement = (EObject) object;
while (!(topLevelElement.eContainer() instanceof Project)) {
if (topLevelElement.eContainer() == null) {
return new HashSet<Object>(); // just for safety => should never happen
}
topLevelElement = topLevelElement.eContainer();
}
// create a list with all children of the object's top-level ancestor
Collection<EObject> allElements = new HashSet<EObject>();
TreeIterator<Object> iterator = EcoreUtil.getAllContents(topLevelElement, true);
while (iterator.hasNext()) {
EObject obj = (EObject)iterator.next();
allElements.add(obj);
// trigger a validation notification for all objects => triggers the update of the
// validation decorations of the open editors
obj.eNotify(new ValidationNotification(obj));
}
// (re-) validate the top level element and all it's children
// => returns a list of affected elements (by up-propagation)
Collection<EObject> affactedElements = getValidationService(project).validate(allElements);
return new HashSet<Object>();
}
}
I know this solution will not scale very well and may run into problems with very large models. However my largest test model has ~2.000 objects and it works well and fairly responsive with models of this size. This is the case even though all elements are validated and perform quite expensive checks (some features are checked against all existing objects ...).
Thanks again for your help and best regards
chris
|
|
|
Powered by
FUDForum. Page generated in 0.25879 seconds