Workspace 6.21.5
Writing a Workspace Polymorphic Data Operation

Introduction

In this tutorial, we will learn how to write a Workspace polymorphic data operation, and add it to our simple plugin that we created in one of the previous tutorials, Writing a Simple Workspace Plugin. By the end of this tutorial, you will:

  • Know how to use the built-in code wizard to create a Workspace polymorphic data operation
  • Understand the code behind a Workspace polymorphic data operation
  • Have added your new operation to a workflow

Contents


Sample files used and modified in this tutorial


Create "Circle" and "Square" data types

  • In Writing a Workspace Datatype, we generated a custom data type - Rectangle.
  • To demonstrate writing a polymorphic data operation, we will need some additional data types to work with.
  • Follow the steps in Writing a Workspace Datatype to create two additional custom data types - Circle and Square.
  • The screenshots shown below only show the wizard screens that are different to the previous Rectangle example. Please follow all the other steps from the Rectangle example and make sure you rebuild the solution.
  1. "Circle" data type -
    Create Circle data type
Circle has a single data member called Radius of type double
  1. "Square" data type -
    Create Square data type
Square has a single data member called Length of type double
  • Rebuild the solution.
  • Test by launching the Workspace editor and dragging a 'Variable' on to the canvas. If the data types were created correctly, then 'Circle' and 'Square' should appear in the drop-down list.
    Variable
    Variable can be set to the 'Circle' data type
    Variable can be set to the 'Square' data type

Using the "Create polymorphic data operation" code wizard

In one of the previous tutorials, we used the Workspace code wizard to generate the code for a simple Workspace operation. In this tutorial, we're going to use the Create Workspace Polymorphic Data Operation wizard to add a Polymorphic Data Operation to our simple plugin. Specifically, we're going to create an operation that calculates the area of a given shape (Circle or Rectangle or Square).

To start the wizard:

  1. Navigate to the Development menu and select Advanced and then select Create polymorphic data operation...
    Finding the code wizard
  2. A window will be displayed that looks like this:
    The create polymorphic data operation wizard

We can use this code wizard to generate the skeleton code required for a Workspace polymorphic data operation. Let's start by filling out the fields on the form:

  • Directory: The directory in which our operation source files will be created. Point this to the same location that your plugin source is located.
  • Operation class name: The C++ class name for our new operation. We will call ours "CalculateShapeArea", normally most operation names start with a verb and do not contain any spaces.
  • Namespace(s): The namespace used for the class. We will use CSIRO as we did in the previous tutorial.
  • Default label: The label that will be displayed on instances of the operation when they are added to a workflow. We will set ours to Calculate shape area
  • Catalogue path: The path in the Operation Catalogue that contains the operation. We will put ours in a folder called Simple plugin
  • Plugin class name: The fully-scoped name of the plugin class that will contain this operation. We're going to use the plugin we created previously, CSIRO::SimplePlugin.
  • Plugin header: The header that contains the definition of the containing Workspace plugin. Again, we refer to the file we generated in the previous tutorial: simpleplugin.h
Note
At any time you can check the purpose of these fields by hovering over them with the mouse and reading the tooltips (as shown above).

Our form will now look something like this:

Our values entered into the wizard

If we now look at the bottom of the plugin wizard, we will see some derived values. Workspace is showing us the name of the scoped class name of the new operation, as well as the scoped class name of the plugin that it is going to add it to. Next:

  • Click the Continue or Next button

The wizard will now show a screen for creating our operation's non-polymorphic inputs and outputs.

In this example, we are going to calculate an area of a given shape. Regardless of whether we are calculating the area of a circle, rectangle or square, the output is a double. So let's create an output of type double:

  1. Click the plus button once. This will create one row in the table, of type 'Scalar input'
  2. Change the Type of the row to "Output"
  3. Change the Visible name to "Area". The visible name is the name that users will see on the Workspace canvas when users are looking at the inputs / outputs of our operation.
  4. Change the Variable name to "area". The variable name is the name that is used to represent the input and its data in the C++ code.
  5. Change the Data type to 'double'. The form should now look like this:
    The non-polymorphic inputs / outputs screen populated
  6. Click Continue or Next

