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.3'

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



44
45
46
# File 'lib/oa/graph.rb', line 44

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



171
172
173
# File 'lib/oa/graph.rb', line 171

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



36
37
38
39
# File 'lib/oa/graph.rb', line 36

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



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

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



107
108
109
110
# File 'lib/oa/graph.rb', line 107

def annotated_at
  solution = @graph.query [nil, RDF::Vocab::OA.annotatedAt, nil]
  solution.first.object.to_s if solution && solution.size == 1
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)



98
99
100
101
102
103
104
# File 'lib/oa/graph.rb', line 98

def body_chars
  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]
  @graph.query(q).each.collect {|stmt| stmt.body_chars.value}
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



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

def id_as_url
  solution = @graph.query self.class.anno_query
  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
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



58
59
60
61
62
63
# File 'lib/oa/graph.rb', line 58

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



50
51
52
53
54
55
# File 'lib/oa/graph.rb', line 50

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



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/oa/graph.rb', line 149

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
    else
      next
    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



80
81
82
83
84
85
# File 'lib/oa/graph.rb', line 80

def motivated_by
  q = self.class.anno_query.dup
  q << [:s, RDF::Vocab::OA.motivatedBy, :motivated_by]
  # if the motivation object gives junk with .to_s, then the anno is illegal anyway and we're not responsible
  @graph.query(q).each.collect {|stmt| stmt.motivated_by.to_s}
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



90
91
92
# File 'lib/oa/graph.rb', line 90

def predicate_urls(predicate)
  @graph.query([nil, predicate, nil]).each_object.collect {|o| o.to_str.strip if o.is_a?(RDF::URI) }.compact
end

#remove_has_body_statementsObject

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

associated with body objects


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

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


131
132
133
# File 'lib/oa/graph.rb', line 131

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


118
119
120
121
# File 'lib/oa/graph.rb', line 118

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


137
138
139
140
141
142
143
144
145
146
# File 'lib/oa/graph.rb', line 137

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
    } if OA::Graph.subject_statements(pred_obj, @graph)
    @graph.delete pstmt
  }
end