Class: OFlow::Box

Inherits:
Object
  • Object
show all
Defined in:
lib/oflow/box.rb

Overview

A Box encapsulates data in the system. It provides a wrapper around the data which becomes immutable as it is frozen in transit between Tasks. The Box allows the contents to be modified by replacing the contents with thawed copies of the original data.

Boxes are shipped between Tasks. A Tracker can also be attached to a Box to follow it and gather a history of it’s movements.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, tracker = nil) ⇒ Box

Create a new Box withe the content provided. The value provided will be frozen to inhibit changes to the value after the Box is created.

Parameters:

  • value

    contents of the Box

  • tracker (Tracker) (defaults to: nil)

    used to track the progress of the Box



23
24
25
26
# File 'lib/oflow/box.rb', line 23

def initialize(value, tracker=nil)
  @tracker = tracker
  @contents = value
end

Instance Attribute Details

#contentsObject (readonly)

The contents of the Box.



17
18
19
# File 'lib/oflow/box.rb', line 17

def contents
  @contents
end

#trackerObject (readonly)

Tracker for the box if there is one.



14
15
16
# File 'lib/oflow/box.rb', line 14

def tracker
  @tracker
end

Instance Method Details

#aget(path) ⇒ Object

Returns the data element described by the path which is an array of element names or indices. Indices can be Fixnum or Strings.

Parameters:

  • path (Array)

    location of element to return

Returns:

  • the data element.



71
72
73
# File 'lib/oflow/box.rb', line 71

def aget(path)
  _aget(path, @contents)
end

#aset(path, value) ⇒ Object

Sets or adds a value in inside the Box where the path is an array of element names or indices. Indices can be Fixnum or Strings.

Parameters:

  • path (Array)

    location of element to change or add.

  • value

    value for the addition or change



53
54
55
# File 'lib/oflow/box.rb', line 53

def aset(path, value)
  Box.new(_aset(path, @contents, value), @tracker)
end

#deep_freeze(value) ⇒ Object

TBD make these module methods on a Freezer module



100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/oflow/box.rb', line 100

def deep_freeze(value)
  case value
  when Array
    value.each { |v| deep_freeze(v) }
  when Hash
    # hash keys are frozen already
    value.each { |k, v| deep_freeze(v) }
  end
  # Don't freeze other Objects. This leaves an out for special purpose
  # functionality.
  value.freeze
end

#freezeObject

Called when passing to another Task. It freezes the contents recursively.



86
87
88
89
# File 'lib/oflow/box.rb', line 86

def freeze()
  deep_freeze(@contents)
  super
end

#get(path) ⇒ Object

Returns the data element described by the path. A path is a set of element names in the case of a Hash or index numbers in the case of an Array joined with the ‘:’ character as a separator.

Parameters:

  • path (String)

    location of element to return

Returns:

  • the data element.



62
63
64
65
# File 'lib/oflow/box.rb', line 62

def get(path)
  return @contents if path.nil?
  aget(path.split(':'))
end

#receive(location, op) ⇒ Box

Receives a Box by creating a new Box whose contents is the same as the existing but with an updated tracker.

Parameters:

  • location (String)

    where the Box was received, full name of Task

  • op (Symbol)

    operation that the Box was received under

Returns:

  • (Box)

    new Box.



33
34
35
36
# File 'lib/oflow/box.rb', line 33

def receive(location, op)
  return self if @tracker.nil?
  Box.new(@contents, @tracker.receive(location, op))
end

#set(path, value) ⇒ Object

Sets or adds a value in inside the Box. The Box is changed with the new contents being thawed where necessary. A path is a set of element names in the case of a Hash or index numbers in the case of an Array joined with the ‘:’ character as a separator.

Parameters:

  • path (String)

    location of element to change or add.

  • value

    value for the addition or change



44
45
46
47
# File 'lib/oflow/box.rb', line 44

def set(path, value)
  return aset(nil, value) if path.nil?
  aset(path.split(':'), value)
end

#thawBox

Makes a copy of the frozen contents and the Box to allow modifications.

Returns:

  • (Box)

    new Box.



93
94
95
96
# File 'lib/oflow/box.rb', line 93

def thaw()
  # Don't freeze the contents.
  Box.new(thaw_value(@contents, true), @tracker)
end

#thaw_value(value, recurse) ⇒ Object

Make a copy of the value, unfrozen.



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/oflow/box.rb', line 114

def thaw_value(value, recurse)
  return value unless value.frozen? || recurse
  case value
  when Array
    # thaws the array itself but not the elements
    value = Array.new(value)
    value.map! { |v| thaw_value(v, true) } if recurse
  when Hash
    # thaws the hash itself but not the elements
    orig = value
    value = {}
    if recurse
      orig.each { |k, v| value[k] = thaw_value(v, true) }
    else
      orig.each { |k, v| value[k] = v }
    end
  when String
    value = String.new(value)
  end
  value
end

#to_sObject Also known as: inspect

Returns a string representation of the Box and contents.



76
77
78
79
80
81
82
# File 'lib/oflow/box.rb', line 76

def to_s()
  if @tracker.nil?
    "Box{#{@contents}}"
  else
    "Box{#{@contents}, tracker: #{@tracker}}"
  end
end