The wizard will now show a screen for creating our operation's polymorphic input, output or input and output. The operation is allowed to have only one polymorphic input/output of type "Scalar input", "Array input", "Output", "Scalar input and output" or "Array input and output".

In this example, the input to the operation is polymorphic and can be a Circle, Rectangle or Square. So let's create the polymorphic input:

  1. The table already has a row displayed with type 'Scalar input' and a list of allowed data types.
  2. Change the Visible name to "Shape". The visible name is the name that users will see on the Workspace canvas when users are looking at the inputs / outputs of our operation.
  3. Change the Variable name to "shape". The variable name is the name that is used to represent the input and its data in the C++ code.
  4. Leave the "Allow all data types" checkbox unchecked as we are going to restrict the input types to Circle, Rectangle and Square.
  5. In the Allowed data types list, select Circle, Rectangle and Square. You will need to hold down the CTRL key to select multiple rows in the list.
  6. The form should now look like this:
    The polymorphic inputs / outputs screen populated and showing Circle selected
    The polymorphic inputs / outputs screen populated and showing Rectangle selected
    The polymorphic inputs / outputs screen populated and showing Square selected
Note
The 'Allowed data types' list must have three selections - Circle, Rectangle and Square.
  1. Click Continue or Next

As we did with the plugin wizard, we now get to select a copyright notice.

Select none for this tutorial
  • Click Generate
Create operation finished

Workspace will now generate the code for our new operation and place it in the directory that we selected earlier (the same directory into which we generated our plugin). If you navigate to this directory, you'll see that it has the following contents:

The contents of the plugin directory after generating the operation

For more details about the code generated, see Writing a Workspace Polymorphic Data Operation - looking at the code or click on one of the links to individual files below.

The new files added are:

  • calculateshapearea.h This file is the C++ header for the new operation we created. It contains the class declaration for the operation as well as a few other things.
  • calculateshapearea.cpp This file is the C++ source for the new operation we created. It contains the class definition for the operation.

The existing files modified are: simpleplugin.cpp and CMakeLists.txt

Note
Although new files for the custom data types Circle and Square are also added we do not discuss them in this tutorial.

Creating and running a simple test workflow

Now you should:

  • quit the Workspace editor,
  • recompile the Simple plug-in (see the steps in the last tutorial) and
  • restart the Workspace editor.

Again the plug-in should automatically load and now the operation should be in the Operation catalogue.

  • As an exercise for the reader, you could now create a simple "workflow" and execute it to see how your operation works.
Running a simple workflow with your Operation to calculate area of a Circle
  • Stop the workflow.
  • Change the operation's data type to 'Square'
Change data type to 'Square'
  • Set a sensible value for the length of a side and run the workflow again.
Area of a Square data type

Summary

This tutorial has introduced you to the essential elements of adding a new polymorphic data operation to your Workspace plugin. The main points to remember are the following:

  • Workspace polymorphic data operations are always a subclass of Operation . The subclass constructor tells the base class what factory to use and what default label to give to new instances of the operation.
  • Data objects in Workspace are usually instances of SimpleInput<X> or SimpleInputArray<X> or SimpleOutput<X> where X is the underlying class of the object.
  • Inputs (InputScalar and InputArray) and Outputs wrap DataObjects, giving them a name and making them available to Workspace to use.
  • Only one data object - input, otuput or input and output is allowed to be polymorphic in nature.
  • The heart of a Workspace operation is its execute() function. Any inputs or outputs added to your operation will already have valid data when execute() is called, so all you need to do is use the data objects you defined for the inputs and outputs as though they were pointers and return a true or false value when you are done to indicate whether the call to execute() succeeded or failed.