athena 0.0.1.53

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.
@@ -0,0 +1,77 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # A component of athena, the database file converter. #
5
+ # #
6
+ # Copyright (C) 2007 University of Cologne, #
7
+ # Albertus-Magnus-Platz, #
8
+ # 50932 Cologne, Germany #
9
+ # #
10
+ # Authors: #
11
+ # Jens Wille <jens.wille@uni-koeln.de> #
12
+ # #
13
+ # athena is free software; you can redistribute it and/or modify it under the #
14
+ # terms of the GNU General Public License as published by the Free Software #
15
+ # Foundation; either version 3 of the License, or (at your option) any later #
16
+ # version. #
17
+ # #
18
+ # athena is distributed in the hope that it will be useful, but WITHOUT ANY #
19
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
20
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more #
21
+ # details. #
22
+ # #
23
+ # You should have received a copy of the GNU General Public License along #
24
+ # with athena. If not, see <http://www.gnu.org/licenses/>. #
25
+ # #
26
+ ###############################################################################
27
+ #++
28
+
29
+ module Athena
30
+
31
+ class Formats
32
+
33
+ @formats = { :in => {}, :out => {} }
34
+
35
+ class << self
36
+
37
+ def formats
38
+ Formats.instance_variable_get :@formats
39
+ end
40
+
41
+ def [](direction, format)
42
+ formats[direction][format]
43
+ end
44
+
45
+ def valid_format?(direction, format)
46
+ formats[direction].has_key? format
47
+ end
48
+
49
+ def convert(*args)
50
+ raise NotImplementedError, 'must be defined by sub-class'
51
+ end
52
+
53
+ private
54
+
55
+ def register_format(direction, format)
56
+ formats[direction][format] = self
57
+ end
58
+
59
+ def register_formats(direction, *formats)
60
+ formats.each { |format|
61
+ register_format(direction, format)
62
+ }
63
+ end
64
+
65
+ end
66
+
67
+ def parse(*args)
68
+ raise NotImplementedError, 'must be defined by sub-class'
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+
75
+ Dir[__FILE__.sub(/\.rb$/, '/**/*.rb')].each { |rb|
76
+ require rb
77
+ }
@@ -0,0 +1,65 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # A component of athena, the database file converter. #
5
+ # #
6
+ # Copyright (C) 2007 University of Cologne, #
7
+ # Albertus-Magnus-Platz, #
8
+ # 50932 Cologne, Germany #
9
+ # #
10
+ # Authors: #
11
+ # Jens Wille <jens.wille@uni-koeln.de> #
12
+ # #
13
+ # athena is free software; you can redistribute it and/or modify it under the #
14
+ # terms of the GNU General Public License as published by the Free Software #
15
+ # Foundation; either version 3 of the License, or (at your option) any later #
16
+ # version. #
17
+ # #
18
+ # athena is distributed in the hope that it will be useful, but WITHOUT ANY #
19
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
20
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more #
21
+ # details. #
22
+ # #
23
+ # You should have received a copy of the GNU General Public License along #
24
+ # with athena. If not, see <http://www.gnu.org/licenses/>. #
25
+ # #
26
+ ###############################################################################
27
+ #++
28
+
29
+ require 'iconv'
30
+
31
+ module Athena
32
+
33
+ class Formats
34
+
35
+ class DBM < Athena::Formats
36
+
37
+ register_formats :out, 'dbm', 'midos'
38
+
39
+ CRLF = "\015\012"
40
+
41
+ ICONV_TO_LATIN1 = Iconv.new('latin1', 'utf-8')
42
+
43
+ def self.convert(record)
44
+ dbm = ["ID:#{record.id}"]
45
+ record.struct.each { |field, struct|
46
+ strings = struct[:elements].inject([]) { |array, element|
47
+ values = (struct[:values][element] || []).map { |v|
48
+ (v || '').strip.gsub(/(?:\r?\n)+/, ' ')
49
+ }.reject { |v| v.empty? }
50
+
51
+ array << (values.empty? ? struct[:empty] : values.join('|'))
52
+ }
53
+
54
+ dbm << "#{field.to_s.upcase}:#{ICONV_TO_LATIN1.iconv(struct[:string] % strings)}"
55
+ }
56
+ dbm << '&&&'
57
+
58
+ dbm.join(CRLF) << CRLF << CRLF
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,83 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # A component of athena, the database file converter. #
5
+ # #
6
+ # Copyright (C) 2007 University of Cologne, #
7
+ # Albertus-Magnus-Platz, #
8
+ # 50932 Cologne, Germany #
9
+ # #
10
+ # Authors: #
11
+ # Jens Wille <jens.wille@uni-koeln.de> #
12
+ # #
13
+ # athena is free software; you can redistribute it and/or modify it under the #
14
+ # terms of the GNU General Public License as published by the Free Software #
15
+ # Foundation; either version 3 of the License, or (at your option) any later #
16
+ # version. #
17
+ # #
18
+ # athena is distributed in the hope that it will be useful, but WITHOUT ANY #
19
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
20
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more #
21
+ # details. #
22
+ # #
23
+ # You should have received a copy of the GNU General Public License along #
24
+ # with athena. If not, see <http://www.gnu.org/licenses/>. #
25
+ # #
26
+ ###############################################################################
27
+ #++
28
+
29
+ module Athena
30
+
31
+ class Formats
32
+
33
+ class Sisis < Athena::Formats
34
+
35
+ register_format :in, 'sisis'
36
+
37
+ attr_reader :record_element, :config, :parser
38
+
39
+ def initialize(parser)
40
+ config = parser.config.dup
41
+
42
+ case @record_element = config.delete(:__record_element)
43
+ when String
44
+ # fine!
45
+ when nil
46
+ raise NoRecordElementError, 'no record element specified'
47
+ else
48
+ raise IllegalRecordElementError, "illegal record element #{@record_element}"
49
+ end
50
+
51
+ @config = config
52
+ @parser = parser
53
+ end
54
+
55
+ def parse(source)
56
+ record = nil
57
+
58
+ source.each { |line|
59
+ element, value = line.match(/(\d+).*?:\s*(.*)/)[1, 2]
60
+
61
+ case element
62
+ when record_element
63
+ record.close if record
64
+ record = Athena::Record.new(parser.block, value)
65
+ else
66
+ record.update(element, value, config[element])
67
+ end
68
+ }
69
+
70
+ record.close if record
71
+ end
72
+
73
+ class NoRecordElementError < StandardError
74
+ end
75
+
76
+ class IllegalRecordElementError < StandardError
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+
83
+ end
@@ -0,0 +1,278 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # A component of athena, the database file converter. #
5
+ # #
6
+ # Copyright (C) 2007 University of Cologne, #
7
+ # Albertus-Magnus-Platz, #
8
+ # 50932 Cologne, Germany #
9
+ # #
10
+ # Authors: #
11
+ # Jens Wille <jens.wille@uni-koeln.de> #
12
+ # #
13
+ # athena is free software; you can redistribute it and/or modify it under the #
14
+ # terms of the GNU General Public License as published by the Free Software #
15
+ # Foundation; either version 3 of the License, or (at your option) any later #
16
+ # version. #
17
+ # #
18
+ # athena is distributed in the hope that it will be useful, but WITHOUT ANY #
19
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
20
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more #
21
+ # details. #
22
+ # #
23
+ # You should have received a copy of the GNU General Public License along #
24
+ # with athena. If not, see <http://www.gnu.org/licenses/>. #
25
+ # #
26
+ ###############################################################################
27
+ #++
28
+
29
+ require 'forwardable'
30
+
31
+ require 'rubygems'
32
+
33
+ require 'xmlstreamin'
34
+ require 'nuggets/hash/insert'
35
+
36
+ module Athena
37
+
38
+ class Formats
39
+
40
+ class XML < Athena::Formats
41
+
42
+ include Util
43
+
44
+ register_format :in, 'xml'
45
+
46
+ attr_reader :spec, :listener
47
+
48
+ def initialize(parser)
49
+ @spec = build_spec(parser)
50
+ @listener = XMLStreamin::XMLStreamListener.new(@spec)
51
+ end
52
+
53
+ def parse(source)
54
+ REXML::Document.parse_stream(source, listener)
55
+ end
56
+
57
+ private
58
+
59
+ def build_spec(parser)
60
+ config = parser.config.dup
61
+
62
+ case record_element = config.delete(:__record_element)
63
+ when String
64
+ # fine!
65
+ when nil
66
+ raise NoRecordElementError, 'no record element specified'
67
+ else
68
+ raise IllegalRecordElementError, "illegal record element #{record_element}"
69
+ end
70
+
71
+ element_specs = config.inject({}) { |specs, (element, element_spec)|
72
+ element_spec.each { |field, c|
73
+ element.split('/').reverse.inject({}) { |hash, part|
74
+ s = define_spec(element, field, c, hash.empty? ? :default : hash)
75
+ merge_specs(hash, part, s)
76
+ }.each { |key, s|
77
+ merge_specs(specs, key, s)
78
+ }
79
+ }
80
+
81
+ specs
82
+ }
83
+
84
+ record_spec = RecordSpec.new(parser)
85
+ record_spec.specs!(element_specs)
86
+
87
+ root_spec = BaseSpec.new
88
+ root_spec.specs!(record_element => record_spec)
89
+
90
+ spec = BaseSpec.new
91
+ spec.default!(root_spec)
92
+
93
+ verbose(:spec, BaseSpec) do
94
+ spec.inspect_spec
95
+ end
96
+
97
+ spec
98
+ end
99
+
100
+ def define_spec(element, field, config, arg)
101
+ spec = ElementSpec.new(element, field, config)
102
+
103
+ case arg
104
+ when Hash
105
+ spec.specs!(arg)
106
+ else
107
+ spec.default!(SubElementSpec.new(spec))
108
+ end
109
+
110
+ spec
111
+ end
112
+
113
+ def merge_specs(container, key, spec)
114
+ container.insert!(key, spec) { |s1, s2|
115
+ if s1.respond_to?(:specs!)
116
+ s1.specs!(s2.respond_to?(:specs) ? s2.specs : s2)
117
+ s1
118
+ else
119
+ s1.merge(s2)
120
+ end
121
+ }
122
+ end
123
+
124
+ class BaseSpec < XMLStreamin::XMLSpec
125
+
126
+ include Util
127
+
128
+ @level = 0
129
+
130
+ def start(context, name, attrs)
131
+ verbose(:xml) do
132
+ spit "#{indent(level)}<#{name}>"
133
+ step :down
134
+
135
+ attrs.each { |attr|
136
+ spit "#{indent(level + 1)}[#{attr[0]} = #{attr[1]}]"
137
+ }
138
+ end
139
+
140
+ return context
141
+ end
142
+
143
+ def text(context, data)
144
+ verbose(:xml) do
145
+ content = data.strip
146
+ spit "#{indent(level)}#{content}" unless content.empty?
147
+ end
148
+
149
+ return context
150
+ end
151
+
152
+ def done(context, name)
153
+ verbose(:xml) do
154
+ step :up
155
+ spit "#{indent(level)}</#{name}>"
156
+ end
157
+
158
+ return context
159
+ end
160
+
161
+ def empty(context)
162
+ verbose(:xml) do
163
+ step :up
164
+ end
165
+
166
+ return context
167
+ end
168
+
169
+ def inspect_spec(element = nil, level = 0)
170
+ if respond_to?(:field)
171
+ msg = "#{indent(level)}[#{element}] #{field.to_s.upcase} -> #{name}"
172
+ respond_to?(:spit) ? spit(msg) : warn(msg)
173
+ specs.each { |e, s|
174
+ s.inspect_spec(e, level + 1)
175
+ }
176
+ else
177
+ if specs.empty?
178
+ specs.default.inspect_spec('?', level)
179
+ else
180
+ specs.each { |e, s|
181
+ s.inspect_spec(e, level)
182
+ }
183
+ end
184
+ end
185
+ end
186
+
187
+ private
188
+
189
+ def level
190
+ BaseSpec.instance_variable_get :@level
191
+ end
192
+
193
+ def step(direction)
194
+ steps = { :down => 1, :up => -1 }
195
+ BaseSpec.instance_variable_set :@level, level + steps[direction]
196
+ end
197
+
198
+ end
199
+
200
+ class RecordSpec < BaseSpec
201
+
202
+ attr_reader :parser
203
+ attr_accessor :record
204
+
205
+ def initialize(parser)
206
+ super()
207
+
208
+ @parser = parser
209
+ end
210
+
211
+ def start(context, name, attrs)
212
+ super
213
+
214
+ self.record = Athena::Record.new(parser.block)
215
+ end
216
+
217
+ def done(context, name)
218
+ super
219
+
220
+ record.close
221
+ end
222
+
223
+ end
224
+
225
+ class ElementSpec < BaseSpec
226
+
227
+ attr_reader :name, :field, :config
228
+ attr_accessor :record
229
+
230
+ def initialize(name, field, config)
231
+ super()
232
+
233
+ @name = name
234
+ @field = field
235
+ @config = config
236
+ end
237
+
238
+ def start(context, name, attrs)
239
+ super
240
+
241
+ self.record = Athena::Record[field, config]
242
+ end
243
+
244
+ def text(context, data)
245
+ super
246
+
247
+ record.update name, data
248
+ end
249
+
250
+ end
251
+
252
+ class SubElementSpec < BaseSpec
253
+
254
+ extend Forwardable
255
+
256
+ # Forward to parent element; need to specify *all* its attributes and methods
257
+ def_delegators :@parent, :name, :field, :config, :record, :start, :text
258
+
259
+ def initialize(parent)
260
+ super()
261
+
262
+ @parent = parent
263
+ default! self
264
+ end
265
+
266
+ end
267
+
268
+ class NoRecordElementError < StandardError
269
+ end
270
+
271
+ class IllegalRecordElementError < StandardError
272
+ end
273
+
274
+ end
275
+
276
+ end
277
+
278
+ end