Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Triquetrum/Actor Oriented Classes

Implementing and using Actor Oriented Classes in Triquetrum

Ptolemy II [1] models define actor assemblies that can be executed in different Models of Computation.

Actors can be implemented in different ways. Most Ptolemy II actors are implemented in Java, but other languages like JavaScript, Python, C have also been used. A different approach is to implement actors as composites of contained actor assemblies, or as "submodels". These are called "Actor Oriented Classes" [2].

In Ptolemy II's Vergil model editor, existing AOC implementations can be handled in a similar way as "programmed" actors. Ptolemy II is able to load both Java-based actor classes and MoML-based AOCs from the classpath, show them in the actor palette/library, let users drag-n-drop them on a graphical model canvas, connect ports, configure parameters etc.

AOCs can also be created using Vergil and can then be shared between "consumer models", either via the concept of a "User library" or by adding them to the classpath (e.g. by adding them in the Ptolemy II build or by copying them on the root installation folder). There is no explicit tool support to share models between multiple users.

With issue #78, the goal is to implement support for AOCs in Triquetrum.

This requires some reflection on different levels :

  1. How can we create AOC models? E.g. first designing a plain model and then mark it somehow as a "reusable AOC"? Or should this be a specific wizard/workflow in the editor upfront?
  2. Where do we store AOCs so they can be used for designing and running "consumer models"? Linked to this, how can we share them easily between models and with other users?
  3. How to represent AOCs within parent/consumer models? Vergil shows a customizable actor icon and via an "Open actor" action the user can see the internal details of the AOC model in a separate editor window. In Graphiti it's not straightforward to navigate between diagrams/windows from a parent model. This is related to the tight integration between diagram editors and underlying EMF resources. So e.g. Kieler/ELK use another paradigm where they expand/collapse the contents of a submodel within the same diagram (minimizing the remainder of the surrounding model).
  4. Do we want to support the difference between AOC classes and instances, similarly to Ptolemy II? And if so, also subclassing and other advanced features related to using AOCs in Ptolemy II?

The work will be done in several steps :

  1. Add support for using existing AOCs in the Triquetrum editor. At this stage we depend on using Vergil to implement AOCs.
    1. include AOCs in the editor palette configuration
    2. define a common approach for storing/loading AOC classes for the editor and for a headless workflow runtime
    3. always use AOC instances in our models, we will not be storing AOC class definitions inside models.
    4. simple representation of an AOC in a model with similar configuration options as for a Java-based actor
    5. figure out a way to dynamically add AOCs to an existing Triquetrum installation
    6. extend this to allow opening the AOC model details in a readonly view
  2. Add support for creating AOC models in Triquetrum
    1. graphical models and DSLs?
    2. AOCs defined within a parent model or only as separate models, meant to be used as "reusable submodels"?
    3. classes, subclasses, instances?

Using existing AOCs in Triquetrum

Ptolemy II's Sinewave actor is a typical AOC to try things out. It can be found as a SequenceSource in Vergil's editor palette. When connecting it to a SequencePlotter it generates a nice sine wave.

Pt Sinewave.JPG

Sinewave is implemented as an AOC, and its internal model can be viewed in Vergil :

Pt Sinewave internal.JPG

Using an ActorOrientedClassProvider

Standard Ptolemy II loads Java and AOC actor classes from its classpath. In a managed modular environment such as OSGi (and thus Triquetrum) this is less desirable as an approach. To prepare for Triquetrum (or other OSGi-based runtimes) Ptolemy II has been adapted to provide an API and implementation to load AOCs (and Java actor classes) using different strategies.

By plugging in org.ptolemy.classloading.osgi.OSGiClassLoadingStrategy as the implementation of org.ptolemy.classloading.ClassLoadingStrategy, Ptolemy becomes capable of exploiting OSGi services and all their interesting features for modularity and dynamic extensions.

Both Ptolemy II's own ptolemy.moml.MoMLParser and Triquetrum's editor use the ClassLoadingStrategy approach to find actor classes.

