Difference between pages "Extending the Rodin Structured Editor (How to extend Rodin Tutorial)" and "Extending the Rodin database (How to extend Rodin Tutorial)"

From Event-B
(Difference between pages)
Jump to navigationJump to search
imported>Pascal
 
imported>Tommy
m
 
Line 1: Line 1:
{{Navigation|Previous= [[Extend_Rodin_database_(How_to_extend_Rodin_Tutorial)|Extend the database]]| Next= [[Extend_Rodin_EventB_Explorer(How_to_extend_Rodin_Tutorial)|Adding elements to the Event-B explorer]]| Up= [[Plug-in_Tutorial|How to extend Rodin Tutorial (Index)]]}}
+
{{Navigation|Previous= [[Extend_Rodin_database_(How_to_extend_Rodin_Tutorial)|Extend the database]]|Next=[[Extend_Rodin_Structured_Editor_(How_to_extend_Rodin_Tutorial)|Extend the structured editor]] | Up= [[Plug-in_Tutorial|How to extend Rodin Tutorial (Index)]]}}
  
 
=== In this part ===
 
=== In this part ===
We will use the extension points provided by the plug-in <tt>org.eventb.ui</tt> to add our Probabilistic attribute on events and the Bound element to the structured editor.
+
We will explain how to add a new attribute to events elements and add a new element in the database.
 +
Here are the steps we will detail :
 +
# add dependencies to the plugins providing the extension services and interfaces we want to use,
 +
# add the extensions point we will use, and define our extensions,
 +
# implement required classes to specify newly added elements,
 +
# create an interface using Eclipse content assist
 +
For more information about the database extension, please refer to :  [[Extending_the_Rodin_Database| Extending the Rodin Database]]
  
 
=== Step 1 ===
 
