# Copyright (c) 2009, Digital Enterprise Research Institute (DERI),
# NUI Galway
# All rights reserved.
# author: Cosmin Basca
# email: cosmin.basca@gmail.com
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with
# the distribution.
# * Neither the name of DERI nor the
# names of its contributors may be used to endorse or promote
# products derived from this software without specific prior
# written permission.
# THIS SOFTWARE IS PROVIDED BY DERI ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DERI BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
# OF THE POSSIBILITY OF SUCH DAMAGE.
# -*- coding: utf-8 -*-
__author__ = 'Cosmin Basca'
import logging
from plugin import manager
from plugin.manager import load_plugins, PluginNotFoundException, add_plugin_path, registered_readers, registered_writers
from plugin.reader import RDFReader
from plugin.writer import RDFWriter
from surf.query import Query
from surf.rdf import URIRef
__readers__ = manager.__readers__
__writers__ = manager.__writers__
# A constant to use as context argument when we want to avoid default context.
# Example: sess.get_resource(uri, Concept, context = surf.NO_CONTEXT),
# this explicitly says that no context should be used.
NO_CONTEXT = "no-context"
[docs]class Store(object):
""" The `Store` class is comprised of a reader and a writer, getting
access to an underlying triple store. Also store specific parameters must
be handled by the class, the plugins act based on various settings.
The `Store` is also the `plugin` manager and provides convenience methods
for working with plugins.
"""
""" True if the `reader` plugin is using sub queries, False otherwise. """
use_subqueries = False
default_context = property(lambda self: self.__default_context)
def __init__(self, reader = None, writer = None, *args, **kwargs):
self.log = logging.getLogger(self.__class__.__name__)
self.log.info('initializing the store')
load_plugins()
self.__default_context = None
if "default_context" in kwargs:
self.__default_context = URIRef(kwargs["default_context"])
if reader:
if reader in __readers__:
self.reader = __readers__[reader](*args, **kwargs)
elif isinstance(reader, RDFReader):
# We've received already configured reader, use it.
self.reader = reader
else:
raise PluginNotFoundException('The <%s> READER plugin was not found' % (reader))
else:
self.reader = RDFReader(*args, **kwargs)
if writer:
if writer in __writers__:
self.writer = __writers__[writer](self.reader, *args, **kwargs)
elif isinstance(writer, RDFWriter):
# We've received already configured writer, use it.
self.writer = writer
else:
raise PluginNotFoundException('The <%s> WRITER plugin was not found' % (reader))
else:
self.writer = RDFWriter(self.reader, *args, **kwargs)
if hasattr(self.reader, 'use_subqueries'):
self.use_subqueries = property(fget = lambda self: self.reader.use_subqueries)
self.log.info('store initialized')
def __add_default_context(self, context):
""" Return default context if context is None. """
if context == NO_CONTEXT:
context = None
elif not context:
context = self.__default_context
return context
[docs] def enable_logging(self, enable):
""" Toggle `logging` on or off. """
level = enable and logging.DEBUG or logging.NOTSET
self.log.setLevel(level)
self.reader.enable_logging(enable)
self.writer.enable_logging(enable)
[docs] def is_enable_logging(self):
""" True if `logging` is enabled, False otherwise. """
return (self.log.level == logging.DEBUG)
[docs] def close(self):
""" Close the `store`.
Both the `reader` and the `writer` plugins are closed.
See :func:`surf.plugin.writer.RDFWriter.close`
and :func:`surf.plugin.reader.RDFReader.close` methods.
"""
try:
self.reader.close()
self.log.debug('reader closed successfully')
except Exception, e:
self.log.exception("Error on closing the reader")
try:
self.writer.close()
self.log.debug('writer closed successfully')
except Exception, e:
self.log.exception("Error on closing the writer")
#---------------------------------------------------------------------------
# the reader interface
#---------------------------------------------------------------------------
[docs] def get(self, resource, attribute, direct):
""" :func:`surf.plugin.reader.RDFReader.get` method. """
return self.reader.get(resource, attribute, direct)
# cRud
[docs] def load(self, resource, direct):
""" :func:`surf.plugin.reader.RDFReader.load` method. """
return self.reader.load(resource, direct)
[docs] def is_present(self, resource):
""" :func:`surf.plugin.reader.RDFReader.is_present` method. """
return self.reader.is_present(resource)
[docs] def concept(self, resource):
""" :func:`surf.plugin.reader.RDFReader.concept` method. """
return self.reader.concept(resource)
[docs] def instances_by_attribute(self, resource, attributes, direct, context):
""" :func:`surf.plugin.reader.RDFReader.instances_by_attribute` method. """
context = self.__add_default_context(context)
return self.reader.instances_by_attribute(resource, attributes,
direct, context)
def get_by(self, params):
params["context"] = self.__add_default_context(params.get("context"))
return self.reader.get_by(params)
#---------------------------------------------------------------------------
# the query reader interface
#---------------------------------------------------------------------------
[docs] def execute(self, query):
"""see :meth:`surf.plugin.query_reader.RDFQueryReader.execute` method. """
if hasattr(self.reader, 'execute') and isinstance(query, Query):
return self.reader.execute(query)
return None
[docs] def execute_sparql(self, sparql_query, format = 'JSON'):
"""see :meth:`surf.plugin.query_reader.RDFQueryReader.execute_sparql` method. """
if hasattr(self.reader, 'execute_sparql') and type(sparql_query) in [str, unicode]:
return self.reader.execute_sparql(sparql_query, format = format)
return None
#---------------------------------------------------------------------------
# the writer interface
#---------------------------------------------------------------------------
[docs] def clear(self, context = None):
""" See :func:`surf.plugin.writer.RDFWriter.clear` method. """
context = self.__add_default_context(context)
self.writer.clear(context = context)
# Crud
[docs] def save(self, *resources):
""" See :func:`surf.plugin.writer.RDFWriter.save` method. """
self.writer.save(*resources)
for resource in resources:
resource.dirty = False
# crUd
[docs] def update(self, *resources):
""" See :func:`surf.plugin.writer.RDFWriter.update` method. """
self.writer.update(*resources)
for resource in resources:
resource.dirty = False
# cruD
[docs] def remove(self, *resources, **kwargs):
""" See :func:`surf.plugin.writer.RDFWriter.remove` method. """
self.writer.remove(*resources, **kwargs)
for resource in resources:
resource.dirty = False
[docs] def size(self):
""" See :func:`surf.plugin.writer.RDFWriter.size` method. """
return self.writer.size()
# triple level access methods
[docs] def add_triple(self, s = None, p = None, o = None, context = None):
""" See :func:`surf.plugin.writer.RDFWriter.add_triple` method. """
context = self.__add_default_context(context)
self.writer.add_triple(s = s, p = p, o = o, context = context)
[docs] def set_triple(self, s = None, p = None, o = None, context = None):
""" See :func:`surf.plugin.writer.RDFWriter.set_triple` method. """
context = self.__add_default_context(context)
self.writer.set_triple(s = s, p = p, o = o, context = context)
[docs] def remove_triple(self, s = None, p = None, o = None, context = None):
""" See :func:`surf.plugin.writer.RDFWriter.remove_triple` method. """
context = self.__add_default_context(context)
self.writer.remove_triple(s = s, p = p, o = o, context = context)
[docs] def index_triples(self, **kwargs):
""" See :func:`surf.plugin.writer.RDFWriter.index_triples` method. """
return self.writer.index_triples(**kwargs)
[docs] def load_triples(self, context=None, **kwargs):
""" See :func:`surf.plugin.writer.RDFWriter.load_triples` method. """
context = self.__add_default_context(context)
return self.writer.load_triples(context=context, **kwargs)