xamplr-gen 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
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