rbbt-util 5.44.1 → 6.0.4

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 (175) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/bin/rbbt +67 -90
  4. data/bin/rbbt_exec.rb +2 -2
  5. data/etc/app.d/base.rb +2 -2
  6. data/etc/app.d/semaphores.rb +3 -3
  7. data/lib/rbbt/annotations/annotated_array.rb +207 -207
  8. data/lib/rbbt/annotations/refactor.rb +27 -0
  9. data/lib/rbbt/annotations/util.rb +282 -282
  10. data/lib/rbbt/annotations.rb +343 -320
  11. data/lib/rbbt/association/database.rb +200 -225
  12. data/lib/rbbt/association/index.rb +294 -291
  13. data/lib/rbbt/association/item.rb +227 -227
  14. data/lib/rbbt/association/open.rb +35 -34
  15. data/lib/rbbt/association/util.rb +0 -169
  16. data/lib/rbbt/association.rb +2 -4
  17. data/lib/rbbt/entity/identifiers.rb +119 -118
  18. data/lib/rbbt/entity/refactor.rb +12 -0
  19. data/lib/rbbt/entity.rb +319 -315
  20. data/lib/rbbt/hpc/batch.rb +72 -53
  21. data/lib/rbbt/hpc/lsf.rb +2 -2
  22. data/lib/rbbt/hpc/orchestrate/batches.rb +2 -2
  23. data/lib/rbbt/hpc/orchestrate/chains.rb +25 -5
  24. data/lib/rbbt/hpc/orchestrate/rules.rb +2 -2
  25. data/lib/rbbt/hpc/orchestrate.rb +19 -13
  26. data/lib/rbbt/hpc/slurm.rb +18 -18
  27. data/lib/rbbt/knowledge_base/entity.rb +13 -5
  28. data/lib/rbbt/knowledge_base/query.rb +2 -2
  29. data/lib/rbbt/knowledge_base/registry.rb +32 -31
  30. data/lib/rbbt/knowledge_base/traverse.rb +1 -1
  31. data/lib/rbbt/knowledge_base.rb +1 -1
  32. data/lib/rbbt/monitor.rb +36 -25
  33. data/lib/rbbt/persist/refactor.rb +166 -0
  34. data/lib/rbbt/persist/tsv/tokyocabinet.rb +105 -105
  35. data/lib/rbbt/persist/tsv.rb +187 -185
  36. data/lib/rbbt/persist.rb +556 -551
  37. data/lib/rbbt/refactor.rb +20 -0
  38. data/lib/rbbt/resource/path/refactor.rb +178 -0
  39. data/lib/rbbt/resource/path.rb +317 -497
  40. data/lib/rbbt/resource/util.rb +0 -48
  41. data/lib/rbbt/resource.rb +3 -390
  42. data/lib/rbbt/tsv/accessor.rb +2 -838
  43. data/lib/rbbt/tsv/attach.rb +303 -299
  44. data/lib/rbbt/tsv/change_id.rb +244 -245
  45. data/lib/rbbt/tsv/csv.rb +87 -85
  46. data/lib/rbbt/tsv/dumper.rb +2 -100
  47. data/lib/rbbt/tsv/excel.rb +26 -24
  48. data/lib/rbbt/tsv/field_index.rb +4 -1
  49. data/lib/rbbt/tsv/filter.rb +3 -2
  50. data/lib/rbbt/tsv/index.rb +2 -284
  51. data/lib/rbbt/tsv/manipulate.rb +750 -747
  52. data/lib/rbbt/tsv/marshal.rb +3 -3
  53. data/lib/rbbt/tsv/matrix.rb +2 -2
  54. data/lib/rbbt/tsv/parallel/through.rb +2 -1
  55. data/lib/rbbt/tsv/parallel/traverse.rb +783 -781
  56. data/lib/rbbt/tsv/parser.rb +678 -678
  57. data/lib/rbbt/tsv/refactor.rb +195 -0
  58. data/lib/rbbt/tsv/stream.rb +253 -251
  59. data/lib/rbbt/tsv/util.rb +420 -420
  60. data/lib/rbbt/tsv.rb +210 -208
  61. data/lib/rbbt/util/R/eval.rb +4 -4
  62. data/lib/rbbt/util/R/plot.rb +62 -166
  63. data/lib/rbbt/util/R.rb +21 -18
  64. data/lib/rbbt/util/cmd.rb +2 -318
  65. data/lib/rbbt/util/color.rb +269 -269
  66. data/lib/rbbt/util/colorize.rb +89 -89
  67. data/lib/rbbt/util/concurrency/processes/refactor.rb +22 -0
  68. data/lib/rbbt/util/concurrency/processes/worker.rb +2 -2
  69. data/lib/rbbt/util/concurrency/processes.rb +389 -386
  70. data/lib/rbbt/util/config.rb +169 -167
  71. data/lib/rbbt/util/filecache.rb +1 -1
  72. data/lib/rbbt/util/iruby.rb +20 -0
  73. data/lib/rbbt/util/log/progress/report.rb +241 -241
  74. data/lib/rbbt/util/log/progress/util.rb +99 -99
  75. data/lib/rbbt/util/log/progress.rb +102 -102
  76. data/lib/rbbt/util/log/refactor.rb +49 -0
  77. data/lib/rbbt/util/log.rb +486 -532
  78. data/lib/rbbt/util/migrate.rb +2 -2
  79. data/lib/rbbt/util/misc/concurrent_stream.rb +248 -246
  80. data/lib/rbbt/util/misc/development.rb +12 -11
  81. data/lib/rbbt/util/misc/exceptions.rb +117 -112
  82. data/lib/rbbt/util/misc/format.rb +2 -230
  83. data/lib/rbbt/util/misc/indiferent_hash.rb +2 -107
  84. data/lib/rbbt/util/misc/inspect.rb +2 -476
  85. data/lib/rbbt/util/misc/lock.rb +109 -106
  86. data/lib/rbbt/util/misc/omics.rb +9 -1
  87. data/lib/rbbt/util/misc/pipes.rb +765 -793
  88. data/lib/rbbt/util/misc/refactor.rb +20 -0
  89. data/lib/rbbt/util/misc/ssw.rb +27 -17
  90. data/lib/rbbt/util/misc/system.rb +92 -105
  91. data/lib/rbbt/util/misc.rb +39 -20
  92. data/lib/rbbt/util/named_array/refactor.rb +4 -0
  93. data/lib/rbbt/util/named_array.rb +3 -220
  94. data/lib/rbbt/util/open/refactor.rb +7 -0
  95. data/lib/rbbt/util/open.rb +3 -857
  96. data/lib/rbbt/util/procpath.rb +6 -6
  97. data/lib/rbbt/util/python/paths.rb +27 -0
  98. data/lib/rbbt/util/python/run.rb +115 -0
  99. data/lib/rbbt/util/python/script.rb +110 -0
  100. data/lib/rbbt/util/python/util.rb +3 -3
  101. data/lib/rbbt/util/python.rb +22 -81
  102. data/lib/rbbt/util/semaphore.rb +152 -148
  103. data/lib/rbbt/util/simpleopt.rb +9 -8
  104. data/lib/rbbt/util/ssh/refactor.rb +19 -0
  105. data/lib/rbbt/util/ssh.rb +122 -118
  106. data/lib/rbbt/util/tar.rb +117 -115
  107. data/lib/rbbt/util/tmpfile.rb +69 -67
  108. data/lib/rbbt/util/version.rb +2 -0
  109. data/lib/rbbt/workflow/refactor/entity.rb +11 -0
  110. data/lib/rbbt/workflow/refactor/export.rb +66 -0
  111. data/lib/rbbt/workflow/refactor/inputs.rb +24 -0
  112. data/lib/rbbt/workflow/refactor/recursive.rb +64 -0
  113. data/lib/rbbt/workflow/refactor/task_info.rb +66 -0
  114. data/lib/rbbt/workflow/refactor.rb +150 -0
  115. data/lib/rbbt/workflow/remote_workflow/driver/rest.rb +1 -2
  116. data/lib/rbbt/workflow/remote_workflow/driver/ssh.rb +55 -32
  117. data/lib/rbbt/workflow/remote_workflow/remote_step/rest.rb +3 -1
  118. data/lib/rbbt/workflow/remote_workflow/remote_step/ssh.rb +14 -5
  119. data/lib/rbbt/workflow/remote_workflow/remote_step.rb +19 -7
  120. data/lib/rbbt/workflow/remote_workflow.rb +6 -1
  121. data/lib/rbbt/workflow/step/run.rb +766 -766
  122. data/lib/rbbt/workflow/step/save_load_inputs.rb +254 -254
  123. data/lib/rbbt/workflow/step.rb +2 -362
  124. data/lib/rbbt/workflow/task.rb +118 -118
  125. data/lib/rbbt/workflow/usage.rb +289 -287
  126. data/lib/rbbt/workflow/util/archive.rb +6 -5
  127. data/lib/rbbt/workflow/util/data.rb +1 -1
  128. data/lib/rbbt/workflow/util/orchestrator.rb +249 -246
  129. data/lib/rbbt/workflow/util/trace.rb +79 -44
  130. data/lib/rbbt/workflow.rb +4 -882
  131. data/lib/rbbt-util.rb +21 -13
  132. data/lib/rbbt.rb +16 -3
  133. data/python/rbbt/__init__.py +96 -4
  134. data/python/rbbt/workflow/remote.py +104 -0
  135. data/python/rbbt/workflow.py +64 -0
  136. data/python/test.py +10 -0
  137. data/share/Rlib/plot.R +37 -37
  138. data/share/Rlib/svg.R +22 -5
  139. data/share/install/software/lib/install_helpers +1 -1
  140. data/share/rbbt_commands/hpc/list +2 -3
  141. data/share/rbbt_commands/hpc/orchestrate +4 -4
  142. data/share/rbbt_commands/hpc/tail +2 -0
  143. data/share/rbbt_commands/hpc/task +10 -7
  144. data/share/rbbt_commands/lsf/list +2 -3
  145. data/share/rbbt_commands/lsf/orchestrate +4 -4
  146. data/share/rbbt_commands/lsf/tail +2 -0
  147. data/share/rbbt_commands/lsf/task +10 -7
  148. data/share/rbbt_commands/migrate +1 -1
  149. data/share/rbbt_commands/pbs/list +2 -3
  150. data/share/rbbt_commands/pbs/orchestrate +4 -4
  151. data/share/rbbt_commands/pbs/tail +2 -0
  152. data/share/rbbt_commands/pbs/task +10 -7
  153. data/share/rbbt_commands/resource/produce +8 -1
  154. data/share/rbbt_commands/slurm/list +2 -3
  155. data/share/rbbt_commands/slurm/orchestrate +4 -4
  156. data/share/rbbt_commands/slurm/tail +2 -0
  157. data/share/rbbt_commands/slurm/task +10 -7
  158. data/share/rbbt_commands/system/clean +5 -5
  159. data/share/rbbt_commands/system/status +5 -5
  160. data/share/rbbt_commands/tsv/get +2 -3
  161. data/share/rbbt_commands/tsv/info +10 -13
  162. data/share/rbbt_commands/tsv/keys +18 -14
  163. data/share/rbbt_commands/tsv/slice +2 -2
  164. data/share/rbbt_commands/tsv/transpose +6 -2
  165. data/share/rbbt_commands/workflow/info +20 -24
  166. data/share/rbbt_commands/workflow/list +1 -1
  167. data/share/rbbt_commands/workflow/prov +20 -13
  168. data/share/rbbt_commands/workflow/retry +43 -0
  169. data/share/rbbt_commands/workflow/server +12 -2
  170. data/share/rbbt_commands/workflow/task +80 -73
  171. data/share/rbbt_commands/workflow/write_info +26 -9
  172. data/share/software/opt/ssw/ssw.c +861 -0
  173. data/share/software/opt/ssw/ssw.h +130 -0
  174. data/share/workflow_config.ru +3 -3
  175. metadata +45 -6
