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.



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

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



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

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



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

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

#annotated_atObject



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

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

#annotated_at=(value) ⇒ Object



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

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

#annotated_byObject



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

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

#annotated_by=(value) ⇒ Object



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

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



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

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

#body_idObject



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

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

#contentObject



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

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

#content=(value) ⇒ Object



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

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

#end_timeObject



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

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



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

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

#ensure_body!Object



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

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



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

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



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

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



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

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

#fragment_valueObject



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

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

#fragment_value=(value) ⇒ Object



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

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

#get_value(s, p) ⇒ Object



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

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



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

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

#label=(value) ⇒ Object



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

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

#new_idObject



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

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

#selector_idObject



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

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

#set_value(s, p, value) ⇒ Object



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

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



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

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



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

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



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

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



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

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

#target_idObject



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

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
39
# 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, validate: false, omitDefault: true, documentLoader: DocumentLoader.document_loader)
  graph = output.delete('@graph').try(:first)
  output.merge!(graph) if graph
  if opts[:pretty_json]
    JSON.pretty_generate output
  else
    output.to_json
  end
end