twb 4.9.10 → 5.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/twb.rb +1 -1
- data/lib/twb/analysis/calculatedfields/calculatedfieldsanalyzer.rb +47 -32
- data/lib/twb/analysis/calculatedfields/t.rb +6 -0
- data/lib/twb/calculatedfield.rb +4 -4
- data/lib/twb/columnfield.rb +2 -2
- data/lib/twb/datasource.rb +49 -37
- data/lib/twb/fieldcalculation.rb +171 -98
- data/test/testFieldCalculation.rb +10 -6
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f839625abecd6c9b4ad520856fd216678790a2dace5307e62458db4e07b970cd
|
|
4
|
+
data.tar.gz: f95701f60e3f4f99525113e723392b1d039b361db9ac63eb2689c58ef4a3a490
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d59954bb21cc6b232402d0792219df4e0e48ddcf8a664088b58409c7e28b30175f3f3304910459304f2d87639bf1ce5a6f7d9b533b43ed0088bfbb1c4f131c8f
|
|
7
|
+
data.tar.gz: c8fa036df0e3e8808f507404f5930a8db20ca19fb7a04251eda1deee7dc1ea09f1e06a811f79539275d2eed9cb473f009239dca5ae1c56c7179f4826ed0201c0
|
data/lib/twb.rb
CHANGED
|
@@ -249,47 +249,62 @@ DOTHEADER
|
|
|
249
249
|
]
|
|
250
250
|
end
|
|
251
251
|
#-- collect fields referenced in formula
|
|
252
|
-
emit "# Calculated Fields: #{calculation.
|
|
253
|
-
calculation.
|
|
254
|
-
emit " referenced field ::
|
|
255
|
-
emit " referenced field.name ::'#{rf.name.nil?}' :: '#{rf.name}'"
|
|
256
|
-
emit " referenced field.uiname::'#{rf.uiname}'"
|
|
257
|
-
# if @doGraph
|
|
258
|
-
unless rf.uiname.nil?
|
|
259
|
-
properties = {'DataSource' => ds.uiname, 'DataSourceReference' => 'local', :source => rf}
|
|
260
|
-
refFieldNode = Twb::Util::Graphnode.new(name: rf.uiname, id: rf.id, type: rf.type, properties: properties)
|
|
261
|
-
@nodes.add refFieldNode
|
|
262
|
-
fieldFieldEdge = Twb::Util::Graphedge.new(from: calcFieldNode, to: refFieldNode, relationship: 'references')
|
|
263
|
-
@edges.add fieldFieldEdge
|
|
264
|
-
end
|
|
265
|
-
# end
|
|
266
|
-
referencedFields.add rf.id
|
|
267
|
-
refFieldTable = ds.fieldTable(rf.name)
|
|
268
|
-
emit "refFieldTable.nil? : #{refFieldTable.nil?}"
|
|
269
|
-
unless refFieldTable.nil?
|
|
270
|
-
tableID = refFieldTable + ':::' + ds.uiname
|
|
271
|
-
tableName = "||#{refFieldTable}||"
|
|
272
|
-
# if @doGraph
|
|
273
|
-
tableNode = Twb::Util::Graphnode.new(name: tableName, id: tableID, type: :DBTable, properties: properties)
|
|
274
|
-
@nodes.add tableNode
|
|
275
|
-
fieldFieldEdge = Twb::Util::Graphedge.new(from: refFieldNode, to: tableNode, relationship: 'is a field in')
|
|
276
|
-
@edges.add fieldFieldEdge
|
|
277
|
-
# end
|
|
278
|
-
# fldToDsNode = tableNode
|
|
279
|
-
end
|
|
252
|
+
emit "# Calculated Fields: #{calculation.referencedFields.length}"
|
|
253
|
+
calculation.referencedFields.each do |rf|
|
|
254
|
+
emit " referenced field :: %12s %s " % [ rf.dataSourceName, rf.uiname ]
|
|
280
255
|
@csvFormulaFields << [
|
|
281
256
|
@referencedFieldsCount += 1,
|
|
282
257
|
@twb.name,
|
|
283
258
|
# @modTime,
|
|
284
|
-
ds.uiname,
|
|
259
|
+
rf.dataSourceName, # ds.uiname,
|
|
285
260
|
calcField.uiname,
|
|
286
261
|
calculation.formulaFlat,
|
|
287
262
|
calculation.formulaFlatResolved,
|
|
288
263
|
rf.name,
|
|
289
|
-
rf.uiname,
|
|
290
|
-
rf.id,
|
|
291
|
-
refFieldTable
|
|
264
|
+
rf.uiname, #.uiname,
|
|
265
|
+
'', # rf.id,
|
|
266
|
+
'', #refFieldTable
|
|
292
267
|
]
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
# emit " referenced field.name ::'#{rf.name.nil?}' :: '#{rf.name}'"
|
|
271
|
+
# emit " referenced field.uiname::'#{rf.uiname}'"
|
|
272
|
+
# if @doGraph
|
|
273
|
+
# unless rf.uiname.nil?
|
|
274
|
+
# properties = {'DataSource' => ds.uiname, 'DataSourceReference' => 'local', :source => rf}
|
|
275
|
+
# refFieldNode = Twb::Util::Graphnode.new(name: rf.uiname, id: rf.id, type: rf.type, properties: properties)
|
|
276
|
+
# @nodes.add refFieldNode
|
|
277
|
+
# fieldFieldEdge = Twb::Util::Graphedge.new(from: calcFieldNode, to: refFieldNode, relationship: 'references')
|
|
278
|
+
# @edges.add fieldFieldEdge
|
|
279
|
+
# end
|
|
280
|
+
# # end
|
|
281
|
+
# referencedFields.add rf.id
|
|
282
|
+
# refFieldTable = ds.fieldTable(rf.name)
|
|
283
|
+
# emit "refFieldTable.nil? : #{refFieldTable.nil?}"
|
|
284
|
+
# unless refFieldTable.nil?
|
|
285
|
+
# tableID = refFieldTable + ':::' + ds.uiname
|
|
286
|
+
# tableName = "||#{refFieldTable}||"
|
|
287
|
+
# # if @doGraph
|
|
288
|
+
# tableNode = Twb::Util::Graphnode.new(name: tableName, id: tableID, type: :DBTable, properties: properties)
|
|
289
|
+
# @nodes.add tableNode
|
|
290
|
+
# fieldFieldEdge = Twb::Util::Graphedge.new(from: refFieldNode, to: tableNode, relationship: 'is a field in')
|
|
291
|
+
# @edges.add fieldFieldEdge
|
|
292
|
+
# # end
|
|
293
|
+
# # fldToDsNode = tableNode
|
|
294
|
+
# end
|
|
295
|
+
# @csvFormulaFields << [
|
|
296
|
+
# @referencedFieldsCount += 1,
|
|
297
|
+
# @twb.name,
|
|
298
|
+
# # @modTime,
|
|
299
|
+
# ds.uiname,
|
|
300
|
+
# calcField.uiname,
|
|
301
|
+
# calculation.formulaFlat,
|
|
302
|
+
# calculation.formulaFlatResolved,
|
|
303
|
+
# rf.name,
|
|
304
|
+
# rf.uiname,
|
|
305
|
+
# rf.id,
|
|
306
|
+
# refFieldTable
|
|
307
|
+
# ]
|
|
293
308
|
end # resolvedFields.each do
|
|
294
309
|
end # if calculation.has_formula
|
|
295
310
|
end # ds.calculatedFields.each
|
data/lib/twb/calculatedfield.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (C) 2014, 2015,
|
|
1
|
+
# Copyright (C) 2014, 2015, 2020 Chris 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
|
|
@@ -26,7 +26,7 @@ module Twb
|
|
|
26
26
|
attr_reader :node, :properties
|
|
27
27
|
attr_reader :caption, :name, :uiname
|
|
28
28
|
attr_reader :datatype, :role, :propType
|
|
29
|
-
attr_reader :calculation, :
|
|
29
|
+
attr_reader :calculation, :referencedFields
|
|
30
30
|
attr_reader :isGroup, :groupMembers
|
|
31
31
|
attr_reader :hidden
|
|
32
32
|
|
|
@@ -52,8 +52,8 @@ module Twb
|
|
|
52
52
|
@properties ||= loadProperties
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
def
|
|
56
|
-
@calculation.
|
|
55
|
+
def referencedFields
|
|
56
|
+
@calculation.referencedFields
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def formulaLines
|
data/lib/twb/columnfield.rb
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
15
15
|
|
|
16
16
|
require 'nokogiri'
|
|
17
|
+
require 'pry'
|
|
17
18
|
|
|
18
19
|
module Twb
|
|
19
20
|
|
|
@@ -85,7 +86,6 @@ module Twb
|
|
|
85
86
|
@aggregation = load 'aggregation'
|
|
86
87
|
@autoColumn = load 'auto-column'
|
|
87
88
|
@datatypeCustomized = load 'datatype-customized'
|
|
88
|
-
# @calcField = loadCalcField
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
def id
|
|
@@ -94,7 +94,7 @@ module Twb
|
|
|
94
94
|
|
|
95
95
|
def load nodeName
|
|
96
96
|
attr = @node.attribute(nodeName)
|
|
97
|
-
val = attr.nil? ? nil : attr.text.strip
|
|
97
|
+
val = attr.nil? ? nil : attr.text.strip
|
|
98
98
|
return val
|
|
99
99
|
end
|
|
100
100
|
|
data/lib/twb/datasource.rb
CHANGED
|
@@ -56,7 +56,7 @@ module Twb
|
|
|
56
56
|
attr_reader :tableFieldsMap
|
|
57
57
|
attr_reader :fieldUINames
|
|
58
58
|
attr_reader :aliases
|
|
59
|
-
attr_reader :calculatedFields, :
|
|
59
|
+
attr_reader :calculatedFields, :calculatedFieldsMap, :calculatedFieldNames, :calculatedField
|
|
60
60
|
attr_reader :allFields
|
|
61
61
|
attr_reader :groups
|
|
62
62
|
attr_reader :filters
|
|
@@ -391,40 +391,6 @@ module Twb
|
|
|
391
391
|
return @fieldUINames
|
|
392
392
|
end
|
|
393
393
|
|
|
394
|
-
def loadFieldUINames
|
|
395
|
-
# puts 'loadFieldUINames'
|
|
396
|
-
@fieldUINames = {}
|
|
397
|
-
# puts 'metadataFields'
|
|
398
|
-
metadataFields.each do |fld|
|
|
399
|
-
# puts " - name:%-45s | uiname:%-45s | localName:%-45s " % [ "'#{fld.name}'", "'#{fld.uiname}'", "'#{fld.localName}'"]
|
|
400
|
-
@fieldUINames[fld.uiname] = fld.uiname
|
|
401
|
-
@fieldUINames[fld.localName] = fld.uiname unless fld.localName.nil?
|
|
402
|
-
@fieldUINames[fld.name] = fld.uiname unless fld.name.nil?
|
|
403
|
-
end
|
|
404
|
-
# puts 'calculatedFields'
|
|
405
|
-
calculatedFields.each do |fld|
|
|
406
|
-
# puts " - name:%-45s | uiname:%-45s " % [ "'#{fld.name}'", "'#{fld.uiname}'"]
|
|
407
|
-
@fieldUINames[fld.name] = fld.uiname
|
|
408
|
-
@fieldUINames[fld.uiname] = fld.uiname
|
|
409
|
-
end
|
|
410
|
-
# puts 'localFields'
|
|
411
|
-
localFields.each do |fld|
|
|
412
|
-
# puts " - name:%-45s | uiname:%-45s " % [ "'#{fld.name}'", "'#{fld.uiname}'"]
|
|
413
|
-
@fieldUINames[fld.name] = fld.uiname
|
|
414
|
-
@fieldUINames[fld.uiname] = fld.uiname
|
|
415
|
-
end
|
|
416
|
-
# puts "columnFields: #{columnFields.length}"
|
|
417
|
-
columnFields.each do |fld|
|
|
418
|
-
@fieldUINames[fld.name] = fld.uiname
|
|
419
|
-
@fieldUINames[fld.uiname] = fld.uiname
|
|
420
|
-
end
|
|
421
|
-
groups.each do |fld|
|
|
422
|
-
@fieldUINames[fld.name] = fld.uiname
|
|
423
|
-
@fieldUINames[fld.uiname] = fld.uiname
|
|
424
|
-
end
|
|
425
|
-
return @fieldUINames
|
|
426
|
-
end
|
|
427
|
-
|
|
428
394
|
def tableFields
|
|
429
395
|
@tableFieldsMap.values
|
|
430
396
|
end
|
|
@@ -482,8 +448,7 @@ module Twb
|
|
|
482
448
|
|
|
483
449
|
def loadAllFields
|
|
484
450
|
@allFields = SortedSet.new
|
|
485
|
-
|
|
486
|
-
@allFields << dbf
|
|
451
|
+
@allFields << dbFields
|
|
487
452
|
@allFields << calculatedFieldNames
|
|
488
453
|
end
|
|
489
454
|
|
|
@@ -532,6 +497,53 @@ module Twb
|
|
|
532
497
|
|
|
533
498
|
private
|
|
534
499
|
|
|
500
|
+
def loadFieldUINames
|
|
501
|
+
@fieldUINames = {}
|
|
502
|
+
# puts"metadataFields: #{metadataFields.length}"
|
|
503
|
+
metadataFields.each do |fld|
|
|
504
|
+
# puts" - name:%-45s | caption:%-45s | uiname:%-45s " % [ "'#{fld.name}'", "'#{fld.caption}'", "'#{fld.uiname}'"]
|
|
505
|
+
unless fld.name.nil?
|
|
506
|
+
@fieldUINames[fld.uiname] = fld.uiname
|
|
507
|
+
@fieldUINames[fld.localName] = fld.uiname unless fld.localName.nil?
|
|
508
|
+
@fieldUINames[fld.name] = fld.uiname
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
# puts"localFields: #{localFields.length}"
|
|
512
|
+
localFields.each do |fld|
|
|
513
|
+
# puts" - name:%-45s | caption:%-45s | uiname:%-45s " % [ "'#{fld.name}'", "'#{fld.caption}'", "'#{fld.uiname}'"]
|
|
514
|
+
unless fld.caption.nil?
|
|
515
|
+
@fieldUINames[fld.name] = fld.caption
|
|
516
|
+
@fieldUINames[fld.uiname] = fld.caption
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
# puts"groups: #{groups.length}"
|
|
520
|
+
groups.each do |fld|
|
|
521
|
+
# puts" - name:%-45s | caption:%-45s | uiname:%-45s " % [ "'#{fld.name}'", "'#{fld.caption}'", "'#{fld.uiname}'"]
|
|
522
|
+
unless fld.caption.nil?
|
|
523
|
+
@fieldUINames[fld.name] = fld.caption
|
|
524
|
+
@fieldUINames[fld.uiname] = fld.caption
|
|
525
|
+
end
|
|
526
|
+
end
|
|
527
|
+
# puts"calculatedFields: #{calculatedFields.length}"
|
|
528
|
+
calculatedFields.each do |fld|
|
|
529
|
+
# puts" - name:%-45s | caption:%-45s | uiname:%-45s " % [ "'#{fld.name}'", "'#{fld.caption}'", "'#{fld.uiname}'"]
|
|
530
|
+
unless fld.caption.nil?
|
|
531
|
+
@fieldUINames[fld.name] = fld.caption
|
|
532
|
+
@fieldUINames[fld.uiname] = fld.caption
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
# puts"columnFields: #{columnFields.length}"
|
|
536
|
+
columnFields.each do |fld|
|
|
537
|
+
# puts" - name:%-45s | caption:%-45s | uiname:%-45s " % [ "'#{fld.name}'", "'#{fld.caption}'", "'#{fld.uiname}'"]
|
|
538
|
+
unless fld.caption.nil?
|
|
539
|
+
# @fieldUINames[fld.name] = fld.caption
|
|
540
|
+
@fieldUINames[fld.name.gsub(/^[\[]|[\]]$/,'')] = fld.caption
|
|
541
|
+
@fieldUINames[fld.uiname] = fld.caption
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
return @fieldUINames
|
|
545
|
+
end
|
|
546
|
+
|
|
535
547
|
def loadGroups
|
|
536
548
|
@groups = []
|
|
537
549
|
groupNodes = @node.xpath('.//group')
|
data/lib/twb/fieldcalculation.rb
CHANGED
|
@@ -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,
|
|
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 ||=
|
|
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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
|
141
|
-
@
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
232
|
-
# puts "\n\
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
#puts "@name
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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
|
|
384
|
+
end # class ReferencedField
|
|
312
385
|
|
|
313
386
|
end # module Twb
|
|
@@ -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
|
|
31
|
-
|
|
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 datediff('day',[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 datediff('day',[Order Date] , [other].[Ship Date])' />
|
|
45
48
|
EOHTML
|
|
46
49
|
calcNode = doc.at_xpath('./calculation')
|
|
47
|
-
|
|
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
|
+
version: 5.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris Gerrard
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-05
|
|
11
|
+
date: 2020-06-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: creek
|
|
@@ -67,6 +67,7 @@ files:
|
|
|
67
67
|
- lib/twb/analysis/calculatedfields/fieldsaliasesanalyzer.rb
|
|
68
68
|
- lib/twb/analysis/calculatedfields/groupfieldsanalyzer.rb
|
|
69
69
|
- lib/twb/analysis/calculatedfields/markdownemitter.rb
|
|
70
|
+
- lib/twb/analysis/calculatedfields/t.rb
|
|
70
71
|
- lib/twb/analysis/datasources/categoricalcolorcodinganalyzer.rb
|
|
71
72
|
- lib/twb/analysis/datasources/datasourcefieldsanalyzer.rb
|
|
72
73
|
- lib/twb/analysis/datasources/datasourcefieldscsvemitter.rb
|