Class: ActiveAnnotations::RDFAnnotation

Inherits:
Object
  • Object
show all
Defined in:
lib/active_annotations/rdf_annotation.rb

Constant Summary collapse

CONTEXT_URI =
'http://www.w3.org/ns/oa.jsonld'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(content = nil) ⇒ RDFAnnotation

Returns a new instance of RDFAnnotation.



40
41
42
43
44
45
46
47
# File 'lib/active_annotations/rdf_annotation.rb', line 40

def initialize(content=nil)
  @graph = RDF::Graph.new
  if content.nil?
    self.add_default_content!
  else
    @graph << content
  end
end

Instance Attribute Details

#graphObject (readonly)

Returns the value of attribute graph.



20
21
22
# File 'lib/active_annotations/rdf_annotation.rb', line 20

def graph
  @graph
end

Class Method Details

.from_jsonld(json) ⇒ Object



23
24
25
26
# File 'lib/active_annotations/rdf_annotation.rb', line 23

def self.from_jsonld(json)
  content = JSON.parse(json)
  self.new(JSON::LD::API.toRDF(content, documentLoader: DocumentLoader.document_loader))
end

Instance Method Details

#add_default_content!Object



71
72
73
74
75
76
77
# File 'lib/active_annotations/rdf_annotation.rb', line 71

def add_default_content!
  aid = new_id
  add_statements(
    RDF::Statement.new(aid, RDF.type, RDF::Vocab::OA.Annotation),
    RDF::Statement.new(aid, RDF::Vocab::DC.created, DateTime.now)
  )
end

#add_statements(*statements) ⇒ Object



67
68
69
# File 'lib/active_annotations/rdf_annotation.rb', line 67

def add_statements(*statements)
  statements.each { |statement| @graph << statement }
end

#annotated_atObject



192
193
194
# File 'lib/active_annotations/rdf_annotation.rb', line 192

def annotated_at
  get_value(annotation_id, RDF::Vocab::DC.modified) || get_value(annotation_id, RDF::Vocab::OA.annotatedAt)
end

#annotated_at=(value) ⇒ Object



196
197
198
# File 'lib/active_annotations/rdf_annotation.rb', line 196

def annotated_at=(value)
  set_value(annotation_id, RDF::Vocab::DC.modified, value)
end

#annotated_byObject



178
179
180
# File 'lib/active_annotations/rdf_annotation.rb', line 178

def annotated_by
  get_value(annotation_id, RDF::Vocab::DC.creator) || get_value(annotation_id, RDF::Vocab::OA.annotatedBy)
end

#annotated_by=(value) ⇒ Object



182
183
184
185
186
187
188
189
190
# File 'lib/active_annotations/rdf_annotation.rb', line 182

def annotated_by=(value)
  unless annotated_by.nil?
    @graph.delete({ subject: RDF::URI(annotated_by) })
  end

  value = value.nil? ? nil : RDF::URI(value)
  set_value(annotation_id, RDF::Vocab::DC.creator, value)
  set_value(value, RDF.type, RDF::Vocab::FOAF.Person)
end

#annotation_idObject



121
122
123
# File 'lib/active_annotations/rdf_annotation.rb', line 121

def annotation_id
  find_id(RDF::Vocab::OA.Annotation)
end

#body_idObject



125
126
127
128
# File 'lib/active_annotations/rdf_annotation.rb', line 125

def body_id
  statement = @graph.first(subject: annotation_id, predicate: RDF::Vocab::OA.hasBody)
  statement.nil? ? nil : statement.object
end

#contentObject



169
170
171
# File 'lib/active_annotations/rdf_annotation.rb', line 169

def content
  get_value(body_id, RDF::Vocab::CNT.chars)
end

#content=(value) ⇒ Object



173
174
175
176
# File 'lib/active_annotations/rdf_annotation.rb', line 173

def content=(value)
  ensure_body!
  set_value(body_id, RDF::Vocab::CNT.chars, value)
end

#end_timeObject



158
159
160
161
162
163
# File 'lib/active_annotations/rdf_annotation.rb', line 158

def end_time
  value = fragment_value.nil? ? nil : fragment_value.object.value.scan(/^t=(.*)$/).flatten.first.split(/,/)[1]
  Float(value)
rescue
  value
end

#end_time=(value) ⇒ Object



165
166
167
# File 'lib/active_annotations/rdf_annotation.rb', line 165

def end_time=(value)
  self.fragment_value = "t=#{[start_time, value].join(',')}"
end

#ensure_body!Object



79
80
81
82
83
84
85
86
87
88
# File 'lib/active_annotations/rdf_annotation.rb', line 79

def ensure_body!
  if body_id.nil?
    bid = new_id
    add_statements(
      RDF::Statement.new(annotation_id, RDF::Vocab::OA.hasBody, bid),
      RDF::Statement.new(bid, RDF.type, RDF::Vocab::DCMIType.Text),
      RDF::Statement.new(bid, RDF.type, RDF::Vocab::CNT.ContentAsText)
    )
  end
end

#ensure_selector!Object



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/active_annotations/rdf_annotation.rb', line 100

