Entities

When a workflow is associated with a StoreObject, the Entities system allows you easy access to the metadata.

Using Entities

First, you configure named entities. Then after they’re configured, you access entities through the M.entities property on your workflow instance.

This object has properties named after the entities you’ve defined. For example, if the process is associated with a project, you might obtain the project object with M.entities.project.

The entities system can traverse the object graph. If the project has supervisors, then M.entities.supervisor_list would be an array containing all the objects representing the supervisors.

Each named entity defines several properties on the M.entities object with a suffix to determine whether you want StoreObjects or Refs, whether you want a list of all of them or just the first, and whether an absent object is an error.

Suffix Value Required
(no suffix) The first attribute value as a StoreObject Yes
_maybe The first attribute value as a StoreObject or undefined No
_ref The first attribute value as a Ref Yes
_refMaybe The first attribute value as a Ref or undefined No
_list An array of zero or more attribute values as StoreObjects No
_refList An array of zero or more attribute values as Refs No

Where a suffix has a Yes in the Required column, it will throw an exception if that entity does not exist.

Configuring Entities

use() the std:entities feature, passing in a dictionary of entity names to definitions.

A definition is an array containing:

  • Source entity name (or "object" for the object associated with the workflow)
  • Attribute descriptor
  • Optional Qualifier

For example:

EgWorkflow.use("std:entities", {
    "project": ["object", A.Project],
    "supervisor": ["project", A.Supervisor],
    "leadSupervisor": ["project", A.Supervisor, Q.Lead]
});

std:entities can only be used once. Use std:entities:add_entities to add additional entities.

Entity roles

After you’ve defined your entities, you’ll probably want to use the std:entities:roles feature too. This allows you to use role names as actionableBy in state definitions.

EgWorkflow.use("std:entities:roles");

// And then use roles in states
EgWorkflow.states({
    "example": {
        actionableBy: "supervisor",
        // ...
    },
    // ...
});

Users are associated with entities when their ref property matches that entity.

Where roles are defined through entities, if the underlying object changes (for example, a new lead supervisor is appointed), then any processes actionable by the old user will be moved to the new user.

Tagging WorkUnits with entities

You can automatically apply WorkUnit tags from entities with the std:entities:tags feature. The arguments are entity names or arrays of entity names. For example:

EgWorkflow.use("std:entities:tags", "project", "supervisor");

will tag by project and supervisor, which can then be used in WorkUnit queries to locate all instances applicable to that project or supervisor.

Be wary of multi-values. If there is more than one entity in the list, the first one will be used for the tag.

Adding more entities

To avoid potential errors, std:entities can only be used once. You must use std:entities:add_entities to explicitly add more entities.

EgWorkflow.use("std:entities:add_entities", {
    "advocate": ["project", A.Advocate]
});

This is mainly intended for use by other features, and your plugin should define all entities in one place.

Defining entities by function

Sometimes the logic to find an entity depends on things which can’t be expressed with simple attributes and qualifiers. You can use a function instead, which must return an array of Refs. The return value will be de-duplicated with O.deduplicateArrayOfRefs().

this is the entities object. Access to the workflow instance is available via the this.M, but it won’t be available when there is no workflow context e.g. with P.workflow.standaloneEntities(), so use with caution.

For example:

EgWorkflow.use("std:entities", {
    "project": ["object", A.Project],
    "supervisor": ["project", A.Supervisor],
    "examiner": ["project", A.Supervisor, Q.Examiner],
    "responsibleStaff": function() {
        return [
          this.examiner_refMaybe || this.supervisor_refMaybe,
          this.facultyApprover_refMaybe
        ];
    }
});

For compatibility with legacy code, this function will always be called with a single argument, "list".

Text system helpers

When using std:entities, entities that you define become available in the workflow text system. Simply use the entity name enclosed in @ symbols, and upon rendering the title of the object that the entity references will be displayed instead

For example, to display the name of the entity supervisor in a transition name:

EgWorkflow.text({
    // ...
    "transition:return_supervisor": "Return to @supervisor@"
    // ...
});