[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