[Mpuls-commits] r2141 - in wasko/branches/2.0/jmdweb: controllers converter lib model
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Thu Mar 25 09:41:40 CET 2010
Author: torsten
Date: 2010-03-25 09:41:39 +0100 (Thu, 25 Mar 2010)
New Revision: 2141
Removed:
wasko/branches/2.0/jmdweb/controllers/__init__.py
wasko/branches/2.0/jmdweb/converter/__init__.py
wasko/branches/2.0/jmdweb/converter/wasko_v1v2.py
wasko/branches/2.0/jmdweb/lib/csv.py
wasko/branches/2.0/jmdweb/lib/excel.py
wasko/branches/2.0/jmdweb/lib/exportselection.py
wasko/branches/2.0/jmdweb/lib/uuid.py
wasko/branches/2.0/jmdweb/lib/xmlexport.py
wasko/branches/2.0/jmdweb/lib/xmlhelper.py
wasko/branches/2.0/jmdweb/lib/xmlimport.py
wasko/branches/2.0/jmdweb/model/casexml.py
wasko/branches/2.0/jmdweb/model/data.py
wasko/branches/2.0/jmdweb/model/exprtree.py
wasko/branches/2.0/jmdweb/model/io/
wasko/branches/2.0/jmdweb/model/nodecomponents.py
wasko/branches/2.0/jmdweb/model/phase_transition.py
wasko/branches/2.0/jmdweb/model/phases.py
wasko/branches/2.0/jmdweb/model/phases_factory.py
wasko/branches/2.0/jmdweb/model/semantic.py
Log:
Removed old and unusd modules and libs which deals with the old formedtree or
phasemodell. Also removed xml import and export helpers.
Deleted: wasko/branches/2.0/jmdweb/controllers/__init__.py
===================================================================
--- wasko/branches/2.0/jmdweb/controllers/__init__.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/controllers/__init__.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,23 +0,0 @@
-# Copyright 2007, 2008 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
Deleted: wasko/branches/2.0/jmdweb/converter/__init__.py
===================================================================
--- wasko/branches/2.0/jmdweb/converter/__init__.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/converter/__init__.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1 +0,0 @@
-#Do not remove me!
Deleted: wasko/branches/2.0/jmdweb/converter/wasko_v1v2.py
===================================================================
--- wasko/branches/2.0/jmdweb/converter/wasko_v1v2.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/converter/wasko_v1v2.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,131 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# (c) 2008 by Intevation GmbH
-# This is Free software under the GPLv3.
-# See LICENSE comming with the source of 'mpuls offline'
-# for details.
-#
-# author: Sascha L. Teichmann <sascha.teichmann at intevation.de>
-#
-# Converts WASKO v1 to v2 documents
-# old:
-# geschw_w_a
-# geschw_m_a
-# geschw_hh_a
-# geschw_w_b
-# geschw_m_b
-# geschw_hh_b
-# geschw_w_c
-# geschw_m_c
-# geschw_hh_c
-# geschw_w_d
-# geschw_m_d
-# geschw_hh_d
-#
-# new:
-# geschw_w
-# geschw_m
-# geschw_hh
-# geschw_alt_a
-# geschw_alt_b
-# geschw_alt_c
-# geschw_alt_d
-#
-# old -> new:
-# geschw_w = geschw_w_a + geschw_w_b + geschw_w_c + geschw_w_d
-# geschw_m = geschw_m_a + geschw_m_b + geschw_m_c + geschw_m_d
-# geschw_hh_a = geschw_hh_a + geschw_hh_b + geschw_hh_c + geschw_hh_d
-# geschw_alt_a = geschw_w_a + geschw_m_a
-# geschw_alt_b = geschw_w_b + geschw_m_b
-# geschw_alt_c = geschw_w_c + geschw_m_c
-# geschw_alt_d = geschw_w_d + geschw_m_d
-
-from jmdweb.lib.xmlhelper import decode_int
-
-
-def getConverterFactory():
- return WaskoV1V2
-
-OLD_ITEMS = frozenset([
- 'geschw_w_a', 'geschw_m_a', 'geschw_hh_a',
- 'geschw_w_b', 'geschw_m_b', 'geschw_hh_b',
- 'geschw_w_c', 'geschw_m_c', 'geschw_hh_c',
- 'geschw_w_d', 'geschw_m_d', 'geschw_hh_d'])
-
-ADDS = (
- ('geschw_w', ('geschw_w_a', 'geschw_w_b', 'geschw_w_c', 'geschw_w_d')),
- ('geschw_m', ('geschw_m_a', 'geschw_m_b', 'geschw_m_c', 'geschw_m_d')),
- ('geschw_hh', ('geschw_hh_a', 'geschw_hh_b', 'geschw_hh_c', 'geschw_hh_d')),
- ('geschw_alt_a', ('geschw_w_a', 'geschw_m_a')),
- ('geschw_alt_b', ('geschw_w_b', 'geschw_m_b')),
- ('geschw_alt_c', ('geschw_w_c', 'geschw_m_c')),
- ('geschw_alt_d', ('geschw_w_d', 'geschw_m_d')))
-
-def add(a, b):
- if a is None: return b
- if b is None: return a
- return a + b
-
-class WaskoV1V2(object):
-
- def __init__(self):
- self.data = {}
- self.nat_staat = None
- self.kf_meth_c_1 = None
- self.kf_meth_f_1 = None
-
-
- def reset(self):
- self.data.clear()
- self.nat_staat = None
- self.kf_meth_c_1 = None
- self.kf_meth_f_1 = None
-
- def eat(self, name, attrs, value):
-
- if name == 'kf_meth_c_1':
- self.kf_meth_c_1 = value
- return True
-
- if name == 'kf_meth_f_1':
- self.kf_meth_f_1 = value
- return True
-
- if name == 'nat_staat':
- self.nat_staat = value
- return True
-
- if name == 'nat_staat_t': # do not import
- return True
-
- if name in OLD_ITEMS:
- value = decode_int(value)
- if not value is None:
- self.data[name] = value
- return True
- return False
-
- def finish(self, master_loader):
-
- if not self.kf_meth_c_1 is None \
- or not self.kf_meth_f_1 is None:
- if not self.kf_meth_f_1 is None: value = self.kf_meth_f_1
- else: value = self.kf_meth_c_1
- master_loader.data.append(('kf_meth_f_1', value))
-
- if not self.nat_staat is None:
- nat_staat = decode_int(self.nat_staat)
- if master_loader.version < 2:
- if nat_staat == 29: # deutsch
- nat_staat = 1
- elif nat_staat != -1 or nat_staat != -3:
- nat_staat = 2 # andere
- master_loader.data.append(('nat_staat', nat_staat))
-
- if self.data:
- for key, values in ADDS:
- s = reduce(add, map(lambda v: self.data.get(v), values), None)
- if not s is None:
- master_loader.data.append((key, s))
-
-# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
Deleted: wasko/branches/2.0/jmdweb/lib/csv.py
===================================================================
--- wasko/branches/2.0/jmdweb/lib/csv.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/lib/csv.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,90 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright 2007, 2008 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-#
-# Authors:
-# Sascha L. Teichmann <teichmann at intevation.de>
-#
-
-from types import StringTypes
-
-from datetime import datetime
-
-from exportselection import SelectorFactory, CasePartsSelection
-
-from helpers import dd_mm_YYYY
-
-SEP = "\t"
-
-FETCH_ALL_IDS = \
-"""SELECT id FROM master_tbl_view"""
-
-BLACK_LIST = set(['id', 'master_id', 'uuid_id', 'bearbeiter_id'])
-
-def strReplace(x):
- if type(x) in StringTypes:
- x = unicode(str(x), "utf-8")
- return x.replace("\r", "").replace("\n", " ").replace(SEP, " ")
- if x is None: return ""
- if isinstance(x, datetime): return dd_mm_YYYY(x)
- return str(x)
-
-def exportAsCSV(cur, out, ids=None, case_parts=None, anonymize=False):
- if ids is None:
- cur.execute(FETCH_ALL_IDS)
- ids = []
- while True:
- row = cur.fetchone()
- if row is None: break
- ids.append(int(row[0]))
-
- if case_parts is None:
- case_parts = CasePartsSelection()
-
- selector_factory = SelectorFactory(case_parts, anonymize)
- selector = selector_factory.createSelector()
-
- stmnt = selector.getSelectStatementByView("master_tbl")
- if not stmnt: return
-
- used_indices = None
-
- mid = {}
- for id in ids:
- mid['id'] = id
- cur.execute(stmnt, mid)
- row = cur.fetchone()
- if not row: continue
- if used_indices is None:
- headers, used_indices = [], []
- for idx, d in enumerate(cur.description):
- if d[0] not in BLACK_LIST:
- used_indices.append(idx)
- headers.append(strReplace(d[0]))
- print >> out, SEP.join(headers)
-
- print >> out, SEP.join([strReplace(row[idx]) for idx in used_indices])
-
-# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
Deleted: wasko/branches/2.0/jmdweb/lib/excel.py
===================================================================
--- wasko/branches/2.0/jmdweb/lib/excel.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/lib/excel.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,189 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright 2007, 2008 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-#
-# Authors:
-# Sascha L. Teichmann <teichmann at intevation.de>
-#
-
-from types import StringTypes, IntType, LongType
-
-from jmdweb.model.data import WidgetCollector
-
-from exportselection import CasePartsSelection, SelectorFactory
-
-from StringIO import StringIO
-
-from pylons import g
-
-import sys
-
-FETCH_ALL_IDS = \
-"""SELECT id FROM master_tbl_view"""
-
-class MyStringIO(StringIO):
-
- def close(self):
- pass
-
- def real_close(self):
- MyStringIO.close(self)
-
-class FakeStr(str):
- def __init__(self, buf):
- self.buf = buf
-
-def fake_file(x, *args):
- return isinstance(x, FakeStr) and x.buf or file(x, *args)
-
-import pyExcelerator
-
-pyExcelerator.CompoundDoc.file = fake_file
-
-
-BLACK_LIST = set(['id', 'master_id', 'uuid_id', 'bearbeiter_id'])
-
-
-def to_str(x):
- t = type(x)
- if t in (IntType, LongType):
- return x
- if t in StringTypes:
- x = unicode(str(x), "utf-8")
- if len(x) > 32765: x = x[:32765]
- return x
- return str(x)
-
-class Sheet(object):
-
- def __init__(self, worksheet, column_names):
-
- for idx, name in enumerate(column_names):
- worksheet.write(0, idx, name)
-
- self.worksheet = worksheet
- self.row = 1
- self.column = 0
-
- def next_row(self):
- self.row += 1
- self.column = 0
-
- def add_data(self, value):
- if not value is None:
- self.worksheet.write(self.row, self.column, to_str(value))
- self.column += 1
-
-class Book:
-
- def __init__(self, selector):
- self.selector = selector
-
- self.workbook = pyExcelerator.Workbook()
-
- phase_a_collector = WidgetCollector()
- phase_b_collector = WidgetCollector()
- phase_c_collector = WidgetCollector()
-
- phase_ee = g.formedTree.findByName('ee')
- phase_a = g.formedTree.findByName('phase-a')
- phase_b = g.formedTree.findByName('phase-b')
- phase_c = g.formedTree.findByName('phase-c')
-
- phase_ee.visit(phase_a_collector.visitor)
- phase_a .visit(phase_a_collector.visitor)
- phase_b .visit(phase_b_collector.visitor)
- phase_c .visit(phase_c_collector.visitor)
-
- sheet_a = self.workbook.add_sheet("Phase A")
- sheet_b = self.workbook.add_sheet("Phase B")
- sheet_c = self.workbook.add_sheet("Phase C")
-
- projection = set(selector.master_projection)
-
- a_names = [w.getName() for w in phase_a_collector.widgets if w.getName() in projection]
- b_names = [w.getName() for w in phase_b_collector.widgets if w.getName() in projection]
- c_names = [w.getName() for w in phase_c_collector.widgets if w.getName() in projection]
-
- phase_a_sheet = Sheet(sheet_a, a_names)
- phase_b_sheet = Sheet(sheet_b, b_names)
- phase_c_sheet = Sheet(sheet_c, c_names)
-
- self.sheets = [phase_a_sheet, phase_b_sheet, phase_c_sheet]
-
- name2phase = dict([(n, phase_a_sheet) for n in a_names])
- name2phase.update(dict([(n, phase_b_sheet) for n in b_names]))
- name2phase.update(dict([(n, phase_c_sheet) for n in c_names]))
-
- self.name2phase = name2phase
-
- def add_cases(self, case_ids, cur):
- stmnt = self.selector.getSelectStatementByView("master_tbl")
- if not stmnt: return
- mid = {}
- name2phase, sheets = self.name2phase, self.sheets
- for case_id in case_ids:
- mid['id'] = case_id
- cur.execute(stmnt, mid)
- row = cur.fetchone()
- if not row: continue
- for desc, value in zip(cur.description, row):
- try:
- name2phase[desc[0]].add_data(value)
- except KeyError:
- pass
- for sheet in self.sheets:
- sheet.next_row()
-
- def write_xls(self, fname):
- self.workbook.save(fname)
-
-def exportAsXLS(cur, ids=None, case_parts=None, anonymize=False):
- if ids is None:
- ids = []
- cur.execute(FETCH_ALL_IDS)
- while True:
- row = cur.fetchone()
- if not row: break
- ids.append(int(row[0]))
-
- if case_parts is None:
- case_parts = CasePartsSelection()
-
- selectFactory = SelectorFactory(case_parts, anonymize)
-
- selector = selectFactory.createSelector()
-
- book = Book(selector)
- book.add_cases(ids, cur)
-
- try:
- out = MyStringIO()
- book.write_xls(FakeStr(out))
- return out.getvalue()
- finally:
- out.real_close()
-
-# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
Deleted: wasko/branches/2.0/jmdweb/lib/exportselection.py
===================================================================
--- wasko/branches/2.0/jmdweb/lib/exportselection.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/lib/exportselection.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,209 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright 2007, 2008 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-#
-# Authors:
-# Sascha L. Teichmann <teichmann at intevation.de>
-#
-
-import re
-import sys
-
-from pylons import g
-
-FORM_SECTION_RE = re.compile(r"^form_section_(\d+)$")
-
-RG_UNTERSTUETZUNG = (
- "angebote_bildenden_bereich",
- "angebote_berufsvorbereitung",
- "angebote_berufliche_qualifizierung",
- "angebote_lebensbewaeltigung")
-
-RG_ALL = (
- "kompetenzfestellung",
- "angebote_bildenden_bereich",
- "angebote_berufsvorbereitung",
- "angebote_berufliche_qualifizierung",
- "angebote_lebensbewaeltigung")
-
-
-SECTION_MAP = {
-'form_section_ee': "ee", # Einwilligungserklärung
-'form_section_01': "page-0", # 1. Zuständigkeiten, Eingangsdaten
-'form_section_02': "page-1", # 2. Externe Ansprechpartner
-'form_section_03': "page-2", # 3.1 Persönliche Angaben
-'form_section_04': "page-3", # 3.2 Angaben zu der Mutter
-'form_section_05': "page-4", # 3.3 Angaben zu dem Vater
-'form_section_06': "page-5", # 3.4 Geschwister
-'form_section_07': "page-6", # 3.5 Familieneinkommen
-'form_section_08': "page-7", # 3.6 Bezugspersonen/soziales Umfeld
-'form_section_09': "page-8", # 3.7 Freie Dokumentation
-'form_section_10': "page-9", # 4.1 Angaben zur Schullaufbahn
-'form_section_11': "page-10", # 4.2 Familiärer Hintergrund und Ressourcen
-'form_section_12': "page-11", # 4.3 Unterstützungsleistungen im Vorfeld
-'form_section_13': "page-12", # 4.4 Freie Dokumentation
-'form_section_14': "page-13", # 5.1.1 Verfahren der Kompetenzfeststellung
-'form_section_15': "page-14", # 5.1.2 Ergebnisse der Kompetenzfeststellung
-'form_section_16': "page-15", # 5.1.3 Entwicklung des jungen Menschen
-'form_section_17': "page-16", # 5.2.1 Reintegrations-Vorraussetzungen
-'form_section_18': "page-28", # 5.2.1.5 Erfassung von Fehlzeiten
-'form_section_19': "page-17", # 5.2.2 Probleme
-'form_section_20': "page-18", # 5.2.3 Zielsetzung des Case Management
-'form_section_21': "page-30", # Unterstützungsmaßnahme 1
-'form_section_22': "page-31", # Unterstützungsmaßnahme 2
-'form_section_23': "page-32", # Unterstützungsmaßnahme 3
-'form_section_24': "page-33", # Weitere Unterstützungsmaßnahmen
-'form_section_25': "page-20", # 5.3.2 Vereinbarungen
-'form_section_26': "page-21", # 5.3.3 Elternarbeit
-'form_section_27': "page-22", # 5.4 Freie Dokumentation
-'form_section_28': "page-23", # 6.1.1 Verlauf des Case Management
-'form_section_29': "page-24", # 6.1.2 Beendigung des Case Management
-'form_section_30': "page-25", # 6.2 Erreichte Ziele
-'form_section_31': "page-26", # 6.3 Nachbetreuung
-'form_section_32': "page-27", # 6.4 Freie Dokumentation zur Abschlussbewertung
-}
-
-def form_section_sort(a, b):
- am = FORM_SECTION_RE.match(a)
- bm = FORM_SECTION_RE.match(b)
- if not am and not bm:
- return cmp(a, b)
- if not am: return +1
- if not bm: return -1
- return cmp(int(am.group(1)), int(bm.group(1)))
-
-class CasePartsSelection:
-
- def __init__(self):
- # Remember to change the formular validator if you change this
- # dictionary
- #'appointments' : 1,
- self.selections = dict([
- ('form_section_%02d' % i, 1) for i in xrange(1, 33)])
- self.selections['documents'] = 0
- self.selections['logbook' ] = 0
-
- def numItems(self):
- return len(self.selections)
-
- def isChecked(self, item):
- return self.selections.get(item) == 1
-
- def setChecked(self, item, value):
- self.selections[item] = value
-
- def isAllSelected(self):
- for v in self.selections.itervalues():
- if v < 1: return False
- return True
-
- def allSelectedSections(self):
- s = [kv[0] for kv in self.selections.iteritems() if kv[1] > 0]
- # order form_section_XX to top, XX as int, rest to bottom by alpha
- s.sort(form_section_sort)
- return s
-
- def __str__(self):
- return ", ".join([str(i) for i in self.selections])
-
-class Selector:
-
- def __init__(self, anonymize=False, master_where="id = %(id)s", rg_where="master_id = %(id)s"):
- self.views = {}
- self.exportDocuments = False
- self.exportLogbook = False
- self.anonymize = anonymize
- self.master_where = master_where
- self.rg_where = rg_where
- self.master_projection = None
-
- def getSelectStatementByView(self, view):
- return self.views.get(view)
-
- def addRepeatGroup(self, name):
- relname = (self.anonymize and "rg_%s_tbl_anonym_view" or "rg_%s_tbl_view") % name
- self.views[name] = "SELECT * FROM %s WHERE %s" % (relname, self.rg_where)
-
- def addMasterTable(self, projection):
- #print >> sys.stderr, "id: ", id(self), " ", self.anonymize
- relname = self.anonymize and "master_tbl_anonym_view" or "master_tbl_view"
- self.views['master_tbl'] = "SELECT %s FROM %s WHERE %s" % (
- ", ".join(projection),
- relname,
- self.master_where)
- self.master_projection = projection
-
-class SelectorFactory:
-
- def __init__(self, case_parts, anonymize=False):
- self.case_parts = case_parts
- self.anonymize = anonymize
-
- def createSelector(self, master_where = "id = %(id)s", rg_where = "master_id = %(id)s"):
- selector = Selector(self.anonymize, master_where, rg_where)
- selected_sections = self.case_parts.allSelectedSections()
- # always export einverstaendiserklaerung and phase
- selected_sections.insert(0, 'form_section_ee')
-
- master_tbl_items = ['id']
-
- if not self.anonymize:
- master_tbl_items.append('uuid_id')
-
- for part in selected_sections:
- try:
- page = SECTION_MAP[part]
- except:
- if not self.anonymize:
- if part == "documents":
- selector.exportDocuments = True
- elif part == "logbook":
- selector.exportLogbook = True
- else:
- print >> sys.stderr, "missing %s" % part
- continue
-
-# if page.startswith("rg_"):
-# if page == 'rg_kompetenzfestellung':
-# selector.addRepeatGroup('kompetenzfestellung')
-# elif page == 'rg_unterstuetzungsangebote':
-# for rg in RG_UNTERSTUETZUNG:
-# selector.addRepeatGroup(rg)
-# else:
-# print >> sys.stderr, "ignoring repeat group %s" % page
-# continue
-
- nc = g.formedTree.findByName(page)
- if nc is None:
- print >> sys.stderr, "missing page '%s'" % page
- continue
-
- master_tbl_items.extend([n.getName() for n in nc.allWidgets()])
-
- selector.addMasterTable(master_tbl_items)
-
- return selector
-
-# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
Deleted: wasko/branches/2.0/jmdweb/lib/uuid.py
===================================================================
--- wasko/branches/2.0/jmdweb/lib/uuid.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/lib/uuid.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,55 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright 2007, 2008, 2009 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-#
-# Authors:
-# Sascha L. Teichmann <teichmann at intevation.de>
-#
-
-import os
-
-class UUID(object):
-
- def __init__(self, bytes):
-
- if len(bytes) != 16:
- raise ValueError('bytes is not a 16-char string')
-
- self.int = long(('%02x'*16) % tuple(map(ord, bytes)), 16)
-
- def __str__(self):
- hex = '%032x' % self.int
- return '%s-%s-%s-%s-%s' % (
- hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
-
-def uuid4():
- try:
- return UUID(bytes=os.urandom(16), version=4)
- except:
- import random
- bytes = [chr(random.randrange(256)) for i in range(16)]
- return UUID(bytes=bytes, version=4)
-
-# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 enc=utf-8 :
Deleted: wasko/branches/2.0/jmdweb/lib/xmlexport.py
===================================================================
--- wasko/branches/2.0/jmdweb/lib/xmlexport.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/lib/xmlexport.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,285 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright 2007, 2008 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-#
-# Authors:
-# Sascha L. Teichmann <teichmann at intevation.de>
-#
-
-from types import StringTypes
-
-import re
-import sys
-import xml.utils.iso8601 as iso8601
-from time import mktime
-
-VERSION = 3
-
-
-from pylons import g
-
-import mpulsweb.lib.helpers as h
-
-#from exportselection import RG_UNTERSTUETZUNG, \
-# SelectorFactory, CasePartsSelection, RG_ALL
-
-from exportselection import SelectorFactory, CasePartsSelection
-
-FETCH_ALL_IDS = \
-"""SELECT id FROM master_tbl_view"""
-
-LOAD_LOGBOOK = """
-SELECT uuid_id, datum, bearbeiter, art, kurz_notiz, notiz, dauer
-FROM ka_logbuch_tbl_view
-WHERE master_id = %(id)s
-ORDER BY datum
-"""
-
-LOAD_DOCUMENTS = """
-SELECT uuid_id, groesse, mime, name, encode(daten, 'base64') AS daten
-FROM ka_fall_dokumente_tbl_view
-WHERE master_id = %(id)s
-"""
-
-BLACK_LIST = set(['id', 'master_id', 'bearbeiter_id'])
-
-#USER_LOGIN = re.compile(r"(?:[^_]*)_(?:[^_]*)_(.+)")
-
-#def login(a):
-# b = USER_LOGIN.findall(a)
-# return b and b[0] or a
-
-def cdataWrap(value):
- return u"<![CDATA[%s]]>" % value.replace(u"]]>", u"]]><!CDATA[]]]]><![CDATA[>]]><[!CDATA[")
-
-def escape(value, tagname):
- if tagname == 'uuid_id':
- return "%s" % unicode(str(value), "utf-8")
- if type(value) in StringTypes:
- return cdataWrap(unicode(str(value), "utf-8"))
- if value is None:
- return ""
- return "%s" % value
-
-
-class LogbookEntry:
-
- def __init__(self, row):
- if row[0] is None: self.uuid_id = None
- else: self.uuid_id = unicode(str(row[0]), 'UTF-8')
-
- self.datum = row[1]
-
- if row[2] is None: self.login = None
- else: self.login = unicode(str(row[2]), 'UTF-8')
-
- self.art = row[3]
-
- if row[4] is None: self.kurz_notiz = None
- else: self.kurz_notiz = unicode(str(row[4]), 'UTF-8')
-
- if row[5] is None: self.notiz = None
- else: self.notiz = unicode(str(row[5]), 'UTF-8')
-
- self.dauer = row[6]
-
- def dump(self, out):
- out.write(u"<tagebuch-eintrag>")
- if not self.uuid_id is None:
- out.write(u"<uuid_id>%s</uuid_id>" % self.uuid_id)
- if not self.datum is None:
- out.write(u"<tagebuch-datum>%s</tagebuch-datum>" %
- iso8601.tostring(mktime(self.datum.timetuple()) + 1e-6*self.datum.microsecond))
- if not self.login is None:
- out.write(u"<tagebuch-bearbeiter>%s</tagebuch-bearbeiter>" % self.login)
- if not self.art is None:
- out.write(u"<tagebuch-art>%d</tagebuch-art>" % self.art)
- if not self.kurz_notiz is None:
- out.write(u"<tagebuch-sonstiges>%s</tagebuch-sonstiges>" % cdataWrap(self.kurz_notiz))
- if not self.notiz is None:
- out.write(u"<tagebuch-notiz>%s</tagebuch-notiz>" % cdataWrap(self.notiz))
- if not self.dauer is None:
- out.write(u"<tagebuch-dauer>%d</tagebuch-dauer>" %
- h.timedelta_in_minutes(self.dauer))
- out.write(u"</tagebuch-eintrag>")
-
-class Logbook:
-
- def __init__(self):
- self.entries = []
-
- def addEntry(self, row):
- self.entries.append(LogbookEntry(row))
-
- def dump(self, out):
- if self.entries:
- out.write(u'<tagebuch>');
- for entry in self.entries:
- entry.dump(out)
- out.write(u'</tagebuch>');
-
-class ExportCase:
-
- def __init__(self, master_id, selector):
- self.master_id = int(master_id)
- self.columns = None
- self.rgs = []
- self.selector = selector
- self.logbook = None
- self.blacklist = BLACK_LIST.copy()
- if selector.anonymize:
- self.blacklist.add('uuid_id')
-
- def dumpColums(self, columns):
- out = []
- for tagname, value in columns:
- if not value is None and tagname not in self.blacklist:
- out.append("<%s>%s</%s>" % (tagname, escape(value, tagname), tagname))
- return out
-
- def fetchData(self, cur):
- self.fetchMasterTable(cur)
- #self.fetchRepeatGroups(cur)
- self.fetchLogbook(cur)
-
- def fetchMasterTable(self, cur):
- selector = self.selector
- stmnt = selector.getSelectStatementByView('master_tbl')
- if not stmnt:
- print >> sys.stderr, "No SELECT statement for master_tbl found"
- return
- cur.execute(stmnt, { 'id': self.master_id })
- row = cur.fetchone()
- if not row: raise Exception("No dataset for id %d" % self.master_id)
- self.columns = zip([d[0] for d in cur.description], row)
-
-# def fetchRepeatGroups(self, cur):
-# selector = self.selector
-# id_dict = { 'id': self.master_id }
-# for view in RG_ALL:
-# stmnt = selector.getSelectStatementByView(view)
-# if stmnt is None: continue
-# cur.execute(stmnt, id_dict)
-# rs = []
-# while True:
-# row = cur.fetchone()
-# if not row: break
-# cs = row._index.items() # XXX: hackish!
-# cs.sort(lambda a, b: cmp(a[1], b[1]))
-# cs = [(a[0], row[a[1]]) for a in cs]
-# rs.append(cs)
-# if rs:
-# self.rgs.append((view, rs))
-
- def fetchLogbook(self, cur):
- if not self.selector.exportLogbook:
- return
- cur.execute(LOAD_LOGBOOK, {'id': self.master_id})
- logbook = Logbook()
- while True:
- row = cur.fetchone()
- if not row: break
- logbook.addEntry(row)
- self.logbook = logbook
-
-
- def dumpMasterTable(self, out):
- fields = self.dumpColums(self.columns)
- if fields:
- out.write("<master>%s</master>" % "".join(fields))
-
-# def dumpRepeatGroups(self, out):
-# for view, rgs in self.rgs:
-# for r in rgs:
-# fields = self.dumpColums(r)
-# if fields:
-# out.write("<%s>%s</%s>" % (view, "".join(fields), view))
-
- def dumpLogbook(self, out):
- if self.logbook:
- self.logbook.dump(out)
-
- def dumpDocuments(self, out, cur):
- if not self.selector.exportDocuments:
- return
- # Not using OO aproach because loading documents first
- # would fill up memory
- first = True
- cur.execute(LOAD_DOCUMENTS, {'id': self.master_id})
- while True:
- row = cur.fetchone()
- if not row: break
- if first:
- first = False
- out.write("<anlagen>")
- out.write("<anlage>")
- if not row[0] is None:
- out.write("<uuid_id>%s</uuid_id>" % row[0])
- if not row[1] is None:
- out.write("<anlage-groesse>%d</anlage-groesse>" % row[1])
- if not row[2] is None:
- out.write("<anlage-mime>%s</anlage-mime>" % row[2])
- if not row[4] is None:
- out.write(u"<anlage-name>%s</anlage-name>" % cdataWrap(unicode(str(row[3]), 'UTF-8')))
- if not row[3] is None:
- out.write("<anlage-daten>")
- out.write(row[4])
- out.write("</anlage-daten>")
- out.write("</anlage>")
-
- if not first: out.write("</anlagen>")
-
- def dumpData(self, out, cur):
- out.write("<case>")
- self.dumpMasterTable(out)
- #self.dumpRepeatGroups(out)
- self.dumpLogbook(out)
- self.dumpDocuments(out, cur)
- out.write("</case>")
-
-def exportAsXML(cur, out, ids=None, case_parts=None, anonymize=False):
- if ids is None:
- cur.execute(FETCH_ALL_IDS)
- ids = []
- while True:
- row = cur.fetchone()
- ids.append(int(row[0]))
-
- if case_parts is None:
- case_parts = CasePartsSelection()
-
- selectFactory = SelectorFactory(case_parts, anonymize)
-
- selector = selectFactory.createSelector()
-
- out.write('<?xml version="1.0" encoding="UTF-8"?>\n')
- out.write('<cases version="%d">' % VERSION)
- for mid in ids:
- case = ExportCase(mid, selector)
- case.fetchData(cur)
- case.dumpData(out, cur)
- out.write("</cases>")
-
-# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
Deleted: wasko/branches/2.0/jmdweb/lib/xmlhelper.py
===================================================================
--- wasko/branches/2.0/jmdweb/lib/xmlhelper.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/lib/xmlhelper.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,111 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# (c) 2008 by Intevation GmbH
-# This is Free software under the GPLv3.
-# See LICENSE comming with the source of 'mpuls offline'
-# for details.
-#
-# author: Sascha L. Teichmann <sascha.teichmann at intevation.de>
-#
-
-from xml.sax.handler import ContentHandler
-
-from datetime import datetime, date
-
-import re
-import time
-
-NO_NUMBER = re.compile("[^0-9\-]")
-INT_NUMBER = re.compile("(-?[0-9]+)")
-DATE = re.compile("([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2})")
-
-def iso_time_string(d):
- ''' datetime.strftime() dislikes years before 1900. '''
- 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.strptime(s.replace("-", ""), "%Y%m%dT%H:%M:%S") # Python 2.5
- return datetime(*(time.strptime(s.replace("-", ""), "%Y%m%dT%H:%M:%S")[0:6]))
-
-
-def decode_int(s):
- s = NO_NUMBER.sub("", s)
- m = INT_NUMBER.match(s)
- if not m: return None
- return int(m.group(1))
-
-def decode_date(s):
- s = NO_NUMBER.sub("", s)
- m = DATE.match(s)
- if not m: return None
- return date(int(m.group(1)), int(m.group(2)), int(m.group(3)))
-
-def decode_iso_datetime(s):
- if not s: return None
- try:
- return string_iso_time(s)
- except:
- return None
-
-def iso_datetime_string(d):
- return iso_time_string(d)
-
-class StackedLoader(ContentHandler):
-
- def __init__(self):
- ContentHandler.__init__(self)
- self.factories = {}
- self.current = None
- self.depth = 0
- self.entry_levels = None
- self.stack = None
-
- def add_factories(self, tag, factories, default):
- self.factories[tag] = (factories, default)
-
- def activate_factories(self, tag):
- self.current = self.factories.get(tag)
-
- def startElement(self, name, attrs):
- new_factories = self.factories.get(name)
-
- if new_factories:
- self.entry_levels.append(self.depth)
- self.current = new_factories
-
- if self.current:
- start, end = self.current[0].get(name, self.current[1])
- start(name, attrs)
- else:
- end = None
-
- self.stack.append((end, attrs, []))
-
- self.depth += 1
-
- def endElement(self, name):
-
- t = self.stack.pop()
-
- if t[0]: t[0](name, t[1], u"".join(t[2]))
-
- self.depth -= 1
- if self.entry_levels and self.entry_levels[-1] == self.depth:
- self.entry_levels.pop()
-
- def activate_factories(self, tag):
- try:
- self.current = self.factories[tag]
- except KeyError:
- pass
-
- def characters(self, chars):
- self.stack[-1][2].append(chars)
-
- def startDocument(self):
- self.depth = 0
- self.entry_levels = []
- self.stack = []
-
-# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
Deleted: wasko/branches/2.0/jmdweb/lib/xmlimport.py
===================================================================
--- wasko/branches/2.0/jmdweb/lib/xmlimport.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/lib/xmlimport.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,364 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright 2007, 2008 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-#
-# Authors:
-# Sascha L. Teichmann <teichmann at intevation.de>
-#
-import sys
-from datetime import date
-
-from xml.sax.saxutils import DefaultHandler
-from xml.sax import parse
-
-import re
-
-def _int_converter(s):
- return int(s)
-
-def _bool_converter(s):
- return int(s)
-
-def _date_converter(s):
- return date(*[int(x) for x in s.split("-")])
-
-def _choice_converter(s):
- return int(s)
-
-def _radio_converter(s):
- return int(s)
-
-def _text_converter(s):
- return s
-
-UUID_RE = re.compile(r"^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")
-
-RELATIONS = {
-}
-
-CREATE_FUNCTIONS = {
- 'kompetenzfestellung': 'create_rg_kompetenz_ds',
- 'angebote_bildenden_bereich': 'create_rg_bilden_ds',
- 'angebote_berufsvorbereitung': 'create_rg_beruf_ds',
- 'angebote_berufliche_qualifizierung': 'create_rg_quali_ds',
- 'angebote_lebensbewaeltigung': 'create_rg_leben_ds'
-}
-
-EXPECT_CASES = 0
-EXPECT_CASE = 1
-EXPECT_RELATION = 2
-EXPECT_FIELD = 3
-EXPECT_CHARS = 4
-
-SQL_UPATE = """UPDATE %s_tbl_view SET %s WHERE uuid_id = %%(uuid_id)s"""
-
-SQL_GET_MASTER_ID = \
-"""SELECT get_masterid_from_uuid(%(relation_name)s, %(uuid)s)"""
-
-SQL_CREATE_MASTER_DS = \
-"""SELECT create_master_ds(%(uuid)s)"""
-
-SQL_SELECT_UUID_FROM_RELATION = \
-"""SELECT uuid_id FROM %s_tbl_view WHERE id = %%(id)s"""
-
-SQL_CREATE_REPEAT_GROUP = \
-"""SELECT %s(%%(master_id)s, %%(uuid)s)"""
-
-def get_id_for_uuid(cur, relation_name, uuid):
- cur.execute(SQL_GET_MASTER_ID, {
- 'relation_name': relation_name, 'uuid': uuid })
- row = cur.next()
- if not row: return None
- return row[0]
-
-def create_master(cur, uuid=None):
- cur.execute(SQL_CREATE_MASTER_DS, { 'uuid': uuid })
- row = cur.next()
- if not row: return None
- return row[0]
-
-def create_repeat_group(cur, relation_name, master_id, uuid=None):
- relation_name = CREATE_FUNCTIONS.get(relation_name)
- if relation_name is None: return None
- sql = SQL_CREATE_REPEAT_GROUP % relation_name
- cur.execute(sql, { 'master_id': master_id, 'uuid': uuid })
- row = cur.next()
- if not row: return None
- return row[0]
-
-def get_uuid(cur, relation_name, ds_id):
- if relation_name != 'master': relation_name = "rg_%s" % relation_name
- sql = SQL_SELECT_UUID_FROM_RELATION % relation_name
- cur.execute(sql, { 'id': ds_id })
- row = cur.next()
- if not row: return None
- return row[0]
-
-class Case:
- def __init__(self):
- self.relations = []
-
- def append(self, relation):
- self.relations.append(relation)
-
- def find_first_relation(self, relation_name):
- for relation in self.relations:
- if relation.name == relation_name:
- return relation
- return None
-
-class Relation:
-
- def __init__(self, name, items = None):
- self.name = name
- if items is None: self.items = []
- else: self.items = items
- self.uuid = None
- self.fields = []
-
- def append(self, field):
- self.fields.append(field)
-
- def find_field(self, field_name):
- for k, v in self.fields:
- if k == field_name:
- return v
- return None
-
- def set_field(self, field_name, value):
- for i in xrange(len(self.fields)):
- field = self.fields[i]
- if field[0] == field_name:
- field[1] = value
- return
- self.fields.append((field_name, value))
-
- def update(self, cur):
- if self.uuid is None:
- raise StandardError("UUID is not defined")
-
- if not self.fields: return
-
- sets = []
- values = {}
- for k, v in self.fields:
- sets.append("%s = %%(%s)s" % (k, k))
- values[k] = v
-
- values['uuid_id'] = self.uuid
-
- if self.name != 'master': rel = "rg_%s" % self.name
- else: rel = "master"
-
- sql = SQL_UPATE % (rel, ", ".join(sets))
- cur.execute(sql, values)
-
-
-class XMLHandler(DefaultHandler):
-
- def __init__(self, case_store):
- DefaultHandler.__init__(self)
- self.mode = EXPECT_CASES
- self.ignore = 0
- self.relation = None
- self.chars = None
- self.case_store = case_store
- self.case = None
-
- def startElement(self, name, attrs):
- if self.mode == EXPECT_CASES:
- if name != "cases":
- print >> sys.stderr, "ignore %s" % name
- self.ignore += 1
- else:
- self.mode = EXPECT_CASE
-
- elif self.mode == EXPECT_CASE:
- if name != "case":
- print >> sys.stderr, "ignore %s" % name
- self.ignore += 1
- else:
- self.case = Case()
- self.mode = EXPECT_RELATION
-
- elif self.mode == EXPECT_RELATION:
- rel = RELATIONS.get(name)
- if rel is None:
- print >> sys.stderr, "relation '%s' not found" % name
- self.ignore += 1
- else:
- #print >> sys.stderr, "relation '%s' found" % name
- self.relation = Relation(name, rel)
- self.mode = EXPECT_FIELD
-
- elif self.mode == EXPECT_FIELD:
- self.mode = EXPECT_CHARS
- self.chars = ""
-
- elif self.mode == EXPECT_CHARS:
- self.ignore += 1
-
- def endElement(self, name):
- if self.ignore > 0:
- self.ignore -= 1
- return
-
- if self.mode == EXPECT_CHARS:
- if name != "uuid_id":
- converter = self.relation.items.get(name)
- if converter is None:
- print >> sys.stderr, "missing converter for %s" % name
- else:
- if not self.chars:
- self.relation.append([name, None])
- else:
- #print >> sys.stderr, "convert %s" % name
- self.relation.append([name, converter(self.chars)])
- else:
- self.relation.uuid = self.chars.strip().lower()
- if not UUID_RE.match(self.relation.uuid):
- raise StandardError("UUID is invalid")
- #print >> sys.stderr, "uuid: %s" % self.relation.uuid
-
- self.mode = EXPECT_FIELD
- self.chars = None
-
- if self.mode == EXPECT_FIELD:
- if self.relation and self.relation.name == name:
- self.case.append(self.relation)
- self.relation = None
- self.mode = EXPECT_RELATION
- else:
- pass
-
- elif self.mode == EXPECT_RELATION:
- if name == "case":
- self.case_store.store(self.case)
- self.case = None
- self.mode = EXPECT_CASE
-
- elif self.mode == EXPECT_CASE:
- if name == "cases":
- self.mode = EXPECT_CASES
-
- def characters(self, content):
- if self.mode == EXPECT_CHARS:
- self.chars += content
-
-class CaseStore:
-
- def __init__(self, con, cur):
- self.con = con
- self.cur = cur
- #self.ids = set()
-
- def store(self, case):
-
- success = False
- master_new = False
- kompetenz_new = False
- master_id = None
- cur = self.cur
-
- try:
- # find master
- master = case.find_first_relation('master')
-
- if master is None:
- # need to create one
- master_id = create_master(cur)
- master_new = True
- else:
- # we have a master
- if master.uuid is None:
- # need to create new one
- master_id = create_master(cur)
- master_new = True
- master.uuid = get_uuid(cur, 'master', master_id)
- else:
- # we have a uuid
- master_id = get_id_for_uuid(cur, 'master', master.uuid)
- if master_id is None:
- # does not exist -> create new
- master_id = create_master(cur, master.uuid)
- master_new = True
- # update the master
- master.update(cur)
-
- # now handle the repeat groups
- for relation in case.relations:
- if relation.name == 'master':
- # masters are already handled
- continue
-
- if relation.uuid is None:
- # need to create new
- relation_id = create_repeat_group(cur, relation.name, master_id)
- relation.uuid = get_uuid(cur, relation.name, relation_id)
- if relation.name == 'kompetenzfeststellung':
- kompetenz_new = True
- else:
- # we have a UUID. find out if we have this entry already in our database
- m_id = get_id_for_uuid(cur, relation.name, relation.uuid)
- if not m_id is None and m_id != master_id:
- # exists but not the right master -> ignore
- continue
-
- if m_id is None:
- # create new
- relation_id = create_repeat_group(cur, relation.name, master_id, relation.uuid)
- if relation.name == 'kompetenzfeststellung':
- kompetenz_new = True
-
- # update the relation
- relation.update(cur)
-
- if master_new and kompetenz_new:
- # create at least one kompetenzfeststellung if there is a new master
- create_repeat_group(cur, 'kompetenzfeststellung', master_id)
-
- success = True
- self.con.commit()
- #self.ids.add(master_id)
-
- finally:
- if not success:
- self.con.rollback()
-
-def importFromXML(f, con):
- cur = None
- try:
- cur = con.cursor()
- case_store = CaseStore(con, cur)
- handler = XMLHandler(case_store)
- parse(f, handler)
- finally:
- if cur:
- try: cur.close()
- except: pass
-
- #return case_store.ids
-
-# vim:set ts=4 sw=4 si et sta sts=4:
Deleted: wasko/branches/2.0/jmdweb/model/casexml.py
===================================================================
--- wasko/branches/2.0/jmdweb/model/casexml.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/model/casexml.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,573 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright 2007, 2008, 2009 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-#
-# Authors:
-# Sascha L. Teichmann <teichmann at intevation.de>
-#
-
-from jmdweb.lib.uuid import uuid4
-
-from mpulsweb.lib.db import db
-
-from jmdweb.lib.xmlhelper import \
- decode_int, \
- decode_date, \
- decode_iso_datetime, \
- StackedLoader
-
-import jmdweb.model.data as data
-
-from jmdweb.model.semantic import checkAndConvert, SematicError
-
-from xml.sax import make_parser
-from xml.sax.saxutils import escape
-
-import sys
-import re
-
-from datetime import timedelta
-
-UUID_RE = re.compile(r"^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")
-
-SQL_IS_ANONYMIZED_UUID = \
-"""SELECT is_uuid_anonymized(%(uuid)s)"""
-
-SQL_GET_MASTER_ID = \
-"""SELECT get_masterid_from_uuid(%(relation_name)s, %(uuid)s)"""
-
-SQL_SELECT_ALL_FROM_MASTER = \
-"""SELECT * FROM master_tbl_view WHERE id = %(ds_id)s"""
-
-SQL_CREATE_MASTER_DS = \
-"""SELECT create_master_ds(%(uuid)s)"""
-
-SQL_UPDATE_MASTER = \
-"""UPDATE master_tbl_view SET %s WHERE id = %d"""
-
-SQL_SELECT_IDS_FROM_LOGBOOK = \
-"""SELECT id, master_id FROM ka_logbuch_tbl_view WHERE uuid_id = %(uuid_id)s"""
-
-SQL_CREATE_LOGBOOK_ENTRY = \
-"""SELECT create_logbuch_ds(%(mid)s, %(uuid_id)s)"""
-
-SQL_UPDATE_LOGBOOK = \
-"""UPDATE ka_logbuch_tbl_view SET %s WHERE id = %d"""
-
-SQL_GET_STATUS = \
-"""SELECT s.status AS status FROM
- master_tbl_view m INNER JOIN ka_status_tbl_view s
- ON s.master_id = m.id
- WHERE m.id = %(mid)s
-"""
-
-CASE_NOT_AVAILABLE = u'''Daten zum Fall '%d' können nicht geladen werden.
-Bitte stellen Sie sicher, dass Sie die/der Bearbeiterin/Bearbeiter sind,
-oder dass der Fall Ihnen in Vertretung überantwortet wurde.'''
-
-VERSION = 3
-
-DECODERS = {
- data.RadioNode: decode_int,
- data.TextAreaLeaf: lambda s: s,
- data.TextLeaf: lambda s: s,
- data.ChoiceNode: decode_int,
- data.IntLeaf: decode_int,
- data.DateLeaf: decode_date
-}
-
-def convert_from_db(s):
- if type(s) == str: return unicode(s, 'utf-8')
- return s
-
-def is_uuid(s):
- return bool(UUID_RE.match(s))
-
-def is_uuid_anonymized(cur, uuid):
- cur.execute(SQL_IS_ANONYMIZED_UUID, { 'uuid': uuid })
- row = cur.fetchone()
- if not row: return False
- return row[0]
-
-def get_status(cur, mid):
- cur.execute(SQL_GET_STATUS, { 'mid': mid })
- row = cur.fetchone()
- if not row: return None
- return row[0]
-
-def get_logbuch_ids_from_uuid(cur, uuid_id):
- cur.execute(SQL_SELECT_IDS_FROM_LOGBOOK, { 'uuid_id': uuid_id })
- return cur.fetchone()
-
-def create_logbook_entry(cur, mid, uuid_id):
- cur.execute(SQL_CREATE_LOGBOOK_ENTRY, {
- 'mid' : mid,
- 'uuid_id': uuid_id })
- row = cur.fetchone()
- if row: return row[0]
- return None
-
-class XMLImportException(Exception):
-
- def __init__(self, desc, errors = None):
- self.desc = desc
- self.errors = errors
-
- def __str__(self):
- return repr(self.desc)
-
-class LogbookEntry(object):
-
- def __init__(self, uuid = None):
- self.uuid = uuid
- self.datum = None
- self.art = None
- self.bearbeiter = None
- self.kurz_notiz = None
- self.notiz = None
- self.dauer = None
-
- def getUUID(self):
- #if not self.uuid: self.uuid = str(uuid4())
- return self.uuid
-
- def setUUID(self, uuid):
- self.uuid = uuid
-
- def setDate(self, datum):
- self.datum = datum
-
- def getDate(self):
- return dd_mm_YYYY(self.datum)
-
- def getTime(self):
- return HH_MM(self.datum)
-
- def setEditor(self, editor):
- self.bearbeiter = editor
-
- def getEditor(self):
- if self.bearbeiter is None: return u""
- return self.bearbeiter
-
- def getType(self):
- return self.art
-
- def setType(self, art):
- self.art = art
-
- def getDuration(self):
- if self.dauer is None: return u""
- return "%d" % self.dauer
-
- def setDuration(self, duration):
- self.dauer = duration
-
- def getShortNotice(self):
- if self.kurz_notiz is None: return u""
- return self.kurz_notiz
-
- def setShortNotice(self, short_notice):
- self.kurz_notiz = short_notice
-
- def getNotice(self):
- if self.notiz is None: return u""
- return self.notiz
-
- def setNotice(self, notice):
- self.notiz = notice
-
- def to_xml(self, out):
- out.append(u'<tagebuch-eintrag>')
-
- if not self.uuid is None:
- out.append(u'<uuid_id>%s</uuid_id>' % self.uuid)
-
- if not self.datum is None:
- out.append(u'<tagebuch-datum>%s</tagebuch-datum>' % \
- iso_datetime_string(self.datum))
-
- if not self.bearbeiter is None:
- out.append(u'<tagebuch-bearbeiter>%s</tagebuch-bearbeiter>' % \
- escape(self.bearbeiter))
-
- if not self.art is None:
- out.append(u'<tagebuch-art>%d</tagebuch-art>' % \
- self.art)
-
- if not self.kurz_notiz is None:
- out.append(u'<tagebuch-sonstiges>%s</tagebuch-sonstiges>' % \
- escape(self.kurz_notiz))
-
- if not self.notiz is None:
- out.append(u'<tagebuch-notiz>%s</tagebuch-notiz>' % \
- escape(self.notiz))
-
- if not self.dauer is None:
- out.append(u'<tagebuch-dauer>%d</tagebuch-dauer>' % self.dauer)
-
- out.append(u'</tagebuch-eintrag>')
-
- def to_database(self, cur, ds_id):
-
- lid = None
- if not self.uuid is None: # has uuid
- old = get_logbuch_ids_from_uuid(cur, self.uuid)
- if old:
- if old[1] != ds_id:
- raise XMLImportException(u'UUID gehört zum falschen Datensatz.')
- lid = old[0]
-
- if lid is None:
- lid = create_logbook_entry(cur, ds_id, self.uuid)
-
- changes, fields = {}, []
-
- for attr in (
- 'datum', 'bearbeiter', 'art', 'kurz_notiz', 'notiz', 'dauer'):
- v = getattr(self, attr)
- if not v is None:
- changes[attr] = v
- fields.append('%s = %%(%s)s' % (attr, attr))
-
- if changes:
- update = SQL_UPDATE_LOGBOOK % (','.join(fields), lid)
- cur.execute(update, changes)
-
-class Logbook(object):
-
- def __init__(self):
- self.entries = []
-
- def to_xml(self):
- if not self.entries: return u""
- out = [u"<tagebuch>"]
- for entry in self.entries:
- entry.to_xml(out)
- out.append(u"</tagebuch>")
- return u"".join(out)
-
- def to_database(self, cur, ds_id):
- for entry in self.entries:
- entry.to_database(cur, ds_id)
-
- def add_entry(self, entry):
- self.entries.append(entry)
-
- def reset(self):
- self.entries = []
-
-class LogbookLoader(object):
-
- def __init__(self):
- self.logbook = Logbook()
- self.entry = None
-
- def to_database(self, cur, ds_id):
- self.logbook.to_database(cur, ds_id)
- self.logbook.reset()
-
- def register_loader(self, loader):
-
- factories = {
- u"tagebuch": (self.default_start, self.default_end),
- u"tagebuch-eintrag": (self.eintrag_start, self.eintrag_end),
- u"uuid_id": (self.default_start, self.uuid_end),
- u'tagebuch-datum': (self.default_start, self.datum_end),
- u'tagebuch-art': (self.default_start, self.art_end),
- u'tagebuch-sonstiges': (self.default_start, self.kurz_end),
- u'tagebuch-bearbeiter': (self.default_start, self.bearbeiter_end),
- u'tagebuch-notiz': (self.default_start, self.notiz_end),
- u'tagebuch-dauer': (self.default_start, self.dauer_end),
- }
-
- loader.add_factories(
- u"tagebuch",
- factories,
- (self.default_start, self.default_end))
-
- def art_end(self, name, attrs, value):
- if self.entry:
- value = decode_int(value)
- if not value is None: self.entry.setType(value)
-
- def dauer_end(self, name, attrs, value):
- if self.entry:
- value = decode_int(value)
- if not value is None:
- value = timedelta(minutes=value)
- self.entry.dauer = value
-
- def bearbeiter_end(self, name, attrs, value):
- if self.entry: self.entry.bearbeiter = value
-
- def notiz_end(self, name, attrs, value):
- if self.entry: self.entry.notiz = value
-
- def kurz_end(self, name, attrs, value):
- if self.entry: self.entry.kurz_notiz = value
-
- def datum_end(self, name, attrs, value):
- if self.entry:
- self.entry.datum = decode_iso_datetime(value.strip())
-
- def eintrag_start(self, name, attrs):
- self.entry = LogbookEntry()
-
- def eintrag_end(self, name, attrs, value):
- if not self.entry.uuid:
- self.entry.uuid = str(uuid4())
- self.logbook.entries.append(self.entry)
- self.entry = None
-
- def uuid_end(self, name, attrs, value):
- if self.entry:
- value = value.strip().lower()
- if not is_uuid(value):
- raise XMLImportException("'%s' ist keine UUID." % repr(value))
- self.entry.uuid = value
-
- def default_start(self, name, attrs):
- pass
-
- def default_end(self, name, attrs, value):
- pass
-
-
-class MasterHandler(object):
-
- def __init__(self, formed, logbook_loader, cur, converter = None):
- self.formed = formed
- self.version = 1
- self.uuid = None
- self.data = []
- self.logbook_loader = logbook_loader
- self.cur = cur
- self.converter = converter
- self.errors = []
-
- def register_loader(self, loader):
- loader.add_factories(
- 'master',
- {},
- (self.element_start, self.element_end))
-
- def element_start(self, name, attrs):
-
- if name == u"cases":
- self.version = 1
- try:
- self.version = int(attrs[u'version'])
- except (KeyError, ValueError):
- pass
-
- if self.version > VERSION:
- raise XMLImportException(
- u"Dateien der Version %d können nicht importiert werden." % \
- self.version)
-
- elif name == u"case":
- self.uuid = None
- self.data = []
- if self.converter:
- self.converter.reset()
-
- def element_end(self, name, attrs, value):
-
- if name == u"case":
- if self.converter: self.converter.finish(self)
- self.finish()
- return
-
- if self.converter and self.converter.eat(name, attrs, value):
- return
-
- try:
- widget = self.formed.widgets[name]
- except KeyError:
- if name == u'uuid_id':
- value = value.strip().lower()
- if not is_uuid(value):
- raise XMLImportException(u"'%s' ist keine UUID" % repr(value))
- self.uuid = value
- return
-
- if value == u'':
- self.data.append((name, None))
- else:
- try:
- value = checkAndConvert(widget, value)
- self.data.append((name, value))
- except SematicError, se:
- self.errors.append(se.value)
-
- def finish(self):
- create_case, data = True, None
-
- if self.uuid:
- #print >> sys.stderr, "found uuid '%s'" % repr(master_handler.uuid)
-
- if is_uuid_anonymized(self.cur, self.uuid):
- raise XMLImportException(
- u"Die Fallakte wurde auf dem zentralen Server bereits anonymisiert. " \
- u"Ein Import ist daher nicht mehr möglich.")
-
- ds_id = get_id_for_uuid(self.cur, 'master', self.uuid)
- if not ds_id is None:
- # check status first
- status = get_status(self.cur, ds_id)
- if status == 4:
- raise XMLImportException(
- u"Die Akte ist auf dem zentralen Server zur Zeit " \
- u"schwebend anonymisiert und daher nicht bearbeitbar.")
- if status == 3:
- raise XMLImportException(
- u"Die Akte ist auf dem zentralen Server zur Zeit " \
- u"schwebend gelöscht und daher nicht bearbeitbar.")
- #print >> sys.stderr, "case %d already exists" % ds_id
- self.cur.execute(SQL_SELECT_ALL_FROM_MASTER % { 'ds_id': ds_id })
- row = self.cur.fetchone()
- if not row:
- raise XMLImportException(CASE_NOT_AVAILABLE % ds_id)
- data = dict(zip([n[0] for n in self.cur.description], map(convert_from_db, row)))
- create_case = False
- #else:
- # print >> sys.stderr, "case with uuid '%s' does not exists" % repr(
- # master_handler.uuid)
- #else:
- # print >> sys.stderr, "case does not have an uuid"
-
- if data is None:
- # print >> sys.stderr, "preset case with defaults from formed"
- data = self.formed.name2default
-
- changed = {}
-
- def get_data(var):
- try:
- return changed[var]
- except KeyError:
- return data.get(var)
-
- # apply the rules
-
- errors = self.errors
- self.errors = []
-
- for var, value in self.data:
- old_value = get_data(var)
- if old_value == value: continue
-
- rules = self.formed.getRulesForVariable(var)
- okay = True
- if rules:
- for rule in rules:
- mark = rule.getMark()
- if mark and mark.find("warning:") >= 0: continue
- #print rule.getAttribute('expr')
- expr = rule.getExpr()
-
- isNull, params = False, {}
- n_okay = True
- for dep in expr.getDependencies():
- dep_v = get_data(dep)
- if dep != var and dep_v is None: isNull = True; break
- params[dep] = dep_v
- if not isNull:
- params[var] = value
- try: n_okay = expr.evaluate(params)
- except: n_okay = False
- if not n_okay:
- errors.append(rule.getValue())
- okay = False
- if okay:
- changed[var] = value
-
- if errors:
- raise XMLImportException(
- u"Es wurden Inkonsistenzen festgestellt.", errors)
-
- if create_case:
- ds_id = create_master(self.cur, self.uuid)
-
- store_changes(self.cur, changed, ds_id)
-
- # store the logbook too
- self.logbook_loader.to_database(self.cur, ds_id)
-
-def get_id_for_uuid(cur, relation_name, uuid):
- cur.execute(SQL_GET_MASTER_ID, {
- 'relation_name': relation_name, 'uuid': uuid })
- row = cur.next()
- if not row: return None
- return row[0]
-
-def create_master(cur, uuid=None):
- cur.execute(SQL_CREATE_MASTER_DS, { 'uuid': uuid })
- row = cur.next()
- if not row: return None
- return row[0]
-
-def store_changes(cur, changes, ds_id):
- if not changes: return
- fields = ['%s = %%(%s)s' % (v, v) for v in changes.iterkeys()]
- update = SQL_UPDATE_MASTER % (",".join(fields), ds_id)
- cur.execute(update, changes)
-
-def import_xml(f, formed, converter_factory):
-
- converter = converter_factory and converter_factory() or None
-
- loader = StackedLoader()
-
- logbook_loader = LogbookLoader()
-
- con, cur = None, None
- try:
- con = db.getConnection()
- cur = con.cursor()
- try:
- master_handler = MasterHandler(formed, logbook_loader, cur, converter)
-
- master_handler.register_loader(loader)
-
- loader.activate_factories('master') # for backwards compat
-
- logbook_loader.register_loader(loader)
-
- parser = make_parser()
- parser.setContentHandler(loader)
- parser.parse(f)
-
- con.commit()
- except:
- try: con.rollback()
- except: pass
- raise
-
- finally:
- db.recycleConnection(con, cur)
-
-# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 enc=utf-8 :
Deleted: wasko/branches/2.0/jmdweb/model/data.py
===================================================================
--- wasko/branches/2.0/jmdweb/model/data.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/model/data.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,433 +0,0 @@
-# -*- coding: latin1 -*-
-#
-# Copyright 2007, 2008 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-#
-# Authors:
-# Sascha L. Teichmann <teichmann at intevation.de>
-#
-
-from nodecomponents import \
- NodeComponent, \
- Node, \
- Leaf, \
- VISIT_IGNORE_CHILDREN, \
- VISIT_CONTINUE
-
-from exprtree import Expr
-
-import sys
-import os
-
-class WidgetCollector(object):
-
- def __init__(self):
- self.widgets = []
-
- def visitor(self, nc):
- if isinstance(nc, Node):
- if isinstance(nc, (RadioNode, ChoiceNode)):
- self.widgets.append(nc)
- return VISIT_IGNORE_CHILDREN
- if isinstance(nc, GroupNode) and nc.isRepeat() and nc != self:
- return VISIT_IGNORE_CHILDREN
- elif isinstance(nc, Leaf) and not isinstance(nc,
- (RuleLeaf, ExternalChoiceListLeaf, InfoLeaf)):
- self.widgets.append(nc)
-
- return VISIT_CONTINUE
-
-
-class ConditionalWidgetCollector(object):
-
- def __init__(self, evaluator = lambda expr: True):
- self.widgets = []
- self.evaluator = evaluator
-
- def visitor(self, nc):
- if isinstance(nc, Node):
- if isinstance(nc, ConditionalNode):
- expr = nc.getExpr()
- if expr and not self.evaluator(expr):
- return VISIT_IGNORE_CHILDREN
- elif isinstance(nc, (RadioNode, ChoiceNode)):
- self.widgets.append(nc)
- return VISIT_IGNORE_CHILDREN
- elif isinstance(nc, GroupNode) and nc.isRepeat() and nc != self:
- return VISIT_IGNORE_CHILDREN
- elif isinstance(nc, Leaf) and not isinstance(nc,
- (RuleLeaf, ExternalChoiceListLeaf, InfoLeaf)):
- self.widgets.append(nc)
-
- return VISIT_CONTINUE
-
-
-class FilteredNodeComponentProxy:
- def __init__(self, params):
- self.params = params
-
- def set(self, nc):
- self.nc = nc
-
- def getName(self):
- if not self.nc: return ""
- return self.nc.getName()
-
- def allWidgets(self):
- if self.nc:
- print >> sys.stderr, self.nc
- return [w for w in self.nc.allWidgets() if w.getName() in self.params]
- return []
-
-class PageNode(Node):
- def __init__(self):
- Node.__init__(self)
- self.attributes["invisible"] = ""
-
- def setInvisible(self, flag):
- self.setAttribute("invisible", flag and "true" or "")
-
- def isInvisible(self):
- return self.getAttribute("invisible") and True or False
-
- def allWidgets(self):
- collector = WidgetCollector()
- self.visit(collector.visitor)
- return collector.widgets
-
-class GroupNode(Node):
- def __init__(self):
- Node.__init__(self)
- self.attributes["repeat"] = ""
- self.attributes["invisible"] = ""
-
- def isRepeat(self):
- return self.getAttribute("repeat") and True or False
-
- def setRepeat(self, repeat):
- repeat = repeat and "true" or ""
- self.setAttribute("repeat", repeat)
-
- def isInvisible(self):
- return self.getAttribute("invisible") and True or False
-
- def setInvisible(self, invisible):
- invisible = invisible and "true" or ""
- self.setAttribute("invisible", invisible)
-
- def allWidgets(self):
- collector = WidgetCollector()
- self.visit(collector.visitor)
- return collector.widgets
-
-class ConditionalNode(Node):
-
- def __init__(self):
- Node.__init__(self)
- self.attributes["expr"] = ""
- self.attributes["invisible"] = ""
- self.expr = None
-
- def setAttribute(self, attrib, value, broadcast=True):
- if attrib == "expr":
- newExpr = Expr(value)
- newExpr.compile()
- self.expr = newExpr
- Node.setAttribute(self, attrib, value, broadcast)
-
- def setExpr(self, expr):
- self.setAttribute('expr', expr)
-
- def getExpr(self):
- return self.expr
-
- def isInvisible(self):
- return self.getAttribute("invisible") and True or False
-
- def setInvisible(self):
- invisible = invisible and "true" or ""
- self.setAttribute("invisible", invisible)
-
-class MatrixNode(GroupNode):
- def __init__(self):
- GroupNode.__init__(self)
-
-class RadioNode(Node):
- def __init__(self):
- Node.__init__(self)
- self.attributes["selected"] = ""
-
- def firstFindDefault(self):
- value = None
- if self.children:
- for child in self.children:
- if isinstance(child, ExternalChoiceListLeaf):
- found, v = child.find_default()
- if found:
- value = v
- break
- elif isinstance(child, BoolLeaf):
- if child.getChecked():
- v = child.getValue()
- if v: value = int(v)
- break
-
- self.found_default = value
- return Node.firstFindDefault(self)
-
- def getSelected(self):
- return self.getAttribute("selected")
-
- def setSelected(self, selected):
- self.setSelected("selected", selected)
-
-class BoolLeaf(Leaf):
- def __init__(self):
- Leaf.__init__(self)
- self.attributes["checked"] = ""
-
- def getChecked(self):
- return self.getAttribute("checked")
-
- def setChecked(self, checked):
- self.setSelected("checked", checked)
-
-class ExternalChoiceListLeaf(Leaf):
- def __init__(self):
- Leaf.__init__(self)
- self.choice = None
- self.path = None
-
- def setLoadContext(self, path):
- self.path = os.path.dirname(path)
-
- def find_default(self):
- found, value = False, None
- children = self.getChildren()
- if children:
- for child in children:
- if isinstance(child, BoolLeaf):
- if child.getChecked():
- v = child.getValue()
- if v: value = int(v)
- break
- return found, value
-
- def getChildren(self):
- if not self.choice:
- fname = self.getValue()
- if fname:
- if not os.path.isabs(fname) and self.path:
- fname = os.path.join(self.path, fname)
- try: # TODO: This loading code should be else where!
- import jmdweb.model.io.document
- document = jmdweb.model.io.document.openDocument(fname)
- self.choice = document.findByClassAndName(ChoiceNode)
- except Exception, inst:
- print >> sys.stderr, repr(inst)
- if self.choice:
- return self.choice.children
- return None
-
-class InfoLeaf(Leaf):
- def __init__(self):
- Leaf.__init__(self)
- self.attributes["invisible"] = ""
-
- def isInvisible(self):
- return self.getAttribute("invisible") and True or False
-
- def setInvisible(self, invisible):
- invisible = invisible and "true" or ""
- self.setAttribute("invisible", invisible)
-
-class TextAreaLeaf(Leaf):
- def __init__(self):
- Leaf.__init__(self)
- self.attributes["cols"] = ""
- self.attributes["rows"] = ""
-
- def firstFindDefault(self):
- value = self.getValue()
- if not value: value = None
- self.found_default = value
- return Leaf.firstFindDefault(self)
-
- def getCols(self):
- return self.getAttribute("cols")
-
- def setCols(self, cols):
- return self.setAttribute("cols", cols)
-
- def getRows(self):
- return self.getAttribute("rows")
-
- def setRows(self, rows):
- return self.setAttribute("rows", rows)
-
-class TextLeaf(Leaf):
- def __init__(self):
- Leaf.__init__(self)
- self.attributes["size"] = "40"
- self.attributes["maxlength"] = "60"
-
- def firstFindDefault(self):
- value = self.getValue()
- if not value: value = None
- self.found_default = value
- return Leaf.firstFindDefault(self)
-
- def getSize(self):
- return self.getAttribute("size")
-
- def setSize(self, size):
- self.setAttribute("size", size)
-
- def getMaxLength(self):
- return self.getAttribute("maxlength")
-
- def setMaxLength(self, length):
- self.setAttribute("maxlength", length)
-
-class ChoiceNode(Node):
- def __init__(self):
- Node.__init__(self)
- self.attributes["size"] = "1"
- self.attributes["multiple"] = ""
-
- def firstFindDefault(self):
- value = None
- if self.children:
- for child in self.children:
- if isinstance(child, ExternalChoiceListLeaf):
- found, v = child.find_default()
- if found:
- value = v
- break
- elif isinstance(child, BoolLeaf):
- if child.getChecked():
- v = child.getValue()
- if v: value = int(v)
- break
-
- self.found_default = value
- return Node.firstFindDefault(self)
-
-
- def getSize(self):
- return self.getAttribute("size")
-
- def setSize(self, size):
- self.setAttribute("size", size)
-
- def getMultiple(self):
- return self.getAttribute("multiple")
-
- def setMultiple(self, multiple):
- self.setAttribute("multiple", multiple)
-
- def getSelected(self):
- return self.getAttribute("selected")
-
- def setSelected(self, selected):
- self.setAttribute("selected", selected)
-
-class IntLeaf(Leaf):
- def __init__(self):
- Leaf.__init__(self)
- self.attributes["minvalue"] = ""
- self.attributes["maxvalue"] = ""
-
- def firstFindDefault(self):
- value = self.getValue().strip()
- if value:
- try:
- value = int(value)
- except ValueError:
- print >> sys.stderr, "Broken default for '%s'" % self.getName()
- value = None
- else:
- value = None
- self.found_default = value
- return Leaf.firstFindDefault(self)
-
- def getMinValue(self):
- return self.getAttribute("minvalue")
-
- def setMinValue(self, minValue):
- self.setAttribute("minvalue", minValue)
-
- def getMaxValue(self):
- return self.getAttribute("maxvalue")
-
- def setMaxValue(self, maxValue):
- self.setAttribute("maxvalue", maxValue)
-
-class DateLeaf(Leaf):
- def __init__(self):
- Leaf.__init__(self)
-
- def firstFindDefault(self):
- value = self.getValue().strip()
- if value:
- try:
- value = date(*[int(x) for x in value.split("-")])
- except (TypeError, ValueError):
- print >> sys.stderr, "Broken default for '%s'" % self.getName()
- value = None
- else:
- value = None
- self.found_default = value
- return Leaf.firstFindDefault(self)
-
-class RuleLeaf(Leaf):
- def __init__(self):
- Leaf.__init__(self)
- self.attributes["expr"] = ""
- self.attributes["mark"] = ""
- self.expr = None
-
- def shallowCopy(self):
- r = Leaf.shallowCopy(self)
- if self.expr: r.expr = self.expr.clone()
- else: r.expr = None
- return r
-
- def setAttribute(self, attrib, value, broadcast=True):
- if attrib == "expr":
- newExpr = Expr(value)
- newExpr.compile()
- self.expr = newExpr
- Leaf.setAttribute(self, attrib, value, broadcast)
-
- def getExpr(self):
- return self.expr
-
- def getMark(self):
- return self.getAttribute("mark")
-
- def setMark(self, mark):
- self.setAttribute("mark", mark)
-
-# vim:set ts=4 sw=4 si et sta sts=4:
Deleted: wasko/branches/2.0/jmdweb/model/exprtree.py
===================================================================
--- wasko/branches/2.0/jmdweb/model/exprtree.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/model/exprtree.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,319 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: latin1 -*-
-#
-# Copyright 2007, 2008, 2009 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-#
-# Authors:
-# Sascha L. Teichmann <teichmann at intevation.de>
-#
-
-import sys
-import re
-import codecs
-import traceback
-
-from datetime import date
-from types import StringTypes
-
-from jmdweb.model import UNKNOWN_DATE, UNKNOWN_INT, UNKNOWN_STR
-
-FLT_RE = re.compile(r'^([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)$')
-INT_RE = re.compile(r'^([-+]?[0-9]+)$')
-VAR_RE = re.compile(r'^\$(\w+)$')
-
-from shlex import split as lexsplit
-
-class Node(object):
-
- def __init__(self):
- pass
-
- def eval(self, ctx):
- return None
-
-class Unary(Node):
-
- def __init__(self, a = None):
- Node.__init__(self)
- self.a = a
-
- def __repr__(self):
- return "%s(%s)" % (
- self.__class__.__name__,
- repr(self.a))
-
-class Binary(Unary):
-
- def __init__(self, a = None, b = None):
- Unary.__init__(self, a)
- self.b = b
-
- def __repr__(self):
- return "%s(%s, %s)" % (
- self.__class__.__name__,
- repr(self.a),
- repr(self.b))
-
-class OperatorUnary(Unary):
-
- def __init__(self, a, operator):
- Unary.__init__(self, a)
- self.operator = operator
-
- def eval(self, ctx):
- return self.operator(self.a.eval(ctx))
-
- def __repr__(self):
- return "%s[%s](%s)" % (
- self.__class__.__name__,
- self.operator.__name__,
- repr(self.a))
-
-class OperatorBinary(Binary):
-
- def __init__(self, a, b, operator):
- Binary.__init__(self, a, b)
- self.operator = operator
-
- def eval(self, ctx):
- return self.operator(self.a.eval(ctx), self.b.eval(ctx))
-
- def __repr__(self):
- return "%s[%s](%s, %s)" % (
- self.__class__.__name__,
- self.operator.__name__,
- repr(self.a),
- repr(self.b))
-
-class Not(Unary):
-
- def eval(self, ctx):
- return not self.a.eval(ctx)
-
-class And(Binary):
-
- def eval(self, ctx):
- ea = self.a.eval(ctx)
- if not ea: return False
- return bool(self.b.eval(ctx))
-
-class Or(Binary):
-
- def eval(self, ctx):
- return self.a.eval(ctx) and True or bool(self.b.eval(ctx))
-
-class Var(Node):
-
- def __init__(self, var_name):
- self.var_name = var_name
-
- def eval(self, ctx):
- return ctx.vars[self.var_name]
-
- def __repr__(self):
- return "var(%s)" % (self.var_name)
-
-class Const(Node):
-
- def __init__(self, const):
- self.const = const
-
- def eval(self, ctx):
- return self.const
-
- def __repr__(self):
- return "const(%s)" % repr(self.const)
-
-class Today(Node):
-
- def eval(self, ctx):
- return date.today()
-
-class DateNode(Node):
-
- def __init__(self, year, month, day):
- self.day = day
- self.month = month
- self.year = year
-
- def eval(self, ctx):
- day = self.day.eval(ctx)
- month = self.month.eval(ctx)
- year = self.year.eval(ctx)
- return date(year, month, day)
-
-class Out(Node):
-
- def __init__(self, parent):
- self.parent = parent
-
- def eval(self, ctx):
- e = self.parent.eval(ctx)
- print >> sys.stderr, "OUT: %s" % repr(e)
- return e
-
-class IThenElse(Node):
-
- def __init__(self, q, a, b):
- self.q = q
- self.a = a
- self.b = b
-
- def eval(self, ctx):
- if self.q.eval(ctx): return self.a.eval(ctx)
- return self.b.eval(ctx)
-
-def ADD(a, b): return a + b
-def MINUS(a, b): return a - b
-def MUL(a, b): return a * b
-def DIV(a, b): return a / b
-def MOD(a, b): return a % b
-def POW(a, b): return a ** b
-def EQ(a, b): return a == b
-def NE(a, b): return a != b
-def GT(a, b): return a > b
-def LT(a, b): return a < b
-def LE(a, b): return a <= b
-def GE(a, b): return a >= b
-def MIN(a, b): return min(a, b)
-def MAX(a, b): return max(a, b)
-def INT(a): return int(a)
-def FLOAT(a): return float(a)
-def STR(a): return str(a)
-def LEN(a): return len(a)
-def ABS(a): return abs(a)
-def NOT(a): return not a
-def ISSET(a): return not a is None
-def TYPE(a): return type(a)
-
-def KNOWN(a):
- return not (
- a == UNKNOWN_INT \
- or a == UNKNOWN_DATE \
- or (type(a) in StringTypes and a.lower() == UNKNOWN_STR))
-
-NODE_FACTORIES = {
- '+': lambda s: OperatorBinary(s.pop(), s.pop(), ADD),
- '-': lambda s: OperatorBinary(s.pop(-2), s.pop(), MINUS),
- '*': lambda s: OperatorBinary(s.pop(), s.pop(), MUL),
- '/': lambda s: OperatorBinary(s.pop(-2), s.pop(), DIV),
- '%': lambda s: OperatorBinary(s.pop(-2), s.pop(), MOD),
- '**': lambda s: OperatorBinary(s.pop(-2), s.pop(), POW),
- '==': lambda s: OperatorBinary(s.pop(), s.pop(), EQ),
- '!=': lambda s: OperatorBinary(s.pop(), s.pop(), NE),
- '>': lambda s: OperatorBinary(s.pop(-2), s.pop(), GT),
- '<': lambda s: OperatorBinary(s.pop(-2), s.pop(), LT),
- '<=': lambda s: OperatorBinary(s.pop(-2), s.pop(), LE),
- '>=': lambda s: OperatorBinary(s.pop(-2), s.pop(), GE),
- 'min': lambda s: OperatorBinary(s.pop(), s.pop(), MIN),
- 'max': lambda s: OperatorBinary(s.pop(), s.pop(), MAX),
- 'int': lambda s: OperatorUnary(s.pop(), INT),
- 'float': lambda s: OperatorUnary(s.pop(), FLOAT),
- 'str': lambda s: OperatorUnary(s.pop(), STR),
- 'len': lambda s: OperatorUnary(s.pop(), LEN),
- 'abs': lambda s: OperatorUnary(s.pop(), ABS),
- 'not': lambda s: OperatorUnary(s.pop(), NOT),
- 'isset': lambda s: OperatorUnary(s.pop(), ISSET),
- 'known': lambda s: OperatorUnary(s.pop(), KNOWN),
- 'type': lambda s: OperatorUnary(s.pop(), TYPE),
- 'and': lambda s: And(s.pop(-2), s.pop()),
- 'or': lambda s: Or(s.pop(-2), s.pop()),
- 'today': lambda s: Today(),
- 'date': lambda s: DateNode(s.pop(), s.pop(), s.pop()),
- '.': lambda s: Out(s.pop()),
- '?': lambda s: IThenElse(s.pop(), s.pop(), s.pop())
-}
-
-class EvalContext(object):
-
- def __init__(self, vars):
- self.vars = vars
-
-class Expr(object):
-
- def __init__(self, expr):
- self.expr = expr
- self.prog = None
- self.depends = None
-
- def evaluate(self, vars=None):
- if self.prog is None:
- self.compile()
-
- ctx = EvalContext(vars)
- try:
- return self.prog.eval(ctx)
- except:
- traceback.print_exc(file = sys.stderr)
- print >> sys.stderr, "Expr: ", repr(self.prog)
- raise
-
- def compile(self):
- depends = set()
-
- stack = []
-
- # XXX: shlex does not support unicode -> ascii
- encoder = codecs.getencoder("ascii")
- for token in lexsplit(encoder(self.expr)[0]):
- token = unicode(token)
- m = VAR_RE.match(token)
- if m:
- var = m.group(1)
- stack.append(Var(var))
- depends.add(var)
- continue
- m = INT_RE.match(token)
- if m:
- stack.append(Const(int(m.group(1))))
- continue
- m = FLT_RE.match(token)
- if m:
- stack.append(Const(float(m.group(1))))
- continue
- try:
- stack.append(NODE_FACTORIES[token](stack))
- except KeyError:
- stack.append(Const(token))
-
- self.prog = stack and stack[0] or None
- self.depends = depends
-
- def getDependencies(self):
- if self.depends is None:
- self.compile()
- return self.depends
-
-#def main():
-# for arg in sys.argv[1:]:
-# expr = Expr(arg)
-# vars = { 'a': 3 }
-# result = expr.evaluate(vars)
-# print str(result)
-#
-#if __name__ == "__main__":
-# main()
-
-# vim:set ts=4 sw=4 si et sta sts=4:
Deleted: wasko/branches/2.0/jmdweb/model/nodecomponents.py
===================================================================
--- wasko/branches/2.0/jmdweb/model/nodecomponents.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/model/nodecomponents.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,325 +0,0 @@
-# -*- coding: latin1 -*-
-#
-# Copyright 2007, 2008 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-#
-# Authors:
-# Sascha L. Teichmann <teichmann at intevation.de>
-#
-
-VISIT_IGNORE_CHILDREN = 2
-VISIT_CONTINUE = None
-
-class NodeComponent:
-
- def __init__(self):
- self.parent = None
- self.attributes = {}
- self.attributes["name"] = ""
- self.attributes["description"] = ""
- self.attributes["formularname"] = ""
- self.attributes["modes"] = ""
- self.attributes["annotation"] = ""
- self.attributes["target"] = ""
- self.attributes["alternative"] = ""
- self.attributes["flags"] = ""
-
- self.found_default = None
- self.findDefault = self.firstFindDefault
-
- def firstFindDefault(self):
- self.findDefault = self.defaultFound
- return self.found_default
-
- def defaultFound(self):
- return self.found_default
-
- def setAttribute(self, key, value, broadcast=True):
- self.attributes[key] = value
-
- def getAttribute(self, key):
- return self.attributes.get(key, None)
-
- def getAnnotation(self):
- return self.getAttribute("annotation")
-
- def setAnnotation(self, annotation):
- return self.setAttribute("annotation", annotation)
-
- def getAlternative(self):
- return self.getAttribute("alternative")
-
- def setAlternative(self, alternative):
- return self.setAttribute("alternative", alternative)
-
- def getTarget(self):
- return self.getAttribute("target")
-
- def setTarget(self, target):
- return self.setAttribute("target", target)
-
- def setFormularName(self, name):
- self.setAttribute("formularname", name)
-
- def getFormularName(self):
- return self.getAttribute("formularname")
-
- def setName(self, name):
- self.setAttribute("name", name)
-
- def getName(self):
- return self.getAttribute("name")
-
- def setDescription(self, description):
- self.setAttribute("description", description)
-
- def getDescription(self):
- return self.getAttribute("description")
-
- def getModes(self):
- return self.getAttribute("modes")
-
- def setModes(self, modes):
- self.setAttribute("modes", modes)
-
- def getFlags(self):
- return self.getAttribute("flags")
-
- def setFlags(self, flags):
- return self.setAttribute("flags", flags)
-
- def getParent(self):
- return self.parent
-
- def pathToRoot(self):
- current = self
- path = []
- while not current is None:
- path.insert(0, current)
- current = current.parent
- return path
-
- def depth(self):
- d = -1
- current = self
- while not current is None:
- d += 1
- current = current.parent
- return d
-
- def walk(self):
- yield self
-
- def visit(self, visitor):
- return visitor(self)
-
- def shallowCopy(self):
- nc = self.__class__()
- nc.attributes = self.attributes.copy()
- return nc
-
- def clone(self):
- return self.shallowCopy()
-
-class Node(NodeComponent):
-
- def __init__(self):
- NodeComponent.__init__(self)
- self.attributes["containers"] = ""
- self.children = []
-
- def getContainers(self):
- return self.getAttribute("containers")
-
- def setContainers(self, containers):
- self.setAttribute("containers", containers)
-
- def addChild(self, child, idx=-1, broadcast=True):
- if idx == -1:
- idx = len(self.children)
- self.children.insert(idx, child)
- child.parent = self
-
- def indexOfChild(self, child):
- try:
- return self.children.index(child)
- except ValueError:
- return -1
-
- def getChildByName(self, name):
- for child in self.children:
- if child.getName() == name:
- return child
- return None
-
- def removeChild(self, child, broadcast=True):
- try:
- self.children.remove(child)
- child.parent = None
- except ValueError:
- return
-
- def walk(self):
- yield self
- for child in self.children:
- for x in child.walk():
- yield x
-
- def visit(self, visitor):
-
- result = visitor(self)
- if result == VISIT_IGNORE_CHILDREN:
- return VISIT_CONTINUE
- if result != VISIT_CONTINUE:
- return result
- for child in self.children:
- result = child.visit(visitor)
- if result == VISIT_IGNORE_CHILDREN:
- return VISIT_CONTINUE
- if result != VISIT_CONTINUE:
- return result
- return VISIT_CONTINUE
-
- def clone(self):
- n = NodeComponent.clone(self)
- children = []
- for child in self.children:
- child = child.clone()
- children.append(child)
- child.parent = n
- n.children = children
- return n
-
- def firstLevel(self, crit):
- visited = set()
- for c in self.walk():
- if c != self and crit(c):
- parent = c.parent
- found = False
- while parent:
- if parent in visited:
- found = True
- break
- parent = parent.parent
- if not found:
- visited.add(c)
- yield c
-
-class RootNode(Node):
- def __init__(self, document=None):
- Node.__init__(self)
- self.document = document
-
-class CaseNode(Node):
- def __init__(self):
- Node.__init__(self)
-
-class LogbookNode(Node):
- def __init__(self):
- Node.__init__(self)
-
-class Leaf(NodeComponent):
- def __init__(self):
- NodeComponent.__init__(self)
- self.attributes["value"] = ""
-
- def getValue(self):
- return self.getAttribute("value")
-
- def setValue(self, value):
- self.setAttribute("value", value)
-
-class Document:
-
- def __init__(self, root=None):
- if root is None: self.root = RootNode()
- else: self.root = root
- self.root.document = self
-
- def importDocument(self, ndocument):
- root, nroot = self.root, ndocument.root
- if not root or not nroot: return
-
- for child in nroot.children[:]:
- nroot.removeChild(child)
- root.addChild(child)
-
- def getNames(self):
- names = set()
- root = self.root
- if not root: names
- for nc in root.walk():
- name = nc.getName()
- if name: names.add(name)
- return names
-
- def getNodeComponentByName(self, name):
- root = self.root
- if not root: None
- for child in root.walk():
- if child.getName() == name:
- return child
- return None
-
- def findByName(self, name):
- if self.root:
- for nc in self.root.walk():
- if name == nc.getName():
- return nc
- return None
-
- def findByClassAndName(self, clazz, name=None):
- if self.root:
- for nc in self.root.walk():
- if isinstance(nc, clazz) and \
- (not name or nc.getName() == name):
- return nc
- return None
-
- def indexOfcomponentByClassAndName(self, clazz, name=None):
- idx = 0
- if self.root:
- for nc in self.root.walk():
- if isinstance(nc, clazz):
- if not name or nc.getName() == name:
- return idx
- idx += 1
- return -1
-
- def findAllByClass(self, clazz):
- if self.root:
- for nc in self.root.walk():
- if isinstance(nc, clazz):
- yield nc
-
- def visit(self, visitor):
- if self.root:
- self.root.visit(visitor)
-
- def walk(self):
- if self.root:
- for nc in self.root.walk():
- yield nc
-
-# vim:set ts=4 sw=4 si et sta sts=4:
Deleted: wasko/branches/2.0/jmdweb/model/phase_transition.py
===================================================================
--- wasko/branches/2.0/jmdweb/model/phase_transition.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/model/phase_transition.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,136 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright 2007, 2008 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-#
-# Authors:
-# Sascha L. Teichmann <sascha.teichmann at intevation.de>
-#
-
-import sys
-
-UNKNOWN = -1
-CLEAR_START = 0
-CLEAR_ENDE = 1
-CM_START = 2
-CM_ENDE = 3
-NB_START = 4
-NB_ENDE = 5
-
-PHASE_STARTINGS = (CLEAR_START,CM_START,NB_START)
-PHASE_ENDINGS = (CLEAR_ENDE,CM_ENDE,NB_ENDE)
-
-# dictionary for GUI
-PHASE_DESCRIPTIONS = {
- UNKNOWN : u"Unbekannt",
- CLEAR_START : u"Eingangsdokumentation läuft",
- CLEAR_ENDE : u"Eingangsdokumentation beendet",
- CM_START : u"Case Management läuft",
- CM_ENDE : u"Case Management beendet",
- NB_START : u"Nachbetreuung läuft",
- NB_ENDE : u"Nachbetreuung beendet",
-}
-
-# dictionary for symbolic handling like usage in FormEd trees.
-PHASE_SYMBOLS = {
- UNKNOWN : u"unbekannt",
- CLEAR_START : u"phase_a_start",
- CLEAR_ENDE : u"phase_a_end",
- CM_START : u"phase_b_start",
- CM_ENDE : u"phase_b_end",
- NB_START : u"phase_c_start",
- NB_ENDE : u"phase_c_end",
-}
-
-SYMBOLS_PHASE = dict([(i[1], i[0]) for i in PHASE_SYMBOLS.iteritems()])
-
-
-PHASE_SUCCESSORS = {
- UNKNOWN : [CLEAR_START],
- CLEAR_START : [CLEAR_ENDE],
- CLEAR_ENDE : [CM_START],
- CM_START : [CM_ENDE],
- CM_ENDE : [NB_START],
- NB_START : [NB_ENDE],
- NB_ENDE : []
-}
-
-def phase_description(phase):
- return PHASE_DESCRIPTIONS.get(phase, "-/-")
-
-def phase_symbol(phase):
- return PHASE_SYMBOLS[phase]
-
-def symbol_phase(symbol):
- return SYMBOLS_PHASE[symbol]
-
-def phase_successors(phase):
- try:
- return PHASE_SUCCESSORS[phase]
- except KeyError:
- return []
-
-def phase_predecessors(phase):
- preds = set()
- for k, v in PHASE_SUCCESSORS.iteritems():
- if phase in v:
- preds.add(k)
- return list(preds)
-
-def phase_predecessors_path(phase, path=None, include_root=False):
- if not path:
- path = []
- if include_root:
- path.append(phase)
- for p in phase_predecessors(phase):
- path.append(p)
- phase_predecessors_path(p, path=path)
- return path
-
-def phase_successors_path(phase, path=None, include_root=False):
- if not path:
- path = []
- if include_root:
- path.append(phase)
- for p in phase_successors(phase):
- path.append(p)
- phase_successors_path(p, path=path)
- return path
-
-def phase_neighbors(phase1, phase2):
- try:
- return phase2 in PHASE_SUCCESSORS[phase1] or phase1 in PHASE_SUCCESSORS[phase2]
- except KeyError, ke:
- print >> sys.stderr, "missing key in phase_neighbors:", ke
- return False
-
-def phase_end(phase):
- '''Return True if the current phase is the end part of a phase pair.'''
- return phase in PHASE_ENDINGS
-
-def phase_start(phase):
- '''Return True if the current phase is the start part of a phase pair.'''
- return phase in PHASE_STARTINGS
-
-# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8:
Deleted: wasko/branches/2.0/jmdweb/model/phases.py
===================================================================
--- wasko/branches/2.0/jmdweb/model/phases.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/model/phases.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,116 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright 2007, 2008 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-# Authors:
-#
-# Sascha L. Teichmann <sascha.teichmann at intevation.de>
-#
-
-from jmdweb.model.phase_transition import \
- phase_neighbors, phase_symbol, phase_description, phase_predecessors_path, phase_successors_path
-
-class Phase:
-
- def __init__(self, phase, running = False, complete = False, time = None, links = ""):
- self.phase = phase
- self.running = running
- self.complete = complete
- self.time = time
- self.links = links
- self.preds = []
-
- def isNeighbor(self, other):
- return phase_neighbors(self.phase, other.phase)
-
- def isRunning(self):
- return self.running
-
- def addPredecessor(self, pred):
- self.preds.append(pred)
-
- def getLabel(self):
- return phase_symbol(self.phase)
-
- def getDescription(self):
- return phase_description(self.phase)
-
- def isComplete(self):
- return self.complete
-
- def isRecursiveComplete(self):
- if not self.complete:
- return False
-
- for pred in self.preds:
- if not pred.isRecursiveComplete():
- return False
-
- return True
-
- def hasPredecessor(self, other):
- #for p in self.preds:
- # if other.phase == p.phase or p.hasPredecessor(other): return True
- #return False
- predecessors = phase_predecessors_path(self.phase)
- return other.phase in predecessors
-
- def hasSuccessor(self, other):
- successors = phase_successors_path(self.phase)
- return other.phase in successors
-
- def getTime(self):
- if str(self.time) != '0001-01-01':
- return self.time
- return None
-
- def getLinks(self):
- return self.links
-
-class PhasePair:
-
- def __init__(self, start, end, description):
- self.start = start
- self.end = end
- self.description = description
-
- def getStart(self):
- return self.start
-
- def getEnd(self):
- return self.end
-
- def getDuration(self):
- t1 = self.start.getTime()
- t2 = self.end.getTime()
- if not t1 or not t2: return None
- return t2 - t1
-
- def getDescription(self):
- return self.description
-
- def isRunning(self):
- return self.start.isRunning() or self.end.isRunning()
-
-# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
Deleted: wasko/branches/2.0/jmdweb/model/phases_factory.py
===================================================================
--- wasko/branches/2.0/jmdweb/model/phases_factory.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/model/phases_factory.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,333 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright 2007, 2008, 2010 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-# Authors:
-#
-# Sascha L. Teichmann <sascha.teichmann at intevation.de>
-#
-
-from xml.sax.saxutils import quoteattr
-from cgi import escape
-
-from jmdweb.model.phases import Phase, PhasePair
-from jmdweb.model.phase_transition import CLEAR_ENDE, CLEAR_START, CM_ENDE, \
- CM_START, NB_ENDE, NB_START, phase_predecessors, phase_symbol
-
-#from jmdweb.model.data import PageNode
-
-
-PAIRS = (
- (CLEAR_START, CLEAR_ENDE, u"Eingangs-<wbr />Dokumentation"),
- (CM_START, CM_ENDE, u"Case Management"),
- (NB_START, NB_ENDE, u"Nach­betreuung"))
-
-
-def description(nc):
- p = nc
- while p:
- desc = p.getDescription()
- if desc:
- desc = desc.strip()
- if desc:
- return desc
- p = p.parent
- return nc.getName()
-
-
-def page(nc):
- p = nc
- while p:
- if isinstance(p, PageNode):
- return p
- p = p.parent
- return p
-
-
-def nescape(s):
- return escape(s).replace(' ', ' ')
-
-
-def space_short(s, n):
- L = len(s)
- if (L - 3) <= n:
- return s
- r = list(s[0:n])
-
- while True:
- R = len(r)
- if R >= L or r[-1].isspace() or s[R].isspace():
- break
- r.append(s[R])
-
- r.append(R < (L - 3) and u'...' or s[L - (L - R):])
- return u''.join(r)
-
-
-class RequiredFields:
-
- def __init__(self, formed):
- self.formed = formed
- self.phase_times = {}
- self.missing_cache = {}
- self.rule_eval_cache = {}
- self.var_eval_cache = {}
-
-
- def getPhaseTime(self, phase):
- try:
- return self.phase_times[phase]
- except KeyError:
- try:
- time_vars = self.formed.getTimeVars(phase)
- if not time_vars:
- return None
- pt = [self.formed.getData(x.getName()) for x in time_vars]
- if pt:
- pt = pt[0]
- else:
- pt = None
- self.phase_times[phase] = pt
- except KeyError:
- return None
- return pt
-
- def isPhaseComplete(self, phase, master_id=None):
- return not bool(self.missingFields(phase, master_id))
-
-# def missingFields(self, phase, master_id):
-# outfile = None
-# try:
-# outfile = open("/tmp/phases.txt", "a")
-# return self.missingFieldsX(phase, outfile)
-# finally:
-# if outfile:
-# try: outfile.close()
-# except: pass
-
- def missingFields(self, phase, master_id = None):
- vars = self.formed.getPhaseVars(phase)
- if not vars:
- return []
-
- try:
- missing = self.missing_cache[phase]
- return missing
- except KeyError:
- pass
-
- getData = self.formed.getData
-
- missing = []
- self.missing_cache[phase] = missing
- for var in vars:
- var_name = var.getName()
- try:
- result = self.var_eval_cache[var_name]
- if not result:
- missing.append(var)
- continue
- except KeyError:
- pass
-
- rules = self.formed.getRulesForVariable(var_name)
- if not rules:
- continue
-
- result = True
- for rule in rules:
- # only eval warning rules
- mark = WARNING.search(rule.getMark())
- if not mark:
- continue
- rule_name = rule.getName()
- try:
- result = self.rule_eval_cache[rule_name]
- except KeyError:
- expr = rule.getExpr()
- deps = expr.getDependencies()
- params = dict((v, getData(v, master_id)) for v in deps)
- try:
- result = expr.evaluate(params)
- except:
- result = True
-
- self.rule_eval_cache[rule_name] = result
-
- if not result:
- break
-
- self.var_eval_cache[var_name] = result
- if not result:
- missing.append(var)
-
- return missing
-
- def getLinkListForPhase(self, phase, navigation=None, link=None,
- master_id=None):
- if not navigation and not link:
- return u""
-
- all_vars = self.formed.getPhaseVars(phase)
- if not all_vars:
- return u""
-
- missing_set = set([x.getName() for x in
- self.missingFields(phase, master_id=master_id)])
-
- pages = []
- used_pages = {}
- on_invisible_page = []
-
- for var in all_vars:
- p = page(var)
- if p.isInvisible():
- on_invisible_page.append(var)
- continue
- p_name = p.getName()
- try:
- t = used_pages[p_name]
- except KeyError:
- tree_item = navigation.findTreeItemByPageName(p_name)
- if not tree_item:
- continue
- tree_item = tree_item.deepest_item()
- t = [tree_item, []]
- pages.append(t)
- used_pages[p_name] = t
-
- if var.getName() in missing_set:
- t[1].append(var)
-
- if not pages and not on_invisible_page:
- return u""
-
- out = [u"<ul>"]
-
- for var in on_invisible_page:
- out.append(u"<li>")
- missing = var.getName() in missing_set
- if missing:
- out.append(u'<span class="required_missing">')
- out.append(escape(var.getDescription()))
- if missing:
- out.append(u"</span>")
- out.append(u"</li>")
-
- for tree_item, warn in pages:
- out.append(u"<li>")
- if not warn:
- out.append(u'<a href=%s'
- u' title="Seite für Phase vollständig ausgefüllt">'
- u'<strong>%s</strong></a>'
- % (link(tree_item), nescape(tree_item.description)))
- else:
- if len(warn) < 6:
- out2 = []
- for v in warn:
- desc = description(v)
- if len(desc) > 15:
- title = quoteattr(u"Fehlende Angabe: %s" % desc)
- desc = escape(space_short(desc, 15))
- else:
- title = u'"Fehlende Angabe für diese Phase"'
- desc = escape(desc)
-
- out2.append(u'<a href=%s class="required_missing"'
- u' title=%s>%s'
- % (link(tree_item, u"#f_" + v.getName()),
- title, desc))
- links = u",</a> ".join(out2) + u"</a>"
- out.append(u'<strong>%s</strong>: %s'
- % (nescape(tree_item.description), links))
- else:
- out.append(u'<a href=%s'
- u' title="Auf dieser Seite sind noch %d Felder'
- u' auszufüllen.">'
- u'<strong>%s'
- u' <span class="required_missing">(%d)</span>'
- u'</strong></a>'
- % (link(tree_item), len(warn),
- nescape(tree_item.description), len(warn)))
- out.append(u"</li>")
-
- out.append(u"</ul>")
-
- return u"".join(out)
-
- def phases_pairs(self, current_phase, navigation=None, link=None,
- master_id=None):
- pairs = []
- all = {}
- symbol = phase_symbol(current_phase)
-
- cur_phase = Phase(current_phase, True,
- self.isPhaseComplete(symbol, master_id),
- self.getPhaseTime(symbol),
- self.getLinkListForPhase(symbol, navigation, link,
- master_id))
-
- for p1, p2, description in PAIRS:
- symbol = phase_symbol(p1)
- start = Phase(p1, p1 == current_phase,
- self.isPhaseComplete(symbol, master_id),
- self.getPhaseTime(symbol),
- self.getLinkListForPhase(symbol, navigation, link,
- master_id))
- all[p1] = start
-
- symbol = phase_symbol(p2)
- ende = Phase(p2, p2 == current_phase,
- self.isPhaseComplete(symbol, master_id),
- self.getPhaseTime(symbol),
- self.getLinkListForPhase(symbol, navigation, link,
- master_id))
-
- all[p2] = ende
-
- # Only add phases which are on the path of the current phase
- #pairs.append(PhasePair(start, ende, description))
- if (cur_phase.hasSuccessor(start) or cur_phase.hasPredecessor(start)
- or current_phase == p1):
- pairs.append(PhasePair(start, ende, description))
-
- for p in all.itervalues():
- for pred in phase_predecessors(p.phase):
- try:
- p.addPredecessor(all[pred])
- except KeyError:
- pass
-
- return pairs
-
- def currentPhase(required_fields, current_phase, master_id=None):
- symbol = phase_symbol(current_phase)
- cur_phase = Phase(current_phase, True,
- required_fields.isPhaseComplete(symbol, master_id),
- required_fields.getPhaseTime(symbol),
- required_fields.getLinkListForPhase(symbol, None,
- None, master_id))
- return cur_phase
-
-# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
Deleted: wasko/branches/2.0/jmdweb/model/semantic.py
===================================================================
--- wasko/branches/2.0/jmdweb/model/semantic.py 2010-03-25 08:28:41 UTC (rev 2140)
+++ wasko/branches/2.0/jmdweb/model/semantic.py 2010-03-25 08:41:39 UTC (rev 2141)
@@ -1,361 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright 2007, 2008 Intevation GmbH, Germany, <info at intevation.de>
-#
-# This file is part of mpuls WASKA (CoMPUter-based case fiLeS -
-# Web-Anwendungs-Server fuer Kompetenzagenturen).
-#
-# mpuls WASKA is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Affero General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or (at your
-# option) any later version.
-#
-# mpuls WASKA is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with mpuls WASKA. If not, see <http://www.gnu.org/licenses/>.
-#
-# mpuls WASKA has been developed on behalf of the
-# Projekttraeger im Deutschen Zentrum fuer Luft- und Raumfahrt e.V. (PT-DLR)
-# within the programme Kompetenzagenturen (Durchfuehrungsphase) funded by
-# the Bundesministerium fuer Familie, Senioren, Frauen und Jugend and
-# European Social Fund resources.
-#
-# Authors:
-# Sascha L. Teichmann <teichmann at intevation.de>
-#
-
-import re
-
-import data
-
-from datetime import date
-
-from sys import maxint
-
-from formed.meta import UNKNOWN_INT, UNKNOWN_DATE
-
-def safe_unicode(s):
- return s
-
-
-class ErrorItem:
-
- def __init__(self, page=None, bad=None, name=None):
- self.page = page
- self.bad = bad
- self.name = name
- self.messages = []
-
- def addMessage(self, msg):
- self.messages.append(msg)
-
- def getName(self):
- return self.name
-
- def getMessages(self):
- return self.messages
-
- def __repr__(self):
- return self.__str__()
-
- def __str__(self):
- r = ["page: %s" % repr(self.page)]
- r.append("bad: %s" % repr(self.bad))
- r.append("name: %s" % repr(self.name))
- r.append("messages: [%s]" % ", ".join([repr(s) for s in self.messages]))
- return ", ".join(r)
-
-class SematicError(Exception):
-
- def __init__(self, value):
- Exception.__init__(self)
- self.value = value
-
- def __str__(self):
- return repr(self.value)
-
-class ValueChecker:
- def checkAndConvert(self, value, nc):
- return None
-
-class Converter:
- def convert(self, value, nc):
- return None
-
-class TextChecker:
-
- def convert(self, value, nc):
- return self.checkAndConvert(value, nc)
-
- def checkAndConvert(self, value, nc):
-
- ml = nc.getMaxLength()
- if ml:
- try:
- value = value[:int(ml)]
- try:
- return safe_unicode(unicode(str(value), 'utf-8'))
- except (TypeError, UnicodeError):
- return value
- except ValueError:
- raise SematicError("Invalid max length value")
- return value
-
-class TextAreaChecker:
-
- def convert(self, value, nc):
- return self.checkAndConvert(value, nc)
-
- def checkAndConvert(self, value, nc):
- try:
- return safe_unicode(unicode(str(value), 'utf-8'))
- except (TypeError, UnicodeError):
- pass
- return value
-
-class IntChecker(ValueChecker):
-
- def convert(self, value, nc):
- return self.checkAndConvert(value, nc)
-
- def checkAndConvert(self, value, nc):
- value = value.strip()
-
- if value[:2].lower() == u"un":
- return UNKNOWN_INT
-
- try:
- value = int(float(value))
- except ValueError:
- raise SematicError("'%s' ist keine ganze Zahl." % value)
- try:
- minv = nc.getMinValue()
- maxv = nc.getMaxValue()
-
- if isinstance(minv, (type(u""), type(""))):
- if len(minv): minv = int(minv)
- else: minv = -maxint-1
- else:
- minv = int(minv)
-
- if isinstance(maxv, (type(""), type(u""))):
- if len(maxv): maxv = int(maxv)
- else: maxv = maxint
-
- minv, maxv = min(minv, maxv), max(minv, maxv)
-
- if value < minv:
- raise SematicError(
- u"%d ist kleiner als der zulässige Minimalwert %d." % (value, minv))
-
- if value > maxv:
- raise SematicError(
- u"%d ist größer als der zulässige Maximalwert %d." % (value, maxv))
- except ValueError:
- raise SematicError(
- "Check constraints for '%s'" % nc.getName())
- return value
-
-class DateChecker(ValueChecker):
-
- DATE = re.compile(r"^([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{2,4})$")
- DATE_IDX = (1, 2, 3)
- DATE_ISO = re.compile(r"^([0-9]{2,4})-([0-9]{1,2})-([0-9]{1,2})$")
- DATE_ISO_IDX = (3, 2, 1)
- YEAR = re.compile(r"^([0-9]{1,4})$")
-
- DAY_MONTH = re.compile(r"^([0-9]{1,2})\.([0-9]{1,2})$")
-
- def convert(self, value, nc):
- return self.checkAndConvert(value, nc)
-
- def checkAndConvert(self, value, nc):
- value = value.strip()
-
- if value[:2].lower() == u"un":
- return UNKNOWN_DATE
-
- m = DateChecker.DAY_MONTH.match(value)
- if m:
- day = int(m.group(1))
- month = int(m.group(2))
- year = date.today().year
- try:
- return date(year, month, day)
- except ValueError:
- raise SematicError(u"'%s' ist kein gültiges Datum. (Format: DD.MM.JJJJ)" % value)
-
- for reg, idx in ((DateChecker.DATE, DateChecker.DATE_IDX), (DateChecker.DATE_ISO, DateChecker.DATE_ISO_IDX)):
- m = reg.match(value)
- if not m: continue
- day = int(m.group(idx[0]))
- month = int(m.group(idx[1]))
- year = int(m.group(idx[2]))
-
- if year < 100:
- if year < 70: year += 2000
- else: year += 1900
-
- try:
- return date(year, month, day)
- except ValueError:
- raise SematicError(u"'%s' ist kein gültiges Datum. (Format: DD.MM.JJJJ)" % value)
-
- m = DateChecker.YEAR.match(value)
- if m:
- year = int(m.group(1))
-
- if year < 100:
- if year < 70: year += 2000
- else: year += 1900
-
- try:
- return date(year, 1, 1)
- except ValueError:
- raise SematicError(u"'%s' ist kein gültiges Datum. (Format: DD.MM.JJJJ)" % value)
-
- raise SematicError("'%s' ist kein Datum. (Format: DD.MM.JJJJ)" % value)
-
-class ChoiceChecker(ValueChecker):
-
- def checkAndConvert(self, value, nc):
-
- value = value.strip()
- for c in nc.children:
- if isinstance(c, data.BoolLeaf):
- v = c.getValue()
- if v == value:
- try:
- return int(v)
- except ValueError:
- return v
- elif isinstance(c, data.ExternalChoiceListLeaf):
- cc = c.getChildren()
- if cc:
- for i in cc:
- if isinstance(i, data.BoolLeaf):
- v = i.getValue()
- if v == value:
- try:
- return int(v)
- except ValueError:
- return v
-
- raise SematicError("'%s' is not a valid value for '%s'" % (
- value, nc.getName()))
-
-def _checkBool(nc, value):
- for m in ("getDescription", "getAlternative"):
- v = getattr(nc, m)()
- if v is None: continue
- v = v.strip().lower()
- if v == value:
- try:
- return int(nc.getValue().strip())
- except ValueError:
- return v
- return None
-
-class ChoiceConverter(Converter):
-
- def convert(self, value, nc):
-
- value = value.strip().lower()
- for c in nc.children:
- if isinstance(c, data.BoolLeaf):
- v = _checkBool(c, value)
- if not v is None: return v
- elif isinstance(c, data.ExternalChoiceListLeaf):
- cc = c.getChildren()
- if cc:
- for i in cc:
- if isinstance(i, data.BoolLeaf):
- v = _checkBool(i, value)
- if not v is None: return v
-
- raise SematicError(u"'%s' ist kein valider Wert für '%s'" % (
- value, nc.getName()))
-
-class RadioChecker(ValueChecker):
-
- def checkAndConvert(self, value, nc):
- value = value.strip()
- for c in nc.children:
- if isinstance(c, data.BoolLeaf):
- v = c.getValue()
- if v == value:
- try:
- return int(v)
- except ValueError:
- raise SematicError(u"'%s' ist kein valider Wert für '%s'." % (
- value, nc.getName()))
-
- raise SematicError(u"'%s' ist kein valider Wert für '%s'." % (
- value, nc.getName()))
-
-class RadioConverter(Converter):
-
- def convert(self, value, nc):
- value = value.strip()
- for c in nc.children:
- if isinstance(c, data.BoolLeaf):
- v = c.getDescription().strip().lower()
- if v == value:
- return c.getValue()
- raise SematicError("'%s' is not a valid value for '%s'" % (
- value, nc.getName()))
-
-class BoolChecker(ValueChecker):
-
- def checkAndConvert(self, value, nc):
- value = value.strip()
- return len(value) and 1 or 0
-
-class BoolConverter(Converter):
-
- def convert(self, value, nc):
- value = value.strip().lower()
- if not value: return None
- return (value == "ja" or value == '1') and 1 or 0
-
-TYPES = {
- data.IntLeaf : IntChecker(),
- data.DateLeaf: DateChecker(),
- data.TextLeaf: TextChecker(),
- data.TextAreaLeaf: TextAreaChecker(),
- data.ChoiceNode: ChoiceChecker(),
- data.BoolLeaf: BoolChecker(),
- data.RadioNode: RadioChecker()
-}
-
-CONVERTERS = {
- data.IntLeaf : IntChecker(),
- data.DateLeaf: DateChecker(),
- data.TextLeaf: TextChecker(),
- data.TextAreaLeaf: TextAreaChecker(),
- data.ChoiceNode: ChoiceConverter(),
- data.BoolLeaf: BoolConverter(),
- data.RadioNode: RadioConverter()
-}
-
-def checkAndConvert(nc, value):
- try:
- checker = TYPES[nc.__class__]
- except KeyError:
- raise SematicError("no type check found for '%s'"
- % str(nc.__class__))
- return checker.checkAndConvert(value, nc)
-
-def convertFromDescription(nc, value):
- try:
- converter = CONVERTERS[nc.__class__]
- except KeyError:
- raise SematicError("no converter found for '%s'"
- % str(nc.__class__))
- return converter.convert(value, nc)
-
-# vim:set ts=4 sw=4 si et sta sts=4:
More information about the Mpuls-commits
mailing list