Class: JenaAdapter

Inherits:
ActiveRdfAdapter
  • Object
show all
Defined in:
lib/activerdf_jena/jena_adapter.rb

Overview

Author: Karsten Huneycutt Copyright 2007 Valkeir Corporation License: LGPL

Defined Under Namespace

Classes: DataSourceDBConnection, JenaAdapterConfigurationError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params = {}) ⇒ JenaAdapter

:database

either use :url, :type, :username, AND :password (for a
regular connection) OR :datasource AND :type (for a container 
connection), default to memory data store
example for a derby connection:
  :database => {:url => "jdbc:derby:superfunky;create=true", :type => "Derby", :username => "", :password => ""}

:file

database wins over this, this wins over memory store.  parameter is
a string or file indicating the root directory for all files.

:model

name of model to use, default is jena's default

:ontology

set to language type if this needs to be viewed as an ontology, 
default nil, available :owl, :owl_dl, :owl_lite, :rdfs

:reasoner

set to reasoner to use -- default nil (none).  options:  :pellet, 
:transitive, :rdfs, :rdfs_simple, :owl_micro, :owl_mini, :owl, 
:generic_rule

:lucene

set to true to enable true lucene indexing of this store, default false


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/activerdf_jena/jena_adapter.rb', line 70

def initialize(params = {})
  dbparams = params[:database]
  self.ontology_type = params[:ontology]
  self.reasoner = params[:reasoner]
  self.keyword_search = params[:lucene]
  
  # if the model name is not provided and file persistence is used, then jena just
  # creates random files in the tmp dir. not good, as we need to know the model name
  # to have persistence
  if params[:model]
    self.model_name = params[:model]
  else
    self.model_name = "default"
  end
  
  if params[:file]
    if params[:file].respond_to? :path
      self.root_directory = File.expand_path(params[:file].path)
    else
      self.root_directory = params[:file]
    end
  end

  # do some sanity checking
  if self.keyword_search? && !LuceneARQ.lucene_available?
    raise JenaAdapterConfigurationError, "Lucene requested but is not available"
  end
  
  if self.reasoner == :pellet && !Pellet.pellet_available?
    raise JenaAdapterConfigurationError, "Pellet requested but not available"
  end

  if self.reasoner && !self.ontology_type
    raise JenaAdapterConfigurationError, "Ontology model needed for reasoner"
  end

  if dbparams
    if dbparams[:datasource]
      self.connection = DataSourceDBConnection.new(dbparams[:datasource],
                                                   dbparams[:type])
    else
      begin
        if !Jena::DB.send("#{dbparams[:type].downcase}_available?")
          raise JenaAdapterConfigurationError, "database type #{dbparams[:type]} not available"
        end
      rescue NameError
        raise JenaAdapterConfigurationError, "database type #{dbparams[:type]} not recognized"
      end

      self.connection = Jena::DB::DBConnection.new(dbparams[:url], 
                                                   dbparams[:username],
                                                   dbparams[:password],
                                                   dbparams[:type])
    end

    self.model_maker = Jena::Model::ModelFactory.createModelRDBMaker(connection)
    
  elsif self.root_directory
    self.model_maker = Jena::Model::ModelFactory.createFileModelMaker(self.root_directory)
  else
    self.model_maker = Jena::Model::ModelFactory.createMemModelMaker
  end
  

  self.base_model = self.model_maker.openModel(model_name)
  
  if self.ontology_type
    rf = map_reasoner_factory(self.reasoner)
    onturi = map_ontology_type(self.ontology_type)

    spec = 
      Jena::Ontology::OntModelSpec.new(self.model_maker,
                                       Jena::Ontology::OntDocumentManager.new,
                                       rf, onturi)

    self.model = Jena::Model::ModelFactory.
      createOntologyModel(spec, self.base_model)
    self.reasoning = true
  else
    self.model = self.base_model
    self.reasoning = false
  end
  
  self.reads = true
  self.writes = true
  
  self
end

Instance Attribute Details

#base_modelObject

Returns the value of attribute base_model.



47
48
49
# File 'lib/activerdf_jena/jena_adapter.rb', line 47

def base_model
  @base_model
end

#connectionObject

Returns the value of attribute connection.



46
47
48
# File 'lib/activerdf_jena/jena_adapter.rb', line 46

def connection
  @connection
end

#lucene_indexObject

Returns the value of attribute lucene_index.



47
48
49
# File 'lib/activerdf_jena/jena_adapter.rb', line 47

def lucene_index
  @lucene_index
end

#modelObject

Returns the value of attribute model.



47
48
49
# File 'lib/activerdf_jena/jena_adapter.rb', line 47

def model
  @model
end

#model_makerObject

Returns the value of attribute model_maker.



47
48
49
# File 'lib/activerdf_jena/jena_adapter.rb', line 47

def model_maker
  @model_maker
end

#model_nameObject

Returns the value of attribute model_name.



46
47
48
# File 'lib/activerdf_jena/jena_adapter.rb', line 46

def model_name
  @model_name
end

#ontology_typeObject

Returns the value of attribute ontology_type.



46
47
48
# File 'lib/activerdf_jena/jena_adapter.rb', line 46

def ontology_type
  @ontology_type
end

#reasonerObject

Returns the value of attribute reasoner.



46
47
48
# File 'lib/activerdf_jena/jena_adapter.rb', line 46

def reasoner
  @reasoner
end

#root_directoryObject

Returns the value of attribute root_directory.



