Shapes

The library uses standard flowchart shapes to define the requirement of each control step.

There are currently 4 Shape types:

All the shapes inherit from the base IShape interface and contain the default properties to manage a shape.

//shape with required properties
var shape = { 
		"id": "abc123",  
		"shapeType": "Shape"
	};
	
// shape with all properties
var shape = { 
		"id": "abc123",  
		"shapeType": "Shape", 
		"description": "Description of the shape",
		"log": [],
		"processed": false,
		"processCount": 0
	};

The id field of a shape should be unique to the tree it resides in as the execute function will find the first matching id when using a decisionPath that references an id.

The shapeType property is used by the execute function to determine the current shape this should not be altered at any time.

Entry Shape

This shape tells you where the flowchart begins. It can also be added later at any point providing you with the subsequent entry points for your flowchart.

The nextShape property contains a child shape that is to be called following the completion of the entry step.

var entry = { 
		"id": 1,  
		"shapeType": "Entry", 
		"description": "Start",
		"nextShape": null
	};

Terminator Shape

This shape tells you where the flowchart ends.

var terminator = { 
		"id": 1,  
		"shapeType": "Terminator", 
		"description": "End"
	};

Operation Shape

This shape is used to manage an action that is to be taken.

The shape either contains a process function or a processName value that is use to attach a function to the step by name. When the decision tree reaches this shape it will call the process function, once completed it will then move to the next shape.

If the processName is populated then the function will be assigned even if one is already present.

The nextShape property contains a child shape that is to be called following the completion of the operation step.

var operation = { 
		"id": 1,  
		"shapeType": "Operation", 
		"description": "Call my process name function",
		"nextShape": null,
		"processName": "DecisionTreeTest.add",
		"process": function(data, shape, callback){...},
		"properties": {value: 2}
	};

Decision Shape

A decision asks a question, the answer of which determines which route to follow.

The shape inherits the operation shape and therefore a process is run first. As with the Operation Shape, if the processName is populated then the function will be assigned even if one is already present.

The shape either contains a decide function or a decideName value that is use to attach a function to the step by name. It is the responsibility of the decide function to determine the next shape to be called.

Each decision shape contains an array of DecisionPaths which are used to hold the paths that a decision can take. The decide function can either set a decisionPath selected property to true or manually set the nextShape property from the selected decisionPath.

The nextShape property contains a child shape that is to be called following the completion of the operation step.

var decision = { 
		"id": 1,  
		"shapeType": "Decision", 
		"description": "Call my process name function",
		"nextShape": null,
		"processName": "DecisionTreeTest.add",
		"process": function(data, shape, callback){...},
		"decidesName": "DecisionTreeTest.checkValue",
		"decide": function(data, shape, callback){...},
		"properties": {value: 2, decision: 10},
		"paths": []
	};

Decision Paths

A Decision Path works in a similar way to a flowchart arrow that follows a decision. It contains all the relevant data to determine which path the decision tree should take next.

The path contains: a value that is used by the decide function to determine if the path should be taken (similar to a label on a flowchart) a selected value to assist the execute function to set the nextShape. it can optionally have the nextShape object defined as a child or the id of the the next shape to jump to in the flow

var path = { 
		"value": true,
		"selected": false,
		"nextShape": null,
		"nextShapeId": "abc123"
	};

Execute Function

The execute function provides the structure and manages the steps taken in a decision tree leaving the functions required to process and decide a route to your application.

To call the function you must pass in the root shape and the data object to process.

In addition it is recommended that you assign a callback function to be called when the process is complete or if an error occurs.

If any functions in the shapes pass an error to its callback, no more functions are run and the complete callback is immediately called with the value of the error.

You also have the option to not keep a list of processed shapes, it is recommended to turn this off for decision trees that are large or have multiple repeated steps.

//execute the tree on the root shape
    decisionTree.execute(shape, data, function(err, result, processedShapes){
        console.log("result: " + result.a);
        for (var x = 0; x < processedShapes.length; x++) {
            console.log("processed Shape: " + processedShapes[x].description + " id:" + processedShapes[x].id);
        }
    }, true);

Use within Node.js

If your shapes are defining the process and decision functions by name then you must send through the modules that contain the functions for the exectute function to set the targets.

This takes the format of { "NAME", var }

In the example below there are two applications that have the required functions in, app1 and app2.

For example:

var app1 = require("./app1.js");
var app2 = require("./app2.js");

//execute the tree on the root shape
decisionTree.execute(shape, data, app1.complete, { "app1": app1, "app2": app2 });

Callback Functions

There are two types of callback functions used:

Application Functions

All of the operation and decision functions are called by the Execute function with the same signature. data - the object being processed shape - the current shape that is processing the object * callback - a function that calls back the execute function

On completion the function must call the callback function passing: null or error shape - the current shape

function add(data, shape, callback) {
		try {
			var v = Number(shape.properties.value);
			if(isNaN(v)) {
				throw new Error("'" + v + "' is not a number");
			}
			data.a += v;
			callback(null, shape);
		} catch (e) {
			callback(e, shape);
		}
	} 
	

Complete Function

When the Execute function has completed if a callback function has been passed then it will be called. The callback function is also called immediately if an error is thrown.

  • err - an error if one occurred or null if succesful
  • result - the resulting objecting from processing
  • processedShapes - an array of all the shapes processed by the Execute function
function complete(err, result, processedShapes) {
        ....
    }