class Twb::FieldCalculation

Attributes

caption[R]
class[R]
comments[R]
dataSource[R]
field[R]
fieldNode[R]
fields[R]
formula[R]
formulaFlat[R]
formulaFlatResolved[R]
formulaLines[R]
formulaLinesCount[R]
formulaResolved[R]
formulaResolvedLines[R]
formulaUC[R]
has_formula[R]
is_lod[R]
is_tableCalc[R]
lodCodePos[R]
name[R]
node[R]
referencedFields[R]
remoteFields[R]
scopeIsolation[R]
uiname[R]
uuid[R]

Public Class Methods

new(calcField, datasource=nil) click to toggle source
# File lib/twb/fieldcalculation.rb, line 57
def initialize(calcField, datasource=nil)
  raise ArgumentError.new("FieldCalculation must be initialized with a CalculatedField, has been provided with a #{calcField.class}") if calcField.class != Twb::CalculatedField
  init
  # initLogger
  @field        = calcField
  calcNode      = calcField.node
  @istableCalc  = false
  # @localEmit    = false
  emit "FieldCalculation calcNode.nil? :: #{calcNode.nil?} "
  unless calcNode.nil?
    @node         = calcNode.at_xpath('./calculation')
    @fieldNode    = calcField.node
    @dataSource   = datasource
    @class        = attribText(@node, 'class')
    @remoteFields = {}
    if 'categorical-bin'.eql? @class
      @name      = @node.attribute('column').text.gsub(/^\[|\]$/,'')   # assumes the column attribute exists
      @caption   = attribText(@fieldNode, 'caption')
      uiname     = if datasource.nil?
                      @name
                   else
                      datasource.fieldUIName(@name)
                   end
      @uiname       = "#{uiname} <<group>>"
      @has_formula  = true
      @formula      = "grouped <<[#{uiname}]>> values"
      @formulaLines = [ @formula ] 
      @formulaFlat  = @formula 
      @comments     = [ ]
      @is_lod       = false
    else
      @caption   = calcField.caption
      @name      = calcField.name
      @uiname    = calcField.uiname
      #--
      @scopeIsolation = attribText(@node, 'scope-isolation') 
      #-- Formula --
      @has_formula    = @node.has_attribute?('formula')
      if @has_formula
        @formula      = @node.attribute('formula').text.gsub(/\r\n/,"\n")
        emit "\n-- init: #{@formula}"
        @formulaUC    = @formula.upcase
        @formulaLines = formula.split(/\n|\r\n/)
        @formulaFlat  = flattenFormula(@formulaLines)
        @comments     = getComments(@formulaLines)
        @lodCodePos   = @formula =~ /^[ ]*{[ ]*(fixed|include|exclude)[ ]*/i
        @is_lod       = !lodCodePos.nil? && @lodCodePos >= 0
        @is_tableCalc = @@tableCalcs.any? { |tc| @formulaUC.include?(tc) }  #assessTableCalc @formula
        # puts "#{@lodCodePos} \t #{@is_lod} \t #{@is_lod.class} \t => #{@formula}"
      end
    end
  end
end

Public Instance Methods

attribText(node, attribute) click to toggle source
# File lib/twb/fieldcalculation.rb, line 119
def attribText(node, attribute)
  node.attribute(attribute).nil? ? nil : node.attribute(attribute).text
end
enlineResolvedFormula() click to toggle source
# File lib/twb/fieldcalculation.rb, line 158
def enlineResolvedFormula
end
flattenFormula(lines) click to toggle source
# File lib/twb/fieldcalculation.rb, line 170
def flattenFormula lines
  formula = ''
  lines.each do |line|
      # line.strip
      formula += ' ' + line.gsub(/\/\/.*/, '') # unless line =~ /^[ ]*\/\//
  end
  return formula.strip
end
flattenResolvedFormula() click to toggle source
# File lib/twb/fieldcalculation.rb, line 165
def flattenResolvedFormula
  formula = formulaResolved
  formula.gsub(/\n/, ' ')
end
getComments(lines) click to toggle source
# File lib/twb/fieldcalculation.rb, line 180
def getComments lines
  comments = ''
  lines.each do |line|
    if line =~ /\/\// then
      comments += ' ' + line.gsub(/^.*\/\//,'// ')
    end
  end
  return comments.strip
end
id() click to toggle source
# File lib/twb/fieldcalculation.rb, line 111
def id
    @id ||= @id = @formulaFlat.hash + calcField.hash
end
resolveFormula() click to toggle source
# File lib/twb/fieldcalculation.rb, line 127
def resolveFormula
  # emit "\ndef resolveFormula:\n--\n#{@formula}"
  resolved = @formula
  # emit "\t formula:#{resolved}:"
  # parseFormFields # - extracts the fields from the formula; as persisted they're the internal names
  referencedFields.each do |refField|
    # emit "\t refField: "
    resolved.gsub!(refField.techCode,refField.uiCode)
    #   if calcField.techUIdiff
    #    # puts ":::: #{calcField.techCode}  //  #{calcField.uiCode}"
    #     formula = formula.gsub(calcField.techCode,calcField.uiCode)
    #    # puts ":--: #{formula}"
    #   end
  end
  # emit "\t formula:#{resolved}:"
  return resolved
end

Private Instance Methods

parseFormFields() click to toggle source
# File lib/twb/fieldcalculation.rb, line 258
def parseFormFields # formula
  @referencedFields = Array.new
  rawFields         = Array.new
  if !@formula.nil? && @formula.include?('[') && @formula.include?(']')
  chars  = formula.split('')
  until chars.empty?
    char0 = chars[0]
    case char0
    when '"', "'"
      pullString(chars)
    when '['
      rawFields << pullField(chars)
    else
      unless chars.nil? | chars.empty?
        chars.shift
      end
    end
  end
  rawFields.each do |rf|
    ds = rf[:ds]
    dataSource = if ''.eql? ds
                   @dataSource
                 else 
                   @dataSource.workbook.datasource(ds)
                 end
    # fieldUIName = dataSource.fieldUIName(rf[:field])
    refField    = ReferencedField.new(rf[:field], dataSource)
    @referencedFields << refField
    end
  end
  return @referencedFields
end
parseFormFieldsx() click to toggle source
# File lib/twb/fieldcalculation.rb, line 291
def parseFormFieldsx # formula
  rawFields = Set.new
  if !@formula.nil? && @formula.include?('[') && @formula.include?(']')
    noComms   = @formula.gsub(/\/\/.*\r\n/,' ')
    formBase  = noComms.gsub(/\r\n/,' ')
    formLen   = formBase.length
    formChars = formBase.split '' 
    until formChars.empty?
      c = formChars.shift
      case c
        when '"', "'"  
          pullString(formChars, c)
        when '['       
          rawFields << pullField(formChars, ']', @referencedFields)
      end
    end
  end
  @referencedFields = Set.new
  rawFields.each do |rf|
    # @referencedFields << rf
    dataSource = if ''.eql? rf[:ds]
                   @dataSource
                 else 
                   @dataSource.workbook.datasource(rf[:ds])
                 end
    # if dataSource.nil?
    #   binding.pry
    # end
    fieldUIName = dataSource.fieldUIName(rf[:field])
    # binding.pry
    refField = ReferencedField.new(rf[:field], dataSource)
    # binding.pry
    @referencedFields << refField
  end
  return @referencedFields
end
pullField(chars) click to toggle source
# File lib/twb/fieldcalculation.rb, line 220
def pullField chars
  # chars = str.split ''
  done  = false
  ds    = ''
  field = ''
  until done
    s01 = chars[0..1].join
    s02 = chars[0..2].join
    if ']'.eql? chars[0]
      case s01
      when ']]'
        field += ']]'
        chars.shift(2)
      when ']'
        field += chars.shift
        done = true
      else
        if '].['.eql?(s02)
          ds = field + ']'
          chars.shift(2)
          # fldstr   = chars.join
          field    = pullField(chars)[:field]
          done     = true
        else
          field += ']'
          chars.shift
          done = true
        end
      end
    else
      field += chars[0]
      chars.shift
    end
  end
  # puts "field: '#{field}' \t\t ds: #{ds}"
  return {:field => field.sub(/\[/,'').sub(/\]$/,''), :ds => ds.sub(/\[/,'').sub(/\]$/,'') }
end
pullString(chars) click to toggle source
# File lib/twb/fieldcalculation.rb, line 193
def pullString chars
  delim1 = chars.shift
  delim2 = delim1+delim1
  field  = delim1
  done   = false
  until done | chars.empty?
    s01 = chars[0..1].join
    if !delim1.eql? chars[0]
      field += chars.shift
    else
      case s01
      when delim2
        field += delim2
        chars.shift(2)
      when delim1
        field += delim1
        chars.shift
        done = true
      else
        field += delim1
        chars.shift
        done = true
      end
    end
  end
end