twb 4.9.3 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -16,6 +16,7 @@
16
16
  require 'nokogiri'
17
17
  require 'digest/md5'
18
18
  require 'csv'
19
+ require 'pry'
19
20
 
20
21
  module Twb
21
22
 
@@ -35,7 +36,7 @@ module Twb
35
36
  attr_reader :is_tableCalc
36
37
  attr_reader :is_lod, :lodCodePos
37
38
  attr_reader :class, :scopeIsolation
38
- attr_reader :fields, :remoteFields, :calcFields
39
+ attr_reader :fields, :remoteFields, :referencedFields
39
40
  attr_reader :comments, :uuid
40
41
 
41
42
  # attr_accessor :ttlogfile
@@ -120,59 +121,29 @@ module Twb
120
121
  end
121
122
 
122
123
  def formulaResolved
123
- @formulaResolved ||= @formulaResolved = resolveFormula
124
+ @formulaResolved ||= resolveFormula
124
125
  end
125
126
 
126
127
  def resolveFormula
127
128
  # puts "\ndef resolveFormula:\n--\n#{@formula}"
128
129
  formula = @formula
129
- parseFormFields # - extracts the fields from the formula; as persisted they're the internal names
130
- @calcFields.each do |calcField|
131
- if calcField.techUIdiff
132
- # puts ":::: #{calcField.techCode} // #{calcField.uiCode}"
133
- formula = formula.gsub(calcField.techCode,calcField.uiCode)
134
- # puts ":--: #{formula}"
135
- end
130
+ # parseFormFields # - extracts the fields from the formula; as persisted they're the internal names
131
+ referencedFields.each do |calcField|
132
+ # if calcField.techUIdiff
133
+ # # puts ":::: #{calcField.techCode} // #{calcField.uiCode}"
134
+ # formula = formula.gsub(calcField.techCode,calcField.uiCode)
135
+ # # puts ":--: #{formula}"
136
+ # end
136
137
  end
137
138
  return formula
138
139
  end
139
140
 
140
- def calcFields
141
- @calcFields ||= parseFormFields
141
+ def referencedFields
142
+ @referencedFields ||= parseFormFields
142
143
  end
143
144
 
144
- def parseFormFields
145
- # puts "--parseFormFields"
146
- @fields = Set.new
147
- @calcFields = Set.new
148
- formula = @formulaFlat
149
- if !formula.nil? && formula.include?('[') && formula.include?(']')
150
- fields = Set.new
151
- # noSqLits = formula.gsub( /'[\[\.\]]+'/, ' ')
152
- quotes = formula.gsub('"',"'")
153
- noSqLits = quotes.gsub( /'[\[\.\]]+'/, ' ')
154
- flatForm = noSqLits.gsub( /\n/, ' ')
155
- stripFrt = flatForm.gsub( /^[^\[]*[\[]/ , '[' )
156
- stripBck = stripFrt.gsub( /\][^\]]+$/ , ']' )
157
- stripMid = stripBck.gsub( /\][^\]]{2,}\[/ , ']]..[[' )
158
- stripCom = stripMid.gsub( /\][ ]*,[ ]*\[/ , ']]..[[' )
159
- stripFns = stripMid.gsub( /\][ ]*[\*\/+\-><,=][ ]*\[/ , ']]..[[' )
160
- fields = stripFns.split(']..[')
161
- emit "::self::: #{self} :: #{__LINE__} :: fields:'#{fields.inspect}'"
162
- fields.each do |field|
163
- emit "::self::: #{self} :: #{__LINE__} :: field:'#{field}'"
164
- cf = CalculationField.new( field.gsub(/^\[|\]$/, ''), @dataSource )
165
- @calcFields.add cf
166
- @fields.add field.gsub(/^\[|\]$/, '')
167
- end
168
- end
169
- return @calcFields
170
- end
171
145
 
172
146
  def formulaResolvedLines
173
- # puts "\ndef formulaResolvedLines\n--\n#{formulaResolved}"
174
- # puts "--\n#{formulaResolved.split(/\n|\r\n/)}"
175
- # puts "--\n#{formulaResolved.split(/\n|\r\n/)}"
176
147
  formulaResolved.split(/\n|\r\n/)
177
148
  end
178
149
 
@@ -212,11 +183,149 @@ module Twb
212
183
  return comments.strip
