rbbt-util 5.5.68 → 5.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rbbt/association.rb +1 -1
  3. data/lib/rbbt/association/index.rb +2 -1
  4. data/lib/rbbt/entity.rb +2 -0
  5. data/lib/rbbt/persist/tsv.rb +46 -232
  6. data/lib/rbbt/persist/tsv/cdb.rb +139 -0
  7. data/lib/rbbt/persist/tsv/kyotocabinet.rb +168 -0
  8. data/lib/rbbt/persist/tsv/leveldb.rb +121 -0
  9. data/lib/rbbt/persist/tsv/lmdb.rb +148 -0
  10. data/lib/rbbt/persist/tsv/tokyocabinet.rb +158 -0
  11. data/lib/rbbt/resource/rake.rb +2 -1
  12. data/lib/rbbt/tsv/accessor.rb +74 -101
  13. data/lib/rbbt/tsv/parser.rb +2 -5
  14. data/lib/rbbt/tsv/serializers.rb +6 -0
  15. data/lib/rbbt/tsv/util.rb +8 -2
  16. data/lib/rbbt/util/R.rb +6 -0
  17. data/lib/rbbt/util/cmd.rb +7 -4
  18. data/lib/rbbt/util/misc.rb +10 -4
  19. data/lib/rbbt/util/open.rb +8 -6
  20. data/lib/rbbt/util/simpleopt.rb +1 -1
  21. data/lib/rbbt/workflow.rb +17 -3
  22. data/lib/rbbt/workflow/accessor.rb +5 -1
  23. data/lib/rbbt/workflow/definition.rb +6 -0
  24. data/lib/rbbt/workflow/step.rb +10 -4
  25. data/lib/rbbt/workflow/task.rb +1 -1
  26. data/share/rbbt_commands/tsv/json +37 -0
  27. data/share/rbbt_commands/workflow/task +8 -2
  28. data/test/rbbt/persist/test_tsv.rb +77 -0
  29. data/test/rbbt/persist/tsv/test_cdb.rb +23 -0
  30. data/test/rbbt/persist/tsv/test_kyotocabinet.rb +33 -0
  31. data/test/rbbt/persist/tsv/test_leveldb.rb +22 -0
  32. data/test/rbbt/persist/tsv/test_lmdb.rb +22 -0
  33. data/test/rbbt/persist/tsv/test_tokyocabinet.rb +242 -0
  34. data/test/rbbt/test_persist.rb +1 -225
  35. data/test/rbbt/test_workflow.rb +0 -1
  36. data/test/rbbt/workflow/test_step.rb +14 -12
  37. data/test/test_helper.rb +4 -2
  38. metadata +20 -4
  39. data/test/rbbt/workflow/test_soap.rb +0 -105
@@ -95,7 +95,7 @@ module SOPT
95
95
  def self.parse(opts)
96
96
  info = {}
97
97
 
98
- opts.split(/:/).each do |opt|
98
+ opts.split(/[:\n]+/).each do |opt|
99
99
  next if opt.strip.empty?
100
100
 
101
101
  short, long = opt.strip.sub(/(^[^\s]*)\*/,'\1').split('--').values_at(0,1)
data/lib/rbbt/workflow.rb CHANGED
@@ -196,9 +196,13 @@ module Workflow
196
196
 
197
197
  dependencies = real_dependencies(task, jobname, inputs, task_dependencies[taskname] || [])
198
198
 
199
- input_values = task.take_input_values(inputs)
200
-
201
- step_path = step_path taskname, jobname, input_values, dependencies
199
+ if inputs.empty?
200
+ step_path = step_path taskname, jobname, [], [], task.extension
201
+ input_values = task.take_input_values(inputs)
202
+ else
203
+ input_values = task.take_input_values(inputs)
204
+ step_path = step_path taskname, jobname, input_values, dependencies, task.extension
205
+ end
202
206
 
203
207
  step = Step.new step_path, task, input_values, dependencies
204
208
 
@@ -258,4 +262,14 @@ module Workflow
258
262
  local_persist_setup
259
263
  local_workdir_setup
260
264
  end
