wf4ever-rosrs-client 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.rvmrc +1 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +20 -0
- data/README.md +180 -0
- data/Rakefile +44 -0
- data/VERSION +1 -0
- data/lib/wf4ever/rosrs/annotation.rb +76 -0
- data/lib/wf4ever/rosrs/exceptions.rb +19 -0
- data/lib/wf4ever/rosrs/folder.rb +127 -0
- data/lib/wf4ever/rosrs/folder_entry.rb +44 -0
- data/lib/wf4ever/rosrs/helper.rb +12 -0
- data/lib/wf4ever/rosrs/namespaces.rb +42 -0
- data/lib/wf4ever/rosrs/rdf_graph.rb +72 -0
- data/lib/wf4ever/rosrs/research_object.rb +233 -0
- data/lib/wf4ever/rosrs/resource.rb +59 -0
- data/lib/wf4ever/rosrs/session.rb +672 -0
- data/lib/wf4ever/rosrs_client.rb +20 -0
- data/test/helper.rb +17 -0
- data/test/test_abstract_interaction.rb +200 -0
- data/test/test_rosrs_session.rb +393 -0
- metadata +166 -0
@@ -0,0 +1,233 @@
|
|
1
|
+
module ROSRS
|
2
|
+
|
3
|
+
class ResearchObject
|
4
|
+
|
5
|
+
attr_reader :uri, :session
|
6
|
+
|
7
|
+
def initialize(rosrs_session, uri)
|
8
|
+
@session = rosrs_session
|
9
|
+
if URI(uri).relative?
|
10
|
+
uri = (rosrs_session.uri + URI(uri)).to_s
|
11
|
+
end
|
12
|
+
uri = uri + '/' unless uri.end_with?('/')
|
13
|
+
@uri = uri
|
14
|
+
@loaded = false
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.create(session, name)
|
18
|
+
c,r,u,m = session.create_research_object(name)
|
19
|
+
self.new(session, u)
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Has this RO's manifest been fetched and parsed?
|
24
|
+
def loaded?
|
25
|
+
@loaded
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Fetch and parse the RO manifest
|
30
|
+
def load
|
31
|
+
manifest_uri, @manifest = @session.get_manifest(uri)
|
32
|
+
@folders = extract_folders
|
33
|
+
@resources = extract_resources
|
34
|
+
@annotations = extract_annotations
|
35
|
+
@loaded = true
|
36
|
+
end
|
37
|
+
|
38
|
+
def manifest
|
39
|
+
load unless loaded?
|
40
|
+
@manifest
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Get Annotations in this RO for the given resource_uri.
|
45
|
+
# If resource_uri is nil, get the Annotations on the RO itself.
|
46
|
+
def annotations(resource_uri = nil)
|
47
|
+
load unless loaded?
|
48
|
+
if resource_uri.nil?
|
49
|
+
@annotations[@uri]
|
50
|
+
else
|
51
|
+
@annotations[resource_uri] || []
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Return the Resource object for the given resource_uri, if it exists.
|
57
|
+
# If resource_uri is nil, return all Resources in the RO.
|
58
|
+
def resources(resource_uri = nil)
|
59
|
+
load unless loaded?
|
60
|
+
if resource_uri.nil?
|
61
|
+
@resources.values
|
62
|
+
else
|
63
|
+
@resources[resource_uri]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Return the Folder object for the given resource_uri, if it exists.
|
69
|
+
# If resource_uri is nil, return all Folder in the RO.
|
70
|
+
def folders(resource_uri = nil)
|
71
|
+
load unless loaded?
|
72
|
+
if resource_uri.nil?
|
73
|
+
@folders.values
|
74
|
+
else
|
75
|
+
@folders[resource_uri]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Return the root folder of the RO.
|
81
|
+
def root_folder
|
82
|
+
load unless loaded?
|
83
|
+
@root_folder
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Delete this RO from the repository
|
88
|
+
def delete
|
89
|
+
code = @session.delete_research_object(@uri)[0]
|
90
|
+
@loaded = false
|
91
|
+
code == 204
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Create an annotation for a given resource_uri, using the supplied annotation body.
|
96
|
+
def create_annotation(resource_uri, annotation)
|
97
|
+
annotation = ROSRS::Annotation.create(self, resource_uri, annotation)
|
98
|
+
load unless loaded?
|
99
|
+
@annotations[resource_uri] ||= []
|
100
|
+
@annotations[resource_uri] << annotation
|
101
|
+
annotation
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Create a folder in the research object.
|
106
|
+
def create_folder(name)
|
107
|
+
folder = ROSRS::Folder.create(self, name)
|
108
|
+
load unless loaded?
|
109
|
+
@folders[folder.uri] = folder
|
110
|
+
folder
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# Aggregate a resource
|
115
|
+
# If a body (and optional content type) is given, it will create an internal resource with that body, plus the proxy
|
116
|
+
# that points to it. If only the first argument is given, an external resource will be created.
|
117
|
+
def aggregate(uri, body = nil, content_type = 'text/plain')
|
118
|
+
resource = ROSRS::Resource.create(self, uri, body, content_type)
|
119
|
+
load unless loaded?
|
120
|
+
@resources[resource.uri] = resource
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Remove the chosen resource from the RO
|
125
|
+
def remove(resource)
|
126
|
+
resource.delete
|
127
|
+
end
|
128
|
+
|
129
|
+
def remove_resource(resource)
|
130
|
+
@resources.delete(resource.uri)
|
131
|
+
@annotations.delete(resource.uri)
|
132
|
+
resource
|
133
|
+
end
|
134
|
+
|
135
|
+
def remove_folder(folder)
|
136
|
+
@folders.delete(folder.uri)
|
137
|
+
@annotations.delete(folder.uri)
|
138
|
+
folder
|
139
|
+
end
|
140
|
+
|
141
|
+
def remove_annotation(annotation)
|
142
|
+
@annotations[annotation.resource_uri].delete(annotation)
|
143
|
+
annotation
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
def extract_annotations
|
149
|
+
annotations = {}
|
150
|
+
queries = [RDF::RO.annotatesAggregatedResource, RDF::AO.annotatesResource].collect do |predicate|
|
151
|
+
RDF::Query.new do
|
152
|
+
pattern [:annotation_uri, RDF.type, RDF::RO.AggregatedAnnotation]
|
153
|
+
pattern [:annotation_uri, predicate, :resource_uri]
|
154
|
+
pattern [:annotation_uri, RDF::AO.body, :body_uri]
|
155
|
+
pattern [:annotation_uri, RDF::DC.creator, :created_by]
|
156
|
+
pattern [:annotation_uri, RDF::DC.created, :created_at]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
queries.each do |query|
|
161
|
+
@manifest.query(query) do |result|
|
162
|
+
annotations[result.resource_uri.to_s] ||= []
|
163
|
+
annotations[result.resource_uri.to_s] << ROSRS::Annotation.new(self,
|
164
|
+
result.annotation_uri.to_s,
|
165
|
+
result.body_uri.to_s,
|
166
|
+
result.resource_uri.to_s,
|
167
|
+
:created_at => result.created_at.to_s,
|
168
|
+
:created_by => result.created_by.to_s)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
annotations
|
173
|
+
end
|
174
|
+
|
175
|
+
def extract_folders
|
176
|
+
folders = {}
|
177
|
+
|
178
|
+
query = RDF::Query.new do
|
179
|
+
pattern [:research_object, RDF::ORE.aggregates, :folder]
|
180
|
+
pattern [:folder, RDF.type, RDF::RO.Folder]
|
181
|
+
pattern [:proxy_uri, RDF::ORE.proxyFor, :folder]
|
182
|
+
end
|
183
|
+
|
184
|
+
@manifest.query(query).each do |result|
|
185
|
+
folder_uri = result.folder.to_s
|
186
|
+
folders[folder_uri] = ROSRS::Folder.new(self, folder_uri, result.proxy_uri.to_s)
|
187
|
+
end
|
188
|
+
|
189
|
+
@root_folder = folders[extract_root_folder]
|
190
|
+
|
191
|
+
folders
|
192
|
+
end
|
193
|
+
|
194
|
+
def extract_root_folder
|
195
|
+
query = RDF::Query.new do
|
196
|
+
pattern [:research_object, RDF::ORE.aggregates, :folder]
|
197
|
+
pattern [:research_object, RDF::RO.rootFolder, :folder]
|
198
|
+
pattern [:folder, RDF.type, RDF::RO.Folder]
|
199
|
+
pattern [:proxy_uri, RDF::ORE.proxyFor, :folder]
|
200
|
+
end
|
201
|
+
|
202
|
+
result = @manifest.query(query).first
|
203
|
+
if result
|
204
|
+
result.folder.to_s
|
205
|
+
else
|
206
|
+
nil
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def extract_resources
|
211
|
+
resources = {}
|
212
|
+
folder_resources = @folders.values.map {|f| f.uri}
|
213
|
+
|
214
|
+
query = RDF::Query.new do
|
215
|
+
pattern [:research_object, RDF::ORE.aggregates, :resource]
|
216
|
+
pattern [:resource, RDF.type, RDF::RO.Resource]
|
217
|
+
#pattern [:resource, RDF::RO.name, :name]
|
218
|
+
pattern [:proxy_uri, RDF::ORE.proxyFor, :resource]
|
219
|
+
pattern [:resource, RDF::DC.creator, :created_by]
|
220
|
+
pattern [:resource, RDF::DC.created, :created_at]
|
221
|
+
end
|
222
|
+
|
223
|
+
@manifest.query(query).each do |result|
|
224
|
+
unless folder_resources.include?(result.resource.to_s) # We only want non-folder resources
|
225
|
+
resources[result.resource.to_s] = ROSRS::Resource.new(self, result.resource.to_s, result.proxy_uri.to_s)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
resources
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module ROSRS
|
2
|
+
|
3
|
+
class Resource
|
4
|
+
attr_reader :research_object, :uri, :proxy_uri, :created_at, :created_by
|
5
|
+
|
6
|
+
def initialize(research_object, uri, proxy_uri = nil, options = {})
|
7
|
+
@research_object = research_object
|
8
|
+
@uri = uri
|
9
|
+
@proxy_uri = proxy_uri
|
10
|
+
@session = @research_object.session
|
11
|
+
@created_at = options[:created_at]
|
12
|
+
@created_by = options[:created_by]
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Get all the annotations on this resource
|
17
|
+
def annotations
|
18
|
+
@research_object.annotations(@uri)
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Add an annotation to this resource
|
23
|
+
def annotate(annotation)
|
24
|
+
@research_object.create_annotation(@uri, annotation)
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Removes this resource from the Research Object.
|
29
|
+
def delete
|
30
|
+
code = @session.delete_resource(@proxy_uri)[0]
|
31
|
+
@loaded = false
|
32
|
+
@research_object.remove_resource(self)
|
33
|
+
code == 204
|
34
|
+
end
|
35
|
+
|
36
|
+
def internal?
|
37
|
+
@uri.include?(@research_object.uri)
|
38
|
+
end
|
39
|
+
|
40
|
+
def external?
|
41
|
+
!internal?
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.create(research_object, uri, body = nil, content_type = 'text/plain')
|
45
|
+
if body.nil?
|
46
|
+
code, reason, proxy_uri, resource_uri = research_object.session.aggregate_external_resource(research_object.uri, uri)
|
47
|
+
self.new(research_object, resource_uri, proxy_uri)
|
48
|
+
else
|
49
|
+
code, reason, proxy_uri, resource_uri = research_object.session.aggregate_internal_resource(research_object.uri,
|
50
|
+
uri,
|
51
|
+
:body => body,
|
52
|
+
:ctype => content_type)
|
53
|
+
self.new(research_object, resource_uri, proxy_uri)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|