48
49
50
# File 'lib/activerdf_jena/jena_adapter.rb', line 48

def root_directory
  @root_directory
end

Instance Method Details

#add(subject, predicate, object, context = nil) ⇒ Object



197
198
199
200
201
202
# File 'lib/activerdf_jena/jena_adapter.rb', line 197

def add(subject, predicate, object, context = nil)
  self.lucene_index_behind = true
  self.model.add(build_statement(subject, predicate, object))
  self.model.prepare if self.model.respond_to? :prepare
  self.model.rebind if self.model.respond_to? :rebind
end

#clearObject



180
181
182
183
184
# File 'lib/activerdf_jena/jena_adapter.rb', line 180

def clear
  self.model.removeAll
  self.model.prepare if self.model.respond_to? :prepare
  self.model.rebind if self.model.respond_to? :rebind
end

#closeObject



174
175
176
177
178
# File 'lib/activerdf_jena/jena_adapter.rb', line 174

def close
  ConnectionPool.remove_data_source(self)
  self.model.close
  self.connection.close unless self.connection.nil?
end

#delete(subject, predicate, object, context = nil) ⇒ Object



187
188
189
190
191
192
193
194
195
# File 'lib/activerdf_jena/jena_adapter.rb', line 187

def delete(subject, predicate, object, context = nil)
  self.lucene_index_behind = true
  s = (is_wildcard?(subject) ? nil : build_subject(subject))
  p = (is_wildcard?(predicate) ? nil : build_predicate(predicate))
  o = (is_wildcard?(object) ? nil : build_object(object))
  self.model.removeAll(s, p, o)
  self.model.prepare if self.model.respond_to? :prepare
  self.model.rebind if self.model.respond_to? :rebind
end

#dumpObject



164
165
166
167
168
169
170
171
172
# File 'lib/activerdf_jena/jena_adapter.rb', line 164

def dump
  it = self.model.listStatements
  res = ""
  while it.hasNext
    res += it.nextStatement.asTriple.toString
    res += " . \n"
  end
  res
end

#flushObject



204
205
206
# File 'lib/activerdf_jena/jena_adapter.rb', line 204

def flush
  # no-op
end

#load(uri, params = {}) ⇒ Object

:format

format -- :ntriples, :n3, or :rdfxml, default :rdfxml

:into

either the name of a model, :default_model for the main model, or 
:submodel to load into an anonymous memory model, default is :submodel
if this is an ontology, :default_model if it's not.

:rebind

rebind with the inferencer, default true; no effect if no inferencer


217
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
250
# File 'lib/activerdf_jena/jena_adapter.rb', line 217

def load(uri, params = {})
  into = params[:into] ? params[:into] : 
    (self.ontology_type ? :submodel : :default_model)
  format = params[:format] ? params[:format] : :rdfxml
  rebind = params[:rebind] ? params[:rebind] : true
  
  jena_format =
    case format
    when :rdfxml
      "RDF/XML"
    when :ntriples
      "N-TRIPLE"
    when :n3
      "N3"
    end

  case into
  when :default_model
    self.model.read(uri, jena_format)
    
  when :submodel
    self.model.add(Jena::Model::ModelFactory.createDefaultModel.read(uri, jena_format))
    
  else
    self.model.add(self.model_maker.createModel(into).read(uri, jena_format))
  end
  
  if rebind && self.reasoner && self.model.respond_to?(:rebind)
    self.model.rebind
  end

  self.lucene_index_behind = true
  
end

#query(query, params = {}) ⇒ Object

this method gets called by the ActiveRDF query engine



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'lib/activerdf_jena/jena_adapter.rb', line 253

def query(query, params = {})

  if self.keyword_search? && query.keyword?
          
    # duplicate the query
    query_with_keywords = query.dup
    
    # now duplicate the where stuff so we can fiddle with it...
    # this is GROSS -- fix this if Query ever sprouts a proper
    # deep copy or a where_clauses setter
    query_with_keywords.instance_variable_set("@where_clauses", query.where_clauses.dup)

    # now, for each of the keyword clauses, set up the search
    query.keywords.each do |var, keyword|
      # use this if activerdf expects the subject to come back and not the
      # literal and using indexbuilderstring
      #query.where("lucene_literal_#{var}".to_sym, LuceneARQ::KEYWORD_PREDICATE, keyword)
      #query.where(var, "lucene_property_#{var}".to_sym, "lucene_literal_#{var}".to_sym)

      # use this if activerdf expects the literal to come back, not the 
      # subject, or if using indexbuildersubject (which makes the subject
      # come back instead of the literal
      query_with_keywords.where(var, RDFS::Resource.new(LuceneARQ::KEYWORD_PREDICATE), keyword)

    end

  else
    query_with_keywords = query
  end

  # jena knows about lucene, so use the query object that has the keyword
  # search requests expanded.
  jena_results = query_jena(query_with_keywords)

  # use the conjunctive query facility in pellet to get additional 
  # answers, if we're using pellet and we don't have a pure keyword
  # query
  if self.reasoner == :pellet && query.where_clauses.size > 0
    # pellet doesn't know about lucene, so we use the original query
    # object
    pellet_results = query_pellet(query)
    results = (jena_results + pellet_results).uniq!
  else
    results = jena_results
  end

  if query.ask?
    return [[true]] if results.size > 0
    return [[false]]
  end
  
  if query.count?
    return results.size
  end

  results
  
end

#sizeObject



160
161
162
# File 'lib/activerdf_jena/jena_adapter.rb', line 160

def size
  self.model.size
end