edoors-ruby 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,18 +22,18 @@ require 'version'
22
22
  #
23
23
  module Edoors
24
24
  #
25
- PATH_SEP = '/'.freeze
26
- LINK_SEP = ','.freeze
27
- ACT_SEP = '?'.freeze
25
+ PATH_SEP = '/'.freeze
26
+ ACT_SEP = '?'.freeze
28
27
  #
29
- ACT_GET = 'get'.freeze
30
- ACT_ERROR = 'error'.freeze
28
+ ACT_GET = 'get'.freeze
29
+ ACT_ERROR = 'error'.freeze
31
30
  #
32
- SYS_ACT_HIBERNATE = 'hibernate'.freeze
33
- SYS_ACT_ADD_LINK = 'sys_add_link'.freeze
31
+ SYS_ACT_HIBERNATE = 'hibernate'.freeze
32
+ SYS_ACT_ADD_LINK = 'sys_add_link'.freeze
33
+ SYS_ACT_ADD_ROOM = 'sys_add_room'.freeze
34
34
  #
35
- FIELD_ERROR_MSG = 'edoors_error'.freeze
36
- FIELD_HIBERNATE_PATH= 'hibernate_path'.freeze
35
+ FIELD_ERROR_MSG = 'edoors_error'.freeze
36
+ FIELD_HIBERNATE_PATH = 'hibernate_path'.freeze
37
37
  #
38
38
  class Exception < ::Exception; end
39
39
  #
@@ -22,14 +22,24 @@
22
22
  module Edoors
23
23
  #
24
24
  ACT_FOLLOW = 'follow'.freeze
25
+ ACT_PASS_THROUGH = 'pass_through'.freeze
25
26
  #
26
27
  class Board < Door
28
+ #
29
+ # creates a Board object from the arguments.
30
+ #
31
+ # @param [String] n the name of this Board
32
+ # @param [Iota] p the parent
27
33
  #
28
34
  def initialize n, p
29
35
  super n, p
30
36
  @postponed = {}
31
37
  end
32
38
  #
39
+ # called by JSON#generate to serialize the Board object into JSON data
40
+ #
41
+ # @param [Array] a belongs to JSON generator
42
+ #
33
43
  def to_json *a
34
44
  {
35
45
  'kls' => self.class.name,
@@ -38,6 +48,12 @@ module Edoors
38
48
  }.merge(hibernate!).to_json *a
39
49
  end
40
50
  #
51
+ # creates a Board object from a JSON data
52
+ #
53
+ # @param [Hash] o belongs to JSON parser
54
+ #
55
+ # @raise Edoors::Exception if the json kls attribute is wrong
56
+ #
41
57
  def self.json_create o
42
58
  raise Edoors::Exception.new "JSON #{o['kls']} != #{self.name}" if o['kls'] != self.name
43
59
  board = self.new o['name'], o['parent']
@@ -48,9 +64,13 @@ module Edoors
48
64
  board
49
65
  end
50
66
  #
67
+ # process the given particle then forward it to user code
68
+ #
69
+ # @param [Particle] p the Particle to be processed
70
+ #
51
71
  def process_p p
52
72
  @viewer.receive_p p if @viewer
53
- if p.action!=Edoors::ACT_ERROR
73
+ if p.action!=Edoors::ACT_ERROR and p.action!=Edoors::ACT_PASS_THROUGH
54
74
  p2 = @postponed[p.link_value] ||= p
55
75
  return if p2==p
56
76
  @postponed.delete p.link_value
@@ -62,6 +82,25 @@ module Edoors
62
82
  _garbage if not @saved.nil?
63
83
  end
64
84
  #
85
+ # stores back the given Particle
86
+ #
87
+ # @param [Particle] p the particle to be stored
88
+ #
89
+ # this can be used to prevent the overhead of sending the particle back to self
90
+ #
91
+ def keep! p
92
+ @postponed[p.link_value] = p
93
+ @saved = nil
94
+ end
95
+ #
96
+ # sends away all stored Particle
97
+ #
98
+ def flush!
99
+ while p=@postponed.shift
100
+ send_p p[1]
101
+ end
102
+ end
103
+ #
65
104
  end
66
105
  #
67
106
  end
@@ -22,12 +22,21 @@
22
22
  module Edoors
