stupidedi 1.1.0

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 (500) hide show
  1. data/README.md +215 -0
  2. data/Rakefile +108 -0
  3. data/bin/edi-ed +71 -0
  4. data/bin/edi-pp +81 -0
  5. data/doc/Defining.md +0 -0
  6. data/doc/Generating.md +321 -0
  7. data/doc/LICENSE.md +0 -0
  8. data/doc/Navigating.md +645 -0
  9. data/doc/Parsing.md +0 -0
  10. data/doc/Serializing.md +7 -0
  11. data/doc/Tokenizing.md +0 -0
  12. data/doc/Validating.md +0 -0
  13. data/doc/design/Parser.md +0 -0
  14. data/doc/design/Reader.md +0 -0
  15. data/lib/ruby/array.rb +164 -0
  16. data/lib/ruby/blank.rb +67 -0
  17. data/lib/ruby/enumerable.rb +35 -0
  18. data/lib/ruby/exception.rb +33 -0
  19. data/lib/ruby/hash.rb +4 -0
  20. data/lib/ruby/instance_exec.rb +26 -0
  21. data/lib/ruby/module.rb +79 -0
  22. data/lib/ruby/object.rb +63 -0
  23. data/lib/ruby/string.rb +73 -0
  24. data/lib/ruby/symbol.rb +24 -0
  25. data/lib/ruby/to_d.rb +81 -0
  26. data/lib/ruby/to_date.rb +33 -0
  27. data/lib/ruby/to_time.rb +24 -0
  28. data/lib/ruby/try.rb +43 -0
  29. data/lib/stupidedi/blank_slate.rb +11 -0
  30. data/lib/stupidedi/builder/builder_dsl.rb +281 -0
  31. data/lib/stupidedi/builder/constraint_table.rb +418 -0
  32. data/lib/stupidedi/builder/generation.rb +112 -0
  33. data/lib/stupidedi/builder/instruction.rb +102 -0
  34. data/lib/stupidedi/builder/instruction_table.rb +204 -0
  35. data/lib/stupidedi/builder/navigation.rb +655 -0
  36. data/lib/stupidedi/builder/state_machine.rb +55 -0
  37. data/lib/stupidedi/builder/states/abstract_state.rb +332 -0
  38. data/lib/stupidedi/builder/states/failure_state.rb +69 -0
  39. data/lib/stupidedi/builder/states/functional_group_state.rb +97 -0
  40. data/lib/stupidedi/builder/states/initial_state.rb +63 -0
  41. data/lib/stupidedi/builder/states/interchange_state.rb +94 -0
  42. data/lib/stupidedi/builder/states/loop_state.rb +79 -0
  43. data/lib/stupidedi/builder/states/table_state.rb +96 -0
  44. data/lib/stupidedi/builder/states/transaction_set_state.rb +112 -0
  45. data/lib/stupidedi/builder/states/transmission_state.rb +59 -0
  46. data/lib/stupidedi/builder/tokenization.rb +196 -0
  47. data/lib/stupidedi/builder.rb +23 -0
  48. data/lib/stupidedi/color.rb +93 -0
  49. data/lib/stupidedi/config/code_list_config.rb +42 -0
  50. data/lib/stupidedi/config/editor_config.rb +51 -0
  51. data/lib/stupidedi/config/functional_group_config.rb +62 -0
  52. data/lib/stupidedi/config/interchange_config.rb +79 -0
  53. data/lib/stupidedi/config/transaction_set_config.rb +91 -0
  54. data/lib/stupidedi/config.rb +101 -0
  55. data/lib/stupidedi/editor/00501.rb +341 -0
  56. data/lib/stupidedi/editor/005010/N2.rb +0 -0
  57. data/lib/stupidedi/editor/005010/N3.rb +0 -0
  58. data/lib/stupidedi/editor/005010/N4.rb +63 -0
  59. data/lib/stupidedi/editor/005010/NM1.rb +0 -0
  60. data/lib/stupidedi/editor/005010.rb +469 -0
  61. data/lib/stupidedi/editor/X222-HC837.rb +195 -0
  62. data/lib/stupidedi/editor/abstract_ed.rb +36 -0
  63. data/lib/stupidedi/editor/claim_ack.rb +9 -0
  64. data/lib/stupidedi/editor/implementation_ack.rb +213 -0
  65. data/lib/stupidedi/editor/interchange_ack.rb +9 -0
  66. data/lib/stupidedi/editor/result.rb +100 -0
  67. data/lib/stupidedi/editor/result_set.rb +69 -0
  68. data/lib/stupidedi/editor/transaction_set_ed.rb +275 -0
  69. data/lib/stupidedi/editor/transmission_ed.rb +90 -0
  70. data/lib/stupidedi/editor.rb +37 -0
  71. data/lib/stupidedi/either.rb +287 -0
  72. data/lib/stupidedi/exceptions/invalid_element_error.rb +8 -0
  73. data/lib/stupidedi/exceptions/invalid_schema_error.rb +8 -0
  74. data/lib/stupidedi/exceptions/output_error.rb +8 -0
  75. data/lib/stupidedi/exceptions/parse_error.rb +8 -0
  76. data/lib/stupidedi/exceptions/stupidedi_error.rb +8 -0
  77. data/lib/stupidedi/exceptions/tokenize_error.rb +8 -0
  78. data/lib/stupidedi/exceptions/zipper_error.rb +8 -0
  79. data/lib/stupidedi/exceptions.rb +11 -0
  80. data/lib/stupidedi/guides/005010/X214-HN277.rb +409 -0
  81. data/lib/stupidedi/guides/005010/X221-HP835.rb +613 -0
  82. data/lib/stupidedi/guides/005010/X221A1-HP835.rb +613 -0
  83. data/lib/stupidedi/guides/005010/X222-HC837P.rb +2291 -0
  84. data/lib/stupidedi/guides/005010/X222A1-HC837P.rb +2297 -0
  85. data/lib/stupidedi/guides/005010/X231-FA999.rb +123 -0
  86. data/lib/stupidedi/guides/005010/X231A1-FA999.rb +119 -0
  87. data/lib/stupidedi/guides/005010/element_reqs.rb +38 -0
  88. data/lib/stupidedi/guides/005010/guide_builder.rb +180 -0
  89. data/lib/stupidedi/guides/005010/segment_reqs.rb +32 -0
  90. data/lib/stupidedi/guides/005010.rb +64 -0
  91. data/lib/stupidedi/guides.rb +5 -0
  92. data/lib/stupidedi/inspect.rb +26 -0
  93. data/lib/stupidedi/reader/input/abstract_input.rb +133 -0
  94. data/lib/stupidedi/reader/input/delegated_input.rb +111 -0
  95. data/lib/stupidedi/reader/input/file_input.rb +155 -0
  96. data/lib/stupidedi/reader/input.rb +30 -0
  97. data/lib/stupidedi/reader/position.rb +69 -0
  98. data/lib/stupidedi/reader/result.rb +168 -0
  99. data/lib/stupidedi/reader/segment_dict.rb +175 -0
  100. data/lib/stupidedi/reader/separators.rb +85 -0
  101. data/lib/stupidedi/reader/stream_reader.rb +172 -0
  102. data/lib/stupidedi/reader/token_reader.rb +466 -0
  103. data/lib/stupidedi/reader/tokens/component_element_tok.rb +56 -0
  104. data/lib/stupidedi/reader/tokens/composite_element_tok.rb +64 -0
  105. data/lib/stupidedi/reader/tokens/repeated_element_tok.rb +64 -0
  106. data/lib/stupidedi/reader/tokens/segment_tok.rb +51 -0
  107. data/lib/stupidedi/reader/tokens/simple_element_tok.rb +63 -0
  108. data/lib/stupidedi/reader.rb +121 -0
  109. data/lib/stupidedi/schema/abstract_def.rb +74 -0
  110. data/lib/stupidedi/schema/abstract_use.rb +73 -0
  111. data/lib/stupidedi/schema/code_list.rb +94 -0
  112. data/lib/stupidedi/schema/element_def.rb +173 -0
  113. data/lib/stupidedi/schema/element_req.rb +56 -0
  114. data/lib/stupidedi/schema/element_use.rb +251 -0
  115. data/lib/stupidedi/schema/functional_group_def.rb +114 -0
  116. data/lib/stupidedi/schema/interchange_def.rb +93 -0
  117. data/lib/stupidedi/schema/loop_def.rb +152 -0
  118. data/lib/stupidedi/schema/repeat_count.rb +85 -0
  119. data/lib/stupidedi/schema/segment_def.rb +108 -0
  120. data/lib/stupidedi/schema/segment_req.rb +43 -0
  121. data/lib/stupidedi/schema/segment_use.rb +98 -0
  122. data/lib/stupidedi/schema/syntax_note.rb +63 -0
  123. data/lib/stupidedi/schema/table_def.rb +139 -0
  124. data/lib/stupidedi/schema/transaction_set_def.rb +88 -0
  125. data/lib/stupidedi/schema.rb +28 -0
  126. data/lib/stupidedi/sets/absolute_set.rb +297 -0
  127. data/lib/stupidedi/sets/abstract_set.rb +174 -0
  128. data/lib/stupidedi/sets/null_set.rb +125 -0
  129. data/lib/stupidedi/sets/relative_complement.rb +137 -0
  130. data/lib/stupidedi/sets/relative_set.rb +269 -0
  131. data/lib/stupidedi/sets/universal_set.rb +104 -0
  132. data/lib/stupidedi/sets.rb +57 -0
  133. data/lib/stupidedi/tail_call.rb +109 -0
  134. data/lib/stupidedi/thread_local.rb +174 -0
  135. data/lib/stupidedi/values/abstract_element_val.rb +19 -0
  136. data/lib/stupidedi/values/abstract_val.rb +130 -0
  137. data/lib/stupidedi/values/composite_element_val.rb +95 -0
  138. data/lib/stupidedi/values/functional_group_val.rb +102 -0
  139. data/lib/stupidedi/values/interchange_val.rb +86 -0
  140. data/lib/stupidedi/values/invalid_envelope_val.rb +61 -0
  141. data/lib/stupidedi/values/invalid_segment_val.rb +78 -0
  142. data/lib/stupidedi/values/loop_val.rb +70 -0
  143. data/lib/stupidedi/values/repeated_element_val.rb +105 -0
  144. data/lib/stupidedi/values/segment_val.rb +104 -0
  145. data/lib/stupidedi/values/segment_val_group.rb +20 -0
  146. data/lib/stupidedi/values/simple_element_val.rb +80 -0
  147. data/lib/stupidedi/values/table_val.rb +66 -0
  148. data/lib/stupidedi/values/transaction_set_val.rb +66 -0
  149. data/lib/stupidedi/values/transmission_val.rb +52 -0
  150. data/lib/stupidedi/values.rb +21 -0
  151. data/lib/stupidedi/version.rb +3 -0
  152. data/lib/stupidedi/versions/functional_groups/004010/element_defs.rb +54 -0
  153. data/lib/stupidedi/versions/functional_groups/004010/element_reqs.rb +18 -0
  154. data/lib/stupidedi/versions/functional_groups/004010/element_types/date_val.rb +527 -0
  155. data/lib/stupidedi/versions/functional_groups/004010/element_types/fixnum_val.rb +335 -0
  156. data/lib/stupidedi/versions/functional_groups/004010/element_types/float_val.rb +299 -0
  157. data/lib/stupidedi/versions/functional_groups/004010/element_types/identifier_val.rb +287 -0
  158. data/lib/stupidedi/versions/functional_groups/004010/element_types/string_val.rb +338 -0
  159. data/lib/stupidedi/versions/functional_groups/004010/element_types/time_val.rb +309 -0
  160. data/lib/stupidedi/versions/functional_groups/004010/element_types.rb +124 -0
  161. data/lib/stupidedi/versions/functional_groups/004010/functional_group_def.rb +30 -0
  162. data/lib/stupidedi/versions/functional_groups/004010/segment_defs/GE.rb +20 -0
  163. data/lib/stupidedi/versions/functional_groups/004010/segment_defs/GS.rb +27 -0
  164. data/lib/stupidedi/versions/functional_groups/004010/segment_defs/SE.rb +20 -0
  165. data/lib/stupidedi/versions/functional_groups/004010/segment_defs/ST.rb +20 -0
  166. data/lib/stupidedi/versions/functional_groups/004010/segment_defs.rb +23 -0
  167. data/lib/stupidedi/versions/functional_groups/004010/segment_reqs.rb +18 -0
  168. data/lib/stupidedi/versions/functional_groups/004010/syntax_notes.rb +174 -0
  169. data/lib/stupidedi/versions/functional_groups/004010.rb +38 -0
  170. data/lib/stupidedi/versions/functional_groups/005010/element_defs.rb +1405 -0
  171. data/lib/stupidedi/versions/functional_groups/005010/element_reqs.rb +18 -0
  172. data/lib/stupidedi/versions/functional_groups/005010/element_types/date_val.rb +577 -0
  173. data/lib/stupidedi/versions/functional_groups/005010/element_types/fixnum_val.rb +322 -0
  174. data/lib/stupidedi/versions/functional_groups/005010/element_types/float_val.rb +354 -0
  175. data/lib/stupidedi/versions/functional_groups/005010/element_types/identifier_val.rb +368 -0
  176. data/lib/stupidedi/versions/functional_groups/005010/element_types/operators.rb +117 -0
  177. data/lib/stupidedi/versions/functional_groups/005010/element_types/string_val.rb +398 -0
  178. data/lib/stupidedi/versions/functional_groups/005010/element_types/time_val.rb +327 -0
  179. data/lib/stupidedi/versions/functional_groups/005010/element_types.rb +132 -0
  180. data/lib/stupidedi/versions/functional_groups/005010/functional_group_def.rb +30 -0
  181. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AK1.rb +21 -0
  182. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AK2.rb +21 -0
  183. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AK9.rb +28 -0
  184. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AMT.rb +21 -0
  185. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/BHT.rb +24 -0
  186. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/BPR.rb +49 -0
  187. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CAS.rb +56 -0
  188. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CL1.rb +22 -0
  189. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CLM.rb +41 -0
  190. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CLP.rb +34 -0
  191. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CN1.rb +24 -0
  192. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CR1.rb +32 -0
  193. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CR2.rb +35 -0
  194. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CR3.rb +25 -0
  195. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CRC.rb +26 -0
  196. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CTP.rb +36 -0
  197. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CTX.rb +24 -0
  198. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CUR.rb +57 -0
  199. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DMG.rb +34 -0
  200. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DN1.rb +22 -0
  201. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DN2.rb +24 -0
  202. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DTM.rb +24 -0
  203. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DTP.rb +21 -0
  204. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/FRM.rb +25 -0
  205. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/GE.rb +20 -0
  206. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/GS.rb +27 -0
  207. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/HCP.rb +39 -0
  208. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/HI.rb +31 -0
  209. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/HL.rb +22 -0
  210. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/IK3.rb +22 -0
  211. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/IK4.rb +22 -0
  212. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/IK5.rb +24 -0
  213. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/K3.rb +21 -0
  214. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/LIN.rb +69 -0
  215. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/LQ.rb +22 -0
  216. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/LX.rb +19 -0
  217. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/MEA.rb +39 -0
  218. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/MIA.rb +45 -0
  219. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/MOA.rb +28 -0
  220. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N1.rb +24 -0
  221. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N2.rb +20 -0
  222. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N3.rb +20 -0
  223. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N4.rb +30 -0
  224. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/NM1.rb +35 -0
  225. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/NTE.rb +20 -0
  226. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/OI.rb +24 -0
  227. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PAT.rb +31 -0
  228. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PER.rb +32 -0
  229. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PLB.rb +40 -0
  230. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PRV.rb +26 -0
  231. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PS1.rb +21 -0
  232. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PWK.rb +30 -0
  233. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/QTY.rb +25 -0
  234. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/RDM.rb +23 -0
  235. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/REF.rb +23 -0
  236. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SBR.rb +28 -0
  237. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SE.rb +20 -0
  238. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/ST.rb +21 -0
  239. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/STC.rb +30 -0
  240. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV1.rb +44 -0
  241. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV2.rb +29 -0
  242. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV3.rb +30 -0
  243. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV5.rb +29 -0
  244. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SVC.rb +26 -0
  245. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SVD.rb +24 -0
  246. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TOO.rb +21 -0
  247. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TRN.rb +22 -0
  248. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TS2.rb +40 -0
  249. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TS3.rb +45 -0
  250. data/lib/stupidedi/versions/functional_groups/005010/segment_defs.rb +227 -0
  251. data/lib/stupidedi/versions/functional_groups/005010/segment_reqs.rb +18 -0
  252. data/lib/stupidedi/versions/functional_groups/005010/syntax_notes.rb +165 -0
  253. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/FA999.rb +38 -0
  254. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HB271.rb +85 -0
  255. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HC837.rb +163 -0
  256. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HI278.rb +64 -0
  257. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HN277.rb +74 -0
  258. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HP835.rb +68 -0
  259. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HR276.rb +57 -0
  260. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HS270.rb +53 -0
  261. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/RA820.rb +240 -0
  262. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs.rb +68 -0
  263. data/lib/stupidedi/versions/functional_groups/005010.rb +38 -0
  264. data/lib/stupidedi/versions/functional_groups.rb +8 -0
  265. data/lib/stupidedi/versions/interchanges/00401/element_defs.rb +224 -0
  266. data/lib/stupidedi/versions/interchanges/00401/interchange_def.rb +45 -0
  267. data/lib/stupidedi/versions/interchanges/00401/segment_defs/IEA.rb +20 -0
  268. data/lib/stupidedi/versions/interchanges/00401/segment_defs/ISA.rb +34 -0
  269. data/lib/stupidedi/versions/interchanges/00401/segment_defs/TA1.rb +23 -0
  270. data/lib/stupidedi/versions/interchanges/00401/segment_defs.rb +28 -0
  271. data/lib/stupidedi/versions/interchanges/00401.rb +23 -0
  272. data/lib/stupidedi/versions/interchanges/00501/element_defs.rb +269 -0
  273. data/lib/stupidedi/versions/interchanges/00501/interchange_def.rb +47 -0
  274. data/lib/stupidedi/versions/interchanges/00501/segment_defs/IEA.rb +20 -0
  275. data/lib/stupidedi/versions/interchanges/00501/segment_defs/ISA.rb +34 -0
  276. data/lib/stupidedi/versions/interchanges/00501/segment_defs/ISB.rb +18 -0
  277. data/lib/stupidedi/versions/interchanges/00501/segment_defs/ISE.rb +18 -0
  278. data/lib/stupidedi/versions/interchanges/00501/segment_defs/TA1.rb +23 -0
  279. data/lib/stupidedi/versions/interchanges/00501/segment_defs/TA3.rb +18 -0
  280. data/lib/stupidedi/versions/interchanges/00501/segment_defs.rb +37 -0
  281. data/lib/stupidedi/versions/interchanges/00501.rb +23 -0
  282. data/lib/stupidedi/versions/interchanges.rb +8 -0
  283. data/lib/stupidedi/versions.rb +6 -0
  284. data/lib/stupidedi/writer/claredi.rb +142 -0
  285. data/lib/stupidedi/writer/default.rb +124 -0
  286. data/lib/stupidedi/writer.rb +6 -0
  287. data/lib/stupidedi/zipper/abstract_cursor.rb +351 -0
  288. data/lib/stupidedi/zipper/dangling_cursor.rb +103 -0
  289. data/lib/stupidedi/zipper/edited_cursor.rb +157 -0
  290. data/lib/stupidedi/zipper/memoized_cursor.rb +131 -0
  291. data/lib/stupidedi/zipper/path.rb +124 -0
  292. data/lib/stupidedi/zipper/root_cursor.rb +120 -0
  293. data/lib/stupidedi/zipper.rb +25 -0
  294. data/lib/stupidedi.rb +66 -0
  295. data/spec/examples/integration/generating.example +551 -0
  296. data/spec/examples/integration/navigating.example +214 -0
  297. data/spec/examples/integration/parsing.example +445 -0
  298. data/spec/examples/ruby/array.example +476 -0
  299. data/spec/examples/ruby/blank.example +62 -0
  300. data/spec/examples/ruby/count.example +68 -0
  301. data/spec/examples/ruby/object.example +99 -0
  302. data/spec/examples/ruby/string.example +111 -0
  303. data/spec/examples/ruby/symbol.example +117 -0
  304. data/spec/examples/ruby/to_d.example +90 -0
  305. data/spec/examples/ruby/try.example +50 -0
  306. data/spec/examples/stupidedi/either.example +375 -0
  307. data/spec/examples/stupidedi/reader/failure.example +68 -0
  308. data/spec/examples/stupidedi/reader/input/delegated_input.example +292 -0
  309. data/spec/examples/stupidedi/reader/separators.example +73 -0
  310. data/spec/examples/stupidedi/reader/stream_reader.example +48 -0
  311. data/spec/examples/stupidedi/reader/success.example +34 -0
  312. data/spec/examples/stupidedi/reader/token_reader.example +775 -0
  313. data/spec/examples/stupidedi/reader.example +168 -0
  314. data/spec/examples/stupidedi/sets/absolute_set.example +1577 -0
  315. data/spec/examples/stupidedi/sets/null_set.example +2 -0
  316. data/spec/examples/stupidedi/sets/relative_set.example +2 -0
  317. data/spec/examples/stupidedi/sets/universal_set.example +1 -0
  318. data/spec/examples/stupidedi/versions/005010/element_types/an.example +201 -0
  319. data/spec/examples/stupidedi/versions/005010/element_types/dt.example +258 -0
  320. data/spec/examples/stupidedi/versions/005010/element_types/id.example +192 -0
  321. data/spec/examples/stupidedi/versions/005010/element_types/nn.example +177 -0
  322. data/spec/examples/stupidedi/versions/005010/element_types/r.example +178 -0
  323. data/spec/examples/stupidedi/versions/005010/element_types/tm.example +2 -0
  324. data/spec/examples/stupidedi/zipper/abstract_cursor.example +417 -0
  325. data/spec/examples/stupidedi/zipper.example +9 -0
  326. data/spec/fixtures/X186-AG824/1-bad.txt +21 -0
  327. data/spec/fixtures/X186-AG824/1-good.txt +17 -0
  328. data/spec/fixtures/X186-AG824/2-bad.txt +26 -0
  329. data/spec/fixtures/X186-AG824/2-good.txt +21 -0
  330. data/spec/fixtures/X186-AG824/3-bad.txt +87 -0
  331. data/spec/fixtures/X186-AG824/3-good.txt +61 -0
  332. data/spec/fixtures/X212-HN277/1-bad.txt +54 -0
  333. data/spec/fixtures/X212-HN277/1-good.txt +46 -0
  334. data/spec/fixtures/X212-HN277/2-bad.txt +37 -0
  335. data/spec/fixtures/X212-HN277/2-good.txt +29 -0
  336. data/spec/fixtures/X212-HN277/3-bad.txt +22 -0
  337. data/spec/fixtures/X212-HN277/3-good.txt +17 -0
  338. data/spec/fixtures/X212-HN277/4-bad.txt +30 -0
  339. data/spec/fixtures/X212-HN277/4-good.txt +24 -0
  340. data/spec/fixtures/X212-HR276/1-bad.txt +53 -0
  341. data/spec/fixtures/X212-HR276/1-good.txt +46 -0
  342. data/spec/fixtures/X212-HR276/2-bad.txt +45 -0
  343. data/spec/fixtures/X212-HR276/2-good.txt +38 -0
  344. data/spec/fixtures/X212-HR276/3-bad.txt +32 -0
  345. data/spec/fixtures/X212-HR276/3-good.txt +26 -0
  346. data/spec/fixtures/X212-HR276/4-bad.txt +32 -0
  347. data/spec/fixtures/X212-HR276/4-good.txt +26 -0
  348. data/spec/fixtures/X214-HN277/1-bad.txt +58 -0
  349. data/spec/fixtures/X214-HN277/1-good.txt +47 -0
  350. data/spec/fixtures/X214-HN277/2-bad.txt +34 -0
  351. data/spec/fixtures/X214-HN277/2-good.txt +22 -0
  352. data/spec/fixtures/X214-HN277/3-bad.txt +64 -0
  353. data/spec/fixtures/X214-HN277/3-good.txt +54 -0
  354. data/spec/fixtures/X214-HN277/4-bad.txt +77 -0
  355. data/spec/fixtures/X214-HN277/4-good.txt +63 -0
  356. data/spec/fixtures/X216-HI278/1-bad.txt +42 -0
  357. data/spec/fixtures/X216-HI278/1-good.txt +27 -0
  358. data/spec/fixtures/X216-HI278/2-bad.txt +43 -0
  359. data/spec/fixtures/X216-HI278/2-good.txt +29 -0
  360. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-1.txt +24 -0
  361. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-1_Clean.txt +20 -0
  362. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-2.txt +46 -0
  363. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-2_Clean.txt +30 -0
  364. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-3.txt +38 -0
  365. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-3_Clean.txt +24 -0
  366. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4a.txt +39 -0
  367. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4a_Clean.txt +24 -0
  368. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4b.txt +43 -0
  369. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4b_Clean.txt +25 -0
  370. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-5.txt +63 -0
  371. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-5_Clean.txt +41 -0
  372. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-6.txt +36 -0
  373. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-6_Clean.txt +20 -0
  374. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-1r.txt +34 -0
  375. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-1r_Clean.txt +23 -0
  376. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-2r.txt +46 -0
  377. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-2r_Clean.txt +31 -0
  378. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-3r.txt +44 -0
  379. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-3r_Clean.txt +26 -0
  380. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-4ar_Clean.txt +28 -0
  381. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-4br_Clean.txt +35 -0
  382. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-5r.txt +60 -0
  383. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-5r_Clean.txt +42 -0
  384. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-6r.txt +40 -0
  385. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-6r_Clean.txt +24 -0
  386. data/spec/fixtures/X218-RA820/1-bad.txt +31 -0
  387. data/spec/fixtures/X218-RA820/1-good.txt +25 -0
  388. data/spec/fixtures/X218-RA820/2-bad.txt +37 -0
  389. data/spec/fixtures/X218-RA820/2-good.txt +29 -0
  390. data/spec/fixtures/X218-RA820/3-bad.txt +29 -0
  391. data/spec/fixtures/X218-RA820/3-good.txt +23 -0
  392. data/spec/fixtures/X218-RA820/4-bad.txt +36 -0
  393. data/spec/fixtures/X218-RA820/4-good.txt +27 -0
  394. data/spec/fixtures/X220-BE834/1-bad.txt +35 -0
  395. data/spec/fixtures/X220-BE834/1-good.txt +29 -0
  396. data/spec/fixtures/X220-BE834/10-bad.txt +26 -0
  397. data/spec/fixtures/X220-BE834/10-good.txt +19 -0
  398. data/spec/fixtures/X220-BE834/2-bad.txt +31 -0
  399. data/spec/fixtures/X220-BE834/2-good.txt +23 -0
  400. data/spec/fixtures/X220-BE834/3-bad.txt +36 -0
  401. data/spec/fixtures/X220-BE834/3-good.txt +26 -0
  402. data/spec/fixtures/X220-BE834/4-bad.txt +27 -0
  403. data/spec/fixtures/X220-BE834/4-good.txt +21 -0
  404. data/spec/fixtures/X220-BE834/5-bad.txt +26 -0
  405. data/spec/fixtures/X220-BE834/5-good.txt +17 -0
  406. data/spec/fixtures/X220-BE834/6-bad.txt +25 -0
  407. data/spec/fixtures/X220-BE834/6-good.txt +20 -0
  408. data/spec/fixtures/X220-BE834/7-bad.txt +25 -0
  409. data/spec/fixtures/X220-BE834/7-good.txt +20 -0
  410. data/spec/fixtures/X220-BE834/8-bad.txt +25 -0
  411. data/spec/fixtures/X220-BE834/8-good.txt +20 -0
  412. data/spec/fixtures/X220-BE834/9-bad.txt +27 -0
  413. data/spec/fixtures/X220-BE834/9-good.txt +21 -0
  414. data/spec/fixtures/X221-HP835/1-bad.txt +58 -0
  415. data/spec/fixtures/X221-HP835/1-good.txt +40 -0
  416. data/spec/fixtures/X221-HP835/2-bad.txt +51 -0
  417. data/spec/fixtures/X221-HP835/2-good.txt +40 -0
  418. data/spec/fixtures/X221-HP835/3a-bad.txt +78 -0
  419. data/spec/fixtures/X221-HP835/3a-good.txt +49 -0
  420. data/spec/fixtures/X221-HP835/3b-bad.txt +60 -0
  421. data/spec/fixtures/X221-HP835/3b-good.txt +32 -0
  422. data/spec/fixtures/X221-HP835/3c-bad.txt +55 -0
  423. data/spec/fixtures/X221-HP835/3c-good.txt +34 -0
  424. data/spec/fixtures/X222-HC837/1-bad.txt +60 -0
  425. data/spec/fixtures/X222-HC837/1-good.txt +53 -0
  426. data/spec/fixtures/X222-HC837/10a-bad.txt +52 -0
  427. data/spec/fixtures/X222-HC837/10a-good.txt +40 -0
  428. data/spec/fixtures/X222-HC837/10b-bad.txt +99 -0
  429. data/spec/fixtures/X222-HC837/10b-good.txt +80 -0
  430. data/spec/fixtures/X222-HC837/10c-bad.txt +105 -0
  431. data/spec/fixtures/X222-HC837/10c-good.txt +80 -0
  432. data/spec/fixtures/X222-HC837/11-bad.txt +69 -0
  433. data/spec/fixtures/X222-HC837/11-good.txt +45 -0
  434. data/spec/fixtures/X222-HC837/12-bad.txt +73 -0
  435. data/spec/fixtures/X222-HC837/12-good.txt +51 -0
  436. data/spec/fixtures/X222-HC837/13-bad.txt +64 -0
  437. data/spec/fixtures/X222-HC837/13-good.txt +46 -0
  438. data/spec/fixtures/X222-HC837/3a-bad.txt +83 -0
  439. data/spec/fixtures/X222-HC837/3a-good.txt +59 -0
  440. data/spec/fixtures/X222-HC837/3b-bad.txt +97 -0
  441. data/spec/fixtures/X222-HC837/3b-good.txt +70 -0
  442. data/spec/fixtures/X222-HC837/3c-bad.txt +95 -0
  443. data/spec/fixtures/X222-HC837/3c-good.txt +74 -0
  444. data/spec/fixtures/X222-HC837/4-bad.txt +67 -0
  445. data/spec/fixtures/X222-HC837/4-good.txt +48 -0
  446. data/spec/fixtures/X222-HC837/5-bad.txt +73 -0
  447. data/spec/fixtures/X222-HC837/5-good.txt +60 -0
  448. data/spec/fixtures/X222-HC837/6-bad.txt +50 -0
  449. data/spec/fixtures/X222-HC837/6-good.txt +39 -0
  450. data/spec/fixtures/X222-HC837/7-bad.txt +93 -0
  451. data/spec/fixtures/X222-HC837/7-good.txt +78 -0
  452. data/spec/fixtures/X222-HC837/8-bad.txt +64 -0
  453. data/spec/fixtures/X222-HC837/8-good.txt +52 -0
  454. data/spec/fixtures/X222-HC837/9-bad.txt +56 -0
  455. data/spec/fixtures/X222-HC837/9-good.txt +38 -0
  456. data/spec/fixtures/X223-HC837/1-bad.txt +66 -0
  457. data/spec/fixtures/X223-HC837/1-good.txt +53 -0
  458. data/spec/fixtures/X223-HC837/2-bad.txt +69 -0
  459. data/spec/fixtures/X223-HC837/2-good.txt +60 -0
  460. data/spec/fixtures/X223-HC837/3-bad.txt +89 -0
  461. data/spec/fixtures/X223-HC837/3-good.txt +61 -0
  462. data/spec/fixtures/X223-HC837/4-bad.txt +60 -0
  463. data/spec/fixtures/X223-HC837/4-good.txt +40 -0
  464. data/spec/fixtures/X223-HC837/5-bad.txt +75 -0
  465. data/spec/fixtures/X223-HC837/5-good.txt +58 -0
  466. data/spec/fixtures/X224-HC837/1-bad.txt +54 -0
  467. data/spec/fixtures/X224-HC837/1-good.txt +44 -0
  468. data/spec/fixtures/X224-HC837/2a-bad.txt +52 -0
  469. data/spec/fixtures/X224-HC837/2a-good.txt +42 -0
  470. data/spec/fixtures/X224-HC837/2b-bad.txt +67 -0
  471. data/spec/fixtures/X224-HC837/2b-good.txt +52 -0
  472. data/spec/fixtures/X224-HC837/3-bad.txt +67 -0
  473. data/spec/fixtures/X224-HC837/3-good.txt +51 -0
  474. data/spec/fixtures/X224-HC837/4-bad.txt +49 -0
  475. data/spec/fixtures/X224-HC837/4-good.txt +40 -0
  476. data/spec/fixtures/X230-FA997/1-bad.txt +19 -0
  477. data/spec/fixtures/X230-FA997/1-good.txt +16 -0
  478. data/spec/fixtures/X231-FA999/1-bad.txt +20 -0
  479. data/spec/fixtures/X231-FA999/1-good.txt +20 -0
  480. data/spec/fixtures/X279-HB271/1-bad.txt +36 -0
  481. data/spec/fixtures/X279-HB271/1-good.txt +30 -0
  482. data/spec/fixtures/X279-HB271/2-bad.txt +22 -0
  483. data/spec/fixtures/X279-HB271/2-good.txt +16 -0
  484. data/spec/fixtures/X279-HB271/3-bad.txt +44 -0
  485. data/spec/fixtures/X279-HB271/3-good.txt +36 -0
  486. data/spec/fixtures/X279-HS270/1-bad.txt +29 -0
  487. data/spec/fixtures/X279-HS270/1-good.txt +23 -0
  488. data/spec/fixtures/X279-HS270/2-bad.txt +32 -0
  489. data/spec/fixtures/X279-HS270/2-good.txt +25 -0
  490. data/spec/spec_helper.rb +34 -0
  491. data/spec/support/fixtures.rb +26 -0
  492. data/spec/support/matchers/either_matchers.rb +26 -0
  493. data/spec/support/matchers/navigation_matchers.rb +247 -0
  494. data/spec/support/node.rb +41 -0
  495. data/spec/support/quickcheck/characters.rb +28 -0
  496. data/spec/support/quickcheck/property.rb +105 -0
  497. data/spec/support/quickcheck/serialized_edi.rb +399 -0
  498. data/spec/support/quickcheck.rb +302 -0
  499. data/spec/support/rcov.rb +34 -0
  500. metadata +577 -0
