Skip to main content



      Home
Home » Modeling » EMF "Technology" (Ecore Tools, EMFatic, etc)  » ECP Trigger Validation
ECP Trigger Validation [message #1482145] Fri, 21 November 2014 09:29 Go to next message
Eclipse UserFriend
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 #1482195 is a reply to message #1482145] Fri, 21 November 2014 10:24 Go to previous messageGo to next message
Eclipse UserFriend
What I forgot to mention:
I added a context menu entry to the tree in the model explorer to allow for manually triggering the validation as a workaround.
I used Diagnostician.INSTANCE.validate(modelElement) to execute the validation.
When using the menu entry the validation is activated but the tree remains unchanged (the little red overlays remain there).
How can I force the tree to update the validation overay icons?
Re: ECP Trigger Validation [message #1484791 is a reply to message #1482145] Sun, 23 November 2014 14:45 Go to previous messageGo to next message
Eclipse UserFriend
Hi,

I think the validation rules you describe do not scale very well for
bigger models. Therefore I would execute them live, but only on a trigger.
I am not sure, whether the current API offers to manually trigger the
update, please have a look at the bundle
"org.eclipse.emf.ecp.validation" and potentially
org.eclipse.emf.ecp.validation.connector

Best regards

Jonas

Am 21.11.2014 15:29, schrieb Christian Reuter:
> 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


--
Get professional Eclipse developer support:
http://eclipsesource.com/en/services/developer-support/
Re: ECP Trigger Validation [message #1485965 is a reply to message #1484791] Mon, 24 November 2014 13:05 Go to previous messageGo to next message
Eclipse UserFriend
Hi Jonas,

thank you for your help.

So here is what I came up with after studying the validation bundles:
Unfortunately the validation process is quite complicated and it is hard to find out where to step in.
I finally created a new Context menu entry which calls the following code in it's handler:

		// get selected model element
		final EObject modelElement = getSelectedModelElement(event);
		if (modelElement == null) {
			return null;
		}
				
		Job job = new Job("ForceValidation") {
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				// get the project manager instance (must use non-API method as 
				// the method notifyObjectsChanged is not exposed by the interface
				ECPProjectManagerImpl projectManager = (ECPProjectManagerImpl) ECPUtil.getECPProjectManager();

				// create a list with the selected object and all its children
				Collection<Object> objects = new HashSet<Object>();
				objects.add(modelElement);
				TreeIterator<Object> iterator = EcoreUtil.getAllContents(modelElement, true);
				while (iterator.hasNext()) {
					objects.add(iterator.next());
			    }

				// get the project of the selected element
				ECPProject project = projectManager.getProject(modelElement);
				
				// trigger the observers (fake object change)
				projectManager.notifyObjectsChanged(project, objects, false);				

				return Status.OK_STATUS;
			}
		};

		// Start the Job
		job.schedule(); 		


Not a very elegant solution but at least it works.

Unfortunately it is very slow which is most likely because each object which is passed to projectManager.notifyObjectsChanged(...) propagates it's change up the tree to the root object. therefore I guess that all objects except the leafs are validated and decorated multiple times.

Maybe I should have exchanged some classes but that would have been much more implementation work.

If anybody has a better solution it is highly welcome!!

I suggest to expose an API method in future to trigger re-validation of the selected tree element.
Also a switch which decides whether changes are only propagated upwards or automatically trigger re-validation of everything would be useful.
I think it is not such a rare use case that validation has to take more into account than just the direct path to the root object.

Regards,

chris
Re: ECP Trigger Validation [message #1486477 is a reply to message #1485965] Mon, 24 November 2014 23:05 Go to previous messageGo to next message
Eclipse UserFriend
Hi Chris,

please let me know, if you are interested in contributing or sponsoring
the extension of the validation service API.

Best regards

Jonas

Am 24.11.2014 19:05, schrieb Christian Reuter:
> Hi Jonas,
>
> thank you for your help.
>
> So here is what I came up with after studying the validation bundles:
> Unfortunately the validation process is quite complicated and it is hard
> to find out where to step in.
> I finally created a new Context menu entry which calls the following
> code in it's handler:
>
>
> // get selected model element
> final EObject modelElement = getSelectedModelElement(event);
> if (modelElement == null) {
> return null;
> }
>
> Job job = new Job("ForceValidation") {
> @Override
> protected IStatus run(IProgressMonitor monitor) {
> // get the project manager instance (must use non-API
> method as // the method notifyObjectsChanged is not
> exposed by the interface
> ECPProjectManagerImpl projectManager =
> (ECPProjectManagerImpl) ECPUtil.getECPProjectManager();
>
> // create a list with the selected object and all its
> children
> Collection<Object> objects = new HashSet<Object>();
> objects.add(modelElement);
> TreeIterator<Object> iterator =
> EcoreUtil.getAllContents(modelElement, true);
> while (iterator.hasNext()) {
> objects.add(iterator.next());
> }
>
> // get the project of the selected element
> ECPProject project =
> projectManager.getProject(modelElement);
>
> // trigger the observers (fake object change)
> projectManager.notifyObjectsChanged(project, objects,
> false);
>
> return Status.OK_STATUS;
> }
> };
>
> // Start the Job
> job.schedule();
>
>
> Not a very elegant solution but at least it works.
>
> Unfortunately it is very slow which is most likely because each object
> which is passed to projectManager.notifyObjectsChanged(...) propagates
> it's change up the tree to the root object. therefore I guess that all
> objects except the leafs are validated and decorated multiple times.
>
> Maybe I should have exchanged some classes but that would have been much
> more implementation work.
>
> If anybody has a better solution it is highly welcome!!
>
> I suggest to expose an API method in future to trigger re-validation of
> the selected tree element. Also a switch which decides whether changes
> are only propagated upwards or automatically trigger re-validation of
> everything would be useful.
> I think it is not such a rare use case that validation has to take more
> into account than just the direct path to the root object.
>
> Regards,
>
> chris


--
Get professional Eclipse developer support:
http://eclipsesource.com/en/services/developer-support/
Re: ECP Trigger Validation [message #1486997 is a reply to message #1486477] Tue, 25 November 2014 08:19 Go to previous messageGo to next message
Eclipse UserFriend
Hi Jonas,

sorry - at the moment I am burried under the work of my current projects so there's currently no time to come up with a solution which is worth being contributed.

BTW: in the meantime I created a small extension plugin which adds copy / paste of model elements and "Force Validation" to the model explorer.
The plugin also registers a ECPProjectContentChangedObserver instance which observes object changes and automatically validates everything else in the background after the normal process has validated the changed object itself and has propagated up to the top level element.
If another change occurs during the validation process another validation job is scheduled until a complete run finishes without any changes in the meantime.
Validation of everything after every change takes some time if the model is large but it works ...

Thanks again for your tips!

chris

[Updated on: Tue, 25 November 2014 08:20] by Moderator

Re: ECP Trigger Validation [message #1489850 is a reply to message #1486997] Thu, 27 November 2014 13:47 Go to previous messageGo to next message
Eclipse UserFriend
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
Re: ECP Trigger Validation [message #1490573 is a reply to message #1489850] Fri, 28 November 2014 03:52 Go to previous messageGo to next message
Eclipse UserFriend
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 Go to previous message
Eclipse UserFriend
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
Previous Topic:[Edapt] Migrator / MigrationReconstructor for Models without XMI Serialization
Next Topic:EMFStore and codereview/gerrit
Goto Forum:
  


Current Time: Sat Jul 12 03:44:30 EDT 2025

Powered by FUDForum. Page generated in 0.25879 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top