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 +27 -0
- data/README +17 -0
- data/gemspec.rb +13 -0
- data/lib/file_formatter.rb +19 -0
- data/lib/file_formatter_input.rb +52 -0
- data/lib/file_formatter_input_data.rb +131 -0
- data/lib/file_formatter_output.rb +54 -0
- data/lib/file_formatter_output_data.rb +53 -0
- data/manual.doc +0 -0
- metadata +55 -0
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
|
+
|