from oldman.resource.resource import ClientResource
from oldman.store.selector import DataStoreSelector
from oldman.model.manager import ClientModelManager
DEFAULT_MODEL_NAME = "Default_Client"
[docs]class ClientResourceManager:
"""
TODO: describe
"""
def __init__(self, data_stores, schema_graph=None, attr_extractor=None, oper_extractor=None,
declare_default_operation_functions=True):
self._model_manager = ClientModelManager(self, schema_graph=schema_graph, attr_extractor=attr_extractor,
oper_extractor=oper_extractor,
declare_default_operation_functions=declare_default_operation_functions)
self._store_selector = DataStoreSelector(data_stores)
# Default model
self._model_manager.create_model(DEFAULT_MODEL_NAME, {u"@context": {}}, self, untyped=True,
iri_prefix=u"http://localhost/.well-known/genid/client/",
is_default=True)
@property
[docs] def model_manager(self):
return self._model_manager
[docs] def declare_method(self, method, name, class_iri):
"""Attaches a method to the :class:`~oldman.resource.Resource` objects that are instances of a given RDFS class.
Like in Object-Oriented Programming, this method can be overwritten by attaching a homonymous
method to a class that has a higher inheritance priority (such as a sub-class).
To benefit from this method (or an overwritten one), :class:`~oldman.resource.Resource` objects
must be associated to a :class:`~oldman.model.Model` that corresponds to the RDFS class or to one of its
subclasses.
:param method: Python function that takes as first argument a :class:`~oldman.resource.Resource` object.
:param name: Name assigned to this method.
:param class_iri: Targeted RDFS class. If not overwritten, all the instances
(:class:`~oldman.resource.Resource` objects) should inherit this method.
"""
models = self._model_manager.find_descendant_models(class_iri)
for model in models:
if model.class_iri is None:
continue
model.declare_method(method, name, class_iri)
[docs] def new(self, id=None, types=None, hashless_iri=None, collection_iri=None, **kwargs):
"""Creates a new :class:`~oldman.resource.Resource` object **without saving it** in the `data_store`.
The `kwargs` dict can contains regular attribute key-values that will be assigned to
:class:`~oldman.attribute.OMAttribute` objects.
:param id: IRI of the new resource. Defaults to `None`.
If not given, the IRI is generated by the IRI generator of the main model.
:param types: IRIs of RDFS classes the resource is instance of. Defaults to `None`.
Note that these IRIs are used to find the models of the resource
(see :func:`~oldman.resource.manager.ResourceManager.find_models_and_types` for more details).
:param hashless_iri: hash-less IRI that MAY be considered when generating an IRI for the new resource.
Defaults to `None`. Ignored if `id` is given. Must be `None` if `collection_iri` is given.
:param collection_iri: IRI of the controller to which this resource belongs. This information
is used to generate a new IRI if no `id` is given. The IRI generator may ignore it.
Defaults to `None`. Must be `None` if `hashless_iri` is given.
:return: A new :class:`~oldman.resource.Resource` object.
"""
if (types is None or len(types) == 0) and len(kwargs) == 0:
name = id if id is not None else ""
self._logger.info(u"""New resource %s has no type nor attribute.
As such, nothing is stored in the data graph.""" % name)
# Store of the resource
store = self._store_selector.select_store(id=id, types=types, hashless_iri=hashless_iri,
collection_iri=collection_iri, **kwargs)
return ClientResource(self, self._model_manager, store, id=id, types=types, hashless_iri=hashless_iri,
collection_iri=collection_iri, **kwargs)
[docs] def create(self, id=None, types=None, hashless_iri=None, collection_iri=None, **kwargs):
"""Creates a new resource and save it in the `data_store`.
See :func:`~oldman.resource.manager.ResourceManager.new` for more details.
"""
return self.new(id=id, types=types, hashless_iri=hashless_iri,
collection_iri=collection_iri, **kwargs).save()
[docs] def get(self, id=None, types=None, hashless_iri=None, eager_with_reversed_attributes=True, **kwargs):
"""See :func:`oldman.store.datastore.DataStore.get`."""
#TODO: consider parallelism
store_resources = [store.get(id=id, types=types, hashless_iri=hashless_iri,
eager_with_reversed_attributes=eager_with_reversed_attributes, **kwargs)
for store in self._store_selector.select_stores(id=id, types=types,
hashless_iri=hashless_iri, **kwargs)]
returned_store_resources = filter(lambda x: x, store_resources)
resources = self._model_manager.convert_store_resources(returned_store_resources)
resource_count = len(resources)
if resource_count == 1:
return resources[0]
elif resource_count == 0:
return None
#TODO: find a better exception and explain better
#TODO: see if relevant
raise Exception("Non unique object")
[docs] def filter(self, types=None, hashless_iri=None, limit=None, eager=False, pre_cache_properties=None, **kwargs):
"""See :func:`oldman.store.datastore.DataStore.filter`."""
#TODO: support again generator. Find a way to aggregate them.
resources = [r for store in self._store_selector.select_stores(types=types, hashless_iri=hashless_iri,
pre_cache_properties=pre_cache_properties,
**kwargs)
for r in store.filter(types=types, hashless_iri=hashless_iri, limit=limit, eager=eager,
pre_cache_properties=pre_cache_properties, **kwargs)]
return self._model_manager.convert_store_resources(resources)
[docs] def sparql_filter(self, query):
"""See :func:`oldman.store.datastore.DataStore.sparql_filter`."""
#TODO: support again generator. Find a way to aggregate them.
resources = [r for store in self._store_selector.select_sparql_stores(query)
for r in store.sparql_filter(query)]
return self._model_manager.convert_store_resources(resources)
[docs] def use_store_model(self, class_iri, data_store=None):
raise NotImplementedError("TODO: implement me here")
[docs] def import_store_models(self):
"""TODO: check possible conflicts with local models."""
for store in self._store_selector.data_stores:
for store_model in store.model_manager.models:
is_default = (store_model.class_iri is None)
self._model_manager.import_model(store_model, store,
is_default=is_default)
[docs] def get_model(self, class_name_or_iri):
return self._model_manager.get_model(class_name_or_iri)