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

From Event-B
(Difference between pages)
Jump to navigationJump to search
imported>Pascal
 
imported>Pascal
 
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)]]}}
+
{{TOCright}}
 +
= Introduction =
 +
The purpose of this page is to describe how to extend the static checker. It covers on the one hand, the definition of the extension, and on the other hand its implementation.
  
=== In this part ===
+
The useful extension points are listed below; they offer the possibility to contribute to the static checker:
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.
+
* <tt>org.rodinp.core.autoTools</tt>
 +
* <tt>org.eventb.core.configurations</tt>
 +
* <tt>org.rodinp.core.internalElementTypes</tt>
 +
* <tt>org.eventb.core.scModuleTypes</tt>
 +
* <tt>org.eventb.core.scStateTypes</tt>
  
=== Step 1 ===
+
= Before Starting =
To structure a bit our development, we will separate the UI from the business layer.<br>
 
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>
 
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.
 
  
=== Step 2 ===
+
It is necessary to define the static checked elements that are similar to the unchecked elements. We will use as an example the ''decompositionFile'' that is defined as follows:
1. Add an extension to the extension point <tt>org.eventb.ui.editorItems</tt>.<br>
 
At this point, we start to extend the structured editor.<br>
 
  
=== Step 3 ===
+
*decompositionFile
First, let's add the probabilistic attribute to Event-B events.<br>
+
**decompositionRoot
The probabilistic attribute can have two values : 'standard' (by default) and 'probabilistic'. Thus we need to create a 'choiceAttribute' extension.
+
***Component (machine to be decomposed)
Create a new 'choice attribute' extension:<br>
+
***Configuration (''style'': shared events/shared variables;''newProjectOption'': decompose in the same project/different projects;''decomposeContextOption'':no decomposition/minimal decomposition)
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>
+
***SubComponent (resulting decomposed parts)
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>
+
****SubComponentElement (elements used to decompose: variables for shared event decomposition and events for shared variable decomposition)
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:Decomp file pretty print.png]]
  
  private IEvent asEvent(IRodinElement element) {
+
To extend the static checker, it is necessary to add a new content type (<tt>org.eclipse.core.contenttype.contentTypes</tt>) containing the checked version of the decompositionFile:
assert element instanceof IEvent;
 
return (IEvent) element;
 
}
 
: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
+
      <content-type
.getBooleanAttrType(QualProbPlugin.PLUGIN_ID + ".probabilistic");
+
          base-type="org.rodinp.core.rodin"
 +
          file-extensions="dcc,dcc_tmp"
 +
          id="scDcpFile"
 +
          name="Event-B Statically Checked Decomposition File"
 +
          priority="normal">
 +
    </content-type>
  
: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.
+
and the respective file association (<tt>org.rodinp.core.fileAssociations</tt>):
  
<tt>IAttributeType.Boolean</tt> defines that our probabilistic attribute is actually coded as a boolean. We will implement the probabilistic attribute as follows:
+
    <fileAssociation
* If the event is probabilistic, the probabilistic attribute is set to <tt>true</tt>,
+
          content-type-id="ch.ethz.eventb.decomposition.core.scDcpFile"
* Otherwise, the event is standard (e.g. non probabilistic), so the probabilistic attribute is set to <tt>false</tt>.
+
          root-element-type="ch.ethz.eventb.decomposition.core.scDcpFile">
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.
+
    </fileAssociation>
 +
     
 +
The respective static checked elements must be added as internal elements using the extension <tt>org.rodinp.core.internalElementTypes</tt>:
  
Now let's fill the methods required to implement <tt>IAttributeManipulation</tt> :
+
<extension
:1. <tt>getPossibleValues(IRodinElement element, IProgressMonitor monitor)</tt> should return an array of two constant values : "standard" and "probabilistic".<br>
+
        point="org.rodinp.core.internalElementTypes">
: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>
+
    <internalElementType
: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>
+
          class="ch.ethz.eventb.decomposition.core.basis.DecompositionRoot"
: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>
+
          id="dcpFile"
: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>
+
          name="%eventBdcpFile">
: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.
+
    </internalElementType>
 +
    <internalElementType
 +
          class="ch.ethz.eventb.decomposition.core.basis.SCDecompositionRoot"
 +
          id="scDcpFile"
 +
          name="Event-B Statically Checked Decomposition Root">
 +
    </internalElementType>
 +
    <internalElementType
 +
          class="ch.ethz.eventb.decomposition.core.basis.DecompositionConfiguration"
 +
          id="configuration"
 +
          name="%eventBDecompositionConfiguration">
 +
    </internalElementType>
 +
    <internalElementType
 +
          class="ch.ethz.eventb.decomposition.core.basis.SCDecompositionConfiguration"
 +
          id="scConfiguration"
 +
          name="Event-B Statically Checked Decomposition Configuration">
 +
    </internalElementType>
 +
</extension>
  
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>
+
In the above example, the first internal element type is the unckecked internal element, and the second is the same internal element but in the checked version. Having the checked elements defined, we can start to extend the static checker for our files and respective elements.
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 ===
+
= AutoTools =
Finally, let's add the Bound element to Event-B machines.<br>
 
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.
 
  
We will then:
+
The static checker it is a tool that runs automatically. In order to implement the tool, it is necessary to define the following extension point <tt>org.rodinp.core.autoTools</tt>. This extension point allows tools to run automatically when changes to the Rodin database are committed. To implement the reactive model of Rodin, automatic tools run only when one of their input files has changed. As such, for each automatic tool, plugin developers must provide two kinds of contributions:
# 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':
+
* Some dependency extractors.
:- In typeId, specify the ID of the extension Bound in our business plug-in (here <tt>fr.systerel.rodinextension.sample.bound</tt>).
+
* The tool itself.
:- In imagePath, you can specify the icon to be displayed next to the element (we created here a folder 'icons' containing an default icon).
 
