Class: OA::Graph

Inherits:
Object
  • Object
show all
Defined in:
lib/oa/graph.rb,
lib/oa/graph/version.rb

Overview

a wrapper class for RDF::Graph that adds methods specific to OpenAnnotation (www.openannotation.org/spec/core/) Annotation objects. This is intended to be used for an RDF::Graph of a single annotation

Constant Summary collapse

OA_CONTEXT_URL =
'http://www.w3.org/ns/oa.jsonld'
OA_DATED_CONTEXT_URL =
'http://www.w3.org/ns/oa-context-20130208.json'
IIIF_CONTEXT_URL =
'http://iiif.io/api/presentation/2/context.json'
VERSION =
'0.0.1'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rdf_graph) ⇒ Graph

instantiate this class for an RDF::Graph of a single annotation



42
43
44
# File 'lib/oa/graph.rb', line 42

def initialize(rdf_graph)
  @graph = rdf_graph
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args, &block) ⇒ Object

send unknown methods to RDF::Graph



186
187
188
# File 'lib/oa/graph.rb', line 186

def method_missing(sym, *args, &block)
  @graph.send sym, *args, &block
end

Class Method Details

.anno_queryRDF::Query

Returns query for a subject :s with type of RDF::Vocab::OA.Annotation.

Returns:

  • (RDF::Query)

    query for a subject :s with type of RDF::Vocab::OA.Annotation



34
35
36
37
# File 'lib/oa/graph.rb', line 34

def self.anno_query
  q = RDF::Query.new
  q << [:s, RDF.type, RDF::Vocab::OA.Annotation]
end

.subject_statements(subject, graph) ⇒ Array[RDF::Statement]

given an RDF::Resource (an RDF::Node or RDF::URI), look for all the statements with that object as the subject, and recurse through the graph to find all descendant statements pertaining to the subject

Parameters:

  • subject

    the RDF object to be used as the subject in the graph query. Should be an RDF::Node or RDF::URI

  • graph (RDF::Graph)

Returns:

  • (Array[RDF::Statement])

    all the triples with the given subject



23
24
25
26
27
28
29
30
# File 'lib/oa/graph.rb', line 23

def self.subject_statements(subject, graph)
  result = []
  graph.query([subject, nil, nil]).each { |stmt|
    result << stmt
    subject_statements(stmt.object, graph).each { |s| result << s }
  }
  result.uniq
end

Instance Method Details

#annotated_atString

Returns The datetime from the annotatedAt property, or nil.

Returns:

  • (String)

    The datetime from the annotatedAt property, or nil



122
123
124
125
126
127
# File 'lib/oa/graph.rb', line 122

def annotated_at
  solution = @graph.query [nil, RDF::Vocab::OA.annotatedAt, nil]
  return if solution && solution.size == 1

  solution.first.object.to_s
end

#body_charsArray<String>

For all bodies that are of type ContentAsText, get the characters as a

single String in the returned Array.

Returns:

  • (Array<String>)

    body chars as Strings, in an Array (one element for each contentAsText body)



108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/oa/graph.rb', line 108

def body_chars
  result = []
  q = RDF::Query.new
  q << [nil, RDF::Vocab::OA.hasBody, :body]
  q << [:body, RDF.type, RDF::Vocab::CNT.ContentAsText]
  q << [:body, RDF::Vocab::CNT.chars, :body_chars]
  solns = @graph.query q
  solns.each { |soln|
    result << soln.body_chars.value
  }
  result
end

#id_as_urlString

Returns the id of this annotation as a url string, or nil if it is a Node.

Returns:

  • (String)

    the id of this annotation as a url string, or nil if it is a Node



67
68
69
70
71
72
73
74
# File 'lib/oa/graph.rb', line 67

def id_as_url
  solution = @graph.query self.class.anno_query
  return if solution && solution.size == 1

  rdf_resource = solution.first.s
  rdf_resource.to_s if rdf_resource.is_a?(RDF::URI)
  # TODO:  raise exception if not a URI?
end

#jsonld_iiifObject

Returns json-ld representation of graph with IIIF context as a url.

Returns:

  • json-ld representation of graph with IIIF context as a url



56
57
58
59
60
61
# File 'lib/oa/graph.rb', line 56

def jsonld_iiif
  inline_context = @graph.dump(:jsonld, context: IIIF_CONTEXT_URL)
  hash_from_json = JSON.parse(inline_context)
  hash_from_json['@context'] = IIIF_CONTEXT_URL
  hash_from_json.to_json
