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
}