:- 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:
+
== Declaration ==
:- Create an extension 'childRelation' using the extension point <tt>org.eventb.ui.editorItems</tt>.<br>
 
:- 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:
+
The <tt>autoTools</tt> extension-point allows tool writers to register their tool implementation under a symbolic name that is then used by the Rodin platform to find and run the tool. The symbolic name is the id of the tool extension. An example of the implementation of a static checker can be seen as follows:
:- 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:
+
<extension
:- Repeat addition of an ''attributeReference'' to the above ''attributeRelation'' but specifying <tt>org.eventb.ui.expression</tt> as descriptionID.
+
        point="org.rodinp.core.autoTools">
 +
    <tool
 +
          class="ch.ethz.eventb.decomposition.internal.core.sc.DecompositionStaticChecker"
 +
          id="decompositionSC"
 +
          name="Decomposition Static Checker">
 +
        <extractor
 +
              class="ch.ethz.eventb.decomposition.internal.core.sc.DecompositionStaticChecker"
 +
              name="Decomposition Extractor of Static Checker">
 +
          <inputType
 +
                id="ch.ethz.eventb.decomposition.core.dcpFile">
 +
          </inputType>
 +
        </extractor>
 +
    </tool>
 +
  </extension>
  
You can now launch a Rodin product with our plug-ins imported and see the result:
+
We defined a static checking tool that will run for the defined input type (<tt>ch.ethz.eventb.decomposition.core.dcpFile</tt>). The class provided for extractors shall implement the <tt>org.rodinp.core.builder.IExtractor</tt> interface, while the class provided for tools themselves shall implement <tt>org.rodinp.core.builder.IAutomaticTool</tt>.
  
[[Image:Extend_Rodin_Tuto_1_8_Used_ExtensionsExtended_UI.png]]
+
The Rodin platform (see plug-in <tt>org.eventb.core</tt>) provides a static checking automatic tool for context/machine files.
  
Congratulations! You are now able to edit the elements you added in Rodin Database.
+
== Programmatic usage ==
 +
The class to be implemented usually extends the class <tt>org.eventb.core.sc.StaticChecker</tt>
 +
and needs to implement the abstract method <tt>extract</tt> from the interface <tt>org.rodinp.core.builder.IExtractor</tt>:
  
{{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)]]}}
+
    public void extract(IFile file, IGraph graph, IProgressMonitor monitor)throws CoreException {
 +
        try {
 +
              monitor.beginTask(Messages.bind(Messages.build_extracting, file.getName()), 1);
 +
              IRodinFile source = RodinCore.valueOf(file);
 +
              IDecompositionRoot root = (IDecompositionRoot) source.getRoot();
 +
              IRodinFile target = root.getSCDecompositionRoot().getRodinFile();
 +
              graph.addTarget(target.getResource());
 +
              graph.addToolDependency(source.getResource(), target.getResource(),true);
 +
            } finally {
 +
              monitor.done();
 +
            }
 +
    }
  
[[Category:Developer documentation|*Index]]
+
The interface <tt>org.rodinp.core.builder.IGraph</tt> is used by the extractors registered with the builder to manipulate the dependency graph of all Rodin resources of a Rodin project. It is a façade to the more complicated ways of manipulating the dependency graph inside the builder. Some information is cached in the corresponding object, so the contents of the façade must be synchronised with the graph at the end of an extraction. Requests to add nodes to the graph must be made explicitly by calls to the method <tt>addNode</tt>. Dependencies are managed by the façade. It saves clients to have to compute dependency graph deltas themselves.
[[Category:Rodin Platform|*Index]]
+
 
[[Category:Tutorial|*Index]]
+
We have already defined the static checking tool and the target for which it will run. Now, we need to configure the static checker tool. It is necessary to define the checks that are required for each element and this is done by providing an extension to <tt>org.eventb.core.configurations</tt>.
 +
 
 +
= Configuration =
 +
 
 +
The configuration is used to define which modules are used by the static checker. Similarly, it can be used for the proof obligation generator (POG).
 +
 
 +
== Declaration ==
 +
 
 +
<!ELEMENT configuration ((config | pogModule | scModule))+>
 +
  <!ATTLIST configuration
 +
  id  CDATA #REQUIRED
 +
  name CDATA #REQUIRED
 +
  >
 +
  id - the identifier for this attribute type (simple id token, unique for attribute types within the extension namespace). The token cannot contain dot (.) or whitespace.
 +
  name - the human-readable name of this attribute type
 +
 
 +
For static checks, we need <tt>scModule</tt> and <tt>config</tt> elements. Below we see on an example how to define the configuration:
 +
 
 +
<extension
 +
        point="org.eventb.core.configurations">
 +
      <configuration
 +
            id="dcmp"
 +
            name="Decomposition Configuration">
 +
        <config
 +
              id="ch.ethz.eventb.decomposition.core.dcmpBaseSC">
 +
        </config>
 +
      </configuration>
 +
      <configuration
 +
            id="dcmpSC"
 +
            name="Decomposition Static Checker Root Module">
 +
        <scModule
 +
              id="ch.ethz.eventb.decomposition.core.decompositionModule">
 +
        </scModule>
 +
      </configuration>
 +
      <configuration
 +
            id="dcmpBaseSC"
 +
            name="Decomposition Static Checker Base Module">
 +
        <config
 +
              id="ch.ethz.eventb.decomposition.core.dcmpSC">
 +
        </config>
 +
        <scModule
 +
              id="ch.ethz.eventb.decomposition.core.componentModule">
 +
        </scModule>
 +
        <scModule
 +
            id="ch.ethz.eventb.decomposition.core.decompositionConfigurationModule">
 +
        </scModule>
 +
        <scModule
 +
              id="ch.ethz.eventb.decomposition.core.subComponentModule">
 +
        </scModule>
 +
        <scModule
 +
              id="ch.ethz.eventb.decomposition.core.subComponentElementModule">
 +
        </scModule>
 +
      </configuration>
 +
  </extension>
 +
 
 +
