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
}