Class: RFlow::Component::HashPort

Inherits:
Port
  • Object
show all
Defined in:
lib/rflow/component/port.rb

Overview

Allows for a list of connections to be assigned to each port/key combination. Note that binding an input port to an un-indexed output port will result in messages from all indexed connections being received. Similarly, sending to an unindexed port will result in the same message being sent to all indexed connections.

Direct Known Subclasses

InputPort, OutputPort

Instance Attribute Summary collapse

Attributes inherited from Port

#component, #connected

Instance Method Summary collapse

Methods inherited from Port

#connected?

Constructor Details

#initialize(component, args = {}) ⇒ HashPort

Returns a new instance of HashPort.

Parameters:

  • component (Component)

    the component the port belongs to

  • args (Hash) (defaults to: {})

    supported args are :uuid and :name



124
125
126
127
128
129
# File 'lib/rflow/component/port.rb', line 124

def initialize(component, args = {})
  super(component)
  self.uuid = args[:uuid]
  self.name = args[:name]
  @connections_for = Hash.new {|hash, key| hash[key] = []}
end

Instance Attribute Details

#nameString

The name of the port.

Returns:

  • (String)


116
117
118
# File 'lib/rflow/component/port.rb', line 116

def name
  @name
end

#uuidString

The UUID of the port.

Returns:

  • (String)


119
120
121
# File 'lib/rflow/component/port.rb', line 119

def uuid
  @uuid
end

Instance Method Details

#[](key) ⇒ HashSubPort

Get the subport for a given key, which can be used to send messages or direct connection.

Parameters:

  • key (String)

    the key to subscript with

Returns:



135
136
137
# File 'lib/rflow/component/port.rb', line 135

def [](key)
  HashSubPort.new(self, key)
end

#add_connection(key, connection) ⇒ void

This method returns an undefined value.

Adds a connection for a given key.

Parameters:

  • key (String)

    the key to subscript with

  • connection (Connection)

    the connection to add



158
159
160
161
162
# File 'lib/rflow/component/port.rb', line 158

def add_connection(key, connection)
  RFlow.logger.debug "Attaching #{connection.class.name} connection '#{connection.name}' (#{connection.uuid}) to port '#{name}' (#{uuid}), key '#{connection.input_port_key}'"
  @connections_for[key] << connection
  @all_connections = nil
end

#all_connectionsArray<Connection>

Retrieve all connections to the port, regardless of key. The resulting Array also supports send_message(message) which will deliver the message on all connections.

Returns:



235
236
237
# File 'lib/rflow/component/port.rb', line 235

def all_connections
  @all_connections ||= @connections_for.values.flatten.uniq.extend(ConnectionCollection)
end

#collect_messages(key, receiver) ⇒ MessageCollectingConnection

Collect messages being sent to this port in a MessageCollectingConnection for retrieval later, usually for unit testing purposes. yields after establishing the new connection.

Parameters:

  • key (String)

    the key to subscript with

  • receiver (Array)

    array in which to place arriving messages

Returns:



180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/rflow/component/port.rb', line 180

def collect_messages(key, receiver)
  begin
    connection = RFlow::MessageCollectingConnection.new.tap do |c|
      c.messages = receiver
    end
    add_connection key, connection

    yield if block_given?
    connection
  ensure
    remove_connection key, connection if connection && block_given?
  end
end

#connect!void

This method returns an undefined value.

Override in subclasses to handle establishing the connection.

Raises:

  • (NotImplementedError)


229
# File 'lib/rflow/component/port.rb', line 229

def connect!; raise NotImplementedError, 'Raw ports do not know which direction to connect'; end

#connections_for(key) ⇒ Array<Connection>

Returns all the connections that should be sent/received on this subport. Merges the nil-keyed port (i.e. any connections for a port without a key) to those specific for the key, so should only be used to read a list of connections, not to add new ones. Use #add_connection to add a new connection for a given key.

Parameters:

  • key (String)

    the key to subscript with

Returns:



147
148
149
150
151
152
# File 'lib/rflow/component/port.rb', line 147

def connections_for(key)
  case key
  when nil; @connections_for[nil]
  else @connections_for[key] + @connections_for[nil]
  end
end

#direct_connect(key = nil, other_port) ⇒ void

This method returns an undefined value.

Directly connect this port to another port. If it’s an input port, forward messages to that input port; if it’s an output port, forward messages so they appear to come from that output port.

Parameters:

  • key (String) (defaults to: nil)

    the key to subscript with

  • other_port (Port)

    the port to forward to



200
201
202
203
204
205
206
# File 'lib/rflow/component/port.rb', line 200

def direct_connect(key = nil, other_port)
  case other_port
  when InputPort; add_connection key, ForwardToInputPort.new(other_port)
  when OutputPort; add_connection key, ForwardToOutputPort.new(other_port)
  else raise ArgumentError, "Unknown port type #{other_port.class.name}"
  end
end

#eachArray<Connection>

Enumerate all connections, yielding each.

Returns:



216
217
218
# File 'lib/rflow/component/port.rb', line 216

def each
  @connections_for.values.each {|connections| yield connections }
end

#keysArray<String>

A list of connected keys.

Returns:

  • (Array<String>)


210
211
212
# File 'lib/rflow/component/port.rb', line 210

def keys
  @connections_for.keys
end

#remove_connection(key, connection) ⇒ void

This method returns an undefined value.

Removes a connection from a given key.

Parameters:

  • key (String)

    the key to subscript with

  • connection (Connection)

    the connection to remove



168
169
170
171
172
# File 'lib/rflow/component/port.rb', line 168

def remove_connection(key, connection)
  RFlow.logger.debug "Removing #{connection.class.name} connection '#{connection.name}' (#{connection.uuid}) from port '#{name}' (#{uuid}), key '#{connection.input_port_key}'"
  @connections_for[key].delete(connection)
  @all_connections = nil
end

#send_message(message) ⇒ void

This method returns an undefined value.

Override in subclasses to actually send messages places.

Parameters:

  • message (Message)

    the message to send

Raises:

  • (NotImplementedError)


223
224
225
# File 'lib/rflow/component/port.rb', line 223

def send_message(message)
  raise NotImplementedError, 'Raw ports do not know how to send messages'
end