genprovider 0.2.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 (94) hide show
  1. data/CHANGELOG +8 -0
  2. data/CHANGELOG~ +4 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +58 -0
  5. data/README.rdoc +50 -0
  6. data/Rakefile +6 -0
  7. data/bin/genprovider +256 -0
  8. data/bin/regprovider +105 -0
  9. data/features/003-create.feature +10 -0
  10. data/features/004-modify.feature +9 -0
  11. data/features/005-delete.feature +7 -0
  12. data/features/datatypes.feature +13 -0
  13. data/features/ensure-format.feature +28 -0
  14. data/features/have-instances.feature +19 -0
  15. data/features/mof/trivial.mof +20 -0
  16. data/features/registration.feature +12 -0
  17. data/features/run-genprovider.feature +10 -0
  18. data/features/show-context.feature +9 -0
  19. data/features/step_definitions/genprovider.rb +52 -0
  20. data/features/step_definitions/mof.rb +3 -0
  21. data/features/step_definitions/registration.rb +21 -0
  22. data/features/step_definitions/wbemcli.rb +58 -0
  23. data/features/support/env.rb +20 -0
  24. data/genprovider.gemspec +36 -0
  25. data/lib/genprovider/class.rb +200 -0
  26. data/lib/genprovider/classinfo.rb +88 -0
  27. data/lib/genprovider/output.rb +104 -0
  28. data/lib/genprovider/provider.rb +721 -0
  29. data/lib/genprovider/rdoc.rb +149 -0
  30. data/lib/genprovider/registration.rb +22 -0
  31. data/lib/genprovider/testcase.rb +139 -0
  32. data/lib/genprovider/version.rb +3 -0
  33. data/lib/genprovider.rb +35 -0
  34. data/samples/mof/LMI_Embedded.mof +6 -0
  35. data/samples/mof/RCP_ArrayDataTypes.mof +27 -0
  36. data/samples/mof/RCP_ClassMethod.mof +7 -0
  37. data/samples/mof/RCP_ComplexMethod.mof +14 -0
  38. data/samples/mof/RCP_IndicationGenerator.mof +13 -0
  39. data/samples/mof/RCP_PassCData.mof +10 -0
  40. data/samples/mof/RCP_ShowContext.mof +11 -0
  41. data/samples/mof/RCP_SimpleClass.mof +7 -0
  42. data/samples/mof/RCP_SimpleDataTypes.mof +27 -0
  43. data/samples/mof/RCP_SimpleMethod.mof +9 -0
  44. data/samples/mof/qualifiers.mof +20 -0
  45. data/samples/provider/lmi_embedded.rb +148 -0
  46. data/samples/provider/rcp_array_data_types.rb +219 -0
  47. data/samples/provider/rcp_class_method.rb +54 -0
  48. data/samples/provider/rcp_complex_method.rb +170 -0
  49. data/samples/provider/rcp_pass_c_data.rb +130 -0
  50. data/samples/provider/rcp_show_context.rb +134 -0
  51. data/samples/provider/rcp_simple_class.rb +124 -0
  52. data/samples/provider/rcp_simple_data_types.rb +152 -0
  53. data/samples/provider/rcp_simple_method.rb +143 -0
  54. data/samples/registration/LMI_Embedded.registration +7 -0
  55. data/samples/registration/RCP_ArrayDataTypes.registration +7 -0
  56. data/samples/registration/RCP_ClassMethod.registration +8 -0
  57. data/samples/registration/RCP_ComplexMethod.registration +8 -0
  58. data/samples/registration/RCP_PassCData.registration +7 -0
  59. data/samples/registration/RCP_ShowContext.registration +7 -0
  60. data/samples/registration/RCP_SimpleDataTypes.registration +7 -0
  61. data/samples/registration/RCP_SimpleMethod.registration +8 -0
  62. data/samples/sfcb.reg/RCP_ComputerSystem.reg +5 -0
  63. data/samples/sfcb.reg/RCP_OSProcess.reg +5 -0
  64. data/samples/sfcb.reg/RCP_OperatingSystem.reg +5 -0
  65. data/samples/sfcb.reg/RCP_PhysicalMemory.reg +5 -0
  66. data/samples/sfcb.reg/RCP_Processor.reg +5 -0
  67. data/samples/sfcb.reg/RCP_RunningOS.reg +5 -0
  68. data/samples/sfcb.reg/RCP_SimpleClass.reg +5 -0
  69. data/samples/sfcb.reg/RCP_UnixProcess.reg +5 -0
  70. data/sfcbd +4 -0
  71. data/stress.sh +4 -0
  72. data/tasks/clean.rake +4 -0
  73. data/tasks/doc.rake +16 -0
  74. data/tasks/features.rake +8 -0
  75. data/tasks/prepstage.rake +16 -0
  76. data/tasks/registration.rake +10 -0
  77. data/tasks/sfcb.rake +3 -0
  78. data/tasks/test.rake +10 -0
  79. data/test/env.rb +23 -0
  80. data/test/helper.rb +23 -0
  81. data/test/mkreg.rb +32 -0
  82. data/test/mof/RCP_ClassMethod.rb +15 -0
  83. data/test/mof/RCP_ComplexMethod.rb +16 -0
  84. data/test/mof/RCP_SimpleMethod.rb +15 -0
  85. data/test/registration.rb +37 -0
  86. data/test/sfcb.rb +94 -0
  87. data/test/test_lmi_embedded.rb +64 -0
  88. data/test/test_rcp_array_data_types.rb +140 -0
  89. data/test/test_rcp_class_method.rb +31 -0
  90. data/test/test_rcp_complex_method.rb +68 -0
  91. data/test/test_rcp_simple_data_types.rb +66 -0
  92. data/test/test_rcp_simple_method.rb +47 -0
  93. data/valgrind +8 -0
  94. metadata +288 -0
