class Construqt::Flavour::Ciscian::PatternBasedVerb

Attributes

changes[RW]
section[RW]

Public Class Methods

compare(nu, old) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 423
def self.compare(nu, old)
  unless (nu.nil? || old.nil?)
    if (nu.serialize==old.serialize)
      return []
    end
  end

  nu_ports=nu.nil? ? {} : nu.integrate
  old_ports=old.nil? ? {} : old.integrate

  result = self.new(self.section)

  key_var = (old||nu).find_key_var
  set_keys = (old||nu).keys_of_set + (nu||old).keys_of_set

  set_keys.each do |key_val|
    variables(self.patterns).each do |v|
      if is_key_value?(v)
        result.add({key_var => key_val})
      elsif is_value?(v)
        result.add({key_var => key_val, v => (nu_ports[key_val] && nu_ports[key_val][v]) ? nu_ports[key_val][v] : nil})
      else
        set = []
        set += nu_ports[key_val][v] if nu_ports[key_val]
        set += old_ports[key_val][invert(v)] if old_ports[key_val] && old_ports[key_val][invert(v)]
        set -= nu_ports[key_val][invert(v)] if nu_ports[key_val] && nu_ports[key_val][invert(v)]
        set -= old_ports[key_val][v] if old_ports[key_val]
        result.add({key_var => key_val, v => set}) if set.length > 0
      end
    end
  end

  return [result]
end
extract_varname(variable) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 388
def self.extract_varname(variable)
  matchdata=variable.match(/{(\+|\-|\=|\*)([^}]+)}/)
  throw "could not extract varname from #{variable}" unless matchdata
  return matchdata[2]
end
find_regex(varname) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 384
def self.find_regex(varname)
  return nil
end
find_variables(pattern) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 373
def self.find_variables(pattern)
  return pattern.scan(/{[^}]+}/)
end
invert(a) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 358
def self.invert(a)
  return a.gsub(/\+/,"-") if a.match(/\+/)
  return a.gsub(/\-/,"+") if a.match(/\-/)
  throw "cannot invert #{a}"
end
is_key_value?(v) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 458
def self.is_key_value?(v)
  return !v.nil? && v.start_with?("{*")
end
is_value?(v) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 462
def self.is_value?(v)
  return !v.nil? && v.start_with?("{=")
end
matches(patterns, line) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 394
def self.matches(patterns, line)
  patterns.each do |pattern|
    variables = find_variables(pattern)
    regex=pattern
    variables.each do |var|
      var_regex = find_regex(extract_varname(var))
      var_regex = "#{Construqt::Util::PORTS_DEF_REGEXP}" unless var_regex
      regex=regex.gsub(var, var_regex)
    end

    regex=regex.gsub(" ", "\\s+")
    regex="^"+regex+"$"
    if (matchdata=line.match(regex))
      values={"pattern" => pattern}
      (1..variables.length).each do |i|
        if find_regex(extract_varname(variables[i-1])).nil?
          values[variables[i-1]]=Construqt::Util.expandRangeDefinition(matchdata[i])
        else
          values[variables[i-1]]=[matchdata[i]]
        end
      end

      return values
    end
  end

  return false
end
new(section) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 345
def initialize(section)
  self.section=section
  self.changes=[]
end
parse_line(line, lines, section, result) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 377
def self.parse_line(line, lines, section, result)
  entry=matches(self.patterns, line.to_s)
  return false unless entry
  section.add(self.section, self).add(entry)
  return true
end
variables(patterns) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 364
def self.variables(patterns)
  variables=[]
  patterns.each do |pattern|
    variables+=find_variables(pattern)
  end

  return variables
end

Public Instance Methods

add(entry) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 353
def add(entry)
  changes << entry
  self
end
always_select_empty_pattern() click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 542
def always_select_empty_pattern
  false
end
determine_output_patterns(value_sets) click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 546
def determine_output_patterns(value_sets)
  output_patterns=[]
  empty_pattern = nil
  self.class.patterns.each do |pattern|
    pvs = self.class.find_variables(pattern)
    if (pvs.empty?)
      empty_pattern=pattern
    else
      pvs.each do |pv|
        if (!value_sets[pv].nil? && !value_sets[pv].empty?)
          output_patterns << pattern
          break
        end
      end
    end
  end

  output_patterns.unshift(empty_pattern) if (output_patterns.empty? || self.always_select_empty_pattern) && !empty_pattern.nil?
  return output_patterns
end
find_key_var() click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 466
def find_key_var
  #find variable for key
  key_var=nil
  changes.each do |entry|
    entry.keys.each do |v|
      if self.class.is_key_value?(v)
        throw "can only have one key value variable in pattern {*var}" if key_var !=nil && key_var !=v
        key_var = v
      end
    end
  end

  return key_var
end
group?() click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 567
def group?
  true
end
integrate() click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 496
def integrate
  set_keys = keys_of_set

  #initialize sets
  sets={}
  set_keys.each do |key_val|
    sets[key_val] = {}
  end

  #initialize start values of values inside sets
  set_keys.each do |key_val|
    self.class.variables(self.class.patterns).each do |v|
      if self.class.is_key_value?(v)
        sets[key_val][v]=key_val
      elsif self.class.is_value?(v)
        sets[key_val][v]=nil
      else
        sets[key_val][v]=[]
      end
    end
  end

  key_var=find_key_var
  changes.each do |entry|
    sets.each do|key_val,value_sets|
      value_sets.each do |v,set|
        if (entry[key_var]==key_val)
          if self.class.is_key_value?(v)
            value_sets[v] = entry[v]
          elsif self.class.is_value?(v)
            value_sets[v] = entry[v]
          else
            value_sets[v] += entry[v] if entry[v]
            #remove duplicates without changing insertion order:
            value_sets[v] = value_sets[v].reverse.uniq.reverse

            value_sets[self.class.invert(v)] -= entry[v] if entry[v] && value_sets[self.class.invert(v)]
          end
        end
      end
    end
  end

  return sets
end
keys_of_set() click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 481
def keys_of_set
  keys=[]

  key_var=find_key_var

  if key_var
    changes.each do |entry|
      keys << entry[key_var] if entry[key_var]
    end
  end

  return keys unless keys.empty?
  return [nil]
end
serialize() click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 571
def serialize
  buffer = []
  sets = integrate

  sets.each do |key_val,value_sets|
    determine_output_patterns(value_sets).each do |pattern|
      index = 0
      i = 0
      begin
        substitution=false
        result = pattern
        i += 1
        self.class.find_variables(pattern).each do |v|
          if (self.group?)
            if (!value_sets[v].kind_of?(Array) && (self.class.is_value?(v) || self.class.is_key_value?(v)))
              result = result.gsub(v, value_sets[v].to_s) unless value_sets[v].nil? || value_sets[v].to_s.empty?
            else
              result = result.gsub(v, Construqt::Util.createRangeDefinition(value_sets[v])) unless value_sets[v].nil? || value_sets[v].empty?
            end
          else
            if (index < value_sets[v].length)
              result = result.gsub(v, value_sets[v][index])
              substitution=true
            end
          end
        end

        buffer << result if self.class.find_variables(result).empty?
        index+=1
      end while substitution
    end
  end

  return buffer
end
yes() click to toggle source
# File lib/construqt/flavour/ciscian/ciscian.rb, line 350
def yes
end