hutch-xamplr 1.0.5 → 1.1.0

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 (76) hide show
  1. data/Rakefile +1 -0
  2. data/VERSION.yml +2 -2
  3. data/examples/random-people-shared-addresses/Makefile +2 -2
  4. data/examples/random-people-shared-addresses/batch-load-users.rb +2 -5
  5. data/examples/random-people-shared-addresses/find-mentions.rb +1 -4
  6. data/examples/random-people-shared-addresses/find-people-by-address.rb +1 -4
  7. data/examples/random-people-shared-addresses/optimise.rb +1 -4
  8. data/examples/random-people-shared-addresses/people.rb +0 -15
  9. data/examples/random-people-shared-addresses/query.rb +1 -4
  10. data/examples/random-people-shared-addresses/query2.rb +1 -4
  11. data/examples/random-people-shared-addresses/results.write.BASELINE +298 -0
  12. data/examples/random-people-shared-addresses/results.write.NEW_ATTR_ENCODING +294 -0
  13. data/examples/random-people-shared-addresses/settings.rb +3 -0
  14. data/examples/random-people/batch-load-users.rb +1 -4
  15. data/examples/random-people/optimise.rb +1 -4
  16. data/examples/random-people/people.rb +0 -3
  17. data/examples/random-people/query.rb +1 -5
  18. data/examples/random-people/query2.rb +1 -4
  19. data/examples/random-people/settings.rb +3 -0
  20. data/examples/random-people/what-to-query-on.rb +1 -3
  21. data/examples/read-testing/Makefile +10 -0
  22. data/examples/read-testing/load.rb +65 -0
  23. data/examples/read-testing/read.rb +51 -0
  24. data/examples/read-testing/results.read.BASELINE +6 -0
  25. data/examples/read-testing/results.read.FAST +5 -0
  26. data/examples/read-testing/rrr.rb +87 -0
  27. data/examples/read-testing/settings.rb +2 -0
  28. data/examples/read-testing/xampl-gen.rb +36 -0
  29. data/examples/read-testing/xml/text.xml +8 -0
  30. data/lib/xamplr.rb +10 -1
  31. data/lib/xamplr/exceptions.rb +97 -0
  32. data/lib/xamplr/from-xml-orig.rb +350 -0
  33. data/lib/xamplr/from-xml.rb +272 -183
  34. data/lib/xamplr/handwritten/example.rb +0 -58
  35. data/lib/xamplr/handwritten/hand-example.rb +0 -27
  36. data/lib/xamplr/handwritten/test-handwritten.rb +0 -37
  37. data/lib/xamplr/mixins.rb +10 -48
  38. data/lib/xamplr/persist-to-xml.rb +249 -0
  39. data/lib/xamplr/persistence.rb +44 -412
  40. data/lib/xamplr/persistence.rb.more_thread_safe +0 -13
  41. data/lib/xamplr/persistence.rb.partially_thread_safe +0 -13
  42. data/lib/xamplr/persister.rb +298 -0
  43. data/lib/xamplr/{persister → persisters}/caches.rb +0 -0
  44. data/lib/xamplr/{persister → persisters}/caching.rb +1 -1
  45. data/lib/xamplr/{persister → persisters}/filesystem.rb +4 -5
  46. data/lib/xamplr/{persister → persisters}/in-memory.rb +1 -1
  47. data/lib/xamplr/{persister → persisters}/simple.rb +0 -0
  48. data/lib/xamplr/{persister → persisters}/tokyo-cabinet.rb +53 -15
  49. data/lib/xamplr/simpleTemplate/{input-c.r4 → obsolete/input-c.r4} +0 -0
  50. data/lib/xamplr/simpleTemplate/{play.r6.txt → obsolete/play.r6.txt} +0 -0
  51. data/lib/xamplr/simpleTemplate/{play_more.r6.txt → obsolete/play_more.r6.txt} +0 -0
  52. data/lib/xamplr/simpleTemplate/{test001.r5 → obsolete/test001.r5} +0 -0
  53. data/lib/xamplr/simpleTemplate/{test002.r5 → obsolete/test002.r5} +0 -0
  54. data/lib/xamplr/simpleTemplate/{test003.r5 → obsolete/test003.r5} +0 -0
  55. data/lib/xamplr/templates/child_indexed.template +1 -1
  56. data/lib/xamplr/templates/element_classes.template +1 -1
  57. data/lib/xamplr/templates/element_data.template +0 -39
  58. data/lib/xamplr/templates/element_empty.template +0 -40
  59. data/lib/xamplr/templates/element_mixed.template +0 -41
  60. data/lib/xamplr/templates/element_simple.template +0 -40
  61. data/lib/xamplr/test-support/bench.rb +6 -26
  62. data/lib/xamplr/test-support/test.rb +1 -89
  63. data/lib/xamplr/visitor.rb +0 -778
  64. data/lib/xamplr/visitors.rb +573 -0
  65. data/lib/xamplr/xampl-generator.rb +1 -1
  66. data/lib/xamplr/xampl-hand-generated.rb +0 -85
  67. data/lib/xamplr/xampl-module.rb +36 -0
  68. data/lib/xamplr/xampl-object-internals.rb +6 -0
  69. data/lib/xamplr/xampl-object.rb +10 -341
  70. data/lib/xamplr/xampl-persisted-object.rb +122 -0
  71. data/lib/xamplr/xml-text.rb +117 -0
  72. metadata +53 -18
  73. data/lib/xamplr/persister/subversion.rb +0 -61
  74. data/lib/xamplr/rac.sh +0 -6
  75. data/lib/xamplr/rac_gen.sh +0 -1
  76. data/lib/xamplr/templates/child_indexed.template.000 +0 -87
