Module: Tripod::Finders::ClassMethods

Defined in:
lib/tripod/finders.rb

Instance Method Summary collapse

Instance Method Details

#_construct_query_for_uris_and_graphs(uris_and_graphs) ⇒ Object

 Generate a CONSTRUCT query for the given uri and graph pairs.



196
197
198
199
200
201
202
203
# File 'lib/tripod/finders.rb', line 196

def _construct_query_for_uris_and_graphs(uris_and_graphs)
  value_pairs = uris_and_graphs.map do |(uri, graph)|
    u = RDF::URI.new(uri).to_base
    g = graph ? RDF::URI.new(graph).to_base : 'UNDEF'
    "(#{u} #{g})"
  end
  query = "CONSTRUCT { ?uri ?p ?o . #{ self.all_triples_construct("?uri") }} WHERE { GRAPH ?g { ?uri ?p ?o . #{ self.all_triples_where("?uri") } VALUES (?uri ?g) { #{ value_pairs.join(' ') } } } }"
end

#_create_and_hydrate_resources_from_sparql(select_sparql, opts = {}) ⇒ Object

Given a select query, perform a DESCRIBE query to get a graph of data from which we create and hydrate a collection of resources.

Parameters:

  • options (Hash)

    a customizable set of options



161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/tripod/finders.rb', line 161

def _create_and_hydrate_resources_from_sparql(select_sparql, opts={})
  # TODO: Optimization?: if return_graph option is false, then don't do this next line?
  uris_and_graphs = _select_uris_and_graphs(select_sparql, :uri_variable => opts[:uri_variable], :graph_variable => opts[:graph_variable])

  #there are no resources if there are no uris and graphs
  if uris_and_graphs.empty?
    []
  else
    construct_query = _construct_query_for_uris_and_graphs(uris_and_graphs)
    graph = _graph_of_triples_from_construct_or_describe(construct_query)
    _resources_from_graph(graph, uris_and_graphs)
  end
end

#_describe_query_for_select(select_sparql, opts = {}) ⇒ Object

 For a select query, generate a query which DESCRIBES all the results

Parameters:

  • options (Hash)

    a customizable set of options



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/tripod/finders.rb', line 178

def _describe_query_for_select(select_sparql, opts={})
  uri_variable = opts[:uri_variable] || "uri"
  "
    CONSTRUCT {
      ?tripod_construct_s ?tripod_construct_p ?tripod_construct_o .
      #{ all_triples_construct('?tripod_construct_s') }
    }
    WHERE {
      { SELECT (?#{uri_variable} as ?tripod_construct_s) {
        #{select_sparql}
      } }
      ?tripod_construct_s ?tripod_construct_p ?tripod_construct_o .
      #{ all_triples_where('?tripod_construct_s') }
    }
  "
end

#_graph_of_triples_from_construct_or_describe(construct_query) ⇒ Object

given a construct or describe query, return a graph of triples.



151
152
153
154
# File 'lib/tripod/finders.rb', line 151

def _graph_of_triples_from_construct_or_describe(construct_query)
  ntriples_str = Tripod::SparqlClient::Query.query(construct_query, Tripod.ntriples_header_str)
  _rdf_graph_from_ntriples_string(ntriples_str, graph=nil)
end

#_raw_describe_select_results(select_sparql, opts = {}) ⇒ Object

For a select query, get a raw serialisation of the DESCRIPTION of the resources from the database.

Parameters:

  • options (Hash)

    a customizable set of options



209
210
211
212
213
# File 'lib/tripod/finders.rb', line 209

def _raw_describe_select_results(select_sparql, opts={})
  accept_header = opts[:accept_header] || Tripod.ntriples_header_str
  query = _describe_query_for_select(select_sparql, :uri_variable => opts[:uri_variable])
  Tripod::SparqlClient::Query.query(query, accept_header)
end

#_rdf_graph_from_ntriples_string(ntriples_string, graph = nil) ⇒ Object

