Bug 259922 - [console] Overhaul the OCL Example
Summary: [console] Overhaul the OCL Example
Status: NEW
Alias: None
Product: OCL
Classification: Modeling
Component: Core (show other bugs)
Version: 1.2.0   Edit
Hardware: PC Mac OS X - Carbon (unsup.)
: P3 enhancement (vote)
Target Milestone: 3.2.0   Edit
Assignee: OCL Inbox CLA
QA Contact:
URL:
Whiteboard: Broad Appeal Usability
Keywords: plan
Depends on:
Blocks: 318358
  Show dependency tree
 
Reported: 2009-01-04 18:38 EST by Christian Damus CLA
Modified: 2011-05-27 07:54 EDT (History)
5 users (show)

See Also:
ed: indigo-


Attachments
First cut of a new console example (102.96 KB, application/octet-stream)
2009-01-11 23:15 EST, Christian Damus CLA
no flags Details
Patch to the old OCL example interpreter plugin.properties file (999 bytes, patch)
2009-01-12 01:50 EST, Nicolas Rouquette CLA
no flags Details | Diff
change visibility from protected to public (843 bytes, patch)
2009-01-15 13:45 EST, Nicolas Rouquette CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Christian Damus CLA 2009-01-04 18:38:11 EST
The current "Interactive OCL Console" example has several deficiencies as a demonstration of the client side of the OCL API (the provider side is already sufficiently demonstrated by the Ecore and UML metamodel bindings):

  - no support for OCL text documents
  - problems in the XMI save/load of expressions (which isn't
      particularly interesting, anyway)
  - no support for creating definitions
  - every constraint parsed or expression evaluated is in a new
     throw-away environment
  - no access to parsing and evaluation options offered by the
     metamodel bindings (esp. the "evaluation mode" in UML)

A new example is warranted to address these shortcomings.  It is also a good opportunity, since the examples feature will be rejigged, to deliver the generated *.edit plug-ins as discussed in bug 196973.
Comment 1 Nicolas Rouquette CLA 2009-01-11 20:44:13 EST
+1: I look forward to this functionality!
Comment 2 Christian Damus CLA 2009-01-11 23:15:22 EST
Created attachment 122227 [details]
First cut of a new console example

Attached the firt cut of a new "console" example.

The "console" consists of three views:  Environment Browser, OCL Input, and OCL Results.  All of these views can be opened from the "Window -> Show View" menu (of course).  The Ecore and UML model editors also have new "Show OCL Console" actions 
that open the OCL Input and Environment Browser views.


Environment Browser
=====================

In this view, the user creates and manages OCL environments.  Each environment is independent of the others and is reusable in any user action.  Most actions are performed in the currently selected environment.

The "New Environment" action creates a new OCL environment for the target metamodel most appropriate to the currently select EObject.  This selection is determined from the active editor, if possible, otherwise some other workbench part.  Currently, support for Ecore and UML metamodels is plugged in via extensions in the two plug-ins included in the attachment.

Environments are distingushed visually using the icon for the Package concept of their target metamodel.  Any number of environments can be created.

The browser organizes the contents of each environment into folders, grouping:
  - Constraints
  - Definitions
  - Variables
  - Queries

(I'm currently unsure of how to sensibly define variables, or even whether it is interesting, so that folder doesn't do anything)

One convenient way to create Constraints and Definitions in an OCL environment is to load a *.ocl document (text, not XMI) using the action in the environment browser view.

