Class: XamplGenerator::Generator

Inherits:
Object
  • Object
show all
Defined in:
lib/xamplr-gen/xampl-generator.rb

Constant Summary collapse

@@standard_templates =
[
        "xamplr-gen/templates/child_modules.template",
        "xamplr-gen/templates/child.template",
        "xamplr-gen/templates/child_indexed.template",
        "xamplr-gen/templates/element_classes.template",
        "xamplr-gen/templates/element_data.template",
        "xamplr-gen/templates/element_empty.template",
        "xamplr-gen/templates/element_mixed.template",
        "xamplr-gen/templates/element_simple.template",
        "xamplr-gen/templates/package.template",
]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options_in = nil, *predefined_elements) ⇒ Generator

Returns a new instance of Generator.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/xamplr-gen/xampl-generator.rb', line 40

def initialize(options_in = nil, *predefined_elements)
  @elements_map = {}
  @xpp = nil
  @templates = nil
  @generated_package_map = nil

  if options_in then
    @options = options_in
  else
    @options = Xampl.make(Options) do |options|
      options.new_index_attribute("id")
      options.new_index_attribute("pid").persisted = true;

      options.new_resolve do |resolver|
        resolver.pkg = "XamplAdHoc"
        resolver.namespace=""
      end
    end
  end

  predefined_elements.each do |elements|
    throw :elements_need_a_pid unless elements.pid
    @elements_map[elements.pid] = elements
  end
end

Instance Attribute Details

#elements_mapObject

Returns the value of attribute elements_map.



26
27
28
# File 'lib/xamplr-gen/xampl-generator.rb', line 26

def elements_map
  @elements_map
end

#optionsObject

Returns the value of attribute options.



26
27
28
# File 'lib/xamplr-gen/xampl-generator.rb', line 26

def options
  @options
end

#templatesObject

Returns the value of attribute templates.



26
27
28
# File 'lib/xamplr-gen/xampl-generator.rb', line 26

def templates
  @templates
end

Class Method Details

.choose_names(original_name, attr_prefix = "_", attr_suffix = "_") ⇒ Object



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/xamplr-gen/xampl-generator.rb', line 384

def Generator.choose_names(original_name, attr_prefix="_", attr_suffix="_")

#      name = original_name.gsub(/[^a-zA-Z_]+/, "_")

  # NOTE (2009-04-16) -- if tag starts with a number, prefix it with an 'x'
  name = original_name.sub(/^([0-9])/) { | m | "x" + m }
  name = name.gsub(/[^a-zA-Z0-9_]+/, "_")


  attr_name = name.gsub(/[A-Z]+/, "_\\&")
  attr_name.gsub!(/__+/, "_")
  attr_name = attr_name[1..-1] if "_"[0] == attr_name[0]
  attr_name.downcase!

  name.gsub!(/[A-Z]/, "_\\&")
  name.gsub!(/__+/, "_")
  class_name = ""
  #name.each("_") do |chunk|
  name.split("_").each do |chunk|
    class_name << chunk.capitalize
  end
  class_name.gsub!("_", "")

  return class_name, attr_name
end

Instance Method Details

#analyseObject



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/xamplr-gen/xampl-generator.rb', line 155

def analyse
  namespace_package_map = {}
  namespace_prefix_map = {}
  options.resolve_child.each do |resolve|
    namespace_package_map[resolve.namespace] = resolve.pkg
  end

  @elements_map.each do |ns, elements|
    package = namespace_package_map[ns]

    elements.element_child.each do |element|
      element.package = package
      element.analyse(options)
    end
  end

  @required_packages = {}
  @elements_map.each do |ns, elements|
    package = namespace_package_map[ns]

    required = @required_packages[package]
    unless required then
      required = {}
      @required_packages[package] = required
    end

    elements.element_child.each do |element|
      element.child_element_child.each do |child_element|
        celement = child_element.find_element(@elements_map)
        #required[celement.package] = celement.package
        unless package == celement.package then
          required[celement.package] = celement.package
        end
      end
    end
  end
end

#comprehend_from_files(filenames) ⇒ Object



142
143
144
145
146
147
# File 'lib/xamplr-gen/xampl-generator.rb', line 142