end

#jsonld_oaObject

Returns json-ld representation of graph with OpenAnnotation context as a url.

Returns:

  • json-ld representation of graph with OpenAnnotation context as a url



48
49
50
51
52
53
# File 'lib/oa/graph.rb', line 48

def jsonld_oa
  inline_context = @graph.dump(:jsonld, context: OA_DATED_CONTEXT_URL)
  hash_from_json = JSON.parse(inline_context)
  hash_from_json['@context'] = OA_DATED_CONTEXT_URL
  hash_from_json.to_json
end

#make_null_relative_uri_out_of_blank_nodeObject

transform an outer blank node into a null relative URI



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/oa/graph.rb', line 166

def make_null_relative_uri_out_of_blank_node
  anno_stmts = @graph.query([nil, RDF.type, RDF::Vocab::OA.Annotation])
  anno_rdf_obj = anno_stmts.first.subject
  if anno_rdf_obj.is_a?(RDF::Node)
    # use null relative URI representation of blank node
    anno_subject = RDF::URI.new
  else # it's already a URI
    anno_subject = anno_rdf_obj
  end
  OA::Graph.subject_statements(anno_rdf_obj, @graph).each { |s|
    if s.subject == anno_rdf_obj && anno_subject != anno_rdf_obj
      @graph << RDF::Statement(subject: anno_subject,
                               predicate: s.predicate,
                               object: s.object)
      @graph.delete s
    end
  }
end

#motivated_byArray<String>

Returns Array of urls expressing the OA motivated_by values.

Returns:

  • (Array<String>)

    Array of urls expressing the OA motivated_by values



78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/oa/graph.rb', line 78

def motivated_by
  motivations = []
  q = self.class.anno_query.dup
  q << [:s, RDF::Vocab::OA.motivatedBy, :motivated_by]
  solution = @graph.query q
  if solution && solution.size > 0
    solution.each { |res|
      motivations << res.motivated_by.to_s
    }
  end
  # TODO:  raise exception if none? (validation)
  motivations
end

#predicate_urls(predicate) ⇒ Array<String>

Returns urls for the predicate, as an Array of Strings.

Parameters:

  • predicate (RDF::URI)

    either RDF::Vocab::OA.hasTarget or RDF::Vocab::OA.hasBody

Returns:

  • (Array<String>)

    urls for the predicate, as an Array of Strings



94
95
96
97
98
99
100
101
102
# File 'lib/oa/graph.rb', line 94

def predicate_urls(predicate)
  urls = []
  predicate_solns = @graph.query [nil, predicate, nil]
  predicate_solns.each { |predicate_stmt|
    predicate_obj = predicate_stmt.object
    urls << predicate_obj.to_str.strip if predicate_obj.is_a?(RDF::URI)
  }
  urls
end

#remove_has_body_statementsObject

remove all RDF::Vocab::OA.hasBody statements and any other statements associated

with body objects


142
143
144
# File 'lib/oa/graph.rb', line 142

def remove_has_body_statements
  remove_predicate_and_its_object_statements RDF::Vocab::OA.hasBody
end

#remove_has_target_statementsObject

remove all RDF::Vocab::OA.hasTarget statements and any other statements

associated with body objects


148
149
150
# File 'lib/oa/graph.rb', line 148

def remove_has_target_statements
  remove_predicate_and_its_object_statements RDF::Vocab::OA.hasTarget
end

#remove_non_base_statementsObject

remove all RDF::Vocab::OA.hasBody and .hasTarget statements

and any other statements associated with body and target objects,
leaving all statements to be stored as part of base object in LDP store


135
136
137
138
# File 'lib/oa/graph.rb', line 135

def remove_non_base_statements
  remove_has_target_statements
  remove_has_body_statements
end

#remove_predicate_and_its_object_statements(predicate) ⇒ Object

remove all such predicate statements and any other statements associated

with predicates' objects


154
155
156
157
158
159
160
161
162
163
# File 'lib/oa/graph.rb', line 154

def remove_predicate_and_its_object_statements(predicate)
  predicate_stmts = @graph.query([nil, predicate, nil])
  predicate_stmts.each { |pstmt|
    pred_obj = pstmt.object
    OA::Graph.subject_statements(pred_obj, @graph).each { |s|
      @graph.delete s
    } unless !OA::Graph.subject_statements(pred_obj, @graph)
    @graph.delete pstmt
  }
end