tokamak 1.0.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +27 -0
  4. data/Gemfile.lock +77 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.rdoc +69 -0
  7. data/Rakefile +50 -0
  8. data/VERSION +1 -0
  9. data/lib/tokamak.rb +21 -0
  10. data/lib/tokamak/atom.rb +8 -0
  11. data/lib/tokamak/atom/base.rb +87 -0
  12. data/lib/tokamak/atom/builder.rb +107 -0
  13. data/lib/tokamak/atom/helpers.rb +13 -0
  14. data/lib/tokamak/error.rb +6 -0
  15. data/lib/tokamak/json.rb +10 -0
  16. data/lib/tokamak/json/base.rb +83 -0
  17. data/lib/tokamak/json/builder.rb +98 -0
  18. data/lib/tokamak/json/helpers.rb +13 -0
  19. data/lib/tokamak/representation.rb +3 -0
  20. data/lib/tokamak/representation/atom.rb +18 -0
  21. data/lib/tokamak/representation/atom/atom.rng +597 -0
  22. data/lib/tokamak/representation/atom/base.rb +140 -0
  23. data/lib/tokamak/representation/atom/category.rb +39 -0
  24. data/lib/tokamak/representation/atom/entry.rb +56 -0
  25. data/lib/tokamak/representation/atom/factory.rb +48 -0
  26. data/lib/tokamak/representation/atom/feed.rb +108 -0
  27. data/lib/tokamak/representation/atom/link.rb +66 -0
  28. data/lib/tokamak/representation/atom/person.rb +46 -0
  29. data/lib/tokamak/representation/atom/source.rb +57 -0
  30. data/lib/tokamak/representation/atom/tag_collection.rb +36 -0
  31. data/lib/tokamak/representation/atom/xml.rb +94 -0
  32. data/lib/tokamak/representation/generic.rb +20 -0
  33. data/lib/tokamak/representation/json.rb +11 -0
  34. data/lib/tokamak/representation/json/base.rb +25 -0
  35. data/lib/tokamak/representation/json/keys_as_methods.rb +72 -0
  36. data/lib/tokamak/representation/json/link.rb +27 -0
  37. data/lib/tokamak/representation/json/link_collection.rb +21 -0
  38. data/lib/tokamak/representation/links.rb +9 -0
  39. data/lib/tokamak/values.rb +29 -0
  40. data/lib/tokamak/xml.rb +12 -0
  41. data/lib/tokamak/xml/base.rb +60 -0
  42. data/lib/tokamak/xml/builder.rb +115 -0
  43. data/lib/tokamak/xml/helpers.rb +13 -0
  44. data/lib/tokamak/xml/link.rb +31 -0
  45. data/lib/tokamak/xml/links.rb +35 -0
  46. data/spec/integration/atom/atom_spec.rb +191 -0
  47. data/spec/integration/full_atom.xml +92 -0
  48. data/spec/integration/full_json.js +46 -0
  49. data/spec/integration/json/json_spec.rb +172 -0
  50. data/spec/integration/xml/xml_spec.rb +203 -0
  51. data/spec/spec_helper.rb +12 -0
  52. metadata +248 -0
