twb 2.2.1 → 3.7.2
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 +13 -1
- data/lib/twb/action.rb +5 -1
- data/lib/twb/analysis/AnnotatedFieldsCSVEmitter.rb +3 -0
- data/lib/twb/analysis/CalculatedFields/CalculatedFieldsAnalyzer.rb +276 -287
- data/lib/twb/analysis/CalculatedFields/MarkdownEmitter.rb +48 -34
- data/lib/twb/analysis/DataSources/DataSourceFieldsCSVEmitter.rb +103 -103
- data/lib/twb/analysis/DataSources/googlesheetdatasourcesanalyzer.rb +79 -0
- data/lib/twb/analysis/DocumentedFieldsMarkdownEmitter.rb +1 -1
- data/lib/twb/analysis/Sheets/sheetfieldsanalyzer.rb +82 -0
- data/lib/twb/analysis/Sheets/sheetfiltersanalyzer.rb +214 -0
- data/lib/twb/calculatedfield.rb +20 -5
- data/lib/twb/codedfield.rb +87 -0
- data/lib/twb/columnfield.rb +21 -2
- data/lib/twb/connection.rb +33 -0
- data/lib/twb/dashboard.rb +5 -1
- data/lib/twb/datasource.rb +131 -20
- data/lib/twb/dbfield.rb +4 -0
- data/lib/twb/field.rb +5 -1
- data/lib/twb/fieldcalculation.rb +134 -78
- data/lib/twb/localfield.rb +5 -1
- data/lib/twb/mappedfield.rb +5 -1
- data/lib/twb/metadatafield.rb +5 -1
- data/lib/twb/storyboard.rb +5 -1
- data/lib/twb/tabclass.rb +71 -0
- data/lib/twb/tabtest.rb +31 -0
- data/lib/twb/tabtool.rb +63 -0
- data/lib/twb/twbcodedfield.rb +87 -0
- data/lib/twb/util/cypher.rb +112 -0
- data/lib/twb/util/cypherpython.rb +128 -0
- data/lib/twb/util/docprep.rb +46 -0
- data/lib/twb/util/fielddomainloader.rb +108 -0
- data/lib/twb/util/gml.rb +144 -0
- data/lib/twb/util/gmledge.rb +73 -0
- data/lib/twb/util/graph.rb +30 -0
- data/lib/twb/util/graphedge.rb +8 -9
- data/lib/twb/util/graphnode.rb +46 -29
- data/lib/twb/util/tabgraph.rb +30 -0
- data/lib/twb/window.rb +5 -1
- data/lib/twb/workbook.rb +18 -5
- data/lib/twb/worksheet.rb +5 -1
- data/test/fieldAliases.rb +10 -0
- data/test/testFieldAliases.rb +65 -0
- data/test/testFieldDomainLoaded.rb +14 -0
- data/test/testFieldDomainLoader.rb +131 -0
- metadata +22 -1
data/lib/twb/localfield.rb
CHANGED
@@ -19,7 +19,7 @@ module Twb
|
|
19
19
|
|
20
20
|
# Assumption: A field can only be either a MetadataField or a LocalField, not both in a given Workbook data connection.
|
21
21
|
|
22
|
-
class LocalField
|
22
|
+
class LocalField < TabClass
|
23
23
|
|
24
24
|
attr_reader :node, :type, :datatype, :name, :uiname, :hidden, :ordinal, :properties
|
25
25
|
|
@@ -44,6 +44,10 @@ module Twb
|
|
44
44
|
# return self
|
45
45
|
end
|
46
46
|
|
47
|
+
def id
|
48
|
+
@id ||= @id = @name.hash
|
49
|
+
end
|
50
|
+
|
47
51
|
def properties
|
48
52
|
@properties ||= loadProperties
|
49
53
|
end
|
data/lib/twb/mappedfield.rb
CHANGED
@@ -17,7 +17,7 @@ require 'nokogiri'
|
|
17
17
|
|
18
18
|
module Twb
|
19
19
|
|
20
|
-
class DbField
|
20
|
+
class DbField < TabClass
|
21
21
|
|
22
22
|
include Comparable
|
23
23
|
|
@@ -37,6 +37,10 @@ module Twb
|
|
37
37
|
@id = "#{dataSource}::#{dbname}::#{dbtable}::#{uiname}"
|
38
38
|
end
|
39
39
|
|
40
|
+
def id
|
41
|
+
@id ||= @id = @name.hash
|
42
|
+
end
|
43
|
+
|
40
44
|
def properties
|
41
45
|
@properties ||= loadProperties
|
42
46
|
end
|
data/lib/twb/metadatafield.rb
CHANGED
@@ -17,7 +17,7 @@ require 'nokogiri'
|
|
17
17
|
|
18
18
|
module Twb
|
19
19
|
|
20
|
-
class MetadataField
|
20
|
+
class MetadataField < TabClass
|
21
21
|
|
22
22
|
include Comparable
|
23
23
|
|
@@ -78,6 +78,10 @@ module Twb
|
|
78
78
|
@id = "'%s::%s' " % [@table,@remoteName]
|
79
79
|
end
|
80
80
|
|
81
|
+
def id
|
82
|
+
@id ||= @id = @name.hash
|
83
|
+
end
|
84
|
+
|
81
85
|
def properties
|
82
86
|
@properties ||= loadProperties
|
83
87
|
end
|
data/lib/twb/storyboard.rb
CHANGED
@@ -18,7 +18,7 @@ require 'digest/md5'
|
|
18
18
|
|
19
19
|
module Twb
|
20
20
|
|
21
|
-
class Storyboard
|
21
|
+
class Storyboard < TabClass
|
22
22
|
|
23
23
|
@@hasher = Digest::SHA256.new
|
24
24
|
|
@@ -31,6 +31,10 @@ module Twb
|
|
31
31
|
loadSheets
|
32
32
|
end
|
33
33
|
|
34
|
+
def id
|
35
|
+
@id ||= @id = @name.hash
|
36
|
+
end
|
37
|
+
|
34
38
|
def loadSheets
|
35
39
|
@sheets = {}
|
36
40
|
sheets = @node.xpath('.//story-point').to_a
|
data/lib/twb/tabclass.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Copyright (C) 2014, 2015, 2016 Chris Gerrard
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'logger'
|
17
|
+
|
18
|
+
module Twb
|
19
|
+
|
20
|
+
class TabClass
|
21
|
+
|
22
|
+
attr_accessor :uuid, :type, :id, :properties, :ttlogfile, :ttlogfilename
|
23
|
+
|
24
|
+
@@ttlogfilename = 'TableauTools.ttlog'
|
25
|
+
@@ttdocdir = './ttdoc'
|
26
|
+
@localEmit = false
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@ttlogfile = 'TableauTools.ttlog'
|
30
|
+
@logger = Logger.new(@ttlogfile)
|
31
|
+
@logger.level = Logger::DEBUG
|
32
|
+
end
|
33
|
+
|
34
|
+
def type
|
35
|
+
@type ||= @type = self.class.to_s.split(/(?=[A-Z])/).join(' ')
|
36
|
+
end
|
37
|
+
|
38
|
+
def uuid
|
39
|
+
@uuid ||= @uuid = SecureRandom.uuid
|
40
|
+
end
|
41
|
+
|
42
|
+
def properties
|
43
|
+
{}
|
44
|
+
end
|
45
|
+
|
46
|
+
def setDocFileName
|
47
|
+
docFile @@ttlogfilename
|
48
|
+
end
|
49
|
+
|
50
|
+
def docFile name
|
51
|
+
@ttdocdir.nil? ? name : "#{@@ttdocdir}/#{name}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def emit(local=@localEmit, stuff)
|
55
|
+
# puts "\nstuff.class #{stuff.class} :: #{stuff}" if local
|
56
|
+
if stuff.is_a? String then
|
57
|
+
lines = stuff.split(/\n/)
|
58
|
+
lines.each do |line|
|
59
|
+
@logger.debug "#{@emitPrefix}#{line}"
|
60
|
+
puts "#{@emitPrefix}#{line}" if local
|
61
|
+
end
|
62
|
+
else
|
63
|
+
@logger.debug "#{@emitPrefix}#{stuff}"
|
64
|
+
puts "#{@emitPrefix}#{stuff}" if local
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
data/lib/twb/tabtest.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Copyright (C) 2014, 2015, 2016 Chris Gerrard
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'tabtool'
|
17
|
+
|
18
|
+
module Twb
|
19
|
+
|
20
|
+
class TabToolTest
|
21
|
+
include TabTool
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@ttlogfile = 'TableauTools.ttlog'
|
25
|
+
@logger = Logger.new(@ttlogfile)
|
26
|
+
@logger.level = Logger::DEBUG
|
27
|
+
end
|
28
|
+
|
29
|
+
end # class TabToolTest
|
30
|
+
|
31
|
+
end # module Twb
|
data/lib/twb/tabtool.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# Copyright (C) 2014, 2018 Chris Gerrard
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'logger'
|
17
|
+
|
18
|
+
module TabTool
|
19
|
+
|
20
|
+
attr_accessor :ttdocdir, :logger, :loglevel, :logfilename
|
21
|
+
attr_reader :funcdoc, :docfiles
|
22
|
+
|
23
|
+
TTDOCDIR = './ttdoc'
|
24
|
+
|
25
|
+
@funcdoc = {:class=>nil, :blurb=>nil, :description=>nil,}
|
26
|
+
@docfiles = {}
|
27
|
+
|
28
|
+
@ttdocdir = './ttdoc'
|
29
|
+
@logfilename = 'TabTools.ttlog'
|
30
|
+
@loglevel = Logger::DEBUG
|
31
|
+
@localEmit = false
|
32
|
+
|
33
|
+
def funcdoc
|
34
|
+
@funcdoc.nil? ? {:class=>'n/a', :blurb=>'generic TabTool blurb', :description=>'A useful Tableau Tool.'} : @funcdoc
|
35
|
+
end
|
36
|
+
|
37
|
+
def docFile name
|
38
|
+
# emit "docFile: TTDOCDIR: #{TTDOCDIR} name:'#{name}'"
|
39
|
+
TTDOCDIR.nil? ? name : "#{TTDOCDIR}/#{name}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def emit(local=@localEmit, stuff)
|
43
|
+
initLogger if @logger.nil?
|
44
|
+
if stuff.is_a? String then
|
45
|
+
lines = stuff.split(/\n/)
|
46
|
+
lines.each do |line|
|
47
|
+
@logger.debug "#{@emitPrefix}#{line}"
|
48
|
+
puts "#{@emitPrefix}#{line}" if local
|
49
|
+
end
|
50
|
+
else
|
51
|
+
@logger.debug "#{@emitPrefix}#{stuff}"
|
52
|
+
puts "#{@emitPrefix}#{stuff}" if local
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def initLogger
|
57
|
+
lfn = docFile("#{self.class.to_s.split('::').last}.ttlog")
|
58
|
+
@logger = Logger.new(lfn)
|
59
|
+
@logger.level = Logger::DEBUG
|
60
|
+
end
|
61
|
+
|
62
|
+
end # module TabTool
|
63
|
+
|
@@ -0,0 +1,87 @@
|
|
1
|
+
class CodedField
|
2
|
+
|
3
|
+
include Comparable
|
4
|
+
|
5
|
+
attr_reader :name, :techCode
|
6
|
+
attr_reader :uiname, :uiCode
|
7
|
+
attr_reader :dataSource, :dataSourceName, :dataSourceRef, :dataSourceExists
|
8
|
+
attr_reader :fqName, :type
|
9
|
+
attr_reader :techUIdiff
|
10
|
+
|
11
|
+
def initialize code, datasource
|
12
|
+
# puts "\n\nCalculationField :: %-25s | %s " % [datasource.uiname, code]
|
13
|
+
@dataSource = datasource
|
14
|
+
@dataSourceName = datasource.uiname
|
15
|
+
@dataSourceRef = :local
|
16
|
+
@dataSourceExists = true
|
17
|
+
@techUIdiff = false
|
18
|
+
@uiname = ''
|
19
|
+
rawCode = code.gsub(/^\[|\]$/,'')
|
20
|
+
parts = rawCode.split('].[')
|
21
|
+
#puts "Field: #{code} \t parts: #{parts.length} - #{parts.inspect}"
|
22
|
+
if parts.length == 1
|
23
|
+
@name = parts[0]
|
24
|
+
@techCode = "[#{parts[0]}]"
|
25
|
+
#puts "@name: #{@name}"
|
26
|
+
if datasource.nil?
|
27
|
+
# puts 'a'
|
28
|
+
@uiname = @name
|
29
|
+
@uiCode = @techCode
|
30
|
+
@techUIdiff = false
|
31
|
+
else # !datasource.nil?
|
32
|
+
# puts 'b'
|
33
|
+
#puts "b - found uiname for '#{@name}'?: #{!datasource.fieldUIName(@name).nil?} \t is:#{datasource.fieldUIName(@name)} "
|
34
|
+
@uiname = datasource.fieldUIName(@name).nil? ? @name : datasource.fieldUIName(@name)
|
35
|
+
@uiCode = @uiname.nil? ? @techCode : "[#{@uiname}]"
|
36
|
+
@techUIdiff = !@techCode.eql?(@uiCode)
|
37
|
+
# puts ":b #{datasource.fieldUIName(@name).nil?} ... #{@name} ... #{@uiname}"
|
38
|
+
# puts "CalculationField :: uin: %-25s | @name:%-s" % [@uiname,@name]
|
39
|
+
end
|
40
|
+
else # parts.length <> 1
|
41
|
+
# puts 'c'
|
42
|
+
rdstech = parts[0]
|
43
|
+
calcField = parts[1]
|
44
|
+
@uiname = calcField
|
45
|
+
@dataSourceName = rdstech
|
46
|
+
@dataSourceRef = :remote
|
47
|
+
@techCode = "[#{rdstech}].[#{calcField}]"
|
48
|
+
workbook = datasource.workbook
|
49
|
+
@dataSource = workbook.nil? ? nil : workbook.datasource(rdstech)
|
50
|
+
# puts "\t twb: #{workbook.class} / remoteds: #{remoteds.class} : #{remoteds.nil? ? "<<NOT FOUND:#{rdstech}:>>" : remoteds.uiname} "
|
51
|
+
#--
|
52
|
+
if @dataSource.nil? || @dataSource.fieldUIName(calcField).nil?
|
53
|
+
# puts 'd'
|
54
|
+
@uiname = calcField
|
55
|
+
@uiCode = "[<<NOT FOUND>>#{rdstech}].[#{calcField}]"
|
56
|
+
@techUIdiff = true
|
57
|
+
@dataSourceExists = false
|
58
|
+
else # !remoteds.nil?
|
59
|
+
# puts 'e'
|
60
|
+
@dataSourceName = @dataSource.uiname
|
61
|
+
@uiname = @dataSource.fieldUIName(calcField)
|
62
|
+
@uiCode = "[#{@dataSourceName}].[#{@uiname}]"
|
63
|
+
@techUIdiff = !@techCode.eql?(@uiCode)
|
64
|
+
@dataSourceExists = true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
# puts "\t dsName: #{@dataSourceName}"
|
68
|
+
# puts "\t @name: #{@name}"
|
69
|
+
# puts "\t uiname: #{@uiname}"
|
70
|
+
@fqName = "#{@dataSourceName}::#{@uiname}"
|
71
|
+
@type = @dataSource.calculatedField(@uiname).nil? ? :DatabaseField : :CalculatedField
|
72
|
+
end # initialize
|
73
|
+
|
74
|
+
def id
|
75
|
+
@id ||= @id = "#{@dataSourceName}::#{@uiname}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def <=>(other)
|
79
|
+
# myName = @uiname.nil? ? '' : @uiname
|
80
|
+
# otherName = other.uiName.nil? ? "" : other.uiName
|
81
|
+
# # puts "#{@uiname} / #{myName} <=> #{otherName} / #{other.uiName}"
|
82
|
+
# # puts "#{@uiname.nil?} // #{other.uiName.nil?}"
|
83
|
+
# myName <=> otherName
|
84
|
+
@fqName <=> other.fqName
|
85
|
+
end
|
86
|
+
|
87
|
+
end # class CalculationField
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# Copyright (C) 2012, 2015 Chris Gerrard
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'csv'
|
17
|
+
|
18
|
+
module Twb
|
19
|
+
module Util
|
20
|
+
|
21
|
+
class Cypher
|
22
|
+
|
23
|
+
include TabTool
|
24
|
+
|
25
|
+
@@hasher = Digest::SHA256.new
|
26
|
+
|
27
|
+
#====================================================================
|
28
|
+
|
29
|
+
attr_accessor :nodes, :edges, :fileName, :fileName
|
30
|
+
attr_accessor :cleanup
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
emit "Cypher.initialize"
|
34
|
+
@fileName = 'Neo4jCommands'
|
35
|
+
@nodes = []
|
36
|
+
@edges = []
|
37
|
+
@cleanup = false
|
38
|
+
end
|
39
|
+
|
40
|
+
def render
|
41
|
+
@file = File.open(docFile("#{@fileName}.cypher"),'w')
|
42
|
+
renderNodes
|
43
|
+
renderEdges
|
44
|
+
@file.close
|
45
|
+
return @file
|
46
|
+
end
|
47
|
+
|
48
|
+
def renderNodes
|
49
|
+
csv = CSV.open(docFile("#{@fileName}.nodes.csv"),'w')
|
50
|
+
csv << ['Type','Name','UUID']
|
51
|
+
nodesCSV = Set.new
|
52
|
+
nodeCmds = SortedSet.new
|
53
|
+
nodesByType = Hash.new { |type,nodes| type[nodes] = [] }
|
54
|
+
@nodes.each do |node|
|
55
|
+
nodesCSV << [node.type, node.name, node.uuid]
|
56
|
+
nodeCmds << encode('MERGE','node',node,';')
|
57
|
+
nodesByType[node.type] << node
|
58
|
+
end
|
59
|
+
if @cleanup
|
60
|
+
nodesByType.keys.each do |type|
|
61
|
+
@file.puts "DROP CONSTRAINT ON (node:#{type}) ASSERT node.uuid IS UNIQUE ;"
|
62
|
+
end
|
63
|
+
@file.puts "MATCH (n) DETACH DELETE n ;"
|
64
|
+
nodesByType.keys.each do |type|
|
65
|
+
@file.puts "CREATE CONSTRAINT ON (node:#{type}) ASSERT node.uuid IS UNIQUE ;"
|
66
|
+
end
|
67
|
+
@file.puts "//--"
|
68
|
+
end
|
69
|
+
nodesCSV.each do |rec|
|
70
|
+
csv << rec
|
71
|
+
end
|
72
|
+
nodeCmds.each do |cmd|
|
73
|
+
@file.puts cmd
|
74
|
+
end
|
75
|
+
csv.close
|
76
|
+
end
|
77
|
+
# USING PERIODIC COMMIT
|
78
|
+
# LOAD CSV WITH HEADERS FROM "file:://C:/tech/Tableau/Tableau Tools/Ruby/experiments/GraphElements.nodes.csv" AS row
|
79
|
+
# CREATE (:row.Type {name: row.Name, uuid: row.UUID});
|
80
|
+
|
81
|
+
def renderEdges
|
82
|
+
csv = CSV.open("./ttdoc/#{@fileName}.edges.csv",'w')
|
83
|
+
csv << ['Source Type' , 'Source Name' , 'Source UUID' , 'Relationship', 'Target Type', 'Target Name', 'Target UUID' ]
|
84
|
+
@edges.each do |edge|
|
85
|
+
relationship = edge.relationship.upcase.gsub(/[ ]+/,'_')
|
86
|
+
csv << [edge.from.type, edge.from.name, edge.from.uuid, relationship , edge.to.type , edge.to.name, edge.to.uuid ]
|
87
|
+
@file.puts ' '
|
88
|
+
@file.puts encodeEdge('MATCH', 'source', edge.from)
|
89
|
+
@file.puts encodeEdge('MATCH', 'target', edge.to)
|
90
|
+
@file.puts "%-8s (source)-[r:%s]->(target) " % ['MERGE', edge.relationship.upcase.gsub(/[ ]+/,'_')]
|
91
|
+
@file.puts "RETURN source.name, type(r), target.name ;"
|
92
|
+
end
|
93
|
+
csv.close
|
94
|
+
end
|
95
|
+
|
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 ]
|
98
|
+
end
|
99
|
+
|
100
|
+
def encodeEdge command, varName, node, terminator=''
|
101
|
+
"%-8s (%s:%s { uuid: '%s' } ) %s" % [command, varName, node.type, node.uuid, terminator ]
|
102
|
+
end
|
103
|
+
|
104
|
+
def to_s
|
105
|
+
"file:#{@fileName}; #nodes:#{@nodes.length}; #edges:#{@edges.length}"
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end # module Util
|
112
|
+
end # module Twb
|