We structure the configuration as follows (although it can be structured in a different way):
 +
 
 +
* "Decomposition Configuration" (id=dcmp) is defined by a base static checker module that contains the configuration element "Decomposition Static Checker Base Module" (see "config" markup, id=ch.ethz.eventb.decomposition.core.dcmpBaseSC). This configuration element is a reference to the respective configuration.
 +
* "Decomposition Static Checker Root Module" (id=dcmpSC) defines the initial module for decomposition (initialisation of the static checker) as the Root Module.
 +
* "Decomposition Static Checker Base Module" (id =dcmpBaseSC) defines all other modules, for each element in the decompositionFile:
 +
** <tt>ch.ethz.eventb.decomposition.core.componentModule</tt>
 +
** <tt>ch.ethz.eventb.decomposition.core.decompositionConfigurationModule</tt>
 +
** <tt>ch.ethz.eventb.decomposition.core.subComponentModule</tt>
 +
** <tt>ch.ethz.eventb.decomposition.core.subComponentElementModule</tt>
 +
 
 +
Here we are just defining the configuration of the modules. These modules shall be defined separately using the extension point <tt>org.eventb.core.scModuleTypes</tt>. These are used to process the necessary operations for each element inside a statically checked file.
 +
 
 +
== Programmatic usage ==
 +
The configuration is programmatically set with the <tt>org.eventb.core.IConfigurationElement.setConfiguration</tt> dedicated method.
 +
 
 +
= Modules =
 +
== Filter ==
 +
 
 +
Filters are used to validate inserted elements. After the successful validation of all elements, they can be processed and stored in the statically-checked file. In order to implement a filter, we use the following extension from the extension point <tt>org.eventb.core.scModuleTypes</tt>:
 +
 
 +
<!ELEMENT filterType (prereq)*>
 +
  <!ATTLIST filterType
 +
  id    CDATA #REQUIRED
 +
  name  CDATA #REQUIRED
 +
  parent CDATA #REQUIRED
 +
  class  CDATA #REQUIRED
 +
  >
 +
  id - the identifier for this filter type (simple id token, unique for (filter/processor/root) types within the extension namespace).
 +
  The token cannot contain dot (.) or whitespace.
 +
  name - the human-readable name of this filter module
 +
  parent - the optional parent (processor) module. Root modules must leave the attribute undefined. It is not allowed to choose a filter module as parent.
 +
  class - the fully-qualified name of a subclass of org.eventb.core.sc.SCFilterModule
 +
 
 +
For the filter type, the classes usually extend the abstract class <tt>org.eventb.core.sc.SCFilterModule</tt>. It also contains three methods:
 +
 
 +
* <tt>public abstract boolean accept(IRodinElement element, ISCStateRepository repository, IProgressMonitor monitor) throws CoreException;</tt>: it runs the static checker module. It returns whether the element should be accepted or not. If an error marker is associated with the element, the returned value should usually be <tt>false</tt>. Exceptions from this rule are possible, in particular if the element has been already marked with an error.
 +
 
 +
* <tt>public abstract void initModule(ISCStateRepository repository,IProgressMonitor monitor) throws CoreException;</tt>: Initialisation code for the module.
 +
 
 +
* <tt>public abstract void endModule(ISCStateRepository repository,IProgressMonitor monitor) throws CoreException;</tt>: Termination code for the module.
 +
 
 +
== Processor ==
 +
 
 +
Processors literally process the elements, storing them in the static checked file, running sub-processors and adding states to the repository if required. To implement a processor, it is required to use the following extension from the extension point <tt>org.eventb.core.scModuleTypes</tt>:
 +
 
 +
  <!ELEMENT processorType (prereq)*>
 +
  <!ATTLIST processorType
 +
  id    CDATA #REQUIRED
 +
  name  CDATA #REQUIRED
 +
  parent CDATA #REQUIRED
 +
  class  CDATA #REQUIRED
 +
  >
 +
  id - the identifier for this processor type (simple id token, unique for (filter/processor/root) types within the extension namespace).
 +
  The token cannot contain dot (.) or whitespace.
 +
  name - the human-readable name of this processor module
 +
  parent - the optional parent (processor) module. Root modules must leave the attribute undefined. It is not allowed to choose a filter module as parent.
 +
  class - the fully-qualified name of a subclass of <tt>org.eventb.core.sc.SCProcessorModule</tt>
 +
 
 +
The classes that implement the root type and processor type usually extend the abstract class <tt>org.eventb.core.sc.SCProcessorModule</tt>. They contain a constant called <tt>MODULE_TYPE</tt> that identifies the <tt>scModule</tt> element. An example is:
 +
 
 +
public static final IModuleType<DecompositionModule> MODULE_TYPE = SCCore.getModuleType(DecompositionCorePlugin.PLUGIN_ID + ".decompositionModule");
 +
 
 +
that identifies the decomposition root module. Moreover, this classes should implement the three methods that are defined in the interface <tt>org.eventb.internal.core.tool.types.ISCProcessorModule</tt>:
 +
 
 +
* <tt>public abstract void initModule(IRodinElement element,ISCStateRepository repository,IProgressMonitor monitor) throws CoreException</tt>: Initialisation code for the module. Used to initialise the global variables of the class.
 +