23
23
  #
24
24
  class Door < Iota
25
+ #
26
+ # creates a Door object from the arguments.
27
+ #
28
+ # @param [String] n the name of this Door
29
+ # @param [Iota] p the parent
25
30
  #
26
31
  def initialize n, p
27
32
  super n, p
28
33
  @saved = nil
29
34
  end
30
35
  #
36
+ # called by JSON#generate to serialize the Door object into JSON data
37
+ #
38
+ # @param [Array] a belongs to JSON generator
39
+ #
31
40
  def to_json *a
32
41
  {
33
42
  'kls' => self.class.name,
@@ -35,6 +44,12 @@ module Edoors
35
44
  }.merge(hibernate!).to_json *a
36
45
  end
37
46
  #
47
+ # creates a Door object from a JSON data
48
+ #
49
+ # @param [Hash] o belongs to JSON parser
50
+ #
51
+ # @raise Edoors::Exception if the json kls attribute is wrong
52
+ #
38
53
  def self.json_create o
39
54
  raise Edoors::Exception.new "JSON #{o['kls']} != #{self.name}" if o['kls'] != self.name
40
55
  door = self.new o['name'], o['parent']
@@ -42,23 +57,37 @@ module Edoors
42
57
  door
43
58
  end
44
59
  #
45
- def require_p p_kls
60
+ # require a Particle of the given class
61
+ #
62
+ # @param [Class] p_kls the class of the desired Particle
63
+ #
64
+ def require_p p_kls=Edoors::Particle
46
65
  @spin.require_p p_kls
47
66
  end
48
67
  #
68
+ # release the given Particle
69
+ #
70
+ # @param [Particle] p the Particle to be released
71
+ #
49
72
  def release_p p
50
73
  @saved=nil if @saved==p # particle is released, all is good
51
74
  @spin.release_p p
52
75
  end
53
76
  #
77
+ # release the Particle that have not been released or sent by user code
78
+ #
54
79
  def _garbage
55
- puts " ! #{path} didn't give back #{@saved}" if @spin.debug_errors
80
+ puts " ! #{path} didn't give back #{@saved}" if @spin.debug_garbage
56
81
  puts "\t#{@saved.data Edoors::FIELD_ERROR_MSG}" if @saved.action==Edoors::ACT_ERROR
57
82
  @spin.release_p @saved
58
83
  @saved = nil
59
84
  end
60
85
  private :_garbage
61
86
  #
87
+ # process the given particle then forward it to user code
88
+ #
89
+ # @param [Particle] p the Particle to be processed
90
+ #
62
91
  def process_p p
63
92
  @viewer.receive_p p if @viewer
64
93
  @saved = p
@@ -66,12 +95,24 @@ module Edoors
66
95
  _garbage if not @saved.nil?
67
96
  end
68
97
  #
98
+ # dead end, for now user defined Door do not have to deal with system Particle
99
+ # the Particle is released
100
+ #
101
+ # @param [Particle] p the Particle to deal with
102
+ #
69
103
  def process_sys_p p
70
104
  # nothing todo with it now
71
105
  @spin.release_p p
72
106
  end
73
107
  #
74
- def _send sys, p, a=nil, d=nil
108
+ # send the given Particle through the direct @parent
109
+ #
110
+ # @param [Particle] p the Particle to be sent
111
+ # @param [Boolean] sys if true send to system Particle fifo
112
+ # @param [String] a the post action
113
+ # @param [Iota] d the post destination
114
+ #
115
+ def _send p, sys, a, d
75
116
  p.init! self
76
117
  p.set_dst! a, d||self if a
77
118
  @saved=nil if @saved==p # particle is sent back the data, all is good
@@ -80,12 +121,28 @@ module Edoors
80
121
  end
81
122
  private :_send
82
123
  #
124
+ # send the given Particle to the application Particle fifo
125
+ #
126
+ # @param [Particle] p the Particle to be sent
127
+ # @param [String] a the post action
128
+ # @param [Iota] d the post destination
129
+ #
130
+ # @see Door#_send real implementation
131
+ #
83
132
  def send_p p, a=nil, d=nil
84
- _send false, p, a, d
133
+ _send p, false, a, d
85
134
  end
86
135
  #
