twb 1.0.1 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8aae5b5038ecc0eade737b33b274b8a05dd3cc94
4
- data.tar.gz: 161e0430d5558f2151f04be57a79a1ddb9e8c02a
3
+ metadata.gz: 4680a8b2c0894aed8b9da0a4d6ba3fd0070c3008
4
+ data.tar.gz: 07d8a00756ff29178a6a331fe129737a563f5c24
5
5
  SHA512:
6
- metadata.gz: 297a5b3feadd0ad310843a4308883e7a74971ecb200b31450cabd568cba460fbd7b7b1dfb09a401f8f82e3612618310ded0c1c7049217d84f26f4592418ef44b
7
- data.tar.gz: 8ae0b5c9b192d3f9796fe7f9bee9cc09cd2b7bd415692903d6861d34d24c39239c0fc230b69b60b0edef7d6b2e842b745ae62d3b1968b0b2b50f8baffde4b9a6
6
+ metadata.gz: 9451fdcfcbc401ec98eb42c978621c76db842a3b785bf1d896c3283b55cdd2d524f1f2d52ff1c416b9c042efa3c3de140eab4bdc727e1be604790a30646e7a86
7
+ data.tar.gz: 12376fde72224cee30b7c0ceb2141f017b1a7cbb8991ba70c4dc4ba05748990a3b135212e6409b4f810c56705e983c210d3a90f6b31c185ef336003efd0d4fdc
data/lib/twb.rb CHANGED
@@ -40,5 +40,5 @@ require_relative 'twb/analysis/calculatedfieldsanalyzer'
40
40
  # Represents Tableau Workbooks and their contents.
41
41
  #
42
42
  module Twb
43
- VERSION = '1.0.1'
43
+ VERSION = '1.0.4'
44
44
  end
@@ -1,4 +1,4 @@
1
- # TTC_CalculatedFields.rb - this Ruby script Copyright 2017 Christopher Gerrard
1
+ # calculatedfieldsanalyzer.rb - this Ruby script Copyright 2017 Christopher Gerrard
2
2
  #
3
3
  # This program is free software: you can redistribute it and/or modify
4
4
  # it under the terms of the GNU General Public License as published by
@@ -111,7 +111,6 @@ DOTHEADER
111
111
  def processTWB twbWithDir
112
112
  twb = File.basename(twbWithDir)
113
113
  @twb = Twb::Workbook.new twbWithDir
114
- puts " - #{twbWithDir}"
115
114
  emit "- Workbook: #{twbWithDir}"
116
115
  emit " version: #{@twb.version}"
117
116
  return if twbWithDir.end_with? == "Tableau Calculated Fields Analyses.twb"
@@ -144,7 +143,7 @@ DOTHEADER
144
143
  calculationNodes = ds.calculatedFields
145
144
  emit "calculationNodes : nil? '#{calculationNodes.nil?}'" # - len '#{calculationNodes.length}'"
146
145
  calculationNodes.each do |calcNode|
147
- calculation = Twb::FieldCalculation.new calcNode
146
+ calculation = Twb::FieldCalculation.new(calcNode, ds)
148
147
  emit "HANDLING CALCULATION NODE:"
149
148
  emit calcNode.attributes
150
149
  #-- field names --
@@ -39,7 +39,7 @@ module Twb
39
39
  attr_reader :name, :caption, :uiname, :dsclass
40
40
  attr_reader :connection, :connHash
41
41
  attr_reader :tables
42
- attr_reader :localfields, :metadatafields, :mappedFields, :fieldUINames, :calculatedFields
42
+ attr_reader :localfields, :metadatafields, :mappedFields, :fieldUINames, :calculatedFields
43
43
  attr_reader :filters
44
44
  attr_reader :node
45
45
 
@@ -19,34 +19,66 @@ module Twb
19
19
 
20
20
  class FieldCalculation
21
21
 
22
- attr_reader :node, :fieldNode
23
- attr_reader :formula, :formulaLines, :formulaFlat
24
- attr_reader :uiname, :techname, :caption
22
+ attr_reader :node, :fieldNode, :dataSource
23
+ attr_reader :formula, :resolvedFormula, :formulaLines, :formulaFlat
24
+ attr_reader :uiname, :techname, :caption
25
25
  attr_reader :class, :scopeIsolation
26
- attr_reader :fields, :resolvedFields
26
+ attr_reader :fields, :resolvedFields, :remoteFields
27
27
  attr_reader :comments
28
28
 
