tokamak 1.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
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