136
+ # send the given Particle to the system Particle fifo
137
+ #
138
+ # @param [Particle] p the Particle to be sent
139
+ # @param [String] a the post action
140
+ # @param [Iota] d the post destination
141
+ #
142
+ # @see Door#_send real implementation
143
+ #
87
144
  def send_sys_p p, a=nil, d=nil
88
- _send true, p, a, d
145
+ _send p, true, a, d
89
146
  end
90
147
  #
91
148
  end
@@ -20,8 +20,18 @@
20
20
 
21
21
  #
22
22
  module Edoors
23
+ #
24
+ IOTA_NAME = 'edoors_iota_name'.freeze
23
25
  #
24
26
  class Iota
27
+ #
28
+ # creates a Iota object from the arguments.
29
+ #
30
+ # @param [String] n the name of this Iota
31
+ # @param [Iota] p the parent
32
+ #
33
+ # @see Room#add_iota adds itself to it's parent children list
34
+ # @see Spin#add_to_world adds itself to @spin's world
25
35
  #
26
36
  def initialize n, p
27
37
  raise Edoors::Exception.new "Iota name #{n} is not valid" if n.include? Edoors::PATH_SEP
@@ -39,25 +49,33 @@ module Edoors
39
49
  attr_reader :name, :path, :spin
40
50
  attr_accessor :viewer, :parent
41
51
  #
52
+ # override this to initialize your object on system start
53
+ #
42
54
  def start!
43
- # override this to initialize your object on system start
44
55
  end
45
56
  #
57
+ # override this to initialize your object on system stop
58
+ #
46
59
  def stop!
47
- # override this to initialize your object on system stop
48
60
  end
49
61
  #
62
+ # override this to save your object state on hibernate
63
+ # #
50
64
  def hibernate!
51
- # override this to save your object state on hibernate
52
65
  {}
53
66
  end
54
67
  #
68
+ # override this to restore your object state on resume
69
+ #
55
70
  def resume! o
56
- # override this to restore your object state on resume
57
71
  end
58
72
  #
73
+ # has to be override, used by user side code
74
+ #
75
+ # @raise NoMethodError
76
+ #
59
77
  def receive_p p
60
- raise NoMethodError.new "receive_p(p) must be overridden"
78
+ raise NoMethodError.new "#{self.path} receive_p(p) must be overridden"
61
79
  end
62
80
  #
63
81
  end
@@ -23,45 +23,65 @@ module Edoors
23
23
  #
24
24
  LNK_SRC = 'edoors_lnk_src'.freeze
25
25
  LNK_DSTS = 'edoors_lnk_dsts'.freeze
26
- LNK_FIELDS = 'edoors_lnk_fields'.freeze
27
- LNK_CONDF = 'edoors_lnk_condf'.freeze
28
- LNK_CONDV = 'edoors_lnk_condv'.freeze
26
+ LNK_KEYS = 'edoors_lnk_keys'.freeze
27
+ LNK_VALUE = 'edoors_lnk_value'.freeze
29
28
  #
30
29
  class Link
31
30
  #
32
- def initialize src, dsts, fields=nil, cond_fields=nil, cond_value=nil
33
- @src = src # link source name
34
- @dsts = dsts # , separated destinations to apply to the particle on linking success
35
- @fields = fields # , separated fields to apply to the particle on linking success
36
- @cond_fields = cond_fields # , separated fields used to generate the link value with particle payload
37
- @cond_value = cond_value # value which will be compared to the particle link value to link or not
38
- @door = nil # pointer to the source
31
+ # creates a Link object from the arguments.
32
+ #
33
+ # @param [String] src link source name
34
+ # @param [Array] dsts destinations to apply to the particle on linking success
35
+ # @param [Array] keys keys to apply as link_keys to the particle on linking success
36
+ # @param [Hash] value will be used to check linking with particles
37
+ #
38
+ # @see Room#_try_links try to apply links on a Particle
39
+ # @see Particle#link_with? linking test
40
+ #
41
+ def initialize src, dsts, keys=nil, value=nil
42
+ @src = src
43
+ @dsts = dsts
44
+ @keys = keys
45
+ @value = value
46
+ @door = nil # pointer to the source set from @src by Room#add_link
39
47
  end
40
48
  #
