[Mpuls-commits] r4048 - in base/trunk: . mpulsweb/model

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Wed Oct 27 19:01:09 CEST 2010


Author: bh
Date: 2010-10-27 19:01:06 +0200 (Wed, 27 Oct 2010)
New Revision: 4048

Modified:
   base/trunk/ChangeLog
   base/trunk/mpulsweb/model/case.py
   base/trunk/mpulsweb/model/logbook.py
Log:
Main implementation of logbook import (mpuls/issue1314)

* mpulsweb/model/case.py (MPulsXMLImporter.__init__): New.  Pass
the logbook factory to the base class so that logbooks can be
imported too.
(MPulsXMLImporter.import_case): Import the logbook if the case has
one.

* mpulsweb/model/logbook.py (string_iso_time): New. Helper function to
decode timestamps when importing from XML.
(get_logbook_import_factory): New. Returns a component factory for
XML import via libformed.
(xml_to_db): New. Map XML element names to the corresponding database
column
(import_logbook): New. Import the logbook from XML.
(load_known_entries): New.  Helper function to load the known
logbook entries including their uuids
(update_logbook_entry, create_logbook_entry): New functions to
create or update logbook entries when importing from XML.


Modified: base/trunk/ChangeLog
===================================================================
--- base/trunk/ChangeLog	2010-10-27 16:45:21 UTC (rev 4047)
+++ base/trunk/ChangeLog	2010-10-27 17:01:06 UTC (rev 4048)
@@ -1,5 +1,27 @@
 2010-10-27  Bernhard Herzog  <bh at intevation.de>
 
+	Main implementation of logbook import (mpuls/issue1314)
+
+	* mpulsweb/model/case.py (MPulsXMLImporter.__init__): New.  Pass
+	the logbook factory to the base class so that logbooks can be
+	imported too.
+	(MPulsXMLImporter.import_case): Import the logbook if the case has
+	one.
+
+	* mpulsweb/model/logbook.py (string_iso_time): New. Helper function to
+	decode timestamps when importing from XML.
+	(get_logbook_import_factory): New. Returns a component factory for
+	XML import via libformed.
+	(xml_to_db): New. Map XML element names to the corresponding database
+	column
+	(import_logbook): New. Import the logbook from XML.
+	(load_known_entries): New.  Helper function to load the known
+	logbook entries including their uuids
+	(update_logbook_entry, create_logbook_entry): New functions to
+	create or update logbook entries when importing from XML.
+
+2010-10-27  Bernhard Herzog  <bh at intevation.de>
+
 	* mpulsweb/model/case.py (MPulsXMLImporter.import_case): Rename
 	parameter case to components like in the base class.
 	(MPulsXMLImporter.import_allowed): Rename parameter case to

Modified: base/trunk/mpulsweb/model/case.py
===================================================================
--- base/trunk/mpulsweb/model/case.py	2010-10-27 16:45:21 UTC (rev 4047)
+++ base/trunk/mpulsweb/model/case.py	2010-10-27 17:01:06 UTC (rev 4048)
@@ -59,7 +59,8 @@
     ConsistenceCheckException, PHASEFIELD
 from mpulsweb.model.user import UserObject
 from mpulsweb.model.agencysettings import Agency
-from mpulsweb.model.logbook import export_logbook
+from mpulsweb.model.logbook import export_logbook, get_logbook_import_factory, \
+     import_logbook
 
 
 log = logging.getLogger(__name__)