def comprehend_from_files(filenames)
  filenames.each do |filename|
    puts "comprehend file #{filename}"
    parse_filename(filename)
  end
end

#comprehend_from_strings(strings) ⇒ Object



149
150
151
152
153
# File 'lib/xamplr-gen/xampl-generator.rb', line 149

def comprehend_from_strings(strings)
  strings.each do |string|
    parse_string(string)
  end
end

#ensure_templatesObject



193
194
195
196
197
198
# File 'lib/xamplr-gen/xampl-generator.rb', line 193

def ensure_templates
  return if @templates

  @templates = StandardGeneratorTemplates.new
  @templates.compile_scripts(@@standard_templates)
end

#find_place(directory_name, package) ⇒ Object



200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/xamplr-gen/xampl-generator.rb', line 200

def find_place(directory_name, package)
  #puts "find_place:: package: #{package}"

  @generated_package_map = {} unless @generated_package_map

  place = @generated_package_map[package]
  if nil == place then
    place = ""
    @generated_package_map[package] = place
  end
  return place
end

#generate(directory_name, params = {:verbose => false}, &eval_context) ⇒ Object



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/xamplr-gen/xampl-generator.rb', line 213

def generate(directory_name, params={:verbose => false}, &eval_context)
  ensure_templates

  module_names = Set.new
  @elements_map.each do |ns, elements|
    elements.element_child.each do |element|
      module_names << element.package
      break
    end
  end

  lookup_element = {}
  @elements_map.each do |ns, elements|
    elements.element_child.each do |element|
      lookup_element[element.nstag] = element
    end
  end

  @templates.lookup_element = lookup_element

  @elements_map.each do |ns, elements|
    elements.element_child.each do |element|
      place = find_place(directory_name, element.package)

      @templates.element = element
      @templates.package_name = element.package

      if element.class_name == element.package then
        puts "ERROR: Class #{ element.package } is in a module with the same name -- this NOT going to work"
      elsif module_names.member?(element.class_name)
        puts "WARNING: a Class and a Module have the same name (#{ element.package } or maybe #{ element.class_name }) -- this is highly unlikely to work"
      end

      @templates.child_modules(place)
    end
  end

  unless @generated_package_map then
    puts "Nothing to do. That is, NOTHING is generated. (Are you where you think you are?)"
    return false
  end

  if File.directory? directory_name then
    begin
      FileUtils.rm_rf([ directory_name ])
    rescue => e
      puts "could not clean up #{ directory_name } -- #{ e }"
      return
    end
  elsif File.exists? directory_name then
    puts "please move #{ directory_name } out of the way of xampl-gen"
    return
  end

  if directory_name then
    FileUtils.mkdir_p(directory_name) unless File.exist?(directory_name)
  end


  @elements_map.each do |ns, elements|
    elements.element_child.each do |element|
      place = find_place(directory_name, element.package)

      @templates.element = element
      @templates.package_name = element.package

      @templates.element_classes(place)
    end
  end

  @generated_package_map.each do |package_name, definition|
    package_name = "XamplAdHoc" unless package_name

    @templates.element = nil
    @templates.package_name = package_name
    @templates.options = @options

    @templates.required_packages = @required_packages[package_name] || {}

    @templates.place = definition

    package_definition = @templates.package

    if directory_name then
      output_filename = File.join(directory_name, "#{package_name}.rb")
      puts "WRITE TO FILE: #{output_filename}"
      File.open(output_filename, "w") do |file|
        file.puts package_definition
      end
    end
    if block_given? then
      package_name = "XamplAdHoc" unless package_name
      puts "EVALUATE: #{package_name}"
      eval_context.call(package_definition, package_name)
    end
  end

  report_elements if params[:verbose]
  return true
end

#generate_and_eval(params = {:verbose => false}, &eval_context) ⇒ Object



379
380
381
382
# File 'lib/xamplr-gen/xampl-generator.rb', line 379

def generate_and_eval(params={:verbose => false}, &eval_context)
  analyse
  return generate(nil, params, &eval_context)
end

#generate_to_directory(directory_name, params = {:verbose => false}) ⇒ Object



374
375
376
377
# File 'lib/xamplr-gen/xampl-generator.rb', line 374

def generate_to_directory(directory_name, params={:verbose => false})
  analyse
  return generate(directory_name, params)
end