213
184
  end
214
185
 
215
- end # class FieldCalculation
186
+ private
216
187
 
217
188
 
189
+ def pullString chars
190
+ delim1 = chars.shift
191
+ delim2 = delim1+delim1
192
+ field = delim1
193
+ done = false
194
+ until done | chars.empty?
195
+ s01 = chars[0..1].join
196
+ if !delim1.eql? chars[0]
197
+ field += chars.shift
198
+ else
199
+ case s01
200
+ when delim2
201
+ field += delim2
202
+ chars.shift(2)
203
+ when delim1
204
+ field += delim1
205
+ chars.shift
206
+ done = true
207
+ else
208
+ field += delim1
209
+ chars.shift
210
+ done = true
211
+ end
212
+ end
213
+ end
214
+ end
215
+
216
+ def pullField chars
217
+ # chars = str.split ''
218
+ done = false
219
+ ds = ''
220
+ field = ''
221
+ until done
222
+ s01 = chars[0..1].join
223
+ s02 = chars[0..2].join
224
+ if ']'.eql? chars[0]
225
+ case s01
226
+ when ']]'
227
+ field += ']]'
228
+ chars.shift(2)
229
+ when ']'
230
+ field += chars.shift
231
+ done = true
232
+ else
233
+ if '].['.eql?(s02)
234
+ ds = field + ']'
235
+ chars.shift(2)
236
+ # fldstr = chars.join
237
+ field = pullField(chars)[:field]
238
+ done = true
239
+ else
240
+ field += ']'
241
+ chars.shift
242
+ done = true
243
+ end
244
+ end
245
+ else
246
+ field += chars[0]
247
+ chars.shift
248
+ end
249
+ end
250
+ # puts "field: '#{field}' \t\t ds: #{ds}"
251
+ return {:field => field.sub(/\[/,'').sub(/\]$/,''), :ds => ds.sub(/\[/,'').sub(/\]$/,'') }
252
+ end
218
253
 
219
- class CalculationField
254
+ def parseFormFields # formula
255
+ @referencedFields = Array.new
256
+ rawFields = Array.new
257
+ if !@formula.nil? && @formula.include?('[') && @formula.include?(']')
258
+ chars = formula.split('')
259
+ until chars.empty?
260
+ char0 = chars[0]
261
+ case char0
262
+ when '"', "'"
263
+ pullString(chars)
264
+ when '['
265
+ rawFields << pullField(chars)
266
+ else
267
+ unless chars.nil? | chars.empty?
268
+ chars.shift
269
+ end
270
+ end
271
+ end
272
+ rawFields.each do |rf|
273
+ ds = rf[:ds]
274
+ dataSource = if ''.eql? ds
275
+ @dataSource
276
+ else
277
+ @dataSource.workbook.datasource(ds)
278
+ end
279
+ # fieldUIName = dataSource.fieldUIName(rf[:field])
280
+ refField = ReferencedField.new(rf[:field], dataSource)
281
+ @referencedFields << refField
282
+ end
283
+ end
284
+ return @referencedFields
285
+ end
286
+
287
+ def parseFormFieldsx # formula
288
+ rawFields = Set.new
289
+ if !@formula.nil? && @formula.include?('[') && @formula.include?(']')
290
+ noComms = @formula.gsub(/\/\/.*\r\n/,' ')
291
+ formBase = noComms.gsub(/\r\n/,' ')
292
+ formLen = formBase.length
293
+ formChars = formBase.split ''
294
+ until formChars.empty?
295
+ c = formChars.shift
296
+ case c
297
+ when '"', "'"
298
+ pullString(formChars, c)
299
+ when '['
300
+ rawFields << pullField(formChars, ']', @referencedFields)
301
+ end
302
+ end
303
+ end
304
+ @referencedFields = Set.new
305
+ rawFields.each do |rf|
306
+ # @referencedFields << rf
307
+ dataSource = if ''.eql? rf[:ds]
308
+ @dataSource
309
+ else
310
+ @dataSource.workbook.datasource(rf[:ds])
311
+ end
312
+ # if dataSource.nil?
313
+ # binding.pry
314
+ # end
315
+ fieldUIName = dataSource.fieldUIName(rf[:field])
316
+ # binding.pry
317
+ refField = ReferencedField.new(rf[:field], dataSource)
318
+ # binding.pry
319
+ @referencedFields << refField
320
+ end
321
+ return @referencedFields
322
+ end
323
+
324
+ end # class FieldCalculation
325
+
326
+
327
+ # class CalculationField
328
+ class ReferencedField
220
329
  # is a field used in a calculation, resolved into its human-meaningful form
