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
@@ -0,0 +1,128 @@
|
|
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 CypherPython
|
22
|
+
|
23
|
+
# @@hasher = Digest::SHA256.new
|
24
|
+
|
25
|
+
@@docfileName = './ttdoc/cypherpython.log'
|
26
|
+
|
27
|
+
#====================================================================
|
28
|
+
|
29
|
+
attr_accessor :nodes, :edges
|
30
|
+
attr_accessor :fileName, :fileName
|
31
|
+
attr_accessor :user, :password
|
32
|
+
attr_accessor :cleanup
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
@docfile = File.open(@@docfileName,'a+')
|
36
|
+
@docfile.puts "Starting up the Cypher in Python process"
|
37
|
+
@fileName = 'Neo4jCypherPython'
|
38
|
+
@user = 'neo4j'
|
39
|
+
@password = 'imthepwd2oo'
|
40
|
+
@nodes = []
|
41
|
+
@edges = []
|
42
|
+
@cleanup = false
|
43
|
+
end
|
44
|
+
|
45
|
+
def render
|
46
|
+
@file = File.open("./ttdoc/#{@fileName}.py",'w')
|
47
|
+
@file.puts '# -*- coding: latin-1 -*-'
|
48
|
+
@file.puts ' '
|
49
|
+
@file.puts 'from py2neo import Graph'
|
50
|
+
@file.puts "graph = Graph('http://localhost:7474/db/data', user='#{@user}', password='#{@password}')"
|
51
|
+
@file.puts ' '
|
52
|
+
renderNodes
|
53
|
+
renderEdges
|
54
|
+
@file.close
|
55
|
+
return @file
|
56
|
+
end
|
57
|
+
|
58
|
+
def renderNodes
|
59
|
+
csv = CSV.open("./ttdoc/#{@fileName}.py.nodes.csv",'w')
|
60
|
+
csv << ['Type','Name','UUID']
|
61
|
+
nodesCSV = Set.new
|
62
|
+
nodeCmds = SortedSet.new
|
63
|
+
nodesByType = Hash.new { |type,nodes| type[nodes] = [] }
|
64
|
+
@nodes.each do |node|
|
65
|
+
nodesCSV << [node.type, node.name, node.uuid]
|
66
|
+
nodeCmds << encodeNode('MERGE','node',node,';')
|
67
|
+
nodesByType[node.type] << node
|
68
|
+
end
|
69
|
+
if @cleanup
|
70
|
+
nodesByType.keys.each do |type|
|
71
|
+
@file.puts "DROP CONSTRAINT ON (node:#{type}) ASSERT node.uuid IS UNIQUE ;"
|
72
|
+
end
|
73
|
+
@file.puts "MATCH (n) DETACH DELETE n ;"
|
74
|
+
nodesByType.keys.each do |type|
|
75
|
+
@file.puts "CREATE CONSTRAINT ON (node:#{type}) ASSERT node.uuid IS UNIQUE ;"
|
76
|
+
end
|
77
|
+
@file.puts "//--"
|
78
|
+
end
|
79
|
+
nodesCSV.each do |rec|
|
80
|
+
csv << rec
|
81
|
+
end
|
82
|
+
nodeCmds.each do |cmd|
|
83
|
+
@file.puts cmd
|
84
|
+
end
|
85
|
+
csv.close
|
86
|
+
end
|
87
|
+
# USING PERIODIC COMMIT
|
88
|
+
# LOAD CSV WITH HEADERS FROM "file:://C:/tech/Tableau/Tableau Tools/Ruby/experiments/GraphElements.nodes.csv" AS row
|
89
|
+
# CREATE (:row.Type {name: row.Name, uuid: row.UUID});
|
90
|
+
|
91
|
+
def renderEdges
|
92
|
+
csv = CSV.open("./ttdoc/#{@fileName}.edges.csv",'w')
|
93
|
+
csv << ['Source Type' , 'Source Name' , 'Source UUID' , 'Relationship', 'Target Type', 'Target Name', 'Target UUID' ]
|
94
|
+
@edges.each do |edge|
|
95
|
+
relationship = edge.relationship.upcase.gsub(/[ ]+/,'_')
|
96
|
+
csv << [edge.from.type, edge.from.name, edge.from.uuid, relationship , edge.to.type , edge.to.name, edge.to.uuid ]
|
97
|
+
@file.puts ' '
|
98
|
+
@file.puts 'query = """'
|
99
|
+
@file.puts encodeEdge('MATCH', 'source', edge.from)
|
100
|
+
@file.puts encodeEdge('MATCH', 'target', edge.to)
|
101
|
+
@file.puts "%-8s (source)-[r:%s]->(target) " % ['MERGE', edge.relationship.upcase.gsub(/[ ]+/,'_')]
|
102
|
+
@file.puts "RETURN source.name, type(r), target.name ;"
|
103
|
+
@file.puts '"""'
|
104
|
+
@file.puts 'graph.run(query)'
|
105
|
+
@file.puts "print '-',"
|
106
|
+
end
|
107
|
+
csv.close
|
108
|
+
end
|
109
|
+
|
110
|
+
def encodeNode command, varName, node, terminator=''
|
111
|
+
# "g.run('MERGE (node:CalculatedField { name:\"YTD Cost Amount\", uuid: \"ccd4f66d0c8ee09eca10ab3a1adabe35\" } ) ');"
|
112
|
+
# "g.run"
|
113
|
+
"graph.run( \"%-8s (%s:%s { name:'%s', uuid: '%s' } ) %s\")\nprint '.'," % [command, varName, node.type, node.name.gsub('"','\"'), node.uuid, terminator ]
|
114
|
+
end
|
115
|
+
|
116
|
+
def encodeEdge command, varName, node, terminator=''
|
117
|
+
"%-8s (%s:%s { uuid: '%s' } ) %s" % [command, varName, node.type, node.uuid, terminator ]
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_s
|
121
|
+
"file:#{@fileName}; #nodes:#{@nodes.length}; #edges:#{@edges.length}"
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end # module Util
|
128
|
+
end # module Twb
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Copyright (C) 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
|
+
module Twb
|
17
|
+
module Util
|
18
|
+
|
19
|
+
class DocPrep
|
20
|
+
|
21
|
+
@@dir = './ttdoc'
|
22
|
+
|
23
|
+
attr_accessor :dir
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
reset
|
27
|
+
end
|
28
|
+
|
29
|
+
def reset
|
30
|
+
@dir = @@dir
|
31
|
+
init
|
32
|
+
end
|
33
|
+
|
34
|
+
def prepFile fileName
|
35
|
+
"#{@dir}/#{fileName}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def init dirName
|
39
|
+
Dir.mkdir @Name
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
end # class DocPrep
|
44
|
+
|
45
|
+
end # module Util
|
46
|
+
end # module Twb
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# Copyright (C) 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
|
+
module Twb
|
17
|
+
module Util
|
18
|
+
|
19
|
+
require 'creek'
|
20
|
+
require 'csv'
|
21
|
+
|
22
|
+
class FieldDomainLoader
|
23
|
+
|
24
|
+
@@xmlLocation = './ttdoc'
|
25
|
+
|
26
|
+
attr_reader :domains
|
27
|
+
attr_accessor :xmllocation, :workboook, :datasource, :csvOption
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
reset
|
31
|
+
end
|
32
|
+
|
33
|
+
def reset
|
34
|
+
@workbok = nil
|
35
|
+
@xmllocation = @@xmlLocation
|
36
|
+
@csvOption = 'w'
|
37
|
+
initCSV @csvOption
|
38
|
+
end
|
39
|
+
|
40
|
+
def initCSV opt
|
41
|
+
@csvFile = CSV.open(@xmllocation + '/TwbFieldDomains.csv', opt )
|
42
|
+
if 'w'.eql? opt
|
43
|
+
@csvFile << ['Workbook', 'Data Source', 'Field', 'Value']
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def load
|
48
|
+
path = @xmllocation + '/*.xlsx'
|
49
|
+
Dir.glob(path) do |fileName|
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def loadWorkbook twb
|
54
|
+
@workbook = twb.name
|
55
|
+
dsFieldDomains = {}
|
56
|
+
dss = twb.datasources
|
57
|
+
dsFieldDomains = {}
|
58
|
+
dss.each do |ds|
|
59
|
+
fieldDomains = loadDataSource ds
|
60
|
+
dsFieldDomains[ds.uiname] = fieldDomains
|
61
|
+
end
|
62
|
+
return dsFieldDomains
|
63
|
+
end
|
64
|
+
|
65
|
+
def loadDataSource ds
|
66
|
+
@datasource = ds.uiname
|
67
|
+
fieldDomains = loadxlsx(@xmllocation + '/' + @datasource + '.xlsx')
|
68
|
+
end
|
69
|
+
|
70
|
+
def loadxlsx fileName
|
71
|
+
fieldDomains = {}
|
72
|
+
if File.file?(fileName)
|
73
|
+
xlsx = Creek::Book.new fileName
|
74
|
+
sheets = xlsx.sheets
|
75
|
+
sheets.each do |sheet|
|
76
|
+
rows = sheet.rows.to_a
|
77
|
+
if rows.count > 1
|
78
|
+
fieldValues = parseRows(rows)
|
79
|
+
unless fieldValues.empty? || fieldValues.values.first.empty?
|
80
|
+
fieldDomains[fieldValues.keys.first] = fieldValues.values.first
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
else
|
85
|
+
puts "#### ALERT #### XLSX file does not exist: #{fileName}"
|
86
|
+
end
|
87
|
+
return fieldDomains
|
88
|
+
end
|
89
|
+
|
90
|
+
def parseRows rows
|
91
|
+
fieldValues = {}
|
92
|
+
unless rows.empty?
|
93
|
+
firstRow = rows[0].to_a[0]
|
94
|
+
fieldName = firstRow[1].to_s
|
95
|
+
fieldValues[fieldName] = SortedSet.new
|
96
|
+
values = rows[1..-1]
|
97
|
+
values.each do |row|
|
98
|
+
value = row.to_a[0][1].to_s
|
99
|
+
fieldValues[fieldName] << value
|
100
|
+
end
|
101
|
+
end
|
102
|
+
return fieldValues
|
103
|
+
end
|
104
|
+
|
105
|
+
end # class FieldDomainLoader
|
106
|
+
|
107
|
+
end # module Util
|
108
|
+
end # module Twb
|
data/lib/twb/util/gml.rb
ADDED
@@ -0,0 +1,144 @@
|
|
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 'digest/md5'
|
17
|
+
|
18
|
+
module Twb
|
19
|
+
module Util
|
20
|
+
|
21
|
+
class GML
|
22
|
+
|
23
|
+
include TabTool
|
24
|
+
|
25
|
+
@@hasher = Digest::SHA256.new
|
26
|
+
|
27
|
+
@@docfileName = './ttdoc/gml.log'
|
28
|
+
|
29
|
+
#====================================================================
|
30
|
+
@@gmlHeader = <<GMLHEADER
|
31
|
+
graph [
|
32
|
+
directed 1
|
33
|
+
rankdir "LR"
|
34
|
+
splines "line"
|
35
|
+
|
36
|
+
GMLHEADER
|
37
|
+
|
38
|
+
@@gmlFooter = "\n]"
|
39
|
+
|
40
|
+
attr_accessor :nodes, :edges, :fileName, :gmlHeader
|
41
|
+
|
42
|
+
def initialize
|
43
|
+
# @docFile = File.open(@@docfileName,'w')
|
44
|
+
# @docFile.puts "Starting up the GML process"
|
45
|
+
@gmlHeader = @@gmlHeader
|
46
|
+
@fileName = 'gmlFile'
|
47
|
+
@nodes = SortedSet.new
|
48
|
+
@edges = SortedSet.new
|
49
|
+
end
|
50
|
+
|
51
|
+
# def gmlHeader=(text)
|
52
|
+
# @gmlHeader = text
|
53
|
+
# end
|
54
|
+
|
55
|
+
# def init fileName
|
56
|
+
# # do stuff for new GML file here
|
57
|
+
# @fileName = fileName
|
58
|
+
# prepare
|
59
|
+
# end
|
60
|
+
|
61
|
+
def prepare
|
62
|
+
@nodes = SortedSet.new
|
63
|
+
@edges = SortedSet.new
|
64
|
+
end
|
65
|
+
|
66
|
+
def render
|
67
|
+
# puts "GML.render - rendering into #{@fileName}"
|
68
|
+
file = File.open(docFile("#{@fileName}.gml"),'w')
|
69
|
+
file.puts @gmlHeader
|
70
|
+
renderNodes file
|
71
|
+
renderEdges file
|
72
|
+
file.puts @@gmlFooter
|
73
|
+
file.close
|
74
|
+
return file
|
75
|
+
end
|
76
|
+
|
77
|
+
def renderNodes file
|
78
|
+
nodes = Set.new
|
79
|
+
@nodes.each do |node|
|
80
|
+
gmlID = Digest::MD5.hexdigest(node.id)
|
81
|
+
gmlName = node.name.gsub('&','&').gsub('"','"')
|
82
|
+
nodes << "node [\n id \"#{gmlID}\" \n label \"#{gmlName}\" \n ]"
|
83
|
+
end
|
84
|
+
nodes.each do |node|
|
85
|
+
file.puts node
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def renderEdges file
|
90
|
+
edges = Set.new
|
91
|
+
@edges.each do |edge|
|
92
|
+
gmlSourceID = Digest::MD5.hexdigest(edge.from.id)
|
93
|
+
gmlTargetID = Digest::MD5.hexdigest(edge.to.id)
|
94
|
+
edges << "edge [\n source \"#{gmlSourceID}\" \n target \"#{gmlTargetID}\" \n ]"
|
95
|
+
end
|
96
|
+
edges.each do |edge|
|
97
|
+
file.puts edge
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def to_s
|
102
|
+
"file:#{@fileName}; #nodes:#{@nodes.length}; #edges:#{@edges.length}"
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end # module Util
|
109
|
+
end # module Twb
|
110
|
+
|
111
|
+
|
112
|
+
# node [
|
113
|
+
# id 7
|
114
|
+
# label "5"
|
115
|
+
# edgeAnchor "corners"
|
116
|
+
# labelAnchor "n"
|
117
|
+
# graphics [
|
118
|
+
# center [ x 82.0000 y 42.0000 ]
|
119
|
+
# w 16.0000
|
120
|
+
# h 16.0000
|
121
|
+
# type "rectangle"
|
122
|
+
# fill "#000000"
|
123
|
+
# ]
|
124
|
+
# ]
|
125
|
+
# edge [
|
126
|
+
# label "24"
|
127
|
+
# labelAnchor "first"
|
128
|
+
# source 7
|
129
|
+
# target 15
|
130
|
+
# graphics [
|
131
|
+
# type "line"
|
132
|
+
# arrow "last"
|
133
|
+
# Line [
|
134
|
+
# point [ x 82.0000 y 42.0000 ]
|
135
|
+
# point [ x 10.0000 y 10.0000 ]
|
136
|
+
# point [ x 100.000 y 100.000 ]
|
137
|
+
# point [ x 80.0000 y 30.0000 ]
|
138
|
+
# point [ x 120.000 y 230.000 ]
|
139
|
+
# point [ x 73.0000 y 160.000 ]
|
140
|
+
# ]
|
141
|
+
# ]
|
142
|
+
# ]
|
143
|
+
|
144
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Copyright (C) 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
|
+
module Twb
|
17
|
+
module Util
|
18
|
+
|
19
|
+
class GMLedge
|
20
|
+
|
21
|
+
# @from - the origin node
|
22
|
+
# @to - the destination node
|
23
|
+
# @relationship - useful for categorizing the edge
|
24
|
+
# @properties - useful for categorizing the edge
|
25
|
+
attr_reader :from, :to, :relationship
|
26
|
+
attr_accessor :properties
|
27
|
+
attr_reader :cypherCreate
|
28
|
+
|
29
|
+
# Neo4J cypher variable quote character: `
|
30
|
+
|
31
|
+
def initialize (from:, to:, relationship:, properties: {})
|
32
|
+
raise ArgumentError.new("from: parameter must be a Graphnode, is a '#{from.class}'") unless from.is_a? Twb::Util::Graphnode
|
33
|
+
raise ArgumentError.new( "to: parameter must be a Graphnode, is a '#{to.class}'" ) unless to.is_a? Twb::Util::Graphnode
|
34
|
+
@from = from
|
35
|
+
@to = to
|
36
|
+
@relationship = relationship
|
37
|
+
@properties = properties
|
38
|
+
@cypherCreate = "CREATE #{cypher_s}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def eql? other
|
42
|
+
@from == other.from && @to == other.to && @relationship == other.relationship && @properties == other.properties
|
43
|
+
end
|
44
|
+
|
45
|
+
def hash
|
46
|
+
[@from.hash, @to.hash, @relationship, @properties].hash
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
"'#{@from.name}//{@from.id}' --#{@relationship}--> '#{@to.name}//#{@to.id}'"
|
51
|
+
end
|
52
|
+
|
53
|
+
def dot
|
54
|
+
"%s -> %s" % [dotquote(from.id), dotquote(to.id)]
|
55
|
+
end
|
56
|
+
|
57
|
+
def dotquote str
|
58
|
+
ns = str.gsub(/(["])/,'\\"')
|
59
|
+
return "\"#{ns}\""
|
60
|
+
end
|
61
|
+
|
62
|
+
def cypher_s
|
63
|
+
"(%s)-[:`%s`]->(%s)" % [@from.cypherID,@relationship,@to.cypherID]
|
64
|
+
end
|
65
|
+
|
66
|
+
def gml
|
67
|
+
"%s -> %s" % [dotquote(from.id), dotquote(to.id)]
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end # module Util
|
73
|
+
end # module Twb
|