restfulie 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. data/Gemfile +28 -0
  2. data/Gemfile.lock +128 -0
  3. data/LICENSE +17 -0
  4. data/README.textile +138 -0
  5. data/Rakefile +146 -0
  6. data/lib/restfulie/client/base.rb +36 -0
  7. data/lib/restfulie/client/cache/basic.rb +76 -0
  8. data/lib/restfulie/client/cache/fake.rb +15 -0
  9. data/lib/restfulie/client/cache/http_ext.rb +123 -0
  10. data/lib/restfulie/client/cache/restrictions.rb +13 -0
  11. data/lib/restfulie/client/cache.rb +11 -0
  12. data/lib/restfulie/client/configuration.rb +67 -0
  13. data/lib/restfulie/client/dsl.rb +66 -0
  14. data/lib/restfulie/client/entry_point.rb +61 -0
  15. data/lib/restfulie/client/ext/atom_ext.rb +14 -0
  16. data/lib/restfulie/client/ext/http_ext.rb +22 -0
  17. data/lib/restfulie/client/ext/json_ext.rb +16 -0
  18. data/lib/restfulie/client/feature/base.rb +75 -0
  19. data/lib/restfulie/client/feature/base_request.rb +35 -0
  20. data/lib/restfulie/client/feature/cache.rb +16 -0
  21. data/lib/restfulie/client/feature/enhance_response.rb +12 -0
  22. data/lib/restfulie/client/feature/follow_request.rb +41 -0
  23. data/lib/restfulie/client/feature/history.rb +26 -0
  24. data/lib/restfulie/client/feature/history_request.rb +19 -0
  25. data/lib/restfulie/client/feature/open_search/pattern_matcher.rb +25 -0
  26. data/lib/restfulie/client/feature/open_search.rb +21 -0
  27. data/lib/restfulie/client/feature/serialize_body.rb +32 -0
  28. data/lib/restfulie/client/feature/setup_header.rb +22 -0
  29. data/lib/restfulie/client/feature/throw_error.rb +41 -0
  30. data/lib/restfulie/client/feature/verb.rb +119 -0
  31. data/lib/restfulie/client/feature.rb +5 -0
  32. data/lib/restfulie/client/http/cache.rb +28 -0
  33. data/lib/restfulie/client/http/error.rb +77 -0
  34. data/lib/restfulie/client/http/response_holder.rb +29 -0
  35. data/lib/restfulie/client/http.rb +7 -0
  36. data/lib/restfulie/client/master_delegator.rb +31 -0
  37. data/lib/restfulie/client/mikyung/concatenator.rb +18 -0
  38. data/lib/restfulie/client/mikyung/core.rb +70 -0
  39. data/lib/restfulie/client/mikyung/languages/german.rb +24 -0
  40. data/lib/restfulie/client/mikyung/languages/portuguese.rb +23 -0
  41. data/lib/restfulie/client/mikyung/languages.rb +11 -0
  42. data/lib/restfulie/client/mikyung/rest_process_model.rb +191 -0
  43. data/lib/restfulie/client/mikyung/steady_state_walker.rb +38 -0
  44. data/lib/restfulie/client/mikyung/then_condition.rb +39 -0
  45. data/lib/restfulie/client/mikyung/when_condition.rb +57 -0
  46. data/lib/restfulie/client/mikyung.rb +15 -0
  47. data/lib/restfulie/client.rb +26 -0
  48. data/lib/restfulie/common/converter/atom/base.rb +91 -0
  49. data/lib/restfulie/common/converter/atom/builder.rb +111 -0
  50. data/lib/restfulie/common/converter/atom/helpers.rb +17 -0
  51. data/lib/restfulie/common/converter/atom.rb +12 -0
  52. data/lib/restfulie/common/converter/json/base.rb +87 -0
  53. data/lib/restfulie/common/converter/json/builder.rb +102 -0
  54. data/lib/restfulie/common/converter/json/helpers.rb +17 -0
  55. data/lib/restfulie/common/converter/json.rb +12 -0
  56. data/lib/restfulie/common/converter/open_search/descriptor.rb +32 -0
  57. data/lib/restfulie/common/converter/open_search.rb +16 -0
  58. data/lib/restfulie/common/converter/values.rb +33 -0
  59. data/lib/restfulie/common/converter/xml/base.rb +63 -0
  60. data/lib/restfulie/common/converter/xml/builder.rb +113 -0
  61. data/lib/restfulie/common/converter/xml/helpers.rb +17 -0
  62. data/lib/restfulie/common/converter/xml/link.rb +30 -0
  63. data/lib/restfulie/common/converter/xml/links.rb +21 -0
  64. data/lib/restfulie/common/converter/xml.rb +14 -0
  65. data/lib/restfulie/common/converter.rb +43 -0
  66. data/lib/restfulie/common/core_ext/hash.rb +18 -0
  67. data/lib/restfulie/common/core_ext.rb +1 -0
  68. data/lib/restfulie/common/error.rb +19 -0
  69. data/lib/restfulie/common/links.rb +9 -0
  70. data/lib/restfulie/common/logger.rb +19 -0
  71. data/lib/restfulie/common/representation/atom/atom.rng +597 -0
  72. data/lib/restfulie/common/representation/atom/base.rb +142 -0
  73. data/lib/restfulie/common/representation/atom/category.rb +41 -0
  74. data/lib/restfulie/common/representation/atom/entry.rb +59 -0
  75. data/lib/restfulie/common/representation/atom/factory.rb +43 -0
  76. data/lib/restfulie/common/representation/atom/feed.rb +110 -0
  77. data/lib/restfulie/common/representation/atom/link.rb +68 -0
  78. data/lib/restfulie/common/representation/atom/person.rb +48 -0
  79. data/lib/restfulie/common/representation/atom/source.rb +59 -0
  80. data/lib/restfulie/common/representation/atom/tag_collection.rb +38 -0
  81. data/lib/restfulie/common/representation/atom/xml.rb +90 -0
  82. data/lib/restfulie/common/representation/atom.rb +20 -0
  83. data/lib/restfulie/common/representation/generic.rb +22 -0
  84. data/lib/restfulie/common/representation/json/base.rb +27 -0
  85. data/lib/restfulie/common/representation/json/keys_as_methods.rb +74 -0
  86. data/lib/restfulie/common/representation/json/link.rb +29 -0
  87. data/lib/restfulie/common/representation/json/link_collection.rb +23 -0
  88. data/lib/restfulie/common/representation/json.rb +13 -0
  89. data/lib/restfulie/common/representation/links.rb +11 -0
  90. data/lib/restfulie/common/representation.rb +3 -0
  91. data/lib/restfulie/common.rb +18 -0
  92. data/lib/restfulie/server/action_controller/base.rb +48 -0
  93. data/lib/restfulie/server/action_controller/params_parser.rb +100 -0
  94. data/lib/restfulie/server/action_controller/patch.rb +6 -0
  95. data/lib/restfulie/server/action_controller/restful_responder.rb +12 -0
  96. data/lib/restfulie/server/action_controller/trait/cacheable.rb +81 -0
  97. data/lib/restfulie/server/action_controller/trait/created.rb +17 -0
  98. data/lib/restfulie/server/action_controller/trait.rb +9 -0
  99. data/lib/restfulie/server/action_controller.rb +11 -0
  100. data/lib/restfulie/server/action_view/helpers.rb +50 -0
  101. data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +21 -0
  102. data/lib/restfulie/server/action_view/template_handlers.rb +30 -0
  103. data/lib/restfulie/server/action_view.rb +10 -0
  104. data/lib/restfulie/server/configuration.rb +24 -0
  105. data/lib/restfulie/server/controller.rb +74 -0
  106. data/lib/restfulie/server/core_ext/array.rb +61 -0
  107. data/lib/restfulie/server/core_ext.rb +1 -0
  108. data/lib/restfulie/server.rb +25 -0
  109. data/lib/restfulie/version.rb +14 -0
  110. data/lib/restfulie.rb +34 -0
  111. metadata +242 -0