221
330
 
222
331
  include Comparable
@@ -228,65 +337,29 @@ module Twb
228
337
  attr_reader :fqName, :type
229
338
  attr_reader :techUIdiff
230
339
 
231
- def initialize code, datasource
232
- # puts "\n\nCalculationField :: %-25s | %s " % [datasource.uiname, code]
340
+ def initialize name, datasource
341
+ # puts "\n\nReferencedField :: ds: %-25s | n: %s " % [datasource, name]
342
+ @name = name
233
343
  @dataSource = datasource
234
- @dataSourceName = datasource.uiname
344
+ @dataSourceName = datasource.nil? ? nil : datasource.uiname
235
345
  @dataSourceRef = :local
236
346
  @dataSourceExists = true
347
+ @techCode = "[#{name}]"
237
348
  @techUIdiff = false
238
- @uiname = ''
239
- rawCode = code.gsub(/^\[|\]$/,'')
240
- parts = rawCode.split('].[')
241
- #puts "Field: #{code} \t parts: #{parts.length} - #{parts.inspect}"
242
- if parts.length == 1
243
- @name = parts[0]
244
- @techCode = "[#{parts[0]}]"
245
- #puts "@name: #{@name}"
246
- if datasource.nil?
247
- # puts 'a'
248
- @uiname = @name
249
- @uiCode = @techCode
250
- @techUIdiff = false
251
- else # !datasource.nil?
252
- # puts 'b'
253
- #puts "b - found uiname for '#{@name}'?: #{!datasource.fieldUIName(@name).nil?} \t is:#{datasource.fieldUIName(@name)} "
254
- @uiname = datasource.fieldUIName(@name).nil? ? @name : datasource.fieldUIName(@name)
255
- @uiCode = @uiname.nil? ? @techCode : "[#{@uiname}]"
256
- @techUIdiff = !@techCode.eql?(@uiCode)
257
- # puts ":b #{datasource.fieldUIName(@name).nil?} ... #{@name} ... #{@uiname}"
258
- # puts "CalculationField :: uin: %-25s | @name:%-s" % [@uiname,@name]
259
- end
260
- else # parts.length <> 1
261
- # puts 'c'
262
- rdstech = parts[0]
263
- calcField = parts[1]
264
- @uiname = calcField
265
- @dataSourceName = rdstech
266
- @dataSourceRef = :remote
267
- @techCode = "[#{rdstech}].[#{calcField}]"
268
- workbook = datasource.workbook
269
- @dataSource = workbook.nil? ? nil : workbook.datasource(rdstech)
270
- # puts "\t twb: #{workbook.class} / remoteds: #{remoteds.class} : #{remoteds.nil? ? "<<NOT FOUND:#{rdstech}:>>" : remoteds.uiname} "
271
- #--
272
- if @dataSource.nil? || @dataSource.fieldUIName(calcField).nil?
273
- # puts 'd'
274
- @uiname = calcField
275
- @uiCode = "[<<NOT FOUND>>#{rdstech}].[#{calcField}]"
276
- @techUIdiff = true
277
- @dataSourceExists = false
278
- else # !remoteds.nil?
279
- # puts 'e'
280
- @dataSourceName = @dataSource.uiname
281
- @uiname = @dataSource.fieldUIName(calcField)
282
- @uiCode = "[#{@dataSourceName}].[#{@uiname}]"
283
- @techUIdiff = !@techCode.eql?(@uiCode)
284
- @dataSourceExists = true
285
- end
349
+ if dataSource.nil?
350
+ # puts 'a'
351
+ @uiname = @name
352
+ @uiCode = @techCode
353
+ @techUIdiff = false
354
+ else # !datasource.nil?
355
+ # puts 'b'
356
+ # puts "b - found uiname for '#{@name}'?: #{!datasource.fieldUIName(@name).nil?} \t is:#{datasource.fieldUIName(@name)} "
357
+ @uiname = datasource.fieldUIName(@name).nil? ? @name : datasource.fieldUIName(@name)
358
+ @uiCode = @uiname.nil? ? @techCode : "[#{@uiname}]"
359
+ @techUIdiff = !@techCode.eql?(@uiCode)
360
+ # puts ":b #{datasource.fieldUIName(@name).nil?} ... #{@name} ... #{@uiname}"
361
+ # puts "CalculationField :: uin: %-25s | @name:%-s" % [@uiname,@name]
286
362
  end
