class Rtml::Widgets::DocumentVariableProcessing < Rtml::Widget VALID_OPTIONS = %w(type name format perms value) VALID_TYPES = %w(integer string opaque date) affects :document entry_point :declare_variable, :define_variable, :variable?, :variable_declared?, :variable_defined? entry_point :string, :integer, :opaque, :date, :binary, :boolean, :datetime entry_point :strings, :integers, :opaques, :date, :binaries, :booleans, :datetimes entry_point :string?, :integer?, :opaque?, :date?, :binary?, :boolean?, :datetime? entry_point :defined_variables, :variable_definitions entry_point :declared_variables, :variable_declarations entry_point :variable, :variable_names def initialize(*args, &block) super(*args, &block) Rtml::Test::BuiltinVariables::BUILTIN_VARIABLES.each do |name, options| define_variable(name, options) end end # Declares a TML variable to be used within this document. Valid options include: # :name the name of the variable # :type string, integer, opaque, date # :volatile yes, no # :perms "rw---", "rwxrw", etc def declare_variable(name, options = { }) unless variable?(name) define_variable name, options document.root.build :vardcl, options.merge(:name => name.to_s) end end # Returns an array containing the name of each defined variable. def variable_names variable_definitions.collect { |i| i['name'] } end # Defines a TML variable to be used within this document, without explicitly declaring it. # This is useful for adding built-in TML variables, or those set at the Incendo gateway level, # to RTML's scope. def define_variable(name, options = {}) options_with_name = options.merge(:name => name.to_s) validate_options(options_with_name) vd = variable_definitions(options[:type]) options = options_with_name.with_indifferent_access vd << options unless vd.include?(options) vd end def validate_options(options) options.each do |key, value| unless VALID_OPTIONS.include?(key.to_s) raise Rtml::Errors::InvalidOptionError, "Option '#{key}' is not allowed; expected one of #{VALID_OPTIONS.inspect}" end case key.to_s when 'type' unless VALID_TYPES.include?(value.to_s) raise Rtml::Errors::InvalidOptionError, "Type must be one of #{VALID_TYPES.inspect}; found #{value}" end end end end # Returns all known variable definitions of the specified type, which can be one of # :all, :string, :date, :opaque, :binary, :integer, :boolean def variable_definitions(type = :all) vdn = '@variable_definitions' type = valid_tml_type(type) vd = document.instance_variable_get(vdn) || document.instance_variable_set(vdn, {}.with_indifferent_access) if type == :all vd.collect { |i, j| j }.flatten else vd[type] = [] unless vd[type] document.instance_variable_set(vdn, vd) vd[type] end end alias defined_variables variable_definitions # Returns all explicit variable declarations of the specified type, which can be one of # :all, :string, :date, :opaque, :binary, :integer, :boolean def variable_declarations(type = :all) r = [] type = valid_tml_type(type) vardecs = (document / 'vardcl') || [] vardecs = [vardecs] unless vardecs.kind_of? Array vardecs.each do |vardec| if type == :all || vardec.property('type') == type r << vardec end end r end alias declared_variables variable_declarations %w(string integer opaque date).each do |type| line = __LINE__ + 2 code = <<-end_code def #{type}(*names) options = names.extract_options! names.each do |name| declare_variable(name, (options || {}).merge(:type => #{type.inspect})) end end def #{type.pluralize}(*names) if names.empty? variable_declarations(#{type.inspect}) else #{type}(*names) end end def #{type}?(name) name = name.to_s !variable_definitions(#{type.inspect}).collect { |var| var[:name] == name }.empty? end end_code eval code, binding, __FILE__, line end def variable_defined?(name) name = name.to_s !variable_definitions(:all).select { |var| var[:name] == name }.empty? end def variable_declared?(name) name = name.to_s !variable_declarations(:all).select { |var| var.property(:name) == name }.empty? end alias variable? variable_defined? alias datetime date alias datetimes dates alias datetime? date? alias binary opaque alias binaries opaques alias binary? opaque? alias boolean integer alias booleans integers alias boolean? integer? def document parent end private def valid_tml_type(type) type = "opaque" if type.to_s == "binary" type = "integer" if type.to_s == "boolean" type = "date" if type.to_s == "datetime" type end end