file-formatter 0.2.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/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ File-Formatter for Ruby
2
+ -----------------------
3
+ Homepage: http://rubyforge.org/projects/file-formatter/
4
+ Copyright: Copyright � 2007 Daniel Mantilla.
5
+ Summary: MIT-style
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ * The names of its contributors may not be used to endorse or promote
15
+ products derived from this software without specific prior written
16
+ permission.
17
+
18
+ The above copyright notice and this permission notice shall be included in
19
+ all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
data/README ADDED
@@ -0,0 +1,17 @@
1
+ File Formatter for Ruby
2
+ -----------------------
3
+ This library provides the ability to transform delimited or fixed length files
4
+ into another delimited file. It's completely flexible on the names used and
5
+ full Ruby expressions can be used when generating the output.
6
+ Please refer to the documentation ("manual.doc") for further explanation.
7
+
8
+ Homepage:: http://rubyforge.org/projects/file-formatter/
9
+ Copyright:: 2007, Daniel Mantilla
10
+
11
+ LICENSE NOTES
12
+ -------------
13
+ Please read the file LICENSE for licensing restrictions on this library.
14
+
15
+ Requirements
16
+ ------------
17
+ File-Formatter requires Ruby 1.8.2 or better, it uses CSV to parse delimited files.
data/gemspec.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ SPEC = Gem::Specification.new do |s|
3
+ s.name = "file-formatter"
4
+ s.version = "0.2.1"
5
+ s.author = "Daniel Mantilla"
6
+ s.email = "dmantilla@yahoo.com"
7
+ s.homepage = "http://appcabinet.com"
8
+ s.platform = Gem::Platform::RUBY
9
+ s.summary = "Transforms a fixed/delimited file into another delimited file"
10
+ s.files = Dir["./*"] + Dir["*/**"]
11
+ s.has_rdoc = true
12
+ s.require_path = "lib"
13
+ end
@@ -0,0 +1,19 @@
1
+ require 'file_formatter_input'
2
+ require 'file_formatter_input_data'
3
+ require 'file_formatter_output'
4
+ require 'file_formatter_output_data'
5
+
6
+ class FileFormatter
7
+
8
+ # CONSTANTS
9
+
10
+ DATA_FORMATS = [:delimited, :fixed]
11
+ DATA_DELIMITERS = {
12
+ :colon => ':',
13
+ :semicolon => ';',
14
+ :pipe => '|',
15
+ :space => ' ',
16
+ :comma => ',',
17
+ :dot => '.'
18
+ }
19
+ end
@@ -0,0 +1,52 @@
1
+ class FileFormatterInput
2
+
3
+ include Reloadable if defined? Reloadable
4
+
5
+ attr_accessor :__yaml__, :file_path, :file_name
6
+
7
+ def initialize(yaml_def)
8
+ raise 'No definition was provided' if yaml_def.size.zero?
9
+
10
+ @__yaml__ = yaml_def.dup
11
+
12
+ @data = FileFormatterInputData.new
13
+
14
+ # Load Yaml into a hash
15
+ input_def = YAML::load(yaml_def)
16
+ raise 'Hash was not provided.' unless input_def.is_a? Hash
17
+ raise 'No entries exist in the Hash' if input_def.length.zero?
18
+
19
+ input_def.each {|k,v| instance_eval("self.#{k}=v")}
20
+ end
21
+
22
+ def data; @data; end
23
+ def data=(value); @data.data = value; end
24
+
25
+ def file_full_name; File.join(file_path, file_name); end
26
+
27
+ def parse(max_lines=nil)
28
+ input = File.open(file_full_name)
29
+
30
+ i = 0
31
+
32
+ while !input.eof?
33
+ @data.__set_content__(input.readline)
34
+
35
+ yield @data
36
+
37
+ break if (i += 1) == max_lines
38
+ end
39
+
40
+ input.close
41
+ input = nil
42
+ end
43
+
44
+ def method_missing(sym, *args)
45
+ if sym.to_s == @data.__name__
46
+ @data
47
+ else
48
+ super(sym, *args)
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,131 @@
1
+ class FileFormatterInputData
2
+
3
+ include Reloadable if defined? Reloadable
4
+
5
+ attr_accessor :data, :__name__, :__format__, :__delimiter__
6
+
7
+ def initialize
8
+ @__format__ = :delimited
9
+ @__delimiter__ = :comma
10
+ # A hash is used to speed things up a bit
11
+ @children = []
12
+ end
13
+
14
+ def __set_content__(text_line)
15
+ if __format__ == :delimited
16
+ # Parse the line (space separator has a different behaviour)
17
+ if __delimiter__ == :space
18
+ @content = text_line.split(FileFormatter::DATA_DELIMITERS[__delimiter__])
19
+ else
20
+ @content = CSV::parse_line(text_line, FileFormatter::DATA_DELIMITERS[__delimiter__])
21
+ end
22
+ else
23
+ # Fixed format
24
+ @content = []
25
+ i = 0
26
+ @data.keys.sort.each do |k|
27
+ # There may be situations where indexed are skipped, as a result
28
+ # some nil values may be stored in the array
29
+ if @data[k]
30
+ #puts @data[k].to_yaml
31
+ @content << text_line[i, @data[k][1]]
32
+ i += @data[k][1]
33
+ end
34
+ end
35
+ end
36
+ # Check if there are any other objects embedded
37
+ @children.each {|item| item[1].__set_content__(@content[item[0]])}
38
+ end
39
+
40
+ def __format__=(value)
41
+ symbol_value = value.is_a?(Symbol) ? value : value.downcase.intern
42
+
43
+ if FileFormatter::DATA_FORMATS.include? symbol_value
44
+ @__format__ = symbol_value
45
+ else
46
+ raise "Invalid format '#{value}'"
47
+ end
48
+ end
49
+
50
+ def __delimiter__=(value)
51
+ symbol_value = value.is_a?(Symbol) ? value : value.downcase.intern
52
+
53
+ if FileFormatter::DATA_DELIMITERS.include? symbol_value
54
+ @__delimiter__ = symbol_value
55
+ else
56
+ raise "Invalid delimiter '#{value}'"
57
+ end
58
+ end
59
+
60
+ def data=(hash_value)
61
+ @data = {}
62
+
63
+ # Make sure the file format is set first if specified
64
+ self.__format__ = hash_value['format'] if hash_value['format']
65
+
66
+ hash_value.each do |k,v|
67
+ # Only string keys are stored as properties and removed from hash
68
+ if k.is_a? String
69
+ instance_eval("self.__#{k}__ = v")
70
+ hash_value.delete(k)
71
+ elsif k.is_a? Fixnum
72
+ # If the value has a hash
73
+ if v.is_a? Hash
74
+ # And the hash is a data element, create a new instance of the class
75
+ if v.include? 'data'
76
+ input_data = FileFormatterInputData.new
77
+ input_data.data = v['data']
78
+ @data[k] = [input_data]
79
+ @children << [k,input_data]
80
+ end
81
+ else
82
+ # Not a hash? the value is stored as an array always
83
+ # If it's a fixed format file, make sure there are two values
84
+ # the first is the field name and the second the length
85
+ if __format__ == :fixed
86
+ field_name, field_length = v.split(',')
87
+ # If the length was not specified, throw error
88
+ if field_length.to_i.zero?
89
+ raise "Field #{field_name} has not length associated."
90
+ else
91
+ @data[k] = [field_name, field_length.to_i]
92
+ end
93
+ else
94
+ @data[k] = [v]
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ def method_missing(sym, *args)
102
+ element_name = sym.to_s
103
+ # We look for the element name in the hash
104
+ # i.e. {1=>'name', 2=>'address'}
105
+ # if a "name" method is requested search in the values and return the key
106
+ if entry = @data.find {|k,v| v[0] == element_name}
107
+ # if there is content (!nil) return the requested element from the array
108
+ @content ? @content[entry[0]].to_s : '[error no input provided]'
109
+
110
+ elsif !@children.size.zero?
111
+ # Check if any of the values that contain instances of FileFormatterInputData matches the symbol
112
+ inner_data = nil
113
+ @data.each do |k,v|
114
+ if v[0].is_a? FileFormatterInputData
115
+ if v[0].__name__ == element_name
116
+ inner_data = v[0]
117
+ break
118
+ end
119
+ end
120
+ end
121
+
122
+ if inner_data
123
+ inner_data
124
+ else
125
+ super(sym, *args)
126
+ end
127
+ else
128
+ super(sym, *args)
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,54 @@
1
+ class FileFormatterOutput
2
+
3
+ include Reloadable if defined? Reloadable
4
+
5
+ attr_accessor :__yaml__, :file_path, :file_name
6
+
7
+ def initialize(yaml_def, formatter_input)
8
+ raise 'No definition was provided' if yaml_def.size.zero?
9
+
10
+ @__yaml__ = yaml_def.dup
11
+
12
+ @data = FileFormatterOutputData.new(formatter_input)
13
+
14
+ # Load Yaml into a hash
15
+ output_def = YAML::load(yaml_def)
16
+ raise 'Hash was not provided.' unless output_def.is_a? Hash
17
+ raise 'No entries exist in the Hash' if output_def.length.zero?
18
+
19
+ output_def.each {|k,v| instance_eval("self.#{k}=v")}
20
+ end
21
+
22
+ def data; @data; end
23
+ def data=(value); @data.data = value; end
24
+
25
+ def file_full_name; File.join(file_path, file_name); end
26
+
27
+ def generate(max_lines=nil)
28
+ input = File.open(@data.__formatter_input__.file_full_name)
29
+ output = File.open(file_full_name, 'w')
30
+
31
+ i = 0
32
+
33
+ while !input.eof?
34
+ @data.__formatter_input__.data.__set_content__(input.readline)
35
+ output_line = @data.__generate_line__
36
+
37
+ yield output_line if block_given?
38
+
39
+ output.puts output_line
40
+
41
+ break if (i += 1) == max_lines
42
+ end
43
+
44
+ output.close
45
+ output = nil
46
+
47
+ input.close
48
+ input = nil
49
+
50
+ return i
51
+ end
52
+
53
+ end
54
+
@@ -0,0 +1,53 @@
1
+ class FileFormatterOutputData
2
+
3
+ include Reloadable if defined? Reloadable
4
+
5
+ attr_accessor :data, :__formatter_input__, :__name__, :__format__, :__delimiter__
6
+
7
+ def initialize(formatter_input)
8
+ @__formatter_input__ = formatter_input
9
+
10
+ @__format__ = :delimited
11
+ @__delimiter__ = :comma
12
+ end
13
+
14
+ def data=(hash_value)
15
+ @data = {}
16
+ hash_value.each do |k,v|
17
+ # Only string keys are stored as properties and removed from hash
18
+ if k.is_a? String
19
+ instance_eval("self.__#{k}__ = v")
20
+ hash_value.delete(k)
21
+ elsif k.is_a? Fixnum
22
+ @data[k] = v
23
+ end
24
+ end
25
+ end
26
+
27
+ def __raw_value__(index); @data.fetch(index, ''); end
28
+
29
+ def __value__(index)
30
+ value = __raw_value__(index).to_s
31
+ instance_eval(value) rescue value
32
+ end
33
+
34
+ def __generate_line__
35
+ array_out = []
36
+ @data.each do |k,v|
37
+ array_out[k] = __value__(k) if k.is_a?(Fixnum)
38
+ end
39
+
40
+ CSV.generate_line(array_out, FileFormatter::DATA_DELIMITERS[__delimiter__])
41
+ end
42
+
43
+ def method_missing(sym, *args)
44
+ # If the requested method matches the name of the formatter_input
45
+ # it is returned, i.e. 'presort_run'
46
+ if @__formatter_input__ and (sym.to_s == @__formatter_input__.data.__name__)
47
+ @__formatter_input__.data
48
+ else
49
+ super(sym, *args)
50
+ end
51
+ end
52
+
53
+ end
data/manual.doc ADDED
Binary file
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: file-formatter
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.2.1
7
+ date: 2007-05-07 00:00:00 -04:00
8
+ summary: Transforms a fixed/delimited file into another delimited file
9
+ require_paths:
10
+ - lib
11
+ email: dmantilla@yahoo.com
12
+ homepage: http://appcabinet.com
13
+ rubyforge_project:
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Daniel Mantilla
31
+ files:
32
+ - ./gemspec.rb
33
+ - ./lib
34
+ - ./LICENSE
35
+ - ./manual.doc
36
+ - ./README
37
+ - lib/file_formatter.rb
38
+ - lib/file_formatter_input.rb
39
+ - lib/file_formatter_input_data.rb
40
+ - lib/file_formatter_output.rb
41
+ - lib/file_formatter_output_data.rb
42
+ test_files: []
43
+
44
+ rdoc_options: []
45
+
46
+ extra_rdoc_files: []
47
+
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ requirements: []
53
+
54
+ dependencies: []
55
+