Skip to main content

Visualisations

Providing a visual representation of decision logic is a core concern of Decisions4s. Below we present the available ways of generating such representation. The recommended starting point is the Shareable URL — it requires no hosting and renders directly in a browser.

Shareable URL

A DMNModel can produce a self-contained URL pointing at a hosted dmn-js viewer. The DMN XML is deflate-compressed and base64url-encoded into the URL fragment, so no server stores the content — anyone with the link sees the same diagram. The default viewer is hosted alongside this documentation at /dmn-viewer/; pass a different base URL to shareUrl(...) to point at a self-hosted instance.

"org.business4s" %% "decisions4s-dmn" % "0.2.1"
val shareUrl: String = DmnRenderer.render(decisionTable).shareUrl()
Example output
warning

URL length is bounded by what your channel of choice (chat client, email, browser address bar) accepts. Decision tables with dozens of rules or long expressions may exceed practical limits; fall back to hosting the diagram and linking to it in those cases.

Markdown

Markdown representation is provided out-of-the box in the core module.

import decisions4s.*

val decisionTable: DecisionTable[Input, Output, ?] = ???
val markdown: String = MarkdownRenderer.render(decisionTable)
Example output
(I) numOfApprovals(I) isTargetBranchProtected(I) authorIsAdmin(O) allowMerging(O) notifyUnusualAction
> 0false-truefalse
> 1true-truefalse
--truetruetrue
---falsefalse

HTML

A standalone HTML representation is also provided in the core module, which can be useful for sharing the decisions easily with other people in a quick and easy way. For sharing decisions in a systemic way we recommend either a custom renderer or DMN rendering through dmn-js, both described below.

import decisions4s.html.HtmlRenderer

val html: String = HtmlRenderer.render(decisionTable)
Example output (raw)
<!DOCTYPE html>
<html>
<head>
<style>
.decision-table {
font-family: Arial, sans-serif;
border-collapse: collapse;
width: auto;
margin: 20px 0;
}
.decision-table th, .decision-table td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
.decision-table th {
background-color: #f2f2f2;
}
.header-main {
text-align: center;
font-weight: bold;
}
.section-header {
background-color: #e0e0e0;
text-align: center;
font-weight: bold;
}
</style>
</head>
<body>

<table class="decision-table">
<thead>
<tr>
<th colspan="5" class="header-main">PullRequestDecision (Hit Policy: First)</th>
</tr>
<tr>
<th colspan="3" class="section-header">Inputs</th>
<th colspan="2" class="section-header">Outputs</th>

</tr>
<tr>
<th>numOfApprovals</th>
<th>isTargetBranchProtected</th>
<th>authorIsAdmin</th>
<th>allowMerging</th>
<th>notifyUnusualAction</th>

</tr>
</thead>
<tbody>
<tr><td>&gt; 0</td><td>false</td><td>-</td><td>true</td><td>false</td></tr>
<tr><td>&gt; 1</td><td>true</td><td>-</td><td>true</td><td>false</td></tr>
<tr><td>-</td><td>-</td><td>true</td><td>true</td><td>true</td></tr>
<tr><td>-</td><td>-</td><td>-</td><td>false</td><td>false</td></tr>
</tbody>
</table>

</body>
</html>
Example output (rendered)

Decision Model and Notation (DMN)

DMN model can be generated using the following dependency:

"org.business4s" %% "decisions4s-dmn" % "0.2.1"
import decisions4s.dmn.*

val dmnXml: String = DmnRenderer.render(decisionTable).toXML
Example output
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<definitions id="definitions" name="definitions" namespace="http://camunda.org/schema/1.0/dmn" xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/">
<decision id="decision_1" name="PullRequestDecision">
<decisionTable hitPolicy="FIRST" id="table_1">
<input id="input_0" label="numOfApprovals">
<inputExpression id="input_0_expr_1"/>
</input>
<input id="input_1" label="isTargetBranchProtected">
<inputExpression id="input_1_expr_1"/>
</input>
<input id="input_2" label="authorIsAdmin">
<inputExpression id="input_2_expr_1"/>
</input>
<output id="output_0" label="allowMerging"/>
<output id="output_1" label="notifyUnusualAction"/>
<rule id="rule_0">
<inputEntry id="rule_0_input_0">
<text>&gt; 0</text>
</inputEntry>
<inputEntry id="rule_0_input_1">
<text>false</text>
</inputEntry>
<inputEntry id="rule_0_input_2">
<text>-</text>
</inputEntry>
<outputEntry id="rule_0_output_0">
<text>true</text>
</outputEntry>
<outputEntry id="rule_0_output_1">
<text>false</text>
</outputEntry>
</rule>
<rule id="rule_1">
<inputEntry id="rule_1_input_0">
<text>&gt; 1</text>
</inputEntry>
<inputEntry id="rule_1_input_1">
<text>true</text>
</inputEntry>
<inputEntry id="rule_1_input_2">
<text>-</text>
</inputEntry>
<outputEntry id="rule_1_output_0">
<text>true</text>
</outputEntry>
<outputEntry id="rule_1_output_1">
<text>false</text>
</outputEntry>
</rule>
<rule id="rule_2">
<inputEntry id="rule_2_input_0">
<text>-</text>
</inputEntry>
<inputEntry id="rule_2_input_1">
<text>-</text>
</inputEntry>
<inputEntry id="rule_2_input_2">
<text>true</text>
</inputEntry>
<outputEntry id="rule_2_output_0">
<text>true</text>
</outputEntry>
<outputEntry id="rule_2_output_1">
<text>true</text>
</outputEntry>
</rule>
<rule id="rule_3">
<inputEntry id="rule_3_input_0">
<text>-</text>
</inputEntry>
<inputEntry id="rule_3_input_1">
<text>-</text>
</inputEntry>
<inputEntry id="rule_3_input_2">
<text>-</text>
</inputEntry>
<outputEntry id="rule_3_output_0">
<text>false</text>
</outputEntry>
<outputEntry id="rule_3_output_1">
<text>false</text>
</outputEntry>
</rule>
</decisionTable>
</decision>
</definitions>

DMN As Image

DMN is an XML file that is not human-friendly without a way to render it. Decisions4s comes with an additional utility that allows converting the DMN into an image through dmn-js library.

warning

Rendering the image involves running a web browser through Selenium and capturing screenshots from there. By default, the assumed browser is Chrome and so ChromeDriver needs to be installed.

This process is rather slow and not recommended for live server-side usage.

"org.business4s" %% "decisions4s-dmn-to-image" % "0.2.1"
import decisions4s.dmn.image.*

val converter = DmnToImageConverter()
converter.convertDiagram(dmnXml)
Example output

PullRequestDecision.png

Alternative Visualizations

It's possible to convert DecisionTables into other formats, e.g., csv file or alternative markdown representations. Users are encouraged to write their own representations using decisions4s.internal.RenderUtils.prepare that converts a decision table to a structured format ready for further customizations.