=== Step 1 ===
To structure a bit our development, we will separate the UI from the business layer.<br>
+
When one wants to use extension points provided by a plugin, one has to add a dependency to this plugin.
1. Create a new plug-in (here <tt>fr.systerel.rodinextension.sample.ui</tt>, and this time, select "This plug-in will make contributions to the UI" as it will be indeed the case here.<br>
+
We will use 2 extension points to extend the database, so we need to add a dependency to the plugin <tt>org.rodinp.core</tt> which defines them.
2. Add our business plug-in (<tt>fr.systerel.rodinextension.sample</tt>) to the dependencies as well as <tt>org.eventb.ui</tt> that provides the extensions points we want to use.
+
Moreover, as we want to manipulate event-b elements, we will manipulate interfaces and public classes provided by the event-B plugin.
 +
We will then add a dependency to the plugin <tt>org.eventb.core</tt>
 +
To do this, open the MANIFEST.MF file in the forlder META-INF of our plugin to get the following:
 +
 
 +
[[Image:Extend_Rodin_Tuto_1_5_Manifest_dependencies.png|500px]]
 +
 
 +
1. Click on the "Dependencies" Tab, <br>
 +
2. Click on the Add button.<br>
 +
A dialog appears, start to enter <tt>org.rodinp.core</tt> and select this plugin, press "OK" to add it to the dependencies.<br>
 +
The dependency to <tt>org.rodinp.core</tt> has been added.
 +
Re-do the above operations to add <tt>org.eventb.core</tt>.
 +
 
 +
You should now have the following dependencies added to the plugin :
 +
 
 +
[[Image:Extend_Rodin_Tuto_1_5_Added_Dependencies.png|200px]]
  
 
=== Step 2 ===
 
=== Step 2 ===
1. Add an extension to the extension point <tt>org.eventb.ui.editorItems</tt>.<br>
+
We will add now the Extensions Points that we want to use, and define extensions using them.
At this point, we start to extend the structured editor.<br>
+
 
 +
[[Image:Extend_Rodin_Tuto_1_6_Add_Extension_Point.png|400px]]
 +
 
 +
1. Click on the "Extensions" Tab, <br>
 +
2. and click on the "Add" button.
 +
 
 +
[[Image:Extend_Rodin_Tuto_1_6_Extension_Point_Selection.png|440px]]
 +
 
 +
As we will start by extending the database by adding the attribute "probabilistic", we will create an extension for <tt>org.rodinp.core.attributeTypes</tt> extension point. Hence, we need to add this extension point first before creating an extension with it.
 +
To do so... on the wizard that appeared (see picture above):<br>
 +
1. start to type the extension point name <tt>org.rodinp.core.attributeTypes</tt>, to reveal it in the list of available extension points,<br>
 +
2. select it in the list, and click on "Finish" to add it.
 +
 
 +
The extension point <tt>org.rodinp.core.attributeTypes</tt> now appears in the list on the "Extensions" page of the MANIFEST.MF of our plugin.
  
 
=== Step 3 ===
 
=== Step 3 ===
First, let's add the probabilistic attribute to Event-B events.<br>
+
We will now add the attribute "probabilistic" in the database, creating an extension for <tt>org.rodinp.core.attributeTypes</tt>.
The probabilistic attribute can have two values : 'standard' (by default) and 'probabilistic'. Thus we need to create a 'choiceAttribute' extension.
+
Right click on the extension point, select <tt>New > attributeType</tt> as in the picture below :
Create a new 'choice attribute' extension:<br>
 
1. Give a unique ID to identify this attribute in the UI plug-in (such as <tt>fr.systerel.rodinextension.sample.ui.probabilistic</tt>).<br>
 
2. In typeID, give the ID reference of the probabilistic attribute in our business plug-in (here <tt>fr.systerel.rodinextension.sample.probabilistic</tt>).<br>
 
3. Set the ''required'' attribute to <tt>true</tt> as we want this attribute to appear by default in the structured editor when editing events.<br>
 
4. Create a class (using Eclipse assist, see [[Extend_Rodin_database_(How_to_extend_Rodin_Tutorial)|Extending the Rodin Database]]) to manipulate this attribute; this class should implements the interface <tt>org.eventb.ui.IAttributeManipulation</tt>.
 
  
:Before doing any manipulation of the given <tt>IRodinElement</tt>, we have to cast this element as an <tt>IInternalElement</tt> (interface from <tt>org.rodinp.core</tt> providing access to element attributes). As we know that the element that will carry the probabilistic attribute is of type <tt>IEvent</tt>, and as <tt>IEvent</tt> implements the interface <tt>IInternalElement</tt>, let's create the following method.
+
[[Image:Extend_Rodin_Tuto_1_7_Add_Attibute_Extension.png|440px]]
  
  private IEvent asEvent(IRodinElement element) {
+
A new extension <tt>attributeType</tt> has been added. We will edit it to add our "probabilistic" attribute.<br>
assert element instanceof IEvent;
+
As an event can be probabilistic or not, we set the kind of this attribute to <tt>boolean</tt>.
return (IEvent) element;
+
Give a unique ID to this attribute (here <tt>probabilistic</tt>) and a name (here <tt>Event-B Probabilistic Attribute</tt>).
}
+
You should now have something similar to what appears in the picture below :
:We also have to add the ID of the probabilistic attribute as a constant, as we will need it at various places in this class. We then add the following code:
 
  
  public static IAttributeType.Boolean PROB_ATTRIBUTE = RodinCore
+
[[Image:Extend_Rodin_Tuto_1_7_Add_Attibute_Extension2.png]]
.getBooleanAttrType(QualProbPlugin.PLUGIN_ID + ".probabilistic");
 
  
:It is necessary to add the <tt>fr.systerel.rodinextension.sample.QualProbPlugin</tt> import clause. Then use the quick assist (while you go over QualProbPlugin underlined in red in the import clause) to export the <tt>fr.systerel.rodinextension.sample</tt> plug-in and make this class accessible.
+
=== Step 4 ===
 +
 
 +
We will now add a new element "'''Bound'''" to set the upper bound of the probabilistic variant.<br>
 +
Repeat the step 2, to add the extension point : <tt>org.rodinp.core.internalElementTypes</tt>.<br>
 +
Create an extension to specify our new element "'''Bound'''" using the right click as previously.<br>
 +
You shall now specify the details for this new extension element :
 +
 
 +
[[Image:Extend_Rodin_Tuto_1_7_Bound_Extension.png]]
 +
 
 +
As in the picture above :<br>
 +
1. give the element a unique ID (here <tt>bound</tt>)<br>
 +
2. give a name to this element (here Event-B Bound Element)<br>
 +
3. now things differ, as this extension point (<tt>org.rodinp.core.internalElementTypes</tt>) requires us to provide a class describing the element.<br>
 +
Click on the "class*:" link to open a wizard that will help us to create this class.
 +
 
 +
The following wizard appears :
 +
 
 +
[[Image:Extend_Rodin_Tuto_1_7_Bound_Extension_New_Java_Class_Bound.png|400px]]
 +
 
 +
1. First specify a package where you want this class to be stored. As we want to organise a bit the project, we will say that all elements that we add will be part of a new package called <tt>fr.systerel.rodinextension.sample.basis</tt>,<br>
 +
2. Give the name of the class : "Bound",<br>
 +
3. We see that the superclass of this element is <tt>org.rodinp.core.basis.InternalElement</tt> but we know that we will implement an element specific to Event-B, so we put here <tt>org.eventb.core.basis.EventBElement</tt>,<br>
 +
4. You can optionnaly add comments automatically to the created class, if you set them in "Preferences > Java > Code Style > Code Templates",<br>
 +
5. Click on "Finish" to create the class.
  
<tt>IAttributeType.Boolean</tt> defines that our probabilistic attribute is actually coded as a boolean. We will implement the probabilistic attribute as follows:
+
The class ''Bound.java'' has now been created. We can open it and review its contents that we anyway shall modify now.
* If the event is probabilistic, the probabilistic attribute is set to <tt>true</tt>,
 
* Otherwise, the event is standard (e.g. non probabilistic), so the probabilistic attribute is set to <tt>false</tt>.
 
Note that there are several types for attributes. See [http://wiki.event-b.org/index.php/Extending_the_Rodin_Database#Getting_the_corresponding_Java_attribute_kind here] for more details.
 
  
Now let's fill the methods required to implement <tt>IAttributeManipulation</tt> :
+
=== Step 5 ===
:1. <tt>getPossibleValues(IRodinElement element, IProgressMonitor monitor)</tt> should return an array of two constant values : "standard" and "probabilistic".<br>
+
We now opened the class ''Bound.java'' and see that we need to implement the method <tt>getElementType()</tt> inherited from the superclass.<br>
:2. <tt>getValue(IRodinElement element, IProgressMonitor monitor)</tt> should 'convert' the given element as an event (using <tt>asEvent</tt>) and return the value corresponding to the state of the probabilistic attribute (retrieved by <tt>IInternalElement.getAttributeValue(PROB_ATTRIBUTE)</tt>). For example, it should return "probabilistic" if the attribute has value <tt>true</tt>, "standard" otherwise.<br>
+
As the type of element might be needed from outside, and is common to all Bound element, we will create a constanst in a new interface IBound that we have to create.<br>
:3. <tt>hasValue(IRodinElement element, IProgressMonitor monitor)</tt> should check if the given element converted as an event has a probabilistic attribute using the method <tt>IInternalElement.hasAttribute(PROB_ATTRIBUTE)</tt>.<br>
+
Enter in the method body the following code :
:4. <tt>removeAttribute(IRodinElement element, IProgressMonitor monitor)</tt> should convert the given element as an event, and use <tt>IInternalElement.removeAttribute(PROB_ATTRIBUTE, monitor)</tt>.<br>
+
return IBound.ELEMENT_TYPE;
:5. <tt>setDefaultValue(IRodinElement element, IProgressMonitor monitor)</tt> should convert the given element as an event, and do <tt>IInternalElement.setAttributeValue(PROB_ATTRIBUTE,</tt> '''false'''<tt>, monitor);</tt> as the default value for the probabilistic attribute is '''false'''.<br>
 
:6. finally, <tt>setValue(IRodinElement element, String value, IProgressMonitor monitor)</tt> should check that the given value correspond to the "probabilistic" string constant, and set the value of the element (previously converted as an event) to <tt>true</tt> if it is the case, or set the value to <tt>false</tt> otherwise.
 
  
Now we will add this attribute to events. To do so, we need to create an attribute relation that will link our probabilistic attribute to events. Return to the MANIFEST.MF extensions page.<br>
+
[[Image:Extend_Rodin_Tuto_1_7_Create_Interface_Menu.png|400px]]
1. Create a new ''attributeRelation'' extension from the <tt>org.eventb.ui.editorItems</tt> extension point.<br>
 
2. Enter <tt>org.eventb.core.event</tt> as ''elementTypeId'' in the attribute relation. This means that events will hold an attribute.<br>
 
3. From this extension specify that the attribute held by events (among others) will be our probabilistic attribute by adding an ''attributeReference'' with the ID of our UI extension for the probabilistic attribute (here <tt>fr.systerel.rodinextension.sample.ui.probabilistic</tt>).
 
  
=== Step 4 ===
+
Then use the quick assist (while you go over IBound underlined in red), to create the interface IBound.
Finally, let's add the Bound element to Event-B machines.<br>
+
The following wizard appears :
This step differs from the previous, as our element Bound is a new element (not an attribute). We want it to appear at top level in the structured editor, as invariants, events, etc.
+
 +
[[Image:Extend_Rodin_Tuto_1_7_Create_Interface_Wizard.png|400px]]
  
We will then:
+
Use here the "Extended Interfaces" field to specify that the element '''Bound''' should be commented (thus shall implement ICommentedElement) and will carry an expression (thus shall implement IExpressionElement) for the value of the bound.  
# Register the Bound element as an UI element (i.e. a new type of element in the UI).
 
# Set this element to be a 'child' of machine elements (i.e. Bound will belong to machine files).
 
# Set up a link to edit expressions of the Bound element in the UI (Bound elements carry one expression [they extend <tt>IExpressionElement</tt>]).
 
# Set up a link to edit comments of the Bound element in the UI (Bound elements carry one comment [they extend <tt>ICommentedElement</tt>]).
 
  
1. To register the Bound element in the UI, create an extension 'element':
+
public interface IBound extends ICommentedElement, IExpressionElement {
:- In typeId, specify the ID of the extension Bound in our business plug-in (here <tt>fr.systerel.rodinextension.sample.bound</tt>).
+
IInternalElementType<IBound> ELEMENT_TYPE = RodinCore
:- In imagePath, you can specify the icon to be displayed next to the element (we have created here a folder 'icons' containing a default icon).
+
.getInternalElementType(QualProbPlugin.PLUGIN_ID + ".bound");
:- In prefix, type 'BOUND', this value will appear as the header of bound elements in the structured editor.
+
}
:- In 'defaultColumn' field, put the value '0' as to make the Bound element appear at top level in the outline of machines.
 
  
2. To set Bound element to be a child element of a machine:
+
Modify the class <tt>Bound.java</tt> to add <tt>implements IBound</tt>.<br>
:- Create an extension 'childRelation' using the extension point <tt>org.eventb.ui.editorItems</tt>.<br>
+
At this point of the development, you should have the following extensions :
:- In ''parentTypeId'' field of this extension, enter "<tt>org.eventb.core.machineFile</tt>" to refer to machine files.<br>
 
:- Create a sub element for the child relation extension<br>
 
:- and refer to the ID of the bound in our business class (here <tt>fr.systerel.rodinextension.sample.bound</tt>).<br>
 
:- Put a priority of '65' to display Bound elements after ''variants'' but before ''events'' (Have a look at the ''childRelation'' for <tt>org.eventb.core.machineFile</tt> type in extension <tt>org.eventb.ui.editorItems</tt> of the package <tt>org.eventb.ui</tt> to view the priorities of other elements displayed in the structured editor).
 
  
3. To set up a link to edit the expression of a Bound element:
+
[[Image:Extend_Rodin_Tuto_1_7_Used_Extensions.png]]
:- Create an extension ''attributeRelation'' for our elementTypeId <tt>fr.systerel.rodinextension.sample.bound</tt>.
 
:- Add one ''attributeReference'' to <tt>org.eventb.ui.expression</tt> (descriptionID).
 
  
4. To set up a link to edit the comment of a Bound element:
+
and you should have the following contents in your plugin :
:- Repeat addition of an ''attributeReference'' to the above ''attributeRelation'' but specifying <tt>org.eventb.ui.expression</tt> as descriptionID.
 
  
You can now launch a Rodin product with our plug-ins imported and see the result:
+
[[Image:Extend_Rodin_Tuto_1_7_ProjectExplorer2.png.png]]
  
[[Image:Extend_Rodin_Tuto_1_8_Used_ExtensionsExtended_UI.png]]
+
The sources of the plugin at this point can be downloaded here : // FIXME attach sources here.
  
Congratulations! You are now able to edit the elements that you added in Rodin Database.
+
=== In Brief ===
  
{{Navigation|Previous= [[Extend_Rodin_database_(How_to_extend_Rodin_Tutorial)|Extending the database]] | Next= [[Extend_Rodin_EventB_Explorer(How_to_extend_Rodin_Tutorial)|Adding elements to the Event-B explorer]] | Up= [[Plug-in_Tutorial|How to extend Rodin Tutorial (Index)]]}}
+
We saw how to use Eclipse to add extension points that will be used in our plugin and created our extensions using some helpful Eclipse automatic actions (wizard, content assist...).
 +
As we had a detailed view (captures) of all the actions further needed, the next parts of this tutorial will focus only on the extensions.
 +
 +
{{Navigation|Previous= [[Extend_Rodin_database_(How_to_extend_Rodin_Tutorial)|Extend the database]]|Next= [[Extend_Rodin_Structured_Editor_(How_to_extend_Rodin_Tutorial)|Extend the structured editor]] | Up= [[Plug-in_Tutorial|How to extend Rodin Tutorial (Index)]]}}
  
 
[[Category:Developer documentation|*Index]]
 
[[Category:Developer documentation|*Index]]
 
[[Category:Rodin Platform|*Index]]
 
[[Category:Rodin Platform|*Index]]
 
[[Category:Tutorial|*Index]]
 
[[Category:Tutorial|*Index]]

Revision as of 16:05, 19 August 2010

In this part

We will explain how to add a new attribute to events elements and add a new element in the database. Here are the steps we will detail :

  1. add dependencies to the plugins providing the extension services and interfaces we want to use,
  2. add the extensions point we will use, and define our extensions,
  3. implement required classes to specify newly added elements,
  4. create an interface using Eclipse content assist

For more information about the database extension, please refer to : Extending the Rodin Database

Step 1

When one wants to use extension points provided by a plugin, one has to add a dependency to this plugin. We will use 2 extension points to extend the database, so we need to add a dependency to the plugin org.rodinp.core which defines them. Moreover, as we want to manipulate event-b elements, we will manipulate interfaces and public classes provided by the event-B plugin. We will then add a dependency to the plugin org.eventb.core To do this, open the MANIFEST.MF file in the forlder META-INF of our plugin to get the following:

Extend Rodin Tuto 1 5 Manifest dependencies.png

1. Click on the "Dependencies" Tab,
2. Click on the Add button.
A dialog appears, start to enter org.rodinp.core and select this plugin, press "OK" to add it to the dependencies.
The dependency to org.rodinp.core has been added. Re-do the above operations to add org.eventb.core.

You should now have the following dependencies added to the plugin :

Extend Rodin Tuto 1 5 Added Dependencies.png

Step 2

We will add now the Extensions Points that we want to use, and define extensions using them.

Extend Rodin Tuto 1 6 Add Extension Point.png

1. Click on the "Extensions" Tab,
2. and click on the "Add" button.

Extend Rodin Tuto 1 6 Extension Point Selection.png

As we will start by extending the database by adding the attribute "probabilistic", we will create an extension for org.rodinp.core.attributeTypes extension point. Hence, we need to add this extension point first before creating an extension with it. To do so... on the wizard that appeared (see picture above):
1. start to type the extension point name org.rodinp.core.attributeTypes, to reveal it in the list of available extension points,
2. select it in the list, and click on "Finish" to add it.

The extension point org.rodinp.core.attributeTypes now appears in the list on the "Extensions" page of the MANIFEST.MF of our plugin.

Step 3

We will now add the attribute "probabilistic" in the database, creating an extension for org.rodinp.core.attributeTypes. Right click on the extension point, select New > attributeType as in the picture below :

Extend Rodin Tuto 1 7 Add Attibute Extension.png

A new extension attributeType has been added. We will edit it to add our "probabilistic" attribute.
As an event can be probabilistic or not, we set the kind of this attribute to boolean. Give a unique ID to this attribute (here probabilistic) and a name (here Event-B Probabilistic Attribute). You should now have something similar to what appears in the picture below :

Extend Rodin Tuto 1 7 Add Attibute Extension2.png

Step 4

We will now add a new element "Bound" to set the upper bound of the probabilistic variant.
Repeat the step 2, to add the extension point : org.rodinp.core.internalElementTypes.
Create an extension to specify our new element "Bound" using the right click as previously.
You shall now specify the details for this new extension element :

Extend Rodin Tuto 1 7 Bound Extension.png

As in the picture above :
1. give the element a unique ID (here bound)
2. give a name to this element (here Event-B Bound Element)
3. now things differ, as this extension point (org.rodinp.core.internalElementTypes) requires us to provide a class describing the element.
Click on the "class*:" link to open a wizard that will help us to create this class.

The following wizard appears :

Extend Rodin Tuto 1 7 Bound Extension New Java Class Bound.png

1. First specify a package where you want this class to be stored. As we want to organise a bit the project, we will say that all elements that we add will be part of a new package called fr.systerel.rodinextension.sample.basis,
2. Give the name of the class : "Bound",
3. We see that the superclass of this element is org.rodinp.core.basis.InternalElement but we know that we will implement an element specific to Event-B, so we put here org.eventb.core.basis.EventBElement,
4. You can optionnaly add comments automatically to the created class, if you set them in "Preferences > Java > Code Style > Code Templates",
5. Click on "Finish" to create the class.

The class Bound.java has now been created. We can open it and review its contents that we anyway shall modify now.

Step 5

We now opened the class Bound.java and see that we need to implement the method getElementType() inherited from the superclass.
As the type of element might be needed from outside, and is common to all Bound element, we will create a constanst in a new interface IBound that we have to create.
Enter in the method body the following code :

return IBound.ELEMENT_TYPE;

Extend Rodin Tuto 1 7 Create Interface Menu.png

Then use the quick assist (while you go over IBound underlined in red), to create the interface IBound. The following wizard appears :

Extend Rodin Tuto 1 7 Create Interface Wizard.png

Use here the "Extended Interfaces" field to specify that the element Bound should be commented (thus shall implement ICommentedElement) and will carry an expression (thus shall implement IExpressionElement) for the value of the bound.

public interface IBound extends ICommentedElement, IExpressionElement {
	IInternalElementType<IBound> ELEMENT_TYPE = RodinCore
			.getInternalElementType(QualProbPlugin.PLUGIN_ID + ".bound");
}

Modify the class Bound.java to add implements IBound.
At this point of the development, you should have the following extensions :

Extend Rodin Tuto 1 7 Used Extensions.png

and you should have the following contents in your plugin :

Extend Rodin Tuto 1 7 ProjectExplorer2.png.png

The sources of the plugin at this point can be downloaded here : // FIXME attach sources here.

In Brief

We saw how to use Eclipse to add extension points that will be used in our plugin and created our extensions using some helpful Eclipse automatic actions (wizard, content assist...). As we had a detailed view (captures) of all the actions further needed, the next parts of this tutorial will focus only on the extensions.