287
- # puts "\t dsName: #{@dataSourceName}"
288
- # puts "\t @name: #{@name}"
289
- # puts "\t uiname: #{@uiname}"
290
363
  @fqName = "#{@dataSourceName}::#{@uiname}"
291
364
  @type = if @dataSource.nil?
292
365
  :CalculatedField
@@ -308,6 +381,6 @@ module Twb
308
381
  @fqName <=> other.fqName
309
382
  end
310
383
 
311
- end # class CalculationField
384
+ end # class ReferencedField
312
385
 
313
386
  end # module Twb
@@ -26,18 +26,20 @@ module Util
26
26
 
27
27
  #====================================================================
28
28
 
29
- attr_accessor :nodes, :edges, :fileName, :fileName
29
+ attr_accessor :nodes, :edges, :fileName, :mode
30
30
  attr_accessor :cleanup
31
31
 
32
32
  def initialize
33
33
  emit "Cypher.initialize"
34
34
  @fileName = 'Neo4jCommands'
35
+ @mode = :create
35
36
  @nodes = []
36
37
  @edges = []
37
38
  @cleanup = false
38
39
  end
39
40
 
40
41
  def render
42
+ puts "Cypher.render"
41
43
  @file = File.open(docFile("#{@fileName}.cypher"),'w')
42
44
  renderNodes
43
45
  renderEdges
@@ -46,6 +48,7 @@ module Util
46
48
  end
47
49
 
48
50
  def renderNodes
51
+ puts "Cypher def renderNodes @nodes:#{@nodes.to_s}"
49
52
  csv = CSV.open(docFile("#{@fileName}.nodes.csv"),'w')
50
53
  csv << ['Type','Name','UUID']
51
54
  nodesCSV = Set.new
@@ -53,7 +56,7 @@ module Util
53
56
  nodesByType = Hash.new { |type,nodes| type[nodes] = [] }
54
57
  @nodes.each do |node|
55
58
  nodesCSV << [node.type, node.name, node.uuid]
56
- nodeCmds << encode('MERGE','node',node,';')
59
+ nodeCmds << encode(node,';')
57
60
  nodesByType[node.type] << node
58
61
  end
59
62
  if @cleanup
@@ -93,8 +96,12 @@ module Util
93
96
  csv.close
94
97
  end
95
98
 
96
- def encode command, varName, node, terminator=''
97
- "%-8s (%s:%s { name:'%s', uuid: '%s' } ) %s" % [command, varName, node.type, node.name, node.uuid, terminator ]
99
+ def encode node, terminator=''
100
+ puts "def encode node: #{node} "
101
+ case @mode
102
+ when :merge then "MERGE (%s:%s { name:'%s', uuid: '%s' } ) %s" % [node.uuid, varName, node.type, node.name, terminator ]
103
+ when :create then "CREATE (#{node.uuid}:#{node.type} {} )"
104
+ end
98
105
  end
99
106
 
100
107
  def encodeEdge command, varName, node, terminator=''
@@ -77,7 +77,7 @@ GMLHEADER
77
77
 
78
78
  def renderNodes file
79
79
  nodes = Set.new
80
- puts 'def renderNodes'
80
+ # puts 'def renderNodes'
81
81
  @nodes.each do |node|
82
82
  gmlID = Digest::MD5.hexdigest(node.id)
83
83
  gmlName = node.name.gsub('&','&amp;').gsub('"','&quot;')
@@ -118,7 +118,7 @@ module Util
118
118
  end
119
119
 
120
120
  def <=>(other)
121
- uuid <=> other.uuid
121
+ hash <=> other.hash
122
122
  end
123
123
 
124
124
  end # class Graphnode
@@ -16,7 +16,9 @@
16
16
  require 'nokogiri'
17
17
 
18
18
  #require 'twb'