@@ -0,0 +1,140 @@
1
+ module Tokamak
2
+ module Representation
3
+ module Atom
4
+ class Base < XML
5
+ ATOM_ATTRIBUTES = {
6
+ :feed => {
7
+ :required => [:id, :title, :updated],
8
+ :recommended => [:author, :link],
9
+ :optional => [:category, :contributor, :rights, :generator, :icon, :logo, :subtitle]
10
+ },
11
+
12
+ :entry => {
13
+ :required => [:id, :title, :updated],
14
+ :recommended => [:author, :link, :content, :summary],
15
+ :optional => [:category, :contributor, :rights, :published, :source]
16
+ }
17
+ }
18
+
19
+ def initialize(xml_obj = nil)
20
+ @authors = nil
21
+ @contributors = nil
22
+ @links = nil
23
+ @categories = nil
24
+ @reserved = []
25
+ super(xml_obj)
26
+ end
27
+
28
+ # lists all extension points available in this entry
29
+ def extensions
30
+ result = []
31
+ @doc.children.each do |e|
32
+ if e.element? && !@reserved.map(&:to_s).include?(e.node_name)
33
+ result << e
34
+ end
35
+ end
36
+ return result
37
+ end
38
+
39
+ # simpletext
40
+ def id
41
+ text("id")
42
+ end
43
+
44
+ def id=(value)
45
+ set_text("id", value)
46
+ end
47
+
48
+ # text
49
+ def title
50
+ text("title")
51
+ end
52
+
53
+ def title=(value)
54
+ set_text("title", value)
55
+ end
56
+
57
+ def updated
58
+ value = text("updated")
59
+ Time.parse(value) unless value.nil?
60
+ end
61
+
62
+ def updated=(value)
63
+ set_text("updated", value)
64
+ end
65
+
66
+ def published
67
+ value = text("published")
68
+ Time.parse(value) unless value.nil?
69
+ end
70
+
71
+ def published=(value)
72
+ set_text("published", value)
73
+ end
74
+
75
+ # text
76
+ def rights
77
+ text("rights")
78
+ end
79
+
80
+ def rights=(value)
81
+ set_text("rights", value)
82
+ end
83
+
84
+ # Author have name, and optional uri and email, this describes a person
85
+ def authors
86
+ return @authors if @authors
87
+
88
+ @authors = TagCollection.new(@doc)
89
+ @doc.xpath("xmlns:author").each do |author|
90
+ @authors << Person.new("author", author)
91
+ end
92
+ @authors
93
+
94
+ end
95
+
96
+ def contributors
97
+ return @contributors if @contributors
98
+
99
+ @contributors = TagCollection.new(@doc)
100
+ @doc.xpath("xmlns:author").each do |contributor|
101
+ @contributors << Person.new("contributor", contributor)
102
+ end
103
+ @contributors
104
+ end
105
+
106
+ include Tokamak::Representation::Links
107
+
108
+ # It has one required attribute, href, and five optional attributes: rel, type, hreflang, title, and length
109
+ def links
110
+ return @links if @links
111
+
112
+ @links = TagCollection.new(@doc) do |array, symbol, *args|
113
+ linkset = array.select {|link| link.rel == symbol.to_s }
114
+ unless linkset.empty?
115
+ linkset.size == 1 ? linkset.first : linkset
116
+ else
117
+ nil
118
+ end
119
+ end
120
+ @doc.xpath("xmlns:link").each do |link|
121
+ @links << Link.new(link)
122
+ end
123
+ @links
124
+
125
+ end
126
+
127
+ def categories
128
+ return @categories if @categories
129
+
130
+ @categories = TagCollection.new(@doc)
131
+ @doc.xpath("xmlns:category").each do |category|
132
+ @categories << Link.new(category)
133
+ end
134
+ @categories
135
+
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,39 @@
1
+ module Tokamak
2
+ module Representation
3
+ module Atom
4
+ class Category < XML
5
+ def initialize(options_or_obj)
6
+ if options_or_obj.kind_of?(Hash)
7
+ @doc = Nokogiri::XML::Document.new()
8
+ options_or_obj = create_element("category", options_or_obj)
9
+ end
10
+ super(options_or_obj)
11
+ end
12
+
13
+ def term
14
+ @doc["term"]
15
+ end
16
+
17
+ def term=(value)
18
+ @doc["term"] = value
19
+ end
20
+
21
+ def scheme
22
+ @doc["scheme"]
23
+ end
24
+
25
+ def scheme=(value)
26
+ @doc["scheme"] = value
27
+ end
28
+
29
+ def label
30
+ @doc["label"]
31
+ end
32
+
33
+ def label=(value)
34
+ @doc["label"] = value
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,56 @@
1
+ module Tokamak
2
+ module Representation
3
+ module Atom
4
+ class Entry < Base
5
+ def initialize(xml_obj = nil)
6
+ @source = nil
7
+ super(xml_obj)
8
+ @reserved = Base::ATOM_ATTRIBUTES[:entry][:required] + Base::ATOM_ATTRIBUTES[:entry][:recommended] + Base::ATOM_ATTRIBUTES[:entry][:optional]
9
+ end
10
+
11
+ # text
12
+ def content
13
+ text("content")
14
+ end
15
+
16
+ def content=(value)
17
+ set_text("content", value)
18
+ end
19
+
20
+ # text
21
+ def summary
22
+ text("summary")
23
+ end
24
+
25
+ def summary=(value)
26
+ set_text("summary", value)
27
+ end
28
+
29
+ # rfc 3339
30
+ def published
31
+ value = text("published")
32
+ Time.parse(value) unless value.nil?
33
+ end
34
+
35
+ def published=(value)
36
+ set_text("published", value)
37
+ end
38
+
39
+ # comp: id, title, udpated, rights (optional)
40
+ def source
41
+ unless @source
42
+ @doc.xpath("xmlns:source").each do |source|
43
+ @source = Generator.new(source)
44
+ end
45
+ end
46
+
47
+ return source
48
+ end
49
+
50
+ def source=(obj)
51
+ @source = obj
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,48 @@
1
+ module Tokamak
2
+ module Representation
3
+ module Atom
4
+ # Create a new Representation::Atom object using a +string_or_io+
5
+ # object.
6
+ #
7
+ # Examples
8
+ # xml = IO.read("spec/units/lib/atoms/full_atom.xml")
9
+ # atom = Tokamak::Representation::Atom.new(xml)
10
+ class Factory
11
+ # RelaxNG file to validate atom
12
+ RELAXNG_ATOM = File.join(File.dirname(__FILE__), 'atom.rng')
13
+
14
+ if Nokogiri::VERSION_INFO["libxml"]["loaded"] < "2.7.7"
15
+ puts "WARNING! In order to use schema validation on atom representations you need libxml version 2.7.7 or superior loaded in your system."
16
+ SCHEMA = nil
17
+ else
18
+ SCHEMA = ::Nokogiri::XML::RelaxNG(File.open(RELAXNG_ATOM))
19
+ end
20
+
21
+ def self.create(string_or_io)
22
+ doc = string_or_io.kind_of?(Nokogiri::XML::Document) ? string_or_io : Nokogiri::XML(string_or_io)
23
+
24
+ if SCHEMA && !(errors = SCHEMA.validate(doc)).empty?
25
+ raise AtomInvalid.new("Invalid Atom: "+ errors.join(", "))
26
+ end
27
+
28
+ representation_for doc
29
+
30
+ end
31
+
32
+ private
33
+ def self.representation_for(doc)
34
+ case doc.root.name
35
+ when "feed"
36
+ Tokamak::Representation::Atom::Feed.new(doc)
37
+ when "entry"
38
+ Tokamak::Representation::Atom::Entry.new(doc)
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ class AtomInvalid < StandardError
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,108 @@
1
+ module Tokamak
2
+ module Representation
3
+ module Atom
4
+ class Feed < Base
5
+ def initialize(xml_obj = nil)
6
+ @generator = nil
7
+ @entries = nil
8
+ super(xml_obj)
9
+ @reserved = Base::ATOM_ATTRIBUTES[:feed][:required] + Base::ATOM_ATTRIBUTES[:feed][:recommended] + Base::ATOM_ATTRIBUTES[:feed][:optional] + [:entry]
10
+ end
11
+
12
+ def entries
13
+ unless @entries
14
+ @entries = TagCollection.new(@doc)
15
+ @doc.xpath("xmlns:entry").each do |entry|
16
+ @entries << Entry.new(entry)
17
+ end
18
+ end
19
+
20
+ return @entries
21
+ end
22
+
23
+ # comp: attr: uri, version (optionals); content (mandatory)
24
+ def generator
25
+ unless @generator
26
+ @doc.xpath("xmlns:generator").each do |generator|
27
+ @generator = Generator.new(generator)
28
+ end
29
+ end
30
+
31
+ return generator
32
+ end
33
+
34
+ def generator=(obj)
35
+ @generator = obj
36
+ end
37
+
38
+ # simple text
39
+ def icon
40
+ text("icon")
41
+ end
42
+
43
+ def icon=(value)
44
+ set_text("icon", value)
45
+ end
46
+
47
+ # simple text
48
+ def logo
49
+ text("logo")
50
+ end
51
+
52
+ def logo=(value)
53
+ set_text("logo", value)
54
+ end
55
+
56
+ # text
57
+ def subtitle
58
+ text("subtitle")
59
+ end
60
+
61
+ def subtitle=(value)
62
+ set_text("subtitle", value)
63
+ end
64
+ end
65
+
66
+ class Generator < XML
67
+ def initialize(options_or_obj)
68
+ if options_or_obj.kind_of?(Hash)
69
+ @doc = Nokogiri::XML::Document.new()
70
+ node = @doc.create_element("generator")
71
+ node.add_namespace_definition(nil, "http://www.w3.org/2005/Atom")
72
+ node.parent = @doc
73
+ super(node)
74
+ options_or_obj.each do |key,value|
75
+ self.send("#{key}=".to_sym, value)
76
+ end
77
+ else
78
+ super(options_or_obj)
79
+ end
80
+ end
81
+
82
+ def content
83
+ @doc.content
84
+ end
85
+
86
+ def content=(value)
87
+ @doc.content = value
88
+ end
89
+
90
+ def uri
91
+ @doc["uri"]
92
+ end
93
+
94
+ def uri=(value)
95
+ @doc["uri"] = value
96
+ end
97
+
98
+ def version
99
+ @doc["version"]
100
+ end
101
+
102
+ def version=(value)
103
+ @doc["version"] = value
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,66 @@
1
+ module Tokamak
2
+ module Representation
3
+ module Atom
4
+ class Link < XML
5
+ def initialize(options_or_obj)
6
+ if options_or_obj.kind_of?(Hash)
7
+ @doc = Nokogiri::XML::Document.new()
8
+ options_or_obj = create_element("link", options_or_obj)
9
+ end
10
+ super(options_or_obj)
11
+ end
12
+
13
+ def href
14
+ @doc["href"]
15
+ end
16
+
17
+ def href=(value)
18
+ @doc["href"] = value
19
+ end
20
+
21
+ def rel
22
+ @doc["rel"]
23
+ end
24
+
25
+ def rel=(value)
26
+ @doc["rel"] = value
27
+ end
28
+
29
+ if method_defined?(:type)
30
+ alias_method :__type__, :type
31
+ end
32
+ def type
33
+ @doc["type"]
34
+ end
35
+
36
+ def type=(value)
37
+ @doc["type"] = value
38
+ end
39
+
40
+ def hreflang
41
+ @doc["hreflang"]
42
+ end
43
+
44
+ def hreflang=(value)
45
+ @doc["hreflang"] = value
46
+ end
47
+
48
+ def title
49
+ @doc["title"]
50
+ end
51
+
52
+ def title=(value)
53
+ @doc["title"] = value
54
+ end
55
+
56
+ def length
57
+ @doc["length"]
58
+ end
59
+
60
+ def length=(value)
61
+ @doc["length"] = value
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end