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