Some optional background
Dcafs is an ancient project (about 13 years old) that I keep working on from time to time. Recently, I decided to do a major rewrite, which accidently ended up moving towards a more reactive approach. The first core component to undergo a heavy revision is the TaskManager, where a task is a sequence of actions and checks.
This component adds the following functionality to dcafs.
- Inititate actions base on time (delay, interval, clock)
- Interacting with attached devices:
- From sending a fixed message on a set interval to request data
- Up to complete automation sequences spanning multiple devices and realtime data
These sequences were fairly straightforward in XML, as the code was flexible enough to handle the original use cases. However, after the rewrite, achieving 'readable' XML became a limiting factor.
Simple loops can be mimicked in XML but those need to be implemented. Loops in a diagram structure however, are inherent. The code remains the same, just need to beware of going infinite.

Something like this 'do x until y' aka retry logic, is still fairly straightforward. But problems arise if you want to go back or forward to a specific line/action. In XML this would involve splitting things up in smaller sections and giving those an id. Which in turn means having to scroll around the XML looking for the relevant node...
Imagine having to do this in XML (as user).

The primary reason for the project is that it seems like a fun challange, secondary was the added functionality. Potentially lowering the bar of entry to dcafs, is a nice bonus.
How draw.io will be used
Since there's no 'one style fits all' when it comes to diagrams, I wanted to keep it appearance-agnostic. As such, the only rule regarding visual aspects, is that every arrow must have a value (text displayed on it), which we'll call label from now on. This label is used to define the kind of relationship between the connected shapes.
The rest of the configuration is 'invisible', given it's done using shape properties (accessed by right clicking on a shape and selecting 'Edit data'). The mandatory property for any shape is dcafstype which defines what it should map to in code. Other required properties depend on this dcafstype.
Below is an example of two diagrams. Left and right result in the same logic, just different aesthetic. The bold text is just a suggestion, the flavor text underneath uses placeholders to show properties. It's those properties that actually define the logic.

From shape to DrawioCell: parsing draw.io xml
For those that want to read source instead: Drawio.java (do note it's a first version, might not be final) with XMLdigger.java being the helper class that reads the xml. Some explanation of how that digger is used can be found here.
Below is a snippet showing how the majority of a draw.io xml file looks. I won't go into detail explaining it... because I don't know given I only cared about the things I needed anyway.
<mxfile agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/26.2.15 Chrome/134.0.6998.205 Electron/35.2.1 Safari/537.36" host="Electron" version="26.2.15" pages="4">
<diagram id="IfgC_i9sJ90nQT9nQvYs" name="Basics">
<mxGraphModel arrows="1" connect="1" fold="1" grid="1" gridSize="10" guides="1" math="0" page="1" pageHeight="1169" pageScale="1" pageWidth="827" shadow="0" tooltips="1">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell edge="1" id="aRKCRy_f5RSsDbNbkwyN-4" parent="1" source="aRKCRy_f5RSsDbNbkwyN-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" target="aRKCRy_f5RSsDbNbkwyN-3" value="next">
<mxGeometry as="geometry" relative="1" />
</mxCell>
First pass
When a property is added to a shape, the mxCell get encapsulated in an object node.
<object dcafstype="writerblock" id="aRKCRy_f5RSsDbNbkwyN-1" label="label;Runs:<span...
Read more »