given a string of ntriples data, populate an RDF graph. If you pass a graph in, it will add to that one.



140
141
142
143
144
145
146
147
148
# File 'lib/tripod/finders.rb', line 140

def _rdf_graph_from_ntriples_string(ntriples_string, graph=nil)
  graph ||= RDF::Graph.new
  RDF::Reader.for(:ntriples).new(ntriples_string) do |reader|
    reader.each_statement do |statement|
      graph << statement
    end
  end
  graph
end

#_resources_from_graph(graph, uris_and_graphs) ⇒ Object

 given a graph of data, and a hash of uris=>graphs, create and hydrate some resources. Note: if any of the graphs are not set in the hash, those resources can still be constructed, but not persisted back to DB.



218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/tripod/finders.rb', line 218

def _resources_from_graph(graph, uris_and_graphs)
  repo = add_data_to_repository(graph)
  resources = []

  # TODO: ? if uris_and_graphs not passed in, we could get the
  # uris from the graph, and just not create the resoruces with a graph
  # (but they won't be persistable).

  uris_and_graphs.each do |(u,g)|

    # instantiate a new resource
    g ||= {}
    r = self.new(u, g)

    # make a graph of data for this resource's uri
    data_graph = RDF::Graph.new
    repo.query( [RDF::URI.new(u), :predicate, :object] ) do |statement|
      data_graph << statement

      if statement.object.is_a? RDF::Node
        repo.query( [statement.object, :predicate, :object] ) {|s| data_graph << s}
      end
    end

    # use it to hydrate this resource
    r.hydrate!(:graph => data_graph)
    r.new_record = false
    resources << r
  end

  resources
end

#_resources_from_sparql(select_sparql, opts = {}) ⇒ Object

 given a sparql select query, create and hydrate some resources

Parameters:

  • options (Hash)

    a customizable set of options



134
135
136
# File 'lib/tripod/finders.rb', line 134

def _resources_from_sparql(select_sparql, opts={})
  _create_and_hydrate_resources_from_sparql(select_sparql, opts)
end

#_select_uris_and_graphs(sparql, opts = {}) ⇒ Object

based on the query passed in, build an array of [uri, graph] pairs

Parameters:

  • sparql. (String)

    The sparql query

  • opts. (Hash)

    A hash of options.

  • options (Hash)

    a customizable set of options



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/tripod/finders.rb', line 257

def _select_uris_and_graphs(sparql, opts={})
  select_results = Tripod::SparqlClient::Query.select(sparql)
  
  uri_variable = opts[:uri_variable] || 'uri'
  graph_variable = opts[:graph_variable] || 'graph'

  return [] unless select_results.select{|r| r.keys.length > 0 }.any?

  select_results.reduce([]) do |memo, result|
    u = result[uri_variable]['value']
    g = result[graph_variable]['value'] if result[graph_variable]
    memo << [u, g]
    memo
  end
end

#allObject

 execute a query to return all objects (restricted by this class’s rdf_type if specified) returns a criteria object



92
93
94
# File 'lib/tripod/finders.rb', line 92

def all
  Tripod::Criteria.new(self)
end

#countObject



96
97
98
# File 'lib/tripod/finders.rb', line 96

def count
  self.all.count
end

#describe_select_results(select_sparql, opts = {}) ⇒ Object

returns a graph of triples which describe results of the sparql passed in.

Parameters:

  • options (Hash)

    a customizable set of options



122
123
124
125
# File 'lib/tripod/finders.rb', line 122

def describe_select_results(select_sparql, opts={})
  ntriples_string = _raw_describe_select_results(select_sparql, opts) # this defaults to using n-triples
  _rdf_graph_from_ntriples_string(ntriples_string)
end

#describe_uris(uris) ⇒ Object

returns a graph of triples which describe the uris passed in.



105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/tripod/finders.rb', line 105