The Environment Browser is connected to the Properties View.  All elements shown in the browser have names that can be edited in the property sheet or in-line in the tree (only folders can't be edited).

For OCL environment nodes, the Properties view shows the generic and metamodel-specific properties of the environment, which are mostly parsing and evaluation options that should be familiar from the API.  Thus, the "console" now provides access to the target meta-level via the Properties view, as well as such important details as root EClass and, for UML, the evaluation mode.  Parsing and evaluation options can be changed at any time; they only affect future parsing and/or evaluation actions.

The default modeling level is "User Model" (M1), useful for developing model constraints.

OCL environments can be deleted in the usual way, as can the elements within them:  constraints, queries, and definitions.


OCL Input View
=====================

This view simply has a text area in which to enter OCL text, and a message area below it that shows errors when necessary.  Any kind of OCL text is accepted, as follows:

  - at the metamodel modeling level, expressions are parsed
     as query expressions in the context of the metaclass of
     the currently selected element (as in the old example).
     The query is added to the Queries folder of the current
     environment in the browser if it is successfully executed,
     and the results are shown in the OCL Results view (q.v.).
     Edit the query name in the browser for easy recognition
  - at the user-model level, expressions are parsed as
     constraints in the context of the selection (as in the
     old example):
      - invariants in case the selection is a classifier
      - post-conditions in case the selection is an operation
      - derivation in case the selection is an attribute
     If successfully parsed, the constraint is added to the
     Constraints folder of the current environment in the
     browser.  Edit the constraint name in the browser for
     easy recognition
  - (new) helper operations and attributes can be defined
     in the OCL Input view.  When the selected EObject is a
     classifier, just type a def expression and hit <return>.
     e.g.
         def: someOp(p1 : Foo) : Bar = p1.someOp()
     A successfully parsed definition is added to the
     Definitions folder of the current environment in the
     browser
  - (new) ad hoc OCL documents can be entered in this
     view.  Just start with a package or classifier context
     declaration and type as usual (be sure to use
     Ctrl+Return to insert newlines; just Return sends the
     text to the parser.  All of the constraints and
     definitions that successfully parse are shown in the
     browser

Unlike the old example, the OCL Input view no longer clears its contents on successful parse/evaluation of the OCL text.

The OCL Environments view acts like a random-access history for the OCL Input view.  To recall any constraint, definition, or query that was entered via this view, simply select the element in the OCL Environments view, and the original text will be set in the OCL Input view.  This is handy for creating additional OCL elements that are similar to previously entered elements.


OCL Results
=================

The OCL results view is shown whenever a query expression is evaluated.  The presentation of results varies by the kind of result:

  - queries resulting in one or more model elements
     show a list of the elements.  Double-clicking on
     an element or using the context-menu action to
     navigate (useful for multiple selection) will try to
     highlight the selected results in the current editor.
     The registered EMF.Edit providers are used to
     show labels for elements
  - queries resulting in tuples show in a tabular form,
     with coluns named according to the tuple parts.
     This provides a tidy SQL-like presentation
  - queries resulting data values just show their
     string representations
  - validation results show constraint failures only, in
     two columns:  the offending elements with the
     constraints that were violated
  - an empty result is indicated as "(no results)"

There are a few ways to show results in this view:

  - press Return to enter an expression in the OCL
     Input view.  It is evaluated on the currently
     selected model element and the result (or
     results, if the expression type is a collection)
     is shown
  - double-click on a query in the OCL Environments
     view.  It is evaluated on the current model
     element selection, and the result is shown.  Or,
     use the "Execute Query" view action
  - double-click on a constraint in the OCL
     Environments view.  The elements in the
     sub-tree of the currently selected model element
     are checked against this constraint.  Violations
     are shown in the OCL Results view
  - use the "Check Constraints" view action on an
     OCL Environment node to check all of the
     constraints defined in that environment on the
     currently selected model sub-tree.  Constraints
     are checked on elements to which they are
     applicable, and the violations are shown in the
     Results view


Outstanding TODO Items
=======================

The list includes at least:

  - updating the SDK Developer Guide docs
     for this new example
  - support for multi-selection in the model
     editor for evaluation (queries and constraints)
  - support for selections in GMF diagram editors
     (adaptable selections)
  - improving the icons
  - drilling into the structure of constraints,
     queries, and definitions
  - support resource selections
  - figure out how to define variables, or ditch them
Comment 3 Nicolas Rouquette CLA 2009-01-12 01:50:30 EST
Created attachment 122237 [details]
Patch to the old OCL example interpreter plugin.properties file
Comment 4 Nicolas Rouquette CLA 2009-01-12 02:04:00 EST
Wow! This is amazing!

I have 4 comments.

1) The Query folder shows the first line of a multi-line query expression typed in the OCL Input window.
This can be useful to give a useful mnemonic to a complex query, e.g.:

-- who am I?
self.qualifiedName

The query folder only shows "-- who am I?" 

2) confusion between old & new OCL console.