def ensure_selector!
  if selector_id.nil?
    ensure_target!
    sid = new_id
    add_statements(
      RDF::Statement.new(target_id, RDF::Vocab::OA.hasSelector, sid),
      RDF::Statement.new(sid, RDF.type, RDF::Vocab::OA.FragmentSelector),
      RDF::Statement.new(sid, RDF::Vocab::DC.conformsTo, RDF::URI('http://www.w3.org/TR/media-frags/'))
    )
  end
end

#ensure_target!Object



90
91
92
93
94
95
96
97
98
# File 'lib/active_annotations/rdf_annotation.rb', line 90

def ensure_target!
  if target_id.nil?
    tid = new_id
    add_statements(
      RDF::Statement.new(annotation_id, RDF::Vocab::OA.hasTarget, tid),
      RDF::Statement.new(tid, RDF.type, RDF::Vocab::OA.SpecificResource)
    )
  end
end

#find_id(type) ⇒ Object



116
117
118
119
# File 'lib/active_annotations/rdf_annotation.rb', line 116

def find_id(type)
  statement = @graph.first(predicate: RDF.type, object: type)
  statement.nil? ? nil : statement.subject
end

#fragment_valueObject



138
139
140
# File 'lib/active_annotations/rdf_annotation.rb', line 138

def fragment_value
  graph.first(subject: selector_id, predicate: RDF.value)
end

#fragment_value=(value) ⇒ Object



142
143
144
145
# File 'lib/active_annotations/rdf_annotation.rb', line 142

def fragment_value=(value)
  ensure_selector!
  set_value(selector_id, RDF.value, value)
end

#get_value(s, p) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
# File 'lib/active_annotations/rdf_annotation.rb', line 49

def get_value(s, p)
  return nil if s.nil?
  statement = graph.first(subject: s, predicate: p)
  if statement.nil?
    return nil
  elsif statement.object.is_a?(RDF::Literal)
    statement.object.object
  else
    statement.object.value
  end
end

#labelObject



220
221
222
# File 'lib/active_annotations/rdf_annotation.rb', line 220

def label
  get_value(annotation_id, RDF::RDFS.label)
end

#label=(value) ⇒ Object



224
225
226
# File 'lib/active_annotations/rdf_annotation.rb', line 224

def label=(value)
  set_value(annotation_id, RDF::RDFS.label, value)
end

#new_idObject



112
113
114
# File 'lib/active_annotations/rdf_annotation.rb', line 112

def new_id
  RDF::URI.new("urn:uuid:#{SecureRandom.uuid}")
end

#selector_idObject



134
135
136
# File 'lib/active_annotations/rdf_annotation.rb', line 134

def selector_id
  find_id(RDF::Vocab::OA.FragmentSelector)
end

#set_value(s, p, value) ⇒ Object



61
62
63
64
65
# File 'lib/active_annotations/rdf_annotation.rb', line 61

def set_value(s, p, value)
  return nil if s.nil?
  @graph.delete({ subject: s, predicate: p })
  @graph << RDF::Statement.new(s, p, value) unless value.nil?
end

#sourceObject



200
201
202
203
# File 'lib/active_annotations/rdf_annotation.rb', line 200

def source
  # TODO: Replace this with some way of retrieving the actual source
  get_value(target_id, RDF::Vocab::OA.hasSource)
end

#source=(value) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/active_annotations/rdf_annotation.rb', line 205

def source=(value)
  unless target_id.nil?
    statement = @graph.first(subject: target_id, predicate: RDF::Vocab::OA.hasSource)
    @graph.delete({ subject: statement.object, predicate: RDF.type }) unless statement.nil?
    @graph.delete({ subject: target_id, predicate: RDF::Vocab::OA.hasSource })
  end
  unless value.nil?
    ensure_target!
    add_statements(
      RDF::Statement.new(target_id, RDF::Vocab::OA.hasSource, RDF::URI(value.rdf_uri)),
      RDF::Statement.new(RDF::URI(value.rdf_uri), RDF.type, value.rdf_type)
    )
  end
end

#start_timeObject



147
148
149
150
151
152
# File 'lib/active_annotations/rdf_annotation.rb', line 147

def start_time
  value = fragment_value.nil? ? nil : fragment_value.object.value.scan(/^t=(.*)$/).flatten.first.split(/,/)[0]
  Float(value)
rescue
   value
end

#start_time=(value) ⇒ Object



154
155
156
# File 'lib/active_annotations/rdf_annotation.rb', line 154

def start_time=(value)
  self.fragment_value = "t=#{[value, end_time].join(',')}"
end

#target_idObject



130
131
132
# File 'lib/active_annotations/rdf_annotation.rb', line 130

def target_id
  find_id(RDF::Vocab::OA.SpecificResource)
end

#to_jsonld(opts = {}) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/active_annotations/rdf_annotation.rb', line 28

def to_jsonld(opts={})
  input = JSON.parse(graph.dump :jsonld, standard_prefixes: true, prefixes: { oa: RDF::Vocab::OA.to_iri.value })
  frame = YAML.load(File.read(File.expand_path('../frame.yml',__FILE__)))
  output = JSON::LD::API.frame(input, frame, omitDefault: true, documentLoader: DocumentLoader.document_loader)
  output.merge!(output.delete('@graph')[0])
  if opts[:pretty_json]
    JSON.pretty_generate output
  else
    output.to_json
  end
end