hashutils 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.
Files changed (48) hide show
  1. data/README +93 -0
  2. data/Rakefile +51 -0
  3. data/doc/classes/Array.html +131 -0
  4. data/doc/classes/Hash.html +137 -0
  5. data/doc/classes/HashUtils.html +131 -0
  6. data/doc/classes/HashUtils.src/M000018.html +20 -0
  7. data/doc/classes/HashUtilsNamedAttributes.html +131 -0
  8. data/doc/classes/HashUtilsNamedAttributes.src/M000019.html +29 -0
  9. data/doc/classes/HashUtilsXML.html +164 -0
  10. data/doc/classes/HashUtilsXML.src/M000015.html +56 -0
  11. data/doc/classes/HashUtilsXML.src/M000016.html +44 -0
  12. data/doc/classes/HashUtilsXML.src/M000017.html +29 -0
  13. data/doc/classes/TC_HashUtilsFromXML.html +170 -0
  14. data/doc/classes/TC_HashUtilsFromXML.src/M000012.html +25 -0
  15. data/doc/classes/TC_HashUtilsFromXML.src/M000013.html +37 -0
  16. data/doc/classes/TC_HashUtilsFromXML.src/M000014.html +18 -0
  17. data/doc/classes/TC_HashUtilsHashAsAttributes.html +170 -0
  18. data/doc/classes/TC_HashUtilsHashAsAttributes.src/M000008.html +18 -0
  19. data/doc/classes/TC_HashUtilsHashAsAttributes.src/M000009.html +19 -0
  20. data/doc/classes/TC_HashUtilsHashAsAttributes.src/M000010.html +20 -0
  21. data/doc/classes/TC_HashUtilsToXML.html +237 -0
  22. data/doc/classes/TC_HashUtilsToXML.src/M000001.html +34 -0
  23. data/doc/classes/TC_HashUtilsToXML.src/M000002.html +22 -0
  24. data/doc/classes/TC_HashUtilsToXML.src/M000003.html +24 -0
  25. data/doc/classes/TC_HashUtilsToXML.src/M000004.html +30 -0
  26. data/doc/classes/TC_HashUtilsToXML.src/M000005.html +22 -0
  27. data/doc/classes/TC_HashUtilsToXML.src/M000006.html +26 -0
  28. data/doc/classes/TC_HashUtilsToXML.src/M000007.html +31 -0
  29. data/doc/classes/TS_HashUtils.html +137 -0
  30. data/doc/classes/TS_HashUtils.src/M000011.html +22 -0
  31. data/doc/created.rid +1 -0
  32. data/doc/files/lib/hashutils_rb.html +108 -0
  33. data/doc/files/rakefile_rb.html +101 -0
  34. data/doc/files/test/tc_hash_utils_from_xml_rb.html +109 -0
  35. data/doc/files/test/tc_hash_utils_hash_as_attributes_rb.html +109 -0
  36. data/doc/files/test/tc_hash_utils_to_xml_rb.html +110 -0
  37. data/doc/files/test/ts_hash_utils_rb.html +112 -0
  38. data/doc/fr_class_index.html +35 -0
  39. data/doc/fr_file_index.html +32 -0
  40. data/doc/fr_method_index.html +45 -0
  41. data/doc/index.html +24 -0
  42. data/doc/rdoc-style.css +208 -0
  43. data/lib/hashutils.rb +178 -0
  44. data/test/tc_hash_utils_from_xml.rb +47 -0
  45. data/test/tc_hash_utils_hash_as_attributes.rb +24 -0
  46. data/test/tc_hash_utils_to_xml.rb +103 -0
  47. data/test/ts_hash_utils.rb +18 -0
  48. metadata +101 -0
