123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- var OperationConfig = require("../config/OperationConfig.js"),
- Operation = require("./Operation.js");
- /**
- * The Recipe controls a list of Operations and the Dish they operate on.
- *
- * @author n1474335 [n1474335@gmail.com]
- * @copyright Crown Copyright 2016
- * @license Apache-2.0
- *
- * @class
- * @param {Object} recipeConfig
- */
- var Recipe = module.exports = function(recipeConfig) {
- this.opList = [];
- if (recipeConfig) {
- this._parseConfig(recipeConfig);
- }
- };
- /**
- * Reads and parses the given config.
- *
- * @private
- * @param {Object} recipeConfig
- */
- Recipe.prototype._parseConfig = function(recipeConfig) {
- for (var c = 0; c < recipeConfig.length; c++) {
- var operationName = recipeConfig[c].op;
- var operationConfig = OperationConfig[operationName];
- var operation = new Operation(operationName, operationConfig);
- operation.setIngValues(recipeConfig[c].args);
- operation.setBreakpoint(recipeConfig[c].breakpoint);
- operation.setDisabled(recipeConfig[c].disabled);
- this.addOperation(operation);
- }
- };
- /**
- * Returns the value of the Recipe as it should be displayed in a recipe config.
- *
- * @returns {*}
- */
- Recipe.prototype.getConfig = function() {
- var recipeConfig = [];
- for (var o = 0; o < this.opList.length; o++) {
- recipeConfig.push(this.opList[o].getConfig());
- }
- return recipeConfig;
- };
- /**
- * Adds a new Operation to this Recipe.
- *
- * @param {Operation} operation
- */
- Recipe.prototype.addOperation = function(operation) {
- this.opList.push(operation);
- };
- /**
- * Adds a list of Operations to this Recipe.
- *
- * @param {Operation[]} operations
- */
- Recipe.prototype.addOperations = function(operations) {
- this.opList = this.opList.concat(operations);
- };
- /**
- * Set a breakpoint on a specified Operation.
- *
- * @param {number} position - The index of the Operation
- * @param {boolean} value
- */
- Recipe.prototype.setBreakpoint = function(position, value) {
- try {
- this.opList[position].setBreakpoint(value);
- } catch (err) {
- // Ignore index error
- }
- };
- /**
- * Remove breakpoints on all Operations in the Recipe up to the specified position. Used by Flow
- * Control Fork operation.
- *
- * @param {number} pos
- */
- Recipe.prototype.removeBreaksUpTo = function(pos) {
- for (var i = 0; i < pos; i++) {
- this.opList[i].setBreakpoint(false);
- }
- };
- /**
- * Returns true if there is an Flow Control Operation in this Recipe.
- *
- * @returns {boolean}
- */
- Recipe.prototype.containsFlowControl = function() {
- for (var i = 0; i < this.opList.length; i++) {
- if (this.opList[i].isFlowControl()) return true;
- }
- return false;
- };
- /**
- * Returns the index of the last Operation index that will be executed, taking into account disabled
- * Operations and breakpoints.
- *
- * @param {number} [startIndex=0] - The index to start searching from
- * @returns (number}
- */
- Recipe.prototype.lastOpIndex = function(startIndex) {
- var i = startIndex + 1 || 0,
- op;
- for (; i < this.opList.length; i++) {
- op = this.opList[i];
- if (op.isDisabled()) return i-1;
- if (op.isBreakpoint()) return i-1;
- }
- return i-1;
- };
- /**
- * Executes each operation in the recipe over the given Dish.
- *
- * @param {Dish} dish
- * @param {number} [startFrom=0] - The index of the Operation to start executing from
- * @returns {number} - The final progress through the recipe
- */
- Recipe.prototype.execute = function(dish, startFrom) {
- startFrom = startFrom || 0;
- var op, input, output, numJumps = 0;
- for (var i = startFrom; i < this.opList.length; i++) {
- op = this.opList[i];
- if (op.isDisabled()) {
- continue;
- }
- if (op.isBreakpoint()) {
- return i;
- }
- try {
- input = dish.get(op.inputType);
- if (op.isFlowControl()) {
- // Package up the current state
- var state = {
- "progress" : i,
- "dish" : dish,
- "opList" : this.opList,
- "numJumps" : numJumps
- };
- state = op.run(state);
- i = state.progress;
- numJumps = state.numJumps;
- } else {
- output = op.run(input, op.getIngValues());
- dish.set(output, op.outputType);
- }
- } catch (err) {
- var e = typeof err == "string" ? { message: err } : err;
- e.progress = i;
- if (e.fileName) {
- e.displayStr = op.name + " - " + e.name + " in " +
- e.fileName + " on line " + e.lineNumber +
- ".<br><br>Message: " + (e.displayStr || e.message);
- } else {
- e.displayStr = op.name + " - " + (e.displayStr || e.message);
- }
- throw e;
- }
- }
- return this.opList.length;
- };
- /**
- * Returns the recipe configuration in string format.
- *
- * @returns {string}
- */
- Recipe.prototype.toString = function() {
- return JSON.stringify(this.getConfig());
- };
- /**
- * Creates a Recipe from a given configuration string.
- *
- * @param {string} recipeStr
- */
- Recipe.prototype.fromString = function(recipeStr) {
- var recipeConfig = JSON.parse(recipeStr);
- this._parseConfig(recipeConfig);
- };
|