wf4ever-rosrs-client 0.1.1
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/.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
|