xamplr-gen 1.9.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 (50) hide show
  1. data/.document +5 -0
  2. data/.gitignore +22 -0
  3. data/COPYING +619 -0
  4. data/LICENSE +4 -0
  5. data/Makefile +11 -0
  6. data/README.md +33 -0
  7. data/Rakefile +66 -0
  8. data/VERSION +1 -0
  9. data/bin/xampl-gen +17 -0
  10. data/features/step_definitions/xamplr-gen_steps.rb +0 -0
  11. data/features/support/env.rb +6 -0
  12. data/features/xamplr-gen.feature +9 -0
  13. data/lib/xamplr-gen.rb +13 -0
  14. data/lib/xamplr-gen/.cvsignore +1 -0
  15. data/lib/xamplr-gen/graphml-out.rb +449 -0
  16. data/lib/xamplr-gen/my.gen.elements.xml +461 -0
  17. data/lib/xamplr-gen/simpleTemplate/danger.rx +4 -0
  18. data/lib/xamplr-gen/simpleTemplate/obsolete/input-c.r4 +35 -0
  19. data/lib/xamplr-gen/simpleTemplate/obsolete/play.r6.txt +12 -0
  20. data/lib/xamplr-gen/simpleTemplate/obsolete/play_more.r6.txt +20 -0
  21. data/lib/xamplr-gen/simpleTemplate/obsolete/test001.r5 +8 -0
  22. data/lib/xamplr-gen/simpleTemplate/obsolete/test002.r5 +13 -0
  23. data/lib/xamplr-gen/simpleTemplate/obsolete/test003.r5 +37 -0
  24. data/lib/xamplr-gen/simpleTemplate/old/r6.000.rb +122 -0
  25. data/lib/xamplr-gen/simpleTemplate/old/r6.001.rb +145 -0
  26. data/lib/xamplr-gen/simpleTemplate/play.r6 +12 -0
  27. data/lib/xamplr-gen/simpleTemplate/play_more.r6 +20 -0
  28. data/lib/xamplr-gen/simpleTemplate/play_noblanks.r6 +21 -0
  29. data/lib/xamplr-gen/simpleTemplate/playq.r6 +16 -0
  30. data/lib/xamplr-gen/simpleTemplate/r6.rb +87 -0
  31. data/lib/xamplr-gen/simpleTemplate/simple-template.rb +75 -0
  32. data/lib/xamplr-gen/templates/.cvsignore +3 -0
  33. data/lib/xamplr-gen/templates/child.template +47 -0
  34. data/lib/xamplr-gen/templates/child_indexed.template +89 -0
  35. data/lib/xamplr-gen/templates/child_modules.template +5 -0
  36. data/lib/xamplr-gen/templates/element_classes.template +11 -0
  37. data/lib/xamplr-gen/templates/element_data.template +283 -0
  38. data/lib/xamplr-gen/templates/element_empty.template +277 -0
  39. data/lib/xamplr-gen/templates/element_mixed.template +278 -0
  40. data/lib/xamplr-gen/templates/element_simple.template +277 -0
  41. data/lib/xamplr-gen/templates/package.template +38 -0
  42. data/lib/xamplr-gen/xampl-cl-gen.rb +89 -0
  43. data/lib/xamplr-gen/xampl-generator.rb +561 -0
  44. data/lib/xamplr-gen/xampl-hand-generated.rb +1534 -0
  45. data/lib/xamplr-gen/yuml-out.rb +127 -0
  46. data/licence.rb +17 -0
  47. data/test/helper.rb +10 -0
  48. data/test/test_xamplr-gen.rb +7 -0
  49. data/xamplr-gen.gemspec +98 -0
  50. metadata +124 -0
