OpenWGA 7.5 - OpenWGA Concepts and Features

Design and development » HDBModel framework » Relations in HDBModel » Defining a relation

Custom relation filtering

In frequent situations you may need to further narrow down the documents that make valid targets for relations. For example lets assume that the "bill" documents should only target "task" documents that are already marked as closed, which is accomplished by setting an boolean item "closed" to "true".

As HDBModel uses HQL queries in the background to retrieve relation targets it is only natural to specify additional restrictions like these as HQL filter condition:

content.items['closed'].boolean  = 1

You can add such an extra clause to a relation by specifying a <where> inside the <relation> tag:

<relation name="billedtasks" targetclass="task" group="true" baseclass="project">

  <where>content.items['closed'].boolean = 1</where>

</relation>

You could also specify a specific HQL order clause by adding an <order> tag:

<relation name="billedtasks" targetclass="task" group="true" baseclass="project">

  <where>content.items['closed'].boolean = 1</where>

  <order>content.lastmodified desc</order>

</relation>

You can even further customize your query by using tag <param>. It defines a query parameter whose value is calculated by an TMLScript expression. For example, you could retrieve a value from a different document which should be available to the query. The tag will inject the value as a query parameter, so you can use it in you <where> condition:

<relation name="billedtasks" targetclass="task" group="true" baseclass="project">

  <where>content.items['closed'].boolean = 1 AND content.author=:projectleader</where>

  <order>content.lastmodified desc</order>

  <param name="projectleader">context("relation:parent-project").projectleader</param>

</relation>

Central filter definition

Now imagine that you would need this exact filter condition for many relations, so it would be tedious and hardly maintainable to repeat it on each and every relation. So instead of defining filter conditions on the relation you could define a reusable filter right on your target class, "task" in this example. Do the definition using the <filter> tag directly inside its <content> tag. It may take the same tags for filtering as the <relation> tag:

<content contentclass="task">

  <filter name="closed">

    <where>content.items['closed'].boolean = 1</where>

    <order>content.lastmodified desc</order>

  </filter>

</content>

Then reference this filter from any relation that wants to restrict to this filter. Only the filters of your target class are valid:

<relation name="billedtasks" targetclass="task" filter="closed" group="true" baseclass="project"/>

You now may even further restrict your filtered relation by again specifying additional <where>s on your relation definition. For example we could do a more complex query to select only those tasks that no other bill already points to:

<relation name="billedtasks" targetclass="task" filter="closed" group="true" baseclass="project">

  <where>not content in (select rel.target from ContentRelation as rel where rel.parentcontent.contentclass='bill' and rel.group='billedtasks')</where>

</relation>