* <tt>public abstract void process(IRodinElement element,IInternalElement target, ISCStateRepository repository, IProgressMonitor monitor) throws CoreException</tt>: Runs the static checker module. It processes the element. The element itself has already been accepted. If this element has children, then the children modules should be called here (see for example <tt>ch.ethz.eventb.decomposition.core.sc.modules.DecompositionSubComponentModule</tt>).
 +
* <tt>public abstract void endModule(IRodinElement element,ISCStateRepository repository,IProgressMonitor monitor) throws CoreException</tt>: Termination code for the module. It is used to clean up memory (global variables) before finishing the module call.
 +
 
 +
== Root ==
 +
Similar to a processor, but applied to the root of the file. The extension that needs to be implemented is defined below:
 +
 
 +
<!ELEMENT rootType EMPTY>
 +
  <!ATTLIST rootType
 +
  id    CDATA #REQUIRED
 +
  name  CDATA #REQUIRED
 +
  input CDATA #REQUIRED
 +
  class CDATA #REQUIRED
 +
  >
 +
  id - the identifier for this root type (simple id token, unique for (filter/processor/root) types within the extension namespace). The token cannot contain dot (.) or whitespace.
 +
  name - the human-readable name of this root module
 +
  input - identifier of the input file element type for this root module.
 +
  class - the fully-qualified name of a subclass of org.eventb.core.sc.SCProcessorModule
 +
 
 +
== Sequencing ==
 +
 
 +
 
 +
=== Parent ===
 +
{{TODO}}
 +
 
 +
=== Prerequisite ===
 +
 
 +
Some static checks rely on already done static checks so they work as pre-requirements. For instance, if a concrete event is refined, it is necessary to know the abstract machine defined in the refine machine section. So the refine machine is a static check pre-requirement for the refinement an event. To implement a pre-requirement, it is necessary to use the following extension point:
 +
 
 +
<!ELEMENT prereq EMPTY>
 +
  <!ATTLIST prereq
 +
  id CDATA #REQUIRED
 +
  >
 +
  id - the full ids of all (filter and processor) modules that must be run before this module
 +
 
 +
== Example ==
 +
 
 +
An example of module declaration is given below:
 +
 
 +
  <extension
 +
          point="org.eventb.core.scModuleTypes">
 +
        <rootType
 +
              class="ch.ethz.eventb.decomposition.core.sc.modules.DecompositionModule"
 +
              id="decompositionModule"
 +
              input="ch.ethz.eventb.decomposition.core.dcpFile"
 +
              name="Decomposition SC Root Module">
 +
        </rootType>
 +
        <processorType
 +
              class="ch.ethz.eventb.decomposition.core.sc.modules.DecompositionComponentModule"
 +
              id="decompositionComponentModule"
 +
              name="Decomposition SC Component Module"
 +
              parent="ch.ethz.eventb.decomposition.core.decompositionModule">
 +
        </processorType>
 +
        .
 +
        .
 +
        .
 +
        <filterType
 +
              class="ch.ethz.eventb.decomposition.core.sc.modules.DecompositionSubComponentElementFilterModule"
 +
              id="decompositionSubComponentElementFilterModule"
 +
              name="Decomposition SC SubComponentElement Filter Module"
 +
              parent="ch.ethz.eventb.decomposition.core.decompositionCommitSubComponentElementModule">
 +
          <prereq
 +
                id="ch.ethz.eventb.decomposition.core.decompositionConfigurationModule">
 +
          </prereq>
 +
          <prereq
 +
                id="ch.ethz.eventb.decomposition.core.decompositionComponentModule">
 +
          </prereq>
 +
        </filterType>
 +
    </extension>
 +
 
 +
Below is an example of the call of the three processor/root methods in the class <tt>ch.ethz.eventb.decomposition.core.sc.modules.DecompositionModule</tt>:
 +
 
 +
        @Override
 +
        public void initModule(IRodinElement element,ISCStateRepository repository,  IProgressMonitor monitor) throws CoreException {
 +
                accuracyInfo = new DecompositionAccuracyInfo();
 +
                final IDecompositionLabelSymbolTable labelSymbolTable = new DecompositionLabelSymbolTable(LABEL_SYMTAB_SIZE);
 +
                repository.setState(labelSymbolTable);
 +
                repository.setState(accuracyInfo);
 +
                initProcessorModules(element, repository, monitor);
 +
        }
 +
 
 +
        public void process(IRodinElement element, IInternalElement target,ISCStateRepository repository, IProgressMonitor monitor)throws CoreException {
 +
                scRoot = (ISCDecompositionRoot) target;
 +
              processModules(element, target, repository, monitor);
 +
        }
 +
 +
        @Override
 +
        public void endModule(IRodinElement element,ISCStateRepository repository, IProgressMonitor monitor) throws CoreException {
 +
                scRoot.setAccuracy(accuracyInfo.isAccurate(), monitor);
 +
              endProcessorModules(element, repository, monitor);
 +
        }
 +
 +
Whenever a problem is encountered by the static checker, it is possible to raise a warning or an error, highlighting the associated element, using the method <tt>org.eventb.core.sc.SCModule#createProblemMarker</tt>. An example can be seen below:
 +
 
 +
        public void process(IRodinElement element, IInternalElement target,ISCStateRepository repository, IProgressMonitor monitor)throws CoreException {
 +
                monitor.subTask(Messages.bind(Messages.progress_DecompositionComponent));
 +
                IComponent[] decompositionComponents = decompositionFile.getDecompositionComponents();
 +
                if (decompositionComponents.length > 1) {
 +
                        for (int k = 1; k < decompositionComponents.length; k++) {
 +
                                createProblemMarker(decompositionComponents[k], DecompositionConfigurationAttributes.TARGET_ATTRIBUTE,
 +
                                                              DecompositionGraphProblem.TooManyComponentsError);
 +
                        }
 +
              }
 +
              ...
 +
              repository.setState(new ComponentMachineInfo(scComponentMachineRoot,component));
 +
              ...
 +
              monitor.worked(1);
 +
      }
 +
 
 +
