Skip to content

Applicability Gate

Some rules apply only to a subset of elements, and that subset is determined not by a simple field check but by a computed result — for example, a shared parameter that exists and has a value. The applicability gate is the pattern for keeping such elements out of the validator's scope.


The problem

A validator checks a field value. But if the field does not exist or the check does not apply, you do not want the element in the output at all. Including it would cause false positives.


The pattern

Compute a boolean field in the projection, then filter on it after the projection using [condition]:

$[type = "FamilyInstance"].(
  $applicable := $exists(values.mark) and values.mark != null;

  {
    "id": id,
    "name": name,
    "mark": values.mark,
    "checkApplicable": $applicable
  }
)[checkApplicable = true]

Only elements where checkApplicable = true appear in the output. Elements where the condition is false are silently dropped.

The validator then only sees elements that are in scope, so there is no risk of a false positive from an element that was never applicable.


With a shared parameter

Shared parameters have an exists and hasValue field. The gate keeps only elements where the parameter is present and filled:

$[type = "FamilySymbol"].(
  $sp := $getSharedParam($, "NLRS_C_kwaliteitsklasse_code");

  {
    "id": id,
    "name": name,
    "paramValue": $sp.valueAsString,
    "checkApplicable": $sp.exists and $sp.hasValue
  }
)[checkApplicable = true]

Inverting the gate — surface only the missing

To expose elements where the parameter is absent (for a "must exist" check), invert the condition:

$[type = "FamilyInstance"].(
  $applicable := $not($exists(values.mark));

  {
    "id": id,
    "name": name,
    "checkApplicable": $applicable
  }
)[checkApplicable = true]

This outputs only elements where mark is missing — the validator then simply checks that the output is empty.


Gate vs filter predicate

Both $[condition] and [condition] filter elements. The difference is when the condition is evaluated:

Filter predicate $[...] Applicability gate [...]
Position Before the projection After the projection
Reads computed fields? No — those don't exist yet Yes
Reads raw object fields? Yes Yes

Use a filter predicate when the condition depends only on raw data. Use the applicability gate when the condition depends on a computed field in the projection.


Common mistakes

  • Using the gate but forgetting to compute the field — if checkApplicable is missing from the projection, the [checkApplicable = true] filter drops everything
  • Placing the gate before the projection — the computed field does not exist yet at that point