rbbt-util 3.2.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +65 -0
- data/bin/run_workflow.rb +142 -69
- data/lib/rbbt-util.rb +3 -3
- data/lib/rbbt.rb +12 -3
- data/lib/rbbt/annotations.rb +215 -0
- data/lib/rbbt/{util/fix_width_table.rb → fix_width_table.rb} +17 -13
- data/lib/rbbt/persist.rb +164 -0
- data/lib/rbbt/persist/tsv.rb +135 -0
- data/lib/rbbt/resource.rb +100 -0
- data/lib/rbbt/resource/path.rb +180 -0
- data/lib/rbbt/resource/rake.rb +48 -0
- data/lib/rbbt/resource/util.rb +111 -0
- data/lib/rbbt/resource/with_key.rb +28 -0
- data/lib/rbbt/tsv.rb +134 -0
- data/lib/rbbt/tsv/accessor.rb +345 -0
- data/lib/rbbt/tsv/attach.rb +183 -0
- data/lib/rbbt/tsv/attach/util.rb +277 -0
- data/lib/rbbt/{util/tsv/filters.rb → tsv/filter.rb} +76 -37
- data/lib/rbbt/tsv/index.rb +453 -0
- data/lib/rbbt/tsv/manipulate.rb +361 -0
- data/lib/rbbt/tsv/parser.rb +231 -0
- data/lib/rbbt/tsv/serializers.rb +79 -0
- data/lib/rbbt/tsv/util.rb +67 -0
- data/lib/rbbt/util/R.rb +3 -3
- data/lib/rbbt/util/chain_methods.rb +64 -0
- data/lib/rbbt/util/cmd.rb +17 -13
- data/lib/rbbt/util/excel2tsv.rb +4 -3
- data/lib/rbbt/util/log.rb +1 -0
- data/lib/rbbt/util/misc.rb +296 -285
- data/lib/rbbt/util/open.rb +9 -2
- data/lib/rbbt/util/persistence.rb +1 -1
- data/lib/rbbt/util/task/job.rb +3 -1
- data/lib/rbbt/workflow.rb +193 -0
- data/lib/rbbt/workflow/accessor.rb +249 -0
- data/lib/rbbt/workflow/annotate.rb +60 -0
- data/lib/rbbt/workflow/soap.rb +100 -0
- data/lib/rbbt/workflow/step.rb +102 -0
- data/lib/rbbt/workflow/task.rb +76 -0
- data/test/rbbt/resource/test_path.rb +12 -0
- data/test/rbbt/test_annotations.rb +106 -0
- data/test/rbbt/{util/test_fix_width_table.rb → test_fix_width_table.rb} +8 -9
- data/test/rbbt/test_resource.rb +66 -0
- data/test/rbbt/test_tsv.rb +332 -0
- data/test/rbbt/test_workflow.rb +102 -0
- data/test/rbbt/tsv/test_accessor.rb +163 -0
- data/test/rbbt/{util/tsv → tsv}/test_attach.rb +86 -43
- data/test/rbbt/{util/tsv/test_filters.rb → tsv/test_filter.rb} +31 -13
- data/test/rbbt/tsv/test_index.rb +284 -0
- data/test/rbbt/{util/tsv → tsv}/test_manipulate.rb +35 -105
- data/test/rbbt/util/test_R.rb +1 -1
- data/test/rbbt/util/test_chain_methods.rb +22 -0
- data/test/rbbt/util/test_filecache.rb +0 -1
- data/test/rbbt/util/test_misc.rb +97 -79
- data/test/rbbt/util/test_open.rb +1 -0
- data/test/rbbt/util/test_tmpfile.rb +1 -1
- data/test/rbbt/workflow/test_soap.rb +103 -0
- data/test/rbbt/workflow/test_step.rb +142 -0
- data/test/rbbt/workflow/test_task.rb +84 -0
- data/test/test_helper.rb +7 -7
- metadata +80 -54
- data/lib/rbbt/util/rake.rb +0 -176
- data/lib/rbbt/util/resource.rb +0 -355
- data/lib/rbbt/util/task.rb +0 -183
- data/lib/rbbt/util/tc_hash.rb +0 -324
- data/lib/rbbt/util/tsv.rb +0 -236
- data/lib/rbbt/util/tsv/accessor.rb +0 -312
- data/lib/rbbt/util/tsv/attach.rb +0 -416
- data/lib/rbbt/util/tsv/index.rb +0 -419
- data/lib/rbbt/util/tsv/manipulate.rb +0 -300
- data/lib/rbbt/util/tsv/misc.rb +0 -41
- data/lib/rbbt/util/tsv/parse.rb +0 -324
- data/lib/rbbt/util/tsv/resource.rb +0 -88
- data/lib/rbbt/util/workflow.rb +0 -135
- data/lib/rbbt/util/workflow/soap.rb +0 -116
- data/test/rbbt/util/test_persistence.rb +0 -201
- data/test/rbbt/util/test_rake.rb +0 -54
- data/test/rbbt/util/test_resource.rb +0 -77
- data/test/rbbt/util/test_task.rb +0 -133
- data/test/rbbt/util/test_tc_hash.rb +0 -144
- data/test/rbbt/util/test_tsv.rb +0 -221
- data/test/rbbt/util/test_workflow.rb +0 -135
- data/test/rbbt/util/tsv/test_accessor.rb +0 -150
- data/test/rbbt/util/tsv/test_index.rb +0 -241
- data/test/rbbt/util/tsv/test_parse.rb +0 -87
- data/test/rbbt/util/tsv/test_resource.rb +0 -9
data/README.rdoc
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
= Install
|
2
|
+
|
3
|
+
1 - install rvm: https://rvm.beginrescueend.com/ (will need git and curl installed)
|
4
|
+
|
5
|
+
:script
|
6
|
+
|
7
|
+
bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
|
8
|
+
cd
|
9
|
+
cat .bash_profile > tmp.bash_profile
|
10
|
+
echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm"' >> tmp.bash_profile
|
11
|
+
cp .bash_profile .bash_profile.save
|
12
|
+
mv tmp.bash_profile .bash_profile
|
13
|
+
. .bash_profile
|
14
|
+
rvm install 1.8.7
|
15
|
+
|
16
|
+
2 - install tokyocabinet (Intructions for user install follow. For system level, make sure we have dev package)
|
17
|
+
1 - download source from http://fallabs.com/tokyocabinet/tokyocabinet-1.4.47.tar.gz
|
18
|
+
2 - unpack and compile using a user-level prefix
|
19
|
+
3 - set LD_RUN_PATH and LD_LIBRARY_PATH to point there
|
20
|
+
|
21
|
+
:script
|
22
|
+
|
23
|
+
cd
|
24
|
+
mkdir -p tmp/tokyocabinet
|
25
|
+
cd tmp/tokyocabinet
|
26
|
+
wget "http://fallabs.com/tokyocabinet/tokyocabinet-1.4.47.tar.gz"
|
27
|
+
tar xvfz tokyocabinet-1.4.47.tar.gz
|
28
|
+
cd tokyocabinet-1.4.47
|
29
|
+
./configure --prefix="$HOME/software/opt/tokyocabinet"
|
30
|
+
make
|
31
|
+
make install
|
32
|
+
cd
|
33
|
+
cat .bash_profile > tmp.bash_profile
|
34
|
+
echo "export LD_RUN_PATH='$LD_RUN_PATH:$HOME/software/opt/tokyocabinet/lib'" >> tmp.bash_profile
|
35
|
+
echo "export LD_LIBRARY_PATH='$LD_LIBRARY_PATH:$HOME/software/opt/tokyocabinet/lib'" >> tmp.bash_profile
|
36
|
+
echo "export PATH='$PATH:$HOME/software/opt/tokyocabinet/bin'" >> tmp.bash_profile
|
37
|
+
cp .bash_profile .bash_profile.save2
|
38
|
+
mv tmp.bash_profile .bash_profile
|
39
|
+
. .bash_profile
|
40
|
+
|
41
|
+
3 - install gems rbbt-util rbbt-sources rbbt-text rbbt-phgx
|
42
|
+
|
43
|
+
:script
|
44
|
+
|
45
|
+
gem install rbbt-util rbbt-sources rbbt-text rbbt-phgx
|
46
|
+
|
47
|
+
3.bis - Or install github repos and make ruby use them
|
48
|
+
|
49
|
+
:script
|
50
|
+
|
51
|
+
cd
|
52
|
+
cd git/
|
53
|
+
git clone git://github.com/mikisvaz/rbbt-util.git
|
54
|
+
git clone git://github.com/mikisvaz/rbbt-sources.git
|
55
|
+
git clone git://github.com/mikisvaz/rbbt-text.git
|
56
|
+
git clone git://github.com/mikisvaz/rbbt-phgx.git
|
57
|
+
alias druby="env RBBT_LOG=0 ruby $(for d in $HOME/git/rbbt-*;do echo -n "-I$d/lib ";done)"
|
58
|
+
alias drake="env RBBT_LOG=0 rake $(for d in $HOME/git/rbbt-*;do echo -n "-I$d/lib ";done)"
|
59
|
+
|
60
|
+
4 - Set up R to find the helper lib
|
61
|
+
|
62
|
+
:script
|
63
|
+
|
64
|
+
echo "source(system('rbbt_Rutil.rb', intern =T));" >> $HOME/.Rprofile
|
65
|
+
|
data/bin/run_workflow.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'rbbt
|
3
|
+
require 'rbbt'
|
4
4
|
require 'rbbt/util/simpleopt'
|
5
|
-
require 'rbbt/
|
5
|
+
require 'rbbt/workflow'
|
6
6
|
require 'pp'
|
7
7
|
|
8
8
|
def usage(task)
|
@@ -10,12 +10,11 @@ def usage(task)
|
|
10
10
|
exit -1
|
11
11
|
end
|
12
12
|
|
13
|
-
def SOPT_options(task)
|
13
|
+
def SOPT_options(workflow, task)
|
14
14
|
sopt_options = []
|
15
|
-
task.
|
16
|
-
name = info[:name]
|
15
|
+
workflow.rec_inputs(task.name).each do |name|
|
17
16
|
short = name.to_s.chars.first
|
18
|
-
boolean =
|
17
|
+
boolean = workflow.rec_input_types(task.name)[name].to_sym == :boolean
|
19
18
|
|
20
19
|
sopt_options << "-#{short}--#{name}#{boolean ? '' : '*'}"
|
21
20
|
end
|
@@ -23,28 +22,54 @@ def SOPT_options(task)
|
|
23
22
|
sopt_options * ":"
|
24
23
|
end
|
25
24
|
|
26
|
-
def fix_options(task, job_options)
|
27
|
-
option_types = task.
|
25
|
+
def fix_options(workflow, task, job_options)
|
26
|
+
option_types = workflow.rec_input_types(task.name)
|
27
|
+
|
28
|
+
workflow.resolve_locals(job_options)
|
28
29
|
|
29
30
|
job_options_cleaned = {}
|
30
31
|
|
31
32
|
job_options.each do |name, value|
|
32
|
-
value = case
|
33
|
-
when
|
33
|
+
value = case option_types[name].to_sym
|
34
|
+
when :float
|
34
35
|
value.to_f
|
35
|
-
when
|
36
|
+
when :integer
|
36
37
|
value.to_i
|
37
|
-
when
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
when :string, :text
|
39
|
+
case
|
40
|
+
when value == '-'
|
41
|
+
STDIN.read
|
42
|
+
when (String === value and File.exists?(value))
|
43
|
+
Open.read(value)
|
44
|
+
else
|
45
|
+
value
|
46
|
+
end
|
47
|
+
when :array
|
48
|
+
if Array === value
|
49
|
+
value
|
50
|
+
else
|
51
|
+
case
|
52
|
+
when value == '-'
|
53
|
+
STDIN.read
|
54
|
+
when (String === value and File.exists?(value))
|
55
|
+
Open.read(value)
|
43
56
|
else
|
44
|
-
|
45
|
-
end
|
46
|
-
|
57
|
+
value
|
58
|
+
end.split(/[,|\s]/)
|
59
|
+
end
|
60
|
+
when :tsv
|
61
|
+
if TSV === value
|
47
62
|
value
|
63
|
+
else
|
64
|
+
begin
|
65
|
+
if value == '-'
|
66
|
+
TSV.open(STDIN).to_s :sort
|
67
|
+
else
|
68
|
+
TSV.new(value).to_s :sort
|
69
|
+
end
|
70
|
+
rescue
|
71
|
+
value
|
72
|
+
end
|
48
73
|
end
|
49
74
|
else
|
50
75
|
value
|
@@ -55,64 +80,112 @@ def fix_options(task, job_options)
|
|
55
80
|
job_options_cleaned
|
56
81
|
end
|
57
82
|
|
58
|
-
options = SOPT.get "-t--task*:-l--log*:-h--help:-n--name
|
83
|
+
options = SOPT.get "-t--task*:-l--log*:-h--help:-n--name*:-cl--clean:-rcl-recursive_clean:-pn--printname:-srv--server"
|
59
84
|
|
60
|
-
# Set log, fork, clean, recursive_clean and help
|
61
|
-
Log.severity = options[:log].to_i if options.include? :log
|
62
|
-
help = !!options.delete(:help)
|
63
|
-
do_fork = !!options.delete(:fork)
|
64
|
-
clean = !!options.delete(:clean)
|
65
|
-
recursive_clean = !!options.delete(:recursive_clean)
|
66
|
-
|
67
|
-
# Get workflow
|
68
85
|
workflow = ARGV.first
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
namespace = Misc.string2const(namespace)
|
86
|
+
|
87
|
+
if options[:server]
|
88
|
+
require 'rbbt/util/log'
|
89
|
+
require 'rbbt/workflow'
|
90
|
+
require 'rbbt/workflow/rest'
|
91
|
+
require 'sinatra'
|
92
|
+
require 'compass'
|
93
|
+
|
94
|
+
Workflow.require_workflow workflow
|
95
|
+
WorkflowREST.add_workflows Workflow.workflows.last
|
96
|
+
|
97
|
+
WorkflowREST.setup
|
82
98
|
else
|
83
|
-
task_name = options.delete(:task)
|
84
|
-
task = self.tasks[task_name]
|
85
|
-
end
|
86
99
|
|
87
|
-
|
100
|
+
# Set log, fork, clean, recursive_clean and help
|
101
|
+
Log.severity = options[:log].to_i if options.include? :log
|
102
|
+
help = !!options.delete(:help)
|
103
|
+
do_fork = !!options.delete(:fork)
|
104
|
+
clean = !!options.delete(:clean)
|
105
|
+
recursive_clean = !!options.delete(:recursive_clean)
|
106
|
+
|
88
107
|
|
89
|
-
|
108
|
+
# Get workflow
|
109
|
+
|
110
|
+
if Rbbt.etc.remote_workflows.exists?
|
111
|
+
remote_workflows = Rbbt.etc.remote_workflows.yaml
|
112
|
+
else
|
113
|
+
remote_workflows = {}
|
114
|
+
end
|
115
|
+
|
116
|
+
if remote_workflows.include? workflow
|
117
|
+
require 'rbbt/workflow/rest/client'
|
118
|
+
workflow = RbbtRestClient.new remote_workflows[workflow]
|
119
|
+
else
|
120
|
+
Workflow.require_workflow workflow
|
121
|
+
workflow = Workflow.workflows.last
|
122
|
+
end
|
123
|
+
|
124
|
+
# Set task
|
125
|
+
namespace, task = nil, nil
|
126
|
+
|
127
|
+
case
|
128
|
+
when (not options[:task])
|
129
|
+
usage if help
|
130
|
+
task = workflow.last_task
|
131
|
+
namespace = workflow
|
132
|
+
when (options[:task] =~ /\./)
|
133
|
+
namespace, task = options.delete(:task).split('.')
|
134
|
+
namespace = Misc.string2const(namespace)
|
135
|
+
else
|
136
|
+
task_name = options.delete(:task)
|
137
|
+
task = workflow.tasks[task_name]
|
138
|
+
raise "Task not found: #{ task_name }" if task.nil?
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
workflow.usage(task) if help
|
90
143
|
|
91
|
-
|
92
|
-
sopt_option_string = SOPT_options(task)
|
93
|
-
job_options = SOPT.get sopt_option_string
|
94
|
-
job_options = fix_options(task, job_options)
|
144
|
+
name = options.delete(:name) || "Default"
|
95
145
|
|
96
|
-
|
97
|
-
|
146
|
+
# get job args
|
147
|
+
sopt_option_string = SOPT_options(workflow,task)
|
148
|
+
job_options = SOPT.get sopt_option_string
|
149
|
+
job_options = fix_options(workflow,task, job_options)
|
98
150
|
|
99
|
-
|
100
|
-
job.
|
101
|
-
job.recursive_clean if recursive_clean
|
151
|
+
#- get job
|
152
|
+
job = workflow.job(task.name, name, job_options)
|
102
153
|
|
103
|
-
#
|
104
|
-
if
|
105
|
-
job.
|
106
|
-
|
107
|
-
|
108
|
-
|
154
|
+
# clean job
|
155
|
+
job.clean if clean
|
156
|
+
job.recursive_clean if recursive_clean
|
157
|
+
|
158
|
+
# run
|
159
|
+
if do_fork
|
160
|
+
job.fork
|
161
|
+
while not job.done?
|
162
|
+
Log.debug "#{job.step}: #{job.messages.last}"
|
163
|
+
sleep 2
|
164
|
+
end
|
165
|
+
raise job.messages.last if job.error?
|
166
|
+
res = job.load
|
167
|
+
else
|
168
|
+
res = job.run
|
109
169
|
end
|
110
|
-
else
|
111
|
-
job.run
|
112
|
-
end
|
113
170
|
|
114
|
-
|
115
|
-
|
171
|
+
if options.delete(:printname)
|
172
|
+
puts job.name
|
173
|
+
exit
|
174
|
+
else
|
175
|
+
Log.low "Job name: #{job.name}"
|
176
|
+
end
|
116
177
|
|
117
|
-
|
118
|
-
|
178
|
+
#- error
|
179
|
+
|
180
|
+
#print
|
181
|
+
case
|
182
|
+
when Array === res
|
183
|
+
puts res * "\n"
|
184
|
+
when TSV === res
|
185
|
+
puts res
|
186
|
+
when Hash === res
|
187
|
+
puts res.to_yaml
|
188
|
+
else
|
189
|
+
puts res
|
190
|
+
end
|
191
|
+
end
|
data/lib/rbbt-util.rb
CHANGED
@@ -3,11 +3,11 @@ require 'rbbt/util/open'
|
|
3
3
|
require 'rbbt/util/cmd'
|
4
4
|
require 'rbbt/util/tmpfile'
|
5
5
|
require 'rbbt/util/filecache'
|
6
|
-
require 'rbbt/
|
7
|
-
require 'rbbt/
|
6
|
+
require 'rbbt/tsv'
|
7
|
+
require 'rbbt/persist'
|
8
8
|
require 'rbbt/util/misc'
|
9
9
|
|
10
10
|
FileCache.cachedir = Rbbt.var.cache.filecache.find :user
|
11
11
|
Open.cachedir = Rbbt.var.cache["open-remote"].find :user
|
12
12
|
TmpFile.tmpdir = Rbbt.tmp.find :user
|
13
|
-
|
13
|
+
Persist.cachedir = Rbbt.var.cache.persistence.find :user
|
data/lib/rbbt.rb
CHANGED
@@ -1,7 +1,16 @@
|
|
1
|
-
require 'rbbt/util/
|
1
|
+
require 'rbbt/util/open'
|
2
|
+
require 'rbbt/util/tmpfile'
|
3
|
+
require 'rbbt/util/filecache'
|
4
|
+
require 'rbbt/tsv'
|
5
|
+
require 'rbbt/persist'
|
6
|
+
require 'rbbt/resource'
|
2
7
|
|
3
8
|
module Rbbt
|
4
9
|
extend Resource
|
5
|
-
|
6
|
-
|
10
|
+
pkgdir = 'rbbt'
|
7
11
|
|
12
|
+
FileCache.cachedir = var.cache.filecache.find :user
|
13
|
+
TmpFile.tmpdir = tmp.find :user
|
14
|
+
Open.cachedir = var.cache["open-remote"].find :user
|
15
|
+
Persist.cachedir = var.cache.persistence.find :user
|
16
|
+
end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
require 'rbbt/util/chain_methods'
|
2
|
+
require 'json'
|
3
|
+
module Annotated
|
4
|
+
attr_accessor :annotation_types
|
5
|
+
|
6
|
+
def self.extended(base)
|
7
|
+
base.annotation_types ||= []
|
8
|
+
end
|
9
|
+
|
10
|
+
def annotations
|
11
|
+
annotation_types.collect do |mod|
|
12
|
+
mod.annotations
|
13
|
+
end.flatten.uniq
|
14
|
+
end
|
15
|
+
|
16
|
+
def info
|
17
|
+
hash = {:annotation_types => annotation_types}
|
18
|
+
annotations.each do |annotation|
|
19
|
+
value = self.send(annotation)
|
20
|
+
hash[annotation] = value unless value.nil?
|
21
|
+
end
|
22
|
+
hash
|
23
|
+
end
|
24
|
+
|
25
|
+
def id
|
26
|
+
Misc.hash2md5 info
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.load(object, info)
|
30
|
+
annotation_types = info[:annotation_types]
|
31
|
+
annotation_types.each do |mod|
|
32
|
+
mod = Misc.string2const(mod) if String === mod
|
33
|
+
mod.setup_info(object, info)
|
34
|
+
end
|
35
|
+
|
36
|
+
object
|
37
|
+
end
|
38
|
+
|
39
|
+
def tsv_values(*fields)
|
40
|
+
fields = fields.flatten
|
41
|
+
info = self.info
|
42
|
+
values = []
|
43
|
+
fields.each do |field|
|
44
|
+
values << case
|
45
|
+
when field == "JSON"
|
46
|
+
info.to_json
|
47
|
+
when field == "literal"
|
48
|
+
self.gsub(/\n|\t/, ' ')
|
49
|
+
when info.include?(field.to_sym)
|
50
|
+
info.delete(field.to_sym)
|
51
|
+
when self.respond_to?(field)
|
52
|
+
self.send(field)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
values
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.load_tsv_values(id, values, *fields)
|
59
|
+
fields = fields.flatten
|
60
|
+
info = {}
|
61
|
+
literal_pos = fields.index "literal"
|
62
|
+
|
63
|
+
object = if literal_pos.nil?
|
64
|
+
id
|
65
|
+
else
|
66
|
+
v = values[literal_pos]
|
67
|
+
v = v.first if Array === v
|
68
|
+
v
|
69
|
+
end
|
70
|
+
|
71
|
+
fields.each_with_index do |field,i|
|
72
|
+
if field == "JSON"
|
73
|
+
JSON.parse(values[i]).each do |key, value|
|
74
|
+
info[key.to_sym] = value
|
75
|
+
end
|
76
|
+
else
|
77
|
+
info[field.to_sym] = values[i]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
self.load(object, info)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.tsv(annotations, *fields)
|
85
|
+
fields = case
|
86
|
+
when ((fields.compact.empty?) and not annotations.empty?)
|
87
|
+
fields = annotations.first.annotations
|
88
|
+
fields << :annotation_types
|
89
|
+
when (fields == [:literal] and not annotations.empty?)
|
90
|
+
fields = annotations.first.annotations
|
91
|
+
fields << :literal
|
92
|
+
when (fields == [:all] and not annotations.empty?)
|
93
|
+
fields = [:annotation_types] + annotations.first.annotations
|
94
|
+
fields << :literal
|
95
|
+
else
|
96
|
+
fields.flatten
|
97
|
+
end
|
98
|
+
fields = fields.collect{|f| f.to_s}
|
99
|
+
|
100
|
+
tsv = TSV.setup({}, :key_field => "ID", :fields => fields)
|
101
|
+
|
102
|
+
annotations.each do |annotation|
|
103
|
+
tsv[annotation.id] = annotation.tsv_values(fields)
|
104
|
+
end
|
105
|
+
|
106
|
+
tsv
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.load_tsv(tsv)
|
110
|
+
tsv.collect do |id, values|
|
111
|
+
Annotated.load_tsv_values(id, values, tsv.fields)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
module Annotation
|
118
|
+
def self.extended(base)
|
119
|
+
if not base.respond_to? :annotations
|
120
|
+
class << base
|
121
|
+
attr_accessor :annotations, :inheritance, :all_inheritance, :all_annotations
|
122
|
+
self
|
123
|
+
end
|
124
|
+
|
125
|
+
base.annotations = []
|
126
|
+
base.inheritance = []
|
127
|
+
base.all_annotations = []
|
128
|
+
base.all_inheritance = []
|
129
|
+
|
130
|
+
base.module_eval do
|
131
|
+
def self.extended(object)
|
132
|
+
object.extend Annotated
|
133
|
+
if not object.annotation_types.include? self
|
134
|
+
object.annotation_types.concat self.inheritance
|
135
|
+
object.annotation_types << self
|
136
|
+
object.annotation_types.uniq!
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.included(base)
|
141
|
+
base.inheritance << self
|
142
|
+
base.all_inheritance.concat self.all_inheritance if self.respond_to? :all_inheritance
|
143
|
+
base.all_inheritance << self
|
144
|
+
base.all_inheritance.uniq!
|
145
|
+
base.update_annotations
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def update_annotations
|
153
|
+
@all_annotations = all_inheritance.inject([]){|acc,mod| acc.concat mod.annotations}.concat(@annotations)
|
154
|
+
end
|
155
|
+
|
156
|
+
def annotation(*values)
|
157
|
+
@annotations.concat values.collect{|v| v.to_sym}
|
158
|
+
update_annotations
|
159
|
+
|
160
|
+
module_eval do
|
161
|
+
attr_accessor *values
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def setup_info(object, info)
|
166
|
+
object.extend self
|
167
|
+
all_annotations.each do |annotation|
|
168
|
+
object.send(annotation.to_s + '=', info[annotation])
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def setup(object, *values)
|
173
|
+
object.extend self
|
174
|
+
|
175
|
+
all_annotations.zip(values).each do |name, value|
|
176
|
+
object.send(name.to_s + '=', value)
|
177
|
+
end
|
178
|
+
|
179
|
+
object
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
module AnnotatedArray
|
184
|
+
extend ChainMethods
|
185
|
+
self.chain_prefix = :annotated_array
|
186
|
+
|
187
|
+
def annotated_array_get_brackets(pos)
|
188
|
+
value = annotated_array_clean_get_brackets(pos)
|
189
|
+
annotation_types.each do |mod|
|
190
|
+
mod.setup(value, *info.values_at(*mod.annotations))
|
191
|
+
end
|
192
|
+
value
|
193
|
+
end
|
194
|
+
|
195
|
+
def annotated_array_each
|
196
|
+
annotation_array_clean_each do |value|
|
197
|
+
annotation_types.each do |mod|
|
198
|
+
mod.setup(value, annotation)
|
199
|
+
end
|
200
|
+
yield value
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def annotated_array_collect
|
205
|
+
annotation_array_clean_collect do |value|
|
206
|
+
annotation_types.each do |mod|
|
207
|
+
mod.setup(value, annotation)
|
208
|
+
end
|
209
|
+
yield value
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
|