I suggest changing the properties of the old console to avoid having two "Show OCL Console" menus...
(see patch)

3) loading *.ocl

What is the grammar for OCL documents?

I used the example in the org.eclipse.ocl.uml.tests plugin but I didn't get far...
I open a UML model in the UML Editor and open the OCL console.
As I mentioned, I can issue queries, so far so good...
But, loading any OCL document brings this exception:

java.lang.NullPointerException
	at org.eclipse.ocl.util.OCLUtil$1.tryLookupClassifier(OCLUtil.java:120)
	at org.eclipse.ocl.parser.AbstractOCLAnalyzer.lookupClassifier(AbstractOCLAnalyzer.java:4240)
	at org.eclipse.ocl.parser.AbstractOCLAnalyzer.classifierContextDeclCS(AbstractOCLAnalyzer.java:1237)
	at org.eclipse.ocl.parser.AbstractOCLAnalyzer.contextDeclCS(AbstractOCLAnalyzer.java:734)
	at org.eclipse.ocl.parser.AbstractOCLAnalyzer.packageDeclarationCS(AbstractOCLAnalyzer.java:697)
	at org.eclipse.ocl.parser.AbstractOCLAnalyzer.packageDeclarationCS(AbstractOCLAnalyzer.java:713)
	at org.eclipse.ocl.parser.AbstractOCLAnalyzer.documentCS(AbstractOCLAnalyzer.java:642)
	at org.eclipse.ocl.parser.OCLAnalyzer.parseOCLDocument(OCLAnalyzer.java:182)
	at org.eclipse.ocl.OCL.parse(OCL.java:258)
	at org.eclipse.ocl.examples.console.util.OCLConsoleUtil.loadOCLDocument(OCLConsoleUtil.java:205)
	at org.eclipse.ocl.examples.console.actions.LoadDocumentAction.run(LoadDocumentAction.java:91)

