module Blather
##
# Base XMPP Stanza
class Stanza < XMPPNode
@@last_id = 0
@@handler_list = []
class_inheritable_array :handler_heirarchy
##
# Registers a callback onto the callback heirarchy stack
#
# Thanks to help from ActiveSupport every class
# that inherits Stanza can register a callback for itself
# which is added to a list and iterated over when looking for
# a callback to use
def self.register(type, name = nil, ns = nil)
@@handler_list << type
self.handler_heirarchy ||= []
self.handler_heirarchy.unshift type
name = name || self.name || type
super name, ns
end
def self.handler_list
@@handler_list
end
##
# Helper method that creates a unique ID for stanzas
def self.next_id
@@last_id += 1
'blather%04x' % @@last_id
end
##
# Creates a new stanza with the same name as the node
# then inherits all the node's attributes and properties
def self.import(node)
self.new(node.element_name).inherit(node)
end
##
# Automatically set the stanza's ID
# and attach it to a document so XPath searching works
def initialize(name = nil)
super
XML::Document.new.root = self
self.name = name.to_s if name
self.id = self.class.next_id
end
##
# Helper method to ask the object if it's an error
def error?
self.type == :error
end
##
# Copies itself then swaps from and to
# then returns the new stanza
def reply
self.copy(true).reply!
end
##
# Swaps from and to
def reply!
self.to, self.from = self.from, self.to
self
end
attribute_accessor :id, :to_sym => false
attribute_writer :to, :from
##
# returns:: JID created from the "to" value of the stanza
def to
JID.new(attributes[:to]) if attributes[:to]
end
##
# returns:: JID created from the "from" value of the stanza
def from
JID.new(attributes[:from]) if attributes[:from]
end
attribute_accessor :type
##
# Transform the stanza into a stanza error
# err_name_or_class can be the name of the error or the error class to use
# type, text, extras are the same as for StanzaError#new
def as_error(err_name_or_class, type, text = nil, extras = [])
klass = (err_name_or_class.is_a?(Class) ? err_name_or_class : StanzaError.class_from_registration(err_name_or_class))
klass.new self, type, text, extras
end
end
end