The OSGiClassLoadingStrategy implementation tracks all registered OSGi services that implement one of two interfaces :

  • org.ptolemy.classloading.ModelElementClassProvider : provides Java actor classes from OSGi bundles. Implementations are already available and used for providing the default actor library and to allow easy addition of new actors to a Triquetrum editor/runtime (see also https://wiki.eclipse.org/Triquetrum/Extending_Triquetrum)
  • org.ptolemy.classloading.ActorOrientedClassProvider : no implementation yet. This needs to be done to get a first level of AOC support working in Triquetrum.

So a first step for supporting AOCs in Triquetrum involves :

  • implementing an ActorOrientedClassProvider that is capable of loading existing AOC implementations
  • making these AOCs available to the Triquetrum editor via the palette configuration
  • ensuring that a model designer can use AOCs in the same way as Java-based actors
  • ensuring that such models also execute correctly

Loading AOCs from a filesystem

Our first AOCProvider implementation is based on finding AOCs via the WorkflowRepositoryService. We'll integrate o.e.t.workflow.repository.impl.filesystem.WorkflowRepositoryServiceImpl, which is a simple implementation that uses the local filesystem to store/load models for trying out AOC support. The AOCProvider implementation can be found in o.e.t.workflow.aoc.repository.AocProviderFromRepository.

Integrating this file-based repository in the editor is a good trigger to provide a first preferences page, to be able to configure the root folder of the repository (cfr issue #183).
We've followed the approach described by Philip Wenig on the OpenChrom blog (thanks!) to work with preferences in a consistent manner [3].

Adding AOCs in the editor palette

Now that we can load AOCs, we can also add them to the editor palette. E.g to add the Sinewave actor :

<entry
 class="ptolemy.actor.lib.Sinewave" (1)
 displayName="Sinewave"
 icon="icons/SinewaveIcon.xml" (2)
 iconType="ptolemy"
 type="CompositeActor"> (3)
</entry>

(1) : the fully qualified class will be passed to the repository service, and that one should be able to load the AOC class definition XML file based on that.

(2) : AOC actors can also get custom icons, e.g. based on Ptolemy II's icon definitions as in this case. Icon files should be added in the palette configuration bundle as well (cfr https://wiki.eclipse.org/Triquetrum/Extending_Triquetrum#Defining_the_palette_entry).

(3) : AOCs are CompositeActors, it's important to set this as correct entry type.

Another option is to implement a User Library concept in the palette, similar to what Ptolemy II's Vergil has. See below for more details on that.

Configuring an AOC in a model

The Sinewave actor can be configured in exactly the same way as a standard Java-based actor. But now you see the AOC "model" parameters only, not each individual parameter of each contained atomic actor (see the internal view on the Sinewave model, above).

Triq Sinewave1.JPG

Running a model with an AOC

When running this model, it behaves similarly as the Ptolemy II implementation :

Triq Sinewave2.JPG

Using a repository to maintain AOCs

The WorkflowRepositoryService API of Triquetrum can be used to store/load workflow models, to manage and activate model versions etc. It provides an abstraction on the actual physical storage of Triquetrum/Ptolemy II models. Depending on the implementation, this API can be used in a personal or in a team-oriented context for the Triquetrum RCP editor, or even to share models between designer tools and runtime servers.

In its current state, Triquetrum uses standard Eclipse projects to create and maintain workflow models with its editor (or to run them from inside the RCP application). But the repository API is a good option for handling Actor Oriented Classes in an OSGi-based environment, as opposed to looking for files on the classpath as is done in standard Ptolemy II.

So we'll be implementing an integration of the repository API with the RCP editor in the context of our work on AOCs, with following features:

  • consulting available AOC models and their versions
  • activating a desired version of a given model. The active version determines what is effectively used when adding the AOC to a model, or when running the model.
  • storing new/updated AOC models
  • deleting models

Setting up the repository with the Sinewave AOC

To play around with the Sinewave AOC as describe above, you need to setup a workflow repository on your local filesystem.

To get started, File:Workflow-repository.zip is a zipped repository containing only the Sinewave actor. Unzip it to some location on your disk and then configure this location in the Triquetrum preferences :

Triq reposvc prefs.JPG

After that, you will be able to use the Sinewave actor from the palette in Triquetrum.

Using the repository view

Triquetrum has a new "Workflow Repositories" view that shows all registered repositories and their contents.

It currently has following simple features:

  • the currently active version of a model is marked in bold.
  • a selected version can be activated via an action in the context menu.
WorkflowRepositoriesView.JPG

And also following features :

  • storing new/updated AOC models
  • deleting models

Implementing Ptolemy II's User Library in Triquetrum

Vergil provides a special folder in its palette, called a User Library. A user can add/remove/organize entries there from inside the editor, instead of having to edit XML files that define palette contents and then rebuilding Vergil.

We would like to use this mechanism to allow a user to add/remove AOCs to the palette, from the ones available in the workflow repositories. With this in place, we would have a first phase of support for dynamically adding (existing) AOCs to a Triquetrum RCP editor :

  • AOCs can be added to the repository
  • they can be added to the palette in two ways, similarly as with Ptolemy II's Vergil: in the User Library, without needing to rebuild the Triquetrum package ; or as palette contributions via extension points in plugin.xmls if a rebuild is acceptable/desired.

To store the contents of the user library, we would like to be able to reuse the UserLibrary.xml files that Ptolemy/Vergil use. They would be stored in "~/.triquetrum"

Reading a UserLibrary.xml file

When Triquetrum starts up, we must be able to read&parse the UserLibrary.xml file. We try to do this as follows :

File userHome = new File(System.getProperty("user.home"));
File triqUserHome = new File(userHome, ".triquetrum");

EntityLibrary userLibrary = new EntityLibrary();
userLibrary.setName("User Library");
userLibrary.configure(null, new File(triqUserHome, "UserLibrary.xml").toURI().toString(), null);
userLibrary.populate();

Strangely, the resulting userLibrary is empty??? This might be related to the fact that the file contains a class as root element and not an entity?

<class name="UserLibrary" extends="ptolemy.moml.EntityLibrary">
  <configure>
    <group>
         ...
    </group>
  </configure>
</class>

When I change this to the following, just to see what's changing in the parsing logic :

<entity name="UserLibrary" class="ptolemy.moml.EntityLibrary">
...
</entity>

something more happens, but the result is that the library contains 1 entity, called "UserLibrary" again. And that one has no parsed entities yet, but only its _configureText property filled in from the contents of the group element in the xml file...

So we need to figure out how we can load the UserLibrary.xml in the right way, outside of Vergil. Seems to be something else than straightforward pointing to the file and then calling EntityLibrary.populate()...

References

[1] http://ptolemy.eecs.berkeley.edu/ptolemyII/

[2] http://ptolemy.eecs.berkeley.edu/publications/papers/04/Classes/Lee_Classes.pdf

[3] https://openchrom.wordpress.com/2014/01/11/how-to-handle-preferences-consistently/

Back to the top