In the debugger, I noticed something odd:

	public static void loadOCLDocument(IWorkbenchPartSite site, OCLInput input) {
		OCLNode node = getSelectedOCLNode(site);
		OCL ocl = node.element();
		
		try {
			ocl.parse(input); // here,  ocl.environmentFactory.umlMetamodel == null.

It seems to me that the ocl env should know what is our metamodel...
Who has the responsibility for initializing the metamodel?

4) load/save for both OCL documents & OCL environments

With a combination of loaded OCL documents & OCL content I can edit with the console, the only thing missing is to be able to save the whole thing & reload it later.



Comment 5 Christian Damus CLA 2009-01-13 13:23:07 EST
(In reply to comment #3)
> Created an attachment (id=122237)
> Patch to the old OCL example interpreter plugin.properties file

Thanks.  That's a good idea.

(In reply to comment #4)
> Wow! This is amazing!
> 
> I have 4 comments.
> 
> 1) The Query folder shows the first line of a multi-line query expression typed
> in the OCL Input window.

Yes.  You can alse edit the name post facto.

> This can be useful to give a useful mnemonic to a complex query, e.g.:
> 
> -- who am I?
> self.qualifiedName
> 
> The query folder only shows "-- who am I?"

Is that a bad thing?  Newlines are always awkward to deal with in flat labels.


> 3) loading *.ocl
> 
> What is the grammar for OCL documents?

Section 12.12 of the OCL Specification.


> In the debugger, I noticed something odd:
> 
> public static void loadOCLDocument(IWorkbenchPartSite site, OCLInput input) {
> OCLNode node = getSelectedOCLNode(site);
> OCL ocl = node.element();
> 
> try {
> ocl.parse(input); // here,  ocl.environmentFactory.umlMetamodel == null.

The UMLOCLProvider ensures that the UML metamodel and its dependencies are loaded in your resource set.  You should actually see them load in the *.uml editor.

> 
> It seems to me that the ocl env should know what is our metamodel...
> Who has the responsibility for initializing the metamodel?

The UML environment knows about it and loads it when and if it is needed, but in this particular case, something else than the environment is looking for it.  That's why the UMLOCLProvider loads it proactively.

Try debugging the UMLOCLProvider ...


> 4) load/save for both OCL documents & OCL environments
> 
> With a combination of loaded OCL documents & OCL content I can edit with the
> console, the only thing missing is to be able to save the whole thing & reload
> it later.

Heh heh ... yes.  I was thinking of creating a workspace save participant.  However, the problem is that the UML environment needs a resource-set context in which to load models (unlike the Ecore environment).  I would have to figure out a way to re-connect a UML environment to a particular *.uml editor's resource set on start-up.
Comment 6 Nicolas Rouquette CLA 2009-01-15 13:44:12 EST
Christian,

Showing only the first line of a multi-line expression is a good thing for the OCLEnvironment view.
Taking advantage of this feature (accidental luck or intentional wisdom) enhances the usability of the OCLEnvironment view.

Following your suggestion, I tracked down the problem where the result of org.eclipse.ocl.examples.console.uml.UMLOCLProvider.createEnvironmentFactory(EObject)
is a UMLEnvironmentFactory object with a null umlMetamodel property.

I open a metamodel in the UMLEditor (e.g., fUML from the spec: http://www.omg.org/spec/FUML)

a) If I select the UML resource and in the OCLEnvironment view click on the "New Environment" button, I get an error:

"Cannot determine a metamodel context for the environment. Please select an EMF model element in an editor or view.

This error happens when the list of environments in the view is empty.
When I have environments in the OCLEnvironment view, it seems that I can create a new OCLEnvironment 
regardless of whether I select the resource of a model element in the UMLEditor.
I haven't tracked down the peculiar state responsible for this behavior distinction.

b) This time, I selected a model element.
The relevant stack trace is this:

AdapterFactoryEditingDomain$AdapterFactoryEditingDomainResourceSet(ResourceSetImpl).getResource(URI, boolean) line: 371 // step 3
OCLUMLUtil.getUMLMetamodel(ResourceSet) line: 488	// step 2
UMLOCLProvider.createEnvironmentFactory(EObject) line: 83	// step 1
NewEnvironmentAction.createOCL() line: 97	
NewEnvironmentAction.run() line: 67	
NewEnvironmentAction(Action).runWithEvent(Event) line: 498	

At step 1, the UMLOCLProvider has created a new UMLEnvironmentFactory whose umlMetamodel attribute is null. 
The idea is that ECore.resolveAll(...) should be setting the umlMetamodel attribute.

At step 2, the OCLUMLUtil makes sure that the resource set includes a resource for the UML metamodel

Resolving the UML metamodel seems to be the responsibility of the UMLEnvironment itself but this is a protected API.

if org.eclipse.ocl.uml.UMLEnvironmentFactory.getUMLMetamodel() becomes public (see attached patch), 
then this problem has an elegant solution as shown below:

	public EnvironmentFactory<Package, Classifier, Operation, Property, EnumerationLiteral, Parameter, State, CallOperationAction, SendSignalAction, Constraint, Class, EObject> createEnvironmentFactory(
			EObject context) {

		UMLEnvironmentFactory result;
		Resource contextRes = context.eResource();

		if ((contextRes != null) && (contextRes.getResourceSet() != null)) {
			result = new UMLEnvironmentFactory(contextRes.getResourceSet());
		} else {
			result = new UMLEnvironmentFactory();
		}

		// ensure that we have the UML metamodel loaded, and all of its
		// dependencies
		EcoreUtil.resolveAll(result.getUMLMetamodel());

		return result;
	}


Comment 7 Nicolas Rouquette CLA 2009-01-15 13:45:13 EST
Created attachment 122707 [details]
change visibility from protected to public
Comment 8 Nicolas Rouquette CLA 2009-01-22 12:33:52 EST
Quitting the workbench can induce SWT exceptions:

org.eclipse.swt.SWTException: Widget is disposed
at org.eclipse.swt.SWT.error(SWT.java:3827)
at org.eclipse.swt.SWT.error(SWT.java:3742)
at org.eclipse.swt.SWT.error(SWT.java:3713)
at org.eclipse.swt.widgets.Widget.error(Widget.java:463)
at org.eclipse.swt.widgets.Widget.getDisplay(Widget.java:578)
at org.eclipse.ocl.examples.console.tree.AbstractTreeNode.packViewerLater(AbstractTreeNode.java:94)
at org.eclipse.ocl.examples.console.tree.AbstractTreeNode.update(AbstractTreeNode.java:90)
at org.eclipse.ocl.examples.console.tree.EObjectNode$RefreshAdapter.notifyChanged(EObjectNode.java:123)
at org.eclipse.emf.common.notify.impl.BasicNotifierImpl$EAdapterList.didRemove(BasicNotifierImpl.java:95)
at org.eclipse.emf.common.util.BasicEList.didClear(BasicEList.java:260)
at org.eclipse.emf.common.util.BasicEList.clear(BasicEList.java:1000)
at org.eclipse.emf.common.notify.impl.BasicNotifierImpl$EAdapterList.clear(BasicNotifierImpl.java:171)
at org.eclipse.emf.ecore.resource.impl.ResourceImpl.unloaded(ResourceImpl.java:1559)
at org.eclipse.emf.ecore.resource.impl.ResourceImpl.doUnload(ResourceImpl.java:1618)
at org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl.doUnload(XMLResourceImpl.java:505)
at org.eclipse.emf.ecore.resource.impl.ResourceImpl.unload(ResourceImpl.java:1633)
at org.eclipse.ocl.AbstractTypeResolver.dispose(AbstractTypeResolver.java:1068)
at org.eclipse.ocl.AbstractEnvironment.dispose(AbstractEnvironment.java:1168)
at org.eclipse.ocl.OCL.dispose(OCL.java:742)

There is a simple fix in console.tree.AbstractTreeNode:

original:

	protected void packViewerLater() {
		viewer.getControl().getDisplay().asyncExec(new Runnable() {
			
			public void run() {
				// text changes affect width
				viewer.getTree().getColumns()[0].pack();
			}
		});
	}

modified:

	protected void packViewerLater() {
		final Control control = viewer.getControl();
		final Tree tree = viewer.getTree();
		
		if (control.isDisposed() || tree.isDisposed())
			return;
		
		control.getDisplay().asyncExec(new Runnable() {
			
			public void run() {
				// text changes affect width
				tree.getColumns()[0].pack();
			}
		});
	}

Comment 9 Christian Damus CLA 2009-02-09 08:46:38 EST
Adding Rich to cc, as this bug intends to obsolete the console recently incorporated into the DSL Toolkit.
Comment 10 Ed Willink CLA 2009-08-03 03:16:52 EDT
This should be generalised to work with the OCL editor.

Perhaps:

While editing the OCL constraints on a meta-model, DND a user model to create an additional editor sheet and auto-activate the OCL Console, allowing evaluations on the user model exploiting the full OCL constraints.
Comment 11 Adolfo Sanchez-Barbudo Herrera CLA 2009-08-03 08:46:11 EDT
Hi Ed,

I agree that we could make OCL take part of the new UI feature. Your proposal sounds really promising, although I would raise a different bugzilla for it, so that we have one (this) bug to move (and improve) the interpreter as part of the OCL UI and different one which would integrate OCL Editor and the OCL console.

What do you think ?

Cheers,
Adolfo.
Comment 12 Ed Willink CLA 2009-08-03 14:55:42 EDT
I think it's too soon for another Bugzilla.

Someone will take on upgrading the example and pick as many ideas as practical. I thbink we then raise Bugzillas for the residue.