@@ -0,0 +1,142 @@
1
+ module Stupidedi
2
+ module Writer
3
+
4
+ class Claredi
5
+
6
+ def initialize(node)
7
+ @node = node
8
+ end
9
+
10
+ # @return [String]
11
+ def write(out = "")
12
+ out << "<html><head>\n#{style}</head>\n<body>\n"
13
+ build(@node, out)
14
+ out << "</body></html>"
15
+ end
16
+
17
+ private
18
+
19
+ # @return [String]
20
+ def style
21
+ <<-CSS
22
+ <style>
23
+ body { font-size: 0.75em; }
24
+
25
+ .interchange, .functionalgr, .table, .loop > .label {
26
+ font-weight: bold;
27
+ font-family: Georgia;
28
+ }
29
+
30
+ .interchange, .functionalgr, .transaction {
31
+ margin-left: 1em;
32
+ margin-top: 1em;
33
+ margin-bottom: 1em;
34
+ }
35
+
36
+ .transaction > .label {
37
+ font-weight: bold;
38
+ font-size: 1.5em;
39
+ }
40
+
41
+ .table, .loop {
42
+ margin-top: 0.5em;
43
+ margin-bottom: 0.5em;
44
+ margin-right: 0.5em;
45
+ }
46
+
47
+ .table { margin-left: 1em; margin-bottom: 2em; }
48
+ .table > .label {
49
+ font-size: 1.25em;
50
+ border-bottom: 3px solid black;
51
+ margin-top: 1em;
52
+ margin-bottom: 0.5em;
53
+ }
54
+
55
+ .loop { border: 1px solid grey; border-left: 0; }
56
+ .loop > .label {
57
+ padding: 3px;
58
+ background-color: #ddd;
59
+ }
60
+
61
+ .segment {
62
+ display: inline;
63
+ margin-top: 0.25em;
64
+ background-color: #fff;
65
+ font-weight: normal;
66
+ }
67
+
68
+ .segment > .label {
69
+ font-weight: normal;
70
+ font-family: Consolas, Monospace, monospace;
71
+ }
72
+ </style>
73
+ CSS
74
+ end
75
+
76
+ # @return [void]
77
+ def build(node, out = "")
78
+ if node.element?
79
+
80
+ if node.composite?
81
+ out << "*"
82
+ tmp = ""
83
+ node.children.each{|e| build(e, tmp) }
84
+ tmp.gsub!(/:*$/, "")
85
+ out << tmp
86
+ elsif node.component?
87
+ out << "#{node}:"
88
+ elsif node.repeated?
89
+ out << "^"
90
+ node.children.each{|e| build(e, out) }
91
+ else
92
+ out << "*#{node}"
93
+ end
94
+
95
+ elsif node.segment?
96
+ out << "<div class=segment><div class=label title='#{node.definition.name}'>"
97
+ out << '% 3s' % node.definition.id
98
+ # out << ": #{node.definition.name}</div></div>\n"
99
+ tmp = ""
100
+ node.children.each{|e| build(e, tmp) }
101
+ tmp.gsub!(/\**$/, "")
102
+ out << "#{tmp}~</div></div>\n"
103
+
104
+ elsif node.loop?
105
+ m = /^(\w+) (.+)$/.match(node.definition.id)
106
+ id, name = m.captures
107
+ name = name.split(/\s+/).map(&:capitalize).join(" ")
108
+
109
+ out << "<div class=loop><div class=label>#{name} (#{id})</div>\n"
110
+ node.children.each{|c| build(c, out) }
111
+ out << "</div>\n"
112
+
113
+ elsif node.table?
114
+ out << "<div class=table><div class=label>#{node.definition.id}</div>\n"
115
+ node.children.each{|c| build(c, out) }
116
+ out << "</div>\n"
117
+
118
+ elsif node.transaction_set?
119
+ out << "<div class=transaction><div class=label>Transaction Set #{node.definition.id}</div>\n"
120
+ node.children.each{|c| build(c, out) }
121
+ out << "</div>\n"
122
+
123
+ elsif node.functional_group?
124
+ out << "<div class=functionalgr><div class=label>Functional Group #{node.definition.id}</div>\n"
125
+ node.children.each{|c| build(c, out) }
126
+ out << "</div>\n"
127
+
128
+ elsif node.interchange?
129
+ out << "<div class=interchange><div class=label>Interchange #{node.definition.id}</div>\n"
130
+ node.children.each{|c| build(c, out) }
131
+ out << "</div>\n"
132
+
133
+ elsif node.transmission?
134
+ out << "<div class=transmission>\n"
135
+ node.children.each{|c| build(c, out) }
136
+ out << "</div>\n"
137
+ end
138
+ end
139
+ end
140
+
141
+ end
142
+ end
@@ -0,0 +1,124 @@
1
+ module Stupidedi
2
+ module Writer
3
+
4
+ class Default
5
+
6
+ # @return [Reader::Separators]
7
+ attr_reader :separators
8
+
9
+ def initialize(zipper, separators = Reader::Separators.empty)
10
+ @zipper, @separators =
11
+ zipper, separators
12
+ end
13
+
14
+ #
15
+ # @return out
16
+ def write(out = "")
17
+ common = @separators.characters & @zipper.node.characters
18
+ message = common.to_a.map(&:inspect).join(", ")
19
+
20
+ if common.present?
21
+ raise Exceptions::OutputError,
22
+ "separators #{message} occur as data"
23
+ end
24
+
25
+ recurse(@zipper.node, @separators, out)
26
+ return out
27
+ end
28
+
29
+ private
30
+
31
+ def recurse(value, separators, out)
32
+ return if value.invalid?
33
+
34
+ if value.segment?
35
+ segment(value, separators, out)
36
+ else
37
+ if value.interchange?
38
+ separators = value.separators.merge(@separators)
39
+
40
+ raise Exceptions::OutputError,
41
+ "separators.segment cannot be blank" if separators.segment.empty?
42
+
43
+ raise Exceptions::OutputError,
44
+ "separators.element cannot be blank" if separators.element.blank?
45
+
46
+ unless separators == @separators
47
+ # We've inherited some separators from the interchange,
48
+ # so we need to re-check this condition. Note that we
49
+ # can't optimize this by caching @zipper.node.characters
50
+ # the first time (in #write), because we're only interested
51
+ # in conflicts between _this_ subtree (value) and the
52
+ # separators... not the entire tree (@zipper.node)
53
+ common = separators.characters & @zipper.node.characters
54
+ message = common.to_a.map(&:inspect).join(", ")
55
+
56
+ if common.present?
57
+ raise Exceptions::OutputError,
58
+ "separator characters #{message} occur as data"
59
+ end
60
+ end
61
+ end
62
+
63
+ value.children.each{|c| recurse(c, separators, out) }
64
+ end
65
+ end
66
+
67
+ def segment(s, separators, out)
68
+ # It's likely annoying for the user to need to check for at least
69
+ # one non-blank element before generating a segment. Instead, we
70
+ # can check that after the segment was generated and supress any
71
+ # empty segments here.
72
+ return if s.empty?
73
+
74
+ out << s.id.to_s
75
+
76
+ # Trailing empty elements (including component elements) can be omitted,
77
+ # so "NM1*XX*1:2::::*****~" should be abbreviated to "NM1*XX*1:2~".
78
+ elements = s.children.
79
+ reverse.drop_while(&:empty?).reverse # Remove the trailing empties
80
+
81
+ elements.each do |e|
82
+ out << separators.element
83
+ element(e, separators, out)
84
+ end
85
+
86
+ out << separators.segment
87
+ end
88
+
89
+ def element(e, separators, out)
90
+ if e.simple?
91
+ out << e.to_x12
92
+
93
+ elsif e.composite?
94
+ components = e.children.
95
+ reverse.drop_while(&:empty?).reverse
96
+
97
+ unless components.empty?
98
+ out << components.head.to_x12
99
+ end
100
+
101
+ components.tail.each do |c|
102
+ out << separators.component
103
+ out << c.to_x12
104
+ end
105
+
106
+ elsif e.repeated?
107
+ occurrences = e.children.
108
+ reverse.drop_while(&:empty?).reverse
109
+
110
+ unless occurrences.empty?
111
+ element(occurrences.head, separators, out)
112
+ end
113
+
114
+ occurrences.tail.each do |o|
115
+ out << separators.repetition
116
+ element(occurrences.head, separators, out)
117
+ end
118
+ end
119
+ end
120
+
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,6 @@
1
+ module Stupidedi
2
+ module Writer
3
+ autoload :Claredi, "stupidedi/writer/claredi"
4
+ autoload :Default, "stupidedi/writer/default"
5
+ end
6
+ end
@@ -0,0 +1,351 @@
1
+ module Stupidedi
2
+ module Zipper
3
+
4
+ class AbstractCursor
5
+
6
+ # @return [#leaf?, #children, #copy]
7
+ abstract :node
8
+
9
+ # @return [AbstractPath]
10
+ abstract :path
11
+
12
+ # @group Querying the Tree Location
13
+ #########################################################################
14
+
15
+ # (see AbstractPath#depth)
16
+ def depth
17
+ path.depth
18
+ end
19
+
20
+ # (see AbstractPath#first?)
21
+ def first?
22
+ path.first?
23
+ end
24
+
25
+ # (see AbstractPath#last?)
26
+ def last?
27
+ path.last?
28
+ end
29
+
30
+ # True if the node has no children
31
+ abstract :leaf?
32
+
33
+ # True if the node has no parent
34
+ abstract :root?
35
+
36
+ # Returns nodes between this zipper and the other, including `self.node`
37
+ # and `other.node` as end points. When this and the other zipper point to
38
+ # the same node within the tree, a single node is returned. Otherwise, the
39
+ # nodes are returned in order according to a left-to-right depth-first
40
+ # pre-order traversal.
41
+ #
42
+ # @note This method assumes `other` is a zipper for the same tree as the
43
+ # tree wrapped by `this`. In general, there is no way to know if that is
44
+ # or isn't the case, without comparing the entire tree. If this method
45
+ # is called on two different trees, the results are undefined.
46
+ #
47
+ # @return [Array]
48
+ def between(other)
49
+ # Collect ancestors of self, sorted oldest first (deepest last). This
50
+ # forms a boundary of nodes, which is called a "spine" below
51
+ zipper = self
52
+ lspine = [self]
53
+
54
+ until zipper.root?
55
+ zipper = zipper.up
56
+ lspine.unshift(zipper)
57
+ end
58
+
59
+ # Collect ancestors of self, sorted oldest first (deepest last). This
60
+ # forms a list of boundary nodes, which is called a "spine" below
61
+ zipper = other
62
+ rspine = [other]
63
+
64
+ until zipper.root?
65
+ zipper = zipper.up
66
+ rspine.unshift(zipper)
67
+ end
68
+
69
+ # Now we have two spines, both beginning with the root node. We remove
70
+ # the prefix common to both spines.
71
+ while a = lspine.first and b = rspine.first
72
+ if a.path == b.path
73
+ lspine.shift
74
+ rspine.shift
75
+ else
76
+ break
77
+ end
78
+ end
79
+
80
+ if lspine.empty?
81
+ # The other node is a child of self's node, and rspine contains all
82
+ # the nodes along the path between the two nodes, not including the
83
+ # self node.
84
+ return node.cons(rspine.map(&:node))
85
+
86
+ elsif rspine.empty?
87
+ # Self's node is a child of other's node, and lspine contains all
88
+ # the nodes along the path between the two nodes, not including the
89
+ # other node
90
+ return other.node.cons(lspine.map(&:node))
91
+
92
+ elsif lspine.head.path.position > rspine.head.path.position
93
+ # The first elements of lspine and rspine are siblings that share a
94
+ # common parent. Arrange them such that lspine is on the left, and
95
+ # so rspine is on the right
96
+ lspine, rspine = rspine, lspine
97
+ end
98
+
99
+ between = []
100
+
101
+ # Starting at the bottom of the left spine working upward, accumulate
102
+ # all the nodes to the right of the spine. Remember this is contained
103
+ # within the subtree under lspine.head
104
+ lspine.each{|z| between << z.node }
105
+ lspine.tail.reverse.each do |zipper|
106
+ until zipper.last?
107
+ zipper = zipper.next
108
+ between.concat(zipper.flatten)
109
+ end
110
+ end
111
+
112
+ # For the sibling nodes directly between (not including) lspine.head
113
+ # and rspine.head, we can accumulate the entire subtrees.
114
+ count = rspine.head.path.position - lspine.head.path.position - 1
115
+ zipper = lspine.head
116
+
117
+ count.times do
118
+ zipper = zipper.next
119
+ between.concat(zipper.flatten)
120
+ end
121
+
122
+ between << rspine.head.node
123
+
124
+ rspine.tail.each do |zipper|
125
+ count = zipper.path.position
126
+ zipper = zipper.first
127
+
128
+ # We have to do a bit more work to traverse the siblings in left-to-
129
+ # right order, because `zipper` is now the left spine. We start on
130
+ # the first sibling and move left a fixed number of times
131
+ count.times do
132
+ between.concat(zipper.flatten)
133
+ zipper = zipper.next
134
+ end
135
+
136
+ # Now zipper is along the left spine. We don't expand it here, but the
137
+ # next item in rspine is the next child along the left spine
138
+ between << zipper.node
139
+ end
140
+
141
+ between
142
+ end
143
+
144
+ # Flattens the subtree into an Array of nodes. The nodes are arranged
145
+ # according to a depth-first left-to-right preorder traversal.
146
+ #
147
+ # @return [Array]
148
+ def flatten
149
+ nodes = []
150
+ queue = [node]
151
+
152
+ while node = queue.shift
153
+ nodes << node
154
+ queue.unshift(*node.children) unless node.leaf?
155
+ end
156
+
157
+ nodes
158
+ end
159
+
160
+ # @group Traversing the Tree
161
+ #########################################################################
162
+
163
+ # Navigate to the first child node
164
+ #
165
+ # @return [MemoizedCursor]
166
+ def down
167
+ @__down ||= begin
168
+ if leaf?
169
+ raise Exceptions::ZipperError,
170
+ "cannot descend into leaf node"
171
+ end
172
+
173
+ head, *tail = @node.children
174
+
175
+ MemoizedCursor.new(head,
176
+ Hole.new([], @path, tail), self)
177
+ end
178
+ end
179
+
180
+ # Navigate to the first child node, or if there are no children,
181
+ # create a placeholder where the first child node will be placed
182
+ #
183
+ # @return [AbstractCursor]
184
+ def dangle
185
+ if node.leaf?
186
+ raise Exceptions::ZipperError,
187
+ "cannot descend into leaf node"
188
+ end
189
+
190
+ if leaf?
191
+ DanglingCursor.new(self)
192
+ else
193
+ down
194
+ end
195
+ end
196
+
197
+ # Navigate to the `nth` child node
198
+ #
199
+ # @return [AbstractCursor]
200
+ def child(n)
201
+ if n < 0
202
+ raise Exceptions::ZipperError,
203
+ "child index cannot be negative"
204
+ end
205
+
206
+ cursor = down
207
+ until n.zero?
208
+ cursor = cursor.next
209
+ n -= 1
210
+ end
211
+ cursor
212
+ end
213
+
214
+ # Returns a list of cursors, one pointing to each child node.
215
+ #
216
+ # @return [Array<MemoizedCursor>]
217
+ def children
218
+ children = []
219
+
220
+ unless leaf?
221
+ zipper = down
222
+ children << zipper
223
+
224
+ until zipper.last?
225
+ zipper = zipper.next
226
+ children << zipper
227
+ end
228
+ end
229
+
230
+ children
231
+ end
232
+
233
+ # Recursively descend to each node's `nth` child
234
+ #
235
+ # @return [AbstractCursor]
236
+ def descendant(n, *ns)
237
+ cursor = self
238
+
239
+ n.cons(ns).each do |n|
240
+ cursor = cursor.child(n)
241
+ end
242
+
243
+ cursor
244
+ end
245
+
246
+ # Navigate to the parent node
247
+ #
248
+ # @return [AbstractCursor]
249
+ abstract :up
250
+
251
+ # Navigate to the next (rightward) sibling node
252
+ #
253
+ # @return [AbstractCursor]
254
+ abstract :next
255
+
256
+ # Navigate to the previous (leftward) sibling node
257
+ #
258
+ # @return [AbstractCursor]
259
+ abstract :prev
260
+
261
+ # Navigate to the first (leftmost) sibling node
262
+ #
263
+ # @return [AbstractCursor]
264
+ abstract :first
265
+
266
+ # Navigate to the last (rightmost) sibling node
267
+ #
268
+ # @return [AbstractCursor]
269
+ abstract :last
270
+
271
+ # Navigate to the root node
272
+ #
273
+ # @return [RootCursor]
274
+ def root
275
+ cursor = self
276
+ cursor = cursor.up until cursor.root?
277
+ cursor
278
+ end
279
+
280
+ # @group Editing the Tree
281
+ #########################################################################
282
+
283
+ # Insert a new sibling node after (to the right of) the current node,
284
+ # and navigate to the new sibling node
285
+ #
286
+ # @return [EditedCursor]
287
+ abstract :append, :args => %w(sibling)
288
+
289
+ # Insert a new sibling node before (to the left of) the current node,
290
+ # and navigate to the new sibling node
291
+ #
292
+ # @return [EditedCursor]
293
+ abstract :prepend, :args => %w(sibling)
294
+
295
+ # (see #append)
296
+ def insert_right(sibling)
297
+ append(sibling)
298
+ end
299
+
300
+ # (see #prepend)
301
+ def insert_left(sibling)
302
+ prepend(sibling)
303
+ end
304
+
305
+ # Insert a new child node before (to the left of) any existing children
306
+ # nodes and navigate to the new child node
307
+ #
308
+ # @return [EditedCursor]
309
+ def prepend_child(child)
310
+ if node.leaf?
311
+ raise Exceptions::ZipperError,
312
+ "cannot add child to leaf node"
313
+ end
314
+
315
+ EditedCursor.new(child,
316
+ Hole.new([], path, node.children), self)
317
+ end
318
+
319
+ # Insert a new child node after (to the right of) any existing children
320
+ # nodes and navigate to the new child node
321
+ #
322
+ # @return [EditedCursor]
323
+ def append_child(child)
324
+ if node.leaf?
325
+ raise Exceptions::ZipperError,
326
+ "cannot add child to leaf node"
327
+ end
328
+
329
+ EditedCursor.new(child,
330
+ Hole.new(node.children.reverse, path, []), self)
331
+ end
332
+
333
+ # Replace the current node with the given node
334
+ #
335
+ # @return [AbstractCursor]
336
+ abstract :replace, :args => %w(node)
337
+
338
+ # Remove the current node, and navigate to the next (rightward) node if
339
+ # one exists. Otherwise, navigate to the previous (leftward) node if one
340
+ # exists. Otherwise, create a placeholder where the next sibling node will
341
+ # be created.
342
+ #
343
+ # @return [EditedCursor]
344
+ abstract :delete
345
+
346
+ # @endgroup
347
+ #########################################################################
348
+ end
349
+
350
+ end
351
+ end