49
+ # called by JSON#generate to serialize the Link object into JSON data
50
+ #
51
+ # @param [Array] a belongs to JSON generator
52
+ #
41
53
  def to_json *a
42
54
  {
43
- 'kls' => self.class.name,
44
- 'src' => @src,
45
- 'dsts' => @dsts,
46
- 'fields' => @fields,
47
- 'cond_fields' => @cond_fields,
48
- 'cond_value' => @cond_value
55
+ 'kls' => self.class.name,
56
+ 'src' => @src,
57
+ 'dsts' => @dsts,
58
+ 'keys' => @keys,
59
+ 'value' => @value
49
60
  }.to_json *a
50
61
  end
51
62
  #
63
+ # creates a Link object from a JSON data
64
+ #
65
+ # @param [Hash] o belongs to JSON parser
66
+ #
67
+ # @raise Edoors::Exception if the json kls attribute is wrong
68
+ #
52
69
  def self.json_create o
53
70
  raise Edoors::Exception.new "JSON #{o['kls']} != #{self.name}" if o['kls'] != self.name
54
- self.new o['src'], o['dsts'], o['fields'], o['cond_fields'], o['cond_value']
71
+ self.new o['src'], o['dsts'], o['keys'], o['value']
55
72
  end
56
73
  #
57
- def self.from_particle_data p
58
- Edoors::Link.new(p.get_data(Edoors::LNK_SRC), p.get_data(Edoors::LNK_DSTS),
59
- p.get_data(Edoors::LNK_FIELDS), p.get_data(Edoors::LNK_CONDF),
60
- p.get_data(Edoors::LNK_CONDV))
74
+ # creates a Link object from the data of a particle
75
+ #
76
+ # @param [Particle] p the Particle to get Link attributes from
77
+ #
78
+ def self.from_particle p
79
+ pl = p.payload
80
+ Edoors::Link.new pl[Edoors::LNK_SRC], pl[Edoors::LNK_DSTS], pl[Edoors::LNK_KEYS], pl[Edoors::LNK_VALUE]
61
81
  end
62
82
  #
63
83
  attr_accessor :door
64
- attr_reader :src, :dsts, :fields, :cond_fields, :cond_value
84
+ attr_reader :src, :dsts, :keys, :value
65
85
  #
66
86
  end
67
87
  #
@@ -23,6 +23,33 @@ require 'time'
23
23
  module Edoors
24
24
  #
25
25
  class Particle
26
+ #
27
+ # creates a Particle object from the arguments.
28
+ #
29
+ # @param [Hash] o a customizable set of options
30
+ #
31
+ # @option o 'ts' [String]
32
+ # creation time
33
+ # @option o 'src' [String]
34
+ # Iota where it's originated from
35
+ # @option o 'dst' [String]
36
+ # Iota where it's heading to
37
+ # @option o 'room' [String]
38
+ # Room path part of the current destination
39
+ # @option o 'door' [String]
40
+ # Door path part of the current destination
41
+ # @option o 'action' [String]
42
+ # action part of the current destination
43
+ # @option o 'dsts' [String]
44
+ # fifo of path?action strings where to travel to
45
+ # @option o 'link_keys' [String]
46
+ # unordered keys used has payload keys to build link_value
47
+ # @option o 'payload' [String]
48
+ # the data carried by this particle
49
+ # @option o 'merged' [String]
50
+ # list of merged particles
51
+ #
52
+ # @see Spin#require_p require a Particle
26
53
  #
27
54
  def initialize o={}
28
55
  @ts = Time.now # creation time
@@ -31,11 +58,10 @@ module Edoors
31
58
  @room = nil # Room path part of the current destination
32
59
  @door = nil # Door path part of the current destination
33
60
  @action = nil # action part of the current destination
34
- @link_value = nil # the value computed with the link_fields values extracted from the payload
35
- # used for pearing Particles in Boards and linking in routing process
36
61
  @dsts = [] # fifo of path?action strings where to travel to
37
- @link_fields = [] # the fields used to generate the link value
38
- @payload = {} # the actual data carried by this particle
62
+ @link_keys = [] # unordered keys used has payload keys to build link_value
63
+ @link_value = {} # the payload keys and values corresponding to the link keys
64
+ @payload = {} # the data carried by this particle
39
65
  @merged = [] # list of merged particles
40
66
  #