29
- def initialize calcNode
29
+ def initialize(calcNode, datasource=nil)
30
30
  if calcNode
31
31
  @node = calcNode
32
- @fieldNode = @node.xpath('..')
33
- # field names
34
- @caption, = attribText(@fieldNode, 'caption')
35
- @techname = @fieldNode.attribute('name').text.gsub(/^\[|\]$/,'') # assumes the name attribute exists
36
- @uiname = @caption.nil? ? @techName : @caption
37
- #-- Calculation --
38
- @has_formula = @node.has_attribute?('formula')
39
- if @has_formula
40
- @formula = @node.attribute('formula').text
41
- @formulaLines = formula.split(/\n|\r\n/)
42
- @formulaFlat = flattenFormula(formulaLines)
43
- @comments = getComments(formulaLines)
32
+ @fieldNode = @node.at_xpath('..')
33
+ @dataSource = datasource
34
+ @class = attribText(@node, 'class')
35
+ @remoteFields = {}
36
+ if 'categorical-bin'.eql? @class
37
+ # puts calcNode
38
+ # <calculation class='categorical-bin'
39
+ # column='[Calculation_507569757376950272]'
40
+ # default='&quot;Other&quot;'
41
+ # new-bin='true'>
42
+ @techname = calcNode.attribute('column').text.gsub(/^\[|\]$/,'') # assumes the column attribute exists
43
+ @caption = attribText(@fieldNode, 'caption')
44
+ uiname = if datasource.nil?
45
+ @techName
46
+ else
47
+ datasource.fieldUIName(@techname)
48
+ end
49
+ @uiname = "#{uiname} (group)"
50
+ @formula = "grouped '#{uiname}' values"
51
+ @comments = [ ]
52
+ @resolvedFields = [ {:field => uiname, :fieldui => uiname, :source => nil} ]
53
+ else
54
+ # field names
55
+ # puts "\n****** "
56
+ # puts " fnode: #{@fieldNode}\n****** "
57
+ @caption = @fieldNode.attribute('caption').nil? ? nil : @fieldNode.attribute('caption').text
58
+ @techname = @fieldNode.attribute('name').text.gsub(/^\[|\]$/,'') # assumes the name attribute exists
59
+ @uiname = @caption.nil? ? @techname : @caption
60
+ # puts " caption: #{@caption}"
61
+ # puts "techname: #{@techname}"
62
+ # puts " uiname: #{@uiname}"
63
+ #--
64
+ @scopeIsolation = attribText(@node, 'scope-isolation')
65
+ #-- Formula --
66
+ @has_formula = @node.has_attribute?('formula')
67
+ if @has_formula
68
+ @formula = @node.attribute('formula').text
69
+ @formulaLines = formula.split(/\n|\r\n/)
70
+ @formulaFlat = flattenFormula(@formulaLines)
71
+ @comments = getComments(@formulaLines)
72
+ elsif @class.eql? 'categorical-bin'
73
+ @formula = '<<Group>>'
74
+ @formulaLines = [ @formula ]
75
+ @formulaFlat = [ @formula ]
76
+ @comments = [ ]
77
+ end
78
+ #-- Fields --
79
+ parseFormFields # establishes @ fields
80
+ resolveFields # establishes @ resolvedFields
44
81
  end
45
- @class = attribText(@node, 'class')
46
- @scopeIsolation = attribText(@node, 'scope-isolation')
47
- #-- Fields --
48
- parseFormFields # establishes @ fields
49
- resolveFields # establishes @ resolvedFields
50
82
  end
51
83
  end
52
84
 
@@ -54,11 +86,11 @@ module Twb
54
86
  node.attribute(attribute).nil? ? nil : node.attribute(attribute).text
55
87
  end
56
88
 
57
-
89
+
58
90
  def parseFormFields
59
91
  @fields = Set.new []
60
92
  formula = formulaFlat
61
- if formula.include?('[') && formula.include?(']')
93
+ if !formula.nil? && formula.include?('[') && formula.include?(']')
62
94
  noSqLits = formula.gsub(/'[\[\.\]]+'/, ' ')
63
95
  flatForm = noSqLits.gsub( /\n/, ' ')