@@ -0,0 +1,142 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ module Atom
5
+ class Base < XML
6
+ ATOM_ATTRIBUTES = {
7
+ :feed => {
8
+ :required => [:id, :title, :updated],
9
+ :recommended => [:author, :link],
10
+ :optional => [:category, :contributor, :rights, :generator, :icon, :logo, :subtitle]
11
+ },
12
+
13
+ :entry => {
14
+ :required => [:id, :title, :updated],
15
+ :recommended => [:author, :link, :content, :summary],
16
+ :optional => [:category, :contributor, :rights, :published, :source]
17
+ }
18
+ }
19
+
20
+ def initialize(xml_obj = nil)
21
+ @authors = nil
22
+ @contributors = nil
23
+ @links = nil
24
+ @categories = nil
25
+ @reserved = []
26
+ super(xml_obj)
27
+ end
28
+
29
+ # lists all extension points available in this entry
30
+ def extensions
31
+ result = []
32
+ @doc.children.each do |e|
33
+ if e.element?
34
+ result << e unless @reserved.map(&:to_s).include?(e.node_name)
35
+ end
36
+ end
37
+ return result
38
+ end
39
+
40
+ # simpletext
41
+ def id
42
+ text("id")
43
+ end
44
+
45
+ def id=(value)
46
+ set_text("id", value)
47
+ end
48
+
49
+ # text
50
+ def title
51
+ text("title")
52
+ end
53
+
54
+ def title=(value)
55
+ set_text("title", value)
56
+ end
57
+
58
+ def updated
59
+ value = text("updated")
60
+ Time.parse(value) unless value.nil?
61
+ end
62
+
63
+ def updated=(value)
64
+ set_text("updated", value)
65
+ end
66
+
67
+ def published
68
+ value = text("published")
69
+ Time.parse(value) unless value.nil?
70
+ end
71
+
72
+ def published=(value)
73
+ set_text("published", value)
74
+ end
75
+
76
+ # text
77
+ def rights
78
+ text("rights")
79
+ end
80
+
81
+ def rights=(value)
82
+ set_text("rights", value)
83
+ end
84
+
85
+ # Author have name, and optional uri and email, this describes a person
86
+ def authors
87
+ return @authors if @authors
88
+
89
+ @authors = TagCollection.new(@doc)
90
+ @doc.xpath("xmlns:author").each do |author|
91
+ @authors << Person.new("author", author)
92
+ end
93
+ @authors
94
+
95
+ end
96
+
97
+ def contributors
98
+ return @contributors if @contributors
99
+
100
+ @contributors = TagCollection.new(@doc)
101
+ @doc.xpath("xmlns:author").each do |contributor|
102
+ @contributors << Person.new("contributor", contributor)
103
+ end
104
+ @contributors
105
+ end
106
+
107
+ include Restfulie::Common::Links
108
+
109
+ # It has one required attribute, href, and five optional attributes: rel, type, hreflang, title, and length
110
+ def links
111
+ return @links if @links
112
+
113
+ @links = TagCollection.new(@doc) do |array, symbol, *args|
114
+ linkset = array.select {|link| link.rel == symbol.to_s }
115
+ unless linkset.empty?
116
+ linkset.size == 1 ? linkset.first : linkset
117
+ else
118
+ nil
119
+ end
120
+ end
121
+ @doc.xpath("xmlns:link").each do |link|
122
+ @links << Link.new(link)
123
+ end
124
+ @links
125
+
126
+ end
127
+
128
+ def categories
129
+ return @categories if @categories
130
+
131
+ @categories = TagCollection.new(@doc)
132
+ @doc.xpath("xmlns:category").each do |category|
133
+ @categories << Link.new(category)
134
+ end
135
+ @categories
136
+
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,41 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ module Atom
5
+ class Category < XML
6
+ def initialize(options_or_obj)
7
+ if options_or_obj.kind_of?(Hash)
8
+ @doc = Nokogiri::XML::Document.new()
9
+ options_or_obj = create_element("category", options_or_obj)
10
+ end
11
+ super(options_or_obj)
12
+ end
13
+
14
+ def term
15
+ @doc["term"]
16
+ end
17
+
18
+ def term=(value)
19
+ @doc["term"] = value
20
+ end
21
+
22
+ def scheme
23
+ @doc["scheme"]
24
+ end
25
+
26
+ def scheme=(value)
27
+ @doc["scheme"] = value
28
+ end
29
+
30
+ def label
31
+ @doc["label"]
32
+ end
33
+
34
+ def label=(value)
35
+ @doc["label"] = value
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,59 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ module Atom
5
+ class Entry < Base
6
+ def initialize(xml_obj = nil)
7
+ @source = nil
8
+ super(xml_obj)
9
+ @reserved = Base::ATOM_ATTRIBUTES[:entry][:required] + Base::ATOM_ATTRIBUTES[:entry][:recommended] + Base::ATOM_ATTRIBUTES[:entry][:optional]
10
+ end
11
+
12
+ # text
13
+ def content
14
+ text("content")
15
+ end
16
+
17
+ def content=(value)
18
+ set_text("content", value)
19
+ end
20
+
21
+ # text
22
+ def summary
23
+ text("summary")
24
+ end
25
+
26
+ def summary=(value)
27
+ set_text("summary", value)
28
+ end
29
+
30
+ # rfc 3339
31
+ def published
32
+ value = text("published")
33
+ Time.parse(value) unless value.nil?
34
+ end
35
+
36
+ def published=(value)
37
+ set_text("published", value)
38
+ end
39
+
40
+ # comp: id, title, udpated, rights (optional)
41
+ def source
42
+ unless @source
43
+ @doc.xpath("xmlns:source").each do |source|
44
+ @source = Generator.new(source)
45
+ end
46
+ end
47
+
48
+ return source
49
+ end
50
+
51
+ def source=(obj)
52
+ @source = obj
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+
@@ -0,0 +1,43 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ module Atom
5
+ # Create a new Representation::Atom object using a +string_or_io+
6
+ # object.
7
+ #
8
+ # Examples
9
+ # xml = IO.read("spec/units/lib/atoms/full_atom.xml")
10
+ # atom = Restfulie::Common::Representation::Atom.new(xml)
11
+ class Factory
12
+ # RelaxNG file to validate atom
13
+ RELAXNG_ATOM = File.join(File.dirname(__FILE__), 'atom.rng')
14
+
15
+ if Nokogiri::VERSION_INFO["libxml"]["loaded"] < "2.7.7"
16
+ puts "WARNING! In order to use schema validation on atom representations you need libxml version 2.7.7 or superior loaded in your system."
17
+ SCHEMA = nil
18
+ else
19
+ SCHEMA = ::Nokogiri::XML::RelaxNG(File.open(RELAXNG_ATOM))
20
+ end
21
+
22
+ def self.create(string_or_io)
23
+ doc = string_or_io.kind_of?(Nokogiri::XML::Document) ? string_or_io : Nokogiri::XML(string_or_io)
24
+
25
+ if SCHEMA && !(errors = SCHEMA.validate(doc)).empty?
26
+ raise AtomInvalid.new("Invalid Atom: "+ errors.join(", "))
27
+ end
28
+
29
+ case doc.root.name
30
+ when "feed"
31
+ Restfulie::Common::Representation::Atom::Feed.new(doc)
32
+ when "entry"
33
+ Restfulie::Common::Representation::Atom::Entry.new(doc)
34
+ end
35
+ end
36
+ end
37
+
38
+ class AtomInvalid < StandardError
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,110 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ module Atom
5
+ class Feed < Base
6
+ def initialize(xml_obj = nil)
7
+ @generator = nil
8
+ @entries = nil
9
+ super(xml_obj)
10
+ @reserved = Base::ATOM_ATTRIBUTES[:feed][:required] + Base::ATOM_ATTRIBUTES[:feed][:recommended] + Base::ATOM_ATTRIBUTES[:feed][:optional] + [:entry]
11
+ end
12
+
13
+ def entries
14
+ unless @entries
15
+ @entries = TagCollection.new(@doc)
16
+ @doc.xpath("xmlns:entry").each do |entry|
17
+ @entries << Entry.new(entry)
18
+ end
19
+ end
20
+
21
+ return @entries
22
+ end
23
+
24
+ # comp: attr: uri, version (optionals); content (mandatory)
25
+ def generator
26
+ unless @generator
27
+ @doc.xpath("xmlns:generator").each do |generator|
28
+ @generator = Generator.new(generator)
29
+ end
30
+ end
31
+
32
+ return generator
33
+ end
34
+
35
+ def generator=(obj)
36
+ @generator = obj
37
+ end
38
+
39
+ # simple text
40
+ def icon
41
+ text("icon")
42
+ end
43
+
44
+ def icon=(value)
45
+ set_text("icon", value)
46
+ end
47
+
48
+ # simple text
49
+ def logo
50
+ text("logo")
51
+ end
52
+
53
+ def logo=(value)
54
+ set_text("logo", value)
55
+ end
56
+
57
+ # text
58
+ def subtitle
59
+ text("subtitle")
60
+ end
61
+
62
+ def subtitle=(value)
63
+ set_text("subtitle", value)
64
+ end
65
+ end
66
+
67
+ class Generator < XML
68
+ def initialize(options_or_obj)
69
+ if options_or_obj.kind_of?(Hash)
70
+ @doc = Nokogiri::XML::Document.new()
71
+ node = @doc.create_element("generator")
72
+ node.add_namespace_definition(nil, "http://www.w3.org/2005/Atom")
73
+ node.parent = @doc
74
+ super(node)
75
+ options_or_obj.each do |key,value|
76
+ self.send("#{key}=".to_sym, value)
77
+ end
78
+ else
79
+ super(options_or_obj)
80
+ end
81
+ end
82
+
83
+ def content
84
+ @doc.content
85
+ end
86
+
87
+ def content=(value)
88
+ @doc.content = value
89
+ end
90
+
91
+ def uri
92
+ @doc["uri"]
93
+ end
94
+
95
+ def uri=(value)
96
+ @doc["uri"] = value
97
+ end
98
+
99
+ def version
100
+ @doc["version"]
101
+ end
102
+
103
+ def version=(value)
104
+ @doc["version"] = value
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,68 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ module Atom
5
+ class Link < XML
6
+ def initialize(options_or_obj)
7
+ if options_or_obj.kind_of?(Hash)
8
+ @doc = Nokogiri::XML::Document.new()
9
+ options_or_obj = create_element("link", options_or_obj)
10
+ end
11
+ super(options_or_obj)
12
+ end
13
+
14
+ def href
15
+ @doc["href"]
16
+ end
17
+
18
+ def href=(value)
19
+ @doc["href"] = value
20
+ end
21
+
22
+ def rel
23
+ @doc["rel"]
24
+ end
25
+
26
+ def rel=(value)
27
+ @doc["rel"] = value
28
+ end
29
+
30
+ if method_defined?(:type)
31
+ alias_method :__type__, :type
32
+ end
33
+ def type
34
+ @doc["type"]
35
+ end
36
+
37
+ def type=(value)
38
+ @doc["type"] = value
39
+ end
40
+
41
+ def hreflang
42
+ @doc["hreflang"]
43
+ end
44
+
45
+ def hreflang=(value)
46
+ @doc["hreflang"] = value
47
+ end
48
+
49
+ def title
50
+ @doc["title"]
51
+ end
52
+
53
+ def title=(value)
54
+ @doc["title"] = value
55
+ end
56
+
57
+ def length
58
+ @doc["length"]
59
+ end
60
+
61
+ def length=(value)
62
+ @doc["length"] = value
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,48 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ module Atom
5
+ class Person < XML
6
+ def initialize(node_type, options_or_obj)
7
+ if options_or_obj.kind_of?(Hash)
8
+ @doc = Nokogiri::XML::Document.new()
9
+ node = @doc.create_element(node_type)
10
+ node.add_namespace_definition(nil, "http://www.w3.org/2005/Atom")
11
+ node.parent = @doc
12
+ super(node)
13
+ options_or_obj.each do |key,value|
14
+ self.send("#{key}=".to_sym, value)
15
+ end
16
+ else
17
+ super(options_or_obj)
18
+ end
19
+ end
20
+
21
+ def name
22
+ text("name")
23
+ end
24
+
25
+ def name=(value)
26
+ set_text("name", value)
27
+ end
28
+
29
+ def uri
30
+ text("uri")
31
+ end
32
+
33
+ def uri=(value)
34
+ set_text("uri", value)
35
+ end
36
+
37
+ def email
38
+ text("email")
39
+ end
40
+
41
+ def email=(value)
42
+ set_text("email", value)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,59 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ module Atom
5
+ class Source < XML
6
+ def initialize(options_or_obj)
7
+ if options_or_obj.kind_of?(Hash)
8
+ @doc = Nokogiri::XML::Document.new()
9
+ node = @doc.create_element("source")
10
+ node.add_namespace_definition(nil, "http://www.w3.org/2005/Atom")
11
+ node.parent = @doc
12
+ super(node)
13
+ options_or_obj.each do |key,value|
14
+ self.send("#{key}=".to_sym, value)
15
+ end
16
+ else
17
+ super(options_or_obj)
18
+ end
19
+ end
20
+
21
+ def id
22
+ text("id")
23
+ end
24
+
25
+ def id=(value)
26
+ set_text("id", value)
27
+ end
28
+
29
+ # text
30
+ def title
31
+ text("title")
32
+ end
33
+
34
+ def title=(value)
35
+ set_text("title", value)
36
+ end
37
+
38
+ def updated
39
+ value = text("updated")
40
+ Time.parse(value) unless value.nil?
41
+ end
42
+
43
+ def updated=(value)
44
+ set_text("updated", value)
45
+ end
46
+
47
+ # text
48
+ def rights
49
+ text("rights")
50
+ end
51
+
52
+ def rights=(value)
53
+ set_text("rights", value)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,38 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ module Atom
5
+ class TagCollection < ::Array
6
+ def initialize(parent_node, &block)
7
+ @node = parent_node
8
+ @method_missing_block = block_given? ? block : nil
9
+ super(0)
10
+ end
11
+
12
+ def <<(obj)
13
+ obj = [obj] unless obj.kind_of?(Array)
14
+ obj.each do |o|
15
+ o.doc.parent = @node
16
+ super(o)
17
+ end
18
+ end
19
+
20
+ def delete(obj)
21
+ if super(obj)
22
+ obj.doc.unlink
23
+ obj = nil
24
+ end
25
+ end
26
+
27
+ def method_missing(symbol, *args, &block)
28
+ if @method_missing_block
29
+ @method_missing_block.call(self, symbol, *args)
30
+ else
31
+ super
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,90 @@
1
+ module Restfulie
2
+ module Common
3
+ module Representation
4
+ module Atom
5
+ class XML
6
+ attr_accessor :doc
7
+
8
+ def initialize(xml_obj = nil)
9
+ if xml_obj
10
+ xml_obj.kind_of?(Nokogiri::XML::Document) ? @doc = xml_obj.root : @doc = xml_obj
11
+ else
12
+ @doc = Nokogiri::XML::Document.new
13
+ root_node = @doc.create_element(atom_type.to_s)
14
+ root_node.add_namespace_definition(nil, "http://www.w3.org/2005/Atom")
15
+ root_node.parent = @doc
16
+ @doc = @doc.root
17
+ end
18
+ end
19
+
20
+ # Tools
21
+ def css(*args)
22
+ @doc.css(*args)
23
+ end
24
+
25
+ def xpath(*args)
26
+ @doc.xpath(*args)
27
+ end
28
+
29
+ def atom_type
30
+ self.class.name.demodulize.downcase
31
+ end
32
+
33
+ def to_xml
34
+ @doc.to_xml
35
+ end
36
+
37
+ def to_s
38
+ to_xml
39
+ end
40
+
41
+ def method_missing(method)
42
+ text(method) || super
43
+ end
44
+
45
+ protected
46
+
47
+ def text(node_name)
48
+ (node = @doc.at_xpath("xmlns:#{node_name}")) ? node.content : nil
49
+ end
50
+
51
+ def set_text(node_name, value)
52
+ if (node = @doc.at_xpath("xmlns:#{node_name}"))
53
+ value = value.xmlschema if value.kind_of?(Time) || value.kind_of?(DateTime)
54
+ node.content = value
55
+ else
56
+ node = create_element(node_name, value)
57
+ node.parent = @doc
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def create_element(node, *args)
64
+ node = @doc.document.create_element(node) do |n|
65
+ args.each do |arg|
66
+ case arg
67
+ # Adding XML attributes
68
+ when Hash
69
+ arg.each { |k,v|
70
+ key = k.to_s
71
+ if key =~ /^xmlns(:\w+)?$/
72
+ ns_name = key.split(":", 2)[1]
73
+ n.add_namespace_definition(ns_name, v)
74
+ next
75
+ end
76
+ n[k.to_s] = v.to_s
77
+ }
78
+ # Adding XML node content
79
+ else
80
+ arg.kind_of?(Time) || arg.kind_of?(DateTime) ? content = arg.xmlschema : content = arg
81
+ n.content = content
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end