FlowControl.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /**
  2. * Flow Control operations.
  3. *
  4. * @author n1474335 [n1474335@gmail.com]
  5. * @copyright Crown Copyright 2016
  6. * @license Apache-2.0
  7. *
  8. * @namespace
  9. */
  10. var FlowControl = {
  11. /**
  12. * @constant
  13. * @default
  14. */
  15. FORK_DELIM: "\\n",
  16. /**
  17. * @constant
  18. * @default
  19. */
  20. MERGE_DELIM: "\\n",
  21. /**
  22. * @constant
  23. * @default
  24. */
  25. FORK_IGNORE_ERRORS: false,
  26. /**
  27. * Fork operation.
  28. *
  29. * @param {Object} state - The current state of the recipe.
  30. * @param {number} state.progress - The current position in the recipe.
  31. * @param {Dish} state.dish - The Dish being operated on.
  32. * @param {Operation[]} state.opList - The list of operations in the recipe.
  33. * @returns {Object} The updated state of the recipe.
  34. */
  35. runFork: function(state) {
  36. var opList = state.opList,
  37. inputType = opList[state.progress].inputType,
  38. outputType = opList[state.progress].outputType,
  39. input = state.dish.get(inputType),
  40. ings = opList[state.progress].getIngValues(),
  41. splitDelim = ings[0],
  42. mergeDelim = ings[1],
  43. ignoreErrors = ings[2],
  44. subOpList = [],
  45. inputs = [];
  46. if (input)
  47. inputs = input.split(splitDelim);
  48. // Create subOpList for each tranche to operate on
  49. // (all remaining operations unless we encounter a Merge)
  50. for (var i = state.progress + 1; i < opList.length; i++) {
  51. if (opList[i].name === "Merge" && !opList[i].isDisabled()) {
  52. break;
  53. } else {
  54. subOpList.push(opList[i]);
  55. }
  56. }
  57. var recipe = new Recipe(),
  58. output = "",
  59. progress = 0;
  60. recipe.addOperations(subOpList);
  61. // Run recipe over each tranche
  62. for (i = 0; i < inputs.length; i++) {
  63. var dish = new Dish(inputs[i], inputType);
  64. try {
  65. progress = recipe.execute(dish, 0);
  66. } catch (err) {
  67. if (!ignoreErrors) {
  68. throw err;
  69. }
  70. progress = err.progress + 1;
  71. }
  72. output += dish.get(outputType) + mergeDelim;
  73. }
  74. state.dish.set(output, outputType);
  75. state.progress += progress;
  76. return state;
  77. },
  78. /**
  79. * Merge operation.
  80. *
  81. * @param {Object} state - The current state of the recipe.
  82. * @param {number} state.progress - The current position in the recipe.
  83. * @param {Dish} state.dish - The Dish being operated on.
  84. * @param {Operation[]} state.opList - The list of operations in the recipe.
  85. * @returns {Object} The updated state of the recipe.
  86. */
  87. runMerge: function(state) {
  88. // No need to actually do anything here. The fork operation will
  89. // merge when it sees this operation.
  90. return state;
  91. },
  92. /**
  93. * @constant
  94. * @default
  95. */
  96. JUMP_NUM: 0,
  97. /**
  98. * @constant
  99. * @default
  100. */
  101. MAX_JUMPS: 10,
  102. /**
  103. * Jump operation.
  104. *
  105. * @param {Object} state - The current state of the recipe.
  106. * @param {number} state.progress - The current position in the recipe.
  107. * @param {Dish} state.dish - The Dish being operated on.
  108. * @param {Operation[]} state.opList - The list of operations in the recipe.
  109. * @param {number} state.numJumps - The number of jumps taken so far.
  110. * @returns {Object} The updated state of the recipe.
  111. */
  112. runJump: function(state) {
  113. var ings = state.opList[state.progress].getIngValues(),
  114. jumpNum = ings[0],
  115. maxJumps = ings[1];
  116. if (state.numJumps >= maxJumps) {
  117. state.progress++;
  118. return state;
  119. }
  120. state.progress += jumpNum;
  121. state.numJumps++;
  122. return state;
  123. },
  124. /**
  125. * Conditional Jump operation.
  126. *
  127. * @param {Object} state - The current state of the recipe.
  128. * @param {number} state.progress - The current position in the recipe.
  129. * @param {Dish} state.dish - The Dish being operated on.
  130. * @param {Operation[]} state.opList - The list of operations in the recipe.
  131. * @param {number} state.numJumps - The number of jumps taken so far.
  132. * @returns {Object} The updated state of the recipe.
  133. */
  134. runCondJump: function(state) {
  135. var ings = state.opList[state.progress].getIngValues(),
  136. dish = state.dish,
  137. regexStr = ings[0],
  138. jumpNum = ings[1],
  139. maxJumps = ings[2];
  140. if (state.numJumps >= maxJumps) {
  141. state.progress++;
  142. return state;
  143. }
  144. if (regexStr !== "" && dish.get(Dish.STRING).search(regexStr) > -1) {
  145. state.progress += jumpNum;
  146. state.numJumps++;
  147. }
  148. return state;
  149. },
  150. /**
  151. * Return operation.
  152. *
  153. * @param {Object} state - The current state of the recipe.
  154. * @param {number} state.progress - The current position in the recipe.
  155. * @param {Dish} state.dish - The Dish being operated on.
  156. * @param {Operation[]} state.opList - The list of operations in the recipe.
  157. * @returns {Object} The updated state of the recipe.
  158. */
  159. runReturn: function(state) {
  160. state.progress = state.opList.length;
  161. return state;
  162. },
  163. };