@@ -23,7 +23,7 @@
23
23
  accessed
24
24
  index = #{element.attribute_name}.get_the_index
25
25
  if(nil == index) then
26
- raise XamplException.new("no value for the index '#{element.indexed_by_attr}' of #{element.attribute_name} defined in : " << #{element.attribute_name}.pp_xml)
26
+ raise Xampl::XamplException.new("no value for the index '#{element.indexed_by_attr}' of #{element.attribute_name} defined in : " << #{element.attribute_name}.pp_xml)
27
27
  end
28
28
 
29
29
  existing = @#{element.attribute_name}_child[index]
@@ -7,5 +7,5 @@
7
7
  | elsif "mixed" == @element.kind then
8
8
  | element_mixed(result)
9
9
  | else
10
- | raise XamplException.new(:unkown_kind_of_element, "unknown element kind: '#{@element.kind}'")
10
+ | raise Xampl::XamplException.new(:unkown_kind_of_element, "unknown element kind: '#{@element.kind}'")
11
11
  | end
@@ -64,47 +64,8 @@
64
64
  |
65
65
  |}
66
66
  |
67
- |
68
- |if @element.persisted then
69
67
  |
70
68
 
71
- @@to_yaml_properties = [ "@#{@element.indexed_by_attr}" ]
72
- @@to_yaml_properties_all = [
73
- |
74
- |else
75
- |
76
-
77
- @@to_yaml_properties = [
78
- |
79
- |end
80
- |
81
- |@element.attribute_child.each{ | attribute |
82
- |
83
- "@#{attribute.name}",
84
- |
85
- |}
86
- |
87
- "@children",
88
- "@_content"
89
- ]
90
-
91
- def to_yaml_properties
92
- |
93
- |if @element.persisted then
94
- |
95
- if is_yaml_root(self) then
96
- return @@to_yaml_properties_all
97
- else
98
- return @@to_yaml_properties
99
- end
100
- |
101
- |else
102
- |
103
- @@to_yaml_properties
104
- |
105
- |end
106
- |
107
- end
108
69
  |
109
70
  |if @element.persisted then
110
71
  |
@@ -63,46 +63,6 @@
63
63
  |}
64
64
  |
65
65
  |if @element.persisted then
66
- |
67
-
68
- @@to_yaml_properties = [ "@#{@element.indexed_by_attr}" ]
69
- @@to_yaml_properties_all = [
70
-
71
- |
72
- |else
73
- |
74
-
75
- @@to_yaml_properties = [
76
- |
77
- |end
78
- |
79
- |@element.attribute_child.each{ | attribute |
80
- |
81
- "@#{attribute.name}",
82
- |
83
- |}
84
- |
85
- ]
86
-
87
- def to_yaml_properties
88
- |
89
- |if @element.persisted then
90
- |
91
- if is_yaml_root(self) then
92
- return @@to_yaml_properties_all
93
- else
94
- return @@to_yaml_properties
95
- end
96
- |
97
- |else
98
- |
99
- @@to_yaml_properties
100
- |
101
- |end
102
- |
103
- end
104
- |
105
- |if @element.persisted then
106
66
  |
107
67
 
108
68
  def #{@element.class_name}.lookup(pid)
@@ -63,47 +63,6 @@
63
63
  |}
64
64
  |
65
65
  |if @element.persisted then
66
- |
67
-
68
- @@to_yaml_properties = [ "@#{@element.indexed_by_attr}" ]
69
- @@to_yaml_properties_all = [
70
-
71
- |
72
- |else
73
- |
74
-
75
- @@to_yaml_properties = [
76
- |
77
- | end
78
- |
79
- |@element.attribute_child.each{ | attribute |
80
- |
81
- "@#{attribute.name}",
82
- |
83
- |}
84
- |
85
- "@children"
86
- ]
87
-
88
- def to_yaml_properties
89
- |
90
- |if @element.persisted then
91
- |
92
- if is_yaml_root(self) then
93
- return @@to_yaml_properties_all
94
- else
95
- return @@to_yaml_properties
96
- end
97
- |
98
- |else
99
- |
100
- @@to_yaml_properties
101
- |
102
- |end
103
- |
104
- end
105
- |
106
- |if @element.persisted then
107
66
  |
108
67
 
109
68
  def #{@element.class_name}.lookup(pid)
@@ -63,46 +63,6 @@
63
63
  |}
64
64
  |
65
65
  |if @element.persisted then
66
- |
67
-
68
- @@to_yaml_properties = [ "@#{@element.indexed_by_attr}" ]
69
- @@to_yaml_properties_all = [
70
- |
71
- |else
72
- |
73
-
74
- @@to_yaml_properties = [
75
- |
76
- |end
77
- |
78
- |@element.attribute_child.each{ | attribute |
79
- |
80
- "@#{attribute.name}",
81
- |
82
- |}
83
- |
84
- "@_content"
85
- ]
86
-
87
- def to_yaml_properties
88
- |
89
- |if @element.persisted then
90
- |
91
- if is_yaml_root(self) then
92
- return @@to_yaml_properties_all
93
- else
94
- return @@to_yaml_properties
95
- end
96
- |
97
- |else
98
- |
99
- @@to_yaml_properties
100
- |
101
- |end
102
- |
103
- end
104
- |
105
- |if @element.persisted then
106
66
  |
107
67
 
108
68
  def #{@element.class_name}.lookup(pid)
@@ -13,21 +13,18 @@ include Benchmark
13
13
  # results from 16 October 2005
14
14
  #
15
15
 
16
- #Rebuilding From String (YAML & XML) count: 1000 (est. ~ 11s)
16
+ #Rebuilding From String (XML) count: 1000 (est. ~ 11s)
17
17
  # user system total real
18
- #yaml 2.590000 0.050000 2.640000 ( 3.180061)
19
18
  #xml 5.970000 0.080000 6.050000 ( 6.573804)
20
19
  #ruby 1.660000 0.030000 1.690000 ( 2.017015)
21
20
 
22
- #Serialize to String (YAML & XML) count: 1000 (est. ~ 25s)
21
+ #Serialize to String (XML) count: 1000 (est. ~ 25s)
23
22
  # user system total real
24
- #yaml 14.360000 0.250000 14.610000 ( 16.128599)
25
23
  #xml 1.460000 0.020000 1.480000 ( 1.576753)
26
24
  #ruby 0.890000 0.010000 0.900000 ( 1.102071)
27
25
 
28
- #Round Tripping (YAML & XML) count: 1000 (est. ~ 40s)
26
+ #Round Tripping (XML) count: 1000 (est. ~ 40s)
29
27
  # user system total real
30
- #yaml 17.420000 0.270000 17.690000 ( 19.390348)
31
28
  #xml 7.890000 0.110000 8.000000 ( 8.860720)
32
29
  #ruby 2.780000 0.040000 2.820000 ( 3.131707)
33
30
 
@@ -62,10 +59,8 @@ module Bench
62
59
  #ruby_printer = RubyPrinter.new
63
60
  #ruby_s = ruby_printer.to_ruby(thing)
64
61
  ruby_s = thing.to_ruby
65
- yaml_s = thing.as_yaml
66
62
  xml_s = thing.persist
67
63
 
68
- #puts yaml_s
69
64
  puts xml_s
70
65
  puts ruby_s
71
66
  puts "++++++++++++++++++++++++++++++++++++"
@@ -73,13 +68,8 @@ module Bench
73
68
  puts big_thing.to_ruby
74
69
  puts "++++++++++++++++++++++++++++++++++++"
75
70
 
76
- puts "Rebuilding From String (YAML & XML) count: #{count} (est. ~ 11s)"
71
+ puts "Rebuilding From String (XML) count: #{count} (est. ~ 11s)"
77
72
  bm(10) do | x |
78
- x.report("yaml") {
79
- count.times {
80
- something = XamplObject.from_yaml(yaml_s)
81
- }
82
- }
83
73
  x.report("xml") {
84
74
  count.times {
85
75
  another_big_thing = XamplObject.from_xml_string(xml_s)
@@ -92,13 +82,8 @@ module Bench
92
82
  }
93
83
  end
94
84
 
95
- puts "Serialize to String (YAML & XML) count: #{count} (est. ~ 25s)"
85
+ puts "Serialize to String (XML) count: #{count} (est. ~ 25s)"
96
86
  bm(10) do | x |
97
- x.report("yaml") {
98
- count.times {
99
- yaml_s = thing.as_yaml
100
- }
101
- }
102
87
  x.report("xml") {
103
88
  count.times {
104
89
  xml_s = thing.persist
@@ -111,13 +96,8 @@ module Bench
111
96
  }
112
97
  end
113
98
 
114
- puts "Round Tripping (YAML & XML) count: #{count} (est. ~ 40s)"
99
+ puts "Round Tripping (XML) count: #{count} (est. ~ 40s)"
115
100
  bm(10) do | x |
116
- x.report("yaml") {
117
- count.times {
118
- something = XamplObject.from_yaml(thing.as_yaml)
119
- }
120
- }
121
101
  x.report("xml") {
122
102
  count.times {
123
103
  another_thing = XamplObject.from_xml_string(thing.persist)
@@ -257,50 +257,6 @@ class TestXampl < Test::Unit::TestCase
257
257
  check_parents(big_thing)
258
258
  end
259
259
 
260
- def test_yaml_round_trip
261
- emph_content_1 = "there"
262
- emph1 = Emph.new
263
- emph1 << emph_content_1
264
-
265
- emph_content_2 = "are"
266
- emph2 = Emph.new
267
- emph2.content = emph_content_2
268
-
269
- desc1 = Description.new
270
- desc1.kind = "desc1"
271
-
272
- desc1.is_changed = nil
273
- desc1 << "hello " << emph1 << "! How " << emph2 << " you?"
274
-
275
- thing = Thing.new
276
- thing.pid = "thing"
277
- thing.new_stuff.kind = "stuff1"
278
- thing << desc1
279
-
280
- big_thing = Thing.new("big_thing")
281
- big_thing << "leading content" << thing << "trailing content"
282
-
283
- check_parents(big_thing)
284
-
285
- #puts YAML::dump(big_thing)
286
- #puts big_thing.test_to_xml
287
-
288
- #something = XamplObject.from_yaml(YAML::dump(big_thing))
289
- pp_xml = big_thing.pp_xml
290
- bt_as_yaml = big_thing.as_yaml
291
-
292
- something = XamplObject.from_yaml(bt_as_yaml)
293
-
294
- assert_not_same(something, big_thing)
295
- assert_equal(something.test_to_xml, big_thing.persist)
296
- check_parents(something)
297
-
298
- something = XamplObject.from_yaml(big_thing.as_yaml)
299
- assert_equal(something.test_to_xml, big_thing.persist)
300
- assert_not_same(something, big_thing)
301
- check_parents(something)
302
- end
303
-
304
260
  def test_from_xml
305
261
  emph_content_1 = "there"
306
262
  emph1 = Emph.new
@@ -563,25 +519,6 @@ class TestXampl < Test::Unit::TestCase
563
519
  assert(thing === found)
564
520
  end
565
521
 
566
- def test_in_memory_persistence_yaml
567
- pname = "test_in_memory_persistence_yaml" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
568
- Xampl.enable_persister(pname, :in_memory, :yaml_format)
569
- persister2 = Xampl.persister
570
-
571
- stuff = Stuff.new
572
- thing = Thing.new
573
- thing.pid = "thing"
574
- thing << stuff
575
-
576
- Xampl.introduce_to_persister(thing)
577
- Xampl.sync
578
- Xampl.clear_cache
579
- found = Xampl.lookup(Thing, "thing")
580
-
581
- assert_not_equal(thing, found)
582
- assert(thing === found)
583
- end
584
-
585
522
  def test_in_memory_persistence_rollback
586
523
  pname = "first" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
587
524
  original_persister = Xampl.enable_persister(pname, :in_memory)
@@ -854,30 +791,6 @@ class TestXampl < Test::Unit::TestCase
854
791
  assert_equal(thing.object_id, found.object_id)
855
792
  end
856
793
 
857
- def test_filesystem_persistence_yaml
858
- pname = "test_filesystem_persistence_yaml" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
859
- Xampl.enable_persister(pname, :filesystem, :yaml_format)
860
- persister2 = Xampl.persister
861
-
862
- stuff = Stuff.new
863
- thing = Thing.new
864
- thing.pid = "thing"
865
- thing << stuff
866
-
867
- Xampl.introduce_to_persister(thing)
868
- Xampl.sync
869
-
870
- thing.info = "force emptying"
871
-
872
- Xampl.rollback
873
-
874
- assert(thing.load_needed)
875
-
876
- found = Xampl.lookup(Thing, "thing")
877
-
878
- assert_equal(thing.object_id, found.object_id)
879
- end
880
-
881
794
  def test_filesystem_persistence_automatic
882
795
  stuff = Stuff.new
883
796
  thing = Thing.new
@@ -1045,12 +958,11 @@ class TestXampl < Test::Unit::TestCase
1045
958
 
1046
959
  keep_new_thing = new_thing
1047
960
 
1048
- # these (to xml, ruby, yaml) will NOT suck the child thing into memory
961
+ # these (to xml, ruby) will NOT suck the child thing into memory
1049
962
  xml = thing.test_to_xml
1050
963
 
1051
964
  ruby = thing.to_ruby
1052
965
  ruby_thing = XamplObject.from_ruby(ruby)
1053
- yaml_thing = XamplObject.from_yaml(thing.as_yaml)
1054
966
 
1055
967
  assert_equal(0, Xampl.persister.read_count, "not in the cache")
1056
968
 
@@ -1,4 +1,3 @@
1
-
2
1
  module Xampl
3
2
 
4
3
  class Visitor
@@ -137,782 +136,5 @@ module Xampl
137
136
  @cycling = false
138
137
  end
139
138
  end
140
-
141
- class CountingVisitor < Visitor
142
- attr_accessor :count
143
-
144
- def initialize
145
- super
146
- @count = 0
147
- end
148
-
149
- def before_visit(xampl)
150
- @count += 1
151
- end
152
- end
153
-
154
- class ResetIsChanged < Visitor
155
- def initialize
156
- super
157
- end
158
-
159
- def start(xampl, verbose=false)
160
- @verbose = verbose
161
- if verbose
162
- puts "RESET IS CHANGED.... #{xampl}"
163
- puts "SKIPPING!!!" unless xampl.persist_required and xampl.load_needed
164
- end
165
-
166
- return if xampl.persist_required and xampl.load_needed
167
- super(xampl)
168
- end
169
-
170
- def before_visit(xampl)
171
- if xampl.is_changed then
172
- puts "RESET CHANGED: #{xampl} and continue" if verbose
173
- xampl.is_changed = false;
174
- else
175
- puts "RESET CHANGED: #{xampl} block" if verbose
176
- @no_children = true
177
- end
178
- end
179
- end
180
-
181
- class MarkChangedDeep < Visitor
182
- def initialize
183
- super
184
- end
185
-
186
- def before_visit(xampl)
187
- xampl.changed if xampl.persist_required
188
- end
189
- end
190
-
191
- class PrettyXML < Visitor
192
- attr_accessor :ns_to_prefix, :start_body, :body, :out
193
- attr_accessor :indent, :indent_step
194
-
195
- @@compact = true
196
-
197
- def PrettyXML.compact
198
- @@compact
199
- end
200
-
201
- def PrettyXML.compact=(v)
202
- @@compact = v
203
- end
204
-
205
- def initialize(out="", skip=[])
206
- super()
207
-
208
- @out = out
209
- @indent = ""
210
- @indent_step = " "
211
- @start_attr_indent = ""
212
- @was_attr = false
213
-
214
- @depth = 0
215
-
216
- @skip = {}
217
- skip.each{ | ns |
218
- @skip[ns] = ns
219
- }
220
-
221
- @ns_to_prefix = {}
222
- @start_body = nil
223
- @body = ""
224
- @attr_list = nil
225
-
226
- @insert_comment = nil
227
- end
228
-
229
- def short_circuit
230
- body << @insert_comment if @insert_comment
231
- @insert_comment = nil
232
- end
233
-
234
- def cycle(xampl)
235
- @short_circuit = true
236
- @insert_comment = "<!-- CYCLE -->"
237
- return true
238
- end
239
-
240
- def revisit(xampl)
241
- @insert_comment = "<!-- You've seen this before -->"
242
- #body << "<!-- You've seen this before -->"
243
- return true
244
- end
245
-
246
- def register_ns(ns)
247
- if (0 == ns.length) then
248
- return ""
249
- end
250
-
251
- prefix = ns_to_prefix[ns]
252
- if (nil == prefix) then
253
- preferred = XamplObject.lookup_preferred_ns_prefix(ns)
254
- prefix = "" << preferred << ":" if preferred
255
- prefix = "ns" << ns_to_prefix.size.to_s << ":" unless prefix
256
- ns_to_prefix[ns] = prefix
257
- end
258
- return prefix
259
- end
260
-
261
- def attr_esc(s)
262
- if (s.kind_of? XamplObject)
263
- return attr_esc(s.to_xml)
264
- end
265
-
266
- result = s.to_s.dup
267
-
268
- result.gsub!("&", "&amp;")
269
- result.gsub!("<", "&lt;")
270
- result.gsub!(">", "&gt;")
271
- result.gsub!("'", "&apos;")
272
- result.gsub!("\"", "&quot;")
273
-
274
- return result
275
- end
276
-
277
- def content_esc(s)
278
- result = s.to_s.dup
279
-
280
- return result if (s.kind_of? XamplObject)
281
-
282
- result.gsub!("&", "&amp;")
283
- result.gsub!("<", "&lt;")
284
-
285
- return result
286
- end
287
-
288
- def attribute(xampl)
289
- @attr_list = []
290
- pid = nil
291
- if (nil != xampl.attributes) then
292
- xampl.attributes.each{ | attr_spec |
293
- unless @skip[attr_spec[2]] then
294
- value = xampl.instance_variable_get(attr_spec[0])
295
- if value then
296
- prefix = (2 < attr_spec.length) ? register_ns(attr_spec[2]) : ""
297
- @attr_list << (" " << prefix << attr_spec[1] << "='" << attr_esc(value) << "'")
298
- end
299
- end
300
- }
301
- @attr_list.sort!
302
- end
303
- #@attr_list << " xampl:marker='OKAY: #{ xampl }'"
304
- end
305
-
306
- def persist_attribute(xampl)
307
- @attr_list = []
308
- if xampl.persist_required then
309
- index = xampl.indexed_by.to_s
310
- if index then
311
- value = xampl.get_the_index
312
- @attr_list << (" " << index << "='" << attr_esc(value) << "'") if value
313
- end
314
- else
315
- attribute(xampl)
316
- #@attr_list << " xampl:wtf='WTF??'"
317
- end
318
- end
319
-
320
- def show_attributes(attr_indent)
321
- if (nil == @attr_list) then
322
- return ""
323
- else
324
- result = @attr_list.join(attr_indent)
325
- if (0 == result.length) then
326
- return ""
327
- else
328
- return result
329
- end
330
- end
331
- end
332
-
333
- def do_indent
334
- return "\n" << @indent << (@indent_step * @depth)
335
- end
336
-
337
- def start_element(xampl)
338
- xampl.accessed
339
-
340
- if @revisiting or @cycling then
341
- @short_circuit = true
342
- persist_attribute(xampl)
343
- else
344
- attribute(xampl)
345
- end
346
-
347
- tag = xampl.tag
348
- ns = xampl.ns
349
- indent = do_indent
350
- tag_info = "" << "<" << register_ns(ns) << tag
351
- attr_indent = "" << indent << (" " * tag_info.size)
352
- unless @start_body then
353
- @start_attr_indent = attr_indent
354
- attr_defn = show_attributes(attr_indent)
355
- @start_body = "" << indent << tag_info << attr_defn
356
- @was_attr = true if 0 < attr_defn.size
357
- else
358
- @body << indent << tag_info << show_attributes(attr_indent)
359
- end
360
- end
361
-
362
- def end_element(xampl)
363
- tag = xampl.tag
364
- ns = xampl.ns
365
- if @@compact then
366
- @body << "</" << register_ns(ns) << tag << ">"
367
- else
368
- @body << do_indent << "</" << register_ns(ns) << tag << ">"
369
- end
370
- end
371
-
372
- def define_ns
373
- result = ""
374
- indent = @was_attr
375
- ns_to_prefix.each{ | ns, prefix |
376
- result = sprintf("%s%s xmlns:%s='%s'", result, indent ? @start_attr_indent : "", prefix[0..-2], ns)
377
- indent = true
378
- }
379
- return result
380
- end
381
-
382
- def done
383
- out << @start_body << define_ns << @body
384
- end
385
-
386
- def before_visit_without_content(xampl)
387
- start_element(xampl)
388
- @body << "/>"
389
- end
390
-
391
- def before_visit_simple_content(xampl)
392
- start_element(xampl)
393
- @body << ">"
394
- @body << content_esc(xampl._content) if xampl._content
395
- end_element(xampl)
396
- end
397
-
398
- def before_visit_data_content(xampl)
399
- start_element(xampl)
400
- @body << ">"
401
- @body << content_esc(xampl._content) if xampl._content
402
- @depth += 1
403
- end
404
-
405
- def after_visit_data_content(xampl)
406
- @depth += -1
407
- end_element(xampl)
408
- end
409
-
410
- def before_visit_mixed_content(xampl)
411
- start_element(xampl)
412
- @body << ">"
413
- @depth += 1
414
- end
415
-
416
- def after_visit_mixed_content(xampl)
417
- @depth -= 1
418
- end_element(xampl)
419
- end
420
-
421
- def before_visit(xampl)
422
- unless xampl.kind_of?(XamplObject) and @skip[xampl.ns] then
423
- if xampl.respond_to? "before_visit_by_element_kind" then
424
- xampl.before_visit_by_element_kind(self)
425
- else
426
- @body << xampl.to_s
427
- end
428
- else
429
- @no_children = true
430
- end
431
- end
432
-
433
- def after_visit(xampl)
434
- xampl.after_visit_by_element_kind(self) if xampl.respond_to? "after_visit_by_element_kind"
435
- end
436
-
437
- def visit_string(string)
438
- @body << string
439
- end
440
- end
441
-
442
- class PersistXML < Visitor
443
- attr_accessor :ns_to_prefix, :start_body, :body, :out, :mentions
444
-
445
- def initialize(out="", mentions=nil)
446
- super()
447
-
448
- @out = out
449
- @was_attr = false
450
-
451
- @mentions = mentions
452
-
453
- @ns_to_prefix = {}
454
- @start_body = nil
455
- @body = ""
456
- @attr_list = nil
457
- end
458
-
459
- def cycle(xampl)
460
- raise XamplException.new(:cycle_detected_in_xampl_cluster) unless xampl.kind_of?(XamplPersistedObject)
461
- return true
462
- end
463
-
464
- def revisit(xampl)
465
- return true
466
- end
467
-
468
- def register_ns(ns)
469
- if (0 == ns.length) then
470
- return ""
471
- end
472
-
473
- prefix = ns_to_prefix[ns]
474
- if (nil == prefix) then
475
- preferred = XamplObject.lookup_preferred_ns_prefix(ns)
476
- prefix = "" << preferred << ":" if preferred
477
- prefix = "ns" << ns_to_prefix.size.to_s << ":" unless prefix
478
- ns_to_prefix[ns] = prefix
479
- end
480
- return prefix
481
- end
482
-
483
- def attr_esc(s)
484
- if (s.kind_of? XamplObject)
485
- return attr_esc(s.to_xml)
486
- end
487
-
488
- result = s.to_s.dup
489
-
490
- result.gsub!("&", "&amp;")
491
- result.gsub!("<", "&lt;")
492
- result.gsub!(">", "&gt;")
493
- result.gsub!("'", "&apos;")
494
- result.gsub!("\"", "&quot;")
495
-
496
- return result
497
- end
498
-
499
- def content_esc(s)
500
- result = s.to_s.dup
501
-
502
- return result if (s.kind_of? XamplObject)
503
-
504
- result.gsub!("&", "&amp;")
505
- result.gsub!("<", "&lt;")
506
-
507
- return result
508
- end
509
-
510
- def attribute(xampl)
511
- @attr_list = []
512
- if (nil != xampl.attributes) then
513
- xampl.attributes.each{ | attr_spec |
514
- prefix = (2 < attr_spec.length) ? register_ns(attr_spec[2]) : ""
515
- value = xampl.instance_variable_get(attr_spec[0])
516
- @attr_list << (" " << prefix << attr_spec[1] << "='" << attr_esc(value) << "'") \
517
- unless nil == value
518
- }
519
- end
520
- end
521
-
522
- def persist_attribute(xampl)
523
- @attr_list = []
524
- pattr = xampl.indexed_by.to_s
525
- if (nil != xampl.attributes) then
526
- xampl.attributes.each{ | attr_spec |
527
- if pattr == attr_spec[1] then
528
- prefix = (2 < attr_spec.length) ? register_ns(attr_spec[2]) : ""
529
- value = xampl.instance_variable_get(attr_spec[0])
530
- @attr_list << (" " << prefix << attr_spec[1] << "='" << attr_esc(value) << "'") \
531
- unless nil == value
532
- break
533
- end
534
- }
535
- end
536
- end
537
-
538
- def show_attributes
539
- result = @attr_list.join(" ")
540
- if (0 == result.length) then
541
- return ""
542
- else
543
- return result
544
- end
545
- end
546
-
547
- def start_element(xampl)
548
- tag = xampl.tag
549
- ns = xampl.ns
550
- tag_info = "" << "<" << register_ns(ns) << tag
551
- unless @start_body then
552
- attribute(xampl)
553
- attr_defn = show_attributes
554
- @start_body = "" << tag_info << attr_defn
555
- @was_attr = true if 0 < attr_defn.size
556
- else
557
- if xampl.persist_required then
558
- @mentions << xampl if @mentions
559
- @no_children = true
560
- persist_attribute(xampl)
561
- else
562
- attribute(xampl)
563
- end
564
- @body << tag_info << show_attributes
565
- end
566
- end
567
-
568
- def end_element(xampl)
569
- tag = xampl.tag
570
- ns = xampl.ns
571
- @body << "</" << register_ns(ns) << tag << ">"
572
- end
573
-
574
- def define_ns
575
- result = ""
576
- ns_to_prefix.each{ | ns, prefix |
577
- result = sprintf("%s xmlns:%s='%s'", result, prefix[0..-2], ns)
578
- }
579
- return result
580
- end
581
-
582
- def done
583
- out << @start_body << define_ns << @body
584
- end
585
-
586
- def before_visit_without_content(xampl)
587
- start_element(xampl)
588
- @body << "/>"
589
- end
590
-
591
- def before_visit_simple_content(xampl)
592
- start_element(xampl)
593
- if @no_children then
594
- @body << "/>"
595
- else
596
- @body << ">"
597
- @body << content_esc(xampl._content) if xampl._content
598
- end_element(xampl)
599
- end
600
- end
601
-
602
- def before_visit_data_content(xampl)
603
- start_element(xampl)
604
- if @no_children then
605
- @body << "/>"
606
- else
607
- @body << ">"
608
- @body << content_esc(xampl._content) if xampl._content
609
- end
610
- end
611
-
612
- def after_visit_data_content(xampl)
613
- end_element(xampl) unless @no_children
614
- end
615
-
616
- def before_visit_mixed_content(xampl)
617
- if @no_children then
618
- @body << "/>"
619
- else
620
- start_element(xampl)
621
- @body << ">"
622
- end
623
- end
624
-
625
- def after_visit_mixed_content(xampl)
626
- end_element(xampl) unless @no_children
627
- end
628
-
629
- def before_visit(xampl)
630
- if xampl.respond_to? "before_visit_by_element_kind" then
631
- xampl.before_visit_by_element_kind(self)
632
- else
633
- @body << xampl.to_s
634
- end
635
- end
636
-
637
- def after_visit(xampl)
638
- xampl.after_visit_by_element_kind(self) if xampl.respond_to? "after_visit_by_element_kind"
639
- end
640
-
641
- def visit_string(string)
642
- @body << string
643
- end
644
- end
645
-
646
- class CopyXML < Visitor
647
- attr_accessor :ns_to_prefix, :start_body, :body
648
-
649
- def CopyXML.copy(root, translate_pids={})
650
- CopyXML.new.make_copy(root, translate_pids)
651
- end
652
-
653
- def make_copy(root, translate_pids)
654
- @was_attr = false
655
-
656
- @ns_to_prefix = {}
657
- @start_body = nil
658
- @body = ""
659
- @attr_list = nil
660
-
661
- @pid_translations_old_to_new = translate_pids
662
- @pid_translations_new_to_old = translate_pids.invert
663
-
664
- @persisted_xampl_found = { @current_root.get_the_index => root }
665
- @copies_by_old_pid = {}
666
-
667
- while true do
668
- copy_these = []
669
-
670
- @persisted_xampl_found.each do | pid, xampl |
671
- copy_these << xampl unless @copies_by_old_pid[pid]
672
- end
673
-
674
- break if 0 == copy_these.length
675
-
676
- @persisted_xampl_found = {}
677
- copy_these.each do | xampl |
678
- @current_root = xampl
679
- @out = ""
680
- @copies_by_old_pid[@current_root.get_the_index] = @out
681
-
682
- copy_xampl(@current_root)
683
- end
684
- end
685
-
686
- return @copies_by_old_pid
687
- end
688
-
689
- def copy_xampl(root)
690
- start(root).done
691
- end
692
-
693
- @@base_pid = Time.now.to_i.to_s + "_"
694
- @@gen_pid = 0
695
-
696
- def get_the_new_pid(xampl)
697
- current_pid = xampl.get_the_index
698
- @persisted_xampl_found[current_pid] = xampl
699
-
700
- new_pid = @pid_translations_old_to_new[current_pid]
701
-
702
- unless new_pid then
703
- @@gen_pid += 1
704
- new_pid = @@base_pid + @@gen_pid.to_s
705
-
706
- @pid_translations_old_to_new[current_pid] = new_pid
707
- @pid_translations_new_to_old[new_pid] = current_pid
708
- end
709
-
710
- return new_pid
711
- end
712
-
713
- def cycle(xampl)
714
- raise XamplException.new(:cycle_detected_in_xampl_cluster) unless xampl.kind_of?(XamplPersistedObject)
715
- return true
716
- end
717
-
718
- def revisit(xampl)
719
- return true
720
- end
721
-
722
- def register_ns(ns)
723
- if (0 == ns.length) then
724
- return ""
725
- end
726
-
727
- prefix = ns_to_prefix[ns]
728
- if (nil == prefix) then
729
- preferred = XamplObject.lookup_preferred_ns_prefix(ns)
730
- prefix = "" << preferred << ":" if preferred
731
- prefix = "ns" << ns_to_prefix.size.to_s << ":" unless prefix
732
- ns_to_prefix[ns] = prefix
733
- end
734
- return prefix
735
- end
736
-
737
- def attr_esc(s)
738
- if (s.kind_of? XamplObject)
739
- return attr_esc(s.to_xml)
740
- end
741
-
742
- result = s.to_s.dup
743
-
744
- result.gsub!("&", "&amp;")
745
- result.gsub!("<", "&lt;")
746
- result.gsub!(">", "&gt;")
747
- result.gsub!("'", "&apos;")
748
- result.gsub!("\"", "&quot;")
749
-
750
- return result
751
- end
752
-
753
- def content_esc(s)
754
- result = s.to_s.dup
755
-
756
- return result if (s.kind_of? XamplObject)
757
-
758
- result.gsub!("&", "&amp;")
759
- result.gsub!("<", "&lt;")
760
-
761
- return result
762
- end
763
-
764
- def attribute(xampl)
765
- @attr_list = []
766
- if (nil != xampl.attributes) then
767
- xampl.attributes.each{ | attr_spec |
768
- prefix = (2 < attr_spec.length) ? register_ns(attr_spec[2]) : ""
769
- value = get_the_new_pid(xampl.instance_variable_get(attr_spec[0]))
770
- @attr_list << (" " << prefix << attr_spec[1] << "='" << attr_esc(value) << "'") \
771
- unless nil == value
772
- }
773
- end
774
- end
775
-
776
- def persist_attribute(xampl)
777
- @attr_list = []
778
- pattr = xampl.indexed_by.to_s
779
- if (nil != xampl.attributes) then
780
- xampl.attributes.each{ | attr_spec |
781
- if pattr == attr_spec[1] then
782
- prefix = (2 < attr_spec.length) ? register_ns(attr_spec[2]) : ""
783
- value = xampl.instance_variable_get(attr_spec[0])
784
- @attr_list << (" " << prefix << attr_spec[1] << "='" << attr_esc(value) << "'") \
785
- unless nil == value
786
- break
787
- end
788
- }
789
- end
790
- end
791
-
792
- def show_attributes
793
- result = @attr_list.join(" ")
794
- if (0 == result.length) then
795
- return ""
796
- else
797
- return result
798
- end
799
- end
800
-
801
- def start_element(xampl)
802
- tag = xampl.tag
803
- ns = xampl.ns
804
- tag_info = "" << "<" << register_ns(ns) << tag
805
- unless @start_body then
806
- attribute(xampl)
807
- attr_defn = show_attributes
808
- @start_body = "" << tag_info << attr_defn
809
- @was_attr = true if 0 < attr_defn.size
810
- else
811
- if xampl.persist_required then
812
- @no_children = true
813
- persist_attribute(xampl)
814
- else
815
- attribute(xampl)
816
- end
817
- @body << tag_info << show_attributes
818
- end
819
- end
820
-
821
- def end_element(xampl)
822
- tag = xampl.tag
823
- ns = xampl.ns
824
- @body << "</" << register_ns(ns) << tag << ">"
825
- end
826
-
827
- def define_ns
828
- result = ""
829
- ns_to_prefix.each{ | ns, prefix |
830
- result = sprintf("%s xmlns:%s='%s'", result, prefix[0..-2], ns)
831
- }
832
- return result
833
- end
834
-
835
- def done
836
- out << @start_body << define_ns << @body
837
- end
838
-
839
- def before_visit_without_content(xampl)
840
- start_element(xampl)
841
- @body << "/>"
842
- end
843
-
844
- def before_visit_simple_content(xampl)
845
- start_element(xampl)
846
- if @no_children then
847
- @body << "/>"
848
- else
849
- @body << ">"
850
- @body << content_esc(xampl._content) if xampl._content
851
- end_element(xampl)
852
- end
853
- end
854
-
855
- def before_visit_data_content(xampl)
856
- start_element(xampl)
857
- if @no_children then
858
- @body << "/>"
859
- else
860
- @body << ">"
861
- @body << content_esc(xampl._content) if xampl._content
862
- end
863
- end
864
-
865
- def after_visit_data_content(xampl)
866
- end_element(xampl) unless @no_children
867
- end
868
-
869
- def before_visit_mixed_content(xampl)
870
- if @no_children then
871
- @body << "/>"
872
- else
873
- start_element(xampl)
874
- @body << ">"
875
- end
876
- end
877
-
878
- def after_visit_mixed_content(xampl)
879
- end_element(xampl) unless @no_children
880
- end
881
-
882
- def before_visit(xampl)
883
- if xampl.respond_to? "before_visit_by_element_kind" then
884
- xampl.before_visit_by_element_kind(self)
885
- else
886
- @body << xampl.to_s
887
- end
888
- end
889
-
890
- def after_visit(xampl)
891
- xampl.after_visit_by_element_kind(self) if xampl.respond_to? "after_visit_by_element_kind"
892
- end
893
-
894
- def visit_string(string)
895
- @body << string
896
- end
897
- end
898
-
899
- module XamplObject
900
- def pp_xml(out="", skip=[])
901
- PrettyXML.new(out, skip).start(self).done
902
- end
903
-
904
- def to_xml(out="", skip=[])
905
- PersistXML.new(out).start(self).done
906
- end
907
-
908
- def copy_xampl(root, translate_pids={})
909
- CopyXML.copy(root, translate_pids)
910
- end
911
-
912
- def mark_changed_deep
913
- MarkChangedDeep.new.start(self)
914
- end
915
- end
916
-
917
139
  end
918
140