@@ -0,0 +1,721 @@
1
+ #
2
+ # provider.rb
3
+ #
4
+
5
+ class String
6
+ #
7
+ # Convert from CamelCase to under_score
8
+ #
9
+ def decamelize
10
+ self.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
11
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
12
+ tr("-", "_").
13
+ downcase
14
+ end
15
+ end
16
+
17
+ require 'cim'
18
+
19
+ module CIM
20
+ class ReferenceType < Type
21
+ def to_cmpi
22
+ "Cmpi::ref"
23
+ end
24
+ end
25
+ class Type
26
+ def to_cmpi
27
+ t = type
28
+ a = ""
29
+ if array?
30
+ a = "A"
31
+ end
32
+ "Cmpi::#{t}#{a}"
33
+ end
34
+ end
35
+ class ClassFeature
36
+ def method_missing name
37
+ qualifiers[name]
38
+ end
39
+ end
40
+ class Qualifier
41
+ def method_missing name, *args
42
+ if name == :"[]"
43
+ value[*args]
44
+ else
45
+ super name, *args
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+
52
+ module Genprovider
53
+ class Provider
54
+ #
55
+ # iterate features
56
+ # **internal**
57
+ # predicate: feature predicate symbol, like :property?
58
+ # filter: :keys # keys only
59
+ # :nokeys # non-keys only
60
+ # :all # all
61
+ #
62
+ # yields { |feature, klass| } if block_given?
63
+ # returns Array of [feature,klass] pairs else
64
+ #
65
+ def features predicate, filter
66
+ result = nil
67
+ #
68
+ # We start to iterate features from the child class and
69
+ # climb up the parent chain
70
+ # overrides = { name => features }
71
+ # collects information about overridden features along
72
+ # the parent chain
73
+ overrides = {}
74
+
75
+ # climb up parent chain
76
+ klass = @klass
77
+ while klass
78
+ klass.features.each do |feature|
79
+ next unless feature.send(predicate)
80
+
81
+ # overriden in child class ?
82
+ f_override = overrides[feature.name]
83
+ if f_override # Y: f_override = overriding feature
84
+ # copy qualifiers from overridden to overriding feature
85
+ feature.qualifiers.each do |q|
86
+ unless f_override.qualifiers[q.name] # non-overridden qualifier
87
+ f_override.qualifiers << q
88
+ end
89
+ end
90
+ next # skip this feature
91
+ end
92
+
93
+ # does this feature override a parent feature ?
94
+ overrides[feature.name] = feature if feature.override
95
+
96
+ if feature.key?
97
+ next if filter == :nokeys
98
+ else
99
+ next if filter == :keys
100
+ end
101
+ if block_given?
102
+ yield feature, klass
103
+ else
104
+ result ||= Array.new
105
+ result << [feature,klass]
106
+ end
107
+ end
108
+ klass = klass.parent
109
+ end
110
+ result
111
+ end
112
+
113
+ # iterate properties
114
+ # filter: :keys # keys only
115
+ # :nokeys # non-keys only
116
+ # :all # all
117
+ #
118
+ # accepts optional block
119
+ #
120
+ def properties filter, &block
121
+ features :property?, filter, &block
122
+ end
123
+
124
+ # iterate methods
125
+ #
126
+ # accepts optional block
127
+ #
128
+ def methods &block
129
+ features :method?, :all, &block
130
+ end
131
+
132
+ LOG = "@trace_file.puts" # "@log.info"
133
+
134
+ #
135
+ # Find bounds for property values
136
+ #
137
+ # Usage:
138
+ # bounds property, :MaxLen, :Max, :Min
139
+ #
140
+ def bounds property, *args
141
+ s = ""
142
+ args.each do |n|
143
+ v = property.send(n)
144
+ s << "#{n} #{v} " if v
145
+ end
146
+ s
147
+ end
148
+
149
+ #
150
+ # Return reasonable default for type
151
+ #
152
+ def default_for_type type
153
+ if type.array? then "[]"
154
+ elsif type == :boolean then "false"
155
+ else "nil"
156
+ end
157
+ end
158
+
159
+ #
160
+ # generate line to set a property
161
+ # i.e. result.Property = nil # property_type + valuemap
162
+ #
163
+ def property_setter_line property, klass, result_name = "result"
164
+ valuemap = property.ValueMap
165
+ values = property.Values
166
+ type = property.type
167
+ if valuemap
168
+ firstval = values ? values[0] : valuemap[0]
169
+ if firstval.to_s =~ /\s/
170
+ firstval = "send(#{firstval.to_sym.inspect})"
171
+ end
172
+ default = "#{property.name}.#{firstval}"
173
+ default = "[#{default}]" if type.array?
174
+ else
175
+ default = default_for_type type
176
+ end
177
+ bounds = bounds property, :MaxLen, :Max, :Min
178
+ "#{result_name}.#{property.name} = #{default} # #{type} #{bounds} (-> #{klass.name})"
179
+ end
180
+ #
181
+ # Class#each
182
+ #
183
+ def mkeach
184
+ @out.puts "private"
185
+ @out.comment
186
+ @out.comment "Iterator for names and instances"
187
+ @out.comment " yields references matching reference and properties"
188
+ @out.comment
189
+ @out.def "each", "context", "reference", "properties = nil", "want_instance = false"
190
+ @out.puts "result = Cmpi::CMPIObjectPath.new reference.namespace, #{@klass.name.inspect}"
191
+ @out.puts("if want_instance").inc
192
+ @out.puts "result = Cmpi::CMPIInstance.new result"
193
+ @out.puts "result.set_property_filter(properties) if properties"
194
+ @out.end
195
+ @out.puts
196
+ @out.comment "Set key properties"
197
+ @out.puts
198
+ properties :keys do |prop, klass|
199
+ @out.puts(property_setter_line prop, klass)
200
+ end
201
+ @out.puts("unless want_instance").inc
202
+ @out.puts "yield result"
203
+ @out.puts "return"
204
+ @out.end
205
+ @out.puts
206
+ @out.comment "Instance: Set non-key properties"
207
+ @out.puts
208
+ properties :nokeys do |prop, klass|
209
+ deprecated = prop.deprecated
210
+ required = prop.required
211
+ if required
212
+ @out.comment "Required !"
213
+ @out.puts "#{property_setter_line prop, klass}"
214
+ else
215
+ @out.comment "Deprecated !" if deprecated
216
+ # using @out.comment would break the line at col 72
217
+ @out.puts "# #{property_setter_line prop, klass}"
218
+ end
219
+ end
220
+ @out.puts "yield result"
221
+ @out.end
222
+ @out.puts "public"
223
+ end
224
+ #
225
+ # Generate Class#initialize
226
+ #
227
+ def mknew
228
+ @out.comment
229
+ @out.comment "Provider initialization"
230
+ @out.comment
231
+ @out.def "initialize", "name", "broker", "context"
232
+ @out.puts "@trace_file = STDERR"
233
+ @out.puts "super broker"
234
+ @out.end
235
+ end
236
+
237
+ #
238
+ # Generate create_instance
239
+ #
240
+ def mkcreate
241
+ @out.def "create_instance", "context", "result", "reference", "newinst"
242
+ @out.puts "#{LOG} \"#{@name}.create_instance ref \#{reference}, newinst \#{newinst.inspect}\""
243
+ @out.comment "Create instance according to reference and newinst"
244
+ @out.puts "result.return_objectpath reference"
245
+ @out.puts "result.done"
246
+ @out.puts "true"
247
+ @out.end
248
+ end
249
+
250
+ #
251
+ # Generate enum_instance_names
252
+ #
253
+ def mkenum_instance_names
254
+ @out.def "enum_instance_names", "context", "result", "reference"
255
+ @out.puts "#{LOG} \"#{@name}.enum_instance_names ref \#{reference}\""
256
+ @out.puts("each(context, reference) do |ref|").inc
257
+ @out.puts "#{LOG} \"ref \#{ref}\""
258
+ @out.puts "result.return_objectpath ref"
259
+ @out.end
260
+ @out.puts "result.done"
261
+ @out.puts "true"
262
+ @out.end
263
+ end
264
+
265
+ #
266
+ # Generate enum_instances
267
+ #
268
+ def mkenum_instances
269
+ @out.def "enum_instances", "context", "result", "reference", "properties"
270
+ @out.puts "#{LOG} \"#{@name}.enum_instances ref \#{reference}, props \#{properties.inspect}\""
271
+ @out.puts("each(context, reference, properties, true) do |instance|").inc
272
+ @out.puts "#{LOG} \"instance \#{instance}\""
273
+ @out.puts "result.return_instance instance"
274
+ @out.end
275
+ @out.puts "result.done"
276
+ @out.puts "true"
277
+ @out.end
278
+ end
279
+
280
+ #
281
+ # Generate get_instance
282
+ #
283
+ def mkget_instance
284
+ @out.def "get_instance", "context", "result", "reference", "properties"
285
+ @out.puts "#{LOG} \"#{@name}.get_instance ref \#{reference}, props \#{properties.inspect}\""
286
+ @out.puts("each(context, reference, properties, true) do |instance|").inc
287
+ @out.puts "#{LOG} \"instance \#{instance}\""
288
+ @out.puts "result.return_instance instance"
289
+ @out.puts "break # only return first instance"
290
+ @out.end
291
+ @out.puts "result.done"
292
+ @out.puts "true"
293
+ @out.end
294
+ end
295
+
296
+ #
297
+ # Generate set_instance
298
+ #
299
+ def mkset_instance
300
+ @out.def "set_instance", "context", "result", "reference", "newinst", "properties"
301
+ @out.puts "#{LOG} \"#{@name}.set_instance ref \#{reference}, newinst \#{newinst.inspect}, props \#{properties.inspect}\""
302
+ @out.puts("properties.each do |prop|").inc
303
+ @out.puts "newinst.send \"\#{prop.name}=\".to_sym, FIXME"
304
+ @out.end
305
+ @out.puts "result.return_instance newinst"
306
+ @out.puts "result.done"
307
+ @out.puts "true"
308
+ @out.end
309
+ end
310
+
311
+ #
312
+ # Generate delete_instance
313
+ #
314
+ def mkdelete_instance
315
+ @out.def "delete_instance", "context", "result", "reference"
316
+ @out.puts "#{LOG} \"#{@name}.delete_instance ref \#{reference}\""
317
+ @out.puts "result.done"
318
+ @out.puts "true"
319
+ @out.end
320
+ end
321
+
322
+ #
323
+ # Generate exec_query
324
+ #
325
+ def mkquery
326
+ @out.comment "query : String"
327
+ @out.comment "lang : String"
328
+ @out.def "exec_query", "context", "result", "reference", "query", "lang"
329
+ @out.puts "#{LOG} \"#{@name}.exec_query ref \#{reference}, query \#{query}, lang \#{lang}\""
330
+ @out.printf "keys = ["
331
+ first = true
332
+ properties :keys do |property, klass|
333
+ @out.write ", " unless first
334
+ first = false
335
+ @out.write "\"#{property.name}\""
336
+ end
337
+ @out.puts "]"
338
+ @out.puts "expr = CMPISelectExp.new query, lang, keys"
339
+ @out.puts("each(context, reference, expr.filter, true) do |instance|").inc
340
+ @out.puts( "if expr.match(instance)").inc
341
+ @out.puts "result.return_instance instance"
342
+ @out.end
343
+ @out.end
344
+ @out.puts "result.done"
345
+ @out.puts "true"
346
+ @out.end
347
+ end
348
+
349
+ #
350
+ # Generate cleanup
351
+ #
352
+ def mkcleanup
353
+ @out.def "cleanup", "context", "terminating"
354
+ @out.puts "#{LOG} \"#{@name}.cleanup terminating? \#{terminating}\""
355
+ @out.puts "true"
356
+ @out.end
357
+ end
358
+
359
+ def mktypemap
360
+ @out.def("self.typemap")
361
+ @out.puts("{").inc
362
+ properties :all do |property, klass|
363
+ t = property.type
364
+ s = t.to_cmpi
365
+ if t == CIM::ReferenceType
366
+ # use t.name to stay Ruby-compatible. t.to_s would print MOF syntax
367
+ @out.comment t.to_s
368
+ elsif t == :string # check for Embedded{Instance,Object}
369
+ if property.embeddedinstance?
370
+ s = "Cmpi::embedded_instance"
371
+ elsif property.embeddedobject?
372
+ s = "Cmpi::embedded_object"
373
+ end
374
+ elsif t == :stringA # check for Embedded{Instance,Object}
375
+ if property.embeddedinstance?
376
+ s = "Cmpi::embedded_instanceA"
377
+ elsif property.embeddedobject?
378
+ s = "Cmpi::embedded_objectA"
379
+ end
380
+ end
381
+ @out.puts "#{property.name.inspect} => #{s},"
382
+ end
383
+ @out.dec.puts "}"
384
+ @out.end
385
+ end
386
+
387
+ def make_valuemap_header
388
+ return if @valuemap_headers_done
389
+ @out.comment
390
+ @out.comment "----------------- valuemaps following, don't touch -----------------"
391
+ @out.comment
392
+ @valuemap_headers_done = true
393
+ end
394
+ #
395
+ # make_valuemap
396
+ # make one ValueMap class
397
+ #
398
+ def make_valuemap property
399
+ t = property.type
400
+ # get the Values and ValueMap qualifiers
401
+ valuemap = property.ValueMap
402
+ return unless valuemap
403
+ make_valuemap_header
404
+ values = property.Values
405
+ @out.puts
406
+ @out.puts("class #{property.name} < Cmpi::ValueMap").inc
407
+ @out.def "self.map"
408
+ @out.puts("{").inc
409
+ # get to the array
410
+ valuemap = valuemap
411
+ # values might be nil, then only ValueMap given
412
+ if values
413
+ values = values
414
+ elsif !t.matches?(String)
415
+ raise "ValueMap missing Values for property #{property.name} with non-string type #{t}"
416
+ end
417
+ loop do
418
+ val = values.shift if values
419
+ map = valuemap.shift
420
+ if val.nil? && values
421
+ # have values but its empty
422
+ break unless map # ok, both nil
423
+ raise "#{property.name}: Values empty, ValueMap #{map}"
424
+ end
425
+ unless map
426
+ break unless val # ok, both nil
427
+ raise "#{property.name}: Values #{val}, ValueMap empty"
428
+ end
429
+ if val
430
+ if map =~ /\.\./
431
+ @out.comment "#{val.inspect} => #{map},"
432
+ else
433
+ @out.puts "#{val.inspect} => #{map},"
434
+ end
435
+ else
436
+ @out.puts "#{map.inspect} => #{map.to_sym.inspect},"
437
+ end
438
+ end
439
+ @out.dec.puts "}"
440
+ @out.end
441
+ @out.end
442
+ end
443
+
444
+ #
445
+ # Generate valuemap classes
446
+ #
447
+ def mkvaluemaps
448
+ properties :all do |property, klass|
449
+ make_valuemap property
450
+ end
451
+ methods do |method, klass|
452
+ make_valuemap method
453
+ end
454
+ end
455
+
456
+ # base instance callbacks
457
+ # use by association and instance providers
458
+ def mkbaseinstance
459
+ mkeach
460
+ @out.puts
461
+ mkenum_instance_names
462
+ @out.puts
463
+ mkenum_instances
464
+ @out.puts
465
+ mkget_instance
466
+ @out.puts
467
+ end
468
+
469
+ def mkinstance
470
+ mkbaseinstance
471
+ mkcreate
472
+ @out.puts
473
+ mkset_instance
474
+ @out.puts
475
+ mkdelete_instance
476
+ @out.puts
477
+ mkquery
478
+ end
479
+
480
+ def mkargs args, name
481
+ s = ""
482
+ args.each do |arg|
483
+ s << ", " unless s.empty?
484
+ s << arg.name.inspect
485
+ s << ", #{arg.type.to_cmpi}"
486
+ end
487
+ s
488
+ end
489
+
490
+ def explain_args args, text
491
+ @out.comment "#{text} args"
492
+ if args.empty?
493
+ @out.comment " - none -"
494
+ end
495
+ args.each do |arg|
496
+ @out.comment "#{arg.name} : #{arg.type}", 1
497
+ d = arg.description
498
+ @out.comment("#{d}", 3) if d
499
+ valuemap = arg.valuemap
500
+ # values might be nil, then only ValueMap given
501
+ if valuemap
502
+ @out.comment "Value can be one of", 3
503
+ valuemap = valuemap
504
+ values = arg.values
505
+ if values
506
+ values = values
507
+ loop do
508
+ s = values.shift
509
+ v = valuemap.shift
510
+ break unless v && s
511
+ @out.comment "#{s}: #{v}", 5
512
+ end
513
+ else
514
+ valuemap.each do |v|
515
+ @out.comment v, 5
516
+ end
517
+ end
518
+ end
519
+ end
520
+ @out.comment
521
+ end
522
+
523
+ def mkmethods
524
+ @out.comment "Methods"
525
+ @out.puts
526
+ methods do |method, klass|
527
+ next if method.deprecated
528
+ @out.comment "#{klass.name}: #{method.type} #{method.name}(...)"
529
+ @out.comment
530
+ input = []
531
+ output = []
532
+ method.parameters.each do |p|
533
+ input << p if p.in?
534
+ output << p if p.out?
535
+ STDERR.puts "#{p.name} is IN and OUT" if p.in? && p.out?
536
+ STDERR.puts "#{p.name} is neither IN nor OUT" unless p.in? || p.out?
537
+ end
538
+ name = method.name
539
+ decam = name.decamelize
540
+ # type and argument information
541
+ # must be array since order here is order of args passed to function
542
+ # first element is list of input args (alternating name and type)
543
+ # second is list of output args (starting with return type, then name and type of additional out args)
544
+ # -> used by cmpi_bindings !
545
+ @out.comment "type information for #{name}(...)"
546
+ @out.puts "def #{decam}_args; [[#{mkargs(input, decam)}],[#{method.type.to_cmpi}, #{mkargs(output, decam)}]] end"
547
+ @out.comment
548
+ d = method.description.value rescue nil
549
+ if d
550
+ @out.comment "#{d}"
551
+ @out.comment
552
+ end
553
+ v = method.values
554
+ default_return_value = default_for_type method.type
555
+ if v
556
+ @out.comment "See class #{method.name} for return values"
557
+ @out.comment
558
+ firstval = v[0]
559
+ if firstval.to_s =~ /\s/
560
+ firstval = "send(#{firstval.to_sym.inspect})"
561
+ end
562
+ default_return_value = "#{name}.#{firstval}"
563
+ end
564
+ explain_args input, "Input"
565
+ explain_args output, "Additional output"
566
+ args = ["#{decam}", "context", "reference"]
567
+ method.parameters.each do |arg|
568
+ args << arg.name.decamelize
569
+ end
570
+ @out.def *args
571
+ args.shift
572
+ log = ""
573
+ args.each do |arg|
574
+ log << ", " unless log.empty?
575
+ log << "\#{#{arg}}"
576
+ end
577
+ @out.puts "#{LOG} \"#{decam} #{log}\""
578
+
579
+ # Empty arrays are not transferred by sfcc/cimxml, end up as nil
580
+ input.each do |arg|
581
+ next unless arg.type.array?
582
+ @out.puts "#{arg.name.decamelize} ||= []"
583
+ end
584
+
585
+ args = [ "method_return_value" ]
586
+ @out.puts "method_return_value = #{default_return_value} # #{method.type}"
587
+ if output.size > 0
588
+ @out.puts
589
+ @out.comment "Output arguments"
590
+ output.each do |arg|
591
+ name = arg.name.decamelize
592
+ @out.puts "#{name} = nil # #{arg.type}"
593
+ args << name
594
+ end
595
+ end
596
+ @out.puts
597
+ @out.comment " function body goes here"
598
+ @out.puts
599
+ if args.size > 1
600
+ @out.puts "return [#{args.join(', ')}]"
601
+ else
602
+ @out.puts "return #{args[0]}"
603
+ end
604
+ @out.end
605
+ @out.puts
606
+ end
607
+
608
+ # @out.puts
609
+ # @out.def "invoke_method", "context", "result", "reference", "method", "argsin", "argsout"
610
+ # @out.puts "#{LOG} \"invoke_method \#{context}, \#{result}, \#{reference}, \#{method}, \#{argsin}, \#{argsout}\""
611
+ # @out.end
612
+ end
613
+
614
+ def mkassociations
615
+ @out.comment "Associations"
616
+ @out.def "associator_names", "context", "result", "reference", "assoc_class", "result_class", "role", "result_role"
617
+ @out.puts "#{LOG} \"#{@name}.associator_names \#{context}, \#{result}, \#{reference}, \#{assoc_class}, \#{result_class}, \#{role}, \#{result_role}\""
618
+ @out.end
619
+ @out.puts
620
+ @out.def "associators", "context", "result", "reference", "assoc_class", "result_class", "role", "result_role", "properties"
621
+ @out.puts "#{LOG} \"#{@name}.associators \#{context}, \#{result}, \#{reference}, \#{assoc_class}, \#{result_class}, \#{role}, \#{result_role}, \#{properties}\""
622
+ @out.end
623
+ @out.puts
624
+ @out.def "reference_names", "context", "result", "reference", "result_class", "role"
625
+ @out.puts "#{LOG} \"#{@name}.reference_names \#{context}, \#{result}, \#{reference}, \#{result_class}, \#{role}\""
626
+ @out.end
627
+ @out.puts
628
+ @out.def "references", "context", "result", "reference", "result_class", "role", "properties"
629
+ @out.puts "#{LOG} \"#{@name}.references \#{context}, \#{result}, \#{reference}, \#{result_class}, \#{role}, \#{properties}\""
630
+ @out.end
631
+
632
+ end
633
+
634
+ def mkindications
635
+ @out.comment "Indications"
636
+ end
637
+
638
+ def providertypes
639
+ mask = Genprovider.classmask @klass
640
+ res = []
641
+ res << "MethodProvider" if (mask & METHOD_MASK) != 0
642
+ res << "AssociationProvider" if (mask & ASSOCIATION_MASK) != 0
643
+ res << "IndicationProvider" if (mask & INDICATION_MASK) != 0
644
+ res << "InstanceProvider" if (mask & INSTANCE_MASK) != 0
645
+
646
+ [res, mask]
647
+ end
648
+
649
+ #
650
+ # generate provider code for class 'c'
651
+ #
652
+ # returns providername
653
+ #
654
+
655
+ def initialize c, name, out
656
+ @klass = c
657
+ @out = out
658
+
659
+ if name[0,1] == name[0,1].downcase
660
+ raise "Provider name (#{name}) must start with upper case"
661
+ end
662
+ @name = name
663
+
664
+ #
665
+ # Header: class name, provider name (Class qualifier 'provider')
666
+ #
667
+
668
+ @out.comment
669
+ @out.comment "Provider #{name} for class #{@klass.name}:#{@klass.class}"
670
+ @out.comment
671
+
672
+ @out.puts("require 'syslog'").puts
673
+ @out.puts("require 'cmpi/provider'").puts
674
+ @out.puts("module Cmpi").inc
675
+
676
+ Genprovider::Class.mkdescription @out, @klass
677
+ if @klass.parent
678
+ Genprovider::Class.mkdescription @out, @klass.parent
679
+ end
680
+ p,mask = providertypes
681
+
682
+ @out.puts("class #{name} < #{p.shift}").inc
683
+
684
+ @out.puts
685
+ p.each do |t|
686
+ @out.puts "include #{t}IF"
687
+ end
688
+ mknew
689
+ @out.puts
690
+ mkcleanup
691
+ @out.puts
692
+ mktypemap
693
+ @out.puts
694
+ if (mask & METHOD_MASK) != 0
695
+ STDERR.puts " Generating Method provider"
696
+ mkmethods
697
+ @out.puts
698
+ end
699
+ if (mask & ASSOCIATION_MASK) != 0
700
+ STDERR.puts " Generating Association provider"
701
+ mkbaseinstance
702
+ mkassociations
703
+ end
704
+ if (mask & INDICATION_MASK) != 0
705
+ STDERR.puts " Generating Indication provider"
706
+ mkindications
707
+ @out.puts
708
+ end
709
+ if (mask & INSTANCE_MASK) != 0
710
+ STDERR.puts " Generating Instance provider"
711
+ mkinstance
712
+ @out.puts
713
+ end
714
+
715
+ mkvaluemaps
716
+ @out.end # class
717
+ @out.end # module
718
+ end
719
+ end
720
+ end
721
+