ruote 0.9.19 → 0.9.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (401) hide show
  1. data/README.txt +16 -6
  2. data/examples/engine_template.rb +6 -43
  3. data/examples/quickstart.rb +87 -0
  4. data/examples/quotereporter.rb +42 -49
  5. data/examples/simple.rb +56 -0
  6. data/lib/openwfe.rb +20 -34
  7. data/lib/openwfe/contextual.rb +45 -36
  8. data/lib/openwfe/def.rb +21 -30
  9. data/lib/openwfe/engine.rb +17 -26
  10. data/lib/openwfe/engine/engine.rb +132 -397
  11. data/lib/openwfe/engine/expool_methods.rb +34 -122
  12. data/lib/openwfe/engine/file_persisted_engine.rb +39 -60
  13. data/lib/openwfe/engine/fs_engine.rb +54 -0
  14. data/lib/openwfe/engine/launch_methods.rb +245 -0
  15. data/lib/openwfe/engine/listener_methods.rb +128 -0
  16. data/lib/openwfe/engine/lookup_methods.rb +156 -0
  17. data/lib/openwfe/engine/participant_methods.rb +60 -52
  18. data/lib/openwfe/engine/status_methods.rb +102 -97
  19. data/lib/openwfe/engine/tc_engine.rb +55 -0
  20. data/lib/openwfe/engine/tt_engine.rb +55 -0
  21. data/lib/openwfe/engine/update_exp_methods.rb +46 -39
  22. data/lib/openwfe/expool/def_parser.rb +196 -0
  23. data/lib/openwfe/expool/errorjournal.rb +51 -219
  24. data/lib/openwfe/expool/errors.rb +69 -0
  25. data/lib/openwfe/expool/expool_pause_methods.rb +32 -43
  26. data/lib/openwfe/expool/expressionpool.rb +398 -594
  27. data/lib/openwfe/expool/expstorage.rb +68 -72
  28. data/lib/openwfe/expool/fs_expstorage.rb +302 -0
  29. data/lib/openwfe/expool/history.rb +54 -38
  30. data/lib/openwfe/expool/journal.rb +24 -38
  31. data/lib/openwfe/expool/journal_replay.rb +20 -36
  32. data/lib/openwfe/expool/representation.rb +62 -78
  33. data/lib/openwfe/expool/tc_expstorage.rb +239 -0
  34. data/lib/openwfe/expool/{threadedexpstorage.rb → threaded_expstorage.rb} +25 -53
  35. data/lib/openwfe/expool/tt_expstorage.rb +55 -0
  36. data/lib/openwfe/expool/wfidgen.rb +23 -43
  37. data/lib/openwfe/expool/yaml_errorjournal.rb +187 -0
  38. data/lib/openwfe/expressions/condition.rb +33 -58
  39. data/lib/openwfe/expressions/environment.rb +62 -76
  40. data/lib/openwfe/expressions/{expressionmap.rb → expression_map.rb} +40 -54
  41. data/lib/openwfe/expressions/expression_tree.rb +265 -0
  42. data/lib/openwfe/expressions/fe_cancel.rb +19 -39
  43. data/lib/openwfe/expressions/fe_command.rb +80 -84
  44. data/lib/openwfe/expressions/fe_concurrence.rb +250 -313
  45. data/lib/openwfe/expressions/fe_cron.rb +38 -55
  46. data/lib/openwfe/expressions/fe_cursor.rb +49 -74
  47. data/lib/openwfe/expressions/fe_define.rb +44 -90
  48. data/lib/openwfe/expressions/fe_do.rb +83 -70
  49. data/lib/openwfe/expressions/fe_equals.rb +17 -35
  50. data/lib/openwfe/expressions/fe_error.rb +103 -0
  51. data/lib/openwfe/expressions/fe_filter.rb +27 -44
  52. data/lib/openwfe/expressions/fe_filter_definition.rb +37 -54
  53. data/lib/openwfe/expressions/fe_fqv.rb +46 -65
  54. data/lib/openwfe/expressions/fe_http.rb +17 -31
  55. data/lib/openwfe/expressions/fe_if.rb +39 -55
  56. data/lib/openwfe/expressions/fe_iterator.rb +25 -42
  57. data/lib/openwfe/expressions/fe_listen.rb +71 -115
  58. data/lib/openwfe/expressions/fe_losfor.rb +34 -43
  59. data/lib/openwfe/expressions/fe_misc.rb +70 -109
  60. data/lib/openwfe/expressions/fe_participant.rb +61 -99
  61. data/lib/openwfe/expressions/fe_reserve.rb +28 -59
  62. data/lib/openwfe/expressions/fe_save.rb +62 -81
  63. data/lib/openwfe/expressions/fe_sequence.rb +45 -70
  64. data/lib/openwfe/expressions/fe_set.rb +22 -40
  65. data/lib/openwfe/expressions/fe_step.rb +22 -37
  66. data/lib/openwfe/expressions/fe_subprocess.rb +34 -55
  67. data/lib/openwfe/expressions/fe_timeout.rb +28 -44
  68. data/lib/openwfe/expressions/fe_wait.rb +142 -36
  69. data/lib/openwfe/expressions/fe_when.rb +22 -46
  70. data/lib/openwfe/expressions/filter.rb +24 -43
  71. data/lib/openwfe/expressions/flowexpression.rb +211 -192
  72. data/lib/openwfe/expressions/iterator.rb +24 -39
  73. data/lib/openwfe/expressions/merge.rb +30 -52
  74. data/lib/openwfe/expressions/raw.rb +168 -384
  75. data/lib/openwfe/expressions/rprocdef.rb +79 -76
  76. data/lib/openwfe/expressions/time.rb +89 -103
  77. data/lib/openwfe/expressions/timeout.rb +98 -92
  78. data/lib/openwfe/expressions/value.rb +43 -69
  79. data/lib/openwfe/extras/engine/ar_engine.rb +58 -0
  80. data/lib/openwfe/extras/engine/db_persisted_engine.rb +37 -57
  81. data/lib/openwfe/extras/engine/dm_engine.rb +59 -0
  82. data/lib/openwfe/extras/expool/ar_expstorage.rb +337 -0
  83. data/lib/openwfe/extras/expool/db_errorjournal.rb +165 -0
  84. data/lib/openwfe/extras/expool/db_expstorage.rb +73 -0
  85. data/lib/openwfe/extras/expool/db_history.rb +163 -0
  86. data/lib/openwfe/extras/expool/dm_expstorage.rb +327 -0
  87. data/lib/openwfe/extras/listeners/jabber_listeners.rb +102 -0
  88. data/lib/openwfe/extras/listeners/jabberlisteners.rb +26 -0
  89. data/lib/openwfe/extras/listeners/sqs_listeners.rb +128 -0
  90. data/lib/openwfe/extras/misc/activityfeed.rb +19 -34
  91. data/lib/openwfe/extras/misc/jabber_common.rb +122 -0
  92. data/lib/openwfe/extras/participants/active_participants.rb +724 -0
  93. data/lib/openwfe/extras/participants/active_resource_participants.rb +213 -0
  94. data/lib/openwfe/extras/participants/activeparticipants.rb +1 -747
  95. data/lib/openwfe/extras/participants/ar_participants.rb +285 -0
  96. data/lib/openwfe/extras/participants/atomfeed_participants.rb +19 -34
  97. data/lib/openwfe/extras/participants/atompub_participants.rb +19 -34
  98. data/lib/openwfe/extras/participants/basecamp_participants.rb +17 -31
  99. data/lib/openwfe/extras/participants/{csvparticipants.rb → decision_participants.rb} +17 -31
  100. data/lib/openwfe/extras/participants/jabber_participants.rb +147 -0
  101. data/lib/openwfe/extras/participants/jabberparticipants.rb +3 -0
  102. data/lib/openwfe/extras/participants/sqs_participants.rb +108 -0
  103. data/lib/openwfe/extras/participants/{twitterparticipants.rb → twitter_participants.rb} +20 -34
  104. data/lib/openwfe/extras/singlecon.rb +56 -0
  105. data/lib/openwfe/filterdef.rb +83 -65
  106. data/lib/openwfe/flowexpressionid.rb +99 -62
  107. data/lib/openwfe/listeners/listener.rb +54 -65
  108. data/lib/openwfe/listeners/listeners.rb +52 -56
  109. data/lib/openwfe/logging.rb +17 -31
  110. data/lib/openwfe/omixins.rb +25 -58
  111. data/lib/openwfe/participants.rb +1 -34
  112. data/lib/openwfe/participants/{enoparticipants.rb → mail_participants.rb} +33 -47
  113. data/lib/openwfe/participants/participant.rb +37 -36
  114. data/lib/openwfe/participants/participant_map.rb +245 -0
  115. data/lib/openwfe/participants/participants.rb +43 -69
  116. data/lib/openwfe/participants/{soapparticipants.rb → soap_participants.rb} +22 -36
  117. data/lib/openwfe/participants/{storeparticipants.rb → store_participants.rb} +57 -62
  118. data/lib/openwfe/{storage/yamlfilestorage.rb → participants/yaml_filestorage.rb} +35 -64
  119. data/lib/openwfe/representations.rb +770 -0
  120. data/lib/openwfe/rudefinitions.rb +17 -29
  121. data/lib/openwfe/service.rb +21 -32
  122. data/lib/openwfe/tools/flowtracer.rb +21 -35
  123. data/lib/openwfe/util/dollar.rb +48 -61
  124. data/lib/openwfe/util/irb.rb +19 -34
  125. data/lib/openwfe/util/json.rb +55 -0
  126. data/lib/openwfe/util/observable.rb +22 -41
  127. data/lib/openwfe/util/ometa.rb +21 -35
  128. data/lib/openwfe/util/treechecker.rb +17 -31
  129. data/lib/openwfe/util/workqueue.rb +45 -44
  130. data/lib/openwfe/util/xml.rb +80 -234
  131. data/lib/openwfe/utils.rb +67 -110
  132. data/lib/openwfe/version.rb +19 -27
  133. data/lib/openwfe/workitem.rb +119 -84
  134. data/lib/openwfe/worklist/storelocks.rb +17 -33
  135. data/lib/openwfe/worklist/storeparticipant.rb +1 -39
  136. data/lib/openwfe/worklist/worklist.rb +17 -31
  137. data/lib/pooltool.ru +311 -0
  138. data/test/{extras/active_connection.rb → ar_test_connection.rb} +26 -11
  139. data/test/bm/fatxml.rb +70 -0
  140. data/test/bm/load_26c.rb +79 -0
  141. data/test/dm_test_connection.rb +11 -0
  142. data/test/extras/base.rb +3 -0
  143. data/test/extras/et_0_sqs.rb +37 -0
  144. data/test/extras/et_jabber_test.rb +226 -0
  145. data/test/extras/test.rb +16 -0
  146. data/test/functional/base.rb +198 -0
  147. data/test/functional/db_ft_0_ar_participants.rb +136 -0
  148. data/test/functional/eft_0_process_definition.rb +34 -0
  149. data/test/functional/eft_10_unset.rb +60 -0
  150. data/test/functional/eft_11_sleep.rb +95 -0
  151. data/test/functional/eft_12_wait.rb +57 -0
  152. data/test/functional/eft_13_cursor.rb +139 -0
  153. data/test/functional/eft_14_loop.rb +36 -0
  154. data/test/functional/eft_15_undo.rb +77 -0
  155. data/test/functional/eft_16_redo.rb +88 -0
  156. data/test/functional/eft_1_print.rb +57 -0
  157. data/test/functional/eft_2_sequence.rb +47 -0
  158. data/test/functional/eft_3_equals.rb +98 -0
  159. data/test/functional/eft_4_if.rb +96 -0
  160. data/test/functional/eft_5_eval.rb +89 -0
  161. data/test/functional/eft_6_reval.rb +101 -0
  162. data/test/functional/eft_7_exp.rb +47 -0
  163. data/test/functional/eft_8_log.rb +50 -0
  164. data/test/functional/eft_9_set.rb +132 -0
  165. data/test/functional/engine_helper.rb +122 -0
  166. data/test/functional/ft_0_vars_at_launch.rb +27 -0
  167. data/test/functional/ft_1_process_status.rb +46 -0
  168. data/test/functional/ft_2_file_listener.rb +45 -0
  169. data/test/functional/ft_3_on_cancel.rb +171 -0
  170. data/test/functional/ft_4_on_error.rb +220 -0
  171. data/test/functional/ft_5_process_uri.rb +82 -0
  172. data/test/functional/ft_6_process_status.rb +62 -0
  173. data/test/functional/ft_7_parameters.rb +103 -0
  174. data/test/functional/ft_8_dollar.rb +53 -0
  175. data/test/functional/ft_9_register_participants.rb +119 -0
  176. data/test/functional/restart_base.rb +43 -0
  177. data/test/functional/rft_0_sleep.rb +76 -0
  178. data/test/functional/test.rb +24 -0
  179. data/test/path_helper.rb +12 -0
  180. data/test/test.rb +11 -1
  181. data/test/{rutest_utils.rb → test_helper.rb} +8 -31
  182. data/test/unit/test.rb +19 -0
  183. data/test/{fei_test.rb → unit/ut_0_fei.rb} +34 -49
  184. data/test/unit/ut_10_lookup_attribute.rb +86 -0
  185. data/test/unit/ut_11_filter.rb +124 -0
  186. data/test/{condition_test.rb → unit/ut_12_conditional.rb} +33 -40
  187. data/test/unit/ut_13_xmlutil.rb +57 -0
  188. data/test/unit/ut_14_var_field_lookup.rb +85 -0
  189. data/test/{fe_lookup_att_test.rb → unit/ut_15_fe_att_lookup.rb} +14 -21
  190. data/test/{storage_test.rb → unit/ut_16_expstorage_findexp.rb} +3 -9
  191. data/test/unit/ut_17_representations.rb +330 -0
  192. data/test/{hash_test.rb → unit/ut_17b_representations_hash.rb} +25 -21
  193. data/test/{slock_test.rb → unit/ut_18_store_lock.rb} +17 -20
  194. data/test/{wfid_test.rb → unit/ut_1_wfid.rb} +2 -73
  195. data/test/unit/ut_2_utils.rb +53 -0
  196. data/test/unit/ut_3_expmap.rb +65 -0
  197. data/test/{clone_test.rb → unit/ut_4_fulldup.rb} +41 -46
  198. data/test/{obs_test.rb → unit/ut_5_observable.rb} +9 -19
  199. data/test/unit/ut_6_treechecker.rb +101 -0
  200. data/test/unit/ut_7_parser_ruby.rb +344 -0
  201. data/test/unit/ut_7b_parser_ruby.rb +56 -0
  202. data/test/{description_test.rb → unit/ut_8_parser_description.rb} +8 -19
  203. data/test/unit/ut_9_workitem.rb +72 -0
  204. metadata +117 -234
  205. data/lib/openwfe/exceptions.rb +0 -51
  206. data/lib/openwfe/expool/parser.rb +0 -278
  207. data/lib/openwfe/expool/paused_error.rb +0 -77
  208. data/lib/openwfe/expool/yamlexpstorage.rb +0 -224
  209. data/lib/openwfe/expressions/fe_sleep.rb +0 -173
  210. data/lib/openwfe/extras/expool/dberrorjournal.rb +0 -189
  211. data/lib/openwfe/extras/expool/dbexpstorage.rb +0 -355
  212. data/lib/openwfe/extras/expool/dbhistory.rb +0 -135
  213. data/lib/openwfe/extras/listeners/sqslisteners.rb +0 -146
  214. data/lib/openwfe/extras/participants/sqsparticipants.rb +0 -125
  215. data/lib/openwfe/listeners/socketlisteners.rb +0 -272
  216. data/lib/openwfe/orest/definitions.rb +0 -113
  217. data/lib/openwfe/orest/osocket.rb +0 -148
  218. data/lib/openwfe/orest/xmlcodec.rb +0 -682
  219. data/lib/openwfe/participants/participantmap.rb +0 -249
  220. data/lib/openwfe/participants/socketparticipants.rb +0 -202
  221. data/lib/openwfe/storage/yamlcustom.rb +0 -106
  222. data/lib/openwfe/worklist/oldrest.rb +0 -244
  223. data/test/README.txt +0 -27
  224. data/test/back_0916_test.rb +0 -109
  225. data/test/bm/bm_1_xml_vs_prog.rb +0 -59
  226. data/test/bm/bm_2_step.rb +0 -109
  227. data/test/bm/ft_0f_5ms.rb +0 -35
  228. data/test/bm/ft_26_load.rb +0 -208
  229. data/test/bm/ft_26b_load.rb +0 -84
  230. data/test/bm/ft_26c_load.rb +0 -102
  231. data/test/bm/ft_recu.rb +0 -71
  232. data/test/concurrence_test.rb +0 -77
  233. data/test/console_test.rb +0 -12
  234. data/test/cron_ltest.rb +0 -15
  235. data/test/eno_test.rb +0 -76
  236. data/test/expmap_test.rb +0 -54
  237. data/test/expool_20031219_0916.tgz +0 -0
  238. data/test/extras/README.txt +0 -5
  239. data/test/extras/active_with_engine_test.rb +0 -140
  240. data/test/extras/activityfeed_test.rb +0 -85
  241. data/test/extras/ap_0_test.rb +0 -287
  242. data/test/extras/ap_1_test.rb +0 -53
  243. data/test/extras/ap_test_base.rb +0 -24
  244. data/test/extras/atomfeedp_test.rb +0 -113
  245. data/test/extras/atompubp_test.rb +0 -91
  246. data/test/extras/basecamp_test.rb +0 -53
  247. data/test/extras/db_errorjournal_utest.rb +0 -75
  248. data/test/extras/db_expstorage_utest.rb +0 -171
  249. data/test/extras/db_history_0_test.rb +0 -58
  250. data/test/extras/ft_19_csv.rb +0 -58
  251. data/test/extras/ft_71_b14008.rb +0 -85
  252. data/test/extras/sqs_test.rb +0 -57
  253. data/test/extras/twitter_test.rb +0 -62
  254. data/test/file_persisted_engine_test.rb +0 -64
  255. data/test/file_persistence_test.rb +0 -135
  256. data/test/filep_cancel_test.rb +0 -123
  257. data/test/filter_test.rb +0 -109
  258. data/test/flowtestbase.rb +0 -339
  259. data/test/ft_0.rb +0 -68
  260. data/test/ft_0b_sequence.rb +0 -36
  261. data/test/ft_0c_testname.rb +0 -33
  262. data/test/ft_0d_participant.rb +0 -30
  263. data/test/ft_0e_multibody.rb +0 -34
  264. data/test/ft_10_loop.rb +0 -133
  265. data/test/ft_11_ppd.rb +0 -411
  266. data/test/ft_11b_ppd.rb +0 -54
  267. data/test/ft_12_blockparticipant.rb +0 -97
  268. data/test/ft_13_eno.rb +0 -52
  269. data/test/ft_14_subprocess.rb +0 -88
  270. data/test/ft_14b_subprocess.rb +0 -192
  271. data/test/ft_14c_subprocess.rb +0 -68
  272. data/test/ft_15_iterator.rb +0 -216
  273. data/test/ft_15b_iterator.rb +0 -74
  274. data/test/ft_16_fqv.rb +0 -73
  275. data/test/ft_17_condition.rb +0 -84
  276. data/test/ft_18_pname.rb +0 -56
  277. data/test/ft_1_unset.rb +0 -175
  278. data/test/ft_1b_unset.rb +0 -39
  279. data/test/ft_20_cron.rb +0 -53
  280. data/test/ft_21_cron.rb +0 -87
  281. data/test/ft_21b_cron_pause.rb +0 -82
  282. data/test/ft_22_history.rb +0 -78
  283. data/test/ft_23_when.rb +0 -77
  284. data/test/ft_23b_when.rb +0 -70
  285. data/test/ft_23c_wait.rb +0 -80
  286. data/test/ft_23d_cww.rb +0 -58
  287. data/test/ft_24_def.rb +0 -44
  288. data/test/ft_25_cancel.rb +0 -92
  289. data/test/ft_27_getflowpos.rb +0 -143
  290. data/test/ft_28_fileparticipant.rb +0 -63
  291. data/test/ft_29_httprb.rb +0 -106
  292. data/test/ft_2_concurrence.rb +0 -137
  293. data/test/ft_2b_concurrence.rb +0 -188
  294. data/test/ft_2c_concurrence.rb +0 -64
  295. data/test/ft_30_socketlistener.rb +0 -203
  296. data/test/ft_31_flowname.rb +0 -39
  297. data/test/ft_32_journal.rb +0 -91
  298. data/test/ft_32c_journal.rb +0 -102
  299. data/test/ft_32d_journal.rb +0 -81
  300. data/test/ft_33_description.rb +0 -107
  301. data/test/ft_34_cancelwfid.rb +0 -80
  302. data/test/ft_35_localdefs.rb +0 -77
  303. data/test/ft_36_subprocids.rb +0 -97
  304. data/test/ft_37_pnames.rb +0 -70
  305. data/test/ft_38_tag.rb +0 -127
  306. data/test/ft_38b_tag.rb +0 -161
  307. data/test/ft_38c_tag.rb +0 -100
  308. data/test/ft_38d_tag.rb +0 -53
  309. data/test/ft_39_reserve.rb +0 -63
  310. data/test/ft_39b_reserve.rb +0 -84
  311. data/test/ft_3_equals.rb +0 -170
  312. data/test/ft_3b_lookup_vf.rb +0 -83
  313. data/test/ft_40_defined.rb +0 -61
  314. data/test/ft_41_case.rb +0 -110
  315. data/test/ft_42_environments.rb +0 -75
  316. data/test/ft_43_pat10.rb +0 -85
  317. data/test/ft_44_save.rb +0 -70
  318. data/test/ft_44b_restore.rb +0 -212
  319. data/test/ft_45_citerator.rb +0 -214
  320. data/test/ft_45b_citerator.rb +0 -77
  321. data/test/ft_46_pparams.rb +0 -62
  322. data/test/ft_47_filter.rb +0 -160
  323. data/test/ft_48_fe_filter.rb +0 -88
  324. data/test/ft_49_condition.rb +0 -133
  325. data/test/ft_4_misc.rb +0 -232
  326. data/test/ft_50_xml_attribute.rb +0 -152
  327. data/test/ft_51_stack.rb +0 -55
  328. data/test/ft_52_obs_participant.rb +0 -123
  329. data/test/ft_53_null_noop_participant.rb +0 -62
  330. data/test/ft_54_listen.rb +0 -288
  331. data/test/ft_54b_listen.rb +0 -66
  332. data/test/ft_54c_listen.rb +0 -99
  333. data/test/ft_55_ptimeout.rb +0 -58
  334. data/test/ft_56_timeout.rb +0 -59
  335. data/test/ft_57_a.rb +0 -148
  336. data/test/ft_58_ejournal.rb +0 -154
  337. data/test/ft_58b_ejournal.rb +0 -82
  338. data/test/ft_59_ps.rb +0 -212
  339. data/test/ft_5_time.rb +0 -118
  340. data/test/ft_60_ecancel.rb +0 -161
  341. data/test/ft_61_elsub.rb +0 -51
  342. data/test/ft_62_procparticipant.rb +0 -71
  343. data/test/ft_63_pause.rb +0 -137
  344. data/test/ft_64_alias.rb +0 -101
  345. data/test/ft_65_stringlaunch.rb +0 -59
  346. data/test/ft_66_subforget.rb +0 -70
  347. data/test/ft_67_schedlaunch.rb +0 -115
  348. data/test/ft_68_ifparticipant.rb +0 -70
  349. data/test/ft_69_cancelmissing.rb +0 -53
  350. data/test/ft_6_lambda.rb +0 -64
  351. data/test/ft_70_lookupvar.rb +0 -55
  352. data/test/ft_71_log.rb +0 -60
  353. data/test/ft_72_lookup_processes.rb +0 -79
  354. data/test/ft_73_cancel_sub.rb +0 -139
  355. data/test/ft_74_block_and_workitem_dup.rb +0 -63
  356. data/test/ft_75_ruby_attributes.rb +0 -89
  357. data/test/ft_76_merge_isolate.rb +0 -88
  358. data/test/ft_77_segments.rb +0 -35
  359. data/test/ft_78_eval.rb +0 -150
  360. data/test/ft_79_tticket.rb +0 -187
  361. data/test/ft_79b_tticket.rb +0 -172
  362. data/test/ft_79c_outcome.rb +0 -56
  363. data/test/ft_7_lose.rb +0 -104
  364. data/test/ft_7b_lose.rb +0 -78
  365. data/test/ft_80_spname.rb +0 -91
  366. data/test/ft_81_exp.rb +0 -60
  367. data/test/ft_82_trecu.rb +0 -52
  368. data/test/ft_83_badpause.rb +0 -58
  369. data/test/ft_84_updateexp.rb +0 -198
  370. data/test/ft_84b_subrepr.rb +0 -72
  371. data/test/ft_85_dolhash.rb +0 -43
  372. data/test/ft_86_dollar_fv.rb +0 -68
  373. data/test/ft_87_define.rb +0 -74
  374. data/test/ft_88_http.rb +0 -100
  375. data/test/ft_8_forget.rb +0 -44
  376. data/test/ft_9_cursor.rb +0 -154
  377. data/test/ft_9b_cursor.rb +0 -105
  378. data/test/ft_tests.rb +0 -130
  379. data/test/hparticipant_test.rb +0 -168
  380. data/test/lookup_att_test.rb +0 -90
  381. data/test/lookup_vf_test.rb +0 -94
  382. data/test/misc_test.rb +0 -94
  383. data/test/nut_0_irb.rb +0 -20
  384. data/test/param_test.rb +0 -290
  385. data/test/participant_test.rb +0 -101
  386. data/test/pending.rb +0 -23
  387. data/test/ps_representation.rb +0 -133
  388. data/test/rake_ltest.rb +0 -38
  389. data/test/rake_qtest.rb +0 -68
  390. data/test/raw_prog_test.rb +0 -407
  391. data/test/restart_cron_test.rb +0 -136
  392. data/test/restart_paused_test.rb +0 -103
  393. data/test/restart_sleep_test.rb +0 -140
  394. data/test/restart_tests.rb +0 -18
  395. data/test/restart_when_test.rb +0 -112
  396. data/test/ruby_procdef_test.rb +0 -132
  397. data/test/sec_test.rb +0 -206
  398. data/test/timeout_test.rb +0 -105
  399. data/test/treechecker_test.rb +0 -111
  400. data/test/util_xml_test.rb +0 -112
  401. data/test/wi_test.rb +0 -75