In this particular case, if the number of <tt>IComponent</tT> elements is greater than 1, then an error is generated for the related <tt>IComponent</tt> element:
 +
 
 +
[[Image:More_than_one_component_error.png]]
 +
 
 +
=States=
 +
 
 +
The static check of the elements in a file are independent of each other (different and independent modules). Nevertheless, some information depends on other elements. For instance, for label elements, it is necessary to know which labels have been previously used before checking the elements. Since the elements checks are independent, the solution is to ‘share data‘ through states implemented using the extension point <tt>org.eventb.core.scStateTypes</tt>. They are used to dynamically store data that will be used by dependencies. The data are stored in the <tt>SCStateRepository</tt> base, which contains a key and respective contents.
 +
 
 +
==Declaration==
 +
 
 +
<!ELEMENT stateType EMPTY>
 +
  <!ATTLIST stateType
 +
  id    CDATA #REQUIRED
 +
  name  CDATA #REQUIRED
 +
  class CDATA #REQUIRED
 +
  >
 +
  id - the identifier for this attribute type (simple id token, unique for attribute types within the extension namespace). The token cannot contain dot (.) or whitespace.
 +
  name - the human-readable name of this attribute type
 +
  class - the fully-qualified name of a subclass of org.eventb.core.sc.state.ISCState
 +
 
 +
==Programmatic Usage==
 +
 
 +
To store data, we need to call the method
 +
 
 +
<tt>void setState(I state)</tt> [I extends IState]
 +
 
 +
defined in the interface <tt>org.eventb.core.tool.IStateRepository</tt> (See method <tt>initModule</tt> above).
 +
 
 +
To retrieve date, we call the method:
 +
 
 +
</tt>I getState(IStateType<? extends I> stateType) throws CoreException</tt>
 +
 
 +
In order to use the stored state, it is necessary to define the ‘key‘ in the extension point <tt>stateType</tt>.
 +
 
 +
==Example==
 +
 
 +
An example of usage can be seen below:
 +
 
 +
<extension
 +
          point="org.eventb.core.scStateTypes">
 +
        <stateType
 +
              class="ch.ethz.eventb.decomposition.core.sc.state.IDecompositionAccuracyInfo"
 +
              id="decompositionAccuracyInfo"
 +
              name="Decomposition Accuracy Info">
 +
        </stateType>
 +
        <stateType
 +
              class="ch.ethz.eventb.decomposition.core.sc.state.IDecompositionLabelSymbolTable"
 +
              id="decompositionLabelSymbolTable"
 +
              name="Decomposition Label-Symbol Table">
 +
        </stateType>
 +
        <stateType
 +
              class="ch.ethz.eventb.decomposition.core.sc.state.IComponentAccuracyInfo"
 +
              id="componentDecompositionInfo"
 +
              name="Decomposition Component Machine Information">
 +
        </stateType>
 +
        <stateType
 +
              class="ch.ethz.eventb.decomposition.core.sc.state.IDecompositionStyle"
 +
              id="style"
 +
              name="Decomposition Style">
 +
        </stateType>
 +
    </extension>
 +
 
 +
For instance, the last <tt>stateType</tt> element defined above is ''Decomposition Style''. It is required to check which kind of ''subComponentElements'' are expected:
 +
 
 +
* if ''style''= shared event => ''subComponentElement'' expected type is ''variables''.
 +
* if ''style''= shared variable => ''subComponentElement'' expected type is ''events''.
 +
 
 +
[[Category:Developer documentation]]
 +
[[Category:Work in progress]]

Revision as of 14:10, 25 August 2010

Introduction

The purpose of this page is to describe how to extend the static checker. It covers on the one hand, the definition of the extension, and on the other hand its implementation.

The useful extension points are listed below; they offer the possibility to contribute to the static checker:

  • org.rodinp.core.autoTools
  • org.eventb.core.configurations
  • org.rodinp.core.internalElementTypes
  • org.eventb.core.scModuleTypes
  • org.eventb.core.scStateTypes

Before Starting

It is necessary to define the static checked elements that are similar to the unchecked elements. We will use as an example the decompositionFile that is defined as follows:

  • decompositionFile
    • decompositionRoot
      • Component (machine to be decomposed)
      • Configuration (style: shared events/shared variables;newProjectOption: decompose in the same project/different projects;decomposeContextOption:no decomposition/minimal decomposition)
      • SubComponent (resulting decomposed parts)
        • SubComponentElement (elements used to decompose: variables for shared event decomposition and events for shared variable decomposition)

Decomp file pretty print.png

To extend the static checker, it is necessary to add a new content type (org.eclipse.core.contenttype.contentTypes) containing the checked version of the decompositionFile:

     <content-type
          base-type="org.rodinp.core.rodin"
          file-extensions="dcc,dcc_tmp"
          id="scDcpFile"
          name="Event-B Statically Checked Decomposition File"
          priority="normal">
    </content-type>

and the respective file association (org.rodinp.core.fileAssociations):

    <fileAssociation 
         content-type-id="ch.ethz.eventb.decomposition.core.scDcpFile" 
         root-element-type="ch.ethz.eventb.decomposition.core.scDcpFile">
   </fileAssociation>
     

The respective static checked elements must be added as internal elements using the extension org.rodinp.core.internalElementTypes:

<extension
       point="org.rodinp.core.internalElementTypes">
    <internalElementType
          class="ch.ethz.eventb.decomposition.core.basis.DecompositionRoot"
          id="dcpFile"
          name="%eventBdcpFile">
    </internalElementType>
    <internalElementType
          class="ch.ethz.eventb.decomposition.core.basis.SCDecompositionRoot"
          id="scDcpFile"
          name="Event-B Statically Checked Decomposition Root">
    </internalElementType>
    <internalElementType
          class="ch.ethz.eventb.decomposition.core.basis.DecompositionConfiguration"
          id="configuration"
          name="%eventBDecompositionConfiguration">
    </internalElementType>
    <internalElementType
          class="ch.ethz.eventb.decomposition.core.basis.SCDecompositionConfiguration"
          id="scConfiguration"
          name="Event-B Statically Checked Decomposition Configuration">
    </internalElementType>
</extension>

In the above example, the first internal element type is the unckecked internal element, and the second is the same internal element but in the checked version. Having the checked elements defined, we can start to extend the static checker for our files and respective elements.

AutoTools

The static checker it is a tool that runs automatically. In order to implement the tool, it is necessary to define the following extension point org.rodinp.core.autoTools. This extension point allows tools to run automatically when changes to the Rodin database are committed. To implement the reactive model of Rodin, automatic tools run only when one of their input files has changed. As such, for each automatic tool, plugin developers must provide two kinds of contributions:

  • Some dependency extractors.
  • The tool itself.

Declaration

The autoTools extension-point allows tool writers to register their tool implementation under a symbolic name that is then used by the Rodin platform to find and run the tool. The symbolic name is the id of the tool extension. An example of the implementation of a static checker can be seen as follows:

<extension
       point="org.rodinp.core.autoTools">
    <tool
          class="ch.ethz.eventb.decomposition.internal.core.sc.DecompositionStaticChecker"
          id="decompositionSC"
          name="Decomposition Static Checker">
       <extractor
             class="ch.ethz.eventb.decomposition.internal.core.sc.DecompositionStaticChecker"
             name="Decomposition Extractor of Static Checker">
          <inputType
                id="ch.ethz.eventb.decomposition.core.dcpFile">
          </inputType>
       </extractor>
    </tool>
 </extension>

We defined a static checking tool that will run for the defined input type (ch.ethz.eventb.decomposition.core.dcpFile). The class provided for extractors shall implement the org.rodinp.core.builder.IExtractor interface, while the class provided for tools themselves shall implement org.rodinp.core.builder.IAutomaticTool.

The Rodin platform (see plug-in org.eventb.core) provides a static checking automatic tool for context/machine files.

Programmatic usage

The class to be implemented usually extends the class org.eventb.core.sc.StaticChecker and needs to implement the abstract method extract from the interface org.rodinp.core.builder.IExtractor:

    public void extract(IFile file, IGraph graph, IProgressMonitor monitor)throws CoreException {
        try {
              monitor.beginTask(Messages.bind(Messages.build_extracting, file.getName()), 1);
              IRodinFile source = RodinCore.valueOf(file);
              IDecompositionRoot root = (IDecompositionRoot) source.getRoot();
              IRodinFile target = root.getSCDecompositionRoot().getRodinFile();
              graph.addTarget(target.getResource());
              graph.addToolDependency(source.getResource(), target.getResource(),true);
           } finally {
              monitor.done();
           }
    }

The interface org.rodinp.core.builder.IGraph is used by the extractors registered with the builder to manipulate the dependency graph of all Rodin resources of a Rodin project. It is a façade to the more complicated ways of manipulating the dependency graph inside the builder. Some information is cached in the corresponding object, so the contents of the façade must be synchronised with the graph at the end of an extraction. Requests to add nodes to the graph must be made explicitly by calls to the method addNode. Dependencies are managed by the façade. It saves clients to have to compute dependency graph deltas themselves.

We have already defined the static checking tool and the target for which it will run. Now, we need to configure the static checker tool. It is necessary to define the checks that are required for each element and this is done by providing an extension to org.eventb.core.configurations.

Configuration

The configuration is used to define which modules are used by the static checker. Similarly, it can be used for the proof obligation generator (POG).

Declaration

<!ELEMENT configuration ((config | pogModule | scModule))+>
 <!ATTLIST configuration
 id   CDATA #REQUIRED
 name CDATA #REQUIRED
 >
 id - the identifier for this attribute type (simple id token, unique for attribute types within the extension namespace). The token cannot contain dot (.) or whitespace.
 name - the human-readable name of this attribute type

For static checks, we need scModule and config elements. Below we see on an example how to define the configuration:

<extension
        point="org.eventb.core.configurations">
     <configuration
           id="dcmp"
           name="Decomposition Configuration">
        <config
              id="ch.ethz.eventb.decomposition.core.dcmpBaseSC">
        </config>
     </configuration>
     <configuration
           id="dcmpSC"
           name="Decomposition Static Checker Root Module">
        <scModule
              id="ch.ethz.eventb.decomposition.core.decompositionModule">
        </scModule>
     </configuration>
     <configuration
           id="dcmpBaseSC"
           name="Decomposition Static Checker Base Module">
        <config
              id="ch.ethz.eventb.decomposition.core.dcmpSC">
        </config>
        <scModule
              id="ch.ethz.eventb.decomposition.core.componentModule">
        </scModule>
        <scModule
           id="ch.ethz.eventb.decomposition.core.decompositionConfigurationModule">
        </scModule>
        <scModule
              id="ch.ethz.eventb.decomposition.core.subComponentModule">
        </scModule>
        <scModule
              id="ch.ethz.eventb.decomposition.core.subComponentElementModule">
        </scModule>
     </configuration>
  </extension>

