Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dao #1

Open
wants to merge 3 commits into
base: jper
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions sss/config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os, uuid, sys, json
from ingesters_disseminators import DefaultEntryIngester, DefaultDisseminator, FeedDisseminator, BinaryIngester, SimpleZipIngester, METSDSpaceIngester
from negotiator import AcceptParameters, ContentType
from core import SwordServer, Authenticator, WebUI
from core import SwordServer, Authenticator, DAO, WebUI

from sss_logging import logging
ssslog = logging.getLogger(__name__)
Expand Down Expand Up @@ -171,8 +171,9 @@
# In this default configuration we use the built-in SSS repository's
# implementations for everything
"sword_server" : "sss.repository.SSS",
"dao" : "sss.repository.DAO"
"authenticator" : "sss.repository.SSSAuthenticator",
"webui" : "sss.repository.WebInterface"
"webui" : "sss.repository.WebInterface",
}
"""

Expand Down Expand Up @@ -206,7 +207,13 @@ def get_authenticator_implementation(self):
return self._get_class(self.authenticator)
else:
return Authenticator


def get_dao_implementation(self):
if self.dao is not None:
return self._get_class(self.dao)
else:
return DAO

def get_webui_implementation(self):
if self.webui is not None:
return self._get_class(self.webui)
Expand Down Expand Up @@ -293,7 +300,7 @@ def _load_json(self):
c = ""
for line in f:
if line.strip().startswith("#"):
c+= "\n" # this makes it easier to debug the config
c += "\n" # this makes it easier to debug the config
else:
c += line
return json.loads(c)
Expand Down
147 changes: 147 additions & 0 deletions sss/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,153 @@ def basic_authenticate(self, username, password, obo):
def repoze_who_authenticate(self, identity, obo):
raise NotImplementedError()

class DAO(object):
"""
Data Access Object for interacting with the store
"""
def __init__(self, config):
"""
Initialise the DAO and create the store directory in the Configuration() object if it does not already
exist along with the relevant collections.
"""
raise NotImplementedError()

def get_collection_names(self):
""" list all the collections in the store """
raise NotImplementedError()

def get_container_names(self, collection):
""" list all the containers in the collection """
raise NotImplementedError()

def collection_exists(self, collection):
"""
Does the specified collection exist?
Args:
-collection: the Collection name
Returns true or false
"""
raise NotImplementedError()

def container_exists(self, collection, id):
"""
Does the specified container exist? If the collection does not exist this will still return and will return
false
Args:
-collection: the Collection name
-id: the container id
Returns true or false
"""
raise NotImplementedError()

def file_exists(self, collection, id, filename):
raise NotImplementedError()

def create_container(self, collection, id=None):
"""
Create a container in the specified collection. The container will be assigned a random UUID as its
identifier.
Args:
-collection: the collection name in which to create the container
Returns the ID of the container
"""
# invent an identifier for the item, and create its directory
# we may have been passed an ID to use
raise NotImplementedError()

def save(self, filepath, content, opts="w"):
"""
Shortcut to save the content to the filepath with the associated file handle opts (defaults to "w", so pass
in "wb" for binary files
"""
raise NotImplementedError()

def get_filename(self, filename):
"""
Create a timestamped file name to avoid name clashes in the store
"""
raise NotImplementedError()

def store_atom(self, collection, id, atom):
""" Store the supplied atom document content in the object identified by the id in the specified collection """
raise NotImplementedError()

def store_content(self, collection, id, content, filename):
"""
Store the supplied content in the object identified by the id in the specified collection under the supplied
filename. In reality, to avoid name collisions the filename will be preceded with a timestamp in the store.
Returns the localised filename the content was stored under
"""
raise NotImplementedError()

def store_statement(self, collection, id, statement):
""" Store the supplied statement document content in the object identified by the id in the specified collection """
# store the RDF version
raise NotImplementedError()

def store_deposit_receipt(self, collection, id, receipt):
""" Store the supplied receipt document content in the object identified by the id in the specified collection """
raise NotImplementedError()

def store_metadata(self, collection, id, metadata):
""" Store the supplied metadata dictionary in the object identified by the id in the specified collection """
raise NotImplementedError()

def get_metadata(self, collection, id):
raise NotImplementedError()

def remove_content(self, collection, id, keep_metadata=False, keep_atom=False):
"""
Remove all the content from the specified container. If keep_metadata is True then the sss_metadata.xml
file will not be removed
"""
raise NotImplementedError()

def remove_container(self, collection, id):
""" Remove the specified container and all of its contents """
raise NotImplementedError()

def get_store_path(self, collection, id=None, filename=None):
"""
Get the path to the specified filename in the store. This is a utility method and should be used with care;
all content which goes into the store through the store_content method will have its filename localised to
avoid name clashes, so this method CANNOT be used to retrieve those files. Instead, this should be used
internally to locate sss specific files in the container, and for packagers to write their own files into
the store which are not part of the content itself.
"""
raise NotImplementedError()

def get_deposit_receipt_content(self, collection, id):
""" Read the deposit receipt for the specified container """
raise NotImplementedError()

def get_statement_content(self, collection, id):
""" Read the statement for the specified container """
raise NotImplementedError()

def get_statement_feed(self, collection, id):
""" Read the statement for the specified container """
raise NotImplementedError()

def get_atom_content(self, collection, id):
""" Read the statement for the specified container """
raise NotImplementedError()

def load_statement(self, collection, id):
"""
Load the Statement object for the specified container
Returns a Statement object fully populated to represent this object
"""
raise NotImplementedError()

def list_content(self, collection, id, exclude=[]):
"""
List the contents of the specified container, excluding any files whose name exactly matches those in the
exclude list. This method will also not list sss specific files, thus limiting it to the content files of
the object.
"""
raise NotImplementedError()

class EntryDocument(object):

def __init__(self, atom_id=None, alternate_uri=None, content_uri=None, edit_uri=None, se_uri=None, em_uris=None,
Expand Down
16 changes: 11 additions & 5 deletions sss/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from sss_logging import logging
ssslog = logging.getLogger(__name__)


class WebInterface(WebUI):
def get(self, path=None):
if path is not None:
Expand Down Expand Up @@ -146,7 +147,8 @@ def __init__(self, config, auth):
SwordServer.__init__(self, config, auth)

# create a DAO for us to use
self.dao = DAO(self.configuration)
DAO = config.get_dao_implementation()
self.dao = DAO(config)

# create a Namespace object for us to use
self.ns = Namespaces()
Expand Down Expand Up @@ -994,6 +996,9 @@ def get_collection_names(self):
""" list all the collections in the store """
return os.listdir(self.configuration.store_dir)

def get_container_names(self, collection):
return os.listdir(self.get_store_path(collection))

def collection_exists(self, collection):
"""
Does the specified collection exist?
Expand Down Expand Up @@ -1207,7 +1212,8 @@ class HomePage(WebPage):
"""
def __init__(self, config):
self.config = config
self.dao = DAO(self.config)
DAO = config.get_dao_implementation()
self.dao = DAO(config)
self.um = URIManager(config)

def get_home_page(self):
Expand All @@ -1229,17 +1235,16 @@ def get_home_page(self):
class CollectionPage(WebPage):
def __init__(self, config):
self.config = config
DAO = config.get_dao_implementation()
self.dao = DAO(config)
self.um = URIManager(config)

def get_collection_page(self, id):
frag = "<h1>Collection: " + id + "</h1>"

# list all of the containers in the collection
cpath = self.dao.get_store_path(id)
containers = os.listdir(cpath)
frag += "<h2>Containers</h2><ul>"
for container in containers:
for container in self.dao.get_container_names(id):
frag += "<li><a href=\"" + self.um.html_url(id, container) + "\">" + container + "</a></li>"
frag += "</ul>"

Expand All @@ -1250,6 +1255,7 @@ def get_collection_page(self, id):
class ItemPage(WebPage):
def __init__(self, config):
self.config = config
DAO = config.get_dao_implementation()
self.dao = DAO(config)
self.um = URIManager(config)

Expand Down
1 change: 1 addition & 0 deletions sss/sss.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
# In this default configuration we use the built-in SSS repository's
# implementations for everything
"sword_server" : "sss.repository.SSS",
"dao" : "sss.repository.DAO",
"authenticator" : "sss.repository.SSSAuthenticator",
"webui" : "sss.repository.WebInterface"
}