rbbt-util 5.14.33 → 5.14.34
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.
- checksums.yaml +4 -4
- data/bin/rbbt +2 -0
- data/lib/rbbt/association/database.rb +153 -0
- data/lib/rbbt/association/index.rb +89 -20
- data/lib/rbbt/association/open.rb +37 -0
- data/lib/rbbt/association/util.rb +133 -0
- data/lib/rbbt/association.rb +1 -380
- data/lib/rbbt/entity/identifiers.rb +106 -0
- data/lib/rbbt/entity.rb +1 -0
- data/lib/rbbt/knowledge_base/entity.rb +107 -0
- data/lib/rbbt/knowledge_base/query.rb +83 -0
- data/lib/rbbt/knowledge_base/registry.rb +106 -0
- data/lib/rbbt/knowledge_base/syndicate.rb +22 -0
- data/lib/rbbt/knowledge_base.rb +6 -359
- data/lib/rbbt/tsv/accessor.rb +4 -0
- data/lib/rbbt/tsv/change_id.rb +119 -0
- data/lib/rbbt/tsv/index.rb +6 -2
- data/lib/rbbt/tsv/parser.rb +7 -5
- data/lib/rbbt/tsv/util.rb +1 -1
- data/lib/rbbt/tsv.rb +2 -1
- data/lib/rbbt/util/R/model.rb +1 -1
- data/lib/rbbt/util/log.rb +2 -2
- data/lib/rbbt/util/misc/bgzf.rb +2 -0
- data/lib/rbbt/util/misc/inspect.rb +1 -1
- data/lib/rbbt-util.rb +11 -7
- data/lib/rbbt.rb +0 -1
- data/share/rbbt_commands/app/start +1 -1
- data/share/rbbt_commands/tsv/change_id +2 -2
- data/test/rbbt/association/test_database.rb +61 -0
- data/test/rbbt/association/test_index.rb +67 -22
- data/test/rbbt/association/test_open.rb +68 -0
- data/test/rbbt/association/test_util.rb +108 -0
- data/test/rbbt/entity/test_identifiers.rb +40 -0
- data/test/rbbt/knowledge_base/test_entity.rb +0 -0
- data/test/rbbt/knowledge_base/test_query.rb +45 -0
- data/test/rbbt/knowledge_base/test_registry.rb +52 -0
- data/test/rbbt/test_association.rb +3 -3
- data/test/rbbt/test_knowledge_base.rb +79 -51
- data/test/rbbt/test_monitor.rb +0 -2
- data/test/rbbt/test_packed_index.rb +1 -1
- data/test/rbbt/test_resource.rb +6 -6
- data/test/rbbt/test_tsv.rb +34 -44
- data/test/rbbt/tsv/parallel/test_through.rb +2 -4
- data/test/rbbt/tsv/parallel/test_traverse.rb +30 -28
- data/test/rbbt/tsv/test_change_id.rb +10 -0
- data/test/rbbt/util/R/test_model.rb +9 -10
- data/test/rbbt/util/test_misc.rb +1 -1
- data/test/test_helper.rb +4 -1
- metadata +24 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec2d34290a61ca4f3f32cd875a07a15c9c7c06fd
|
4
|
+
data.tar.gz: 08ce21aa7a885530dcba3859231d94874f99bba2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d532ef379f2238e8dbaf311f485a4e18ac774177624e327d7b1d432a6cd0304f17f945448523407bb0cbb8f14a1067b50d36585b6d554d646dd5a01124c5b4f2
|
7
|
+
data.tar.gz: b15a2660fd8be0a782fb0a139bc44b8670adf3629446be6c0b8dc3e6d27f017a2c71db0cb6d76602b306917c9909f03013226566d963c0247506a4723968ead8
|
data/bin/rbbt
CHANGED
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'rbbt/association/util'
|
2
|
+
require 'rbbt/tsv/change_id'
|
3
|
+
|
4
|
+
module Association
|
5
|
+
|
6
|
+
def self.add_reciprocal(tsv)
|
7
|
+
new = TSV.open(tsv.dumper_stream)
|
8
|
+
tsv.with_unnamed do
|
9
|
+
case tsv.type
|
10
|
+
when :double
|
11
|
+
tsv.through do |source, values|
|
12
|
+
Misc.zip_fields(values).each do |info|
|
13
|
+
target, *rest = info
|
14
|
+
new.zip_new target, [source] + rest
|
15
|
+
end
|
16
|
+
end
|
17
|
+
else
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
tsv.annotate(new)
|
22
|
+
|
23
|
+
new
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.translate(tsv, source_final_format, target_final_format, options = {})
|
27
|
+
source_field = tsv.key_field
|
28
|
+
target_field = tsv.fields.first
|
29
|
+
namespace = tsv.namespace
|
30
|
+
|
31
|
+
if source_final_format and source_field != source_final_format
|
32
|
+
Log.debug("Changing source format from #{tsv.key_field} to #{source_final_format}")
|
33
|
+
|
34
|
+
identifier_files = tsv.identifier_files.dup
|
35
|
+
identifier_files.concat Entity.identifier_files(source_final_format) if defined? Entity
|
36
|
+
identifier_files.uniq!
|
37
|
+
identifier_files.collect!{|f| f.annotate(f.gsub(/\bNAMESPACE\b/, namespace))} if namespace
|
38
|
+
identifier_files.reject!{|f| f.match(/\bNAMESPACE\b/)}
|
39
|
+
|
40
|
+
tsv = TSV.translate(tsv, source_field, source_final_format, options.merge(:identifier_files => identifier_files))
|
41
|
+
end
|
42
|
+
|
43
|
+
# Translate target
|
44
|
+
if target_final_format and target_field != target_final_format
|
45
|
+
Log.debug("Changing target format from #{target_field} to #{target_final_format}")
|
46
|
+
old_key_field = tsv.key_field
|
47
|
+
tsv.key_field = "MASK"
|
48
|
+
|
49
|
+
identifier_files = tsv.identifier_files.dup
|
50
|
+
identifier_files.concat Entity.identifier_files(target_final_format) if defined? Entity
|
51
|
+
identifier_files.uniq!
|
52
|
+
identifier_files.collect!{|f| f.annotate(f.gsub(/\bNAMESPACE\b/, namespace))} if namespace
|
53
|
+
identifier_files.reject!{|f| f.match(/\bNAMESPACE\b/)}
|
54
|
+
|
55
|
+
tsv = TSV.translate(tsv, target_field, target_final_format, options.merge(:identifier_files => identifier_files))
|
56
|
+
tsv.key_field = old_key_field
|
57
|
+
end
|
58
|
+
|
59
|
+
tsv
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.reorder_tsv(tsv, options = {})
|
63
|
+
fields, undirected, persist = Misc.process_options options, :fields, :undirected, :persist
|
64
|
+
all_fields = tsv.all_fields
|
65
|
+
|
66
|
+
source_pos, field_pos, source_header, field_headers, source_format, target_format = headers(all_fields, fields, options)
|
67
|
+
|
68
|
+
source_field = source_pos == :key ? :key : all_fields[source_pos]
|
69
|
+
info_fields = field_pos.collect{|f| f == :key ? :key : all_fields[f]}
|
70
|
+
options = options.merge({:key_field => source_field, :fields => info_fields})
|
71
|
+
|
72
|
+
tsv = tsv.reorder source_field, fields, :zipped => true
|
73
|
+
|
74
|
+
tsv.key_field = source_header
|
75
|
+
tsv.fields = field_headers
|
76
|
+
|
77
|
+
tsv = translate tsv, source_format, target_format, :persist => persist if source_format or target_format
|
78
|
+
|
79
|
+
tsv = add_reciprocal tsv if undirected
|
80
|
+
|
81
|
+
tsv
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.open_stream(stream, options = {})
|
85
|
+
fields, undirected, persist = Misc.process_options options, :fields, :undirected, :persist
|
86
|
+
|
87
|
+
parser = TSV::Parser.new stream, options.merge(:fields => nil, :key_field => nil)
|
88
|
+
|
89
|
+
key_field, *_fields = all_fields = parser.all_fields
|
90
|
+
|
91
|
+
source_pos, field_pos, source_header, field_headers, source_format, target_format = headers parser.all_fields, fields, options
|
92
|
+
|
93
|
+
parser.key_field = source_pos
|
94
|
+
parser.fields = field_pos
|
95
|
+
|
96
|
+
case parser.type
|
97
|
+
when :single
|
98
|
+
class << parser
|
99
|
+
def get_values(parts)
|
100
|
+
[parts[@key_field], parts.values_at(*@fields).first]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
when :list
|
104
|
+
class << parser
|
105
|
+
def get_values(parts)
|
106
|
+
[parts[@key_field], parts.values_at(*@fields)]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
when :double, :list, :single
|
110
|
+
class << parser
|
111
|
+
def get_values(parts)
|
112
|
+
[parts[@key_field].split(@sep2,-1), parts.values_at(*@fields).collect{|v| v.nil? ? [] : v.split(@sep2,-1) }]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
when :flat
|
116
|
+
class << parser
|
117
|
+
def get_values(parts)
|
118
|
+
fields = (0..parts.length-1).to_a - [@key_field]
|
119
|
+
values = parts.values_at(*fields).compact.collect{|v| v.split(@sep2,-1) }.flatten
|
120
|
+
[parts[@key_field].split(@sep2,-1), values]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
open_options = options.merge(parser.options).merge(:parser => parser)
|
126
|
+
|
127
|
+
tsv = TSV.parse parser.stream, {}, open_options
|
128
|
+
tsv.key_field = source_header
|
129
|
+
tsv.fields = field_headers
|
130
|
+
|
131
|
+
tsv = tsv.to_double unless tsv.type == :double
|
132
|
+
|
133
|
+
tsv = translate tsv, source_format, target_format, :persist => persist if source_format or target_format
|
134
|
+
|
135
|
+
tsv = add_reciprocal tsv if undirected
|
136
|
+
|
137
|
+
tsv
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.database(file, options = {})
|
141
|
+
case file
|
142
|
+
when TSV
|
143
|
+
file = file.to_double unless file.type == :double
|
144
|
+
reorder_tsv(file, options.dup)
|
145
|
+
when IO
|
146
|
+
open_stream(file, options.dup)
|
147
|
+
else
|
148
|
+
stream = TSV.get_stream(file)
|
149
|
+
open_stream(stream, options.dup)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
@@ -1,5 +1,85 @@
|
|
1
1
|
require 'rbbt/tsv'
|
2
|
+
require 'rbbt/association/open'
|
3
|
+
|
2
4
|
module Association
|
5
|
+
def self.index(file, options = nil, persist_options = nil)
|
6
|
+
options = options.nil? ? {} : options.dup
|
7
|
+
persist_options = persist_options.nil? ? Misc.pull_keys(options, :persist) : persist_options.dup
|
8
|
+
|
9
|
+
persist_options = Misc.add_defaults persist_options.dup, :persist => true, :engine => "BDB"
|
10
|
+
persist = persist_options[:persist]
|
11
|
+
|
12
|
+
file = version_file(file, options[:namespace]) if options[:namespace] and String === file
|
13
|
+
|
14
|
+
undirected = options[:undirected]
|
15
|
+
Persist.persist_tsv(file, "Association Index", options, persist_options.dup) do |data|
|
16
|
+
recycle = options[:recycle]
|
17
|
+
|
18
|
+
persist_options[:file] = persist_options[:file] + '.database' if persist_options[:file]
|
19
|
+
database = open(file, options, persist_options.dup)
|
20
|
+
|
21
|
+
fields = database.fields
|
22
|
+
source_field = database.key_field
|
23
|
+
target_field = fields.first.split(":").last
|
24
|
+
key_field = [source_field, target_field, undirected ? "undirected" : nil].compact * "~"
|
25
|
+
|
26
|
+
TSV.setup(data, :key_field => key_field, :fields => fields[1..-1], :type => :list, :serializer => :list)
|
27
|
+
|
28
|
+
data.key_field = key_field
|
29
|
+
data.fields = fields[1..-1]
|
30
|
+
data.type = :list
|
31
|
+
data.serializer = :list
|
32
|
+
|
33
|
+
database.with_unnamed do
|
34
|
+
database.through do |source, values|
|
35
|
+
case database.type
|
36
|
+
when :single
|
37
|
+
values = [[values]]
|
38
|
+
when :list
|
39
|
+
values = values.collect{|v| [v] }
|
40
|
+
when :flat
|
41
|
+
values = [values]
|
42
|
+
end
|
43
|
+
next if values.empty?
|
44
|
+
next if source.nil? or source.empty?
|
45
|
+
next if values.empty?
|
46
|
+
|
47
|
+
targets, *rest = values
|
48
|
+
|
49
|
+
size = targets ? targets.length : 0
|
50
|
+
|
51
|
+
rest.each_with_index do |list,i|
|
52
|
+
list.replace [list.first] * size if list.length == 1
|
53
|
+
end if recycle and size > 1
|
54
|
+
|
55
|
+
rest = Misc.zip_fields rest
|
56
|
+
|
57
|
+
annotations = rest.length > 1 ?
|
58
|
+
targets.zip(rest) :
|
59
|
+
targets.zip(rest * targets.length)
|
60
|
+
|
61
|
+
annotations.each do |target, info|
|
62
|
+
next if target.nil? or target.empty?
|
63
|
+
key = [source, target] * "~"
|
64
|
+
if data[key].nil? or info.nil?
|
65
|
+
data[key] = info
|
66
|
+
else
|
67
|
+
old_info = data[key]
|
68
|
+
info = old_info.zip(info).collect{|p| p * ";;" }
|
69
|
+
data[key] = info
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
data.close
|
76
|
+
data
|
77
|
+
end.tap do |data|
|
78
|
+
data.read if not Hash === data and data.respond_to? :read
|
79
|
+
Association::Index.setup data
|
80
|
+
data
|
81
|
+
end
|
82
|
+
end
|
3
83
|
module Index
|
4
84
|
|
5
85
|
attr_accessor :source_field, :target_field, :undirected
|
@@ -16,9 +96,15 @@ module Association
|
|
16
96
|
|
17
97
|
def reverse
|
18
98
|
@reverse ||= begin
|
19
|
-
|
20
|
-
|
21
|
-
|
99
|
+
if self.respond_to? :persistence_path
|
100
|
+
persistence_path = self.persistence_path
|
101
|
+
persistence_path = persistence_path.find if Path === persistence_path
|
102
|
+
reverse_filename = persistence_path + '.reverse'
|
103
|
+
else
|
104
|
+
raise "Can only reverse a TokyoCabinet::BDB dataset at the time"
|
105
|
+
end
|
106
|
+
|
107
|
+
self.read if self.respond_to? :read
|
22
108
|
|
23
109
|
if File.exists?(reverse_filename)
|
24
110
|
new = Persist.open_tokyocabinet(reverse_filename, false, serializer, TokyoCabinet::BDB)
|
@@ -66,16 +152,6 @@ module Association
|
|
66
152
|
|
67
153
|
#{{{ Subset
|
68
154
|
|
69
|
-
def select_entities(entities)
|
70
|
-
source_type = Entity.formats[source_field]
|
71
|
-
target_type = Entity.formats[target_field]
|
72
|
-
|
73
|
-
source_entities = entities[:source] || entities[source_field] || entities[Entity.formats[source_field].to_s]
|
74
|
-
target_entities = entities[:target] || entities[target_field] || entities[Entity.formats[target_field].to_s]
|
75
|
-
|
76
|
-
[source_entities, target_entities]
|
77
|
-
end
|
78
|
-
|
79
155
|
def subset(source, target)
|
80
156
|
return [] if source.nil? or target.nil? or source.empty? or target.empty?
|
81
157
|
|
@@ -110,12 +186,5 @@ module Association
|
|
110
186
|
target_matches.values_at(*target.uniq).flatten.compact
|
111
187
|
end
|
112
188
|
|
113
|
-
def subset_entities(entities)
|
114
|
-
source, target = select_entities(entities)
|
115
|
-
return [] if source.nil? or target.nil?
|
116
|
-
return [] if Array === target and target.empty?
|
117
|
-
return [] if Array === source and source.empty?
|
118
|
-
subset source, target
|
119
|
-
end
|
120
189
|
end
|
121
190
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rbbt/association/database'
|
2
|
+
|
3
|
+
module Association
|
4
|
+
def self.version_file(file, namespace)
|
5
|
+
old_file, file = file, file.sub('NAMESPACE', namespace) if namespace and String === file
|
6
|
+
old_file.annotate file if Path === old_file
|
7
|
+
file
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.open(file, options = nil, persist_options = nil)
|
11
|
+
options = options.nil? ? {} : options.dup
|
12
|
+
persist_options = persist_options.nil? ? Misc.pull_keys(options, :persist) : persist_options.dup
|
13
|
+
|
14
|
+
options = Misc.add_defaults options, :zipped => true
|
15
|
+
persist_options = Misc.add_defaults persist_options, :persist => true, :dir => Rbbt.var.associations
|
16
|
+
persist = persist_options[:persist]
|
17
|
+
|
18
|
+
file = version_file(file, options[:namespace]) if options[:namespace] and String === file
|
19
|
+
file = file.call if Proc === file
|
20
|
+
|
21
|
+
data = Persist.persist_tsv(file, "Association Database", options, persist_options) do |data|
|
22
|
+
tsv = Association.database(file, options.merge(:persist => persist))
|
23
|
+
tsv = tsv.to_double unless tsv.type == :double
|
24
|
+
tsv.annotate data
|
25
|
+
|
26
|
+
data.serializer = :double if data.respond_to? :serializer
|
27
|
+
tsv.each do |k,v|
|
28
|
+
data[k] = v
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
data
|
33
|
+
end
|
34
|
+
data
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'rbbt/entity'
|
2
|
+
|
3
|
+
module Association
|
4
|
+
def self.identify_entity_format(format, fields)
|
5
|
+
entity_type = Entity.formats[format]
|
6
|
+
raise "Field #{ format } could not be resolved: #{fields}" if entity_type.nil?
|
7
|
+
main_field = fields.select{|f| Entity.formats[f] == entity_type}.first
|
8
|
+
raise "Field #{ format } not present, options: #{Misc.fingerprint fields}" if main_field.nil?
|
9
|
+
[main_field, nil, format]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.parse_field_specification(spec)
|
13
|
+
return [2,nil,nil] if Fixnum === spec
|
14
|
+
spec = spec.split "=>" unless Array === spec
|
15
|
+
field_part, final_format = spec
|
16
|
+
|
17
|
+
field, format = field_part.split "=~", -1
|
18
|
+
|
19
|
+
field = nil if field.nil? or field.empty?
|
20
|
+
|
21
|
+
[field, format, final_format]
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.normalize_specs(spec, all_fields = nil)
|
25
|
+
return nil if spec.nil?
|
26
|
+
field, header, format = parse_field_specification spec
|
27
|
+
|
28
|
+
specs = if all_fields.nil? or all_fields.include? field
|
29
|
+
[field, header, format]
|
30
|
+
else
|
31
|
+
if all_fields.nil?
|
32
|
+
begin
|
33
|
+
identify_entity_format field, all_fields
|
34
|
+
rescue
|
35
|
+
[field, header, format]
|
36
|
+
end
|
37
|
+
else
|
38
|
+
[field, header, format]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
specs
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.extract_specs(all_fields=nil, options = {})
|
45
|
+
source, source_format, target, target_format = Misc.process_options options, :source, :source_format, :target, :target_format
|
46
|
+
|
47
|
+
key_field, *fields = all_fields.nil? ? [nil] : all_fields
|
48
|
+
|
49
|
+
source_specs = normalize_specs source, all_fields
|
50
|
+
target_specs = normalize_specs target, all_fields
|
51
|
+
|
52
|
+
source_specs = [nil, nil, nil] if source_specs.nil?
|
53
|
+
target_specs = [nil, nil, nil] if target_specs.nil?
|
54
|
+
|
55
|
+
source_specs[2] = source_format if source_format
|
56
|
+
target_specs[2] = target_format if target_format
|
57
|
+
|
58
|
+
if source_specs[0].nil? and target_specs[0].nil?
|
59
|
+
source_specs[0] = key_field
|
60
|
+
target_specs[0] = fields[0]
|
61
|
+
elsif source_specs[0].nil?
|
62
|
+
if target_specs[0] == :key or target_specs[0] == key_field
|
63
|
+
source_specs[0] = fields[0]
|
64
|
+
else
|
65
|
+
source_specs[0] = key_field
|
66
|
+
end
|
67
|
+
elsif target_specs[0].nil?
|
68
|
+
if source_specs[0] == fields.first
|
69
|
+
target_specs[0] = key_field
|
70
|
+
else
|
71
|
+
target_specs[0] = fields.first
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
{:source => source_specs, :target => target_specs}
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.process_formats(field, default_format = {})
|
79
|
+
return nil if default_format.nil? or default_format.empty?
|
80
|
+
default_format.each do |type, format|
|
81
|
+
entity_type = Entity.formats[field] || format
|
82
|
+
return format if entity_type.to_s === type
|
83
|
+
end
|
84
|
+
return nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.headers(all_fields, info_fields = nil, options = {})
|
88
|
+
specs = extract_specs all_fields, options
|
89
|
+
|
90
|
+
source_field = specs[:source][0]
|
91
|
+
target_field = specs[:target][0]
|
92
|
+
|
93
|
+
source_pos = all_fields.index source_field
|
94
|
+
target_pos = all_fields.index target_field
|
95
|
+
|
96
|
+
source_header = specs[:source][1] || specs[:source][0]
|
97
|
+
target_header = specs[:target][1] || specs[:target][0]
|
98
|
+
|
99
|
+
info_fields = all_fields.dup if info_fields.nil?
|
100
|
+
info_fields.delete source_field
|
101
|
+
info_fields.delete target_field
|
102
|
+
info_fields.unshift target_field
|
103
|
+
|
104
|
+
field_headers = [target_header]
|
105
|
+
info_fields[1..-1].each do |field|
|
106
|
+
header = case field
|
107
|
+
when String
|
108
|
+
field
|
109
|
+
when Fixnum
|
110
|
+
all_fields[field]
|
111
|
+
when :key
|
112
|
+
all_fields.first
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
field_headers << header
|
117
|
+
end
|
118
|
+
|
119
|
+
field_pos = info_fields.collect{|f| raise "Field #{f} not found. Options: #{info_fields* ", "}" unless all_fields.include?(f); f == :key ? 0 : all_fields.index(f); }
|
120
|
+
|
121
|
+
source_format = specs[:source][2]
|
122
|
+
target_format = specs[:target][2]
|
123
|
+
|
124
|
+
|
125
|
+
if format = options[:format]
|
126
|
+
source_format = process_formats(specs[:source][1] || specs[:source][0], format) || source_format
|
127
|
+
target_format = process_formats(specs[:target][1] || specs[:target][0], format) || target_format
|
128
|
+
end
|
129
|
+
|
130
|
+
Log.low "Headers -- #{[source_pos, field_pos, source_header, field_headers, source_format, target_format]}"
|
131
|
+
[source_pos, field_pos, source_header, field_headers, source_format, target_format]
|
132
|
+
end
|
133
|
+
end
|