1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
# =XMPP4R - XMPP Library for Ruby
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
# Website::http://xmpp4r.github.io
module Jabber
##
# This class manages a list of callbacks.
#
# ==Callbacks management and priority
#
# Callbacks are managed by the class CallbackList. When they are added, a
# priority (just a number or anything Comparable with other priorities) is
# specified. The biggest the priority is, the earliest the callback will be
# considered.
#
# Callbacks are processed for a given set of objects as long as they return
# false. If you want to stop processing, you must return true. Example :
# cbl = CallbackList.new
# c1 = false
# c2 = false
# c3 = false
# cbl.add(10) { c1 = true; 1 }
# cbl.add(5) { c2 = true; true }
# cbl.add(0) { c3 = true }
# cbl.process('aa')
# puts "#{c1} #{c2} #{c3}"
# This example would display "true true false" as callbacks processing was
# stopped after the second callback returned true.
#
# In XMPP4R, callbacks' priorities are quite normalized since we want to be
# able to "cascade" callbacks in a clean way. Here are values your code should
# take into account :
#
# >= 200:: logging & debugging callbacks. Those callbacks should not consume
# elements.
# 100-199:: Where Helpers register their callbacks. The normal value is 100,
# and Helpers shouldn't register something else unless there's a
# very good reason to.
# < 100:: all those numbers are normally available for your application.
# That's enough, don't you think ?
class CallbackList
include Enumerable
# Create a new list of callbacks
def initialize
@list = []
end
##
# Add a callback to the list
#
# List will be sorted afterwards
#
# prio:: [Integer] the callback's priority, the higher, the sooner.
# ref:: [String] the callback's reference
# block:: [Block] a block to execute
# return:: [Jabber::CallbackList] The list, for chaining
def add(prio = 0, ref = nil, proc = nil, &block)
block = proc if proc
@list.push(Callback.new(prio, ref, block))
@list.sort! { |a, b| b.priority <=> a.priority }
self
end
##
# Delete a callback by reference
# ref:: [String] the reference of the callback to delete
# return:: [CallBackList] The list, for chaining
def delete(ref)
@list.delete_if { |item| item.ref == ref }
self
end
def each(&block)
@list.each(&block)
end
##
# Number of elements in the list
# return:: [Integer] The number of elements
def length
@list.length
end
##
# Process an element through all my callbacks. returns e.consumed?
# e:: [Object] The elements to pass to the callback. You can pass
# several, but of course, you block must know how to handle them.
# return:: [Boolean] true if the element has been consumed
def process(*e)
# If somebody adds a new callback the list will get modified
# and sorted(!) while still iterating through it. So we use a
# local copy of @list. Any freshly added callback will receive
# the next stanzas, not the current.
list = @list.dup
# process through callbacks
list.each do |item|
return true if item.block.call(*e) == true
end
false
end
end
# This class is used to store callbacks inside CallbackList. See the
# CallbackList class for more detailed explanations.
class Callback
# The Callback's priority
attr_reader :priority
# The Callback's reference, using for deleting purposes
attr_reader :ref
# The Callback's block to execute
attr_reader :block
##
# Create a new callback
# priority:: [Integer] the callback's priority. The higher, the sooner it
# will be executed
# ref:: [String] The callback's reference
def initialize(priority = 0, ref = nil, block = Proc.new {})
@priority = priority
@ref = ref
@block = block
end
def to_s
"#<#{[self.class, priority, ref].compact * " "}>"
end
end
end
|