ld4l-open_annotation_rdf 0.0.4
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 +7 -0
- data/.gitignore +23 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +14 -0
- data/README.md +231 -0
- data/Rakefile +2 -0
- data/ld4l-open_annotation_rdf.gemspec +46 -0
- data/lib/ld4l/open_annotation_rdf.rb +66 -0
- data/lib/ld4l/open_annotation_rdf/annotation.rb +82 -0
- data/lib/ld4l/open_annotation_rdf/comment_annotation.rb +47 -0
- data/lib/ld4l/open_annotation_rdf/comment_body.rb +24 -0
- data/lib/ld4l/open_annotation_rdf/configuration.rb +127 -0
- data/lib/ld4l/open_annotation_rdf/semantic_tag_annotation.rb +66 -0
- data/lib/ld4l/open_annotation_rdf/semantic_tag_body.rb +70 -0
- data/lib/ld4l/open_annotation_rdf/tag_annotation.rb +98 -0
- data/lib/ld4l/open_annotation_rdf/tag_body.rb +83 -0
- data/lib/ld4l/open_annotation_rdf/version.rb +5 -0
- data/lib/ld4l/open_annotation_rdf/vocab/cnt.rb +6 -0
- data/lib/ld4l/open_annotation_rdf/vocab/dctypes.rb +5 -0
- data/lib/ld4l/open_annotation_rdf/vocab/oa.rb +23 -0
- data/spec/ld4l/open_annotation_rdf/annotation_spec.rb +603 -0
- data/spec/ld4l/open_annotation_rdf/comment_annotation_spec.rb +559 -0
- data/spec/ld4l/open_annotation_rdf/comment_body_spec.rb +371 -0
- data/spec/ld4l/open_annotation_rdf/configuration_spec.rb +194 -0
- data/spec/ld4l/open_annotation_rdf/semantic_tag_annotation_spec.rb +619 -0
- data/spec/ld4l/open_annotation_rdf/semantic_tag_body_spec.rb +412 -0
- data/spec/ld4l/open_annotation_rdf/tag_annotation_spec.rb +672 -0
- data/spec/ld4l/open_annotation_rdf/tag_body_spec.rb +430 -0
- data/spec/ld4l/open_annotation_rdf_spec.rb +57 -0
- data/spec/spec_helper.rb +21 -0
- metadata +201 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
module LD4L
|
2
|
+
module OpenAnnotationRDF
|
3
|
+
class CommentAnnotation < LD4L::OpenAnnotationRDF::Annotation
|
4
|
+
|
5
|
+
@localname_prefix="ca"
|
6
|
+
|
7
|
+
property :hasBody, :predicate => RDFVocabularies::OA.hasBody, :class_name => LD4L::OpenAnnotationRDF::CommentBody
|
8
|
+
|
9
|
+
|
10
|
+
##
|
11
|
+
# Create a comment annotation body and set the hasBody property to it.
|
12
|
+
#
|
13
|
+
# @param [String]
|
14
|
+
#
|
15
|
+
# @return instance of SemanticTagBody
|
16
|
+
def setComment(comment)
|
17
|
+
@body = LD4L::OpenAnnotationRDF::CommentBody.new(
|
18
|
+
ActiveTriples::LocalName::Minter.generate_local_name(
|
19
|
+
LD4L::OpenAnnotationRDF::CommentBody, 10, @localname_prefix,
|
20
|
+
LD4L::OpenAnnotationRDF.configuration.localname_minter ))
|
21
|
+
@body.content = comment
|
22
|
+
@body.format = "text/plain"
|
23
|
+
set_value(:hasBody, @body)
|
24
|
+
@body
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Special processing for new and resumed CommentAnnotations
|
29
|
+
#
|
30
|
+
def initialize(*args)
|
31
|
+
super(*args)
|
32
|
+
|
33
|
+
# set motivatedBy
|
34
|
+
m = get_values(:motivatedBy)
|
35
|
+
set_value(:motivatedBy, RDFVocabularies::OA.commenting) unless m.kind_of?(Array) && m.size > 0
|
36
|
+
|
37
|
+
# resume CommentBody if it exists
|
38
|
+
comment_uri = get_values(:hasBody).first
|
39
|
+
if( comment_uri )
|
40
|
+
comment_uri = comment_uri.rdf_subject if comment_uri.kind_of?(ActiveTriples::Resource)
|
41
|
+
@body = LD4L::OpenAnnotationRDF::CommentBody.new(comment_uri)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module LD4L
|
2
|
+
module OpenAnnotationRDF
|
3
|
+
class CommentBody < ActiveTriples::Resource
|
4
|
+
|
5
|
+
class << self; attr_reader :localname_prefix end
|
6
|
+
@localname_prefix="cb"
|
7
|
+
|
8
|
+
configure :type => RDFVocabularies::CNT.ContentAsText,
|
9
|
+
:base_uri => LD4L::OpenAnnotationRDF.configuration.base_uri,
|
10
|
+
:repository => :default
|
11
|
+
|
12
|
+
property :content, :predicate => RDFVocabularies::CNT.chars # :type => XSD.string
|
13
|
+
property :format, :predicate => RDF::DC.format # :type => XSD.string
|
14
|
+
|
15
|
+
def initialize(*args)
|
16
|
+
super(*args)
|
17
|
+
|
18
|
+
t = get_values(:type)
|
19
|
+
t << RDFVocabularies::DCTYPES.Text
|
20
|
+
set_value(:type,t)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module LD4L
|
2
|
+
module OpenAnnotationRDF
|
3
|
+
|
4
|
+
# Used by LD4L::OpenAnnotationRDF class to configure...
|
5
|
+
# * base_uri
|
6
|
+
# * local_minter
|
7
|
+
# * unique_tags
|
8
|
+
#
|
9
|
+
# @example Configure all configurable properties
|
10
|
+
# LD4L::OpenAnnotationRDF.configure do |config|
|
11
|
+
# config.base_uri = "http://www.example.org/annotations/"
|
12
|
+
# config.localname_minter = lambda { |prefix=""| prefix+SecureRandom.uuid }
|
13
|
+
# config.unique_tags = true
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# @example Usage of base uri and local name
|
17
|
+
# # uri = base_uri + localname"
|
18
|
+
# annotation = LD4L::OpenAnnotationRDF::CommentAnnotation.new(
|
19
|
+
# ActiveTriples::LocalName::Minter.generate_local_name(
|
20
|
+
# LD4L::OpenAnnotationRDF::CommentBody, 10, 'a',
|
21
|
+
# LD4L::OpenAnnotationRDF.configuration.localname_minter ))
|
22
|
+
# annotation.rdf_subject
|
23
|
+
# # => "http://www.example.org/annotations/a9f85752c-9c2c-4a65-997a-68482895a656"
|
24
|
+
#
|
25
|
+
# @note Use LD4L::OpenAnnotationRDF.configure to call the methods in this class. See 'Configure all configurable
|
26
|
+
# properties' example for most common approach to configuration.
|
27
|
+
class Configuration
|
28
|
+
|
29
|
+
##
|
30
|
+
# @overload base_uri
|
31
|
+
# Get the base_uri to be used when generating rdf_subjects for new objects. See example configuration and usage in class documentation examples.
|
32
|
+
# @return the configured base_uri
|
33
|
+
# @overload base_uri=(new_base_uri)
|
34
|
+
# Set the base_uri to be used when generating rdf_subjects for new objects. See example configuration and usage in class documentation examples.
|
35
|
+
# @param [String] new value for the base_uri
|
36
|
+
# @note base_uri will only take effect when a model class is first created. Once the model class is created, the base_uri is bound to the class.
|
37
|
+
attr_reader :base_uri
|
38
|
+
|
39
|
+
##
|
40
|
+
# @overload localname_minter
|
41
|
+
# Get the localname_minter to be used when generating rdf_subjects for new objects. See example configuration and usage in class documentation examples.
|
42
|
+
# @return the configured localname_minter
|
43
|
+
# @overload localname_minter=(new_localname_minter)
|
44
|
+
# Set the localname_minter to be used when generating rdf_subjects for new objects. See example configuration and usage in class documentation examples.
|
45
|
+
# @param [String] new value for the localname_minter
|
46
|
+
attr_reader :localname_minter
|
47
|
+
|
48
|
+
##
|
49
|
+
# @overload unique_tags
|
50
|
+
# Get whether the GEM should enforce uniqueness of user generated tags when using
|
51
|
+
# the TagAnnotation::setTag method. See example configuration and usage in class documentation examples.
|
52
|
+
# @return the configured unique_tags
|
53
|
+
# @overload unique_tags=(new_unique_tags)
|
54
|
+
# Set whether the GEM should enforce uniqueness of user generated tags when using
|
55
|
+
# the TagAnnotation::setTag method.
|
56
|
+
# @param [Boolean] new value for the unique_tags
|
57
|
+
#
|
58
|
+
# true - enforce uniqueness (default)
|
59
|
+
# - annotations share TagBodys
|
60
|
+
# - setTag method looks for an existing TagBody with the tag value and reuses the existing TagBody
|
61
|
+
# - setTag to change a tag's value will create/reuse a different TagBody for the new tag value
|
62
|
+
# false - do not enforce uniqueness
|
63
|
+
# - annotation owns its TagBody
|
64
|
+
# - setTag first time call creates a TagBody with the tag value
|
65
|
+
# - setTag to change the tag's value will modify the tag value in this annotation's TagBody
|
66
|
+
attr_reader :unique_tags
|
67
|
+
|
68
|
+
def self.default_base_uri
|
69
|
+
@default_base_uri = "http://localhost/".freeze
|
70
|
+
end
|
71
|
+
private_class_method :default_base_uri
|
72
|
+
|
73
|
+
def self.default_localname_minter
|
74
|
+
# by setting to nil, it will use the default minter in the minter gem
|
75
|
+
@default_localname_minter = nil
|
76
|
+
end
|
77
|
+
private_class_method :default_localname_minter
|
78
|
+
|
79
|
+
def self.default_unique_tags
|
80
|
+
@default_unique_tags = true
|
81
|
+
end
|
82
|
+
private_class_method :default_unique_tags
|
83
|
+
|
84
|
+
def initialize
|
85
|
+
@base_uri = self.class.send(:default_base_uri)
|
86
|
+
@localname_minter = self.class.send(:default_localname_minter)
|
87
|
+
@unique_tags = self.class.send(:default_unique_tags)
|
88
|
+
end
|
89
|
+
|
90
|
+
def base_uri=(new_base_uri)
|
91
|
+
@base_uri = new_base_uri
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Reset the base_uri to be used when generating rdf_subject for new objects back to the default configuration.
|
96
|
+
#
|
97
|
+
def reset_base_uri
|
98
|
+
@base_uri = self.class.send(:default_base_uri)
|
99
|
+
end
|
100
|
+
|
101
|
+
def localname_minter=(new_minter)
|
102
|
+
@localname_minter = new_minter
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# Reset the minter to be used to generate the local name portion of the rdf_subject for new objects to the
|
107
|
+
# default minter.
|
108
|
+
#
|
109
|
+
def reset_localname_minter
|
110
|
+
@localname_minter = self.class.send(:default_localname_minter)
|
111
|
+
end
|
112
|
+
|
113
|
+
def unique_tags=(new_unique_indicator)
|
114
|
+
@unique_tags = new_unique_indicator
|
115
|
+
end
|
116
|
+
|
117
|
+
##
|
118
|
+
# Reset whether the GEM should enforce uniqueness of user generated tags, when using
|
119
|
+
# the TagAnnotation::setTag method, to the default configuration (true).
|
120
|
+
#
|
121
|
+
# @see unique_tags=
|
122
|
+
def reset_unique_tags
|
123
|
+
@unique_tags = self.class.send(:default_unique_tags)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module LD4L
|
2
|
+
module OpenAnnotationRDF
|
3
|
+
class SemanticTagAnnotation < LD4L::OpenAnnotationRDF::Annotation
|
4
|
+
|
5
|
+
@localname_prefix = "sta"
|
6
|
+
|
7
|
+
# USAGE: Use setTerm to set the hasBody property to be the URI of the controlled vocabulary term that
|
8
|
+
# is the annotation.
|
9
|
+
|
10
|
+
# TODO: Should a semantic tag be destroyed when the last annotation referencing the term is destroyed?
|
11
|
+
|
12
|
+
##
|
13
|
+
# Set the hasBody property to the URI of the controlled vocabulary term that is the annotation and
|
14
|
+
# create the semantic tag body instance identifying the term as a semantic tag annotation.
|
15
|
+
#
|
16
|
+
# @param [String] controlled vocabulary uri for the term
|
17
|
+
#
|
18
|
+
# @return instance of SemanticTagBody
|
19
|
+
def setTerm(term_uri)
|
20
|
+
raise ArgumentError, 'Argument must be a uri string or an instance of RDF::URI' unless
|
21
|
+
term_uri.kind_of?(String) && term_uri.size > 0 || term_uri.kind_of?(RDF::URI)
|
22
|
+
|
23
|
+
# return existing body if term is unchanged
|
24
|
+
old_term_uri = @body ? @body.rdf_subject.to_s : nil
|
25
|
+
term_uri = RDF::URI(term_uri) unless term_uri.kind_of?(RDF::URI)
|
26
|
+
return @body if old_term_uri && old_term_uri == term_uri.to_s
|
27
|
+
|
28
|
+
@body = LD4L::OpenAnnotationRDF::SemanticTagBody.new(term_uri)
|
29
|
+
set_value(:hasBody, @body)
|
30
|
+
@body
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Special processing for new and resumed SemanticTagAnnotations
|
35
|
+
#
|
36
|
+
def initialize(*args)
|
37
|
+
super(*args)
|
38
|
+
|
39
|
+
# set motivatedBy
|
40
|
+
m = get_values(:motivatedBy)
|
41
|
+
set_value(:motivatedBy, RDFVocabularies::OA.tagging) unless m.kind_of?(Array) && m.size > 0
|
42
|
+
|
43
|
+
# resume SemanticTagBody if it exists
|
44
|
+
term_uri = get_values(:hasBody).first
|
45
|
+
if( term_uri )
|
46
|
+
term_uri = term_uri.rdf_subject if term_uri.kind_of?(ActiveTriples::Resource)
|
47
|
+
@body = LD4L::OpenAnnotationRDF::SemanticTagBody.new(term_uri)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def destroy
|
52
|
+
# TODO Determine behavior of destroy
|
53
|
+
# Behaviour Options
|
54
|
+
# * Always destroy SemanticTagAnnotation
|
55
|
+
# * Handling of SemanticTagBody
|
56
|
+
# ** If SemanticTagBody is used only by this SemanticTagAnnotation, destroy it.
|
57
|
+
# ** Otherwise, do not destroy it.
|
58
|
+
# TODO Write tests for this behaviour.
|
59
|
+
# TODO Write code here to enforce.
|
60
|
+
super
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module LD4L
|
2
|
+
module OpenAnnotationRDF
|
3
|
+
class SemanticTagBody < ActiveTriples::Resource
|
4
|
+
|
5
|
+
class << self; attr_reader :localname_prefix end
|
6
|
+
@localname_prefix="stb"
|
7
|
+
|
8
|
+
# USAGE: When creating a semantic tag body, use the URI of the controlled vocabulary term as the RDF Subject URI
|
9
|
+
# for an instance of this class.
|
10
|
+
|
11
|
+
configure :type => RDFVocabularies::OA.SemanticTag,
|
12
|
+
:base_uri => LD4L::OpenAnnotationRDF.configuration.base_uri,
|
13
|
+
:repository => :default
|
14
|
+
|
15
|
+
##
|
16
|
+
# Get a list of annotations using a term.
|
17
|
+
#
|
18
|
+
# @param [String] controlled vocabulary uri for the term
|
19
|
+
#
|
20
|
+
# @return array of annotation URIs
|
21
|
+
#
|
22
|
+
# NOTE: This method returns only persisted annotations.
|
23
|
+
def self::annotations_using( term_uri )
|
24
|
+
raise ArgumentError, 'Argument must be a uri string or an instance of RDF::URI' unless
|
25
|
+
term_uri.kind_of?(String) && term_uri.size > 0 || term_uri.kind_of?(RDF::URI)
|
26
|
+
|
27
|
+
term_uri = RDF::URI(term_uri) unless term_uri.kind_of?(RDF::URI)
|
28
|
+
|
29
|
+
# find usage by Annotations
|
30
|
+
graph = ActiveTriples::Repositories.repositories[repository]
|
31
|
+
query = RDF::Query.new({
|
32
|
+
:annotation => {
|
33
|
+
RDF.type => RDFVocabularies::OA.Annotation,
|
34
|
+
RDFVocabularies::OA.hasBody => term_uri,
|
35
|
+
}
|
36
|
+
})
|
37
|
+
annotations = []
|
38
|
+
results = query.execute(graph)
|
39
|
+
results.each { |r| annotations << r.to_hash[:annotation] }
|
40
|
+
annotations
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
##
|
45
|
+
# Destroy the SemanticTagBody only if the term is not used by another SemanticAnnotation
|
46
|
+
#
|
47
|
+
# @param [String] controlled vocabulary uri for the term
|
48
|
+
#
|
49
|
+
# @return true if destroyed; otherwise, false if used by other annotations
|
50
|
+
#
|
51
|
+
# NOTE: Use this method after changing the term AND persisting the annotation on which the term was changed.
|
52
|
+
def self::destroy_if_unused( term_uri )
|
53
|
+
raise ArgumentError, 'Argument must be a uri string or an instance of RDF::URI' unless
|
54
|
+
term_uri.kind_of?(String) && term_uri.size > 0 || term_uri.kind_of?(RDF::URI)
|
55
|
+
|
56
|
+
term_uri = RDF::URI(term_uri) unless term_uri.kind_of?(RDF::URI)
|
57
|
+
|
58
|
+
# find usage by Annotations
|
59
|
+
annotations = self::annotations_using( term_uri )
|
60
|
+
destroyed = false
|
61
|
+
if( annotations.empty? )
|
62
|
+
stb = LD4L::OpenAnnotationRDF::SemanticTagBody.new(term_uri)
|
63
|
+
destroyed = stb.destroy!
|
64
|
+
end
|
65
|
+
destroyed
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module LD4L
|
2
|
+
module OpenAnnotationRDF
|
3
|
+
class TagAnnotation < LD4L::OpenAnnotationRDF::Annotation
|
4
|
+
|
5
|
+
@localname_prefix="ta"
|
6
|
+
|
7
|
+
property :hasBody, :predicate => RDFVocabularies::OA.hasBody, :class_name => LD4L::OpenAnnotationRDF::TagBody
|
8
|
+
|
9
|
+
# TODO: Should a tag be destroyed when the last annotation referencing the tag is destroyed?
|
10
|
+
|
11
|
+
##
|
12
|
+
# Set the hasBody property to the URI of the one and only TagBody holding the tag value. Create a new TagBody
|
13
|
+
# if one doesn't exist with this value.
|
14
|
+
#
|
15
|
+
# @param [String] tag value
|
16
|
+
#
|
17
|
+
# @return instance of TagBody
|
18
|
+
def setTag(tag)
|
19
|
+
raise ArgumentError, 'Argument must be a string with at least one character' unless tag.kind_of?(String) && tag.size > 0
|
20
|
+
|
21
|
+
# return existing body if tag value is unchanged
|
22
|
+
old_tag = @body ? @body.tag : nil
|
23
|
+
return @body if old_tag && old_tag.include?(tag)
|
24
|
+
|
25
|
+
if LD4L::OpenAnnotationRDF.configuration.unique_tags
|
26
|
+
# when unique_tags = true, try to find an existing TagBody with the tag value before creating a new TagBody
|
27
|
+
# TODO Determine behavior of setTag when unique_tags=true
|
28
|
+
# Behaviour Options:
|
29
|
+
# * Look for an existing TagBody with this value.
|
30
|
+
# ** If none found, create a new TagBody.
|
31
|
+
# ** If one found, set @body to this TagBody
|
32
|
+
# ** If multiple found, use the first one found
|
33
|
+
# ### the same one may not be the first one found each time the query executes
|
34
|
+
@body = LD4L::OpenAnnotationRDF.configuration.unique_tags ? LD4L::OpenAnnotationRDF::TagBody.fetch_by_tag_value(tag) : nil
|
35
|
+
if @body == nil
|
36
|
+
@body = LD4L::OpenAnnotationRDF::TagBody.new(
|
37
|
+
ActiveTriples::LocalName::Minter.generate_local_name(
|
38
|
+
LD4L::OpenAnnotationRDF::TagBody, 10, @localname_prefix,
|
39
|
+
LD4L::OpenAnnotationRDF.configuration.localname_minter ))
|
40
|
+
@body.tag = tag
|
41
|
+
end
|
42
|
+
else
|
43
|
+
# when unique_tags = false, ??? (see TODO)
|
44
|
+
# TODO Determine behavior of setTag when unique_tags=false
|
45
|
+
# Behaviour Options:
|
46
|
+
# * If this TagAnnotation does not have a TagBody (@body) set, then create a new TagBody.
|
47
|
+
# * If this TagBody is used only by this TagAnnotation, then change the value in the TagBody.
|
48
|
+
# * If this TagBody is used by multiple TagAnnotations,
|
49
|
+
# ** EITHER change the value in the TagBody which changes it for all the TagAnnotations.
|
50
|
+
# ### Likely an undesirable side effect having the value change for all TagAnnotations
|
51
|
+
# ** OR create a new TagBody and update @body to that TagBody
|
52
|
+
# OR
|
53
|
+
# * [CURRENT] Always create a new TagBody each time setTag is called and update @body
|
54
|
+
# ### This last options has the potential for orphaned TagBodys that no TagAnnotation references.
|
55
|
+
# TODO Rethink the current behavior which is always to create a new TagBody potentially leaving around orphans.
|
56
|
+
@body = LD4L::OpenAnnotationRDF::TagBody.new(
|
57
|
+
ActiveTriples::LocalName::Minter.generate_local_name(
|
58
|
+
LD4L::OpenAnnotationRDF::TagBody, 10, @localname_prefix,
|
59
|
+
LD4L::OpenAnnotationRDF.configuration.localname_minter ))
|
60
|
+
@body.tag = tag
|
61
|
+
end
|
62
|
+
set_value(:hasBody, @body)
|
63
|
+
@body
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Special processing for new and resumed TagAnnotations
|
68
|
+
#
|
69
|
+
def initialize(*args)
|
70
|
+
super(*args)
|
71
|
+
|
72
|
+
# set motivatedBy
|
73
|
+
m = get_values(:motivatedBy)
|
74
|
+
set_value(:motivatedBy, RDFVocabularies::OA.tagging) unless m.kind_of?(Array) && m.size > 0
|
75
|
+
|
76
|
+
# resume TagBody if it exists
|
77
|
+
tag_uri = get_values(:hasBody).first
|
78
|
+
if( tag_uri )
|
79
|
+
tag_uri = tag_uri.rdf_subject if tag_uri.kind_of?(ActiveTriples::Resource)
|
80
|
+
@body = LD4L::OpenAnnotationRDF::TagBody.new(tag_uri)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def destroy
|
85
|
+
# TODO Determine behavior of destroy
|
86
|
+
# Behaviour Options
|
87
|
+
# * Always destroy TagAnnotation
|
88
|
+
# * Handling of TagBody
|
89
|
+
# ** If TagBody is used only by this TagAnnotation, destroy it.
|
90
|
+
# ** Otherwise, do not destroy it.
|
91
|
+
# TODO Write tests for this behaviour.
|
92
|
+
# TODO Write code here to enforce.
|
93
|
+
super
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module LD4L
|
2
|
+
module OpenAnnotationRDF
|
3
|
+
class TagBody < ActiveTriples::Resource
|
4
|
+
|
5
|
+
class << self; attr_reader :localname_prefix end
|
6
|
+
@localname_prefix="tb"
|
7
|
+
|
8
|
+
configure :type => RDFVocabularies::OA.Tag,
|
9
|
+
:base_uri => LD4L::OpenAnnotationRDF.configuration.base_uri,
|
10
|
+
:repository => :default
|
11
|
+
|
12
|
+
property :tag, :predicate => RDFVocabularies::CNT.chars # :type => XSD.string
|
13
|
+
|
14
|
+
##
|
15
|
+
# Get a list of annotations using the tag value.
|
16
|
+
#
|
17
|
+
# @param [String] tag value
|
18
|
+
#
|
19
|
+
# @return array of annotation URIs
|
20
|
+
#
|
21
|
+
# NOTE: This method returns only persisted annotations.
|
22
|
+
def self::annotations_using( tag_value )
|
23
|
+
raise ArgumentError, 'Argument must be a string with at least one character' unless
|
24
|
+
tag_value.kind_of?(String) && tag_value.size > 0
|
25
|
+
|
26
|
+
tb = self::fetch_by_tag_value( tag_value )
|
27
|
+
return [] unless tb
|
28
|
+
tag_uri = tb.rdf_subject
|
29
|
+
|
30
|
+
# find usage by Annotations
|
31
|
+
graph = ActiveTriples::Repositories.repositories[repository]
|
32
|
+
query = RDF::Query.new({
|
33
|
+
:annotation => {
|
34
|
+
RDF.type => RDFVocabularies::OA.Annotation,
|
35
|
+
RDFVocabularies::OA.hasBody => tag_uri,
|
36
|
+
}
|
37
|
+
})
|
38
|
+
results = query.execute(graph)
|
39
|
+
|
40
|
+
# process results
|
41
|
+
annotations = []
|
42
|
+
results.each { |r| annotations << r.to_hash[:annotation] }
|
43
|
+
annotations
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
##
|
48
|
+
# Search the configured repository for a TagBody triple that has the tag value for the tag property.
|
49
|
+
#
|
50
|
+
# @param [String] tag value
|
51
|
+
#
|
52
|
+
# @return instance of TagBody if found; otherwise, nil
|
53
|
+
def self::fetch_by_tag_value( tag_value )
|
54
|
+
raise ArgumentError, 'Argument must be a string with at least one character' unless
|
55
|
+
tag_value.kind_of?(String) && tag_value.size > 0
|
56
|
+
|
57
|
+
graph = ActiveTriples::Repositories.repositories[repository]
|
58
|
+
query = RDF::Query.new({
|
59
|
+
:tagbody => {
|
60
|
+
RDF.type => RDFVocabularies::OA.Tag,
|
61
|
+
RDFVocabularies::CNT.chars => tag_value,
|
62
|
+
}
|
63
|
+
})
|
64
|
+
|
65
|
+
tagbody = nil
|
66
|
+
results = query.execute(graph)
|
67
|
+
unless( results.empty? )
|
68
|
+
tagbody_uri = results[0].to_hash[:tagbody]
|
69
|
+
tagbody = LD4L::OpenAnnotationRDF::TagBody.new(tagbody_uri)
|
70
|
+
end
|
71
|
+
tagbody
|
72
|
+
end
|
73
|
+
|
74
|
+
def initialize(*args)
|
75
|
+
super(*args)
|
76
|
+
|
77
|
+
t = get_values(:type)
|
78
|
+
t << RDFVocabularies::CNT.ContentAsText
|
79
|
+
set_value(:type,t)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|