twb 2.2.1 → 3.7.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|