def describe_uris(uris)
  graph = RDF::Graph.new

  if uris.length > 0
    uris_sparql_str = uris.map{ |u| "<#{u.to_s}>" }.join(" ")

    # Do a big describe statement, and read the results into an in-memory repo
    ntriples_string = Tripod::SparqlClient::Query.query("CONSTRUCT { ?s ?p ?o } WHERE { VALUES ?s { #{uris_sparql_str} }.  ?s ?p ?o . }", Tripod.ntriples_header_str)
    graph = _rdf_graph_from_ntriples_string(ntriples_string, graph)
  end

  graph
end

#find(uri, opts = {}) ⇒ Resource

Find a Resource by its uri (and, optionally, by its graph if there are more than one).

Examples:

Find a single resource by a uri.

Person.find('http://ric')
Person.find(RDF::URI('http://ric'))

Find a single resource by uri and graph

Person.find('http://ric', :graph_uri => 'http://example.com/people')

Find a single resource by uri, looking in any graph (i.e. the UNION graph)

Person.find('http://ric', :ignore_graph => true)

Find a single resource by uri and graph (DEPRECATED)

Person.find('http://ric', 'http://example.com/people')
Person.find(RDF::URI('http://ric'), Person.find(RDF::URI('http://example.com/people')))

Parameters:

  • uri (String, RDF::URI)

    The uri of the resource to find

  • opts (Hash, String, RDF::URI) (defaults to: {})

    Either an options hash (see above), or (for backwards compatibility) the uri of the graph from which to get the resource

Returns:

Raises:



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/tripod/finders.rb', line 28

def find(uri, opts={})
  if opts.is_a?(String) # backward compatibility hack
    graph_uri = opts
    ignore_graph = false
  else
    graph_uri = opts.fetch(:graph_uri, nil)
    ignore_graph = opts.fetch(:ignore_graph, false)
  end

  resource = nil
  if ignore_graph
    resource = self.new(uri, :ignore_graph => true)
  else
    graph_uri ||= self.get_graph_uri
    unless graph_uri
      # do a quick select to see what graph to use.
      select_query = "SELECT * WHERE { GRAPH ?g {<#{uri.to_s}> ?p ?o } } LIMIT 1"
      result = Tripod::SparqlClient::Query.select(select_query)
      if result.length > 0
        graph_uri = result[0]["g"]["value"]
      else
        raise Tripod::Errors::ResourceNotFound.new(uri)
      end
    end
    resource = self.new(uri, :graph_uri => graph_uri.to_s)
  end

  resource.hydrate!
  resource.new_record = false

  # check that there are triples for the resource (catches case when someone has deleted data
  # between our original check for the graph and hydrating the object.
  raise Tripod::Errors::ResourceNotFound.new(uri) if resource.repository.empty?

  # return the instantiated, hydrated resource
  resource
end

#find_by_sparql(sparql_query, opts = {}) ⇒ Array

Find a collection of Resources by a SPARQL select statement which returns their uris. Under the hood, this only executes two queries: a select, then a describe.

Examples:

Person.find_by_sparql('SELECT ?uri ?graph WHERE { GRAPH ?graph { ?uri ?p ?o } } LIMIT 3')

Parameters:

  • sparql_query. (String)

    A sparql query which returns a list of uris of the objects.

  • opts. (Hash)

    A hash of options.

  • options (Hash)

    a customizable set of options

Returns:

  • (Array)

    An array of hydrated resources of this class’s type.



79
80
81
# File 'lib/tripod/finders.rb', line 79

def find_by_sparql(sparql_query, opts={})
  _create_and_hydrate_resources_from_sparql(sparql_query, opts)
end

#firstObject



100
101
102
# File 'lib/tripod/finders.rb', line 100

def first
  self.all.first
end

#where(sparql_snippet) ⇒ Object

 execute a where clause on this resource. returns a criteria object



85
86
87
88
# File 'lib/tripod/finders.rb', line 85

def where(sparql_snippet)
  criteria = Tripod::Criteria.new(self)
  criteria.where(sparql_snippet)
end