genprovider 0.2.0

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