41
67
  if not o.empty?
@@ -46,86 +72,132 @@ module Edoors
46
72
  @payload = o['payload']||{}
47
73
  @src = o['spin'].search_down o['src'] if o['src']
48
74
  @dst = o['spin'].search_down o['dst'] if o['dst']
49
- o['dsts'].each do |dst| add_dsts dst end if o['dsts']
50
- set_link_fields *o['link_fields'] if o['link_fields']
75
+ add_dsts *o['dsts'] if o['dsts']
76
+ set_link_keys *o['link_keys'] if o['link_keys']
51
77
  o['merged'].each do |particle|
52
78
  merge! Particle.json_create(particle.merge!('spin'=>o['spin']))
53
79
  end if o['merged']
54
80
  end
55
81
  end
56
82
  #
83
+ # called by JSON#generate to serialize the Particle object into JSON data
84
+ #
85
+ # @param [Array] a belongs to JSON generator
86
+ #
57
87
  def to_json *a
58
88
  {
59
- 'kls' => self.class.name,
60
- 'ts' => @ts,
61
- 'src' => (@src ? @src.path : nil ),
62
- 'dst' => (@dst ? @dst.path : nil ),
63
- 'room' => @room,
64
- 'door' => @door,
65
- 'action' => @action,
66
- 'dsts' => @dsts,
67
- 'link_fields' => @link_fields,
68
- 'payload' => @payload,
69
- 'merged' => @merged
89
+ 'kls' => self.class.name,
90
+ 'ts' => @ts,
91
+ 'src' => (@src ? @src.path : nil ),
92
+ 'dst' => (@dst ? @dst.path : nil ),
93
+ 'room' => @room,
94
+ 'door' => @door,
95
+ 'action' => @action,
96
+ 'dsts' => @dsts,
97
+ 'link_keys' => @link_keys,
98
+ 'payload' => @payload,
99
+ 'merged' => @merged
70
100
  }.to_json *a
71
101
  end
72
102
  #
103
+ # creates a Particle object from a JSON data
104
+ #
105
+ # @param [Hash] o belongs to JSON parser
106
+ #
107
+ # @raise Edoors::Exception if the json kls attribute is wrong
108
+ #
73
109
  def self.json_create o
74
110
  raise Edoors::Exception.new "JSON #{o['kls']} != #{self.name}" if o['kls'] != self.name
75
111
  self.new o
76
112
  end
77
113
  #
78
- # called when released
114
+ # clears all attributes
115
+ #
116
+ # @see Spin#release_p called whe na Particle is released
117
+ #
79
118
  def reset!
80
119
  clear_merged! ( @src ? @src : ( @dst ? @dst : nil ) )
81
- @ts = @src = @dst = @room = @door = @action = @link_value = nil
120
+ @ts = @src = @dst = @room = @door = @action = nil
82
121
  @dsts.clear
83
- @link_fields.clear
122
+ @link_value.clear
123
+ @link_keys.clear
84
124
  @payload.clear
85
125
  end
86
126
  #
87
- # called when sent
127
+ # sets @src, @ts, and reset others
128
+ #
129
+ # @see Particle#apply_link! called when a Link is applied
130
+ # @see Door#_send called when a Door sends a Particle
131
+ #
88
132
  def init! src
89
133
  @src = src
90
134
  @ts = Time.now
91
135
  @dst = @room = @door = @action = nil
92
136
  end
93
137
  #
94
- attr_reader :ts, :src, :dst, :room, :door, :action, :link_value, :payload
138
+ attr_reader :ts, :src, :dst, :room, :door, :action, :payload, :link_value
95
139
  #
96
- # routing
140
+ # returns the next destination
97
141
  #
98
142
  def next_dst
99
143
  @dsts[0]
100
144
  end
101
145
  #
146
+ # clears the destination list
147
+ #
102
148
  def clear_dsts!
103
149
  @dsts.clear
104
150
  end
105
151
  #