We structure the configuration as follows (although it can be structured in a different way):

  • "Decomposition Configuration" (id=dcmp) is defined by a base static checker module that contains the configuration element "Decomposition Static Checker Base Module" (see "config" markup, id=ch.ethz.eventb.decomposition.core.dcmpBaseSC). This configuration element is a reference to the respective configuration.
  • "Decomposition Static Checker Root Module" (id=dcmpSC) defines the initial module for decomposition (initialisation of the static checker) as the Root Module.
  • "Decomposition Static Checker Base Module" (id =dcmpBaseSC) defines all other modules, for each element in the decompositionFile:
    • ch.ethz.eventb.decomposition.core.componentModule
    • ch.ethz.eventb.decomposition.core.decompositionConfigurationModule
    • ch.ethz.eventb.decomposition.core.subComponentModule
    • ch.ethz.eventb.decomposition.core.subComponentElementModule

Here we are just defining the configuration of the modules. These modules shall be defined separately using the extension point org.eventb.core.scModuleTypes. These are used to process the necessary operations for each element inside a statically checked file.

Programmatic usage

The configuration is programmatically set with the org.eventb.core.IConfigurationElement.setConfiguration dedicated method.

Modules

Filter

Filters are used to validate inserted elements. After the successful validation of all elements, they can be processed and stored in the statically-checked file. In order to implement a filter, we use the following extension from the extension point org.eventb.core.scModuleTypes:

<!ELEMENT filterType (prereq)*>
 <!ATTLIST filterType
 id     CDATA #REQUIRED
 name   CDATA #REQUIRED
 parent CDATA #REQUIRED
 class  CDATA #REQUIRED
 >
 id - the identifier for this filter type (simple id token, unique for (filter/processor/root) types within the extension namespace). 
 The token cannot contain dot (.) or whitespace.
 name - the human-readable name of this filter module
 parent - the optional parent (processor) module. Root modules must leave the attribute undefined. It is not allowed to choose a filter module as parent.
 class - the fully-qualified name of a subclass of org.eventb.core.sc.SCFilterModule

For the filter type, the classes usually extend the abstract class org.eventb.core.sc.SCFilterModule. It also contains three methods:

  • public abstract boolean accept(IRodinElement element, ISCStateRepository repository, IProgressMonitor monitor) throws CoreException;: it runs the static checker module. It returns whether the element should be accepted or not. If an error marker is associated with the element, the returned value should usually be false. Exceptions from this rule are possible, in particular if the element has been already marked with an error.
  • public abstract void initModule(ISCStateRepository repository,IProgressMonitor monitor) throws CoreException;: Initialisation code for the module.
  • public abstract void endModule(ISCStateRepository repository,IProgressMonitor monitor) throws CoreException;: Termination code for the module.

Processor

Processors literally process the elements, storing them in the static checked file, running sub-processors and adding states to the repository if required. To implement a processor, it is required to use the following extension from the extension point org.eventb.core.scModuleTypes:

 <!ELEMENT processorType (prereq)*>
 <!ATTLIST processorType
 id     CDATA #REQUIRED
 name   CDATA #REQUIRED
 parent CDATA #REQUIRED
 class  CDATA #REQUIRED
 >
 id - the identifier for this processor type (simple id token, unique for (filter/processor/root) types within the extension namespace). 
 The token cannot contain dot (.) or whitespace.
 name - the human-readable name of this processor module
 parent - the optional parent (processor) module. Root modules must leave the attribute undefined. It is not allowed to choose a filter module as parent.
 class - the fully-qualified name of a subclass of org.eventb.core.sc.SCProcessorModule

The classes that implement the root type and processor type usually extend the abstract class org.eventb.core.sc.SCProcessorModule. They contain a constant called MODULE_TYPE that identifies the scModule element. An example is:

public static final IModuleType<DecompositionModule> MODULE_TYPE = SCCore.getModuleType(DecompositionCorePlugin.PLUGIN_ID + ".decompositionModule");

that identifies the decomposition root module. Moreover, this classes should implement the three methods that are defined in the interface org.eventb.internal.core.tool.types.ISCProcessorModule:

  • public abstract void initModule(IRodinElement element,ISCStateRepository repository,IProgressMonitor monitor) throws CoreException: Initialisation code for the module. Used to initialise the global variables of the class.
  • public abstract void process(IRodinElement element,IInternalElement target, ISCStateRepository repository, IProgressMonitor monitor) throws CoreException: Runs the static checker module. It processes the element. The element itself has already been accepted. If this element has children, then the children modules should be called here (see for example ch.ethz.eventb.decomposition.core.sc.modules.DecompositionSubComponentModule).
  • public abstract void endModule(IRodinElement element,ISCStateRepository repository,IProgressMonitor monitor) throws CoreException: Termination code for the module. It is used to clean up memory (global variables) before finishing the module call.

Root

Similar to a processor, but applied to the root of the file. The extension that needs to be implemented is defined below:

<!ELEMENT rootType EMPTY>
 <!ATTLIST rootType
 id    CDATA #REQUIRED
 name  CDATA #REQUIRED
 input CDATA #REQUIRED
 class CDATA #REQUIRED
 >
 id - the identifier for this root type (simple id token, unique for (filter/processor/root) types within the extension namespace). The token cannot contain dot (.) or whitespace.
 name - the human-readable name of this root module
 input - identifier of the input file element type for this root module.
 class - the fully-qualified name of a subclass of org.eventb.core.sc.SCProcessorModule

Sequencing

Parent

TODO

Prerequisite

Some static checks rely on already done static checks so they work as pre-requirements. For instance, if a concrete event is refined, it is necessary to know the abstract machine defined in the refine machine section. So the refine machine is a static check pre-requirement for the refinement an event. To implement a pre-requirement, it is necessary to use the following extension point:

<!ELEMENT prereq EMPTY>
 <!ATTLIST prereq
 id CDATA #REQUIRED
 >
 id - the full ids of all (filter and processor) modules that must be run before this module

Example