64
96
  stripFrt = flatForm.gsub( /^[^\[]*[\[]/ , '[' )
@@ -74,18 +106,55 @@ module Twb
74
106
 
75
107
  def resolveFields
76
108
  @resolvedFields = []
77
- fields.each do |field|
109
+ @fields.each do |field|
78
110
  rawField = field.gsub(/^\[|\]$/,'')
79
111
  parts = rawField.split('].[')
80
112
  if parts.length > 1
81
- hash = { :field => parts[1], :source => parts[0] }
113
+ source = parts[0]
114
+ fieldCalc = parts[1]
115
+ fieldui = fieldCalc
82
116
  else
83
- hash = { :field => parts[0], :source => nil }
117
+ source = nil
118
+ fieldCalc = parts[0]
119
+ fieldui = @dataSource.fieldUIName(fieldCalc)
120
+ end
121
+ hash = { :field => fieldCalc, :fieldui => fieldui, :source => source }
122
+ @resolvedFields << hash
123
+ end
124
+ end
125
+
126
+
127
+ def resolvedFormula
128
+ @resolvedFormula ||= resolveFormula
129
+ end
130
+
131
+ def resolveFormula
132
+ # puts "resolveFormula :\n-- formula --\n %s \n-- @dataSource.nil? : %s \n-- @resolvedFields.nil? : %s \n--" % [ @formula, @dataSource.nil?, @resolvedFields.nil? ]
133
+ formula = @formula
134
+ unless @dataSource.nil? || @formula.nil? || @resolvedFields.nil?
135
+ @resolvedFields.each do |rf|
136
+ field = rf[:field]
137
+ source = rf[:source]
138
+ # puts " field: #{field}"
139
+ # puts " src: #{source}"
140
+ if source.nil?
141
+ fieldInternal = field # "[#{rf[:field]}]"
142
+ fieldUI = @dataSource.fieldUIName(field)
143
+ # puts " f?: #{formula.include?(field)}"
144
+ # puts " fui: #{fieldUI}"
145
+ formula = formula.gsub(field,fieldUI) unless fieldUI.nil?
146
+ # puts "formula:\n--\n#{formula}"
147
+ else
148
+ @remoteFields[source] = SortedSet.new unless @remoteFields.include? source
149
+ @remoteFields[source].add field
150
+ end
84
151
  end
85
- @resolvedFields << hash unless hash.nil?
86
152
  end
153
+ # puts "resolvedFormula:\n==\n#{formula}\n--"
154
+ return formula
87
155
  end
88
156
 
157
+
89
158
  def flattenFormula lines
90
159
  formula = ''
91
160
  lines.each do |line|
@@ -94,7 +163,8 @@ module Twb
94
163
  end
95
164
  return formula.strip
96
165
  end
97
-
166
+
167
+
98
168
  def getComments lines
99
169
  comments = ''
100
170
  lines.each do |line|
@@ -105,6 +175,7 @@ module Twb
105
175
  return comments.strip
106
176
  end
107
177
 
108
- end
109
178
 
110
- end
179
+ end # class FieldCalculation
180
+
181
+ end # module Twb
@@ -15,19 +15,19 @@
15
15
 
16
16
  module Twb
17
17
  module Util
18
-
18
+
19
19
  class DotFileRenderer
20
20
  @@gvDotLocation = 'C:\\tech\\graphviz\\Graphviz2.38\\bin\\dot.exe'
21
- @@renderTypes = ['pdf', 'png', 'svg']
21
+ @@renderTypes = [:pdf, :png, :svg]
22
22
 
23
23
  def initialize
24
24
  @gvDotLocation = @@gvDotLocation
25
25
  end
26
-
26
+
27
27
  def gvDotLocation=(location)
28
28
  @gvDotLocation = location
29
29
  end
30
-
30
+
31
31
  def renderAll(dotFile)
32
32
  renderedFiles = []
33
33
  @@renderTypes.each do |type|
@@ -35,12 +35,11 @@ module Util
35
35
  end
36
36
  return renderedFiles
37
37
  end
38
-
38
+
39
39
  def render(dotFile, type)
40
- type = type.downcase
41
40
  if @@renderTypes.include?(type)
42
- typeParam = '-T' + type
43
- renderedFile = dotFile.sub(/.dot$/,'') + '.' + type
41
+ typeParam = '-T' + type.to_s
42
+ renderedFile = dotFile.sub(/.dot$/,'') + '.' + type.to_s
44
43
  renderedFileParam = '-o' + renderedFile
45
44
  #puts "\t <render cmd> system #{@gvDotLocation}, #{typeParam}, #{renderedFileParam}, #{dotFile} "
46
45
  system @gvDotLocation, typeParam, renderedFileParam, dotFile
@@ -30,17 +30,18 @@ module Util
30
30
  @@typeColors = { :CalculatedField => 'fillcolor=lightskyblue3',
31
31
  :DBTable => 'fillcolor=steelblue',
32
32
  :TwbDataConnection => 'fillcolor=cornflowerblue',
33
- :DatabaseField => 'fillcolor=steelblue',
33
+ :DatabaseField => 'fillcolor=grey',
34
34
  }
35
35
 
36
+ # not currently used
36
37
  @@typeStyles = { :CalculatedField => 'style=filled',
37
38
  :DBTable => 'style=filled',
38
39
  :TwbDataConnection => 'style=filled',
39
40
  :DatabaseField => 'style=filled'
40
41
  }
41
42
 
43
+ # @id - the technical fully qualified identifier, distinquishes the node from similarly named nodes
42
44
  # @name - the visible name
43
- # @id - the technical identifier, used to distinquish the node from similarly named nodes
44
45
  # @type - useful for categorizing the node
45
46
  attr_reader :id, :type, :name
46
47
  attr_reader :cypherID, :cypherCreate
@@ -73,10 +74,7 @@ module Util
73
74
 
74
75
 
75
76
  def dotLabel
76
- # "JIRA 1::JIRA 1.csv" [label="JIRA 1.csv"]
77
- # style = @type =~ /Data Source|DB Table|Database Field/ ? "style=filled" : ''
78
- # style = @type =~ /Data Source|DB Table|Database Field/ ? "style=filled" : ''
79
- "\"%s\" [label=\"%s\" %s %s %s ]" % [id, name, @@typeShapes[@type], 'style=filled', @@typeColors[@type]]
77
+ "\"%s\" [label=\"%s\" %s %s ]" % [id, name.gsub('"','\"'), @@typeShapes[@type], @@typeColors[@type]]
80
78
  end
81
79
 
82
80
 
@@ -15,33 +15,33 @@
15
15
 
16
16
  module Twb
17
17
  module Util
18
-
18
+
19
19
  class DotFileRenderer
20
20
  @@gvDotLocation = 'C:\\tech\\graphviz\\Graphviz2.38\\bin\\dot.exe'
21
- @@renderTypes = ['pdf', 'png', 'svg']
21
+ @@renderTypes = [:pdf, :png, :svg]
22
22
  def initialize
23
23
  @gvDotLocation = @@gvDotLocation
24
24
  end
25
-
25
+
26
26
  def gvDotLocation=(location)
27
27
  @gvDotLocation = location
28
28
  end
29
-
29
+
30
30
  def render dotFile
31
31
  renderedFiles = []
32
32
  @@renderTypes.each do |type|
33
33
  renderedFiles << render(dotFile,type)
34
34
  end
35
35
  end
36
-
36
+
37
37
  def render(dotFile,type)
38
38
  if @@renderTypes.includes(type)
39
- renderedFile = dotFile + '.' + type
40
- system "\"#{@gvDotLocation}\" -T#{type} -o\"#{renderedFile}\" \"#{dotFile}\""
39
+ renderedFile = dotFile + '.' + type.to_s
40
+ system "\"#{@gvDotLocation}\" -T#{type.to_s} -o\"#{renderedFile}\" \"#{dotFile}\""
41
41
  end
42
42
  return renderedFile
43
43
  end
44
-
44
+
45
45
  end
46
46
 
47
47
  def renderDot(twb,dot)
@@ -38,15 +38,11 @@ class TestDotFileRenderer < Test::Unit::TestCase
38
38
 
39
39
  def test_SpecifyType
40
40
  renderer = Twb::Util::DotFileRenderer.new
41
- renderedFile = renderer.render(@@testDotFile,'pdf')
41
+ renderedFile = renderer.render(@@testDotFile,:pdf)
42
42
  assert(!renderedFile.nil?)
43
- renderedFile = renderer.render(@@testDotFile,'png')
43
+ renderedFile = renderer.render(@@testDotFile,:png)
44
44
  assert(!renderedFile.nil?)
45
- renderedFile = renderer.render(@@testDotFile,'PnG') # should convert to 'png'
46
- assert(!renderedFile.nil?)
47
- renderedFile = renderer.render(@@testDotFile,'PNG') # should convert to 'png'
48
- assert(!renderedFile.nil?)
49
- renderedFile = renderer.render(@@testDotFile,'svg')
45
+ renderedFile = renderer.render(@@testDotFile,:svg)
50
46
  assert(!renderedFile.nil?)
51
47
  renderedFile = renderer.render(@@testDotFile,'xyz') # should fail
52
48
  assert(renderedFile.nil?)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Gerrard