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

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



189
190
191
# File 'lib/oa/graph.rb', line 189

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



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

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)



111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/oa/graph.rb', line 111

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



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



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

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
86
87
88
89
90
91
92
# File 'lib/oa/graph.rb', line 80

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



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

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


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

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


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

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


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

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


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

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