106
- def add_dsts dsts
107
- dsts.split(Edoors::LINK_SEP).each do |dst|
108
- if dst.empty? or dst[0]==Edoors::PATH_SEP or dst[0]==Edoors::PATH_SEP or dst=~/\/\?/\
109
- or dst=~/\/{2,}/ or dst=~/\s+/ or dst==Edoors::ACT_SEP
152
+ # adds destinations to the destination list
153
+ #
154
+ # @param [Array] dsts destinations to add
155
+ #
156
+ # @raise Edoors::Exception if a destination is not acceptable
157
+ #
158
+ # The parameters are checked before beeing added.
159
+ # they must not be empty or be '?' or start with '/'
160
+ # or contain '/?' or '//' or '\s+'
161
+ #
162
+ def add_dsts *dsts
163
+ dsts.each do |dst|
164
+ if dst.empty? or dst==Edoors::ACT_SEP or dst[0]==Edoors::PATH_SEP \
165
+ or dst=~/\/\?/ or dst=~/\/{2,}/ or dst=~/\s+/
110
166
  raise Edoors::Exception.new "destination #{dst} is not acceptable"
111
167
  end
112
168
  @dsts << dst
113
169
  end
114
170
  end
115
171
  #
172
+ # adds a destination to the destination list
173
+ #
174
+ # @param [String] a the action
175
+ # @param [String] d the destination
176
+ #
116
177
  def add_dst a, d=''
117
178
  add_dsts d+Edoors::ACT_SEP+a
118
179
  end
119
180
  #
181
+ # sets the current destination
182
+ #
183
+ # @param [String] a the action
184
+ # @param [String Iota] d the destination
185
+ #
120
186
  def set_dst! a, d
121
187
  @action = a
122
188
  if d.is_a? Edoors::Iota
123
189
  @dst = d
124
190
  else
191
+ @dst = nil
125
192
  _split_path! d
126
193
  end
127
194
  end
128
195
  #
196
+ # splits the next destination into @room, @door, @action attributes
197
+ #
198
+ # the @dst attribute is set to nil
199
+ # the @room, @door, @action attributes are set to nil if not defined
200
+ #
129
201
  def split_dst!
130
202
  @dst = @room = @door = @action = nil
131
203
  return if (n = next_dst).nil?
@@ -133,6 +205,10 @@ module Edoors
133
205
  _split_path! p
134
206
  end
135
207
  #
208
+ # called by Particle#split_dst! to split the path part of the destination
209
+ #
210
+ # @param [String] p path to be splitted
211
+ #
136
212
  def _split_path! p
137
213
  i = p.rindex Edoors::PATH_SEP
138
214
  if i.nil?
@@ -146,81 +222,147 @@ module Edoors
146
222
  end
147
223
  private :_split_path!
148
224
  #
225
+ # sets the current destination and shift the head of destination list
226
+ #
227
+ # @param [Iota] dst the current destination
228
+ #
229
+ # @see Room#_route routing success
230
+ # @see Room#_send routing failure
231
+ #
149
232
  def dst_routed! dst
150
233
  @dst = dst
151
234
  @dsts.shift
152
235
  end
153
236
  #
237
+ # sets the error message, the destination and action
238
+ #
239
+ # @param [String] e error message
240
+ # @param [Iota] dst the destination, @src if nil
241
+ #
242
+ # the error message is set into @payload[[Edoors::FIELD_ERROR_MSG]
243
+ #
154
244
  def error! e, dst=nil
155
245
  @action = Edoors::ACT_ERROR
156
246
  @dst = dst||@src
157
247
  @payload[Edoors::FIELD_ERROR_MSG]=e
158
248
  end
159
249
  #
250
+ # applies the effects of the given Link
251
+ #
252
+ # @param [Link] lnk the link to apply effects
253
+ #
254
+ # updates @src with Link @src, clears the destination list
255
+ # adds the Link destinations to @dsts, sets the @link_keys
256
+ #
160
257
  def apply_link! lnk
161
258
  init! lnk.door
162
259
  clear_dsts!
163
- add_dsts lnk.dsts
164
- set_link_fields lnk.fields
260
+ add_dsts *lnk.dsts
261
+ set_link_keys *lnk.keys
165
262
  end
166
263
  #
167
- # data manipulation
264
+ # adds/updates a key value pair into payload
168
265
  #
169
- def []= k, v
170
- @payload[k]=v
171
- compute_link_value! if @link_fields.include? k
172
- end
266
+ # @param [String] k the key
267
+ # @param [Object] v the value
268
+ #
269
+ # \@link_value attribute will be updated if impacted
173
270
  #