@@ -1,282 +1,282 @@
1
- require 'json'
2
-
3
- module Annotated
4
-
5
- def self.flatten(array)
6
- return array unless Array === array and not array.empty?
7
- array.extend AnnotatedArray if Annotated === array
8
- return array.flatten if AnnotatedArray === array
9
- begin
10
- return array if array.compact.collect{|e| e.info }.uniq.length > 1
11
- rescue
12
- return array
13
- end
14
- array.compact.first.annotate(array.flatten).tap{|a| a.extend AnnotatedArray }
15
- end
16
-
17
- def self.load_entity(object, info)
18
- annotation_types = info.delete(:annotation_types) || info.delete("annotation_types") || []
19
- annotation_types = annotation_types.split("|") if String === annotation_types
20
-
21
- return object if annotation_types.nil? or annotation_types.empty?
22
-
23
- annotated_array = false
24
- annotated_array = true if (info.delete(:annotated_array) || info.delete("annotated_array")).to_s == "true"
25
- entity_id = info.delete(:entity_id) || info.delete("entity_id")
26
-
27
- annotation_types.each do |mod|
28
- begin
29
- mod = Misc.string2const(mod) if String === mod
30
- object.extend mod unless mod === object
31
- rescue Exception
32
- Log.warn "Exception loading annotation into object: #{$!.message}"
33
- end
34
- end
35
-
36
- object.instance_variable_set(:@annotation_values, info)
37
-
38
- object.instance_variable_set(:@id, entity_id) if entity_id
39
-
40
- object.extend AnnotatedArray if annotated_array and Array === object
41
-
42
- object
43
- end
44
-
45
- def self.resolve_array(entry)
46
- if String === entry && entry =~ /^Array:/
47
- entry["Array:".length..-1].split("|")
48
- else
49
- entry
50
- end
51
- end
52
-
53
- def self.load_info(fields, values)
54
- info = {}
55
- fields.each_with_index do |field,i|
56
- next if field == "literal"
57
- case field
58
- when "JSON"
59
- JSON.parse(values[i]).each do |key, value|
60
- info[key.to_sym] = value
61
- end
62
- when nil
63
- next
64
- else
65
- info[field.to_sym] = resolve_array(values[i])
66
- end
67
- end
68
- info
69
- end
70
-
71
- def self.load_tsv_values(id, values, *fields)
72
- fields = fields.flatten
73
- literal_pos = fields.index "literal"
74
-
75
- object = case
76
- when literal_pos
77
- values[literal_pos].tap{|o| o.force_encoding(Encoding.default_external)}
78
- else
79
- id.dup
80
- end
81
-
82
- object = resolve_array(object)
83
-
84
- if Array === values.first
85
- Misc.zip_fields(values).collect do |v|
86
- info = load_info(fields, v)
87
- end
88
- else
89
- info = load_info(fields, values)
90
- end
91
-
92
- self.load_entity(object, info)
93
-
94
- object
95
- end
96
-
97
- def self.load_tsv(tsv)
98
- tsv.with_unnamed do
99
- annotated_entities = tsv.collect do |id, values|
100
- Annotated.load_tsv_values(id, values, tsv.fields)
101
- end
102
-
103
- case tsv.key_field
104
- when "List"
105
- annotated_entities.first
106
- else
107
- annotated_entities
108
- end
109
- end
110
- end
111
-
112
-
113
- def self.tsv(annotations, *fields)
114
- return nil if annotations.nil?
115
-
116
- fields = case
117
-
118
- when ((fields.compact.empty?) && ! annotations.empty?)
119
- fields = AnnotatedArray === annotations ? annotations.annotations : annotations.compact.first.annotations
120
- fields << :annotation_types
121
-
122
- when (fields == [:literal] and ! annotations.compact.empty?)
123
- fields << :literal
124
-
125
- when (fields == [:all] && Annotated === annotations)
126
- annotation_names = annotations.annotations
127
- annotation_names += annotations.first.annotations if Annotated === annotations.first
128
- fields = [:annotation_types] + annotation_names.uniq
129
- fields << :annotated_array if AnnotatedArray === annotations
130
- fields << :literal
131
-
132
- when (fields == [:all] && ! annotations.compact.empty?)
133
- raise "Input array must be annotated or its elements must be" if not Annotated === annotations.compact.first and not Array === annotations.compact.first
134
- raise "Input array must be annotated or its elements must be. No double arrays of singly annotated entities." if not Annotated === annotations.compact.first and Array === annotations.compact.first
135
- fields = [:annotation_types] + (Annotated === annotations ?
136
- annotations.annotations:
137
- annotations.compact.first.annotations)
138
- fields << :literal
139
-
140
- when annotations.empty?
141
- [:annotation_types, :literal]
142
-
143
- else
144
- fields.flatten
145
-
146
- end
147
-
148
- fields = fields.collect{|f| f.to_s}.uniq
149
-
150
- case
151
- when (Annotated === annotations and not (AnnotatedArray === annotations and annotations.double_array))
152
- tsv = TSV.setup({}, :key_field => "List", :fields => fields, :type => :list, :unnamed => true)
153
-
154
- annot_id = annotations.id
155
- annot_id = annot_id * "," if Array === annot_id
156
- tsv[annot_id] = annotations.tsv_values(*fields).dup
157
-
158
- when Array === annotations
159
- tsv = TSV.setup({}, :key_field => "ID", :fields => fields, :type => :list, :unnamed => true)
160
-
161
- annotations.compact.each_with_index do |annotation,i|
162
- tsv[annotation.id + "#" << i.to_s] = annotation.tsv_values(*fields).dup
163
- end
164
-
165
- else
166
- raise "Annotations need to be an Array to create TSV"
167
- end
168
-
169
- tsv
170
- end
171
-
172
- def tsv_values(*fields)
173
- if Array === self and (not AnnotatedArray === self or self.double_array)
174
- Misc.zip_fields(self.compact.collect{|e| e.tsv_values(fields)})
175
- else
176
- fields = fields.flatten
177
-
178
- info = self.info
179
-
180
- values = []
181
-
182
- fields.each do |field|
183
- values << case
184
-
185
- when Proc === field
186
- field.call(self)
187
-
188
- when field == "JSON"
189
- if AnnotatedArray === self
190
- info.merge(:annotated_array => true).to_json
191
- else
192
- info.to_json
193
- end
194
-
195
- when field == "annotation_types"
196
- annotation_types.collect{|t| t.to_s} * "|"
197
-
198
- when field == "annotated_array"
199
- AnnotatedArray === self
200
-
201
- when field == "literal"
202
- (Array === self ? "Array:" << self * "|" : self).gsub(/\n|\t/, ' ')
203
-
204
- when info.include?(field.to_sym)
205
- res = info[field.to_sym]
206
- Array === res ? "Array:" << res * "|" : res
207
-
208
- when self.respond_to?(field)
209
- res = self.send(field)
210
- Array === res ? "Array:"<< res * "|" : res
211
-
212
- end
213
- end
214
-
215
-
216
- values
217
- end
218
- end
219
-
220
- def self.to_hash(e)
221
- hash = {}
222
- if Array === e && AnnotatedArray === e
223
- hash[:literal] = Annotated.purge(e)
224
- hash[:info] = e.info
225
- elsif Array === e
226
- hash = e.collect do |_e|
227
- _hash = {}
228
- _hash[:literal] = _e.dup
229
- _hash[:info] = _e.info if _e.respond_to?(:info)
230
- _hash
231
- end
232
- else
233
- hash[:literal] = e.dup
234
- hash[:info] = e.info
235
- end
236
- hash
237
- end
238
-
239
- def self.load_hash(hash)
240
- if Array === hash
241
- hash.collect{|h| load_hash(h) }
242
- else
243
- literal = hash[:literal]
244
- info = hash[:info]
245
- info[:annotation_types].each do |type|
246
- type = Kernel.const_get(type) if String === type
247
- type.setup(literal, info)
248
- end
249
- literal
250
- end
251
- end
252
-
253
- def marshal_dump
254
- Annotated.to_hash(self)
255
- end
256
- end
257
-
258
- class String
259
- def marshal_load(hash)
260
- if Hash === hash
261
- e = Annotated.load_hash(hash)
262
- self.replace e
263
- e.annotate(self)
264
- self
265
- else
266
- self.replace hash
267
- end
268
- end
269
- end
270
-
271
- class Array
272
- def marshal_load(hash)
273
- if Hash === hash
274
- e = Annotated.load_hash(hash)
275
- self.replace e
276
- e.annotate(self)
277
- self
278
- else
279
- self.replace hash
280
- end
281
- end
282
- end
1
+ #require 'json'
2
+ #
3
+ #module Annotated
4
+ #
5
+ # def self.flatten(array)
6
+ # return array unless Array === array and not array.empty?
7
+ # array.extend AnnotatedArray if Annotated === array
8
+ # return array.flatten if AnnotatedArray === array
9
+ # begin
10
+ # return array if array.compact.collect{|e| e.info }.uniq.length > 1
11
+ # rescue
12
+ # return array
13
+ # end
14
+ # array.compact.first.annotate(array.flatten).tap{|a| a.extend AnnotatedArray }
15
+ # end
16
+ #
17
+ # def self.load_entity(object, info)
18
+ # annotation_types = info.delete(:annotation_types) || info.delete("annotation_types") || []
19
+ # annotation_types = annotation_types.split("|") if String === annotation_types
20
+ #
21
+ # return object if annotation_types.nil? or annotation_types.empty?
22
+ #
23
+ # annotated_array = false
24
+ # annotated_array = true if (info.delete(:annotated_array) || info.delete("annotated_array")).to_s == "true"
25
+ # entity_id = info.delete(:entity_id) || info.delete("entity_id")
26
+ #
27
+ # annotation_types.each do |mod|
28
+ # begin
29
+ # mod = Misc.string2const(mod) if String === mod
30
+ # object.extend mod unless mod === object
31
+ # rescue Exception
32
+ # Log.warn "Exception loading annotation into object: #{$!.message}"
33
+ # end
34
+ # end
35
+ #
36
+ # object.instance_variable_set(:@annotation_values, info)
37
+ #
38
+ # object.instance_variable_set(:@id, entity_id) if entity_id
39
+ #
40
+ # object.extend AnnotatedArray if annotated_array and Array === object
41
+ #
42
+ # object
43
+ # end
44
+ #
45
+ # def self.resolve_array(entry)
46
+ # if String === entry && entry =~ /^Array:/
47
+ # entry["Array:".length..-1].split("|")
48
+ # else
49
+ # entry
50
+ # end
51
+ # end
52
+ #
53
+ # def self.load_info(fields, values)
54
+ # info = {}
55
+ # fields.each_with_index do |field,i|
56
+ # next if field == "literal"
57
+ # case field
58
+ # when "JSON"
59
+ # JSON.parse(values[i]).each do |key, value|
60
+ # info[key.to_sym] = value
61
+ # end
62
+ # when nil
63
+ # next
64
+ # else
65
+ # info[field.to_sym] = resolve_array(values[i])
66
+ # end
67
+ # end
68
+ # info
69
+ # end
70
+ #
71
+ # def self.load_tsv_values(id, values, *fields)
72
+ # fields = fields.flatten
73
+ # literal_pos = fields.index "literal"
74
+ #
75
+ # object = case
76
+ # when literal_pos
77
+ # values[literal_pos].tap{|o| o.force_encoding(Encoding.default_external)}
78
+ # else
79
+ # id.dup
80
+ # end
81
+ #
82
+ # object = resolve_array(object)
83
+ #
84
+ # if Array === values.first
85
+ # Misc.zip_fields(values).collect do |v|
86
+ # info = load_info(fields, v)
87
+ # end
88
+ # else
89
+ # info = load_info(fields, values)
90
+ # end
91
+ #
92
+ # self.load_entity(object, info)
93
+ #
94
+ # object
95
+ # end
96
+ #
97
+ # def self.load_tsv(tsv)
98
+ # tsv.with_unnamed do
99
+ # annotated_entities = tsv.collect do |id, values|
100
+ # Annotated.load_tsv_values(id, values, tsv.fields)
101
+ # end
102
+ #
103
+ # case tsv.key_field
104
+ # when "List"
105
+ # annotated_entities.first
106
+ # else
107
+ # annotated_entities
108
+ # end
109
+ # end
110
+ # end
111
+ #
112
+ #
113
+ # def self.tsv(annotations, *fields)
114
+ # return nil if annotations.nil?
115
+ #
116
+ # fields = case
117
+ #
118
+ # when ((fields.compact.empty?) && ! annotations.empty?)
119
+ # fields = AnnotatedArray === annotations ? annotations.annotations : annotations.compact.first.annotations
120
+ # fields << :annotation_types
121
+ #
122
+ # when (fields == [:literal] and ! annotations.compact.empty?)
123
+ # fields << :literal
124
+ #
125
+ # when (fields == [:all] && Annotated === annotations)
126
+ # annotation_names = annotations.annotations
127
+ # annotation_names += annotations.first.annotations if Annotated === annotations.first
128
+ # fields = [:annotation_types] + annotation_names.uniq
129
+ # fields << :annotated_array if AnnotatedArray === annotations
130
+ # fields << :literal
131
+ #
132
+ # when (fields == [:all] && ! annotations.compact.empty?)
133
+ # raise "Input array must be annotated or its elements must be" if not Annotated === annotations.compact.first and not Array === annotations.compact.first
134
+ # raise "Input array must be annotated or its elements must be. No double arrays of singly annotated entities." if not Annotated === annotations.compact.first and Array === annotations.compact.first
135
+ # fields = [:annotation_types] + (Annotated === annotations ?
136
+ # annotations.annotations:
137
+ # annotations.compact.first.annotations)
138
+ # fields << :literal
139
+ #
140
+ # when annotations.empty?
141
+ # [:annotation_types, :literal]
142
+ #
143
+ # else
144
+ # fields.flatten
145
+ #
146
+ # end
147
+ #
148
+ # fields = fields.collect{|f| f.to_s}.uniq
149
+ #
150
+ # case
151
+ # when (Annotated === annotations and not (AnnotatedArray === annotations and annotations.double_array))
152
+ # tsv = TSV.setup({}, :key_field => "List", :fields => fields, :type => :list, :unnamed => true)
153
+ #
154
+ # annot_id = annotations.id
155
+ # annot_id = annot_id * "," if Array === annot_id
156
+ # tsv[annot_id] = annotations.tsv_values(*fields).dup
157
+ #
158
+ # when Array === annotations
159
+ # tsv = TSV.setup({}, :key_field => "ID", :fields => fields, :type => :list, :unnamed => true)
160
+ #
161
+ # annotations.compact.each_with_index do |annotation,i|
162
+ # tsv[annotation.id + "#" << i.to_s] = annotation.tsv_values(*fields).dup
163
+ # end
164
+ #
165
+ # else
166
+ # raise "Annotations need to be an Array to create TSV"
167
+ # end
168
+ #
169
+ # tsv
170
+ # end
171
+ #
172
+ # def tsv_values(*fields)
173
+ # if Array === self and (not AnnotatedArray === self or self.double_array)
174
+ # Misc.zip_fields(self.compact.collect{|e| e.tsv_values(fields)})
175
+ # else
176
+ # fields = fields.flatten
177
+ #
178
+ # info = self.info
179
+ #
180
+ # values = []
181
+ #
182
+ # fields.each do |field|
183
+ # values << case
184
+ #
185
+ # when Proc === field
186
+ # field.call(self)
187
+ #
188
+ # when field == "JSON"
189
+ # if AnnotatedArray === self
190
+ # info.merge(:annotated_array => true).to_json
191
+ # else
192
+ # info.to_json
193
+ # end
194
+ #
195
+ # when field == "annotation_types"
196
+ # annotation_types.collect{|t| t.to_s} * "|"
197
+ #
198
+ # when field == "annotated_array"
199
+ # AnnotatedArray === self
200
+ #
201
+ # when field == "literal"
202
+ # (Array === self ? "Array:" << self * "|" : self).gsub(/\n|\t/, ' ')
203
+ #
204
+ # when info.include?(field.to_sym)
205
+ # res = info[field.to_sym]
206
+ # Array === res ? "Array:" << res * "|" : res
207
+ #
208
+ # when self.respond_to?(field)
209
+ # res = self.send(field)
210
+ # Array === res ? "Array:"<< res * "|" : res
211
+ #
212
+ # end
213
+ # end
214
+ #
215
+ #
216
+ # values
217
+ # end
218
+ # end
219
+ #
220
+ # def self.to_hash(e)
221
+ # hash = {}
222
+ # if Array === e && AnnotatedArray === e
223
+ # hash[:literal] = Annotated.purge(e)
224
+ # hash[:info] = e.info
225
+ # elsif Array === e
226
+ # hash = e.collect do |_e|
227
+ # _hash = {}
228
+ # _hash[:literal] = _e.dup
229
+ # _hash[:info] = _e.info if _e.respond_to?(:info)
230
+ # _hash
231
+ # end
232
+ # else
233
+ # hash[:literal] = e.dup
234
+ # hash[:info] = e.info
235
+ # end
236
+ # hash
237
+ # end
238
+ #
239
+ # def self.load_hash(hash)
240
+ # if Array === hash
241
+ # hash.collect{|h| load_hash(h) }
242
+ # else
243
+ # literal = hash[:literal]
244
+ # info = hash[:info]
245
+ # info[:annotation_types].each do |type|
246
+ # type = Kernel.const_get(type) if String === type
247
+ # type.setup(literal, info)
248
+ # end
249
+ # literal
250
+ # end
251
+ # end
252
+ #
253
+ # def marshal_dump
254
+ # Annotated.to_hash(self)
255
+ # end
256
+ #end
257
+ #
258
+ #class String
259
+ # def marshal_load(hash)
260
+ # if Hash === hash
261
+ # e = Annotated.load_hash(hash)
262
+ # self.replace e
263
+ # e.annotate(self)
264
+ # self
265
+ # else
266
+ # self.replace hash
267
+ # end
268
+ # end
269
+ #end
270
+ #
271
+ #class Array
272
+ # def marshal_load(hash)
273
+ # if Hash === hash
274
+ # e = Annotated.load_hash(hash)
275
+ # self.replace e
276
+ # e.annotate(self)
277
+ # self
278
+ # else
279
+ # self.replace hash
280
+ # end
281
+ # end
282
+ #end