class AMEE::DataAbstraction::CalculationSet

The CalculationSet class represents a collection of prototype calculations (of the class ProtptypeCalculation.

Prototype calculations are contained within the @calculations instance variable ordered hash. Calculations can be added manually to the @calculations hash or initialized in place using the #calculation method which takes an options hash or block for specifying the prototype calculation properties.

Typical usage is to initialize the CalculationSet and its daughter prototype calculations together using block syntax, thus:

Calculations = CalculationSet.new {

  calculation {
    label :electricity
    path "/some/path/for/electricity"
    ...
  }

  calculation {
    label :transport
    path "a/transport/path"
    ...
  }

  ...
}

Constants

DEFAULT_RAILS_CONFIG_DIR

Attributes

calculations[RW]
file[RW]
name[RW]

Public Class Methods

find(name) click to toggle source

Retrieve a calculation set on the basis of a configuration file name or relatiev/absolute file path. If configuration files are location within the default Rails location under ‘/config/calculations’ then the path and the .rb extenstion can be omitted from the name.

# File lib/amee-data-abstraction/calculation_set.rb, line 54
def self.find(name)
  @@sets[name.to_sym] or load_set(name)
end
find_prototype_calculation(label) click to toggle source

Find a specific prototype calculation instance without specifying the set to which it belongs.

# File lib/amee-data-abstraction/calculation_set.rb, line 73
def self.find_prototype_calculation(label)
  # Make sure all sets are loaded first
  default_config_dir = defined?(::Rails) ? "#{::Rails.root}/#{DEFAULT_RAILS_CONFIG_DIR}" : DEFAULT_RAILS_CONFIG_DIR
  Dir.glob(default_config_dir + "/*.rb").each do |name|
    find(name)
  end
  # Then search them
  @@sets.each_pair do |name,set|
    set = find(name)
    return set[label] if set[label]
  end
  return nil
end
new(name,options={},&block) click to toggle source

Initialise a new Calculation set. Specify the name of the calculation set as the first argument. This name is used as the set key within the class variable @@sets hash.

# File lib/amee-data-abstraction/calculation_set.rb, line 127
def initialize(name,options={},&block)
  raise ArgumentError, "Calculation set must have a name" unless name
  @name = name
  @file = CalculationSet.find_config_file(options[:file]) if options[:file]
  @calculations = ActiveSupport::OrderedHash.new
  @all_blocks=[]
  @all_options={}
  instance_eval(&block) if block
  @@sets[@name.to_sym] = self
end
regenerate_lock_file(name,output_path=nil) click to toggle source

Regenerate a configuration lock file assocaited with the master configuration file name. Optionally set a custom path for the lock file as output_path, otherwise the lock file path and filename will be based upon the master file with the extension .lock.rb.

# File lib/amee-data-abstraction/calculation_set.rb, line 63
def self.regenerate_lock_file(name,output_path=nil)
  set = load_set(name, :lock => false)
  set.generate_lock_file(output_path)
end
sets() click to toggle source

Convenience method for accessing the @@sets class variable

# File lib/amee-data-abstraction/calculation_set.rb, line 45
def self.sets
  @@sets
end

Protected Class Methods

find_config_file(name) click to toggle source

Find the config file assocaited with name. The method first checks the default Rails configuration location (config/calculations) then the file path described by name relative to the Rails root and by absolute path.

# File lib/amee-data-abstraction/calculation_set.rb, line 104
def self.find_config_file(name)
  default_config_dir = defined?(::Rails) ? "#{::Rails.root}/#{DEFAULT_RAILS_CONFIG_DIR}" : nil
  if defined?(::Rails) && File.exists?("#{default_config_dir}/#{name.to_s}.rb")
    "#{default_config_dir}/#{name.to_s}.rb"
  elsif defined?(::Rails) && File.exists?("#{default_config_dir}/#{name.to_s}")
    "#{default_config_dir}/#{name.to_s}"
  elsif defined?(::Rails) && File.exists?("#{::Rails.root}/#{name}")
    "#{::Rails.root}/#{name}"
  elsif File.exists?(name)
    name
  else
    raise ArgumentError, "The config file '#{name}' could not be located"
  end
end
load_set(name,options={}) click to toggle source

Load a calculation set based on a filename or full path. Set :lock => false to specify loading directly from master configuration file.

# File lib/amee-data-abstraction/calculation_set.rb, line 93
def self.load_set(name,options={})
  set = CalculationSet.new(name,:file => name) do
    instance_eval(File.open(self.config_path(options)).read)
  end
  set
end

Public Instance Methods

[](sym) click to toggle source

Shorthand method for returning the prototype calculation which is represented by a label matching sym

# File lib/amee-data-abstraction/calculation_set.rb, line 141
def [](sym)
  @calculations[sym.to_sym]
end
all_calculations(options={},&dsl_block) click to toggle source

Append the supplied block to the DSL block of ALL calculations in this calculation set. This is useful for configuration which is required across all calculations (e.g. overriding human readable names or adding globally applicable metadatum)

# File lib/amee-data-abstraction/calculation_set.rb, line 161
def all_calculations(options={},&dsl_block)
  @all_blocks.push dsl_block
  @all_options.merge(options)
end
calculation(options={},&block) click to toggle source

Instantiate a PrototypeCalculation within this calculation set, initializing with the supplied DSL block to be evaluated in the context of the newly created calculation

# File lib/amee-data-abstraction/calculation_set.rb, line 149
def calculation(options={},&block)
  new_content=PrototypeCalculation.new(options.merge(@all_options),&block)
  @all_blocks.each {|all_block| new_content.instance_eval(&all_block) }
  new_content.name new_content.label.to_s.humanize unless new_content.name
  @calculations[new_content.label]=new_content
end
calculations_all_usages(apath,options={},&dsl_block) click to toggle source

Instantiate several prototype calculations, by loading each possible usage for the category with path given in apath.

Each instantiated calculation is customised on the basis of the supplied DSL block. The usage is given as a parameter to the DSL block

# File lib/amee-data-abstraction/calculation_set.rb, line 172
def calculations_all_usages(apath,options={},&dsl_block)
  dummycalc=PrototypeCalculation.new{path apath}
  
  dummycalc.amee_usages.each do |usage|
    calculation(options){
      path apath
      instance_exec(usage,&dsl_block)
    }
  end
end
config_path(options={}) click to toggle source

Returns the path to the configuration file for self. If a .lock file exists, this takes precedence, otherwise the master config file described by the #file attribute is returned. This arrangement can be overridden by passing :lock => false

# File lib/amee-data-abstraction/calculation_set.rb, line 188
def config_path(options={})
  options[:lock] = true unless options[:lock] == false
  lock_file_exists? && options[:lock] ? lock_file_path : @file
end
generate_lock_file(output_path=nil) click to toggle source

Generates a lock file for the calcuation set configuration. If no argument is provided the, the lock file is generated using the filename and path described by the #lock_file_path method. If a custom output location is required, this can be provided optionally as an argument.

# File lib/amee-data-abstraction/calculation_set.rb, line 210
def generate_lock_file(output_path=nil)
  file = output_path || lock_file_path or raise ArgumentError,
    "No path for lock file known. Either set path for the master config file using the #file accessor method or provide as an argument"
  string = ""
  @calculations.values.each do |prototype_calculation|
    string += "calculation {\n\n"
    string += "  name \"#{prototype_calculation.name}\"\n"
    string += "  label :#{prototype_calculation.label}\n"
    string += "  path \"#{prototype_calculation.path}\"\n\n"
    prototype_calculation.terms.each do |term|
      string += "  #{term.class.to_s.split("::").last.downcase} {\n"
      string += "    name \"#{term.name}\"\n" unless term.name.blank?
      string += "    label :#{term.label}\n" unless term.label.blank?
      string += "    path \"#{term.path}\"\n" unless term.path.blank?
      string += "    value \"#{term.value}\"\n" unless term.value.blank?

      if term.is_a?(AMEE::DataAbstraction::Input)
        string += "    fixed \"#{term.value}\"\n" if term.fixed? && !term.value.blank?
        if term.is_a?(AMEE::DataAbstraction::Drill)
          string += "    choices \"#{term.choices.join('","')}\"\n" if term.instance_variable_defined?("@choices")  && !term.choices.blank?
        elsif term.is_a?(AMEE::DataAbstraction::Profile)
          string += "    choices [\"#{term.choices.join('","')}\"]\n" if term.instance_variable_defined?("@choices")  && !term.choices.blank?
        end
        string += "    optional!\n" if term.optional?
      end

      string += "    default_unit :#{term.default_unit.label}\n" unless term.default_unit.blank?
      string += "    default_per_unit :#{term.default_per_unit.label}\n" unless term.default_per_unit.blank?
      string += "    alternative_units :#{term.alternative_units.map(&:label).join(', :')}\n" unless term.alternative_units.blank?
      string += "    alternative_per_units :#{term.alternative_per_units.map(&:label).join(', :')}\n" unless term.alternative_per_units.blank?
      string += "    unit :#{term.unit.label}\n" unless term.unit.blank?
      string += "    per_unit :#{term.per_unit.label}\n" unless term.per_unit.blank?
      string += "    type :#{term.type}\n" unless term.type.blank?
      string += "    interface :#{term.interface}\n" unless term.interface.blank?
      string += "    note \"#{term.note}\"\n" unless term.note.blank?
      string += "    disable!\n" if !term.is_a?(AMEE::DataAbstraction::Drill) && term.disabled?
      string += "    hide!\n" if term.hidden?
      string += "  }\n\n"
    end
    string += "}\n\n"
  end
  File.open(file,'w') { |f| f.write string }
end
lock_file_exists?() click to toggle source

Returns true if a configuration lock file exists. Otherwise, returns false.

# File lib/amee-data-abstraction/calculation_set.rb, line 201
def lock_file_exists?
  File.exists?(lock_file_path)
end
lock_file_path() click to toggle source

Returns the path to the configuration lock file

# File lib/amee-data-abstraction/calculation_set.rb, line 194
def lock_file_path
  @file.gsub(".rb",".lock.rb") rescue nil
end