An example of module declaration is given below:

 <extension
          point="org.eventb.core.scModuleTypes">
       <rootType
             class="ch.ethz.eventb.decomposition.core.sc.modules.DecompositionModule"
             id="decompositionModule"
             input="ch.ethz.eventb.decomposition.core.dcpFile"
             name="Decomposition SC Root Module">
       </rootType>
       <processorType
             class="ch.ethz.eventb.decomposition.core.sc.modules.DecompositionComponentModule"
             id="decompositionComponentModule"
             name="Decomposition SC Component Module"
             parent="ch.ethz.eventb.decomposition.core.decompositionModule">
       </processorType>
       .
       .
       .
       <filterType
             class="ch.ethz.eventb.decomposition.core.sc.modules.DecompositionSubComponentElementFilterModule"
             id="decompositionSubComponentElementFilterModule"
             name="Decomposition SC SubComponentElement Filter Module"
             parent="ch.ethz.eventb.decomposition.core.decompositionCommitSubComponentElementModule">
          <prereq
                id="ch.ethz.eventb.decomposition.core.decompositionConfigurationModule">
          </prereq>
          <prereq
                id="ch.ethz.eventb.decomposition.core.decompositionComponentModule">
          </prereq>
       </filterType>
    </extension>

Below is an example of the call of the three processor/root methods in the class ch.ethz.eventb.decomposition.core.sc.modules.DecompositionModule:

       @Override
       public void initModule(IRodinElement element,ISCStateRepository repository,  IProgressMonitor monitor) throws CoreException {
               accuracyInfo = new DecompositionAccuracyInfo();
               final IDecompositionLabelSymbolTable labelSymbolTable = new DecompositionLabelSymbolTable(LABEL_SYMTAB_SIZE);
               repository.setState(labelSymbolTable);
               repository.setState(accuracyInfo);
               initProcessorModules(element, repository, monitor);
       }
       public void process(IRodinElement element, IInternalElement target,ISCStateRepository repository, IProgressMonitor monitor)throws CoreException {
               scRoot = (ISCDecompositionRoot) target;
              processModules(element, target, repository, monitor);
       }
       @Override
       public void endModule(IRodinElement element,ISCStateRepository repository, IProgressMonitor monitor) throws CoreException {
               scRoot.setAccuracy(accuracyInfo.isAccurate(), monitor);
              endProcessorModules(element, repository, monitor);
       }

Whenever a problem is encountered by the static checker, it is possible to raise a warning or an error, highlighting the associated element, using the method org.eventb.core.sc.SCModule#createProblemMarker. An example can be seen below:

       public void process(IRodinElement element, IInternalElement target,ISCStateRepository repository, IProgressMonitor monitor)throws CoreException {
               monitor.subTask(Messages.bind(Messages.progress_DecompositionComponent));
               IComponent[] decompositionComponents = decompositionFile.getDecompositionComponents();
               if (decompositionComponents.length > 1) {
                       for (int k = 1; k < decompositionComponents.length; k++) {
                               createProblemMarker(decompositionComponents[k], DecompositionConfigurationAttributes.TARGET_ATTRIBUTE,
                                                             DecompositionGraphProblem.TooManyComponentsError);
                       }
              }
              ...
              repository.setState(new ComponentMachineInfo(scComponentMachineRoot,component));
              ...
             monitor.worked(1);
      }

In this particular case, if the number of IComponent elements is greater than 1, then an error is generated for the related IComponent element:

More than one component error.png

States

The static check of the elements in a file are independent of each other (different and independent modules). Nevertheless, some information depends on other elements. For instance, for label elements, it is necessary to know which labels have been previously used before checking the elements. Since the elements checks are independent, the solution is to ‘share data‘ through states implemented using the extension point org.eventb.core.scStateTypes. They are used to dynamically store data that will be used by dependencies. The data are stored in the SCStateRepository base, which contains a key and respective contents.

Declaration

<!ELEMENT stateType EMPTY>
 <!ATTLIST stateType
 id    CDATA #REQUIRED
 name  CDATA #REQUIRED
 class CDATA #REQUIRED
 >
 id - the identifier for this attribute type (simple id token, unique for attribute types within the extension namespace). The token cannot contain dot (.) or whitespace.
 name - the human-readable name of this attribute type
 class - the fully-qualified name of a subclass of org.eventb.core.sc.state.ISCState

Programmatic Usage

To store data, we need to call the method

void setState(I state) [I extends IState]

defined in the interface org.eventb.core.tool.IStateRepository (See method initModule above).

To retrieve date, we call the method:

I getState(IStateType<? extends I> stateType) throws CoreException

In order to use the stored state, it is necessary to define the ‘key‘ in the extension point stateType.

Example

An example of usage can be seen below:

<extension
          point="org.eventb.core.scStateTypes">
       <stateType
             class="ch.ethz.eventb.decomposition.core.sc.state.IDecompositionAccuracyInfo"
             id="decompositionAccuracyInfo"
             name="Decomposition Accuracy Info">
       </stateType>
       <stateType
             class="ch.ethz.eventb.decomposition.core.sc.state.IDecompositionLabelSymbolTable"
             id="decompositionLabelSymbolTable"
             name="Decomposition Label-Symbol Table">
       </stateType>
       <stateType
             class="ch.ethz.eventb.decomposition.core.sc.state.IComponentAccuracyInfo"
             id="componentDecompositionInfo"
             name="Decomposition Component Machine Information">
       </stateType>
       <stateType
             class="ch.ethz.eventb.decomposition.core.sc.state.IDecompositionStyle"
             id="style"
             name="Decomposition Style">
       </stateType>
   </extension>

For instance, the last stateType element defined above is Decomposition Style. It is required to check which kind of subComponentElements are expected:

  • if style= shared event => subComponentElement expected type is variables.
  • if style= shared variable => subComponentElement expected type is events.