triannon 1.1.0 → 2.0.0
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.
- checksums.yaml +4 -4
- data/README.md +64 -48
- data/app/controllers/concerns/rdf_response_formats.rb +7 -11
- data/app/controllers/triannon/annotations_controller.rb +34 -24
- data/app/models/triannon/annotation.rb +13 -16
- data/app/services/triannon/ldp_loader.rb +13 -34
- data/app/services/triannon/ldp_to_oa_mapper.rb +19 -13
- data/app/services/triannon/ldp_writer.rb +49 -46
- data/app/services/triannon/solr_searcher.rb +8 -6
- data/app/services/triannon/solr_writer.rb +11 -6
- data/app/views/triannon/annotations/new.html.erb +21 -1
- data/app/views/triannon/annotations/show.html.erb +1 -1
- data/config/routes.rb +73 -22
- data/config/solr/log4j.properties +25 -0
- data/config/solr/solr.xml +2 -0
- data/config/solr/triannon-core/conf/schema.xml +2 -0
- data/config/solr/triannon-core/conf/solrconfig.xml +46 -33
- data/lib/tasks/triannon_tasks.rake +30 -8
- data/lib/triannon.rb +0 -1
- data/lib/triannon/error.rb +14 -0
- data/lib/triannon/version.rb +1 -1
- metadata +3 -18
- data/app/views/triannon/annotations/_form.html.erb +0 -21
- data/app/views/triannon/annotations/edit.html.erb +0 -1
@@ -4,29 +4,28 @@ module Triannon
|
|
4
4
|
# Loads an existing Annotation from the LDP server
|
5
5
|
class LdpLoader
|
6
6
|
|
7
|
-
|
7
|
+
# @param [String] root_container the LDP parent container for the annotation
|
8
8
|
# @param [String] id the unique id of the annotation. Can include base_uri prefix or omit it.
|
9
|
-
def self.load id
|
10
|
-
l = Triannon::LdpLoader.new id
|
9
|
+
def self.load(root_container, id)
|
10
|
+
l = Triannon::LdpLoader.new(root_container, id)
|
11
11
|
l.load_anno_container
|
12
12
|
l.load_bodies
|
13
13
|
l.load_targets
|
14
14
|
|
15
|
-
oa_graph = Triannon::LdpToOaMapper.ldp_to_oa
|
15
|
+
oa_graph = Triannon::LdpToOaMapper.ldp_to_oa(l.ldp_annotation, root_container)
|
16
16
|
oa_graph
|
17
17
|
end
|
18
18
|
|
19
|
-
# @deprecated was needed by old annotations#index action, which now redirects to search (2015-04)
|
20
|
-
def self.find_all
|
21
|
-
l = Triannon::LdpLoader.new
|
22
|
-
l.find_all
|
23
|
-
end
|
24
|
-
|
25
19
|
attr_accessor :ldp_annotation
|
26
20
|
|
27
21
|
# @param [String] id the unique id of the annotation. Can include base_uri prefix or omit it.
|
28
|
-
|
22
|
+
# @param [String] root_container the LDP parent container for the annotation
|
23
|
+
def initialize(root_container, id = nil)
|
29
24
|
@id = id
|
25
|
+
@root_container = root_container
|
26
|
+
if @root_container.blank?
|
27
|
+
fail Triannon::LDPContainerError, "Annotations must be in a root container."
|
28
|
+
end
|
30
29
|
base_url = Triannon.config[:ldp]['url']
|
31
30
|
base_url.chop! if base_url.end_with?('/')
|
32
31
|
container_path = Triannon.config[:ldp]['uber_container']
|
@@ -37,18 +36,17 @@ module Triannon
|
|
37
36
|
end
|
38
37
|
@base_uri = "#{base_url}/#{container_path}"
|
39
38
|
@ldp_annotation = Triannon::AnnotationLdp.new
|
40
|
-
|
41
39
|
end
|
42
40
|
|
43
41
|
# load annotation container object into @ldp_annotation's (our Triannon::AnnotationLdp object) graph
|
44
42
|
def load_anno_container
|
45
|
-
load_object_into_annotation_graph(@id)
|
43
|
+
load_object_into_annotation_graph("#{@root_container}/#{@id}")
|
46
44
|
end
|
47
45
|
|
48
46
|
# load body objects into @ldp_annotation's (our Triannon::AnnotationLdp object) graph
|
49
47
|
def load_bodies
|
50
48
|
@ldp_annotation.body_uris.each { |body_uri|
|
51
|
-
body_obj_path = body_uri.to_s.split(@base_uri
|
49
|
+
body_obj_path = body_uri.to_s.split("#{@base_uri}/").last
|
52
50
|
load_object_into_annotation_graph(body_obj_path)
|
53
51
|
}
|
54
52
|
end
|
@@ -56,30 +54,11 @@ module Triannon
|
|
56
54
|
# load target objects into @ldp_annotation's (our Triannon::AnnotationLdp object) graph
|
57
55
|
def load_targets
|
58
56
|
@ldp_annotation.target_uris.each { |target_uri|
|
59
|
-
target_obj_path = target_uri.to_s.split(@base_uri
|
57
|
+
target_obj_path = target_uri.to_s.split("#{@base_uri}/").last
|
60
58
|
load_object_into_annotation_graph(target_obj_path)
|
61
59
|
}
|
62
60
|
end
|
63
61
|
|
64
|
-
# @return [Array<Triannon::Annotation>] an array of Triannon::Annotation objects with just the id set. Enough info to build the index page
|
65
|
-
# @deprecated was needed by old annotations#index action, which now redirects to search (2015-04).
|
66
|
-
def find_all
|
67
|
-
root_ttl = get_ttl
|
68
|
-
objs = []
|
69
|
-
|
70
|
-
g = RDF::Graph.new
|
71
|
-
g.from_ttl root_ttl
|
72
|
-
root_uri = RDF::URI.new @base_uri
|
73
|
-
results = g.query [root_uri, RDF::Vocab::LDP.contains, nil]
|
74
|
-
results.each do |stmt|
|
75
|
-
# FIXME: can't be last with pair trees in fedora urls - leave broke as this method is deprecated
|
76
|
-
id = stmt.object.to_s.split('/').last
|
77
|
-
objs << Triannon::Annotation.new(:id => id)
|
78
|
-
end
|
79
|
-
|
80
|
-
objs
|
81
|
-
end
|
82
|
-
|
83
62
|
protected
|
84
63
|
|
85
64
|
# given a path to the back end storage url, retrieve the object from storage and load
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module Triannon
|
2
2
|
class LdpToOaMapper
|
3
3
|
|
4
|
-
# maps
|
5
|
-
|
6
|
-
|
4
|
+
# maps a Triannon::AnnotationLdp to an OA RDF::Graph
|
5
|
+
# @param [Triannon::AnnotationLdp] ldp_anno
|
6
|
+
# @param [String] root_container the LDP parent container for the annotation
|
7
|
+
def self.ldp_to_oa(ldp_anno, root_container)
|
8
|
+
mapper = Triannon::LdpToOaMapper.new(ldp_anno, root_container)
|
7
9
|
mapper.extract_base
|
8
10
|
mapper.extract_bodies
|
9
11
|
mapper.extract_targets
|
@@ -12,30 +14,32 @@ module Triannon
|
|
12
14
|
|
13
15
|
attr_accessor :id, :oa_graph
|
14
16
|
|
15
|
-
|
17
|
+
# @param [Triannon::AnnotationLdp] ldp_anno
|
18
|
+
# @param [String] root_container the LDP parent container for the annotation
|
19
|
+
def initialize(ldp_anno, root_container)
|
16
20
|
@ldp_anno = ldp_anno
|
21
|
+
@root_container = root_container
|
17
22
|
@ldp_anno_graph = ldp_anno.stripped_graph
|
18
23
|
g = RDF::Graph.new
|
19
24
|
@oa_graph = OA::Graph.new g
|
20
25
|
end
|
21
26
|
|
27
|
+
# load statements from base anno container into @oa_graph
|
22
28
|
def extract_base
|
23
29
|
root_subject_solns = @ldp_anno_graph.query OA::Graph.anno_query
|
24
30
|
if root_subject_solns.count == 1
|
25
31
|
stored_url = Triannon.config[:ldp]['url'].strip
|
26
32
|
stored_url.chop! if stored_url.end_with?('/')
|
27
|
-
|
28
|
-
if
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
stored_url = "#{stored_url}/#{container_path}"
|
33
|
+
uber_container = Triannon.config[:ldp]['uber_container'].strip
|
34
|
+
if uber_container
|
35
|
+
uber_container = uber_container[1..-1] if uber_container.start_with?('/')
|
36
|
+
uber_container.chop! if uber_container.end_with?('/')
|
37
|
+
stored_url = "#{stored_url}/#{uber_container}/#{@root_container}"
|
33
38
|
end
|
34
39
|
@id = root_subject_solns[0].s.to_s.split("#{stored_url}/").last
|
35
|
-
base_url = Triannon.config[:triannon_base_url]
|
36
|
-
base_url.strip!
|
40
|
+
base_url = Triannon.config[:triannon_base_url].strip
|
37
41
|
base_url.chop! if base_url[-1] == '/'
|
38
|
-
@root_uri = RDF::URI.new(base_url + "/#{@id}")
|
42
|
+
@root_uri = RDF::URI.new(base_url + "/#{@root_container}/#{@id}")
|
39
43
|
end
|
40
44
|
|
41
45
|
@ldp_anno_graph.each_statement do |stmnt|
|
@@ -49,6 +53,7 @@ module Triannon
|
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
56
|
+
# load statements from anno body containers into @oa_graph
|
52
57
|
def extract_bodies
|
53
58
|
@ldp_anno.body_uris.each { |body_uri|
|
54
59
|
if !map_external_ref(body_uri, RDF::Vocab::OA.hasBody) &&
|
@@ -59,6 +64,7 @@ module Triannon
|
|
59
64
|
}
|
60
65
|
end
|
61
66
|
|
67
|
+
# load statements from anno target containers into @oa_graph
|
62
68
|
def extract_targets
|
63
69
|
@ldp_anno.target_uris.each { |target_uri|
|
64
70
|
if !map_external_ref(target_uri, RDF::Vocab::OA.hasTarget) &&
|
@@ -4,13 +4,13 @@ module Triannon
|
|
4
4
|
class LdpWriter
|
5
5
|
|
6
6
|
# use LDP protocol to create the OpenAnnotation.Annotation in an RDF store
|
7
|
-
# @param [Triannon::Annotation] anno a Triannon::Annotation object, from
|
8
|
-
#
|
9
|
-
def self.create_anno(anno)
|
7
|
+
# @param [Triannon::Annotation] anno a Triannon::Annotation object, from which we use the graph
|
8
|
+
# @param [String] root_container the LDP parent container for the annotation
|
9
|
+
def self.create_anno(anno, root_container)
|
10
10
|
if anno && anno.graph
|
11
11
|
# TODO: special case if the Annotation object already has an id --
|
12
12
|
# see https://github.com/sul-dlss/triannon/issues/84
|
13
|
-
ldp_writer = Triannon::LdpWriter.new anno
|
13
|
+
ldp_writer = Triannon::LdpWriter.new anno, root_container
|
14
14
|
id = ldp_writer.create_base
|
15
15
|
|
16
16
|
bodies_solns = anno.graph.query([nil, RDF::Vocab::OA.hasBody, nil])
|
@@ -30,8 +30,7 @@ module Triannon
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
# deletes the indicated container and all its child containers from the LDP
|
34
|
-
# store
|
33
|
+
# deletes the indicated container and all its child containers from the LDP store
|
35
34
|
# @param [String] id the unique id for the LDP container for an annotation.
|
36
35
|
# May be a compound id, such as uuid1/t/uuid2, in which case the LDP
|
37
36
|
# container object uuid2 and its children are deleted from the LDP
|
@@ -39,7 +38,7 @@ module Triannon
|
|
39
38
|
# the LDP store.
|
40
39
|
def self.delete_container id
|
41
40
|
if id && id.size > 0
|
42
|
-
ldpw = Triannon::LdpWriter.new nil
|
41
|
+
ldpw = Triannon::LdpWriter.new nil, nil
|
43
42
|
ldpw.delete_containers id
|
44
43
|
end
|
45
44
|
end
|
@@ -126,35 +125,39 @@ module Triannon
|
|
126
125
|
|
127
126
|
|
128
127
|
# @param [Triannon::Annotation] anno a Triannon::Annotation object
|
129
|
-
# @param [String]
|
130
|
-
#
|
131
|
-
def initialize(anno, id = nil)
|
128
|
+
# @param [String] root_container the LDP parent container for the annotation
|
129
|
+
# @param [String] id the unique id for the LDP container for the passed annotation; defaults to nil
|
130
|
+
def initialize(anno, root_container, id = nil)
|
132
131
|
@anno = anno
|
132
|
+
@root_container = root_container
|
133
133
|
@id = id
|
134
134
|
base_url = Triannon.config[:ldp]['url'].strip
|
135
135
|
base_url.chop! if base_url.end_with?('/')
|
136
|
-
|
137
|
-
if
|
138
|
-
|
139
|
-
|
140
|
-
container_path.chop! if container_path.end_with?('/')
|
136
|
+
@uber_container_path = Triannon.config[:ldp]['uber_container'].strip
|
137
|
+
if @uber_container_path
|
138
|
+
@uber_container_path = @uber_container_path[1..-1] if @uber_container_path.start_with?('/')
|
139
|
+
@uber_container_path.chop! if @uber_container_path.end_with?('/')
|
141
140
|
end
|
142
|
-
@base_uri = "#{base_url}/#{
|
141
|
+
@base_uri = "#{base_url}/#{@uber_container_path}"
|
143
142
|
end
|
144
143
|
|
145
144
|
# creates a stored LDP container for this object's Annotation, without its
|
146
145
|
# targets or bodies (as those are put in descendant containers)
|
147
146
|
# SIDE EFFECT: assigns the uuid of the container created to @id
|
148
|
-
# @return [String] the unique id for the LDP container created for this
|
149
|
-
# annotation
|
147
|
+
# @return [String] the unique id for the LDP container created for this annotation
|
150
148
|
def create_base
|
151
149
|
if @anno.graph.query([nil, RDF::Triannon.externalReference, nil]).count > 0
|
152
150
|
fail Triannon::ExternalReferenceError, "Incoming annotations may not have http://triannon.stanford.edu/ns/externalReference as a predicate."
|
153
151
|
end
|
154
|
-
|
155
152
|
if @anno.graph.id_as_url && @anno.graph.id_as_url.size > 0
|
156
153
|
fail Triannon::ExternalReferenceError, "Incoming new annotations may not have an existing id (yet)."
|
157
154
|
end
|
155
|
+
if @root_container.blank?
|
156
|
+
fail Triannon::LDPContainerError, "Annotations must be created in a root container."
|
157
|
+
end
|
158
|
+
unless self.class.container_exist? "#{@uber_container_path}/#{@root_container}"
|
159
|
+
fail Triannon::MissingLDPContainerError, "Annotation root container #{@root_container} doesn't exist."
|
160
|
+
end
|
158
161
|
|
159
162
|
# TODO: special case if the Annotation object already has an id --
|
160
163
|
# see https://github.com/sul-dlss/triannon/issues/84
|
@@ -167,8 +170,9 @@ module Triannon
|
|
167
170
|
g = OA::Graph.new(g)
|
168
171
|
g.remove_non_base_statements
|
169
172
|
g.make_null_relative_uri_out_of_blank_node
|
173
|
+
g << [RDF::URI.new, RDF.type, RDF::Vocab::LDP.BasicContainer]
|
170
174
|
|
171
|
-
@id = create_resource g.to_ttl
|
175
|
+
@id = create_resource g.to_ttl, @root_container
|
172
176
|
end
|
173
177
|
|
174
178
|
# creates the LDP container for any and all bodies for this annotation
|
@@ -202,8 +206,9 @@ module Triannon
|
|
202
206
|
end
|
203
207
|
something_deleted = false
|
204
208
|
ldp_container_uris.each { |uri|
|
205
|
-
ldp_id = uri.to_s.split(@base_uri
|
206
|
-
|
209
|
+
ldp_id = uri.to_s.split("#{@base_uri}/").last
|
210
|
+
ldp_id = "#{@root_container}/#{ldp_id}" unless @root_container.blank? || ldp_id.match(@root_container)
|
211
|
+
resp = conn.delete { |req| req.url "#{ldp_id}" }
|
207
212
|
if resp.status != 204
|
208
213
|
fail Triannon::LDPStorageError.new("Unable to delete LDP container #{ldp_id}", resp.status, resp.body)
|
209
214
|
end
|
@@ -214,18 +219,17 @@ module Triannon
|
|
214
219
|
|
215
220
|
protected
|
216
221
|
|
217
|
-
# POSTS a ttl representation of a graph to an existing LDP container in the
|
218
|
-
# LDP store
|
219
|
-
#
|
220
|
-
#
|
221
|
-
# @param [String] parent_path the path portion of the url for the LDP parent
|
222
|
-
#
|
223
|
-
#
|
224
|
-
#
|
225
|
-
#
|
226
|
-
#
|
227
|
-
# @return [String] path_id representing the unique path of the newly created LDP
|
228
|
-
# container
|
222
|
+
# POSTS a ttl representation of a graph to an existing LDP container in the LDP store,
|
223
|
+
# which will cause the LDP store to create a new container that is a child of
|
224
|
+
# the existing container.
|
225
|
+
# @param [String] ttl a turtle representation of RDF data to be put in the newly created LDP container
|
226
|
+
# @param [String] parent_path the path portion of the url for the LDP parent container for this resource.
|
227
|
+
# if no path is supplied, then the resource will be created as a child of the root annotation;
|
228
|
+
# expected paths would also be
|
229
|
+
# (anno_id)/t for a target resource (new container to be created inside the target container of anno_id)
|
230
|
+
# or
|
231
|
+
# (anno_id)/b for a body resource (new container to be created inside the body container of anno_id)
|
232
|
+
# @return [String] path_id representing the unique path of the newly created LDP container
|
229
233
|
def create_resource ttl, parent_path = nil
|
230
234
|
return if !ttl || ttl.empty?
|
231
235
|
|
@@ -243,7 +247,7 @@ module Triannon
|
|
243
247
|
req.body = ttl
|
244
248
|
end
|
245
249
|
if resp.status != 200 && resp.status != 201
|
246
|
-
fail Triannon::LDPStorageError.new("Unable to create LDP resource in container #{parent_path}
|
250
|
+
fail Triannon::LDPStorageError.new("Unable to create LDP resource in container #{parent_path};\nRDF sent: #{ttl}", resp.status, resp.body)
|
247
251
|
end
|
248
252
|
new_url = resp.headers['Location'] ? resp.headers['Location'] : resp.headers['location']
|
249
253
|
if new_url
|
@@ -257,37 +261,35 @@ module Triannon
|
|
257
261
|
# the base container at @id and has the memberRelation per the
|
258
262
|
# oa_vocab_term. The id of the created container will be (base container
|
259
263
|
# id)/b if hasBody or (base container id)/t if hasTarget
|
260
|
-
# @param [RDF::Vocabulary::Term] oa_vocab_term RDF::Vocab::OA.hasTarget or
|
261
|
-
# RDF::Vocab::OA.hasBody
|
264
|
+
# @param [RDF::Vocabulary::Term] oa_vocab_term RDF::Vocab::OA.hasTarget or RDF::Vocab::OA.hasBody
|
262
265
|
def create_direct_container oa_vocab_term
|
263
266
|
null_rel_uri = RDF::URI.new
|
264
267
|
g = RDF::Graph.new
|
265
268
|
g << [null_rel_uri, RDF.type, RDF::Vocab::LDP.DirectContainer]
|
266
269
|
g << [null_rel_uri, RDF::Vocab::LDP.hasMemberRelation, oa_vocab_term]
|
267
|
-
g << [null_rel_uri, RDF::Vocab::LDP.membershipResource, RDF::URI.new("#{@base_uri}/#{@id}")]
|
270
|
+
g << [null_rel_uri, RDF::Vocab::LDP.membershipResource, RDF::URI.new("#{@base_uri}/#{@root_container}/#{@id}")]
|
268
271
|
|
269
272
|
resp = conn.post do |req|
|
270
|
-
req.url "#{@id}"
|
273
|
+
req.url "#{@root_container}/#{@id}"
|
271
274
|
req.headers['Content-Type'] = 'application/x-turtle'
|
272
275
|
# OA vocab relationships all of form "hasXXX" so this becomes 't' or 'b'
|
273
276
|
req.headers['Slug'] = oa_vocab_term.fragment.slice(3).downcase
|
274
277
|
req.body = g.to_ttl
|
275
278
|
end
|
276
279
|
if resp.status != 201
|
277
|
-
fail Triannon::LDPStorageError.new("Unable to create #{oa_vocab_term.fragment.sub('has', '')} LDP container for anno
|
280
|
+
fail Triannon::LDPStorageError.new("Unable to create #{oa_vocab_term.fragment.sub('has', '')} LDP container for anno #{@root_container}/#{@id};\nRDF sent: #{g.to_ttl}", resp.status, resp.body)
|
278
281
|
end
|
279
282
|
resp
|
280
283
|
end
|
281
284
|
|
282
|
-
# create the target/body resources inside the (already created) target/body
|
283
|
-
#
|
284
|
-
# @param [RDF::URI] predicate either RDF::Vocab::OA.hasTarget or
|
285
|
-
# RDF::Vocab::OA.hasBody
|
285
|
+
# create the target/body resources inside the (already created) target/body container
|
286
|
+
# @param [RDF::URI] predicate either RDF::Vocab::OA.hasTarget or RDF::Vocab::OA.hasBody
|
286
287
|
def create_resources_in_container(predicate)
|
287
288
|
predicate_solns = @anno.graph.query([nil, predicate, nil])
|
288
289
|
resource_ids = []
|
289
290
|
predicate_solns.each { |predicate_stmt |
|
290
291
|
graph_for_resource = RDF::Graph.new
|
292
|
+
graph_for_resource << [RDF::URI.new, RDF.type, RDF::Vocab::LDP.BasicContainer]
|
291
293
|
predicate_obj = predicate_stmt.object
|
292
294
|
if predicate_obj.is_a?(RDF::Node)
|
293
295
|
# we need to use the null relative URI representation of blank nodes
|
@@ -384,10 +386,11 @@ module Triannon
|
|
384
386
|
graph_for_resource.delete(s)
|
385
387
|
}
|
386
388
|
}
|
389
|
+
|
387
390
|
if (predicate == RDF::Vocab::OA.hasTarget)
|
388
|
-
resource_ids << create_resource(graph_for_resource.to_ttl, "#{@id}/t")
|
391
|
+
resource_ids << create_resource(graph_for_resource.to_ttl, "#{@root_container}/#{@id}/t")
|
389
392
|
else
|
390
|
-
resource_ids << create_resource(graph_for_resource.to_ttl, "#{@id}/b")
|
393
|
+
resource_ids << create_resource(graph_for_resource.to_ttl, "#{@root_container}/#{@id}/b")
|
391
394
|
end
|
392
395
|
}
|
393
396
|
resource_ids
|
@@ -49,6 +49,12 @@ module Triannon
|
|
49
49
|
when 'bodyexact'
|
50
50
|
# no need to Solr escape value because it's in quotes
|
51
51
|
q_terms_array << "body_chars_exact:\"#{v}\""
|
52
|
+
when 'bodykeyword'
|
53
|
+
solr_params_hash[:kqf] = 'body_chars_exact^3 body_chars_unstem^2 body_chars_stem'
|
54
|
+
solr_params_hash[:kpf] = 'body_chars_exact^15 body_chars_unstem^10 body_chars_stem^5'
|
55
|
+
solr_params_hash[:kpf3] = 'body_chars_exact^9 body_chars_unstem^6 body_chars_stem^3'
|
56
|
+
solr_params_hash[:kpf2] = 'body_chars_exact^6 body_chars_unstem^4 body_chars_stem^2'
|
57
|
+
q_terms_array << '_query_:"{!dismax qf=$kqf pf=$kpf pf3=$kpf3 pf2=$kpf2}' + RSolr.solr_escape(v) + '"'
|
52
58
|
when 'motivatedby'
|
53
59
|
case
|
54
60
|
when v.include?('#')
|
@@ -60,12 +66,8 @@ module Triannon
|
|
60
66
|
else
|
61
67
|
fq_terms_array << "motivation:#{RSolr.solr_escape(v)}"
|
62
68
|
end
|
63
|
-
when '
|
64
|
-
|
65
|
-
solr_params_hash[:kpf] = 'body_chars_exact^15 body_chars_unstem^10 body_chars_stem^5'
|
66
|
-
solr_params_hash[:kpf3] = 'body_chars_exact^9 body_chars_unstem^6 body_chars_stem^3'
|
67
|
-
solr_params_hash[:kpf2] = 'body_chars_exact^6 body_chars_unstem^4 body_chars_stem^2'
|
68
|
-
q_terms_array << '_query_:"{!dismax qf=$kqf pf=$kpf pf3=$kpf3 pf2=$kpf2}' + RSolr.solr_escape(v) + '"'
|
69
|
+
when 'anno_root'
|
70
|
+
fq_terms_array << "root:#{RSolr.solr_escape(v)}"
|
69
71
|
|
70
72
|
# TODO: add'l params to implement:
|
71
73
|
# targetType - fq
|
@@ -7,16 +7,20 @@ module Triannon
|
|
7
7
|
# Convert a OA::Graph object into a Hash suitable for writing to Solr.
|
8
8
|
#
|
9
9
|
# @param [OA::Graph] triannon_graph a populated OA::Graph object for a *stored* anno
|
10
|
+
# @param [String] root_container the id of the LDP parent container for the annotation
|
10
11
|
# @return [Hash] a hash to be written to Solr, populated appropriately
|
11
|
-
def self.solr_hash(triannon_graph)
|
12
|
+
def self.solr_hash(triannon_graph, root_container)
|
12
13
|
doc_hash = {}
|
13
14
|
triannon_id = triannon_graph.id_as_url
|
14
|
-
if triannon_id
|
15
|
-
#
|
16
|
-
#
|
15
|
+
if triannon_id && root_container.present?
|
16
|
+
# we simplify the URL, removing the triannon base_url. This will only be problematic if
|
17
|
+
# two different LDP Stores had the same root-container/pair-tree/uuid format AND they were
|
18
|
+
# both writing to the same Solr index.
|
17
19
|
solr_id = triannon_id.sub(Triannon.config[:triannon_base_url], "")
|
18
20
|
doc_hash[:id] = solr_id.sub(/^\/*/, "") # remove first char slash(es) if present
|
19
21
|
|
22
|
+
doc_hash[:root] = root_container
|
23
|
+
|
20
24
|
# use short strings for motivation field
|
21
25
|
doc_hash[:motivation] = triannon_graph.motivated_by.map { |m| m.sub(RDF::Vocab::OA.to_s, "") }
|
22
26
|
|
@@ -60,8 +64,9 @@ module Triannon
|
|
60
64
|
# Convert the OA::Graph to a Solr document hash, then call RSolr.add
|
61
65
|
# with the doc hash
|
62
66
|
# @param [OA::Graph] tgraph anno represented as a OA::Graph
|
63
|
-
|
64
|
-
|
67
|
+
# @param [String] root the id of the LDP parent container for the annotation
|
68
|
+
def write(tgraph, root)
|
69
|
+
doc_hash = self.class.solr_hash(tgraph, root) if tgraph && !tgraph.id_as_url.empty? && !root.blank?
|
65
70
|
add(doc_hash) if doc_hash && !doc_hash.empty?
|
66
71
|
end
|
67
72
|
|
@@ -1 +1,21 @@
|
|
1
|
-
<%=
|
1
|
+
<%= form_for @annotation, url: {action: "create"} do |f| %>
|
2
|
+
<% if @annotation.errors.any? %>
|
3
|
+
<div id="error_explanation">
|
4
|
+
<h2><%= pluralize(@annotation.errors.count, "error") %> prohibited this annotation from being saved:</h2>
|
5
|
+
|
6
|
+
<ul>
|
7
|
+
<% @annotation.errors.full_messages.each do |message| %>
|
8
|
+
<li><%= message %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<div class="field">
|
15
|
+
<%= f.label 'Annotation (as json-ld or turtle)' %><br>
|
16
|
+
<%= f.text_area :data, size: "80x20" %>
|
17
|
+
</div>
|
18
|
+
<div class="actions">
|
19
|
+
<%= f.submit %>
|
20
|
+
</div>
|
21
|
+
<% end %>
|