Skip to content

Commit

Permalink
Node grouping support in graphs, fixes noflo#62
Browse files Browse the repository at this point in the history
  • Loading branch information
bergie committed Nov 5, 2013
1 parent 073eb25 commit 87b6f24
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ NoFlo ChangeLog
* Component Loader is able to load arbitrary graphs outside of the normal package manifest registration via the `loadGraph` method
* Libraries can provide a custom loader for their components by registering a `noflo.loader` key in the manifest pointing to a CommonJS module
* Exported ports can now contain metadata
* It is possible to create named groups of nodes in a NoFlo graph, which can be useful for visual editors

## 0.4.2 (September 28th 2013)

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"grunt-tagrelease": "~0.2.0",
"grunt-exec": "~0.4.0",
"grunt-cafe-mocha": "~0.1.2",
"chai": "~1.5.0",
"chai": "~1.8.0",
"mocha": "~1.9.0",
"grunt-mocha-phantomjs": "~0.2.2",
"grunt-component-build": "~0.2.7",
Expand Down
44 changes: 42 additions & 2 deletions spec/Graph.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ describe 'Graph', ->
public: 'out'
private: 'bar.out'
]
groups: [
nodes: ['Foo', 'Bar']
metadata:
label: 'Main'
]
processes:
Foo:
component: 'Bar'
Expand Down Expand Up @@ -139,8 +144,10 @@ describe 'Graph', ->
chai.expect(g.initializers.length).to.equal 1
it 'should contain two exports', ->
chai.expect(g.exports.length).to.equal 2
it 'should contain one group', ->
chai.expect(g.edges.length).to.equal 1
it 'should produce same JSON when serialized', ->
chai.expect(g.toJSON()).to.eql json
chai.expect(g.toJSON()).to.deep.equal json
describe 'renaming a node', ->
it 'should emit an event', (done) ->
g.once 'renameNode', (oldId, newId) ->
Expand All @@ -157,6 +164,17 @@ describe 'Graph', ->
for edge in g.edges
connection = edge if edge.from.node is 'Baz'
chai.expect(connection).to.be.an 'object'
it 'should still be exported', ->
exports = 0
for exported in g.exports
[exportedNode, exportedPort] = exported.private.split '.'
exports++ if exportedNode is 'baz'
chai.expect(exports).to.equal 1
it 'should still be grouped', ->
groups = 0
for group in g.groups
groups++ if group.nodes.indexOf('Baz') isnt -1
chai.expect(groups).to.equal 1
it 'shouldn\'t be have edges with the old name', ->
connection = null
for edge in g.edges
Expand All @@ -171,8 +189,19 @@ describe 'Graph', ->
it 'shouldn\'t have IIPs going to the old name', ->
iip = null
for edge in g.initializers
iip = edge if edge.to.node is 'foo'
iip = edge if edge.to.node is 'Foo'
chai.expect(iip).to.be.a 'null'
it 'shouldn\'t be have export going to the old name', ->
exports = 0
for exported in g.exports
[exportedNode, exportedPort] = exported.private.split '.'
exports++ if exportedNode is 'foo'
chai.expect(exports).to.equal 0
it 'shouldn\'t be grouped with the old name', ->
groups = 0
for group in g.groups
groups++ if group.nodes.indexOf('Foo') isnt -1
chai.expect(groups).to.equal 0
describe 'removing a node', ->
it 'should emit an event', (done) ->
g.once 'removeNode', (node) ->
Expand All @@ -190,6 +219,17 @@ describe 'Graph', ->
for edge in g.initializers
connections++ if edge.to.node is 'Baz'
chai.expect(connections).to.equal 0
it 'shouldn\'t be have exports left behind', ->
exports = 0
for exported in g.exports
[exportedNode, exportedPort] = exported.private.split '.'
exports++ if exportedNode is 'baz'
chai.expect(exports).to.equal 0
it 'shouldn\'t be grouped', ->
groups = 0
for group in g.groups
groups++ if group.nodes.indexOf('Baz') isnt -1
chai.expect(groups).to.equal 0

describe 'with multiple connected ArrayPorts', ->
g = new graph.Graph
Expand Down
63 changes: 61 additions & 2 deletions src/lib/Graph.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Graph extends EventEmitter
edges: []
initializers: []
exports: []
groups: []

# ## Creating new graphs
#
Expand All @@ -38,6 +39,7 @@ class Graph extends EventEmitter
@edges = []
@initializers = []
@exports = []
@groups = []

# ## Exporting a port from subgraph
#
Expand All @@ -49,6 +51,26 @@ class Graph extends EventEmitter
public: publicPort.toLowerCase()
metadata: metadata

removeExport: (publicPort) ->
for exported in @exports
continue unless exported
continue unless exported.public is publicPort
@exports.splice @exports.indexOf(exported), 1

# ## Grouping nodes in a graph
#
addGroup: (group, nodes, metadata) ->
@groups.push
name: group
nodes: nodes
metadata: metadata

removeGroup: (group) ->
for group in @groups
continue unless group
continue unless group.name is group
@groups.splice @groups.indexOf(group), 1

# ## Adding a node to the graph
#
# Nodes are identified by an ID unique to the graph. Additionally,
Expand Down Expand Up @@ -96,6 +118,18 @@ class Graph extends EventEmitter
if initializer.to.node is node.id
@removeInitial initializer.to.node, initializer.to.port

for exported in @exports
continue unless exported
[privateNode, privatePort] = exported.private.split '.'
if privateNode is id.toLowerCase()
@removeExport exported.public

for group in @groups
continue unless group
index = group.nodes.indexOf(id) is -1
continue if index is -1
group.nodes.splice index, 1

if -1 isnt @nodes.indexOf node
@nodes.splice @nodes.indexOf(node), 1

Expand Down Expand Up @@ -132,6 +166,18 @@ class Graph extends EventEmitter
if iip.to.node is oldId
iip.to.node = newId

for exported in @exports
continue unless exported
[privateNode, privatePort] = exported.private.split '.'
continue unless privateNode is oldId.toLowerCase()
exported.private = "#{newId.toLowerCase()}.#{privatePort}"

for group in @groups
continue unless group
index = group.nodes.indexOf(oldId)
continue if index is -1
group.nodes[index] = newId

@emit 'renameNode', oldId, newId

# ## Connecting nodes
Expand Down Expand Up @@ -266,21 +312,30 @@ class Graph extends EventEmitter
json =
properties: {}
exports: []
groups: []
processes: {}
connections: []

json.properties.name = @name if @name
for property, value of @properties
json.properties[property] = value
json.properties.name = @name if @name

for exported in @exports
exportedData =
private: exported.private
public: exported.public
private: exported.private
if exported.metadata
exportedData.metadata = exported.metadata
json.exports.push exportedData

for group in @groups
groupData =
name: group.name
nodes: group.nodes
if group.metadata
groupData.metadata = group.metadata
json.groups.push groupData

for node in @nodes
json.processes[node.id] =
component: node.component
Expand Down Expand Up @@ -343,6 +398,10 @@ exports.loadJSON = (definition, success) ->
for exported in definition.exports
graph.addExport exported.private, exported.public, exported.metadata

if definition.groups
for group in definition.groups
graph.addGroup group.name, group.nodes, group.metadata

success graph

exports.loadFBP = (fbpData, success) ->
Expand Down

0 comments on commit 87b6f24

Please sign in to comment.