rsmart_toolbox 0.1

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.md ADDED
@@ -0,0 +1,31 @@
1
+ # RsmartToolbox
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'rsmart_toolbox'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install rsmart_toolbox
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/rsmart_toolbox/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ # rSmart client library and command-line tool to help interact with rSmart's cloud APIs.
2
+ # Copyright (C) 2014 The rSmart Group, Inc.
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require "bundler/gem_tasks"
18
+ require "rspec/core/rake_task"
19
+
20
+ task :default => [:spec]
21
+ task :test => [:spec]
22
+
23
+ desc "Run the specs."
24
+ RSpec::Core::RakeTask.new do |t|
25
+ t.pattern = "spec/**/*_spec.rb"
26
+ end
@@ -0,0 +1,23 @@
1
+ # rSmart client library and command-line tool to help interact with rSmart's cloud APIs.
2
+ # Copyright (C) 2014 The rSmart Group, Inc.
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'csv'
18
+ require 'optparse'
19
+ require 'pp'
20
+ require "rsmart_toolbox/version"
21
+
22
+ module RsmartToolbox
23
+ end
@@ -0,0 +1,240 @@
1
+ # rSmart client library and command-line tool to help interact with rSmart's cloud APIs.
2
+ # Copyright (C) 2014 The rSmart Group, Inc.
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require "rsmart_toolbox"
18
+
19
+ module RsmartToolbox::ETL
20
+
21
+ class TextParseError < StandardError
22
+ end
23
+
24
+ # Responds to String or Exception.
25
+ def self.error(e)
26
+ if e.kind_of? String
27
+ # default to TextParseError
28
+ return TextParseError.new "ERROR: Line #{$INPUT_LINE_NUMBER}: #{e}"
29
+ end
30
+ if e.kind_of? Exception
31
+ return e.exception "ERROR: Line #{$INPUT_LINE_NUMBER}: #{e}"
32
+ end
33
+ raise ArgumentError, "Unsupported error type: #{e.class}"
34
+ end
35
+
36
+ # Responds to String or Exception.
37
+ def self.warning(e)
38
+ if e.kind_of? String
39
+ # default to TextParseError
40
+ return TextParseError.new "WARN: Line #{$INPUT_LINE_NUMBER}: #{e}"
41
+ end
42
+ if e.kind_of? Exception
43
+ return e.exception "WARN: Line #{$INPUT_LINE_NUMBER}: #{e}"
44
+ end
45
+ raise ArgumentError, "Unsupported error type: #{e.class}"
46
+ end
47
+
48
+ # Test to see if subject is a member of valid_values Array
49
+ def self.valid_value(subject, valid_values, opt={})
50
+ raise ArgumentError, "valid_values must not be nil!" if valid_values.nil?
51
+ if valid_values.kind_of? Regexp
52
+ return true if subject =~ valid_values
53
+ end
54
+ if valid_values.kind_of? Array
55
+ raise ArgumentError, "valid_values must have at least one element!" unless valid_values.length > 0
56
+ if opt[:case_sensitive] == false # case insensitive comparison requested
57
+ raise ArgumentError, "case_sensitive only supported for Strings!" unless subject.kind_of?(String)
58
+ valid_values.each do |valid_value|
59
+ return true if valid_value.casecmp(subject) == 0
60
+ end
61
+ end
62
+ return true if valid_values.include? subject # default to == equality
63
+ end
64
+ return false
65
+ end
66
+
67
+ def self.parse_boolean(str, opt={})
68
+ return true if str == true
69
+ return false if str == false
70
+ b = parse_string str, opt
71
+ return true if b =~ /^(active|a|true|t|yes|y|1)$/i
72
+ return false if b =~ /^(inactive|i|false|f|no|n|0)$/i
73
+ if b.empty? && !opt[:default].nil?
74
+ return opt[:default]
75
+ end
76
+ if b.empty?
77
+ return nil
78
+ end
79
+ raise RsmartToolbox::ETL::error TextParseError.new "invalid value for Boolean: '#{str}'"
80
+ end
81
+
82
+ # Simply here to help ensure we consistently apply the same encoding options.
83
+ def self.encode(str, opt={} )
84
+ opt[:encoding] = "UTF-8" if opt[:encoding].nil?
85
+ str.encode( opt[:encoding], :invalid => :replace,
86
+ :undef => :replace, :replace => "" )
87
+ end
88
+
89
+ # Matches MRI CSV specification:
90
+ # The header String is downcased, spaces are replaced with underscores,
91
+ # non-word characters are dropped, and finally to_sym() is called.
92
+ def self.to_symbol(str)
93
+ raise ArgumentError, "Illegal symbol name: '#{str}'" if str.nil? || str.empty?
94
+ encode( str.downcase.gsub(/\s+/, "_").gsub(/\W+/, "") ).to_sym
95
+ end
96
+
97
+ # DRY up some common string manipulation
98
+ def self.mutate_sql_stmt!(insert_str, column_name, values_str, value)
99
+ insert_str.concat "#{column_name.upcase},"
100
+ # TODO what are all of the valid types that should not be quoted?
101
+ if value.kind_of? Integer
102
+ values_str.concat "#{value},"
103
+ else
104
+ values_str.concat "'#{value}',"
105
+ end
106
+ end
107
+
108
+ def self.escape_single_quotes(str)
109
+ if str.nil?
110
+ return nil
111
+ end
112
+ return str.to_s.gsub("'", "\\\\'")
113
+ end
114
+
115
+ def self.parse_string(str, opt={})
116
+ opt[:strict] = true if opt[:strict].nil?
117
+ retval = encode str.to_s.strip
118
+ if opt[:required] && retval.empty?
119
+ raise RsmartToolbox::ETL::error TextParseError.new "Required data element '#{opt[:name]}' not found: '#{str}'"
120
+ end
121
+ if opt[:default] && retval.empty?
122
+ retval = opt[:default]
123
+ end
124
+ if opt[:length] && retval.length > opt[:length].to_i
125
+ detail = "#{opt[:name]}.length > #{opt[:length]}: '#{str}'-->'#{str[0..(opt[:length] - 1)]}'"
126
+ if opt[:strict]
127
+ raise RsmartToolbox::ETL::error TextParseError.new "Data exceeds maximum field length: #{detail}"
128
+ end
129
+ RsmartToolbox::ETL::warning "Data will be truncated: #{detail}"
130
+ end
131
+ if opt[:valid_values] && ! valid_value(retval, opt[:valid_values], opt)
132
+ raise RsmartToolbox::ETL::error TextParseError.new "Illegal #{opt[:name]}: value '#{str}' not found in: #{opt[:valid_values]}"
133
+ end
134
+ return escape_single_quotes retval
135
+ end
136
+
137
+ def self.parse_string!(row, insert_str, values_str, opt={})
138
+ raise ArgumentError, "opt[:name] is required!" unless opt[:name]
139
+ str = parse_string( row[ to_symbol( opt[:name] ) ], opt )
140
+ mutate_sql_stmt! insert_str, opt[:name], values_str, str
141
+ end
142
+
143
+ def self.parse_integer(str, opt={})
144
+ s = parse_string str, opt
145
+ if s.empty?
146
+ return nil;
147
+ else
148
+ return s.to_i
149
+ end
150
+ end
151
+
152
+ def self.parse_integer!(row, insert_str, values_str, opt={})
153
+ raise ArgumentError, "opt[:name] is required!" unless opt[:name]
154
+ i = parse_integer( row[ to_symbol( opt[:name] ) ], opt )
155
+ mutate_sql_stmt! insert_str, opt[:name], values_str, i
156
+ end
157
+
158
+ def self.parse_float(str, opt={})
159
+ s = parse_string str, opt
160
+ if s.empty?
161
+ return nil;
162
+ else
163
+ return s.to_f
164
+ end
165
+ end
166
+
167
+ # Useful for parsing "flag" like values. Always returns upcase for consistency.
168
+ # Assumes :strict :length of 1 by default.
169
+ def self.parse_flag(str, opt={})
170
+ opt[:length] = 1 if opt[:length].nil?
171
+ opt[:upcase] = true if opt[:upcase].nil?
172
+ retval = parse_string str, opt
173
+ retval = retval.upcase if opt[:upcase] == true
174
+ return retval
175
+ end
176
+
177
+ # Designed specifically for actv_ind, but could be used on *any*
178
+ # fields that matches /^(Y|N)$/i.
179
+ def self.parse_actv_ind(str, opt={})
180
+ # `ACTV_IND` varchar(1) COLLATE utf8_bin DEFAULT 'Y',
181
+ opt[:name] = "actv_ind" if opt[:name].nil?
182
+ opt[:default] = "Y" if opt[:default].nil?
183
+ opt[:valid_values] = /^(Y|N)$/i if opt[:valid_values].nil?
184
+ return parse_flag str, opt
185
+ end
186
+
187
+ # Designed specifically for actv_ind, but could be used on *any*
188
+ # fields that matches /^(Y|N)$/i.
189
+ def self.parse_actv_ind!(row, insert_str, values_str, opt={})
190
+ # `ACTV_IND` varchar(1) COLLATE utf8_bin DEFAULT 'Y',
191
+ opt[:name] = "actv_ind" if opt[:name].nil?
192
+ actv_ind = RsmartToolbox::ETL::parse_actv_ind row[ to_symbol( opt[:name] ) ]
193
+ RsmartToolbox::ETL::mutate_sql_stmt! insert_str, opt[:name], values_str, actv_ind
194
+ end
195
+
196
+ # Parse common command line options for CSV --> SQL transformations.
197
+ def self.parse_csv_command_line_options(
198
+ executable, args, opt={ csv_options: { headers: :first_row,
199
+ header_converters: :symbol,
200
+ skip_blanks: true,
201
+ col_sep: ",", # comma by default
202
+ quote_char: '"', # double quote by default
203
+ }
204
+ } )
205
+ optparse = OptionParser.new do |opts|
206
+ opts.banner = "Usage: #{executable} [options] csv_file"
207
+ opts.on( '-o [sql_file_output]' ,'--output [sql_file_output]', 'The file the SQL data will be writen to... (defaults to <csv_file>.sql)') do |f|
208
+ opt[:sql_filename] = f
209
+ end
210
+ opts.on( '-s [separator_character]' ,'--separator [separator_character]', 'The character that separates each column of the CSV file.') do |s|
211
+ opt[:col_sep] = s
212
+ end
213
+ opts.on( '-q [quote_character]' ,'--quote [quote_character]', 'The character used to quote fields.') do |q|
214
+ opt[:quote_char] = q
215
+ end
216
+ opts.on( '-h', '--help', 'Display this screen' ) do
217
+ puts opts
218
+ exit 1
219
+ end
220
+
221
+ opt[:csv_filename] = args[0] unless opt[:csv_filename]
222
+ if opt[:csv_filename].nil? || opt[:csv_filename].empty?
223
+ puts opts
224
+ exit 1
225
+ end
226
+ end
227
+ optparse.parse!
228
+
229
+ # construct a sensible default ouptput filename
230
+ unless opt[:sql_filename]
231
+ file_extension = File.extname opt[:csv_filename]
232
+ dir_name = File.dirname opt[:csv_filename]
233
+ base_name = File.basename opt[:csv_filename], file_extension
234
+ opt[:sql_filename] = "#{dir_name}/#{base_name}.sql"
235
+ end
236
+
237
+ return opt
238
+ end
239
+
240
+ end
@@ -0,0 +1,190 @@
1
+ # rSmart client library and command-line tool to help interact with rSmart's cloud APIs.
2
+ # Copyright (C) 2014 The rSmart Group, Inc.
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require "rsmart_toolbox/etl"
18
+
19
+ module RsmartToolbox::ETL::GRM
20
+
21
+ def self.parse_rolodex_id!(row, insert_str, values_str, opt={})
22
+ # `ROLODEX_ID` decimal(6,0) NOT NULL DEFAULT '0',
23
+ opt[:name] = "ROLODEX_ID" if opt[:name].nil?
24
+ opt[:required] = true if opt[:required].nil?
25
+ opt[:length] = 6 if opt[:length].nil?
26
+ RsmartToolbox::ETL::parse_integer! row, insert_str, values_str, opt
27
+ end
28
+
29
+ def self.parse_country_code!(row, insert_str, values_str, opt={})
30
+ # `COUNTRY_CODE` char(3) COLLATE utf8_bin DEFAULT NULL,
31
+ opt[:name] = "COUNTRY_CODE" if opt[:name].nil?
32
+ opt[:length] = 3 if opt[:length].nil?
33
+ RsmartToolbox::ETL::parse_string! row, insert_str, values_str, opt
34
+ end
35
+
36
+ def self.parse_state!(row, insert_str, values_str, opt={})
37
+ # `STATE` varchar(30) COLLATE utf8_bin DEFAULT NULL,
38
+ opt[:name] = "STATE" if opt[:name].nil?
39
+ opt[:length] = 30 if opt[:length].nil?
40
+ RsmartToolbox::ETL::parse_string! row, insert_str, values_str, opt
41
+ end
42
+
43
+ def self.parse_sponsor_code!(row, insert_str, values_str, opt={})
44
+ # `SPONSOR_CODE` char(6) COLLATE utf8_bin NOT NULL DEFAULT '',
45
+ opt[:name] = "SPONSOR_CODE" if opt[:name].nil?
46
+ opt[:required] = true if opt[:required].nil?
47
+ opt[:length] = 6 if opt[:length].nil?
48
+ RsmartToolbox::ETL::parse_string! row, insert_str, values_str, opt
49
+ end
50
+
51
+ def self.parse_postal_code!(row, insert_str, values_str, opt={})
52
+ # `POSTAL_CODE` varchar(15) COLLATE utf8_bin DEFAULT NULL,
53
+ opt[:name] = "POSTAL_CODE" if opt[:name].nil?
54
+ opt[:length] = 15 if opt[:length].nil?
55
+ RsmartToolbox::ETL::parse_string! row, insert_str, values_str, opt
56
+ end
57
+
58
+ def self.parse_owned_by_unit!(row, insert_str, values_str, opt={})
59
+ # `OWNED_BY_UNIT` varchar(8) COLLATE utf8_bin NOT NULL,
60
+ opt[:name] = "OWNED_BY_UNIT" if opt[:name].nil?
61
+ opt[:required] = true if opt[:required].nil?
62
+ opt[:length] = 8 if opt[:length].nil?
63
+ RsmartToolbox::ETL::parse_string! row, insert_str, values_str, opt
64
+ end
65
+
66
+ def self.parse_email_address(str, opt={})
67
+ # `EMAIL_ADDRESS` varchar(60) COLLATE utf8_bin DEFAULT NULL,
68
+ opt[:name] = "EMAIL_ADDRESS" if opt[:name].nil?
69
+ opt[:length] = 60 if opt[:length].nil?
70
+ opt[:valid_values] = /^(([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?))?$/ if opt[:valid_values].nil?
71
+ return RsmartToolbox::ETL::parse_string str, opt
72
+ end
73
+
74
+ def self.parse_email_address!(row, insert_str, values_str, opt={})
75
+ # `EMAIL_ADDRESS` varchar(60) COLLATE utf8_bin DEFAULT NULL,
76
+ opt[:name] = "EMAIL_ADDRESS" if opt[:name].nil?
77
+ email_address = parse_email_address row[ RsmartToolbox::ETL::to_symbol( opt[:name] ) ]
78
+ RsmartToolbox::ETL::mutate_sql_stmt! insert_str, opt[:name], values_str, email_address
79
+ end
80
+
81
+ def self.parse_principal_id(str, opt={})
82
+ # `PRNCPL_ID` varchar(40) COLLATE utf8_bin NOT NULL DEFAULT '',
83
+ opt[:name] = "PRNCPL_ID" if opt[:name].nil?
84
+ opt[:required] = true if opt[:required].nil?
85
+ opt[:length] = 40 if opt[:length].nil?
86
+ RsmartToolbox::ETL::parse_string str, opt
87
+ end
88
+
89
+ def self.parse_principal_name(str, opt={})
90
+ # `PRNCPL_NM` varchar(100) COLLATE utf8_bin NOT NULL,
91
+ opt[:name] = "PRNCPL_NM" if opt[:name].nil?
92
+ opt[:length] = 100 if opt[:length].nil?
93
+ opt[:required] = true if opt[:required].nil?
94
+ prncpl_nm = RsmartToolbox::ETL::parse_string str, opt
95
+ unless prncpl_nm =~ /^([a-z0-9\@\.\_\-]+)$/
96
+ raise RsmartToolbox::ETL::error TextParseError.new "Illegal prncpl_nm found: '#{prncpl_nm}'"
97
+ end
98
+ return prncpl_nm
99
+ end
100
+
101
+ def self.parse_emp_stat_cd(str, opt={})
102
+ # `EMP_STAT_CD` varchar(40) COLLATE utf8_bin DEFAULT NULL,
103
+ opt[:name] = "EMP_STAT_CD" if opt[:name].nil?
104
+ opt[:valid_values] = /^(A|D|L|N|P|R|S|T)$/i if opt[:valid_values].nil?
105
+ return RsmartToolbox::ETL::parse_flag str, opt
106
+ end
107
+
108
+ def self.parse_emp_typ_cd(str, opt={})
109
+ # `EMP_TYP_CD` varchar(40) COLLATE utf8_bin DEFAULT NULL,
110
+ opt[:name] = "EMP_TYP_CD" if opt[:name].nil?
111
+ opt[:valid_values] = /^(N|O|P)$/i if opt[:valid_values].nil?
112
+ return RsmartToolbox::ETL::parse_flag str, opt
113
+ end
114
+
115
+ def self.parse_address_type_code(str, opt={})
116
+ # TODO find real column name
117
+ opt[:name] = "TODO_address_type_code" if opt[:name].nil?
118
+ opt[:length] = 3 if opt[:length].nil?
119
+ opt[:valid_values] = /^(HM|OTH|WRK)$/i if opt[:valid_values].nil?
120
+ return RsmartToolbox::ETL::parse_flag str, opt
121
+ end
122
+
123
+ def self.parse_name_code(str, opt={})
124
+ opt[:name] = "NM_TYP_CD" if opt[:name].nil?
125
+ opt[:length] = 4 if opt[:length].nil?
126
+ opt[:valid_values] = /^(OTH|PRFR|PRM)$/i if opt[:valid_values].nil?
127
+ return RsmartToolbox::ETL::parse_flag str, opt
128
+ end
129
+
130
+ def self.parse_prefix(str, opt={})
131
+ opt[:name] = "PREFIX_NM" if opt[:name].nil?
132
+ opt[:length] = 3 if opt[:length].nil?
133
+ opt[:valid_values] = /^(Ms|Mrs|Mr|Dr)?$/ if opt[:valid_values].nil?
134
+ opt[:upcase] = false if opt[:upcase].nil?
135
+ return RsmartToolbox::ETL::parse_flag str, opt
136
+ end
137
+
138
+ def self.parse_suffix(str, opt={})
139
+ opt[:name] = "SUFFIX_NM" if opt[:name].nil?
140
+ opt[:length] = 3 if opt[:length].nil?
141
+ opt[:valid_values] = /^(Jr|Sr|Mr|Md)?$/ if opt[:valid_values].nil?
142
+ opt[:upcase] = false if opt[:upcase].nil?
143
+ return RsmartToolbox::ETL::parse_flag str, opt
144
+ end
145
+
146
+ def self.parse_phone_type(str, opt={})
147
+ # TODO find real column name
148
+ opt[:name] = "TODO_phone_type" if opt[:name].nil?
149
+ opt[:length] = 3 if opt[:length].nil?
150
+ opt[:valid_values] = /^(FAX|HM|MBL|OTH|WRK)$/i if opt[:valid_values].nil?
151
+ return RsmartToolbox::ETL::parse_flag str, opt
152
+ end
153
+
154
+ def self.parse_phone_number(str, opt={})
155
+ # TODO find real column name
156
+ opt[:name] = "PHONE_NBR" if opt[:name].nil?
157
+ opt[:length] = 12 if opt[:length].nil?
158
+ opt[:valid_values] = /^(\d{3}-\d{3}-\d{4})?$/ if opt[:valid_values].nil?
159
+ return RsmartToolbox::ETL::parse_string str, opt
160
+ end
161
+
162
+ def self.parse_email_type(str, opt={})
163
+ opt[:name] = "EMAIL_TYP_CD" if opt[:name].nil?
164
+ opt[:length] = 3 if opt[:length].nil?
165
+ opt[:valid_values] = /^(HM|OTH|WRK)$/i if opt[:valid_values].nil?
166
+ return RsmartToolbox::ETL::parse_flag str, opt
167
+ end
168
+
169
+ def self.parse_year(str, opt={})
170
+ opt[:length] = 4 if opt[:length].nil?
171
+ opt[:valid_values] = /^(\d{4})?$/ if opt[:valid_values].nil?
172
+ return RsmartToolbox::ETL::parse_string str, opt
173
+ end
174
+
175
+ def self.parse_citizenship_type(str, opt={})
176
+ opt[:name] = "CITIZENSHIP_TYPE_CODE" if opt[:name].nil?
177
+ opt[:valid_values] = /^([1-4])$/ if opt[:valid_values].nil?
178
+ return RsmartToolbox::ETL::parse_flag str, opt
179
+ end
180
+
181
+ def self.parse_degree(str, opt={})
182
+ # TODO find real column name
183
+ opt[:name] = "DEGREE" if opt[:name].nil?
184
+ opt[:length] = 5 if opt[:length].nil?
185
+ opt[:valid_values] = /^(AS|BA|BComm|BEd|BS|DA|DC|DD|DDS|DEng|DFA|DH|DHA|DMin|DPA|DSN|DVM|DVS|HS|JD|LLD|LLM|MA|MAEd|MArch|MBA|MD|MDS|MDiv|MEE|MEd|MEng|MFA|MIS|MLS|MPA|MPE|MPH|MPd|MPhil|MS|MSEd|MST|MSW|MTh|PhD|PharD|ScD|ThD|UKNW)?$/ if opt[:valid_values].nil?
186
+ opt[:upcase] = false if opt[:upcase].nil?
187
+ return RsmartToolbox::ETL::parse_flag str, opt
188
+ end
189
+
190
+ end