265
+
266
+ def with_workdir(workdir)
267
+ saved = self.workdir
268
+ begin
269
+ self.workdir = Path.setup(File.expand_path(workdir))
270
+ yield
271
+ ensure
272
+ self.workdir = saved
273
+ end
274
+ end
261
275
  end
@@ -281,7 +281,7 @@ module Workflow
281
281
  end
282
282
 
283
283
  TAG = :hash
284
- def step_path(taskname, jobname, inputs, dependencies)
284
+ def step_path(taskname, jobname, inputs, dependencies, extension = nil)
285
285
  Proc.new{
286
286
  raise "Jobname makes an invalid path: #{ jobname }" if jobname =~ /\.\./
287
287
  if inputs.any? or dependencies.any?
@@ -295,6 +295,10 @@ module Workflow
295
295
  tagged_jobname = jobname
296
296
  end
297
297
 
298
+ if extension and not extension.empty?
299
+ tagged_jobname = tagged_jobname + ('.' << extension.to_s)
300
+ end
301
+
298
302
  workdir[taskname][tagged_jobname].find
299
303
  }
300
304
  end
@@ -7,6 +7,7 @@ module Workflow
7
7
  AnnotatedModule.add_consummable_annotation(self,
8
8
  :result_description => "",
9
9
  :result_type => nil,
10
+ :extension => '',
10
11
  :dependencies => [])
11
12
  def helper(name, &block)
12
13
  helpers[name] = block
@@ -16,6 +17,10 @@ module Workflow
16
17
  @description = description
17
18
  end
18
19
 
20
+ def extension(extension)
21
+ @extension = extension
22
+ end
23
+
19
24
  def returns(description)
20
25
  @result_description = description
21
26
  end
@@ -45,6 +50,7 @@ module Workflow
45
50
  :result_type => (Array === type ? type.to_sym : type),
46
51
  :input_defaults => consume_input_defaults,
47
52
  :input_descriptions => consume_input_descriptions,
53
+ :extension => consume_extension,
48
54
  :input_options => consume_input_options
49
55
  }
50
56
 
@@ -92,12 +92,18 @@ class Step
92
92
  self
93
93
  end
94
94
 
95
+ def checks
96
+ deps = rec_dependencies.collect{|dependency| dependency.path }.uniq
97
+ deps.select!{|p| p.exists? }
98
+ end
99
+
95
100
  def run(no_load = false)
96
- result = Persist.persist "Job", @task.result_type, :file => path, :check => rec_dependencies.collect{|dependency| dependency.path }.uniq, :no_load => no_load do
97
- @exec = false
101
+
102
+ result = Persist.persist "Job", @task.result_type, :file => path, :check => checks, :no_load => no_load do
98
103
  if Step === Step.log_relay_step and not self == Step.log_relay_step
99
104
  relay_log(Step.log_relay_step) unless self.respond_to? :relay_step and self.relay_step
100
105
  end
106
+ @exec = false
101
107
 
102
108
  Open.rm info_file if Open.exists? info_file
103
109
 
@@ -149,7 +155,7 @@ class Step
149
155
  backtrace = $!.backtrace
150
156
 
151
157
  # HACK: This fixes an strange behaviour in 1.9.3 where some
152
- # bactrace strings are coded in ASCII-8BIT
158
+ # backtrace strings are coded in ASCII-8BIT
153
159
  backtrace.each{|l| l.force_encoding("UTF-8")} if String.instance_methods.include? :force_encoding
154
160
 
155
161
  set_info :backtrace, backtrace
@@ -251,7 +257,7 @@ class Step
251
257
 
252
258
  def load
253
259
  raise "Can not load: Step is waiting for proces #{@pid} to finish" if not done?
254
- result = Persist.persist "Job", @task.result_type, :file => @path, :check => rec_dependencies.collect{|dependency| dependency.path} do
260
+ result = Persist.persist "Job", @task.result_type, :file => @path, :check => checks do
255
261
  exec
256
262
  end
257
263
  prepare_result result, @task.result_description, info
@@ -2,7 +2,7 @@ require 'rbbt/util/misc'
2
2
  require 'rbbt/persist'
3
3
 
4
4
  module Task