19
- require 'C:\tech\Tableau\tools\Ruby\gems\twb\lib\twb.rb'
19
+ # require 'C:\tech\Tableau\tools\Ruby\gems\twb\lib\twb.rb'
20
+ # require 'C:\tech\Tableau\Tableau Tools\Ruby\gems\twb\lib\twb.rb'
21
+ require 'twb'
20
22
  require "test/unit"
21
23
 
22
24
  system "cls"
@@ -25,10 +27,11 @@ class TestFieldCalculation < Test::Unit::TestCase
25
27
 
26
28
  def test_fragment1
27
29
  doc = Nokogiri::XML::Document.parse <<-EOHTML
28
- <calculation class='tableau' formula='abc' />
30
+ <calculation class='tableau' name='I am a formular field' formula='abc' datatype='datatype' role='' type='' class='calcfield' />
29
31
  EOHTML
30
- calcNode = doc.at_xpath('./calculation')
31
- calc = Twb::FieldCalculation.new(calcNode)
32
+ calcNode = doc.at_xpath('./calculation')
33
+ calcField = Twb::CalculatedField.new calcNode
34
+ calc = Twb::FieldCalculation.new(calcField)
32
35
  assert(!calc.nil?)
33
36
  #puts "node: #{calcNode}"
34
37
  #puts "formula: #{calc.formula}"
@@ -41,10 +44,11 @@ EOHTML
41
44
 
42
45
  def test_fragment2
43
46
  doc = Nokogiri::XML::Document.parse <<-EOHTML
44
- <calculation class='tableau' formula='// this is the number of days between the order and shipment&#13;&#10;&#13;&#10;datediff(&apos;day&apos;,[Order Date] , [other].[Ship Date])' />
47
+ <calculation class='tableau' name='Another formula fied' formula='// this is the number of days between the order and shipment&#13;&#10;&#13;&#10;datediff(&apos;day&apos;,[Order Date] , [other].[Ship Date])' />
45
48
  EOHTML
46
49
  calcNode = doc.at_xpath('./calculation')
47
- calc = Twb::FieldCalculation.new(calcNode)
50
+ calcField = Twb::CalculatedField calcNode
51
+ calc = Twb::FieldCalculation.new(calcField)
48
52
  assert(!calc.nil?)
49
53
  #puts "node: #{calcNode}"
50
54
  #puts "formula: #{calc.formula}"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twb
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.9.3
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Gerrard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-26 00:00:00.000000000 Z
11
+ date: 2020-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: creek
@@ -58,14 +58,17 @@ extensions: []
58
58
  extra_rdoc_files: []
59
59
  files:
60
60
  - lib/t.rb
61
+ - lib/tfl/Flow.rb
61
62
  - lib/twb.rb
62
63
  - lib/twb/action.rb
63
64
  - lib/twb/analysis/annotatedfieldscsvemitter.rb
64
65
  - lib/twb/analysis/calculatedfields/calculatedfieldsanalyzer.rb
65
66
  - lib/twb/analysis/calculatedfields/csvemitter.rb
67
+ - lib/twb/analysis/calculatedfields/dotanalyzer.rb
66
68
  - lib/twb/analysis/calculatedfields/fieldsaliasesanalyzer.rb
67
69
  - lib/twb/analysis/calculatedfields/groupfieldsanalyzer.rb
68
70
  - lib/twb/analysis/calculatedfields/markdownemitter.rb
71
+ - lib/twb/analysis/calculatedfields/t.rb
69
72
  - lib/twb/analysis/datasources/categoricalcolorcodinganalyzer.rb
70
73
  - lib/twb/analysis/datasources/datasourcefieldsanalyzer.rb
71
74
  - lib/twb/analysis/datasources/datasourcefieldscsvemitter.rb
@@ -82,6 +85,7 @@ files:
82
85
  - lib/twb/analysis/documentedfieldscsvemitter.rb
83
86
  - lib/twb/analysis/documentedfieldsmarkdownemitter.rb
84
87
  - lib/twb/analysis/sheets/analyzedashboardsheets.rb
88
+ - lib/twb/analysis/sheets/dashboardsummarizer.rb
85
89
  - lib/twb/analysis/sheets/dashsheetsanalyzer.rb
86
90
  - lib/twb/analysis/sheets/sheetfieldsanalyzer.rb
87
91
  - lib/twb/analysis/sheets/sheetfiltersanalyzer.rb