Class: T2Server::OutputPort

Inherits:
Port
  • Object
show all
Includes:
XML::Methods
Defined in:
lib/t2-server/port.rb

Overview

Represents an output port of a workflow.

Instance Attribute Summary

Attributes inherited from Port

#depth, #name

Instance Method Summary collapse

Methods included from XML::Methods

#get_uris_from_doc, #xml_children, #xml_document, #xml_first_child, #xml_node_attribute, #xml_node_content, #xml_node_name, #xml_text_node, #xpath_attr, #xpath_compile, #xpath_find, #xpath_first

Constructor Details

#initialize(run, xml) ⇒ OutputPort

:stopdoc: Create a new OutputPort.



164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/t2-server/port.rb', line 164

def initialize(run, xml)
  super(run, xml)

  @error = false
  @structure = parse_data(xml_first_child(xml))

  # cached outputs
  @values = nil
  @refs = nil
  @types = nil
  @sizes = nil
  @total_size = nil
end

Instance Method Details

#[](i) ⇒ Object

:call-seq:

[int] -> obj

This call provides access to the underlying structure of the OutputPort. It can only be used for ports of depth >= 1. For singleton ports, use OutputPort#value instead.

Example usage - To get part of a value from an output port with depth 3: port[0].value(10…100)



211
212
213
214
# File 'lib/t2-server/port.rb', line 211

def [](i)
  return @structure if depth == 0
  @structure[i]
end

#download(uri, range = nil, &block) ⇒ Object

:stopdoc:



377
378
379
# File 'lib/t2-server/port.rb', line 377

def download(uri, range = nil, &block)
  @run.download_output_data(uri, range, &block)
end

#empty?Boolean

:call-seq:

empty? -> true or false

Is this output port empty?

Note that if the output port holds a list then it is not considered empty, even if that list is empty. This is because the port itself is not empty, there is a list there! A separate test should be performed to see if that list is empty or not.

Returns:

  • (Boolean)


196
197
198
199
200
# File 'lib/t2-server/port.rb', line 196

def empty?
  # Funnily enough, an empty list does *not* make a port empty!
  return false if @structure.instance_of? Array
  @structure.empty?
end

#error?Boolean

:call-seq:

error? -> true or false

Is there an error associated with this output port?

Returns:

  • (Boolean)


183
184
185
# File 'lib/t2-server/port.rb', line 183

def error?
  @error
end

#referenceObject

:call-seq:

reference -> string
reference -> array

Get URI references to the data values of this output port as strings.

For a singleton output a single uri is returned. For lists an array of uris is returned. For an individual reference from a list use ‘port[].reference’.



301
302
303
# File 'lib/t2-server/port.rb', line 301

def reference
  @refs ||= strip(:reference)
end

#sizeObject

:call-seq:

size -> fixnum
size -> array

Get the data size of the data value in this output port.

For a singleton output a single size is returned. For lists an array of sizes is returned. For an individual size from a list use ‘port[].size’.



325
326
327
# File 'lib/t2-server/port.rb', line 325

def size
  @sizes ||= strip(:size)
end

#stream_value(stream, range = nil) ⇒ Object

:call-seq:

stream_value(stream) -> fixnum
stream_value(stream, range) -> fixnum

Stream a singleton port value directly to another stream and return the number of bytes written. If a range is supplied then only that range of data is streamed from the server. The stream passed in may be anything that provides a write method; instances of IO and File, for example. No data is cached by this method.

To stream parts of a list port, use PortValue#stream_value on the list item directly:

run.output_port("port_name")[0].stream_value(stream)

Raises:

  • (ArgumentError)


258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/t2-server/port.rb', line 258

def stream_value(stream, range = nil)
  return 0 unless depth == 0
  raise ArgumentError,
    "Stream passed in must provide a write method" unless
      stream.respond_to? :write

  if range.nil?
    @structure.stream_value(stream)
  else
    @structure.stream_value(stream, range)
  end
end

#total_sizeObject

:call-seq:

total_size -> fixnum

Return the total data size of all the data in this output port.



333
334
335
336
337
338
339
340
341
# File 'lib/t2-server/port.rb', line 333

def total_size
  return @total_size if @total_size
  if @structure.instance_of? Array
    return 0 if @structure.empty?
    @total_size = strip(:size).flatten.inject { |sum, i| sum + i }
  else
    @total_size = size
  end
end

#typeObject

:call-seq:

type -> string
type -> array

Get the mime type of the data value in this output port.

For a singleton output a single type is returned. For lists an array of types is returned. For an individual type from a list use ‘port[].type’.



313
314
315
# File 'lib/t2-server/port.rb', line 313

def type
  @types ||= strip(:type)
end

#value(range = nil, &block) ⇒ Object

:call-seq:

value -> binary blob
value(range) -> binary blob
value {|chunk| ...}
value(range) {|chunk| ...}
value -> array

For singleton outputs download or stream the data (or part of it) held by the output port. Please see the documentation for PortValue#value for full details.

For list outputs all data values are downloaded into memory and returned in an Array structure that mirrors the structure of the output port. Do not use this form if the output port has large amounts of data! To get part of a value from a list use something like:

run.output_port("port_name")[0].value(0..100)


232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/t2-server/port.rb', line 232

def value(range = nil, &block)
  if depth == 0
    if range.nil?
      @structure.value(&block)
    else
      @structure.value(range, &block)
    end
  else
    @values = strip(:value) if @values.nil?
    @values
  end
end

#write_value_to_file(filename, range = nil) ⇒ Object

:call-seq:

write_value_to_file(filename) -> fixnum
write_value_to_file(filename, range) -> fixnum

Stream a singleton port value to a file and return the number of bytes written. If a range is supplied then only that range of data is downloaded from the server.

To save parts of a list port to a file, use PortValue#write_value_to_file on the list item directly:

run.output_port("port_name")[0].write_value_to_file


282
283
284
285
286
287
288
289
290
# File 'lib/t2-server/port.rb', line 282

def write_value_to_file(filename, range = nil)
  return 0 unless depth == 0

  if range.nil?
    @structure.write_value_to_file(filename)
  else
    @structure.write_value_to_file(filename, range)
  end
end

#zip(param = nil, &block) ⇒ Object

:call-seq:

zip -> binary blob
zip(filename) -> fixnum
zip(stream) -> fixnum
zip {|chunk| ...}

Get the data in this output port directly from the server in zip format.

This method does not work with singleton ports. Taverna Server cannot currently return zip files of singleton ports on their own. If you wish to get a singleton port in a zip file then you can use Run#zip_output which will return all outputs in a single file.

If this method is called on a singleton port it will return nil and streaming from it will return nothing.

Calling this method with no parameters will simply return a blob of zipped data. Providing a filename will stream the data directly to that file and return the number of bytes written. Passing in an object that has a write method (for example, an instance of File or IO) will stream the zip data directly to that object and return the number of bytes that were streamed. Passing in a block will allow access to the underlying data stream:

port.zip do |chunk|
  print chunk
end

Raises RunStateError if the run has not finished running.



371
372
373
374
# File 'lib/t2-server/port.rb', line 371

def zip(param = nil, &block)
  return nil if depth == 0
  @run.zip_output(param, name, &block)
end