174
- def set_data k, v
271
+ def []= k, v
272
+ @link_value[k] = v if @link_keys.include? k
175
273
  @payload[k] = v
176
- compute_link_value! if @link_fields.include? k
177
274
  end
275
+ alias :set_data :[]=
178
276
  #
179
- def [] k
180
- @payload[k]
277
+ # destroys the value paired with a key
278
+ #
279
+ # @param [String] k the key
280
+ #
281
+ # @return the associated value
282
+ #
283
+ # \@link_value attribute will be updated if impacted
284
+ #
285
+ def del_data k
286
+ @link_value.delete k if @link_keys.include? k
287
+ @payload.delete k
181
288
  end
182
289
  #
183
- def get_data k
290
+ # retrieves a data value from a key
291
+ #
292
+ # @param [String] k the key
293
+ #
294
+ def [] k
184
295
  @payload[k]
185
296
  end
186
- alias :data :get_data
297
+ #
298
+ alias :get_data :[]
299
+ alias :data :[]
300
+ #
301
+ # clones the payload of the given Particle
302
+ #
303
+ # @param [Particle] p the Particle to clone the payload of
187
304
  #
188
305
  def clone_data p
189
306
  @payload = p.payload.clone
190
307
  end
191
308
  #
192
- # link value and fields
309
+ # sets the links keys
310
+ #
311
+ # @param [Array] args list of keys to set
193
312
  #
194
- def set_link_fields *args
195
- @link_fields.clear if not @link_fields.empty?
313
+ # \@link_value attribute will be updated
314
+ #
315
+ def set_link_keys *args
316
+ @link_keys.clear if not @link_keys.empty?
196
317
  args.compact!
197
- args.each do |lfs|
198
- lfs.split(',').each do |lf|
199
- @link_fields << lf
200
- end
318
+ args.each do |lf|
319
+ @link_keys << lf
201
320
  end
202
- compute_link_value!
321
+ @link_value = @payload.select { |k,v| @link_keys.include? k }
203
322
  end
204
323
  #
205
- def compute_link_value!
206
- @link_value = @link_fields.inject('') { |s,lf| s+=@payload[lf].to_s if @payload[lf]; s }
324
+ # tries to link the Particle with the given Link
325
+ #
326
+ # @param [Link] link the link to try to link with
327
+ #
328
+ # returns true if the value of the Link is nil
329
+ # otherwise checks if the extracted key values pairs from the Particle
330
+ # payload using the Link value keys as selectors, equals the Link value
331
+ #
332
+ # @return [Boolean] true if the Link links with the Particle
333
+ #
334
+ def link_with? link
335
+ return true if link.value.nil?
336
+ link.value.keys.inject({}) { |h,k| h[k]=@payload[k] if @payload.has_key?(k); h }.eql? link.value
207
337
  end
208
338
  #
209
- # merge particles management
339
+ # merges the given Particle in
340
+ #
341
+ # @param [Particle] p the Particle to merge in
210
342
  #
211
343
  def merge! p
212
344
  @merged << p
213
345
  end
214
346
  #
347
+ # returns a merged Particle
348
+ #
349
+ # @param [Integer] i the index into the merged Particle list
350
+ #
215
351
  def merged i
216
352
  @merged[i]
217
353
  end
218
354
  #
355
+ # shifts the merged Particle list
356
+ #
219
357
  def merged_shift
220
358
  @merged.shift
221
359
  end
222
360
  #
223
- def clear_merged! r=nil
361
+ # recursively clears the merged Particle list
362
+ #
363
+ # @param [Boolean] r releases the cleared Particle if true
364
+ #
365
+ def clear_merged! r=false
224
366
  @merged.each do |p|
225
367
  p.clear_merged! r
226
368
  r.release_p p if r
@@ -228,6 +370,19 @@ module Edoors
228
370
  @merged.clear
229
371
  end
230
372
  #
373
+ # Yields each element in merged Particle list
374
+ #
375
+ def each_merged
376
+ return if not block_given?
377
+ @merged.each do |p| yield p end
378
+ end
379
+ #
380
+ # returns length of merged Pasrticle list
381
+ #
382
+ def merged_length
383
+ @merged.length
384
+ end
385
+ #
231
386
  end
232
387
  #
233
388
  end