@@ -0,0 +1,277 @@
1
+
2
+ class #{@element.class_name}
3
+ |
4
+ |if @element.persisted then
5
+ |
6
+ include Xampl::XamplPersistedObject
7
+
8
+ #supports class based over-ride of persister format
9
+ @@default_persister_format = nil
10
+
11
+ def default_persister_format
12
+ @@default_persister_format
13
+ end
14
+ def #{@element.class_name}.default_persister_format
15
+ @@default_persister_format
16
+ end
17
+ def #{@element.class_name}.set_default_persister_format(format)
18
+ @@default_persister_format = format
19
+ end
20
+
21
+ def #{@element.class_name}.find_by_query
22
+ things = Xampl.find_xampl do | q |
23
+ q.add_condition('class', :equals, self.name)
24
+ yield(q)
25
+ end
26
+ end
27
+
28
+ |
29
+ |else
30
+ |
31
+ include Xampl::XamplObject
32
+ |
33
+ |end
34
+ |
35
+ include Xampl::XamplWithSimpleContent
36
+
37
+ @@tag = "#{@element.name}"
38
+ @@ns = "#{@element.namespace}"
39
+ @@ns_tag = "{#{@element.namespace}}#{@element.name}"
40
+ @@module_name = "#{@package_name}"
41
+ @@safe_name = "#{@package_name}_#{@element.attribute_name}"
42
+ @@attributes = [
43
+ |
44
+ |@element.attribute_child.each{ | attribute |
45
+ | if attribute.namespace then
46
+ |
47
+ [ :@#{attribute.name}, "#{attribute.name}", "#{attribute.namespace}" ],
48
+ |
49
+ | else
50
+ |
51
+ [ :@#{attribute.name}, "#{attribute.name}" ],
52
+ |
53
+ | end
54
+ |}
55
+ |
56
+ ]
57
+ |
58
+ |@element.child_element_child.each{ | child_element |
59
+ | element_class_name = @lookup_element[child_element.name].class_name
60
+ | element_package = @lookup_element[child_element.name].package
61
+ |
62
+ include #{element_package}::#{element_class_name}AsChild
63
+ |
64
+ |}
65
+ |
66
+ |if @element.persisted then
67
+ |
68
+
69
+ def #{@element.class_name}.lookup(pid)
70
+ Xampl.lookup(#{@element.class_name}, pid)
71
+ end
72
+
73
+ def #{@element.class_name}.[](pid)
74
+ Xampl.lookup(#{@element.class_name}, pid)
75
+ end
76
+ |
77
+ |end
78
+ |
79
+ |@element.attribute_child.each{ | attribute |
80
+ | if attribute.name == @element.indexed_by_attr and @element.persisted then
81
+ |
82
+
83
+ def #{attribute.name}
84
+ @#{attribute.name}
85
+ end
86
+
87
+ def #{attribute.name}=(v)
88
+ accessed
89
+ # This is kind of optimistic, I think you are in trouble if you do this
90
+ Xampl.auto_uncache(self) if @#{attribute.name}
91
+ @#{attribute.name} = v
92
+ changed
93
+ Xampl.auto_cache(self) if v
94
+ end
95
+ |
96
+ | else
97
+ |
98
+
99
+ def #{attribute.name}
100
+ accessed
101
+ @#{attribute.name}
102
+ end
103
+
104
+ def #{attribute.name}=(v)
105
+ accessed
106
+ changed
107
+ @#{attribute.name} = v
108
+ end
109
+ |
110
+ | end
111
+ |}
112
+ |
113
+ | if @element.indexed_by_attr then
114
+ |
115
+
116
+ def initialize(index=nil)
117
+ @#{@element.indexed_by_attr} = index if index
118
+ super()
119
+ |
120
+ | else
121
+ |
122
+
123
+ def initialize
124
+ super
125
+ |
126
+ |end
127
+ |
128
+ |if 0 < @element.attribute_child.size then
129
+ |
130
+
131
+ |
132
+ |end
133
+ |
134
+ |@element.attribute_child.each{ | attribute |
135
+ |
136
+ @#{attribute.name} = nil if not defined? @#{attribute.name}
137
+ |
138
+ |}
139
+ |
140
+
141
+ init_xampl_object
142
+ |
143
+ |@element.child_element_child.each{ | child_element |
144
+ | element_attribute_name = @lookup_element[child_element.name].attribute_name
145
+ |
146
+ init_#{child_element.element_attribute_name}_as_child
147
+ |
148
+ |}
149
+ |
150
+
151
+ yield(self) if block_given?
152
+ init_hook
153
+
154
+ changed
155
+ end
156
+
157
+ def clear_non_persistent_index_attributes
158
+ |
159
+ |@element.attribute_child.each{ | attribute |
160
+ | unless attribute.name == @element.indexed_by_attr and @element.persisted then
161
+ |
162
+ @#{attribute.name} = nil
163
+ |
164
+ | end
165
+ |}
166
+ |
167
+ end
168
+
169
+ def append_to(other)
170
+ other.add_#{@element.attribute_name}(self)
171
+ end
172
+
173
+ |
174
+ |if @element.persisted then
175
+ |
176
+ def #{@element.class_name}.persisted?
177
+ return :#{@element.indexed_by_attr}
178
+ end
179
+
180
+ def persisted?
181
+ return :#{@element.indexed_by_attr}
182
+ end
183
+
184
+ |
185
+ |else
186
+ |
187
+ def #{@element.class_name}.persisted?
188
+ return nil
189
+ end
190
+
191
+ def persisted?
192
+ return nil
193
+ end
194
+
195
+ |
196
+ |end
197
+ |
198
+ def #{@element.class_name}.tag
199
+ @@tag
200
+ end
201
+
202
+ def #{@element.class_name}.ns
203
+ @@ns
204
+ end
205
+
206
+ def #{@element.class_name}.ns_tag
207
+ @@ns_tag
208
+ end
209
+
210
+ def #{@element.class_name}.safe_name
211
+ @@safe_name
212
+ end
213
+
214
+ def #{@element.class_name}.module_name
215
+ @@module_name
216
+ end
217
+
218
+ def tag
219
+ @@tag
220
+ end
221
+
222
+ def ns
223
+ @@ns
224
+ end
225
+
226
+ def ns_tag
227
+ @@ns_tag
228
+ end
229
+
230
+ def safe_name
231
+ @@safe_name
232
+ end
233
+
234
+ def module_name
235
+ @@module_name
236
+ end
237
+
238
+ def attributes
239
+ @@attributes
240
+ end
241
+ |
242
+ |if @element.indexed_by_attr
243
+ |
244
+
245
+ def indexed_by
246
+ :#{@element.indexed_by_attr}
247
+ end
248
+
249
+ def get_the_index
250
+ @#{@element.indexed_by_attr}
251
+ end
252
+
253
+ def set_the_index(index)
254
+ @#{@element.indexed_by_attr} = index
255
+ end
256
+ |
257
+ |end
258
+ |
259
+
260
+ def substitute_in_visit(visitor)
261
+ return visitor.substitute_in_visit_#{@element.attribute_name}(self) || self
262
+ end
263
+
264
+ def before_visit(visitor)
265
+ visitor.before_visit_#{@element.attribute_name}(self)
266
+ end
267
+
268
+ def visit(visitor)
269
+ visitor.visit_#{@element.attribute_name}(self)
270
+ end
271
+
272
+ def after_visit(visitor)
273
+ visitor.after_visit_#{@element.attribute_name}(self)
274
+ end
275
+
276
+ Xampl::FromXML::register(#{@element.class_name}::tag, #{@element.class_name}::ns_tag, #{@element.class_name})
277
+ end
@@ -0,0 +1,38 @@
1
+ |
2
+ | unless 'XamplAdHoc' == package_name
3
+ |
4
+ module #{package_name}
5
+ |
6
+ | end
7
+ |
8
+
9
+ require "xamplr"
10
+ include Xampl
11
+
12
+ |
13
+ | @required_packages.each_key{ | required_package_name |
14
+ |
15
+ require "#{required_package_name}"
16
+ |
17
+ | }
18
+ |
19
+
20
+ |
21
+ | if @options then
22
+ | @options.resolve_child.each{ | r |
23
+ | if r.namespace and (0 < r.namespace.length) and r.preferred_prefix and (0 < r.preferred_prefix.length) then
24
+ |
25
+ XamplObject.ns_preferred_prefix("#{r.namespace}", "#{r.preferred_prefix}")
26
+ |
27
+ | end
28
+ | }
29
+ | end
30
+ |
31
+ #{place}
32
+ |
33
+ | unless 'XamplAdHoc' == package_name
34
+ |
35
+ end
36
+ |
37
+ | end
38
+ |
@@ -0,0 +1,89 @@
1
+
2
+ #require 'xampl-generator'
3
+
4
+ include XamplGenerator
5
+ include Xampl
6
+
7
+ class ProjectGenerator
8
+
9
+ def directory
10
+ File.join(%w{ . xampl_generated_code })
11
+ end
12
+
13
+ def filenames
14
+ Dir.glob("./xml/**/*.xml")
15
+ end
16
+
17
+ def print_base_filename
18
+ File.join(%w{ . generated })
19
+ end
20
+
21
+ def print_options
22
+ # return an array containing any (or none) of:
23
+ # :schema -- a schema-like xml representation of the generated code
24
+ # :graphml -- a graphml file describing the class model (compatible with yEd)
25
+ # :yuml -- a yuml file that represents a simplified class model (compatible with yUML)
26
+
27
+ # [:schema, :graphml, :yuml]
28
+ []
29
+ end
30
+
31
+ def print
32
+ nil
33
+ end
34
+
35
+ def persisted_attributes
36
+ %w{ pid }
37
+ end
38
+
39
+ def indexed_attributes
40
+ %w{ id }
41
+ end
42
+
43
+ def resolve_namespaces
44
+ # any array of arrays
45
+ # each sub-array:
46
+ # 0: a string or an array of strings, containing xml namespaces found in the example xml files
47
+ # an empty string is the default namespace
48
+ # 1: a ruby Module name (get the cases right)
49
+ # 2: a namespace prefix used when writing xml, optional. A generated prefix will be used otherwise.
50
+ []
51
+ end
52
+
53
+ def generate
54
+
55
+ # Xampl.set_default_persister_kind(:simple)
56
+ Xampl.set_default_persister_kind(:in_memory)
57
+ # Xampl.set_default_persister_kind(:filesystem)
58
+ # Xampl.set_default_persister_kind(:tokyo_cabinet)
59
+ # Xampl.set_default_persister_format(:xml_format)
60
+
61
+ Xampl.transaction("project-generation") do
62
+
63
+ options = Options.new do | opts |
64
+ persisted_attributes.each do | pattr |
65
+ opts.new_index_attribute(pattr).persisted = true
66
+ end
67
+
68
+ indexed_attributes.each do | iattr |
69
+ opts.new_index_attribute(iattr)
70
+ end
71
+
72
+ resolve_namespaces.each do | namespace, ruby_module_name, output_ns_prefix |
73
+ opts.resolve(namespace, ruby_module_name, output_ns_prefix)
74
+ end
75
+
76
+ end
77
+
78
+ generator = Generator.new('generator')
79
+ generator.go(:options => options,
80
+ :filenames => filenames,
81
+ :directory => directory)
82
+
83
+ puts generator.print_elements(print_base_filename, print_options)
84
+
85
+ Xampl.rollback
86
+ end
87
+ end
88
+ end
89
+
@@ -0,0 +1,561 @@
1
+
2
+ module XamplGenerator
3
+
4
+ class Attribute
5
+ attr_accessor :tag_name
6
+ end
7
+
8
+ class StandardGeneratorTemplates
9
+ include TemplateEngine
10
+
11
+ attr_accessor :element, :package_name, :place, :lookup_element, :options, :required_packages
12
+
13
+ def initialize
14
+ super
15
+ @element = nil
16
+ @package_name = nil
17
+ @place = nil
18
+ @lookup_element = {}
19
+ @options = nil
20
+ @required_packages = {}
21
+ end
22
+ end
23
+
24
+ class Generator
25
+
26
+ attr_accessor :elements_map, :options, :templates
27
+
28
+ @@standard_templates = [
29
+ "xamplr-gen/templates/child_modules.template",
30
+ "xamplr-gen/templates/child.template",
31
+ "xamplr-gen/templates/child_indexed.template",
32
+ "xamplr-gen/templates/element_classes.template",
33
+ "xamplr-gen/templates/element_data.template",
34
+ "xamplr-gen/templates/element_empty.template",
35
+ "xamplr-gen/templates/element_mixed.template",
36
+ "xamplr-gen/templates/element_simple.template",
37
+ "xamplr-gen/templates/package.template",
38
+ ]
39
+
40
+ def initialize(options_in = nil, *predefined_elements)
41
+ @elements_map = {}
42
+ @xpp = nil
43
+ @templates = nil
44
+ @generated_package_map = nil
45
+
46
+ if options_in then
47
+ @options = options_in
48
+ else
49
+ @options = Xampl.make(Options) do |options|
50
+ options.new_index_attribute("id")
51
+ options.new_index_attribute("pid").persisted = true;
52
+
53
+ options.new_resolve do |resolver|
54
+ resolver.pkg = "XamplAdHoc"
55
+ resolver.namespace=""
56
+ end
57
+ end
58
+ end
59
+
60
+ predefined_elements.each do |elements|
61
+ throw :elements_need_a_pid unless elements.pid
62
+ @elements_map[elements.pid] = elements
63
+ end
64
+ end
65
+
66
+ def start_element(parent)
67
+ name = @xpp.name
68
+ namespace = @xpp.namespace
69
+ namespace = "" unless namespace
70
+ is_empty = @xpp.emptyElement
71
+
72
+ nstag = "{{#{namespace}}}#{name}"
73
+
74
+ elements = @elements_map[namespace]
75
+ if nil == elements then
76
+ elements = Elements.new
77
+ @elements_map[namespace] = elements
78
+ end
79
+
80
+ element = elements.element_child[name]
81
+ if nil == element then
82
+ element = elements.new_element(name)
83
+ end
84
+
85
+ element.namespace = namespace
86
+ element.nstag = nstag
87
+ element.empty = is_empty
88
+
89
+ @xpp.attributeName.each_index do |i|
90
+ attribute = Attribute.new
91
+ attribute.name = @xpp.attributeName[i]
92
+ attribute.namespace = @xpp.attributeNamespace[i]
93
+ element.add_attribute(attribute)
94
+ end
95
+
96
+ if parent then
97
+ parent.new_child_element(nstag) do |ce|
98
+ ce.element_name = name
99
+ ce.namespace = namespace
100
+ end
101
+ end
102
+ return element
103
+ end
104
+
105
+ def parse_filename(filename)
106
+ @xpp = Xampl_PP.new
107
+ @xpp.input = File.new(filename)
108
+ parse
109
+ end
110
+
111
+ def parse_string(string)
112
+ @xpp = Xampl_PP.new
113
+ @xpp.input = string
114
+ parse
115
+ end
116
+
117
+ def parse
118
+ element_stack = []
119
+ current_element = nil
120
+
121
+ while not @xpp.endDocument? do
122
+ case @xpp.nextEvent
123
+ when Xampl_PP::START_ELEMENT
124
+ element_stack.push current_element unless nil == current_element
125
+ current_element = start_element(current_element)
126
+ when Xampl_PP::END_ELEMENT
127
+ current_element = element_stack.pop
128
+ when Xampl_PP::TEXT,
129
+ Xampl_PP::CDATA_SECTION,
130
+ Xampl_PP::ENTITY_REF
131
+ if current_element then
132
+ text = @xpp.text
133
+ if (nil != @xpp.text) then
134
+ text = text.strip
135
+ current_element.found_text_content if 0 < text.size
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ def comprehend_from_files(filenames)
143
+ filenames.each do |filename|
144
+ puts "comprehend file #{filename}"
145
+ parse_filename(filename)
146
+ end
147
+ end
148
+
149
+ def comprehend_from_strings(strings)
150
+ strings.each do |string|
151
+ parse_string(string)
152
+ end
153
+ end
154
+
155
+ def analyse
156
+ namespace_package_map = {}
157
+ namespace_prefix_map = {}
158
+ options.resolve_child.each do |resolve|
159
+ namespace_package_map[resolve.namespace] = resolve.pkg
160
+ end
161
+
162
+ @elements_map.each do |ns, elements|
163
+ package = namespace_package_map[ns]
164
+
165
+ elements.element_child.each do |element|
166
+ element.package = package
167
+ element.analyse(options)
168
+ end
169
+ end
170
+
171
+ @required_packages = {}
172
+ @elements_map.each do |ns, elements|
173
+ package = namespace_package_map[ns]
174
+
175
+ required = @required_packages[package]
176
+ unless required then
177
+ required = {}
178
+ @required_packages[package] = required
179
+ end
180
+
181
+ elements.element_child.each do |element|
182
+ element.child_element_child.each do |child_element|
183
+ celement = child_element.find_element(@elements_map)
184
+ #required[celement.package] = celement.package
185
+ unless package == celement.package then
186
+ required[celement.package] = celement.package
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
192
+
193
+ def ensure_templates
194
+ return if @templates
195
+
196
+ @templates = StandardGeneratorTemplates.new
197
+ @templates.compile_scripts(@@standard_templates)
198
+ end
199
+
200
+ def find_place(directory_name, package)
201
+ #puts "find_place:: package: #{package}"
202
+
203
+ @generated_package_map = {} unless @generated_package_map
204
+
205
+ place = @generated_package_map[package]
206
+ if nil == place then
207
+ place = ""
208
+ @generated_package_map[package] = place
209
+ end
210
+ return place
211
+ end
212
+
213
+ def generate(directory_name, params={:verbose => false}, &eval_context)
214
+ if directory_name then
215
+ FileUtils.mkdir_p(directory_name) unless File.exist?(directory_name)
216
+ end
217
+
218
+ ensure_templates
219
+
220
+ module_names = Set.new
221
+ @elements_map.each do |ns, elements|
222
+ elements.element_child.each do |element|
223
+ module_names << element.package
224
+ break
225
+ end
226
+ end
227
+
228
+ lookup_element = {}
229
+ @elements_map.each do |ns, elements|
230
+ elements.element_child.each do |element|
231
+ lookup_element[element.nstag] = element
232
+ end
233
+ end
234
+
235
+ @templates.lookup_element = lookup_element
236
+
237
+ @elements_map.each do |ns, elements|
238
+ elements.element_child.each do |element|
239
+ place = find_place(directory_name, element.package)
240
+
241
+ @templates.element = element
242
+ @templates.package_name = element.package
243
+
244
+ if element.class_name == element.package then
245
+ puts "ERROR: Class #{ element.package } is in a module with the same name -- this NOT going to work"
246
+ elsif module_names.member?(element.class_name)
247
+ puts "WARNING: a Class and a Module have the same name (#{ element.package }) -- this is highly unlikely to work"
248
+ end
249
+
250
+ @templates.child_modules(place)
251
+ end
252
+ end
253
+
254
+ @elements_map.each do |ns, elements|
255
+ elements.element_child.each do |element|
256
+ place = find_place(directory_name, element.package)
257
+
258
+ @templates.element = element
259
+ @templates.package_name = element.package
260
+
261
+ @templates.element_classes(place)
262
+ end
263
+ end
264
+
265
+ @generated_package_map.each do |package_name, definition|
266
+ package_name = "XamplAdHoc" unless package_name
267
+
268
+ @templates.element = nil
269
+ @templates.package_name = package_name
270
+ @templates.options = @options
271
+
272
+ @templates.required_packages = @required_packages[package_name] || {}
273
+
274
+ @templates.place = definition
275
+
276
+ package_definition = @templates.package
277
+
278
+ if directory_name then
279
+ output_filename = File.join(directory_name, "#{package_name}.rb")
280
+ puts "WRITE TO FILE: #{output_filename}"
281
+ #puts package_definition
282
+ File.open(output_filename, "w") do |file|
283
+ file.puts package_definition
284
+ end
285
+ end
286
+ if block_given? then
287
+ package_name = "XamplAdHoc" unless package_name
288
+ puts "EVALUATE: #{package_name}"
289
+ eval_context.call(package_definition, package_name)
290
+ end
291
+ end
292
+
293
+ report_elements if params[:verbose]
294
+ end
295
+
296
+ def report_elements
297
+ @elements_map.each_value do |elements|
298
+ puts elements.pp_xml
299
+ end
300
+ end
301
+
302
+ def print_elements(base_filename, print_options=nil)
303
+ return unless base_filename
304
+ return unless print_options
305
+ return if 0 == print_options.size
306
+
307
+ root = Elements.new
308
+ @elements_map.each_value do |elements|
309
+ elements.element_child.each do |element|
310
+ root.children << element
311
+ end
312
+ end
313
+
314
+ print_options.each do | print_option |
315
+ case print_option
316
+ when :schema then
317
+ File.open("#{base_filename}.xml", "w") do |out|
318
+ root.pp_xml(out)
319
+ end
320
+ when :graphml then
321
+ graphml_out = GraphMLOut.new(@elements_map)
322
+ graphml_out.write_graph_ml(base_filename)
323
+ when :yuml then
324
+ yuml_out = YUMLOut.new(@elements_map)
325
+ yuml_out.write_yuml(base_filename)
326
+ end
327
+ end
328
+ end
329
+
330
+ def go(args, &eval_context)
331
+ options = args[:options]
332
+ if options then
333
+ @options = options
334
+ end
335
+
336
+ strings = args[:strings]
337
+ if strings then
338
+ comprehend_from_strings(strings)
339
+ end
340
+
341
+ filenames = args[:filenames]
342
+ if filenames then
343
+ comprehend_from_files(filenames)
344
+ end
345
+
346
+ directory = args[:directory]
347
+ if directory then
348
+ generate_to_directory(directory, args)
349
+ else
350
+ generate_and_eval(args) do |module_definition, name|
351
+ yield(module_definition, name)
352
+ end
353
+ end
354
+ end
355
+
356
+ def generate_to_directory(directory_name, params={:verbose => false})
357
+ analyse
358
+ return generate(directory_name, params)
359
+ end
360
+
361
+ def generate_and_eval(params={:verbose => false}, &eval_context)
362
+ analyse
363
+ return generate(nil, params, &eval_context)
364
+ end
365
+
366
+ def Generator.choose_names(original_name, attr_prefix="_", attr_suffix="_")
367
+
368
+ # name = original_name.gsub(/[^a-zA-Z_]+/, "_")
369
+
370
+ # NOTE (2009-04-16) -- if tag starts with a number, prefix it with an 'x'
371
+ name = original_name.sub(/^([0-9])/) { | m | "x" + m }
372
+ name = name.gsub(/[^a-zA-Z0-9_]+/, "_")
373
+
374
+
375
+ attr_name = name.gsub(/[A-Z]+/, "_\\&")
376
+ attr_name.gsub!(/__+/, "_")
377
+ attr_name = attr_name[1..-1] if "_"[0] == attr_name[0]
378
+ attr_name.downcase!
379
+
380
+ name.gsub!(/[A-Z]/, "_\\&")
381
+ name.gsub!(/__+/, "_")
382
+ class_name = ""
383
+ #name.each("_") do |chunk|
384
+ name.split("_").each do |chunk|
385
+ class_name << chunk.capitalize
386
+ end
387
+ class_name.gsub!("_", "")
388
+
389
+ return class_name, attr_name
390
+ end
391
+
392
+ def print_stats
393
+ count = 0
394
+ @elements_map.each do |ns, elements|
395
+ count += elements.element_child.size
396
+ printf("namespace: %s, element: %d\n", ns, elements.element_child.size)
397
+ end
398
+ printf("counts of:: namespace: %d, element: %d\n", @elements_map.size, count)
399
+ @elements_map.each do |ns, elements|
400
+ puts elements.pp_xml
401
+ end
402
+ end
403
+ end
404
+
405
+ class Options
406
+ def resolve(namespace, pkg="XamplAdHoc", preferred_prefix=nil)
407
+ if (namespace.kind_of?(Array)) then
408
+ namespace.each do |ns, prefix|
409
+ self.new_resolve do |resolver|
410
+ resolver.pkg = pkg
411
+ resolver.namespace = ns
412
+ resolver.preferred_prefix = prefix
413
+ end
414
+ end
415
+ else
416
+ self.new_resolve do |resolver|
417
+ resolver.pkg = pkg
418
+ resolver.namespace = namespace
419
+ resolver.preferred_prefix = preferred_prefix
420
+ end
421
+ end
422
+ end
423
+ end
424
+
425
+ class ChildElement
426
+ def find_element(map)
427
+ elements = map[self.namespace]
428
+ return elements.element[self.element_name]
429
+ end
430
+ end
431
+
432
+ class Element
433
+ def found_text_content
434
+ self.has_content = true
435
+ end
436
+
437
+ def analyse(options)
438
+ is_empty, is_simple, is_data, is_mixed = false
439
+
440
+ class_name, attribute_name = Generator.choose_names(@name)
441
+ @class_name = class_name unless @class_name
442
+ @attribute_name = attribute_name unless @attribute_name
443
+
444
+ no_children = (0 == @child_element_child.size)
445
+
446
+ unless @kind then
447
+ if no_children then
448
+ is_simple = @has_content
449
+ is_empty = !is_simple
450
+ else
451
+ is_mixed = @has_content
452
+ is_data = !@has_content
453
+ end
454
+
455
+ # this isn't a very strong piece of information, can't do much about it.
456
+ #attribute_like = ((0 == @attribute_child.size) and is_simple)
457
+
458
+ if is_empty then
459
+ @kind = "empty"
460
+ elsif is_simple then
461
+ @kind = "simple"
462
+ elsif is_data then
463
+ @kind = "data"
464
+ elsif is_mixed then
465
+ @kind = "mixed"
466
+ else
467
+ throw "no kind determined" # this should be impossible
468
+ end
469
+ end
470
+
471
+ unless self.indexed_by_attr then
472
+ attribute_child.each do |attribute|
473
+ aname_orig = attribute.name
474
+ class_name, aname = Generator.choose_names(aname_orig)
475
+ attribute.name = aname
476
+ attribute.tag_name = aname_orig
477
+
478
+ options.index_attribute_child.each do |iattr|
479
+ if aname == iattr.name then
480
+ self.indexed_by_attr = aname
481
+ self.persisted = iattr.persisted
482
+ break
483
+ end
484
+ end
485
+ end
486
+
487
+ if self.persisted then
488
+ attribute = Attribute.new
489
+ attribute.name = 'scheduled_for_deletion_at'
490
+ attribute.tag_name = 'scheduled-for-deletion-at'
491
+ attribute.namespace = nil
492
+ self.add_attribute(attribute)
493
+ end
494
+
495
+ end
496
+ end
497
+ end
498
+
499
+ def XamplGenerator.from_command_line(options=nil)
500
+ opts = GetoptLong.new(
501
+ ["--options", "-o", GetoptLong::REQUIRED_ARGUMENT],
502
+ ["--elements", "-e", GetoptLong::REQUIRED_ARGUMENT],
503
+ ["--gen:options", "-O", GetoptLong::OPTIONAL_ARGUMENT],
504
+ ["--gen:elements", "-E", GetoptLong::OPTIONAL_ARGUMENT],
505
+ ["--directory", "-d", GetoptLong::REQUIRED_ARGUMENT],
506
+ ["--help", "-h", GetoptLong::NO_ARGUMENT],
507
+ ["--version", "-v", GetoptLong::NO_ARGUMENT]
508
+ )
509
+
510
+ write_options = nil
511
+ write_elements = nil
512
+ directory = File.join(".", "tmp")
513
+
514
+ opts.each do |opt, arg|
515
+ case opt
516
+ when "--help" then
517
+ puts "--help, -h :: this help message"
518
+ puts "--options, -o :: xml file seting the generation options"
519
+ puts "--elements, -e :: xml file providing a hint 'schema' (very optional)"
520
+ puts "--gen:options, -O :: write an xml file describing the options used (default gen-options.xml)"
521
+ puts "--gen:elements, -E :: write an xml file describing the 'schema' (default gen-elements.xml)"
522
+ puts "--directory, -o :: where to write the generated files (default #{directory})"
523
+ puts "--version, -o :: what version of xampl is this?"
524
+ exit
525
+ when "--version" then
526
+ puts "version 0.0.0"
527
+ exit
528
+ when "--directory"
529
+ directory = arg
530
+ when "--options"
531
+ puts "sorry, cannot read options yet"
532
+ when "--elements"
533
+ puts "sorry, cannot read elements yet"
534
+ when "--gen:options"
535
+ write_options = (arg and (0 < arg.length)) ? arg : "gen-options.xml"
536
+ when "--gen:elements"
537
+ write_elements = (arg and (0 < arg.length)) ? arg : "gen-elements.xml"
538
+ else
539
+ puts " #{opt} #{arg}"
540
+ end
541
+ end
542
+
543
+ puts "write options to: #{write_options}" if write_options
544
+ puts "write elements to: #{write_elements}" if write_elements
545
+ puts "write generated code to: #{directory}" if directory
546
+
547
+ generator = Generator.new(options)
548
+
549
+ filenames = []
550
+ ARGV.each do |name|
551
+ filenames << name
552
+ end
553
+
554
+ if 0 < filenames.length then
555
+ generator.comprehend_from_files(filenames)
556
+ generator.generate_to_directory(directory)
557
+
558
+ generator.print_elements(write_elements) if write_elements
559
+ end
560
+ end
561
+ end