5
- attr_accessor :inputs, :input_types, :result_type, :input_defaults, :input_descriptions, :input_options, :description, :name, :result_description
5
+ attr_accessor :inputs, :input_types, :result_type, :input_defaults, :input_descriptions, :input_options, :description, :name, :result_description, :extension
6
6
 
7
7
  def self.setup(options = {}, &block)
8
8
  block.extend Task
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rbbt-util'
4
+ require 'rbbt/util/simpleopt'
5
+
6
+ options = SOPT.get("-tch--tokyocabinet:-tcb--tokyocabinet_bd:-m--melt:-s--snake_case")
7
+
8
+ file = ARGV.shift
9
+
10
+ case
11
+ when options[:tokyocabinet]
12
+ tsv = Persist.open_tokyocabinet(file, false)
13
+ when options[:tokyocabinet_bd]
14
+ tsv = Persist.open_tokyocabinet(file, false, nil, TokyoCabinet::BDB)
15
+ else
16
+ tsv = TSV.open(Open.open(file))
17
+ end
18
+
19
+ fields = tsv.fields
20
+
21
+ if options[:snake_case]
22
+ tsv.fields = fields = fields.collect{|f| Misc.snake_case f}
23
+ end
24
+
25
+ raise "No fields specified" if fields.nil?
26
+ if options[:melt]
27
+ puts tsv.to_hash.collect{|key, values|
28
+ h = {:key => key}
29
+ fields.zip(values).each do |field, v|
30
+ h[field] = v
31
+ end
32
+ h
33
+ }.to_json
34
+ else
35
+ puts tsv.to_hash.to_json
36
+ end
37
+
@@ -112,6 +112,8 @@ options = SOPT.get <<EOF
112
112
  -rcl--recursive_clean Clean the last step and its dependencies to recompute the job completely:
113
113
  -jn--jobname* Job name to use. The name 'Default' is used by default:
114
114
  -pn--printname Print the name of the job and exit without starting it:
115
+ -wd--workdir* Change the working directory of the workflow:
116
+ -O--output* Save job result into file:
115
117
  --fork Run job asyncronously:
116
118
  EOF
117
119
 
@@ -169,6 +171,8 @@ sopt_option_string = SOPT_options(workflow, task)
169
171
  job_options = SOPT.get sopt_option_string
170
172
  job_options = fix_options(workflow, task, job_options)
171
173
 
174
+ workflow.workdir = Path.setup(File.expand_path(options.delete(:workdir))) if options[:workdir]
175
+
172
176
  #- get job
173
177
 
174
178
  job = workflow.job(task.name, name, job_options)
@@ -226,10 +230,12 @@ rescue ParameterException
226
230
  usage(workflow, task, $!.message)
227
231
  end
228
232
 
233
+ out = options.include?(:output) ? File.open(options[:output], 'wb') : STDOUT
234
+
229
235
  if Step === res
230
- puts Open.read(res.path) if File.exists? res.path
236
+ out.puts Open.read(res.path) if File.exists? res.path
231
237
  else
232
- puts res
238
+ out.puts res
233
239
  end
234
240
 
235
241
  exit 0