data/doc/index.html ADDED
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
5
+
6
+ <!--
7
+
8
+ RDoc Documentation
9
+
10
+ -->
11
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
12
+ <head>
13
+ <title>RDoc Documentation</title>
14
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
15
+ </head>
16
+ <frameset rows="20%, 80%">
17
+ <frameset cols="25%,35%,45%">
18
+ <frame src="fr_file_index.html" title="Files" name="Files" />
19
+ <frame src="fr_class_index.html" name="Classes" />
20
+ <frame src="fr_method_index.html" name="Methods" />
21
+ </frameset>
22
+ <frame src="files/test/ts_hash_utils_rb.html" name="docwin" />
23
+ </frameset>
24
+ </html>
@@ -0,0 +1,208 @@
1
+
2
+ body {
3
+ font-family: Verdana,Arial,Helvetica,sans-serif;
4
+ font-size: 90%;
5
+ margin: 0;
6
+ margin-left: 40px;
7
+ padding: 0;
8
+ background: white;
9
+ }
10
+
11
+ h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
12
+ h1 { font-size: 150%; }
13
+ h2,h3,h4 { margin-top: 1em; }
14
+
15
+ a { background: #eef; color: #039; text-decoration: none; }
16
+ a:hover { background: #039; color: #eef; }
17
+
18
+ /* Override the base stylesheet's Anchor inside a table cell */
19
+ td > a {
20
+ background: transparent;
21
+ color: #039;
22
+ text-decoration: none;
23
+ }
24
+
25
+ /* and inside a section title */
26
+ .section-title > a {
27
+ background: transparent;
28
+ color: #eee;
29
+ text-decoration: none;
30
+ }
31
+
32
+ /* === Structural elements =================================== */
33
+
34
+ div#index {
35
+ margin: 0;
36
+ margin-left: -40px;
37
+ padding: 0;
38
+ font-size: 90%;
39
+ }
40
+
41
+
42
+ div#index a {
43
+ margin-left: 0.7em;
44
+ }
45
+
46
+ div#index .section-bar {
47
+ margin-left: 0px;
48
+ padding-left: 0.7em;
49
+ background: #ccc;
50
+ font-size: small;
51
+ }
52
+
53
+
54
+ div#classHeader, div#fileHeader {
55
+ width: auto;
56
+ color: white;
57
+ padding: 0.5em 1.5em 0.5em 1.5em;
58
+ margin: 0;
59
+ margin-left: -40px;
60
+ border-bottom: 3px solid #006;
61
+ }
62
+
63
+ div#classHeader a, div#fileHeader a {
64
+ background: inherit;
65
+ color: white;
66
+ }
67
+
68
+ div#classHeader td, div#fileHeader td {
69
+ background: inherit;
70
+ color: white;
71
+ }
72
+
73
+
74
+ div#fileHeader {
75
+ background: #057;
76
+ }
77
+
78
+ div#classHeader {
79
+ background: #048;
80
+ }
81
+
82
+
83
+ .class-name-in-header {
84
+ font-size: 180%;
85
+ font-weight: bold;
86
+ }
87
+
88
+
89
+ div#bodyContent {
90
+ padding: 0 1.5em 0 1.5em;
91
+ }
92
+
93
+ div#description {
94
+ padding: 0.5em 1.5em;
95
+ background: #efefef;
96
+ border: 1px dotted #999;
97
+ }
98
+
99
+ div#description h1,h2,h3,h4,h5,h6 {
100
+ color: #125;;
101
+ background: transparent;
102
+ }
103
+
104
+ div#validator-badges {
105
+ text-align: center;
106
+ }
107
+ div#validator-badges img { border: 0; }
108
+
109
+ div#copyright {
110
+ color: #333;
111
+ background: #efefef;
112
+ font: 0.75em sans-serif;
113
+ margin-top: 5em;
114
+ margin-bottom: 0;
115
+ padding: 0.5em 2em;
116
+ }
117
+
118
+
119
+ /* === Classes =================================== */
120
+
121
+ table.header-table {
122
+ color: white;
123
+ font-size: small;
124
+ }
125
+
126
+ .type-note {
127
+ font-size: small;
128
+ color: #DEDEDE;
129
+ }
130
+
131
+ .xxsection-bar {
132
+ background: #eee;
133
+ color: #333;
134
+ padding: 3px;
135
+ }
136
+
137
+ .section-bar {
138
+ color: #333;
139
+ border-bottom: 1px solid #999;
140
+ margin-left: -20px;
141
+ }
142
+
143
+
144
+ .section-title {
145
+ background: #79a;
146
+ color: #eee;
147
+ padding: 3px;
148
+ margin-top: 2em;
149
+ margin-left: -30px;
150
+ border: 1px solid #999;
151
+ }
152
+
153
+ .top-aligned-row { vertical-align: top }
154
+ .bottom-aligned-row { vertical-align: bottom }
155
+
156
+ /* --- Context section classes ----------------------- */
157
+
158
+ .context-row { }
159
+ .context-item-name { font-family: monospace; font-weight: bold; color: black; }
160
+ .context-item-value { font-size: small; color: #448; }
161
+ .context-item-desc { color: #333; padding-left: 2em; }
162
+
163
+ /* --- Method classes -------------------------- */
164
+ .method-detail {
165
+ background: #efefef;
166
+ padding: 0;
167
+ margin-top: 0.5em;
168
+ margin-bottom: 1em;
169
+ border: 1px dotted #ccc;
170
+ }
171
+ .method-heading {
172
+ color: black;
173
+ background: #ccc;
174
+ border-bottom: 1px solid #666;
175
+ padding: 0.2em 0.5em 0 0.5em;
176
+ }
177
+ .method-signature { color: black; background: inherit; }
178
+ .method-name { font-weight: bold; }
179
+ .method-args { font-style: italic; }
180
+ .method-description { padding: 0 0.5em 0 0.5em; }
181
+
182
+ /* --- Source code sections -------------------- */
183
+
184
+ a.source-toggle { font-size: 90%; }
185
+ div.method-source-code {
186
+ background: #262626;
187
+ color: #ffdead;
188
+ margin: 1em;
189
+ padding: 0.5em;
190
+ border: 1px dashed #999;
191
+ overflow: hidden;
192
+ }
193
+
194
+ div.method-source-code pre { color: #ffdead; overflow: hidden; }
195
+
196
+ /* --- Ruby keyword styles --------------------- */
197
+
198
+ .standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
199
+
200
+ .ruby-constant { color: #7fffd4; background: transparent; }
201
+ .ruby-keyword { color: #00ffff; background: transparent; }
202
+ .ruby-ivar { color: #eedd82; background: transparent; }
203
+ .ruby-operator { color: #00ffee; background: transparent; }
204
+ .ruby-identifier { color: #ffdead; background: transparent; }
205
+ .ruby-node { color: #ffa07a; background: transparent; }
206
+ .ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
207
+ .ruby-regexp { color: #ffa07a; background: transparent; }
208
+ .ruby-value { color: #7fffd4; background: transparent; }
data/lib/hashutils.rb ADDED
@@ -0,0 +1,178 @@
1
+ require "rexml/document"
2
+
3
+ module HashUtils
4
+ def self::from_xml(xml)
5
+ out = {}
6
+ out.from_xml(xml)
7
+ out
8
+ end
9
+ end
10
+
11
+ module HashUtilsXML
12
+
13
+ # to_xml start
14
+
15
+ @@default_tab, @@new_line = " ", "\n"
16
+ @@lt, @@gt, @@clt = "<", ">", "</"
17
+
18
+ def to_xml(args = {:name => nil, :pretty => false})
19
+ tab = (args[:tab].nil?)? "" : args[:tab]
20
+
21
+ build_attrs = Proc.new do |k, v|
22
+ attributes = (self.respond_to?"xml_attributes" and !self.xml_attributes.nil?) ? self.xml_attributes : []
23
+ out = ""
24
+ out += " " + k.to_s + "=\"" + v.to_s + "\"" if attributes.select{|x| x == k}.length > 0
25
+ out
26
+ end
27
+
28
+ build_body = Proc.new do |k, v|
29
+ attributes = (self.respond_to?"xml_attributes" and !self.xml_attributes.nil?) ? self.xml_attributes : []
30
+ out = ""
31
+ if attributes.select{|x| x == k}.length == 0
32
+ new_args = args.merge({:tab => tab, :name => k})
33
+ out += v.to_xml(new_args) if v.respond_to?"to_xml"
34
+ out += ((args[:pretty])? tab : "") + @@lt + k.to_s + @@gt + v.to_s + @@clt + k.to_s + @@gt unless v.respond_to?"to_xml"
35
+ out += @@new_line if args[:pretty]
36
+ end
37
+ out
38
+ end
39
+
40
+ out = ""
41
+ if !args[:name].nil?
42
+ out += ((args[:pretty])? tab : "") + @@lt + args[:name].to_s
43
+ self.each_pair {|k, v| out += build_attrs.call(k, v, args)} if self.respond_to?"each_pair"
44
+ out += @@gt
45
+ end
46
+
47
+ orig_tab = tab
48
+ if !args[:name].nil? and args[:pretty]
49
+ out += @@new_line
50
+ tab += @@default_tab
51
+ end
52
+
53
+ self.each_pair {|k, v| out += build_body.call(k, v)} if self.respond_to?"each_pair"
54
+ self.each {|v| out += build_body.call((@xml_name.nil?) ? "item" : @xml_name, v)} if !self.respond_to?"each_pair"
55
+
56
+ out += ((args[:pretty])? orig_tab : "") + @@clt + args[:name].to_s + @@gt if !args[:name].nil?
57
+ out
58
+ end
59
+
60
+ # to_xml end
61
+
62
+ # from_xml start
63
+
64
+ def from_xml(element)
65
+ out = nil
66
+
67
+ if element.is_a?String
68
+ element = REXML::Document.new(element)
69
+ element = element.root
70
+ end
71
+
72
+ if !element.has_elements? and !element.has_attributes?
73
+ out = element.text
74
+ else
75
+ if element.has_attributes?
76
+ out = {}
77
+ process_xml_attributes(element.attributes, out)
78
+ end
79
+
80
+ if element.has_elements?
81
+ if potential_xml_array?(element.children)
82
+ out = []
83
+ process_xml_elements_as_array(element.children, out)
84
+ else
85
+ out = out || {}
86
+ process_xml_elements(element.children, out)
87
+ end
88
+ end
89
+ end
90
+
91
+ out
92
+ end
93
+
94
+ def from_xml!(element)
95
+ out = self.from_xml(element)
96
+ if out.class == self.class
97
+ self.clear
98
+ if self.is_a?Hash
99
+ self.merge!(out)
100
+ self.xml_attributes = out.xml_attributes
101
+ end
102
+ if self.is_a?Array
103
+ self.concat(out)
104
+ self.xml_name = out.xml_name
105
+ end
106
+ end
107
+ end
108
+
109
+ private
110
+
111
+ def process_xml_attributes(attributes, hash)
112
+ hash.xml_attributes = []
113
+ attributes.each_pair do |k,v|
114
+ hash[k.to_sym] = v.to_s
115
+ hash.xml_attributes.push(k.to_sym)
116
+ end
117
+ end
118
+
119
+ def process_xml_elements(elements, hash)
120
+ elements.each do |e|
121
+ hash[e.name.to_sym] = from_xml(e)
122
+ end
123
+ end
124
+
125
+ def process_xml_elements_as_array(elements, array)
126
+ elements.each do |e|
127
+ array.push(from_xml(e))
128
+ array.xml_name = e.name.to_sym if e.name != "item"
129
+ end
130
+ end
131
+
132
+ def potential_xml_array?(elements)
133
+ last_name = ""
134
+ out = false
135
+ elements.each do |e|
136
+ if e.name == last_name
137
+ out = true
138
+ break
139
+ end
140
+ last_name = e.name
141
+ end
142
+ out
143
+ end
144
+
145
+ # from_xml end
146
+
147
+ end
148
+
149
+ module HashUtilsNamedAttributes
150
+
151
+ def method_missing(m, *args, &block)
152
+ m_to_s = m.to_s
153
+ is_setter = (m_to_s[m_to_s.length-1..m_to_s.length-1] == "=")
154
+ sym = (is_setter) ? m_to_s[0..m_to_s.length-2].to_sym : m
155
+ if is_setter
156
+ self[sym] = args[0]
157
+ else
158
+ if self[sym]
159
+ out = self[sym]
160
+ else
161
+ raise NoMethodError, "undefined method `#{m_to_s}' for Hash"
162
+ end
163
+ end
164
+ end
165
+
166
+ end
167
+
168
+ class Hash
169
+ include HashUtilsXML, HashUtilsNamedAttributes
170
+
171
+ attr_accessor :xml_attributes, :xml_doc_name
172
+ end
173
+
174
+ class Array
175
+ include HashUtilsXML
176
+
177
+ attr_accessor :xml_name
178
+ end
@@ -0,0 +1,47 @@
1
+ require "test/unit"
2
+ require "lib/hashutils.rb"
3
+
4
+ class TC_HashUtilsFromXML < Test::Unit::TestCase
5
+
6
+ def setup
7
+ xml = "<doc attr1='Attribute 1'><elem1>Element 1</elem1><non_named_array><item>1</item><item>2</item></non_named_array><inner attr1='Inner attribute 1'><elem2>Inner element 2</elem2><inner_named_array><book>Book 1</book><book>Book 2</book></inner_named_array></inner></doc>"
8
+
9
+ @immut = {}
10
+ @mut = {}
11
+
12
+ @hash = @immut.from_xml(xml)
13
+ @mut.from_xml!(xml)
14
+
15
+ end
16
+
17
+ #def teardown
18
+ #end
19
+
20
+ def test_should_have_all_content
21
+ assert_equal("Attribute 1", @hash[:attr1])
22
+ assert_equal([:attr1], @hash.xml_attributes)
23
+ assert_equal("Element 1", @hash[:elem1])
24
+ assert_equal(["1", "2"], @hash[:non_named_array])
25
+ assert_nil(@hash[:non_named_array].xml_name)
26
+ assert_equal({:elem2 => "Inner element 2",
27
+ :attr1 => "Inner attribute 1",
28
+ :inner_named_array => ["Book 1", "Book 2"]}, @hash[:inner])
29
+ assert_equal(:book, @hash[:inner][:inner_named_array].xml_name)
30
+
31
+ assert_equal("Attribute 1", @mut[:attr1])
32
+ assert_equal([:attr1], @mut.xml_attributes)
33
+ assert_equal("Element 1", @mut[:elem1])
34
+ assert_equal(["1", "2"], @mut[:non_named_array])
35
+ assert_nil(@mut[:non_named_array].xml_name)
36
+ assert_equal({:elem2 => "Inner element 2",
37
+ :attr1 => "Inner attribute 1",
38
+ :inner_named_array => ["Book 1", "Book 2"]}, @mut[:inner])
39
+ assert_equal(:book, @mut[:inner][:inner_named_array].xml_name)
40
+
41
+ end
42
+
43
+ def test_should_keep_immutable
44
+ assert_equal({}, @immut)
45
+ end
46
+
47
+ end