noflo
Version:
Flow-Based Programming environment for JavaScript
159 lines (129 loc) • 4.85 kB
text/coffeescript
noflo = require "../lib/NoFlo"
class Graph extends noflo.Component
constructor: (@metadata) ->
@network = null
@ready = true
@started = false
@baseDir = null
@loader = null
@inPorts = new noflo.InPorts
graph:
datatype: 'all'
description: 'NoFlo graph definition to be used with the subgraph component'
required: true
immediate: true
@outPorts = new noflo.OutPorts
@inPorts.on 'graph', 'data', (data) =>
@setGraph data
setGraph: (graph) ->
@ready = false
if typeof graph is 'object'
if typeof graph.addNode is 'function'
# Existing Graph object
return @createNetwork graph
# JSON definition of a graph
noflo.graph.loadJSON graph, (err, instance) =>
return @error err if err
instance.baseDir = @baseDir
@createNetwork instance
return
if graph.substr(0, 1) isnt "/" and graph.substr(1, 1) isnt ":" and process and process.cwd
graph = "#{process.cwd()}/#{graph}"
graph = noflo.graph.loadFile graph, (err, instance) =>
return @error err if err
instance.baseDir = @baseDir
@createNetwork instance
createNetwork: (graph) ->
@description = graph.properties.description or ''
@icon = graph.properties.icon or @icon
graph.componentLoader = @loader
noflo.createNetwork graph, (err, @network) =>
return @error err if err
@emit 'network', @network
@network.connect (err) =>
return @error err if err
notReady = false
for name, process of @network.processes
notReady = true unless @checkComponent name, process
do @setToReady unless notReady
, true
start: ->
unless @isReady()
@on 'ready', =>
do @start
return
return unless @network
@started = true
@network.start()
checkComponent: (name, process) ->
unless process.component.isReady()
process.component.once "ready", =>
@checkComponent name, process
@setToReady()
return false
@findEdgePorts name, process
true
isExportedInport: (port, nodeName, portName) ->
# First we check disambiguated exported ports
for pub, priv of @network.graph.inports
continue unless priv.process is nodeName and priv.port is portName
return pub
# Then we check ambiguous ports, and if needed, fix them
for exported in @network.graph.exports
continue unless exported.process is nodeName and exported.port is portName
@network.graph.checkTransactionStart()
@network.graph.removeExport exported.public
@network.graph.addInport exported.public, exported.process, exported.port, exported.metadata
@network.graph.checkTransactionEnd()
return exported.public
# Component has exported ports and this isn't one of them
false
isExportedOutport: (port, nodeName, portName) ->
# First we check disambiguated exported ports
for pub, priv of @network.graph.outports
continue unless priv.process is nodeName and priv.port is portName
return pub
# Then we check ambiguous ports, and if needed, fix them
for exported in @network.graph.exports
continue unless exported.process is nodeName and exported.port is portName
@network.graph.checkTransactionStart()
@network.graph.removeExport exported.public
@network.graph.addOutport exported.public, exported.process, exported.port, exported.metadata
@network.graph.checkTransactionEnd()
return exported.public
# Component has exported ports and this isn't one of them
false
setToReady: ->
if typeof process isnt 'undefined' and process.execPath and process.execPath.indexOf('node') isnt -1
process.nextTick =>
@ready = true
@emit 'ready'
else
setTimeout =>
@ready = true
@emit 'ready'
, 0
findEdgePorts: (name, process) ->
for portName, port of process.component.inPorts
continue if not port or typeof port is 'function' or not port.canAttach
targetPortName = @isExportedInport port, name, portName
continue if targetPortName is false
@inPorts.add targetPortName, port
@inPorts[targetPortName].once 'connect', =>
# Start the network implicitly if we're starting to get data
return if @isStarted()
do @start
for portName, port of process.component.outPorts
continue if not port or typeof port is 'function' or not port.canAttach
targetPortName = @isExportedOutport port, name, portName
continue if targetPortName is false
@outPorts.add targetPortName, port
return true
isReady: ->
@ready
isSubgraph: ->
true
shutdown: ->
return unless @network
@network.stop()
exports.getComponent = (metadata) -> new Graph metadata