@@ -0,0 +1,77 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+ require 'rbbt/persist'
3
+ require 'rbbt/annotations'
4
+ require 'rbbt/util/tmpfile'
5
+ require 'test/unit'
6
+
7
+
8
+
9
+ class TestPersistTSV < Test::Unit::TestCase
10
+ MAX = 100_002
11
+
12
+ def tsv_path
13
+ Random.new
14
+ #require 'rbbt/sources/organism'
15
+ #Organism.identifiers("Hsa")
16
+ require 'rbbt/workflow'
17
+ Workflow.require_workflow "Genomics"
18
+ require 'rbbt/entity/gene'
19
+ require 'rbbt/sources/genomes1000'
20
+ CMD.cmd("grep -v '^\\.\t' | head -n #{MAX}", :in => Genomes1000.mutations.open, :pipe => true)
21
+ end
22
+
23
+ def run_bechmark(file, engine)
24
+ Log.info "Testing #{ Term::ANSIColor.red(engine) }"
25
+ TmpFile.with_file nil, false do |tmp_file|
26
+ db= nil
27
+ Misc.benchmark(1, "Build database with #{MAX - 2} entries") do
28
+ db = TSV.open(file, :fields => [1], :persist => true, :persist_engine => engine, :persist_dir => tmp_file, :type => :single, :unnamed => true)
29
+ fff db
30
+ end
31
+ test = db.keys.sort{rand}[1..100000]
32
+ Misc.benchmark(5, "Access #{test.length} random entries") do
33
+ test.each do |k| db[k] end
34
+ end
35
+ Log.info "Profiling access to #{test.length} random entries"
36
+ Misc.profile :min_percent => 0.1 do
37
+ test.each do |k| db[k] end
38
+ end
39
+ assert_equal "1:10611:G", db["rs189107123"]
40
+ end
41
+ end
42
+
43
+ def test_benchmark_tch
44
+ engine = "HDB"
45
+ run_bechmark(tsv_path, engine)
46
+ end
47
+
48
+ def test_benchmark_tcb
49
+ engine = "BDB"
50
+ run_bechmark(tsv_path, engine)
51
+ end
52
+
53
+ def test_benchmark_kch
54
+ engine = "kch"
55
+ run_bechmark(tsv_path, engine)
56
+ end
57
+
58
+ def test_benchmark_kcb
59
+ engine = "kct"
60
+ run_bechmark(tsv_path, engine)
61
+ end
62
+
63
+ def test_benchmark_cdb
64
+ engine = "CDB"
65
+ run_bechmark(tsv_path, engine)
66
+ end
67
+
68
+ def test_benchmark_leveldb
69
+ engine = "LevelDB"
70
+ run_bechmark(tsv_path, engine)
71
+ end
72
+
73
+ def __test_benchmark_lmdb
74
+ engine = "LMDB"
75
+ run_bechmark(tsv_path, engine)
76
+ end
77
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../test_helper')
2
+ require 'rbbt/persist'
3
+ require 'rbbt/annotations'
4
+ require 'rbbt/util/tmpfile'
5
+ require 'test/unit'
6
+
7
+ module TestAnnotation
8
+ extend Annotation
9
+
10
+ self.annotation :test_annotation
11
+ end
12
+
13
+ class TestPersistTSVCDB < Test::Unit::TestCase
14
+
15
+ def test_organism
16
+ require 'rbbt/sources/organism'
17
+ TmpFile.with_file nil do |tmp_file|
18
+ file = CMD.cmd("head -n 1000000", :in => Organism.identifiers("Hsa").open, :pipe => true)
19
+ tsv = Organism.identifiers("Hsa").tsv(:key_field => "Associated Gene Name", :fields => ["Ensembl Gene ID"], :type => :single, :persist => true, :persist_engine => "CDB", :persist_dir => tmp_file)
20
+ assert_equal "ENSG00000141510", tsv["TP53"]
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../test_helper')
2
+ require 'rbbt/persist'
3
+ require 'rbbt/persist/tsv'
4
+ require 'rbbt/annotations'
5
+ require 'rbbt/util/tmpfile'
6
+ require 'test/unit'
7
+
8
+ require 'rbbt/sources/organism'
9
+
10
+ module TestAnnotation
11
+ extend Annotation
12
+
13
+ self.annotation :test_annotation
14
+ end
15
+
16
+ class TestPersistTSVKC < Test::Unit::TestCase
17
+ def _test_organism_kch
18
+ require 'rbbt/sources/organism'
19
+ TmpFile.with_file do |tmp_file|
20
+ tsv = Organism.identifiers("Hsa").tsv :key_field => "Associated Gene Name", :fields => ["Ensembl Gene ID"], :type => :single, :persist => true, :persist_engine => "kch", :persist_dir => tmp_file
21
+ assert_equal "ENSG00000141510", tsv["TP53"]
22
+ end
23
+ end
24
+
25
+
26
+ def test_organism_kct
27
+ require 'rbbt/sources/organism'
28
+ TmpFile.with_file do |tmp_file|
29
+ tsv = Organism.identifiers("Hsa").tsv :key_field => "Associated Gene Name", :fields => ["Ensembl Gene ID"], :type => :single, :persist => true, :persist_engine => "kct", :persist_dir => tmp_file
30
+ assert_equal "ENSG00000141510", tsv["TP53"]
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../test_helper')
2
+ require 'rbbt/persist'
3
+ require 'rbbt/annotations'
4
+ require 'rbbt/util/tmpfile'
5
+ require 'test/unit'
6
+
7
+ module TestAnnotation
8
+ extend Annotation
9
+
10
+ self.annotation :test_annotation
11
+ end
12
+
13
+ class TestPersistTSVLevelDB < Test::Unit::TestCase
14
+
15
+ def test_organism
16
+ require 'rbbt/sources/organism'
17
+ TmpFile.with_file do |tmp_file|
18
+ tsv = Organism.identifiers("Hsa").tsv :key_field => "Associated Gene Name", :fields => ["Ensembl Gene ID"], :type => :single, :persist => true, :persist_engine => "LevelDB", :persist_dir => tmp_file
19
+ assert_equal "ENSG00000141510", tsv["TP53"]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../test_helper')
2
+ require 'rbbt/persist'
3
+ require 'rbbt/annotations'
4
+ require 'rbbt/util/tmpfile'
5
+ require 'test/unit'
6
+
7
+ module TestAnnotation
8
+ extend Annotation
9
+
10
+ self.annotation :test_annotation
11
+ end
12
+
13
+ class TestPersistTSVLMDB < Test::Unit::TestCase
14
+
15
+ def test_organism
16
+ require 'rbbt/sources/organism'
17
+ TmpFile.with_file do |tmp_file|
18
+ tsv = Organism.identifiers("Hsa").tsv :key_field => "Associated Gene Name", :fields => ["Ensembl Gene ID"], :type => :single, :persist => true, :persist_engine => "LMDB", :persist_dir => tmp_file
19
+ assert_equal "ENSG00000141510", tsv["TP53"]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,242 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../../test_helper')
2
+ require 'rbbt/persist'
3
+ require 'rbbt/annotations'
4
+ require 'rbbt/util/tmpfile'
5
+ require 'test/unit'
6
+
7
+ module TestAnnotation
8
+ extend Annotation
9
+
10
+ self.annotation :test_annotation
11
+ end
12
+
13
+ class TestPersistTSVTC < Test::Unit::TestCase
14
+
15
+ def test_organism
16
+ require 'rbbt/sources/organism'
17
+ TmpFile.with_file do |tmp_file|
18
+ tsv = Organism.identifiers("Hsa").tsv :key_field => "Associated Gene Name", :fields => ["Ensembl Gene ID"], :type => :single, :persist => true, :persist_engine => "HDB", :persist_dir => tmp_file
19
+ assert_equal "ENSG00000141510", tsv["TP53"]
20
+ end
21
+ end
22
+
23
+ def test_annotation_persist
24
+ TmpFile.with_file do |tmp|
25
+ entity1 = "Entity 1"
26
+ entity2 = "Entity 2"
27
+
28
+ TestAnnotation.setup(entity1, :test_annotation => "1")
29
+ TestAnnotation.setup(entity2, :test_annotation => "2")
30
+
31
+ annotations = [entity1, entity2]
32
+
33
+ persisted_annotations = Persist.persist("Test", :annotations, :file => tmp) do
34
+ annotations
35
+ end
36
+
37
+ assert_equal "Entity 1", persisted_annotations.first
38
+ assert_equal "Entity 2", persisted_annotations.last
39
+ assert_equal "1", persisted_annotations.first.test_annotation
40
+ assert_equal "2", persisted_annotations.last.test_annotation
41
+
42
+ persisted_annotations = Persist.persist("Test", :annotations, :file => tmp) do
43
+ annotations
44
+ end
45
+
46
+ assert_equal "Entity 1", persisted_annotations.sort.first
47
+ assert_equal "Entity 2", persisted_annotations.sort.last
48
+ assert_equal "1", persisted_annotations.sort.first.test_annotation
49
+ assert_equal "2", persisted_annotations.sort.last.test_annotation
50
+ end
51
+ end
52
+
53
+ def test_annotation_persist_with_repeitions
54
+ TmpFile.with_file do |tmp|
55
+ entity1 = "Entity 1"
56
+ entity2 = "Entity 2"
57
+ entity2bis = "Entity 2"
58
+
59
+ TestAnnotation.setup(entity1, :test_annotation => "1")
60
+ TestAnnotation.setup(entity2, :test_annotation => "2")
61
+ TestAnnotation.setup(entity2bis, :test_annotation => "2")
62
+
63
+ annotations = [entity1, entity2, entity2bis]
64
+
65
+ persisted_annotations = Persist.persist("Test", :annotations, :file => tmp) do
66
+ annotations
67
+ end
68
+
69
+ assert_equal 3, persisted_annotations.length
70
+
71
+ assert_equal "Entity 1", persisted_annotations.first
72
+ assert_equal "Entity 2", persisted_annotations.last
73
+ assert_equal "1", persisted_annotations.first.test_annotation
74
+ assert_equal "2", persisted_annotations.last.test_annotation
75
+
76
+ persisted_annotations = Persist.persist("Test", :annotations, :file => tmp) do
77
+ annotations
78
+ end
79
+
80
+ assert_equal 3, persisted_annotations.length
81
+
82
+ assert_equal "Entity 1", persisted_annotations.sort.first
83
+ assert_equal "Entity 2", persisted_annotations.sort.last
84
+ assert_equal "1", persisted_annotations.sort.first.test_annotation
85
+ assert_equal "2", persisted_annotations.sort.last.test_annotation
86
+ end
87
+ end
88
+
89
+ def test_bdb
90
+ TmpFile.with_file do |tmp|
91
+ repo = Persist.open_tokyocabinet(tmp, true, :double, TokyoCabinet::BDB)
92
+ repo["test:string1"] = [["STR1"]]
93
+ repo["test:string2"] = [["STR2"]]
94
+ repo["other_test:string3"] = [["STR2"]]
95
+
96
+ assert_equal ["test:string1", "test:string2"].sort, repo.range("test:" << 0.chr, false, "test:" << 255.chr, false).sort
97
+ assert_equal ["other_test:string3"].sort, repo.range("other_test:" << 0.chr, false, "other_test:" << 255.chr, false).sort
98
+ end
99
+ end
100
+
101
+ def test_annotation_persist_repo
102
+ TmpFile.with_file do |tmp|
103
+ repo = Persist.open_tokyocabinet(tmp, true, :list, TokyoCabinet::BDB)
104
+
105
+ entity1 = "Entity 1"
106
+ entity2 = "Entity 2"
107
+
108
+ TestAnnotation.setup(entity1, :test_annotation => "1")
109
+ TestAnnotation.setup(entity2, :test_annotation => "2")
110
+
111
+ annotations = [entity1, entity2]
112
+
113
+ persisted_annotations = Persist.persist("Test", :annotations, :annotation_repo => repo) do
114
+ annotations
115
+ end
116
+
117
+ assert_equal "Entity 1", persisted_annotations.first
118
+ assert_equal "Entity 2", persisted_annotations.last
119
+ assert_equal "1", persisted_annotations.first.test_annotation
120
+ assert_equal "2", persisted_annotations.last.test_annotation
121
+
122
+ persisted_annotations = Persist.persist("Test", :annotations, :annotation_repo => repo) do
123
+ annotations
124
+ end
125
+
126
+ assert_equal "Entity 1", persisted_annotations.sort.first
127
+ assert_equal "Entity 2", persisted_annotations.sort.last
128
+ assert_equal "1", persisted_annotations.sort.first.test_annotation
129
+ assert_equal "2", persisted_annotations.sort.last.test_annotation
130
+ end
131
+ end
132
+
133
+ def test_annotation_persist_repo_annotated_array
134
+ TmpFile.with_file do |tmp|
135
+ repo = Persist.open_tokyocabinet(tmp, true, :list, TokyoCabinet::BDB)
136
+
137
+ entity1 = "Entity 1"
138
+ entity2 = "Entity 2"
139
+
140
+ annotations = [entity1, entity2]
141
+ TestAnnotation.setup(annotations, :test_annotation => "1")
142
+ annotations.extend AnnotatedArray
143
+
144
+ persisted_annotations = Persist.persist("Test", :annotations, :annotation_repo => repo) do
145
+ annotations
146
+ end
147
+
148
+ assert_equal "Entity 1", persisted_annotations.first
149
+ assert_equal "Entity 2", persisted_annotations.last
150
+ assert_equal "1", persisted_annotations.first.test_annotation
151
+ assert_equal "1", persisted_annotations.last.test_annotation
152
+
153
+ persisted_annotations = Persist.persist("Test", :annotations, :annotation_repo => repo) do
154
+ annotations
155
+ end
156
+
157
+ persisted_annotations.extend AnnotatedArray
158
+
159
+ assert_equal "Entity 1", persisted_annotations.sort.first
160
+ assert_equal "Entity 2", persisted_annotations.sort.last
161
+ assert_equal "1", persisted_annotations.sort.first.test_annotation
162
+ assert_equal "1", persisted_annotations.sort.last.test_annotation
163
+ end
164
+ end
165
+
166
+ def test_annotation_persist_repo_triple_array
167
+ TmpFile.with_file(nil, false) do |tmp|
168
+ repo = Persist.open_database(tmp, true, :list, "BDB")
169
+
170
+ entity1 = "Entity 1"
171
+ entity2 = "Entity 2"
172
+
173
+ annotations = [entity1, entity2]
174
+ TestAnnotation.setup(annotations, :test_annotation => "1")
175
+ annotations.extend AnnotatedArray
176
+
177
+ annotations_ary = [annotations]
178
+ TestAnnotation.setup(annotations_ary, :test_annotation => "1")
179
+ annotations_ary.extend AnnotatedArray
180
+
181
+ persisted_annotations = Persist.persist("Test", :annotations, :annotation_repo => repo) do
182
+ annotations_ary
183
+ end
184
+ assert AnnotatedArray === persisted_annotations
185
+
186
+ assert_equal "Entity 1", persisted_annotations.first.first
187
+ assert_equal "Entity 2", persisted_annotations.first.last
188
+ assert_equal "1", persisted_annotations.first.first.test_annotation
189
+ assert_equal "1", persisted_annotations.first.last.test_annotation
190
+
191
+ persisted_annotations = Persist.persist("Test", :annotations, :annotation_repo => repo) do
192
+ annotations_ary
193
+ end
194
+
195
+ assert AnnotatedArray === persisted_annotations
196
+
197
+ assert_equal "Entity 1", persisted_annotations.sort.first.first
198
+ assert_equal "Entity 2", persisted_annotations.sort.first.last
199
+ assert_equal "1", persisted_annotations.sort.first.first.test_annotation
200
+ assert_equal "1", persisted_annotations.sort.first.last.test_annotation
201
+
202
+ end
203
+ end
204
+
205
+ def test_annotation_persist_repo_with_repetitions
206
+ TmpFile.with_file do |tmp|
207
+ repo = Persist.open_tokyocabinet(tmp, true, :list, TokyoCabinet::BDB)
208
+
209
+ entity1 = "Entity 1"
210
+ entity2 = "Entity 2"
211
+ entity2bis = "Entity 2"
212
+
213
+ TestAnnotation.setup(entity1, :test_annotation => "1")
214
+ TestAnnotation.setup(entity2, :test_annotation => "2")
215
+ TestAnnotation.setup(entity2bis, :test_annotation => "2")
216
+
217
+ annotations = [entity1, entity2, entity2bis]
218
+
219
+ persisted_annotations = Persist.persist("Test", :annotations, :annotation_repo => repo) do
220
+ annotations
221
+ end
222
+
223
+ assert_equal 3, persisted_annotations.length
224
+
225
+ assert_equal "Entity 1", persisted_annotations.first
226
+ assert_equal "Entity 2", persisted_annotations.last
227
+ assert_equal "1", persisted_annotations.first.test_annotation
228
+ assert_equal "2", persisted_annotations.last.test_annotation
229
+
230
+ persisted_annotations = Persist.persist("Test", :annotations, :annotation_repo => repo) do
231
+ annotations
232
+ end
233
+
234
+ assert_equal 3, persisted_annotations.length
235
+
236
+ assert_equal "Entity 1", persisted_annotations.sort.first
237
+ assert_equal "Entity 2", persisted_annotations.sort.last
238
+ assert_equal "1", persisted_annotations.sort.first.test_annotation
239
+ assert_equal "2", persisted_annotations.sort.last.test_annotation
240
+ end
241
+ end
242
+ end