source: main/waeup.kofa/trunk/src/waeup/kofa/documents/batching.py @ 15998

Last change on this file since 15998 was 13145, checked in by Henrik Bettermann, 9 years ago

A bit more information.

  • Property svn:keywords set to Id
File size: 5.7 KB
Line 
1## $Id: batching.py 13145 2015-07-07 05:36:46Z henrik $
2##
3## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""Batch processing components for document objects.
19
20Batch processors eat CSV files to add, update or remove large numbers
21of certain kinds of objects at once.
22"""
23import grok
24import unicodecsv as csv  # XXX: csv ops should move to dedicated module.
25from time import time
26from datetime import datetime
27from zope.i18n import translate
28from zope.interface import Interface
29from zope.schema import getFields
30from zope.component import queryUtility, getUtility, createObject
31from zope.event import notify
32from zope.catalog.interfaces import ICatalog
33from hurry.workflow.interfaces import IWorkflowState, IWorkflowInfo
34from waeup.kofa.interfaces import (
35    IBatchProcessor, FatalCSVError, IObjectConverter, IUserAccount,
36    IGNORE_MARKER)
37from waeup.kofa.interfaces import IKofaUtils
38from waeup.kofa.interfaces import MessageFactory as _
39from waeup.kofa.documents.interfaces import (
40    IPDFDocument, IHTMLDocument, IRESTDocument)
41from waeup.kofa.utils.batching import BatchProcessor
42
43
44class DocumentProcessorBase(BatchProcessor):
45    """This is the base class for all kinds of document processors.
46    The `checkConversion` method checks whether `class_name` in a row
47    corresponds with the processor chosen. This is to avoid accidentally
48    wrong imports.
49
50    Document processors do not import workflow states or transitions which
51    means, all imported documents will be unpublished after batch creation.
52    In other words, publishing can't be done by import, it has do be done
53    via the UI.
54    """
55    grok.implements(IBatchProcessor)
56    grok.provides(IBatchProcessor)
57    grok.context(Interface)
58    grok.baseclass()
59
60    util_name = None
61    name = None
62    iface = None
63
64    location_fields = ['document_id',]
65    additional_fields = ['class_name',]
66
67    factory_name = None
68
69    mode = None
70
71    @property
72    def available_fields(self):
73        return sorted(list(set(
74                    self.additional_fields +
75                    getFields(self.iface).keys())))
76
77    def parentsExist(self, row, site):
78        return 'documents' in site.keys()
79
80    def entryExists(self, row, site):
81        document_id = row.get('document_id', None)
82        cat = queryUtility(ICatalog, name='documents_catalog')
83        results = list(cat.searchResults(document_id=(document_id, document_id)))
84        if results:
85            return True
86        return False
87
88    def getParent(self, row, site):
89        return site['documents']
90
91    def getEntry(self, row, site):
92        if not self.entryExists(row, site):
93            return None
94        parent = self.getParent(row, site)
95        return parent.get(row['document_id'])
96
97    def addEntry(self, obj, row, site):
98        parent = self.getParent(row, site)
99        parent.addDocument(obj)
100        return
101
102    def delEntry(self, row, site):
103        document = self.getEntry(row, site)
104        parent = self.getParent(row, site)
105        if document is not None:
106            grok.getSite().logger.info(
107                '%s - Document removed' % document.document_id)
108            del parent[document.document_id]
109        return
110
111    def updateEntry(self, obj, row, site, filename):
112        """Update obj to the values given in row.
113        """
114        items_changed = super(DocumentProcessorBase, self).updateEntry(
115            obj, row, site, filename)
116        # Log actions...
117        location_field = self.location_fields[0]
118        grok.getSite().logger.info(
119            '%s - %s - %s - updated: %s'
120            % (self.name, filename, row[location_field], items_changed))
121        return
122
123    def checkConversion(self, row, mode='ignore'):
124        """Validates all values in row.
125        """
126        errs, inv_errs, conv_dict = super(
127            DocumentProcessorBase, self).checkConversion(row, mode=mode)
128        # We need to check if the class_name corresponds with the
129        # processor chosen. This is to avoid accidentally wrong imports.
130        if mode == 'create':
131            class_name = row.get('class_name', None)
132            if class_name != self.factory_name.strip('waeup.'):
133                errs.append(('class_name','wrong processor'))
134        return errs, inv_errs, conv_dict
135
136
137class PDFDocumentProcessor(DocumentProcessorBase):
138    """A batch processor for IPDFDocument objects.
139    """
140    util_name = 'pdfdocumentprocessor'
141    grok.name(util_name)
142
143    name = _('Public PDF Document Processor')
144    iface = IPDFDocument
145
146    factory_name = 'waeup.PDFDocument'
147
148
149class HTMLDocumentProcessor(DocumentProcessorBase):
150    """A batch processor for IHTMLDocument objects.
151    """
152    util_name = 'htmldocumentprocessor'
153    grok.name(util_name)
154
155    name = _('Public HTML Document Processor')
156    iface = IHTMLDocument
157
158    factory_name = 'waeup.HTMLDocument'
159
160
161class RESTDocumentProcessor(DocumentProcessorBase):
162    """A batch processor for IRESTDocument objects.
163    """
164    util_name = 'restdocumentprocessor'
165    grok.name(util_name)
166
167    name = _('Public REST Document Processor')
168    iface = IRESTDocument
169
170    factory_name = 'waeup.RESTDocument'
Note: See TracBrowser for help on using the repository browser.