@@ -1351,6 +1352,12 @@
 WHERE m.uuid_id = %(uuid)s
 """
 
+    def __init__(self, meta_tree, extra_factories=None):
+        if extra_factories is None:
+            extra_factories = dict()
+        extra_factories["tagebuch"] = get_logbook_import_factory()
+        XMLImporter.__init__(self, meta_tree, extra_factories)
+
     def import_xml(self, db, infile):
         """Extend the base class method to reformat rule violation exceptions
         """
@@ -1379,7 +1386,8 @@
 
     def import_case(self, factory, cursor, components):
         if self.import_allowed(cursor, components):
-            XMLImporter.import_case(self, factory, cursor, components)
+            tree = XMLImporter.import_case(self, factory, cursor, components)
+            import_logbook(tree, cursor, components.get("tagebuch"))
 
     def import_allowed(self, cursor, components):
         uuid = components["master"].uuid

Modified: base/trunk/mpulsweb/model/logbook.py
===================================================================
--- base/trunk/mpulsweb/model/logbook.py	2010-10-27 16:45:21 UTC (rev 4047)
+++ base/trunk/mpulsweb/model/logbook.py	2010-10-27 17:01:06 UTC (rev 4048)
@@ -30,9 +30,17 @@
 import re
 import logging
 from datetime import timedelta, datetime
+import time
 import xml.etree.ElementTree as ET
 
 from pylons import app_globals as g
+
+import formed.meta.data as data
+from formed.meta.structure import StructureNode
+from formed.instance.backends.xmlimport import ComponentFactory
+from formed.instance.simplified import StructureInstanceNode, \
+     StructureInstanceTree
+
 import mpulsweb.lib.helpers as h
 from mpulsweb.lib.db import db
 from mpulsweb.lib.evaluation import LogbookEvaluation
@@ -417,7 +425,10 @@
     return ("%04d-%02d-%02dT%02d:%02d:%02d"
             % (d.year, d.month, d.day, d.hour, d.minute, d.second))
 
+def string_iso_time(s):
+    return datetime(*(time.strptime(s, "%Y-%m-%dT%H:%M:%S")[0:6]))
 
+
 def export_logbook(case, case_id, cursor, selection, anonymize):
     """Add the contents of the case with id case_id to the elementtree case"""
     logbook = Logbook()
@@ -442,4 +453,89 @@
         text_subelement(entry_element, "tagebuch-typ", entry.typ)
 
 
+def get_logbook_import_factory():
+    """Return the component factory for the logbook for the libformed xmlimport
+    """
+    entry_node = StructureNode("tagebuch-eintrag",
+                               {"tagebuch-datum": data.TextLeaf(),
+                                "tagebuch-bearbeiter": data.TextLeaf(),
+                                "tagebuch-art": data.IntLeaf(),
+                                "tagebuch-sonstiges": data.TextLeaf(),
+                                "tagebuch-notiz": data.TextLeaf(),
+                                "tagebuch-dauer": data.IntLeaf(),
+                                "tagebuch-typ": data.IntLeaf(),
+                                },
+                               {})
+    return ComponentFactory(None,
+                            StructureNode(None, {},
+                                          {"tagebuch-eintrag": entry_node}),
+                            StructureInstanceNode,
+                            StructureInstanceTree)
+
+
+xml_to_db = {
+    "tagebuch-datum": "datum",
+    "tagebuch-bearbeiter": "bearbeiter",
+    "tagebuch-art": "art",
+    "tagebuch-sonstiges": "kurz_notiz",
+    "tagebuch-notiz": "notiz",
+    "tagebuch-dauer": "dauer",
+    "tagebuch-typ": "typ",
+    }
+
+def import_logbook(case_tree, cursor, logbook_tree):
+    """Import the logbook"""
+    entries = logbook_tree.root.get_repeat_groups("tagebuch-eintrag")
+    if entries:
+        case_id = case_tree.getRootNode().getIdentifier()
+        known = load_known_entries(case_id, cursor)
+        for entry in entries.itervalues():
+            if entry.uuid in known:
+                update_logbook_entry(case_id, cursor, entry, known[entry.uuid])
+            else:
+                create_logbook_entry(case_id, cursor, entry)
+
+
+def load_known_entries(case_id, cursor):
+    """Return a dictionary with all known logbook entries for the case case_id.
+    The dictionary maps the uuids of the entries to their database ids.
+    """
+    cursor.execute("SELECT id, uuid_id FROM ka_logbuch_tbl_view"
+                   " WHERE master_id = %(id)s", dict(id=case_id))
+    known = dict()
+    for id, uuid in cursor.fetchall():
+        known[uuid] = id
+    return known
+
+def update_logbook_entry(case_id, cursor, entry, entry_id):
+    """Update an existing logbook entry"""
+    assignments = []
+    values = dict(id=entry_id)
+    for key, value in entry.leaves.iteritems():
+        colname = xml_to_db.get(key)
+        if colname is None:
+            raise ValueError("Unknown logbook entry leaf: %r" % key)
+        assignments.append("%s = %%(%s)s" % (colname, key))
+        if value is not None:
+            # We need to special case 'dauer' and 'datum' for now
+            # because it cannot be handled by libformed alone yet.
+            if colname == "dauer":
+                value = timedelta(minutes=value)
+            elif colname == "datum":
+                value = string_iso_time(value)
+        values[key] = value
+
+    statement = ("UPDATE ka_logbuch_tbl_view SET %s WHERE id = %%(id)s"
+                 % (", ".join(assignments),))
+    cursor.execute(statement, values)
+
+
+def create_logbook_entry(case_id, cursor, entry):
+    """Create a new logbook entry."""
+    cursor.execute("SELECT create_logbuch_ds(%(case_id)s, %(uuid)s)",
+                   dict(case_id=case_id, uuid=entry.uuid))
+    entry_id = cursor.fetchone()[0]
+    update_logbook_entry(case_id, cursor, entry, entry_id)
+
+
 # vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8:



More information about the Mpuls-commits mailing list