Class: Jabber::XMPPElement

Inherits:
REXML::Element show all
Defined in:
lib/xmpp4r/xmppelement.rb

Overview

This class represents an XML element and provides functionality for automatic casting of XML element classes according to their element name and namespace.

Deriving classes must met these criteria:

  • The element name and namespace must be specified by calling the name_xmlns class method

  • The class constructor must be callable with no mandatory parameter

Constant Summary collapse

@@name_xmlns_classes =
{}
@@force_xmlns =
false

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from REXML::Element

#==, #delete_elements, #each_elements, #first_element, #first_element_content, #first_element_text, #import, #replace_element_content, #replace_element_text

Constructor Details

#initialize(*arg) ⇒ XMPPElement

Initialize this element, which will then be initialized with the name registered with name_xmlns.



98
99
100
101
102
103
104
105
106
107
108
# File 'lib/xmpp4r/xmppelement.rb', line 98

def initialize(*arg)
  if arg.empty?
    name, xmlns = self.class::name_xmlns_for_class(self.class)
    super(name)
    if self.class::force_xmlns?
      add_namespace(xmlns)
    end
  else
    super
  end
end

Class Method Details

.class_for_name_xmlns(name, xmlns) ⇒ Object

Find a class for given name and namespace

name
String
xmlns
String
result

A descendant of XMPPElement or REXML::Element



70
71
72
73
74
75
76
77
78
# File 'lib/xmpp4r/xmppelement.rb', line 70

def self.class_for_name_xmlns(name, xmlns)
  if @@name_xmlns_classes.has_key? [name, xmlns]
    @@name_xmlns_classes[[name, xmlns]]
  elsif @@name_xmlns_classes.has_key? [name, nil]
    @@name_xmlns_classes[[name, nil]]
  else
    REXML::Element
  end
end

.force_xmlns(force) ⇒ Object

Set whether this element is always built with an xmlns attribute



35
36
37
# File 'lib/xmpp4r/xmppelement.rb', line 35

def self.force_xmlns(force)
  @@force_xmlns = force
end

.force_xmlns?Boolean

Whether this element is always built with an xmlns attribute

Returns:

  • (Boolean)


41
42
43
# File 'lib/xmpp4r/xmppelement.rb', line 41

def self.force_xmlns?
  @@force_xmlns
end

.import(element) ⇒ Object

Import another REXML::Element descendant to:

  • Either an element class that registered with name and xmlns before

  • Or if none was found to the class itself (you may call this class method on a deriving class)



86
87
88
89
90
91
92
93
# File 'lib/xmpp4r/xmppelement.rb', line 86

def self.import(element)
  klass = class_for_name_xmlns(element.name, element.namespace)
  if klass != self and klass.ancestors.include?(self)
    klass.new.import(element)
  else
    self.new.import(element)
  end
end

.name_xmlns(name, xmlns = nil) ⇒ Object

Specify XML element name and xmlns for a deriving class, this pair and the class will be added to a global pool

If the namespace is nil the class is a “wildcard class” matching elements with any xmlns if no other class with that namespace was defined



29
30
31
# File 'lib/xmpp4r/xmppelement.rb', line 29

def self.name_xmlns(name, xmlns=nil)
  @@name_xmlns_classes[[name, xmlns]] = self
end

.name_xmlns_for_class(klass) ⇒ Object

Find the name and namespace for a given class. This class must have registered these two values by calling name_xmlns at definition time.

Raises an exception if none was found

klass
Class
result
String, String

name and namespace



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/xmpp4r/xmppelement.rb', line 53

def self.name_xmlns_for_class(klass)
  klass.ancestors.each do |klass1|
    @@name_xmlns_classes.each do |name_xmlns,k|
      if klass1 == k
        return name_xmlns
      end
    end
  end

  raise NoNameXmlnsRegistered.new(klass)
end

Instance Method Details

#cloneObject



140
141
142
143
144
145
# File 'lib/xmpp4r/xmppelement.rb', line 140

def clone
  cloned = self.class.new
  cloned.add_attributes self.attributes.clone
  cloned.context = @context
  cloned
end

#parent=(new_parent) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
# File 'lib/xmpp4r/xmppelement.rb', line 128

def parent=(new_parent)
  if parent and parent.namespace('') == namespace('') and attributes['xmlns'].nil?
    add_namespace parent.namespace('')
  end

  super

  if new_parent and new_parent.namespace('') == namespace('')
    delete_namespace
  end
end

#set_xml_lang(l) ⇒ Object

Set XML language attribute (chainable)



162
163
164
165
# File 'lib/xmpp4r/xmppelement.rb', line 162

def set_xml_lang(l)
  self.xml_lang = l
  self
end

#typed_add(element) ⇒ Object

Add a child element which will be imported according to the child’s name and xmlns

element
REXML::Element

Child

result
REXML::Element or descendant of XMPPElement

New child



115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/xmpp4r/xmppelement.rb', line 115

def typed_add(element)
  if element.kind_of? REXML::Element
    element_ns = (element.namespace.to_s == '') ? namespace : element.namespace

    klass = XMPPElement::class_for_name_xmlns(element.name, element_ns)
    if klass != element.class
      element = klass.import(element)
    end
  end

  super(element)
end

#xml_langObject

Generic XML attribute ‘xml:lang’ (REXML provides no shortcut)



150
151
152
# File 'lib/xmpp4r/xmppelement.rb', line 150

def xml_lang
  attributes['xml:lang']
end

#xml_lang=(l) ⇒ Object

Set XML language attribute



156
157
158
# File 'lib/xmpp4r/xmppelement.rb', line 156

def xml_lang=(l)
  attributes['xml:lang'] = l
end