Component interface
After selecting the component type, we design the external interface of a component. The interface is the visible part of a component, whereas the implementation is hidden. The interface also hides the type of the component (atomic or composite) and the implementation language of atomic components.
The interface consists of the following elements:
- Input ports: Files that are read by the component
- Output ports: Files that are written by the component
- Parameters: Simple input values (strings, numbers or Booleans)
The interface is specified using an XML file named component.xml
in the component folder. There is a template XML file under doc/templates/components/component.xml
and the XML format is also formally specified using XML Schema under core/src/main/resources/component.xsd
.
Example interface
Continuing to specify the CSV filter component for the demo
bundle, here is its interface as an XML file. The file is located in ~/my-bundles/demo/components/SimpleCSVFilter/component.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<component>
<name>SimpleCSVFilter</name>
<version>1.0</version>
<doc>
Filter columns from CSV file by name using inclusion or exclusion.
</doc>
<author email="author.email@example.com">Author Name</author>
<launcher type="R">
<argument name="file" value="SimpleCSVFilter.r" />
</launcher>
<requires URL="http://www.r-project.org/" type="manual">R</requires>
<inputs>
<input name="in" type="CSV">
<doc>Input CSV file.</doc>
</input>
<input name="columnNames" type="IDList" optional="true">
<doc>Column names to be included / excluded.</doc>
</input>
</inputs>
<outputs>
<output name="out" type="CSV">
<doc>Filtered CSV file.</doc>
</output>
</outputs>
<parameters>
<parameter name="include" type="boolean" default="true">
<doc>
If true, the output contains only columns that are present in columnNames.
If false, the output contains only columns that are not present in columnNames.
</doc>
</parameter>
</parameters>
</component>
Basic metadata
The name (SimpleCSVFilter
) is used in Scala workflow code, so it should be recognizable and unique. Version number is used for dependency tracking; if you increase the version to 1.1, workflows using this component are subject to re-execution.
Launcher
We chose to use R to implement our component, and we specify this in the <launcher>
section. It indicates that Anduril should use R facilities (specifically, Rscript
) to execute this component. The file
argument is the source file.
For implementing components in other languages, all supported launchers are:
Launcher | Arguments |
---|---|
bash | file, source |
java | class, extraClasspath, source |
lua | file, source |
matlab | file, source |
octave | file, source |
python | file, source |
r | file, source |
scala | class, extraClasspath, source |
The source
argument is an additional source file for including in the component documentation. For Java and Scala components, the entry point is specified using class
(a fully qualified JVM class name).
Inputs, outputs and parameters
The <inputs>
, <outputs>
and <parameters>
sections define the external interface. Port types refer to types declared in datatypes.xml
files, either the current bundle or dependency bundles. Array ports are specified by adding the attribute array="true"
. Input ports can be optional, marked by optional="true"
. We chose the make the columnNames
port of CSVFilter
optional so that the component passes CSV files through unfiltered if the second input is missing.
Parameters can have default values, in which case specified them in the workflow is not mandatory. If the default is omitted, it must be provided in the workflow. Parameter types are as follows:
Parameter type | Description |
---|---|
boolean | true or false |
float | 64-bit double precision floating point number |
int | 32-bit signed integer |
string | Unicode string |
Building component manual page
We can generate HTML documentation for the component using anduril build-doc --component doc-dir -b demo
. This results in the following page (note that it includes features we haven’t yet introduced):