exempla-atomic 0.0.8 → 0.0.11
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.
- data/VERSION.yml +1 -1
- data/lib/atomic.rb +4 -3
- data/lib/atomic/entry.rb +70 -58
- data/lib/atomic/extensions.rb +7 -0
- data/lib/atomic/extensions/cirrus.rb +10 -0
- data/lib/atomic/extensions/cirrus/announcement.rb +42 -0
- data/lib/atomic/extensions/cirrus/base.rb +20 -0
- data/lib/atomic/extensions/cirrus/event.rb +11 -0
- data/lib/atomic/extensions/cirrus/news.rb +11 -0
- data/lib/atomic/feed.rb +63 -15
- data/lib/atomic/parser.rb +72 -0
- data/lib/atomic/person.rb +48 -0
- data/lib/atomic/service.rb +106 -48
- data/spec/atomic/entry_spec.rb +8 -5
- data/spec/atomic/parser_spec.rb +16 -0
- data/spec/fixtures/valid_atom_entry.xml +9 -9
- metadata +5 -2
data/VERSION.yml
CHANGED
data/lib/atomic.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/atomic/parser'
|
2
|
+
require File.dirname(__FILE__) + '/atomic/person'
|
1
3
|
require File.dirname(__FILE__) + '/atomic/service'
|
2
4
|
require File.dirname(__FILE__) + '/atomic/feed'
|
3
5
|
require File.dirname(__FILE__) + '/atomic/entry'
|
4
6
|
require File.dirname(__FILE__) + '/atomic/extensions'
|
5
7
|
|
6
|
-
Atomic::
|
7
|
-
|
8
|
-
"xmlns:cirrus" => "http://www.glam.ac.uk/2009/cirrus" }
|
8
|
+
Atomic::NS_ATOM = "http://www.w3.org/2005/Atom"
|
9
|
+
Atomic::NS_APP = "http://www.w3.org/2007/app"
|
data/lib/atomic/entry.rb
CHANGED
@@ -5,50 +5,9 @@ module Atomic
|
|
5
5
|
|
6
6
|
class Entry
|
7
7
|
|
8
|
-
|
8
|
+
include Parser
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
def parse(data)
|
13
|
-
entry = new
|
14
|
-
doc = data.kind_of?(Nokogiri::XML::Element) ? data : Nokogiri.XML(data, nil, nil, Nokogiri::XML::PARSE_RECOVER + Nokogiri::XML::PARSE_NOBLANKS)
|
15
|
-
|
16
|
-
entry_node = doc.xpath('//atom:entry', NAMESPACES).first
|
17
|
-
|
18
|
-
entry.id = entry_node.xpath('atom:id', NAMESPACES).first.text
|
19
|
-
entry.title = entry_node.xpath('atom:title', NAMESPACES).first.text
|
20
|
-
entry.created_at = entry_node.xpath('atom:published', NAMESPACES).first.text
|
21
|
-
entry.updated_at = entry_node.xpath('atom:updated', NAMESPACES).first.text
|
22
|
-
|
23
|
-
content_node = entry_node.xpath('atom:content', NAMESPACES).first
|
24
|
-
|
25
|
-
entry.content = {:type => content_node['type']}
|
26
|
-
if (content_node['type'] == 'application/xml')
|
27
|
-
content_hash = {}
|
28
|
-
case content_node.children.first.name
|
29
|
-
when 'announcement'
|
30
|
-
announcement_node = content_node.xpath('cirrus:announcement', NAMESPACES).first
|
31
|
-
unless announcement_node.nil?
|
32
|
-
content_hash[:message] = announcement_node.xpath('cirrus:message', NAMESPACES).first.text
|
33
|
-
content_hash[:starts_at] = announcement_node.xpath('cirrus:starts-at', NAMESPACES).first.text
|
34
|
-
content_hash[:ends_at] = announcement_node.xpath('cirrus:ends-at', NAMESPACES).first.text
|
35
|
-
end
|
36
|
-
else
|
37
|
-
throw("Unknown Content Type: #{content_node.children.first.name}")
|
38
|
-
end
|
39
|
-
entry.content[:data] = {content_node.children.first.name.to_sym => content_hash}
|
40
|
-
else
|
41
|
-
entry.content[:data] = content_node.inner_html
|
42
|
-
end
|
43
|
-
entry.categories = []
|
44
|
-
entry_node.xpath('atom:category', NAMESPACES).each do |category_node|
|
45
|
-
entry.categories << {:term => category_node['term'], :scheme => category_node['scheme']}
|
46
|
-
end
|
47
|
-
|
48
|
-
entry
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
10
|
+
attr_accessor :id, :title, :categories, :created_at, :updated_at, :content, :links, :author, :contributors
|
52
11
|
|
53
12
|
def initialize(params = {})
|
54
13
|
params.symbolize_keys!
|
@@ -58,7 +17,71 @@ module Atomic
|
|
58
17
|
@categories = params[:categories] || []
|
59
18
|
@created_at = params[:created_at].nil? ? Time.now : Time.parse(params[:created_at])
|
60
19
|
@updated_at = params[:updated_at].nil? ? @created_at : Time.parse(params[:updated_at])
|
61
|
-
@content = params[:content]
|
20
|
+
@content = params[:content] || {}
|
21
|
+
@links = params[:links] || []
|
22
|
+
@author = params[:author]
|
23
|
+
@contributors = params[:contributors] || []
|
24
|
+
end
|
25
|
+
|
26
|
+
def handle_open_element(node, reader)
|
27
|
+
progressed = false
|
28
|
+
case [node.depth, node.uri, node.name]
|
29
|
+
when [0, NS_ATOM, 'entry']
|
30
|
+
when [1, NS_ATOM, 'title']
|
31
|
+
when [1, NS_ATOM, 'id']
|
32
|
+
when [1, NS_ATOM, 'published']
|
33
|
+
when [1, NS_ATOM, 'updated']
|
34
|
+
when [1, NS_ATOM, 'category']
|
35
|
+
when [1, NS_ATOM, 'author']
|
36
|
+
author = Person.new
|
37
|
+
author.deserialize(reader)
|
38
|
+
self.author = author
|
39
|
+
progressed = true
|
40
|
+
when [1, NS_ATOM, 'contributor']
|
41
|
+
contributor = Person.new
|
42
|
+
contributor.deserialize(reader)
|
43
|
+
self.contributors << contributor
|
44
|
+
progressed = true
|
45
|
+
when [1, NS_ATOM, 'content']
|
46
|
+
if node.attributes['type'] == 'application/xml'
|
47
|
+
@processing_xml_content = true
|
48
|
+
end
|
49
|
+
when [1, NS_ATOM, 'link']
|
50
|
+
else
|
51
|
+
if @processing_xml_content
|
52
|
+
extension_class = Extensions::MAP[[node.uri, node.name]]
|
53
|
+
unless extension_class.nil?
|
54
|
+
extension_class.new(self).deserialize(reader)
|
55
|
+
progressed = true
|
56
|
+
end
|
57
|
+
else
|
58
|
+
puts("Entry ==> Unexpected Open Element - [#{node.depth}] #{node.name} #{node.uri} #{node.attributes.inspect}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
return progressed
|
62
|
+
end
|
63
|
+
|
64
|
+
def handle_close_element(node)
|
65
|
+
case [node.depth, node.uri, node.name]
|
66
|
+
when [0, NS_ATOM, 'entry']
|
67
|
+
when [1, NS_ATOM, 'title']
|
68
|
+
@title = node.text
|
69
|
+
when [1, NS_ATOM, 'id']
|
70
|
+
@id = node.text
|
71
|
+
when [1, NS_ATOM, 'published']
|
72
|
+
@created_at = Time.parse(node.text)
|
73
|
+
when [1, NS_ATOM, 'updated']
|
74
|
+
@updated_at = Time.parse(node.text)
|
75
|
+
when [1, NS_ATOM, 'category']
|
76
|
+
@categories << {:scheme => node.attributes['scheme'], :term => node.attributes['term']}
|
77
|
+
when [1, NS_ATOM, 'author']
|
78
|
+
when [1, NS_ATOM, 'content']
|
79
|
+
@processing_xml_content = false
|
80
|
+
when [1, NS_ATOM, 'link']
|
81
|
+
@links << {:href => node.attributes['href'], :rel => node.attributes['rel'], :type => node.attributes['type']}
|
82
|
+
else
|
83
|
+
puts("Entry ==> Unexpected Close Element - [#{node.depth}] #{node.name} #{node.uri} #{node.attributes.inspect} #{node.text}") unless @processing_xml_content
|
84
|
+
end
|
62
85
|
end
|
63
86
|
|
64
87
|
def to_hash
|
@@ -68,23 +91,12 @@ module Atomic
|
|
68
91
|
:categories => @categories,
|
69
92
|
:created_at => @created_at,
|
70
93
|
:updated_at => @updated_at,
|
71
|
-
:content => @content
|
94
|
+
:content => @content,
|
95
|
+
:links => @links,
|
96
|
+
:author => @author
|
72
97
|
}
|
73
98
|
end
|
74
99
|
|
75
|
-
# def method_missing(method_symbol, *arguments)
|
76
|
-
# method_name = method_symbol.to_s
|
77
|
-
# case method_name[-1..-1]
|
78
|
-
# when "="
|
79
|
-
# @attributes[method_name[0..-2]] = arguments.first
|
80
|
-
# when "?"
|
81
|
-
# @attributes[method_name[0..-2]] == true
|
82
|
-
# else
|
83
|
-
# # Returns nil on failure so forms will work
|
84
|
-
# @attributes.has_key?(method_name) ? @attributes[method_name] : nil
|
85
|
-
# end
|
86
|
-
# end
|
87
|
-
|
88
100
|
end
|
89
101
|
|
90
102
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/cirrus/base'
|
2
|
+
require File.dirname(__FILE__) + '/cirrus/announcement'
|
3
|
+
require File.dirname(__FILE__) + '/cirrus/news'
|
4
|
+
require File.dirname(__FILE__) + '/cirrus/event'
|
5
|
+
|
6
|
+
module Atomic
|
7
|
+
module Extensions
|
8
|
+
MAP.merge!(Cirrus::Announcement.mapping => Cirrus::Announcement)
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Atomic
|
2
|
+
module Extensions
|
3
|
+
module Cirrus
|
4
|
+
class Announcement < Atomic::Extensions::Cirrus::Base
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def mapping
|
8
|
+
[namespace, 'announcement']
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def handle_open_element(node, reader)
|
13
|
+
progressed = false
|
14
|
+
case [node.depth, node.uri, node.name]
|
15
|
+
when [0, Announcement.namespace, 'announcement']
|
16
|
+
when [1, Announcement.namespace, 'message']
|
17
|
+
when [1, Announcement.namespace, 'starts-at']
|
18
|
+
when [1, Announcement.namespace, 'ends-at']
|
19
|
+
else
|
20
|
+
puts "Announcement ==>> Unexpected OPEN #{node.depth} #{node.uri} #{node.name} #{node.attributes.inspect}"
|
21
|
+
end
|
22
|
+
return progressed
|
23
|
+
end
|
24
|
+
|
25
|
+
def handle_close_element(node)
|
26
|
+
case [node.depth, node.uri, node.name]
|
27
|
+
when [0, Announcement.namespace, 'announcement']
|
28
|
+
when [1, Announcement.namespace, 'message']
|
29
|
+
@parent.content[:message] = node.text
|
30
|
+
when [1, Announcement.namespace, 'starts-at']
|
31
|
+
@parent.content[:starts_at] = node.text
|
32
|
+
when [1, Announcement.namespace, 'ends-at']
|
33
|
+
@parent.content[:ends_at] = node.text
|
34
|
+
else
|
35
|
+
puts "Announcement ==>> Unexpected CLOSE #{node.depth} #{node.uri} #{node.name} #{node.attributes.inspect}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# To change this template, choose Tools | Templates
|
2
|
+
# and open the template in the editor.
|
3
|
+
|
4
|
+
module Atomic
|
5
|
+
module Extensions
|
6
|
+
module Cirrus
|
7
|
+
class Base
|
8
|
+
include Parser
|
9
|
+
class << self
|
10
|
+
def namespace
|
11
|
+
'http://www.glam.ac.uk/2009/cirrus'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
def initialize(parent)
|
15
|
+
@parent = parent
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/atomic/feed.rb
CHANGED
@@ -6,28 +6,76 @@ module Atomic
|
|
6
6
|
|
7
7
|
class Feed
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
def parse(data)
|
12
|
-
feed = new
|
13
|
-
doc = data.kind_of?(Nokogiri::XML::Element) ? data : Nokogiri.XML(data)
|
14
|
-
feed_node = doc.xpath('//atom:feed', NAMESPACES).first
|
15
|
-
feed.title = feed_node.xpath('atom:title', NAMESPACES).first.text
|
16
|
-
feed.id = feed_node.xpath('atom:id', NAMESPACES).first.text
|
17
|
-
feed_node.xpath('atom:entry', NAMESPACES).each do |entry_node|
|
18
|
-
feed.entries << Entry.parse(entry_node)
|
19
|
-
end
|
20
|
-
feed
|
21
|
-
end
|
9
|
+
include Parser
|
22
10
|
|
23
|
-
|
11
|
+
# class << self
|
12
|
+
#
|
13
|
+
# def parse(data)
|
14
|
+
# feed = new
|
15
|
+
# doc = data.kind_of?(Nokogiri::XML::Element) ? data : Nokogiri.XML(data)
|
16
|
+
# feed_node = doc.xpath('//atom:feed', NAMESPACES).first
|
17
|
+
# feed.title = feed_node.xpath('atom:title', NAMESPACES).first.text
|
18
|
+
# feed.id = feed_node.xpath('atom:id', NAMESPACES).first.text
|
19
|
+
# feed_node.xpath('atom:entry', NAMESPACES).each do |entry_node|
|
20
|
+
# feed.entries << Entry.parse(entry_node)
|
21
|
+
# end
|
22
|
+
# feed
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# end
|
24
26
|
|
25
|
-
attr_accessor :title, :
|
27
|
+
attr_accessor :id, :title, :subtitle, :updated_at, :links, :rights, :generator, :entries
|
26
28
|
|
27
29
|
def initialize(params = {})
|
28
30
|
@title = params[:title]
|
29
31
|
@id = params[:id]
|
30
32
|
@entries = params[:entries] || []
|
33
|
+
@links = params[:links] || []
|
34
|
+
end
|
35
|
+
|
36
|
+
def handle_open_element(node, reader)
|
37
|
+
progressed = false
|
38
|
+
case [node.depth, node.uri, node.name]
|
39
|
+
when [0, 'http://www.w3.org/2005/Atom', 'feed']
|
40
|
+
when [1, NS_ATOM, 'title']
|
41
|
+
when [1, NS_ATOM, 'subtitle']
|
42
|
+
when [1, NS_ATOM, 'updated']
|
43
|
+
when [1, NS_ATOM, 'id']
|
44
|
+
when [1, NS_ATOM, 'link']
|
45
|
+
when [1, NS_ATOM, 'rights']
|
46
|
+
when [1, NS_ATOM, 'generator']
|
47
|
+
when [1, NS_ATOM, 'entry']
|
48
|
+
entry = Entry.new
|
49
|
+
entry.deserialize(reader)
|
50
|
+
@entries << entry
|
51
|
+
progressed = true
|
52
|
+
else
|
53
|
+
puts("Feed ==> Unexpected Open Element - [#{node.depth}] #{node.name} {#{node.uri}} #{node.attributes.inspect}")
|
54
|
+
end
|
55
|
+
return progressed
|
56
|
+
end
|
57
|
+
|
58
|
+
def handle_close_element(node)
|
59
|
+
case [node.depth, node.uri, node.name]
|
60
|
+
when [0, 'http://www.w3.org/2005/Atom', 'feed']
|
61
|
+
when [1, NS_ATOM, 'title']
|
62
|
+
@title = node.text
|
63
|
+
when [1, NS_ATOM, 'subtitle']
|
64
|
+
@subtitle = node.text
|
65
|
+
when [1, NS_ATOM, 'updated']
|
66
|
+
@updated_at = Time.parse(node.text)
|
67
|
+
when [1, NS_ATOM, 'id']
|
68
|
+
@id = node.text
|
69
|
+
when [1, NS_ATOM, 'link']
|
70
|
+
@links << {:href => node.attributes['href'], :rel => node.attributes['rel'], :type => node.attributes['type']}
|
71
|
+
when [1, NS_ATOM, 'rights']
|
72
|
+
@rights = node.text
|
73
|
+
when [1, NS_ATOM, 'generator']
|
74
|
+
@generator = node.text
|
75
|
+
when [1, NS_ATOM, 'entry']
|
76
|
+
else
|
77
|
+
puts("Feed ==> Unexpected Close Element - [#{node.depth}] #{node.name} {#{node.uri}} #{node.attributes.inspect} #{node.text}")
|
78
|
+
end
|
31
79
|
end
|
32
80
|
|
33
81
|
def to_hash
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
module Atomic
|
5
|
+
|
6
|
+
module Parser
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.extend(ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def parse(xml)
|
15
|
+
reader = Nokogiri::XML::Reader.from_memory(xml, nil, nil, Nokogiri::XML::PARSE_NOBLANKS)
|
16
|
+
object = new
|
17
|
+
object.deserialize(reader.read)
|
18
|
+
object
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Node = Struct.new("Node", :depth, :name, :uri, :attributes, :text)
|
23
|
+
|
24
|
+
def deserialize(reader)
|
25
|
+
stack = []
|
26
|
+
start_depth = reader.depth
|
27
|
+
loop do
|
28
|
+
# puts "#{self.class} STACK: #{stack.inspect}"
|
29
|
+
node = Node.new(reader.depth - start_depth, reader.local_name, reader.namespace_uri, reader.attributes)
|
30
|
+
if (stack.empty? || node.depth > stack.last.depth)
|
31
|
+
# child
|
32
|
+
if(reader.value?)
|
33
|
+
stack.last.text = reader.value unless stack.empty?
|
34
|
+
reader.read
|
35
|
+
else
|
36
|
+
# puts "#{self.class} OPEN ELEMENT: #{node.inspect}"
|
37
|
+
redo if handle_open_element(node,reader)
|
38
|
+
stack.push(node)
|
39
|
+
end
|
40
|
+
elsif(node.depth < stack.last.depth)
|
41
|
+
# parent
|
42
|
+
# puts "#{self.class} CLOSE ELEMENT: #{stack.last}"
|
43
|
+
handle_close_element(stack.last)
|
44
|
+
stack.pop
|
45
|
+
else
|
46
|
+
# sibling
|
47
|
+
# puts "#{self.class} SIB CLOSE ELEMENT: #{stack.last}"
|
48
|
+
handle_close_element(stack.last)
|
49
|
+
stack.pop
|
50
|
+
unless stack.empty?
|
51
|
+
# puts "#{self.class} SIB OPEN ELEMENT: #{node.inspect}"
|
52
|
+
redo if handle_open_element(node,reader)
|
53
|
+
stack.push(node)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
break if stack.empty?
|
57
|
+
reader.read
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def handle_open_element(node, reader)
|
62
|
+
progressed = false
|
63
|
+
puts("Open Element - #{node.inspect}")
|
64
|
+
return progressed
|
65
|
+
end
|
66
|
+
|
67
|
+
def handle_close_element(node)
|
68
|
+
puts("Close Element - #{node.inspect}")
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'activesupport'
|
2
|
+
|
3
|
+
module Atomic
|
4
|
+
class Person
|
5
|
+
|
6
|
+
include Parser
|
7
|
+
|
8
|
+
attr_accessor :name, :uri, :email
|
9
|
+
|
10
|
+
def initialize(params = {})
|
11
|
+
params.symbolize_keys!
|
12
|
+
params.assert_valid_keys(:name, :uri, :email)
|
13
|
+
@name = params[:name]
|
14
|
+
@uri = params[:uri]
|
15
|
+
@email = params[:email]
|
16
|
+
end
|
17
|
+
|
18
|
+
def handle_open_element(node, reader)
|
19
|
+
progressed = false
|
20
|
+
case [node.depth, node.uri, node.name]
|
21
|
+
when [0, NS_ATOM, 'author']
|
22
|
+
when [0, NS_ATOM, 'contributor']
|
23
|
+
when [1, NS_ATOM, 'name']
|
24
|
+
when [1, NS_ATOM, 'uri']
|
25
|
+
when [1, NS_ATOM, 'email']
|
26
|
+
else
|
27
|
+
puts("Person ==> Unexpected Open Element - [#{node.depth}] #{node.name} #{node.uri} #{node.attributes.inspect}")
|
28
|
+
end
|
29
|
+
return progressed
|
30
|
+
end
|
31
|
+
|
32
|
+
def handle_close_element(node)
|
33
|
+
case [node.depth, node.uri, node.name]
|
34
|
+
when [0, NS_ATOM, 'author']
|
35
|
+
when [0, NS_ATOM, 'contributor']
|
36
|
+
when [1, NS_ATOM, 'name']
|
37
|
+
@name = node.text
|
38
|
+
when [1, NS_ATOM, 'uri']
|
39
|
+
@uri = node.text
|
40
|
+
when [1, NS_ATOM, 'email']
|
41
|
+
@email = node.text
|
42
|
+
else
|
43
|
+
puts("Person ==> Unexpected Close Element - [#{node.depth}] #{node.name} #{node.uri} #{node.attributes.inspect} #{node.text}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
data/lib/atomic/service.rb
CHANGED
@@ -4,80 +4,138 @@ require 'time'
|
|
4
4
|
|
5
5
|
module Atomic
|
6
6
|
|
7
|
-
class
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
workspace_node = doc.xpath('//app:workspace', NAMESPACES).first
|
13
|
-
workspace.title = workspace_node.xpath('atom:title', NAMESPACES).first.text
|
14
|
-
workspace_node.xpath('app:collection', NAMESPACES).each do |collection_node|
|
15
|
-
workspace.collections << Collection.parse(collection_node)
|
16
|
-
end
|
17
|
-
workspace
|
18
|
-
end
|
19
|
-
end
|
20
|
-
attr_accessor :title, :collections
|
7
|
+
class Collection
|
8
|
+
|
9
|
+
include Parser
|
10
|
+
attr_accessor :href, :title, :content_types, :categories
|
11
|
+
|
21
12
|
def initialize(params = {})
|
13
|
+
@href = params[:href]
|
22
14
|
@title = params[:title]
|
23
|
-
@
|
15
|
+
@content_types = params[:content_types] || []
|
16
|
+
@categories = params[:categories] || []
|
17
|
+
end
|
18
|
+
|
19
|
+
def handle_open_element(node, reader)
|
20
|
+
progressed = false
|
21
|
+
case [node.depth, node.uri, node.name]
|
22
|
+
when [0, NS_APP, 'collection']
|
23
|
+
when [1, NS_ATOM, 'title']
|
24
|
+
when [1, NS_APP, 'accept']
|
25
|
+
when [1, NS_APP, 'categories']
|
26
|
+
@processing_categories = true
|
27
|
+
when [2, NS_APP, 'category']
|
28
|
+
else
|
29
|
+
puts("Collection ==> Unexpected Open Element - [#{node.depth}] #{node.name} {#{node.uri}} #{node.attributes.inspect}")
|
30
|
+
end
|
31
|
+
return progressed
|
32
|
+
end
|
33
|
+
|
34
|
+
def handle_close_element(node)
|
35
|
+
case [node.depth, node.uri, node.name]
|
36
|
+
when [0, NS_APP, 'collection']
|
37
|
+
self.href = node.attributes['href']
|
38
|
+
when [1, NS_ATOM, 'title']
|
39
|
+
self.title = node.text
|
40
|
+
when [1, NS_APP, 'accept']
|
41
|
+
self.content_types << node.text
|
42
|
+
when [1, NS_APP, 'categories']
|
43
|
+
@processing_categories = false
|
44
|
+
when [2, NS_APP, 'category']
|
45
|
+
self.categories << {:scheme => node.attributes['scheme'], :term => node.attributes['term']} if @processing_categories
|
46
|
+
else
|
47
|
+
puts("Collection ==> Unexpected Close Element - [#{node.depth}] #{node.name} {#{node.uri}} #{node.attributes.inspect} #{node.text}")
|
48
|
+
end
|
24
49
|
end
|
50
|
+
|
25
51
|
def to_hash
|
26
52
|
{
|
27
|
-
:
|
28
|
-
:
|
53
|
+
:href => @href,
|
54
|
+
:title => @title
|
29
55
|
}
|
30
56
|
end
|
57
|
+
|
31
58
|
end
|
32
59
|
|
33
|
-
class
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
# puts "*********"
|
39
|
-
# puts collection_node
|
40
|
-
# puts "*********"
|
41
|
-
collection.href = collection_node['href']
|
42
|
-
collection.title = collection_node.xpath('atom:title', NAMESPACES).first.text
|
43
|
-
collection
|
44
|
-
end
|
45
|
-
end
|
46
|
-
attr_accessor :href, :title
|
60
|
+
class Workspace
|
61
|
+
|
62
|
+
include Parser
|
63
|
+
attr_accessor :title, :collections
|
64
|
+
|
47
65
|
def initialize(params = {})
|
48
|
-
@href = params[:href]
|
49
66
|
@title = params[:title]
|
67
|
+
@collections = params[:collections] || []
|
68
|
+
end
|
69
|
+
|
70
|
+
def handle_open_element(node, reader)
|
71
|
+
progressed = false
|
72
|
+
case [node.depth, node.uri, node.name]
|
73
|
+
when [0, NS_APP, 'workspace']
|
74
|
+
when [1, NS_ATOM, 'title']
|
75
|
+
when [1, NS_APP, 'collection']
|
76
|
+
collection = Collection.new
|
77
|
+
collection.deserialize(reader)
|
78
|
+
self.collections << collection
|
79
|
+
progressed = true
|
80
|
+
else
|
81
|
+
puts("Workspace ==> Unexpected Open Element - [#{node.depth}] #{node.name} {#{node.uri}} #{node.attributes.inspect}")
|
82
|
+
end
|
83
|
+
return progressed
|
50
84
|
end
|
85
|
+
|
86
|
+
def handle_close_element(node)
|
87
|
+
case [node.depth, node.uri, node.name]
|
88
|
+
when [0, NS_APP, 'workspace']
|
89
|
+
when [1, NS_ATOM, 'title']
|
90
|
+
self.title = node.text
|
91
|
+
when [1, NS_APP, 'collection']
|
92
|
+
else
|
93
|
+
puts("Workspace ==> Unexpected Close Element - [#{node.depth}] #{node.name} {#{node.uri}} #{node.attributes.inspect} #{node.text}")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
51
97
|
def to_hash
|
52
98
|
{
|
53
|
-
:
|
54
|
-
:
|
99
|
+
:title => @title,
|
100
|
+
:collections => @collections.collect{ |collection| collection.to_hash }
|
55
101
|
}
|
56
102
|
end
|
103
|
+
|
57
104
|
end
|
58
105
|
|
59
106
|
class Service
|
60
|
-
|
61
|
-
class << self
|
62
|
-
|
63
|
-
def parse(data)
|
64
|
-
service = new
|
65
|
-
doc = data.kind_of?(Nokogiri::XML::Element) ? data : Nokogiri.XML(data)
|
66
|
-
service_node = doc.xpath('//app:service', NAMESPACES).first
|
67
|
-
service_node.xpath('app:workspace', NAMESPACES).each do |workspace_node|
|
68
|
-
service.workspaces << Workspace.parse(workspace_node)
|
69
|
-
end
|
70
|
-
service
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
107
|
|
108
|
+
include Parser
|
75
109
|
attr_accessor :workspaces
|
76
110
|
|
77
111
|
def initialize(params = {})
|
78
112
|
@workspaces = params[:workspaces] || []
|
79
113
|
end
|
80
114
|
|
115
|
+
def handle_open_element(node, reader)
|
116
|
+
progressed = false
|
117
|
+
case [node.depth, node.uri, node.name]
|
118
|
+
when [0, NS_APP, 'service']
|
119
|
+
when [1, NS_APP, 'workspace']
|
120
|
+
workspace = Workspace.new
|
121
|
+
workspace.deserialize(reader)
|
122
|
+
self.workspaces << workspace
|
123
|
+
progressed = true
|
124
|
+
else
|
125
|
+
puts("Service ==> Unexpected Open Element - [#{node.depth}] #{node.name} {#{node.uri}} #{node.attributes.inspect}")
|
126
|
+
end
|
127
|
+
return progressed
|
128
|
+
end
|
129
|
+
|
130
|
+
def handle_close_element(node)
|
131
|
+
case [node.depth, node.uri, node.name]
|
132
|
+
when [0, NS_APP, 'service']
|
133
|
+
when [1, NS_APP, 'workspace']
|
134
|
+
else
|
135
|
+
puts("Service ==> Unexpected Close Element - [#{node.depth}] #{node.name} {#{node.uri}} #{node.attributes.inspect} #{node.text}")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
81
139
|
def to_hash
|
82
140
|
{ :workspaces => @workspaces.collect { |workspace| workspace.to_hash } }
|
83
141
|
end
|
data/spec/atomic/entry_spec.rb
CHANGED
@@ -39,14 +39,17 @@ describe Atomic::Entry do
|
|
39
39
|
@entry.title.should == 'Test Announcement'
|
40
40
|
@entry.id.should == 'tag:example.org,2003:3.2397'
|
41
41
|
@entry.categories.size.should == 2
|
42
|
-
|
43
|
-
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should handle author element" do
|
45
|
+
@entry.author.should_not be_nil
|
44
46
|
end
|
45
47
|
|
46
48
|
it "should handle the announcements extension" do
|
47
|
-
@entry.content
|
48
|
-
|
49
|
-
@entry.content[:
|
49
|
+
@entry.content.should_not be_nil
|
50
|
+
@entry.content[:message].should == 'Test Announcement Message'
|
51
|
+
@entry.content[:starts_at].should == '2009-02-10T08:00:00Z'
|
52
|
+
@entry.content[:ends_at].should == '2009-02-10T17:00:00Z'
|
50
53
|
end
|
51
54
|
|
52
55
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Atomic::Parser do
|
4
|
+
before(:each) do
|
5
|
+
@entry_xml = File.read(File.join(File.dirname(__FILE__), '..', 'fixtures', 'valid_atom_entry.xml'))
|
6
|
+
@klass = Class.new do
|
7
|
+
include Atomic::Parser
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should work nicely" do
|
12
|
+
@klass.parse(@entry_xml)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
@@ -5,17 +5,17 @@
|
|
5
5
|
<updated>2009-02-10T08:00:00Z</updated>
|
6
6
|
<published>2009-02-10T08:00:00Z</published>
|
7
7
|
<author>
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
<name>Peter Portal</name>
|
9
|
+
<uri>http://www.glam.ac.uk/</uri>
|
10
|
+
<email>peterportal@glam.ac.uk</email>
|
11
11
|
</author>
|
12
12
|
<category term="trefforest" scheme="http://cirrusstage.glam.ac.uk/schemes/locations"/>
|
13
13
|
<category term="gbs" scheme="http://cirrusstage.glam.ac.uk/schemes/faculties"/>
|
14
14
|
<content type="application/xml">
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
<cirrus:announcement>
|
16
|
+
<cirrus:message>Test Announcement Message</cirrus:message>
|
17
|
+
<cirrus:starts-at type="datetime">2009-02-10T08:00:00Z</cirrus:starts-at>
|
18
|
+
<cirrus:ends-at type="datetime">2009-02-10T17:00:00Z</cirrus:ends-at>
|
19
|
+
</cirrus:announcement>
|
20
20
|
</content>
|
21
|
-
|
21
|
+
</entry>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exempla-atomic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Darrin Wortlehock
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-02-
|
12
|
+
date: 2009-02-24 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -34,6 +34,8 @@ files:
|
|
34
34
|
- lib/atomic/extensions/cirrus/news.rb
|
35
35
|
- lib/atomic/extensions/cirrus/event.rb
|
36
36
|
- lib/atomic/entry.rb
|
37
|
+
- lib/atomic/parser.rb
|
38
|
+
- lib/atomic/person.rb
|
37
39
|
- lib/atomic/extensions.rb
|
38
40
|
- lib/atomic/feed.rb
|
39
41
|
- spec/spec.opts
|
@@ -45,6 +47,7 @@ files:
|
|
45
47
|
- spec/atomic
|
46
48
|
- spec/atomic/entry_spec.rb
|
47
49
|
- spec/atomic/feed_spec.rb
|
50
|
+
- spec/atomic/parser_spec.rb
|
48
51
|
- spec/atomic/service_spec.rb
|
49
52
|
has_rdoc: true
|
50
53
|
homepage: http://github.com/exempla/atomic
|