flattendb 0.0.1.96

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.
data/README ADDED
@@ -0,0 +1,33 @@
1
+ = flattendb - Flatten relational databases
2
+
3
+ == VERSION
4
+
5
+ This documentation refers to flattendb version 0.0.1
6
+
7
+
8
+ == DESCRIPTION
9
+
10
+ TODO: well, the description... ;-)
11
+
12
+
13
+ == AUTHORS
14
+
15
+ * Jens Wille <mailto:jens.wille@uni-koeln.de>
16
+
17
+
18
+ == LICENSE AND COPYRIGHT
19
+
20
+ Copyright (C) 2007 University of Cologne,
21
+ Albertus-Magnus-Platz, 50932 Cologne, Germany
22
+
23
+ flattendb is free software: you can redistribute it and/or modify it under the
24
+ terms of the GNU General Public License as published by the Free Software
25
+ Foundation, either version 3 of the License, or (at your option) any later
26
+ version.
27
+
28
+ flattendb is distributed in the hope that it will be useful, but WITHOUT ANY
29
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
30
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
31
+
32
+ You should have received a copy of the GNU General Public License along with
33
+ flattendb. If not, see <http://www.gnu.org/licenses/>.
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require 'lib/flattendb/version'
2
+
3
+ FILES = FileList['lib/**/*.rb'].to_a
4
+ EXECS = FileList['bin/*'].to_a
5
+ RDOCS = %w[README COPYING ChangeLog]
6
+ OTHER = FileList['[A-Z]*', 'example/*'].to_a
7
+
8
+ task(:doc_spec) {{
9
+ :title => 'flattendb Application documentation',
10
+ :rdoc_files => RDOCS + FILES
11
+ }}
12
+
13
+ task(:gem_spec) {{
14
+ :name => 'flattendb',
15
+ :version => FlattenDB::VERSION,
16
+ :summary => 'Flatten relational databases',
17
+ :files => FILES + EXECS + OTHER,
18
+ :require_path => 'lib',
19
+ :bindir => 'bin',
20
+ :executables => EXECS,
21
+ :extra_rdoc_files => RDOCS,
22
+ :dependencies => %w[highline mysql libxml-ruby builder]
23
+ }}
data/bin/flattendb ADDED
@@ -0,0 +1,129 @@
1
+ #! /usr/bin/ruby
2
+
3
+ #--
4
+ ###############################################################################
5
+ # #
6
+ # flattendb -- Flatten relational databases #
7
+ # #
8
+ # Copyright (C) 2007 University of Cologne, #
9
+ # Albertus-Magnus-Platz, #
10
+ # 50932 Cologne, Germany #
11
+ # #
12
+ # Authors: #
13
+ # Jens Wille <jens.wille@uni-koeln.de> #
14
+ # #
15
+ # flattendb is free software; you can redistribute it and/or modify it under #
16
+ # the terms of the GNU General Public License as published by the Free #
17
+ # Software Foundation; either version 3 of the License, or (at your option) #
18
+ # any later version. #
19
+ # #
20
+ # flattendb is distributed in the hope that it will be useful, but WITHOUT #
21
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
22
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
23
+ # more details. #
24
+ # #
25
+ # You should have received a copy of the GNU General Public License along #
26
+ # with flattendb. If not, see <http://www.gnu.org/licenses/>. #
27
+ # #
28
+ ###############################################################################
29
+ #++
30
+
31
+ require 'optparse'
32
+
33
+ require 'rubygems'
34
+ require 'highline/import'
35
+
36
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
37
+
38
+ require 'flattendb'
39
+
40
+ USAGE = "Usage: #{$0} [-h|--help] [options] <infile> <outfile> <configfile>"
41
+
42
+ $options = {
43
+ :type => :mysql,
44
+ :mysql => {
45
+ :intype => :xml,
46
+ :keep => false
47
+ }
48
+ }
49
+
50
+ def type_options(type, opts, with_heading = true)
51
+ heading = lambda { |name|
52
+ if with_heading
53
+ opts.separator ''
54
+ opts.separator "- #{name}"
55
+ end
56
+ }
57
+
58
+ case type.to_sym
59
+ when :mysql
60
+ heading['MySQL']
61
+
62
+ opts.on('-x', '--xml', "Input file is of type XML [This is the default]") {
63
+ $options[:mysql][:intype] = :xml
64
+ }
65
+ opts.on('-s', '--sql', "Input file is of type SQL") {
66
+ $options[:mysql][:intype] = :sql
67
+ }
68
+ opts.on('-k', '--keep', "Keep intermediate XML dump; only applies if input type is 'sql'") {
69
+ $options[:mysql][:keep] = true
70
+ }
71
+ end
72
+ end
73
+
74
+ OptionParser.new { |opts|
75
+ opts.banner = USAGE
76
+ opts.separator ''
77
+
78
+ opts.separator 'Options:'
79
+ if $type
80
+ opts.separator " [-t, --type] TYPE OVERRIDE IN EFFECT (#{$type})"
81
+ else
82
+ opts.on('-t', '--type TYPE', "Type of database at hand [Default: #{$options[:type]}]") { |t|
83
+ $options[:type] = t.downcase.to_sym
84
+ }
85
+ end
86
+
87
+ opts.separator ''
88
+ opts.separator 'Database-specific Options:'
89
+
90
+ if $type
91
+ type_options($type, opts, false)
92
+ else
93
+ %w[mysql].each { |t|
94
+ type_options(t, opts)
95
+ }
96
+ end
97
+
98
+ opts.separator ''
99
+ opts.separator 'Generic options:'
100
+ opts.on('-h', '--help', 'Print this help message and exit') {
101
+ abort opts.to_s
102
+ }
103
+ opts.on('--version', 'Print program version and exit') {
104
+ abort "#{File.basename($0)} v#{FlattenDB::VERSION}"
105
+ }
106
+ }.parse!
107
+
108
+ $type ||= $options[:type]
109
+ $options = $options[$type] || {}
110
+
111
+ # Load corresponding module
112
+ begin
113
+ require "flattendb/#{$type}"
114
+ rescue LoadError
115
+ abort "Database type '#{$type}' is not supported at the moment."
116
+ end
117
+
118
+ abort USAGE unless ARGV.size == 3
119
+
120
+ $infile, $outfile, configfile = ARGV
121
+
122
+ abort "Input file not found: #{$infile}" unless File.readable?($infile)
123
+
124
+ # Load type-specific script
125
+ load File.join(File.dirname(__FILE__), "flattendb.#{$type}")
126
+
127
+ FlattenDB[$type].new($infile, $outfile, configfile).flatten!.to_xml
128
+
129
+ File.delete($dump_file) if $dump_file && !$options[:keep]
@@ -0,0 +1,97 @@
1
+ #! /usr/bin/ruby
2
+
3
+ # vi:ft=ruby
4
+
5
+ #--
6
+ ###############################################################################
7
+ # #
8
+ # flattendb -- Flatten relational databases #
9
+ # #
10
+ # Copyright (C) 2007 University of Cologne, #
11
+ # Albertus-Magnus-Platz, #
12
+ # 50932 Cologne, Germany #
13
+ # #
14
+ # Authors: #
15
+ # Jens Wille <jens.wille@uni-koeln.de> #
16
+ # #
17
+ # flattendb is free software; you can redistribute it and/or modify it under #
18
+ # the terms of the GNU General Public License as published by the Free #
19
+ # Software Foundation; either version 3 of the License, or (at your option) #
20
+ # any later version. #
21
+ # #
22
+ # flattendb is distributed in the hope that it will be useful, but WITHOUT #
23
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
24
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
25
+ # more details. #
26
+ # #
27
+ # You should have received a copy of the GNU General Public License along #
28
+ # with flattendb. If not, see <http://www.gnu.org/licenses/>. #
29
+ # #
30
+ ###############################################################################
31
+ #++
32
+
33
+ if $0 == __FILE__
34
+ $type = :mysql
35
+ load File.join(File.dirname(__FILE__), 'flattendb')
36
+ else
37
+ case $options[:intype]
38
+ when :xml
39
+ abort "Input file doesn't seem to be a valid XML file, XML declaration missing" \
40
+ unless IO.read($infile, 6) == '<?xml '
41
+ when :sql
42
+ require 'mysql'
43
+
44
+ mysql_cmd = 'mysql'
45
+ dump_cmd = 'mysqldump'
46
+
47
+ [mysql_cmd, dump_cmd].each { |cmd|
48
+ catch :cmd_found do
49
+ ENV['PATH'].split(':').each { |path|
50
+ throw :cmd_found if File.executable?(File.join(path, cmd))
51
+ }
52
+
53
+ abort "Command not found: #{cmd}"
54
+ end
55
+ }
56
+
57
+ mysql_user = ask('Please enter the MySQL user name: ') \
58
+ { |q| q.default = ENV['USER'] }
59
+ mysql_pass = ask("Please enter the MySQL password for that user: ") \
60
+ { |q| q.echo = false }
61
+
62
+ # according to <http://www.adamspiers.org/computing/mysqldiff/#how> MySQL
63
+ # default permissions allow anyone to create databases beginning with the
64
+ # prefix 'test_'
65
+ temp_db = 'flattendb_temp_%d_%d' % [Time.now, $$]
66
+ temp_user = 'flattendb_user'
67
+ temp_pass = 'flattendb_pass'
68
+
69
+ $dump_file = $infile.sub(/\.(?:sql|dump)$/i, '') << '.xml'
70
+ abort "Dump file and output file are the same: #{$dump_file} = #{$outfile}" \
71
+ if File.expand_path($dump_file) == File.expand_path($outfile)
72
+
73
+ mysql_args = "--one-database -u#{temp_user} -p#{temp_pass} #{temp_db} < #{$infile}"
74
+ dump_args = "--xml -u#{temp_user} -p#{temp_pass} #{temp_db} > #{$dump_file}"
75
+
76
+ begin
77
+ mysql = Mysql.real_connect('localhost', mysql_user, mysql_pass)
78
+
79
+ mysql.query("CREATE DATABASE #{temp_db}")
80
+ mysql.query("GRANT ALL ON #{temp_db}.* TO '#{temp_user}'@'localhost' IDENTIFIED BY '#{temp_pass}'")
81
+
82
+ system("#{mysql_cmd} #{mysql_args} && #{dump_cmd} #{dump_args}")
83
+ rescue Mysql::Error => err
84
+ abort "ERROR #{err.errno} (#{err.sqlstate}): #{err.error}"
85
+ ensure
86
+ if mysql
87
+ mysql.query("REVOKE ALL ON #{temp_db}.* FROM '#{temp_user}'@'localhost'") \
88
+ if mysql_user == 'root'
89
+
90
+ mysql.query("DROP DATABASE IF EXISTS #{temp_db}")
91
+ mysql.close
92
+ end
93
+ end
94
+
95
+ $infile = $dump_file
96
+ end
97
+ end
@@ -0,0 +1,120 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ndr>
3
+ <row>
4
+ <Bla>12</Bla>
5
+ <Blub></Blub>
6
+ <ObjID>1</ObjID>
7
+ <attr1>
8
+ <ObjID>1</ObjID>
9
+ <Val>3</Val>
10
+ <attr1ID>1</attr1ID>
11
+ </attr1>
12
+ <attr2>
13
+ <ObjID>1</ObjID>
14
+ <Val>4</Val>
15
+ <attr2ID>3</attr2ID>
16
+ </attr2>
17
+ <barobject>
18
+ <Bar>1002</Bar>
19
+ <ObjID>1</ObjID>
20
+ <attr4>
21
+ <Val>0</Val>
22
+ <attr4ID>2</attr4ID>
23
+ </attr4>
24
+ <attr4ID>2</attr4ID>
25
+ </barobject>
26
+ <fooobject>
27
+ <Foo>112</Foo>
28
+ <ObjID>1</ObjID>
29
+ <attr1>
30
+ <ObjID>1</ObjID>
31
+ <Val>3</Val>
32
+ <attr1ID>1</attr1ID>
33
+ </attr1>
34
+ <attr1ID>1</attr1ID>
35
+ <attr3>
36
+ <Val>8</Val>
37
+ <attr3ID>2</attr3ID>
38
+ </attr3>
39
+ <attr3ID>2</attr3ID>
40
+ </fooobject>
41
+ </row>
42
+ <row>
43
+ <Bla>12</Bla>
44
+ <Blub>hi</Blub>
45
+ <ObjID>2</ObjID>
46
+ <attr1>
47
+ <ObjID>2</ObjID>
48
+ <Val>2</Val>
49
+ <attr1ID>2</attr1ID>
50
+ </attr1>
51
+ <attr2>
52
+ <ObjID>2</ObjID>
53
+ <Val>5</Val>
54
+ <attr2ID>2</attr2ID>
55
+ </attr2>
56
+ <barobject>
57
+ <Bar>1200</Bar>
58
+ <ObjID>2</ObjID>
59
+ <attr4>
60
+ <Val>0</Val>
61
+ <attr4ID>1</attr4ID>
62
+ </attr4>
63
+ <attr4ID>1</attr4ID>
64
+ </barobject>
65
+ <fooobject>
66
+ <Foo>122</Foo>
67
+ <ObjID>2</ObjID>
68
+ <attr1>
69
+ <ObjID>2</ObjID>
70
+ <Val>2</Val>
71
+ <attr1ID>2</attr1ID>
72
+ </attr1>
73
+ <attr1ID>2</attr1ID>
74
+ <attr3>
75
+ <Val>0</Val>
76
+ <attr3ID>1</attr3ID>
77
+ </attr3>
78
+ <attr3ID>1</attr3ID>
79
+ </fooobject>
80
+ </row>
81
+ <row>
82
+ <Bla>1</Bla>
83
+ <Blub>ho</Blub>
84
+ <ObjID>3</ObjID>
85
+ <attr1>
86
+ <ObjID>3</ObjID>
87
+ <Val>1</Val>
88
+ <attr1ID>3</attr1ID>
89
+ </attr1>
90
+ <attr2>
91
+ <ObjID>3</ObjID>
92
+ <Val>6</Val>
93
+ <attr2ID>1</attr2ID>
94
+ </attr2>
95
+ <barobject>
96
+ <Bar>1000</Bar>
97
+ <ObjID>3</ObjID>
98
+ <attr4>
99
+ <Val>9</Val>
100
+ <attr4ID>3</attr4ID>
101
+ </attr4>
102
+ <attr4ID>3</attr4ID>
103
+ </barobject>
104
+ <fooobject>
105
+ <Foo>111</Foo>
106
+ <ObjID>3</ObjID>
107
+ <attr1>
108
+ <ObjID>3</ObjID>
109
+ <Val>1</Val>
110
+ <attr1ID>3</attr1ID>
111
+ </attr1>
112
+ <attr1ID>3</attr1ID>
113
+ <attr3>
114
+ <Val>7</Val>
115
+ <attr3ID>3</attr3ID>
116
+ </attr3>
117
+ <attr3ID>3</attr3ID>
118
+ </fooobject>
119
+ </row>
120
+ </ndr>
File without changes
@@ -0,0 +1,162 @@
1
+ <?xml version="1.0"?>
2
+ <mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
3
+ <database name="ndr">
4
+ <table_structure name="object">
5
+ <field Field="ObjID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
6
+ <field Field="Bla" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
7
+ <field Field="Blub" Type="varchar(50)" Null="YES" Key="" Extra="" />
8
+ <options Name="object" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
9
+ </table_structure>
10
+ <table_data name="object">
11
+ <row>
12
+ <field name="ObjID">1</field>
13
+ <field name="Bla">12</field>
14
+ <field name="Blub"></field>
15
+ </row>
16
+ <row>
17
+ <field name="ObjID">2</field>
18
+ <field name="Bla">12</field>
19
+ <field name="Blub">hi</field>
20
+ </row>
21
+ <row>
22
+ <field name="ObjID">3</field>
23
+ <field name="Bla">1</field>
24
+ <field name="Blub">ho</field>
25
+ </row>
26
+ </table_data>
27
+ <table_structure name="fooobject">
28
+ <field Field="ObjID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
29
+ <field Field="attr1ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
30
+ <field Field="attr3ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
31
+ <field Field="Foo" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
32
+ <options Name="fooobject" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
33
+ </table_structure>
34
+ <table_data name="fooobject">
35
+ <row>
36
+ <field name="ObjID">1</field>
37
+ <field name="attr1ID">1</field>
38
+ <field name="attr3ID">2</field>
39
+ <field name="Foo">112</field>
40
+ </row>
41
+ <row>
42
+ <field name="ObjID">2</field>
43
+ <field name="attr1ID">2</field>
44
+ <field name="attr3ID">1</field>
45
+ <field name="Foo">122</field>
46
+ </row>
47
+ <row>
48
+ <field name="ObjID">3</field>
49
+ <field name="attr1ID">3</field>
50
+ <field name="attr3ID">3</field>
51
+ <field name="Foo">111</field>
52
+ </row>
53
+ </table_data>
54
+ <table_structure name="barobject">
55
+ <field Field="ObjID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
56
+ <field Field="attr4ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
57
+ <field Field="Bar" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
58
+ <options Name="barobject" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
59
+ </table_structure>
60
+ <table_data name="barobject">
61
+ <row>
62
+ <field name="ObjID">1</field>
63
+ <field name="attr4ID">2</field>
64
+ <field name="Bar">1002</field>
65
+ </row>
66
+ <row>
67
+ <field name="ObjID">2</field>
68
+ <field name="attr4ID">1</field>
69
+ <field name="Bar">1200</field>
70
+ </row>
71
+ <row>
72
+ <field name="ObjID">3</field>
73
+ <field name="attr4ID">3</field>
74
+ <field name="Bar">1000</field>
75
+ </row>
76
+ </table_data>
77
+ <table_structure name="attr1">
78
+ <field Field="ObjID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
79
+ <field Field="attr1ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
80
+ <field Field="Val" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
81
+ <options Name="attr1" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
82
+ </table_structure>
83
+ <table_data name="attr1">
84
+ <row>
85
+ <field name="ObjID">1</field>
86
+ <field name="attr1ID">1</field>
87
+ <field name="Val">3</field>
88
+ </row>
89
+ <row>
90
+ <field name="ObjID">2</field>
91
+ <field name="attr1ID">2</field>
92
+ <field name="Val">2</field>
93
+ </row>
94
+ <row>
95
+ <field name="ObjID">3</field>
96
+ <field name="attr1ID">3</field>
97
+ <field name="Val">1</field>
98
+ </row>
99
+ </table_data>
100
+ <table_structure name="attr2">
101
+ <field Field="ObjID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
102
+ <field Field="attr2ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
103
+ <field Field="Val" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
104
+ <options Name="attr2" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
105
+ </table_structure>
106
+ <table_data name="attr2">
107
+ <row>
108
+ <field name="ObjID">1</field>
109
+ <field name="attr2ID">3</field>
110
+ <field name="Val">4</field>
111
+ </row>
112
+ <row>
113
+ <field name="ObjID">2</field>
114
+ <field name="attr2ID">2</field>
115
+ <field name="Val">5</field>
116
+ </row>
117
+ <row>
118
+ <field name="ObjID">3</field>
119
+ <field name="attr2ID">1</field>
120
+ <field name="Val">6</field>
121
+ </row>
122
+ </table_data>
123
+ <table_structure name="attr3">
124
+ <field Field="attr3ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
125
+ <field Field="Val" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
126
+ <options Name="attr3" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
127
+ </table_structure>
128
+ <table_data name="attr3">
129
+ <row>
130
+ <field name="attr3ID">1</field>
131
+ <field name="Val">0</field>
132
+ </row>
133
+ <row>
134
+ <field name="attr3ID">2</field>
135
+ <field name="Val">8</field>
136
+ </row>
137
+ <row>
138
+ <field name="attr3ID">3</field>
139
+ <field name="Val">7</field>
140
+ </row>
141
+ </table_data>
142
+ <table_structure name="attr4">
143
+ <field Field="attr4ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
144
+ <field Field="Val" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
145
+ <options Name="attr4" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
146
+ </table_structure>
147
+ <table_data name="attr4">
148
+ <row>
149
+ <field name="attr4ID">1</field>
150
+ <field name="Val">0</field>
151
+ </row>
152
+ <row>
153
+ <field name="attr4ID">2</field>
154
+ <field name="Val">0</field>
155
+ </row>
156
+ <row>
157
+ <field name="attr4ID">3</field>
158
+ <field name="Val">9</field>
159
+ </row>
160
+ </table_data>
161
+ </database>
162
+ </mysqldump>
@@ -0,0 +1,10 @@
1
+ object:
2
+ attr1: ObjID
3
+ attr2: ObjID
4
+ fooobject:
5
+ @key: ObjID
6
+ attr1: attr1ID
7
+ attr3: attr3ID
8
+ barobject:
9
+ @key: ObjID
10
+ attr4: attr4ID
@@ -0,0 +1,99 @@
1
+ #--
2
+ ###############################################################################
3
+ # #
4
+ # A component of flattendb, the relational database flattener. #
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
+ # flattendb is free software; you can redistribute it and/or modify it under #
14
+ # the terms of the GNU General Public License as published by the Free #
15
+ # Software Foundation; either version 3 of the License, or (at your option) #
16
+ # any later version. #
17
+ # #
18
+ # flattendb is distributed in the hope that it will be useful, but WITHOUT #
19
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
20
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
21
+ # more details. #
22
+ # #
23
+ # You should have received a copy of the GNU General Public License along #
24
+ # with flattendb. If not, see <http://www.gnu.org/licenses/>. #
25
+ # #
26
+ ###############################################################################
27
+ #++
28
+
29
+ require 'rubygems'
30
+ require 'builder'
31
+
32
+ module FlattenDB
33
+
34
+ class Base
35
+
36
+ @types = {}
37
+
38
+ BUILDER_OPTIONS = {
39
+ :xml => {
40
+ :indent => 2
41
+ }
42
+ }
43
+
44
+ # cf. <http://www.w3.org/TR/2006/REC-xml-20060816/#NT-Name>
45
+ ELEMENT_START = %r{^[a-zA-Z_:]}
46
+ ELEMENT_CHARS = %q{\w:.-}
47
+
48
+ class << self
49
+
50
+ def types
51
+ Base.instance_variable_get :@types
52
+ end
53
+
54
+ def [](type)
55
+ types[type]
56
+ end
57
+
58
+ protected
59
+
60
+ def inherited(klass)
61
+ types[klass.name.split('::')[1..-1].downcase.to_sym] = klass
62
+ end
63
+
64
+ end
65
+
66
+ def flatten!(*args)
67
+ raise NotImplementedError, 'must be defined by sub-class'
68
+ end
69
+
70
+ def to_xml(*args)
71
+ raise NotImplementedError, 'must be defined by sub-class'
72
+ end
73
+
74
+ private
75
+
76
+ def initialize_builder(type, output, builder_options = {})
77
+ builder_options = (BUILDER_OPTIONS[type] || {}).merge(builder_options)
78
+
79
+ @builder = case type
80
+ when :xml
81
+ Builder::XmlMarkup.new(builder_options.merge(:target => output))
82
+ else
83
+ raise ArgumentError, "builder of type '#{type}' not supported"
84
+ end
85
+ end
86
+
87
+ # mysql:: <http://dev.mysql.com/doc/refman/5.0/en/identifiers.html>
88
+ def column_to_element(column)
89
+ element = column.dup
90
+
91
+ element.insert(0, '_') unless element =~ ELEMENT_START
92
+ element.gsub!(/[^#{ELEMENT_CHARS}]/, '')
93
+
94
+ element
95
+ end
96
+
97
+ end
98
+
99
+ end