#go(args, &eval_context) ⇒ Object



348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/xamplr-gen/xampl-generator.rb', line 348

def go(args, &eval_context)
  options = args[:options]
  if options then
    @options = options
  end

  strings = args[:strings]
  if strings then
    comprehend_from_strings(strings)
  end

  filenames = args[:filenames]
  if filenames then
    comprehend_from_files(filenames)
  end

  directory = args[:directory]
  if directory then
    generate_to_directory(directory, args)
  else
    generate_and_eval(args) do |module_definition, name|
      yield(module_definition, name)
    end
  end
end

#parseObject



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/xamplr-gen/xampl-generator.rb', line 117

def parse
  element_stack = []
  current_element = nil

  while not @xpp.endDocument? do
    case @xpp.nextEvent
      when Xampl_PP::START_ELEMENT
        element_stack.push current_element unless nil == current_element
        current_element = start_element(current_element)
      when Xampl_PP::END_ELEMENT
        current_element = element_stack.pop
      when Xampl_PP::TEXT,
              Xampl_PP::CDATA_SECTION,
              Xampl_PP::ENTITY_REF
        if current_element then
          text = @xpp.text
          if (nil != @xpp.text) then
            text = text.strip
            current_element.found_text_content if 0 < text.size
          end
        end
    end
  end
end

#parse_filename(filename) ⇒ Object



105
106
107
108
109
# File 'lib/xamplr-gen/xampl-generator.rb', line 105

def parse_filename(filename)
  @xpp = Xampl_PP.new
  @xpp.input = File.new(filename)
  parse
end

#parse_string(string) ⇒ Object



111
112
113
114
115
# File 'lib/xamplr-gen/xampl-generator.rb', line 111

def parse_string(string)
  @xpp = Xampl_PP.new
  @xpp.input = string
  parse
end


320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/xamplr-gen/xampl-generator.rb', line 320

def print_elements(base_filename, print_options=nil)
  return unless base_filename
  return unless print_options
  return if 0 == print_options.size

  root = Elements.new
  @elements_map.each_value do |elements|
    elements.element_child.each do |element|
      root.children << element
    end
  end

  print_options.each do | print_option |
    case print_option
      when :schema then
        File.open("#{base_filename}.xml", "w") do |out|
          root.pp_xml(out)
        end
      when :graphml then
        graphml_out = GraphMLOut.new(@elements_map)
        graphml_out.write_graph_ml(base_filename)
      when :yuml then
        yuml_out = YUMLOut.new(@elements_map)
        yuml_out.write_yuml(base_filename)
    end
  end
end


410
411
412
413
414
415
416
417
418
419
420
# File 'lib/xamplr-gen/xampl-generator.rb', line 410

def print_stats
  count = 0
  @elements_map.each do |ns, elements|
    count += elements.element_child.size
    printf("namespace: %s, element: %d\n", ns, elements.element_child.size)
  end
  printf("counts of:: namespace: %d, element: %d\n", @elements_map.size, count)
  @elements_map.each do |ns, elements|
    puts elements.pp_xml
  end
end

#report_elementsObject



314
315
316
317
318
# File 'lib/xamplr-gen/xampl-generator.rb', line 314

def report_elements
  @elements_map.each_value do |elements|
    puts elements.pp_xml
  end
end

#start_element(parent) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/xamplr-gen/xampl-generator.rb', line 66

def start_element(parent)
  name = @xpp.name
  namespace = @xpp.namespace
  namespace = "" unless namespace
  is_empty = @xpp.emptyElement

  nstag = "{{#{namespace}}}#{name}"

  elements = @elements_map[namespace]
  if nil == elements then
    elements = Elements.new
    @elements_map[namespace] = elements
  end

  element = elements.element_child[name]
  if nil == element then
    element = elements.new_element(name)
  end

  element.namespace = namespace
  element.nstag = nstag
  element.empty = is_empty

  @xpp.attributeName.each_index do |i|
    attribute = Attribute.new
    attribute.name = @xpp.attributeName[i]
    attribute.namespace = @xpp.attributeNamespace[i]
    element.add_attribute(attribute)
  end

  if parent then
    parent.new_child_element(nstag) do |ce|
      ce.element_name = name
      ce.namespace = namespace
    end
  end
  return element
end