Behaviours
Metadata in the Haplo object store uses links to other objects wherever possible. Instead of using text fields, or numbers representing various options, in Haplo, you’ll create ‘concept’ objects which represent each choice, then link to them in other objects.
This does mean you need to know the Ref
of objects which represent things which are important to your plugin. For example, if you use objects to represent the state of a project, you need to be able to compare those states in your plugin.
The platform solves this in a similar way to schema API codes. Objects optionally have a configuration name text value in the ‘configured behaviour’ attribute, and this is used to look up the Ref
of these concept objects. If you follow the recommended approach of using schema requirements to create objects, the configured behaviours will be the codes from your requirements.schema
file.
You should use the same style of names as API codes, including namespacing, when defining behaviour names.
Object hierarchy
The behaviour of a given Ref
is always the behaviour of the root object. If the object has a parent link, those parent links are recursively followed until the root object is found, then the configured behaviour of the root object is returned.
This allows lists to be customised in an installation. Your basic list of objects will contain all the items you care about, but the installation can be configured with additional items in this list. As long as all those additional items have a parent with an expected configured behaviour, looking up the behaviour of any item will yield an behaviour your plugin understands.
Where you want to create a hierarchy yourself, the O.behaviourRef()
function will find the exact object with the given behaviour, even if it is a child object.
Interface
Ref objects
Ref
objects have a behaviour
property
function O.behaviourRef(behaviour)
Given a behaviour as a String
, return the Ref
of the object with the given behaviour in the ‘configured behaviour’ attribute.
Throws an exception if there is no object with this behaviour.
function O.behaviourRefMaybe(behaviour)
As O.behaviourRef()
, but returns null
instead of throwing an exception when there is no object with this behaviour.
Security enforcement
The current user’s permissions are not enforced when reading the object store to determine the behaviour of a Ref
, or to look up the Ref
given a behaviour.
This ensures that consistent values are returned throughout your plugin code. In general this isn’t a worry, as objects with behaviours tend to be classification objects that are readable by all users.
Example
Your requirements.schema
might contain a list, with a type and objects, like this:
# SCHEMA DEFINITIONS type example:type:project-status as ProjectStatus title: Project status search-name: Project status behaviour classification attribute dc:attribute:title [sort=1000] attribute std:attribute:configured-behaviour [sort=1200] attribute std:attribute:parent [sort=1500] attribute std:attribute:notes [sort=1500] label-base std:label:concept attribute example:attribute:project-status as ProjectStatus title: Project status search-name: project-status qualifier std:qualifier:null data-type link ui-options dropdown linked-type example:type:project-status # LIST MEMBERS object example:list:status:active type example:type:doctoral-research-project-status title: Active object example:list:status:complete type example:type:doctoral-research-project-status title: Completed
In your code, you might create an active project like this:
var project = O.object(); project.appendType(T.ProjectStatus); project.appendTitle("Example project"); project.append( O.behaviourRef('example:list:status:active'), A.ProjectStatus);
which creates a link to the Active object created by your requirements.schema
file.
To test project status, you might write code like:
var project = ... // obtain project from somewhere var status = project.first(A.ProjectStatus); if(status && status.behaviour === 'example:list:status:active') { // project is active }