class Genprovider::Provider
Constants
- LOG
Public Class Methods
new(c, name, out)
click to toggle source
generate provider code for class ācā
returns providername
# File lib/genprovider/provider.rb, line 668 def initialize c, name, out @klass = c @out = out if name[0,1] == name[0,1].downcase raise "Provider name (#{name}) must start with upper case" end @name = name # # Header: class name, provider name (Class qualifier 'provider') # @out.comment @out.comment "Provider #{name} for class #{@klass.name}:#{@klass.class}" @out.comment @out.puts("require 'syslog'").puts @out.puts("require 'cmpi/provider'").puts @out.puts("module Cmpi").inc Genprovider::Class.mkdescription @out, @klass if @klass.parent Genprovider::Class.mkdescription @out, @klass.parent end p,mask = providertypes @out.puts("class #{name} < #{p.shift}").inc @out.puts p.each do |t| @out.puts "include #{t}IF" end mknew @out.puts mkcleanup @out.puts mktypemap @out.puts if (mask & METHOD_MASK) != 0 STDERR.puts " Generating Method provider" mkmethods @out.puts end if (mask & ASSOCIATION_MASK) != 0 STDERR.puts " Generating Association provider" mkbaseinstance mkassociations end if (mask & INDICATION_MASK) != 0 STDERR.puts " Generating Indication provider" mkindications @out.puts end if (mask & INSTANCE_MASK) != 0 STDERR.puts " Generating Instance provider" mkinstance @out.puts end mkvaluemaps @out.end # class @out.end # module end
Public Instance Methods
bounds(property, *args)
click to toggle source
Find bounds for property values
Usage: bounds property, :MaxLen, :Max, :Min
# File lib/genprovider/provider.rb, line 140 def bounds property, *args s = "" args.each do |n| v = property.send(n) s << "#{n} #{v} " if v end s end
default_for_type(type)
click to toggle source
Return reasonable default for type
# File lib/genprovider/provider.rb, line 152 def default_for_type type if type.array? then "[]" elsif type == :boolean then "false" else "nil" end end
explain_args(args, text)
click to toggle source
# File lib/genprovider/provider.rb, line 490 def explain_args args, text @out.comment "#{text} args" if args.empty? @out.comment " - none -" end args.each do |arg| @out.comment "#{arg.name} : #{arg.type}", 1 d = arg.description @out.comment("#{d}", 3) if d valuemap = arg.valuemap # values might be nil, then only ValueMap given if valuemap @out.comment "Value can be one of", 3 valuemap = valuemap values = arg.values if values values = values loop do s = values.shift v = valuemap.shift break unless v && s @out.comment "#{s}: #{v}", 5 end else valuemap.each do |v| @out.comment v, 5 end end end end @out.comment end
features(predicate, filter) { |feature, klass| ... }
click to toggle source
iterate features internal
predicate: feature predicate symbol, like :property? filter: :keys # keys only :nokeys # non-keys only :all # all
yields { |feature, klass| } if block_given? returns Array of [feature,klass] pairs else
# File lib/genprovider/provider.rb, line 65 def features predicate, filter result = nil # # We start to iterate features from the child class and # climb up the parent chain # overrides = { name => features } # collects information about overridden features along # the parent chain overrides = {} # climb up parent chain klass = @klass while klass klass.features.each do |feature| next unless feature.send(predicate) # overriden in child class ? f_override = overrides[feature.name] if f_override # Y: f_override = overriding feature # copy qualifiers from overridden to overriding feature feature.qualifiers.each do |q| unless f_override.qualifiers[q.name] # non-overridden qualifier f_override.qualifiers << q end end next # skip this feature end # does this feature override a parent feature ? overrides[feature.name] = feature if feature.override if feature.key? next if filter == :nokeys else next if filter == :keys end if block_given? yield feature, klass else result ||= Array.new result << [feature,klass] end end klass = klass.parent end result end
make_valuemap(property)
click to toggle source
make_valuemap
make one ValueMap class
# File lib/genprovider/provider.rb, line 398 def make_valuemap property t = property.type # get the Values and ValueMap qualifiers valuemap = property.ValueMap return unless valuemap make_valuemap_header values = property.Values @out.puts @out.puts("class #{property.name} < Cmpi::ValueMap").inc @out.def "self.map" @out.puts("{").inc # get to the array valuemap = valuemap # values might be nil, then only ValueMap given if values values = values elsif !t.matches?(String) raise "ValueMap missing Values for property #{property.name} with non-string type #{t}" end loop do val = values.shift if values map = valuemap.shift if val.nil? && values # have values but its empty break unless map # ok, both nil raise "#{property.name}: Values empty, ValueMap #{map}" end unless map break unless val # ok, both nil raise "#{property.name}: Values #{val}, ValueMap empty" end if val if map =~ /\.\./ @out.comment "#{val.inspect} => #{map}," else @out.puts "#{val.inspect} => #{map}," end else @out.puts "#{map.inspect} => #{map.to_sym.inspect}," end end @out.dec.puts "}" @out.end @out.end end
make_valuemap_header()
click to toggle source
# File lib/genprovider/provider.rb, line 387 def make_valuemap_header return if @valuemap_headers_done @out.comment @out.comment "----------------- valuemaps following, don't touch -----------------" @out.comment @valuemap_headers_done = true end
methods(&block)
click to toggle source
iterate methods
accepts optional block
# File lib/genprovider/provider.rb, line 128 def methods &block features :method?, :all, &block end
mkargs(args, name)
click to toggle source
# File lib/genprovider/provider.rb, line 480 def mkargs args, name s = "" args.each do |arg| s << ", " unless s.empty? s << arg.name.inspect s << ", #{arg.type.to_cmpi}" end s end
mkassociations()
click to toggle source
# File lib/genprovider/provider.rb, line 617 def mkassociations @out.comment "Associations" @out.def "associator_names", "context", "result", "reference", "assoc_class", "result_class", "role", "result_role" @out.puts "#{LOG} \"#{@name}.associator_names \#{context}, \#{result}, \#{reference}, \#{assoc_class}, \#{result_class}, \#{role}, \#{result_role}\"" @out.end @out.puts @out.def "associators", "context", "result", "reference", "assoc_class", "result_class", "role", "result_role", "properties" @out.puts "#{LOG} \"#{@name}.associators \#{context}, \#{result}, \#{reference}, \#{assoc_class}, \#{result_class}, \#{role}, \#{result_role}, \#{properties}\"" @out.end @out.puts @out.def "reference_names", "context", "result", "reference", "result_class", "role" @out.puts "#{LOG} \"#{@name}.reference_names \#{context}, \#{result}, \#{reference}, \#{result_class}, \#{role}\"" @out.puts("each(context, reference) do |ref|").inc @out.puts "result.return_objectpath ref" @out.end @out.puts "result.done" @out.puts "true" @out.end @out.puts @out.def "references", "context", "result", "reference", "result_class", "role", "properties" @out.puts "#{LOG} \"#{@name}.references \#{context}, \#{result}, \#{reference}, \#{result_class}, \#{role}, \#{properties}\"" @out.puts("each(context, reference, properties, true) do |instance|").inc @out.puts "result.return_instance instance" @out.end @out.puts "result.done" @out.puts "true" @out.end end
mkbaseinstance()
click to toggle source
base instance callbacks use by association and instance providers
# File lib/genprovider/provider.rb, line 458 def mkbaseinstance mkeach @out.puts mkenum_instance_names @out.puts mkenum_instances @out.puts mkget_instance @out.puts end
mkcleanup()
click to toggle source
Generate cleanup
# File lib/genprovider/provider.rb, line 352 def mkcleanup @out.def "cleanup", "context", "terminating" @out.puts "#{LOG} \"#{@name}.cleanup terminating? \#{terminating}\"" @out.puts "true" @out.end end
mkcreate()
click to toggle source
Generate create_instance
# File lib/genprovider/provider.rb, line 240 def mkcreate @out.def "create_instance", "context", "result", "reference", "newinst" @out.puts "#{LOG} \"#{@name}.create_instance ref \#{reference}, newinst \#{newinst.inspect}\"" @out.comment "Create instance according to reference and newinst" @out.puts "result.return_objectpath reference" @out.puts "result.done" @out.puts "true" @out.end end
mkdelete_instance()
click to toggle source
Generate delete_instance
# File lib/genprovider/provider.rb, line 314 def mkdelete_instance @out.def "delete_instance", "context", "result", "reference" @out.puts "#{LOG} \"#{@name}.delete_instance ref \#{reference}\"" @out.puts "result.done" @out.puts "true" @out.end end
mkeach()
click to toggle source
Class#each
# File lib/genprovider/provider.rb, line 183 def mkeach @out.puts "private" @out.comment @out.comment "Iterator for names and instances" @out.comment " yields references matching reference and properties" @out.comment @out.def "each", "context", "reference", "properties = nil", "want_instance = false" @out.puts "result = Cmpi::CMPIObjectPath.new reference.namespace, #{@klass.name.inspect}" @out.puts("if want_instance").inc @out.puts "result = Cmpi::CMPIInstance.new result" @out.puts "result.set_property_filter(properties) if properties" @out.end @out.puts @out.comment "Set key properties" @out.puts properties :keys do |prop, klass| @out.puts(property_setter_line prop, klass) end @out.puts("unless want_instance").inc @out.puts "yield result" @out.puts "return" @out.end @out.puts @out.comment "Instance: Set non-key properties" @out.puts properties :nokeys do |prop, klass| deprecated = prop.deprecated required = prop.required if required @out.comment "Required !" @out.puts "#{property_setter_line prop, klass}" else @out.comment "Deprecated !" if deprecated # using @out.comment would break the line at col 72 @out.puts "# #{property_setter_line prop, klass}" end end @out.puts "yield result" @out.end @out.puts "public" end
mkenum_instance_names()
click to toggle source
Generate enum_instance_names
# File lib/genprovider/provider.rb, line 253 def mkenum_instance_names @out.def "enum_instance_names", "context", "result", "reference" @out.puts "#{LOG} \"#{@name}.enum_instance_names ref \#{reference}\"" @out.puts("each(context, reference) do |ref|").inc @out.puts "#{LOG} \"ref \#{ref}\"" @out.puts "result.return_objectpath ref" @out.end @out.puts "result.done" @out.puts "true" @out.end end
mkenum_instances()
click to toggle source
Generate enum_instances
# File lib/genprovider/provider.rb, line 268 def mkenum_instances @out.def "enum_instances", "context", "result", "reference", "properties" @out.puts "#{LOG} \"#{@name}.enum_instances ref \#{reference}, props \#{properties.inspect}\"" @out.puts("each(context, reference, properties, true) do |instance|").inc @out.puts "#{LOG} \"instance \#{instance}\"" @out.puts "result.return_instance instance" @out.end @out.puts "result.done" @out.puts "true" @out.end end
mkget_instance()
click to toggle source
Generate get_instance
# File lib/genprovider/provider.rb, line 283 def mkget_instance @out.def "get_instance", "context", "result", "reference", "properties" @out.puts "#{LOG} \"#{@name}.get_instance ref \#{reference}, props \#{properties.inspect}\"" @out.puts("each(context, reference, properties, true) do |instance|").inc @out.puts "#{LOG} \"instance \#{instance}\"" @out.puts "result.return_instance instance" @out.puts "break # only return first instance" @out.end @out.puts "result.done" @out.puts "true" @out.end end
mkindications()
click to toggle source
# File lib/genprovider/provider.rb, line 647 def mkindications @out.comment "Indications" end
mkinstance()
click to toggle source
# File lib/genprovider/provider.rb, line 469 def mkinstance mkbaseinstance mkcreate @out.puts mkset_instance @out.puts mkdelete_instance @out.puts mkquery end
mkmethods()
click to toggle source
# File lib/genprovider/provider.rb, line 523 def mkmethods @out.comment "Methods" @out.puts methods do |method, klass| next if method.deprecated @out.comment "#{klass.name}: #{method.type} #{method.name}(...)" @out.comment input = [] output = [] method.parameters.each do |p| input << p if p.in? output << p if p.out? STDERR.puts "#{p.name} is IN and OUT" if p.in? && p.out? STDERR.puts "#{p.name} is neither IN nor OUT" unless p.in? || p.out? end name = method.name decam = name.decamelize # type and argument information # must be array since order here is order of args passed to function # first element is list of input args (alternating name and type) # second is list of output args (starting with return type, then name and type of additional out args) # -> used by cmpi_bindings ! @out.comment "type information for #{name}(...)" @out.comment "Array of 2 arrys. First array is input arguments as [<in_name1>, <in_type1>, ...]" @out.comment " Second array is [<return type>, <out_name1>, <out_type1>, <out_name2>, <out_type2>, ...]" @out.puts "def #{decam}_args; [[#{mkargs(input, decam)}],[#{method.type.to_cmpi}, #{mkargs(output, decam)}]] end" @out.comment d = method.description.value rescue nil if d @out.comment "#{d}" @out.comment end v = method.values default_return_value = default_for_type method.type if v @out.comment "See class #{method.name} for return values" @out.comment firstval = v[0] if firstval.to_s =~ /\s/ firstval = "send(#{firstval.to_sym.inspect})" end default_return_value = "#{name}.#{firstval}" end explain_args input, "Input" explain_args output, "Additional output" args = ["#{decam}", "context", "reference"] input.each do |arg| args << arg.name.decamelize end @out.def *args args.shift log = "" args.each do |arg| log << ", " unless log.empty? log << "\#{#{arg}}" end @out.puts "#{LOG} \"#{decam} #{log}\"" # Empty arrays are not transferred by sfcc/cimxml, end up as nil input.each do |arg| next unless arg.type.array? @out.puts "#{arg.name.decamelize} ||= []" end args = [ "method_return_value" ] @out.puts "method_return_value = #{default_return_value} # #{method.type}" if output.size > 0 @out.puts @out.comment "Output arguments" output.each do |arg| name = arg.name.decamelize @out.puts "#{name} = nil # #{arg.type}" args << name end end @out.puts @out.comment " function body goes here" @out.puts if args.size > 1 @out.puts "return [#{args.join(', ')}]" else @out.puts "return #{args[0]}" end @out.end @out.puts end # @out.puts # @out.def "invoke_method", "context", "result", "reference", "method", "argsin", "argsout" # @out.comment "method names and parameter names are case-insensitive !" # @out.puts "#{LOG} \"invoke_method \#{context}, \#{result}, \#{reference}, \#{method}, \#{argsin}, \#{argsout}\"" # @out.end end
mknew()
click to toggle source
Generate Class#initialize
# File lib/genprovider/provider.rb, line 227 def mknew @out.comment @out.comment "Provider initialization" @out.comment @out.def "initialize", "name", "broker", "context" @out.puts "@trace_file = STDERR" @out.puts "super broker" @out.end end
mkquery()
click to toggle source
Generate exec_query
# File lib/genprovider/provider.rb, line 325 def mkquery @out.comment "query : String" @out.comment "lang : String" @out.def "exec_query", "context", "result", "reference", "query", "lang" @out.puts "#{LOG} \"#{@name}.exec_query ref \#{reference}, query \#{query}, lang \#{lang}\"" @out.printf "keys = [" first = true properties :keys do |property, klass| @out.write ", " unless first first = false @out.write "\"#{property.name}\"" end @out.puts "]" @out.puts "expr = CMPISelectExp.new query, lang, keys" @out.puts("each(context, reference, expr.filter, true) do |instance|").inc @out.puts( "if expr.match(instance)").inc @out.puts "result.return_instance instance" @out.end @out.end @out.puts "result.done" @out.puts "true" @out.end end
mkset_instance()
click to toggle source
Generate set_instance
# File lib/genprovider/provider.rb, line 299 def mkset_instance @out.def "set_instance", "context", "result", "reference", "newinst", "properties" @out.puts "#{LOG} \"#{@name}.set_instance ref \#{reference}, newinst \#{newinst.inspect}, props \#{properties.inspect}\"" @out.puts("properties.each do |prop|").inc @out.puts "newinst.send \"\#{prop.name}=\".to_sym, FIXME" @out.end @out.puts "result.return_instance newinst" @out.puts "result.done" @out.puts "true" @out.end end
mktypemap()
click to toggle source
# File lib/genprovider/provider.rb, line 359 def mktypemap @out.def("self.typemap") @out.puts("{").inc properties :all do |property, klass| t = property.type s = t.to_cmpi if t == CIM::ReferenceType # use t.name to stay Ruby-compatible. t.to_s would print MOF syntax @out.comment t.to_s elsif t == :string # check for Embedded{Instance,Object} if property.embeddedinstance? s = "Cmpi::embedded_instance" elsif property.embeddedobject? s = "Cmpi::embedded_object" end elsif t == :stringA # check for Embedded{Instance,Object} if property.embeddedinstance? s = "Cmpi::embedded_instanceA" elsif property.embeddedobject? s = "Cmpi::embedded_objectA" end end @out.puts "#{property.name.inspect} => #{s}," end @out.dec.puts "}" @out.end end
mkvaluemaps()
click to toggle source
Generate valuemap classes
# File lib/genprovider/provider.rb, line 447 def mkvaluemaps properties :all do |property, klass| make_valuemap property end methods do |method, klass| make_valuemap method end end
properties(filter, &block)
click to toggle source
iterate properties
filter: :keys # keys only :nokeys # non-keys only :all # all
accepts optional block
# File lib/genprovider/provider.rb, line 120 def properties filter, &block features :property?, filter, &block end
property_setter_line(property, klass, result_name = "result")
click to toggle source
generate line to set a property i.e. result.Property = nil # property_type + valuemap
# File lib/genprovider/provider.rb, line 163 def property_setter_line property, klass, result_name = "result" valuemap = property.ValueMap values = property.Values type = property.type if valuemap firstval = values ? values[0] : valuemap[0] if firstval.to_s =~ /\s/ firstval = "send(#{firstval.to_sym.inspect})" end default = "#{property.name}.#{firstval}" default = "[#{default}]" if type.array? else default = default_for_type type end bounds = bounds property, :MaxLen, :Max, :Min "#{result_name}.#{property.name} = #{default} # #{type} #{bounds} (-> #{klass.name})" end
providertypes()
click to toggle source
# File lib/genprovider/provider.rb, line 651 def providertypes mask = Genprovider.classmask @klass res = [] res << "MethodProvider" if (mask & METHOD_MASK) != 0 res << "AssociationProvider" if (mask & ASSOCIATION_MASK) != 0 res << "IndicationProvider" if (mask & INDICATION_MASK) != 0 res << "InstanceProvider" if (mask & INSTANCE_MASK) != 0 [res, mask] end