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@" // ... });