@@ -0,0 +1,724 @@
1
+ #--
2
+ # Copyright (c) 2007-2009, John Mettraux, Tomaso Tosolini OpenWFE.org
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Italy.
23
+ #++
24
+
25
+
26
+ #require_gem 'activerecord'
27
+ gem 'activerecord'; require 'active_record'
28
+
29
+
30
+ require 'openwfe/workitem'
31
+ require 'openwfe/flowexpressionid'
32
+ require 'openwfe/engine/engine'
33
+ require 'openwfe/participants/participant'
34
+
35
+
36
+ module OpenWFE
37
+ module Extras
38
+
39
+ #
40
+ # DEPRECATED !! use openwfe/extras/participants/ar_participants instead
41
+ #
42
+ # The migration for ActiveParticipant and associated classes.
43
+ #
44
+ # There are two tables 'workitems' and 'fields'. As its name implies,
45
+ # the latter table stores the fields (also called attributes in OpenWFE
46
+ # speak) of the workitems.
47
+ #
48
+ # See Workitem and Field for more details.
49
+ #
50
+ # For centralization purposes, the migration and the model are located
51
+ # in the same source file. It should be quite easy for the Rails hackers
52
+ # among you to sort that out for a Rails based usage.
53
+ #
54
+ class WorkitemTables < ActiveRecord::Migration
55
+
56
+ def self.up
57
+
58
+ create_table :workitems do |t|
59
+ t.column :fei, :string
60
+ t.column :wfid, :string
61
+ t.column :expid, :string
62
+ t.column :wf_name, :string
63
+ t.column :wf_revision, :string
64
+ t.column :participant_name, :string
65
+ t.column :store_name, :string
66
+ t.column :dispatch_time, :timestamp
67
+ t.column :last_modified, :timestamp
68
+
69
+ t.column :yattributes, :text
70
+ # when using compact_workitems, attributes are stored here
71
+ end
72
+ add_index :workitems, :fei, :unique => true
73
+ # with sqlite3, comment out this :unique => true on :fei :(
74
+ add_index :workitems, :wfid
75
+ add_index :workitems, :expid
76
+ add_index :workitems, :wf_name
77
+ add_index :workitems, :wf_revision
78
+ add_index :workitems, :participant_name
79
+ add_index :workitems, :store_name
80
+
81
+ create_table :fields do |t|
82
+ t.column :fkey, :string, :null => false
83
+ t.column :vclass, :string, :null => false
84
+ t.column :svalue, :string
85
+ t.column :yvalue, :text
86
+ t.column :workitem_id, :integer, :null => false
87
+ end
88
+ #add_index :fields, [ :workitem_id, :fkey ], :unique => true
89
+ #add_index :fields, :workitem_id
90
+ add_index :fields, :fkey
91
+ add_index :fields, :vclass
92
+ add_index :fields, :svalue
93
+ end
94
+
95
+ def self.down
96
+
97
+ drop_table :workitems
98
+ drop_table :fields
99
+ end
100
+ end
101
+
102
+ #
103
+ # Reopening InFlowWorkItem to add a 'db_id' attribute.
104
+ #
105
+ class OpenWFE::InFlowWorkItem
106
+
107
+ attr_accessor :db_id
108
+ # deprecated !
109
+ end
110
+
111
+ #
112
+ # The ActiveRecord version of an OpenWFEru workitem (InFlowWorkItem).
113
+ #
114
+ # One can very easily build a worklist based on a participant name via :
115
+ #
116
+ # wl = OpenWFE::Extras::Workitem.find_all_by_participant_name("toto")
117
+ # puts "found #{wl.size} workitems for participant 'toto'"
118
+ #
119
+ # These workitems are not OpenWFEru workitems directly. But the conversion
120
+ # is pretty easy.
121
+ # Note that you probaly won't need to do the conversion by yourself,
122
+ # except for certain advanced scenarii.
123
+ #
124
+ # awi = OpenWFE::Extras::Workitem.find_by_participant_name("toto")
125
+ # #
126
+ # # returns the first workitem in the database whose participant
127
+ # # name is 'toto'.
128
+ #
129
+ # owi = awi.as_owfe_workitem
130
+ # #owi = awi.to_owfe_workitem
131
+ # #
132
+ # # Now we have a copy of the reference as a OpenWFEru
133
+ # # InFlowWorkItem instance.
134
+ #
135
+ # awi = OpenWFE::Extras::Workitem.from_owfe_workitem(owi)
136
+ # #
137
+ # # turns an OpenWFEru InFlowWorkItem instance into an
138
+ # # 'active workitem'.
139
+ #
140
+ class Workitem < ActiveRecord::Base
141
+
142
+ def connection
143
+ ActiveRecord::Base.verify_active_connections!
144
+ super
145
+ end
146
+
147
+ has_many(
148
+ :fields,
149
+ :dependent => :delete_all,
150
+ :class_name => 'OpenWFE::Extras::Field')
151
+
152
+ serialize :yattributes
153
+
154
+ #
155
+ # Returns the flow expression id of this work (its unique OpenWFEru (Ruote)
156
+ # identifier) as a FlowExpressionId instance.
157
+ # (within the Workitem it's just stored as a String).
158
+ #
159
+ def full_fei
160
+
161
+ @full_fei ||= OpenWFE::FlowExpressionId.from_s(fei)
162
+ end
163
+
164
+ #
165
+ # Making sure last_modified is set to Time.now before each save.
166
+ #
167
+ def before_save
168
+
169
+ touch
170
+ end
171
+
172
+ #
173
+ # Generates a (new) Workitem from an OpenWFEru InFlowWorkItem instance.
174
+ #
175
+ # This is a 'static' method :
176
+ #
177
+ # awi = OpenWFE::Extras::Workitem.from_owfe_workitem(wi)
178
+ #
179
+ # (This method saves the 'ActiveWorkitem').
180
+ #
181
+ def Workitem.from_owfe_workitem (wi, store_name=nil)
182
+
183
+ i = Workitem.new
184
+ i.fei = wi.fei.to_s
185
+ i.wfid = wi.fei.wfid
186
+ i.expid = wi.fei.expid
187
+ i.wf_name = wi.fei.workflow_definition_name
188
+ i.wf_revision = wi.fei.workflow_definition_revision
189
+ i.participant_name = wi.participant_name
190
+ i.dispatch_time = wi.dispatch_time
191
+ i.last_modified = nil
192
+
193
+ i.store_name = store_name
194
+
195
+ if wi.attributes['compact_workitems']
196
+
197
+ wi.attributes.delete('compact_workitems')
198
+ i.yattributes = wi.attributes
199
+
200
+ else
201
+
202
+ i.yattributes = nil
203
+ wi.attributes.each { |k, v| i.fields << Field.new_field(k, v) }
204
+ end
205
+
206
+ i.save!
207
+ # making sure to throw an exception in case of trouble
208
+
209
+ i
210
+ end
211
+
212
+ #
213
+ # Turns the 'active' Workitem into a ruote InFlowWorkItem.
214
+ #
215
+ def to_owfe_workitem (options={})
216
+
217
+ wi = OpenWFE::InFlowWorkItem.new
218
+
219
+ wi.fei = full_fei
220
+ wi.participant_name = participant_name
221
+ wi.attributes = fields_hash
222
+
223
+ wi.dispatch_time = dispatch_time
224
+ wi.last_modified = last_modified
225
+
226
+ wi.db_id = self.id
227
+
228
+ wi
229
+ end
230
+
231
+ alias :as_owfe_workitem :to_owfe_workitem
232
+
233
+ #
234
+ # Returns a hash version of the 'fields' of this workitem.
235
+ #
236
+ # (Each time this method is called, it returns a new hash).
237
+ #
238
+ def field_hash
239
+
240
+ self.yattributes || fields.inject({}) { |r, f| r[f.fkey] = f.value; r }
241
+ end
242
+
243
+ alias :fields_hash :field_hash
244
+
245
+ #
246
+ # Replaces the current fields of this workitem with the given hash.
247
+ #
248
+ # This method modifies the content of the db.
249
+ #
250
+ def replace_fields (fhash)
251
+
252
+ if self.yattributes
253
+
254
+ #self.yattributes = fhash
255
+
256
+ else
257
+
258
+ fields.delete_all
259
+ fhash.each { |k, v| fields << Field.new_field(k, v) }
260
+ end
261
+
262
+ #f = Field.new_field("___map_type", "smap")
263
+ #
264
+ # an old trick for backward compatibility with OpenWFEja
265
+
266
+ save!
267
+ # making sure to throw an exception in case of trouble
268
+ end
269
+
270
+ #
271
+ # Returns the Field instance with the given key. This method accept
272
+ # symbols as well as strings as its parameter.
273
+ #
274
+ # wi.field("customer_name")
275
+ # wi.field :customer_name
276
+ #
277
+ def field (key)
278
+
279
+ return self.yattributes[key.to_s] if self.yattributes
280
+
281
+ fields.find_by_fkey(key.to_s)
282
+ end
283
+
284
+ #
285
+ # A shortcut method, replies to the workflow engine and removes self
286
+ # from the database.
287
+ # Handy for people who don't want to play with an ActiveParticipant
288
+ # instance when just consuming workitems (that an active participant
289
+ # pushed in the database).
290
+ #
291
+ def reply (engine)
292
+
293
+ engine.reply(self.as_owfe_workitem)
294
+ self.destroy
295
+ end
296
+
297
+ alias :forward :reply
298
+ alias :proceed :reply
299
+
300
+ #
301
+ # Simply sets the 'last_modified' field to now.
302
+ # (Doesn't save the workitem though).
303
+ #
304
+ def touch
305
+
306
+ self.last_modified = Time.now
307
+ end
308
+
309
+ #
310
+ # Opening engine to update its reply method to accept these
311
+ # active record workitems.
312
+ #
313
+ class OpenWFE::Engine
314
+
315
+ alias :oldreply :reply
316
+
317
+ def reply (workitem)
318
+
319
+ if workitem.is_a?(Workitem)
320
+
321
+ workitem.destroy
322
+ oldreply(workitem.as_owfe_workitem)
323
+ else
324
+
325
+ oldreply(workitem)
326
+ end
327
+ end
328
+
329
+ alias :forward :reply
330
+ alias :proceed :reply
331
+ end
332
+
333
+ #
334
+ # Returns all the workitems belonging to the stores listed
335
+ # in the parameter storename_list.
336
+ # The result is a Hash whose keys are the store names and whose
337
+ # values are list of workitems.
338
+ #
339
+ def self.find_in_stores (storename_list)
340
+
341
+ workitems = find_all_by_store_name(storename_list)
342
+
343
+ result = {}
344
+
345
+ workitems.each do |wi|
346
+ (result[wi.store_name] ||= []) << wi
347
+ end
348
+
349
+ result
350
+ end
351
+
352
+ #
353
+ # Some kind of 'google search' among workitems
354
+ #
355
+ # == Note
356
+ #
357
+ # when this is used on compact_workitems, it will not be able to search
358
+ # info within the fields, because they aren't used by this kind of
359
+ # workitems. In this case the search will be limited to participant_name
360
+ #
361
+ def self.search (search_string, storename_list=nil)
362
+
363
+ #t = OpenWFE::Timer.new
364
+
365
+ storename_list = Array(storename_list) if storename_list
366
+
367
+ # participant_name
368
+
369
+ result = find(
370
+ :all,
371
+ :conditions => conditions(
372
+ 'participant_name', search_string, storename_list),
373
+ :order => 'participant_name')
374
+ # :limit => 10)
375
+
376
+ ids = result.collect { |wi| wi.id }
377
+
378
+ # search in fields
379
+
380
+ fields = Field.search(search_string, storename_list)
381
+ merge_search_results(ids, result, fields)
382
+
383
+ #puts "... took #{t.duration} ms"
384
+
385
+ # over.
386
+
387
+ result
388
+ end
389
+
390
+ #
391
+ # Not really about 'just launched', but rather about finding the first
392
+ # workitem for a given process instance (wfid) and a participant.
393
+ # It deserves its own method because the workitem could be in a
394
+ # subprocess, thus escaping the vanilla find_by_wfid_and_participant()
395
+ #
396
+ def self.find_just_launched (wfid, participant_name)
397
+
398
+ find(
399
+ :first,
400
+ :conditions => [
401
+ "wfid LIKE ? AND participant_name = ?",
402
+ "#{wfid}%",
403
+ participant_name ])
404
+ end
405
+
406
+ protected
407
+
408
+ #
409
+ # builds the condition (the WHERE clause) for the
410
+ # search.
411
+ #
412
+ def self.conditions (keyname, search_string, storename_list)
413
+
414
+ cs = [ "#{keyname} LIKE ?", search_string ]
415
+
416
+ if storename_list
417
+
418
+ cs[0] = "#{cs[0]} AND workitems.store_name IN (?)"
419
+ cs << storename_list
420
+ end
421
+
422
+ cs
423
+ end
424
+
425
+ def self.merge_search_results (ids, wis, new_wis)
426
+
427
+ return if new_wis.size < 1
428
+
429
+ new_wis.each do |wi|
430
+ wi = wi.workitem if wi.kind_of?(Field)
431
+ next if ids.include? wi.id
432
+ ids << wi.id
433
+ wis << wi
434
+ end
435
+ end
436
+ end
437
+
438
+ #
439
+ # A workaround is in place for some classes when then have to get
440
+ # serialized. The names of thoses classes are listed in this array.
441
+ #
442
+ SPECIAL_FIELD_CLASSES = %w{ Time Date DateTime TrueClass FalseClass }
443
+
444
+ #
445
+ # A Field (Attribute) of a Workitem.
446
+ #
447
+ class Field < ActiveRecord::Base
448
+
449
+ def connection
450
+ ActiveRecord::Base.verify_active_connections!
451
+ super
452
+ end
453
+
454
+ belongs_to :workitem, :class_name => 'OpenWFE::Extras::Workitem'
455
+
456
+ serialize :yvalue
457
+
458
+ #
459
+ # A quick method for doing
460
+ #
461
+ # f = Field.new
462
+ # f.key = key
463
+ # f.value = value
464
+ #
465
+ # One can then quickly add fields to an [active] workitem via :
466
+ #
467
+ # wi.fields << Field.new_field("toto", "b")
468
+ #
469
+ # This method does not save the new Field.
470
+ #
471
+ def self.new_field (key, value)
472
+
473
+ Field.new(:fkey => key, :vclass => value.class.to_s, :value => value)
474
+ end
475
+
476
+ def value= (v)
477
+
478
+ limit = connection.native_database_types[:string][:limit]
479
+
480
+ if v.is_a?(String) and v.length <= limit
481
+
482
+ self.svalue = v
483
+
484
+ elsif SPECIAL_FIELD_CLASSES.include?(v.class.to_s)
485
+
486
+ self.svalue = v.to_yaml
487
+
488
+ else
489
+
490
+ self.yvalue = v
491
+ end
492
+ end
493
+
494
+ def value
495
+
496
+ return YAML.load(self.svalue) \
497
+ if SPECIAL_FIELD_CLASSES.include?(self.vclass)
498
+
499
+ self.svalue || self.yvalue
500
+ end
501
+
502
+ #
503
+ # Will return all the fields that contain the given text.
504
+ #
505
+ # Looks in svalue and fkey. Looks as well in yvalue if it contains
506
+ # a string.
507
+ #
508
+ # This method is used by Workitem.search()
509
+ #
510
+ def self.search (text, storename_list=nil)
511
+
512
+ cs = build_search_conditions(text)
513
+
514
+ if storename_list
515
+
516
+ cs[0] = "(#{cs[0]}) AND workitems.store_name IN (?)"
517
+ cs << storename_list
518
+ end
519
+
520
+ find(:all, :conditions => cs, :include => :workitem)
521
+ end
522
+
523
+ protected
524
+
525
+ #
526
+ # The search operates on the content of these columns
527
+ #
528
+ FIELDS_TO_SEARCH = %w{ svalue fkey yvalue }
529
+
530
+ #
531
+ # Builds the condition array for a pseudo text search
532
+ #
533
+ def self.build_search_conditions (text)
534
+
535
+ has_percent = (text.index('%') != nil)
536
+
537
+ conds = []
538
+
539
+ conds << FIELDS_TO_SEARCH.collect { |key|
540
+
541
+ count = has_percent ? 1 : 4
542
+
543
+ s = ([ "#{key} LIKE ?" ] * count).join(" OR ")
544
+
545
+ s = "(vclass = ? AND (#{s}))" if key == 'yvalue'
546
+
547
+ s
548
+ }.join(' OR ')
549
+
550
+ FIELDS_TO_SEARCH.each do |key|
551
+
552
+ conds << 'String' if key == 'yvalue'
553
+
554
+ conds << text
555
+
556
+ unless has_percent
557
+ conds << "% #{text} %"
558
+ conds << "% #{text}"
559
+ conds << "#{text} %"
560
+ end
561
+ end
562
+
563
+ conds
564
+ end
565
+ end
566
+
567
+
568
+ #
569
+ # A basic 'ActiveParticipant'.
570
+ # A store participant whose store is a set of ActiveRecord tables.
571
+ #
572
+ # Sample usage :
573
+ #
574
+ # class MyDefinition < OpenWFE::ProcessDefinition
575
+ # sequence do
576
+ # active0
577
+ # active1
578
+ # end
579
+ # end
580
+ #
581
+ # def play_with_the_engine
582
+ #
583
+ # engine = OpenWFE::Engine.new
584
+ #
585
+ # engine.register_participant(
586
+ # :active0, OpenWFE::Extras::ActiveParticipant)
587
+ # engine.register_participant(
588
+ # :active1, OpenWFE::Extras::ActiveParticipant)
589
+ #
590
+ # li = OpenWFE::LaunchItem.new(MyDefinition)
591
+ # li.customer_name = 'toto'
592
+ # engine.launch li
593
+ #
594
+ # sleep 0.500
595
+ # # give some slack to the engine, it's asynchronous after all
596
+ #
597
+ # wi = OpenWFE::Extras::Workitem.find_by_participant_name("active0")
598
+ #
599
+ # # ...
600
+ # end
601
+ #
602
+ # == Compact workitems
603
+ #
604
+ # It is possible to save all the workitem data into a single table,
605
+ # the workitems table, without
606
+ # splitting info between workitems and fields tables.
607
+ #
608
+ # You can configure the "compact_workitems" behavior by adding to the
609
+ # previous lines:
610
+ #
611
+ # active0 = engine.register_participant(
612
+ # :active0, OpenWFE::Extras::ActiveParticipant)
613
+ #
614
+ # active0.compact_workitems = true
615
+ #
616
+ # This behaviour is determined participant per participant, it's ok to
617
+ # have a participant instance that compacts will there is another that
618
+ # doesn't compact.
619
+ #
620
+ class ActiveParticipant
621
+ include OpenWFE::LocalParticipant
622
+
623
+ #
624
+ # when compact_workitems is set to true, the attributes of a workitem
625
+ # are stored in the yattributes column (they are not expanded into
626
+ # the Fields table).
627
+ # By default, workitem attributes are expanded.
628
+ #
629
+ attr :compact_workitems, true
630
+
631
+ #
632
+ # Forces ruote to not spawn a thread when dispatching to this participant.
633
+ #
634
+ def do_not_thread
635
+ true
636
+ end
637
+
638
+ #
639
+ # This is the method called by the OpenWFEru engine to hand a
640
+ # workitem to this participant.
641
+ #
642
+ def consume (workitem)
643
+
644
+ workitem.attributes['compact_workitems'] = true if compact_workitems
645
+
646
+ Workitem.from_owfe_workitem workitem
647
+ # does the 'saving to db'
648
+ end
649
+
650
+ #
651
+ # Called by the engine when the whole process instance (or just the
652
+ # segment of it that sports this participant) is cancelled.
653
+ # Will removed the workitem with the same fei as the cancelitem
654
+ # from the database.
655
+ #
656
+ # No expression will be raised if there is no corresponding workitem.
657
+ #
658
+ def cancel (cancelitem)
659
+
660
+ Workitem.destroy_all([ 'fei = ?', cancelitem.fei.to_s ])
661
+ # note that delete_all was not removing workitem fields
662
+ # probably my fault (bad :has_many setting)
663
+ end
664
+
665
+ #
666
+ # When the activity/work/operation whatever is over and the flow
667
+ # should resume, this is the method to use to hand back the [modified]
668
+ # workitem to the [local] engine.
669
+ #
670
+ def reply_to_engine (workitem)
671
+
672
+ super(workitem.as_owfe_workitem)
673
+ #
674
+ # replies to the workflow engine
675
+
676
+ workitem.destroy
677
+ #
678
+ # removes the workitem from the database
679
+ end
680
+ end
681
+
682
+ #
683
+ # An extension of ActiveParticipant. It has a 'store_name' and it
684
+ # makes sure to flag every workitem it 'consumes' with that name
685
+ # (in its 'store_name' column/field).
686
+ #
687
+ # This is the participant used mainly in 'densha' for human users.
688
+ #
689
+ class ActiveStoreParticipant < ActiveParticipant
690
+ include Enumerable
691
+
692
+ def initialize (store_name)
693
+
694
+ super()
695
+ @store_name = store_name
696
+ end
697
+
698
+ #
699
+ # This is the method called by the OpenWFEru engine to hand a
700
+ # workitem to this participant.
701
+ #
702
+ def consume (workitem)
703
+
704
+ workitem.attributes['compact_workitems'] = true if compact_workitems
705
+
706
+ Workitem.from_owfe_workitem(workitem, @store_name)
707
+ end
708
+
709
+ #
710
+ # Iterates over the workitems currently in this store.
711
+ #
712
+ def each (&block)
713
+
714
+ return unless block
715
+
716
+ wis = Workitem.find_by_store_name(@store_name)
717
+
718
+ wis.each { |wi| block.call(wi) }
719
+ end
720
+ end
721
+
722
+ end
723
+ end
724
+