]> git.parisson.com Git - telemeta.git/commitdiff
fix OAI-PMH for new models and dublincore api
authorolivier <>
Mon, 15 Feb 2010 19:57:36 +0000 (19:57 +0000)
committerolivier <>
Mon, 15 Feb 2010 19:57:36 +0000 (19:57 +0000)
telemeta/interop/oai.py
telemeta/interop/oaidatasource.py
telemeta/models/core.py
telemeta/models/dublincore.py

index 64ae6d5bf33c55ae58fcfbbc43a737784b26250c..8524b10ee2eb9a569d69b0f4b1865f2aca8f85f1 100644 (file)
@@ -54,7 +54,8 @@ class IDataSource(object):
                 [(dublin core element, element value), ...],
                 change time
               )
-           or None if the record doesn't exist.
+           or None if the record doesn't exist. In case the id isn't wellformed
+           a BadArgumentError should be raised.
 
            The dublin core data must contain an 'identifier' element, which is the same
            as the id parameter."""
@@ -387,7 +388,11 @@ class Response(object):
 
     def get_record(self, id):
         """Append GetRecord result"""
-        record = self.datasource.get_record(id)
+        try:
+            record = self.datasource.get_record(id)
+        except BadArgumentError, e:
+            self.error('badArgument', e.message)
+            return
         if not record:
             self.error('idDoesNotExist')
         else:
@@ -505,3 +510,6 @@ class Response(object):
         except AttributeError:
             # Apparently no free/unlink method in libxml2dom
             pass
+
+class BadArgumentError(Exception):
+    pass
index d0ebc5784c18f03017a8e214d6f937e98b2f174e..21a7eab9bc9793ea7e7f2572918afba525bf5bcb 100644 (file)
@@ -29,7 +29,8 @@
 # The fact that you are presently reading this means that you have had
 # knowledge of the CeCILL license and that you accept its terms.
 
-from telemeta.models import MediaCollection, MediaItem, Revision
+from telemeta.models import MediaCollection, MediaItem, Revision, dublincore
+from telemeta.interop.oai import BadArgumentError
 from datetime import datetime
 
 class TelemetaOAIDataSource(object):
@@ -43,41 +44,17 @@ class TelemetaOAIDataSource(object):
         except IndexError:
             return datetime.now()
 
-    def prepare_record(self, type, record):
+    def prepare_record(self, record):
         ctime = record.get_revision().time
-        dc = []
-        _dc = record.to_dublincore().to_list()
-        for k, v in _dc:
-            if k == 'identifier':
-                dc.append((k, type + ':' + v)) # FIXME: type prepended by CREM model
-            else:
-                dc.append((k, v))
-        return (dc, ctime)
+        return dublincore.express_resource(record).to_list(), ctime
 
     def get_record(self, id):
         """Return a specific record"""
         try:
-            type, id = id.split(':')
-        except ValueError:
-            return None
-        
-        #FIXME: search by code
-        if (type == 'collection'):
-            try:
-                record  = MediaCollection.objects.get(id=id)
-            except MediaCollection.DoesNotExist:
-                return None
-        elif (type == 'item'):
-            try:
-                #FIXME: also search by old_code if code is not found
-                record = MediaItem.objects.get(id=id)
-            except MediaItem.DoesNotExist:
-                return None
-        else:
-            return None
-
-        return self.prepare_record(type, record)
-
+            record = dublincore.lookup_resource(id)
+        except dublincore.MalformedMediaIdentifier, e:
+            raise BadArgumentError(e.message)
+        return record and self.prepare_record(record)
 
     def count_records(self, from_time = None, until_time = None):
         """Must return the number of records between (optional) from and until change time."""
@@ -95,7 +72,7 @@ class TelemetaOAIDataSource(object):
         if (offset < nitems):
             set = query[offset:offset + limit]
             for record in set:
-                result.append(self.prepare_record('item', record))
+                result.append(self.prepare_record(record))
             limit -= len(set)
             offset = 0
         else:
@@ -105,6 +82,6 @@ class TelemetaOAIDataSource(object):
             query = MediaCollection.objects.by_change_time(from_time, until_time)
             set = query[offset:offset + limit]
             for record in set:
-                result.append(self.prepare_record('collection', record))
+                result.append(self.prepare_record(record))
             
         return result
index 7db1716cb5e0da69d37de44b1060fd4afb1261df..02c48b5b8cb7c3439839d4edbb25a96b42dd9512 100644 (file)
@@ -432,13 +432,19 @@ class CoreQuerySet(EnhancedQuerySet):
         
     def _by_change_time(self, type, from_time = None, until_time = None):
         "Search between two revision dates"
-        where = ["element_type = '%s'" % type]
+        table = self.model._meta.db_table
+        where = []
         if from_time:
-            where.append("time >= '%s'" % from_time.strftime('%Y-%m-%d %H:%M:%S'))
+            where.append("revisions.time >= '%s'" % from_time.strftime('%Y-%m-%d %H:%M:%S'))
         if until_time:
-            where.append("time <= '%s'" % until_time.strftime('%Y-%m-%d %H:%M:%S'))
-        return self.extra(
-            where = ["id IN (SELECT DISTINCT element_id FROM revisions WHERE %s)" % " AND ".join(where)]);
+            where.append("revisions.time <= '%s'" % until_time.strftime('%Y-%m-%d %H:%M:%S'))
+
+        qs = self
+        if where:
+            where.extend(["revisions.element_type = '%s'" % type, "revisions.element_id = %s.id" % table])
+            qs = qs.extra(where = [" AND ".join(where)],
+                            tables = ['revisions']).distinct()
+        return qs
 
 class CoreManager(EnhancedManager):
     "Base class for all models managers"
index b59cca8e82693bec0506b05194622b057319cef1..439e7c414e4911feb14bf2a85fe577d434df153f 100644 (file)
@@ -33,6 +33,7 @@
 # Author: Olivier Guilyardi <olivier@samalyse.com>
 
 from telemeta.models.core import Duration
+from telemeta.models.media import MediaItem, MediaCollection
 from django.conf import settings
 
 class Resource(object):
@@ -106,8 +107,9 @@ class Element(object):
     @staticmethod
     def multiple(name, values, refinement=None):
         elements = []
-        for v in values:
-            elements.append(Element(name, v, refinement))
+        if values:
+            for v in values:
+                elements.append(Element(name, v, refinement))
         return elements
 
 class Date(Element):
@@ -211,7 +213,7 @@ def express_item(item):
         Element('publisher',        settings.TELEMETA_ORGANIZATION),
         date,
         Date(item.collection.year_published, refinement='issued'),
-        Element.multiple('coverage', item.location.fullnames(), 'spatial'),
+        Element.multiple('coverage', item.location and item.location.fullnames(), 'spatial'),
         Element('coverage',         item.location_comment, 'spatial'),
         Element('rights',           item.collection.legal_rights, 'license'),
         Element('rights',           media_access_rights(item.collection), 'accessRights'),
@@ -224,4 +226,35 @@ def express_item(item):
 
     return resource
     
-
+def express_resource(res):
+    if isinstance(res, MediaItem):
+        return express_item(res)
+    elif isinstance(res, MediaCollection):
+        return express_collection(res)
+
+    raise Exception("Invalid resource type")        
+
+def lookup_resource(media_id):
+    try:
+        type, code = media_id.split(':', 1)
+    except ValueError:
+        raise MalformedMediaIdentifier("Media identifier must be in type:code format")
+    
+    if (type == 'collection'):
+        try:
+            return MediaCollection.objects.get(code=code)
+        except MediaCollection.DoesNotExist:
+            return None
+    elif (type == 'item'):
+        try:
+            return MediaItem.objects.get(code=code)
+        except MediaItem.DoesNotExist:
+            try:
+                return MediaItem.objects.get(old_code=code)
+            except MediaItem.DoesNotExist:
+                return None
+    else:
+        raise MalformedMediaIdentifier("No such type in media identifier: " + type)
+   
+class MalformedMediaIdentifier(Exception):
+    pass