source: main/waeup.sirp/trunk/src/waeup/sirp/applicants/applicant.py @ 7063

Last change on this file since 7063 was 7063, checked in by uli, 13 years ago

Merge changes from branch ulif-extimgstore back into trunk.
Beside external image storage also waeupdocs should work again.

File size: 6.8 KB
Line 
1##
2## applicants.py
3## Login : <uli@pu.smp.net>
4## Started on  Fri Jul 16 11:46:55 2010 Uli Fouquet
5## $Id$
6##
7## Copyright (C) 2010 Uli Fouquet & Henrik Bettermann
8## This program is free software; you can redistribute it and/or modify
9## it under the terms of the GNU General Public License as published by
10## the Free Software Foundation; either version 2 of the License, or
11## (at your option) any later version.
12##
13## This program is distributed in the hope that it will be useful,
14## but WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16## GNU General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with this program; if not, write to the Free Software
20## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21##
22import os
23import grok
24from grok import index
25from zope.component.interfaces import IFactory
26from zope.interface import implementedBy
27from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
28from waeup.sirp.app import University
29from waeup.sirp.image import WAeUPImageFile
30from waeup.sirp.imagestorage import DefaultFileStoreHandler
31from waeup.sirp.interfaces import (
32    IObjectHistory, IFileStoreHandler, IFileStoreNameChooser)
33from waeup.sirp.utils.helpers import attrs_to_fields
34from waeup.sirp.applicants.interfaces import (
35    IResultEntry, IApplicant, IApplicantEdit,
36    )
37
38
39def get_regno_or_ac(context):
40    reg_no = getattr(context, 'reg_no', None)
41    if reg_no is None:
42        return getattr(context, 'access_code', None)
43    return reg_no
44
45class ResultEntry(grok.Context):
46    grok.implements(IResultEntry)
47
48    def __init__(self, subject=None, score=None):
49        self.subject = subject
50        self.score = score
51
52class Applicant(grok.Model):
53    grok.implements(IApplicant,IApplicantEdit)
54    grok.provides(IApplicant)
55
56    def __init__(self):
57        super(Applicant, self).__init__()
58        IWorkflowInfo(self).fireTransition('init')
59        self.application_date = None
60        return
61
62    def loggerInfo(self, ob_class, comment=None):
63        target = self.__name__
64        return grok.getSite()['applicants'].logger_info(ob_class,target,comment)
65
66    @property
67    def state(self):
68        state = IWorkflowState(self).getState()
69        return state
70
71    @property
72    def history(self):
73        history = IObjectHistory(self)
74        return history
75
76# Set all attributes of Applicant required in IApplicant as field
77# properties. Doing this, we do not have to set initial attributes
78# ourselves and as a bonus we get free validation when an attribute is
79# set.
80Applicant = attrs_to_fields(Applicant)
81
82class ApplicantCatalog(grok.Indexes):
83    """A catalog indexing :class:`Applicant` instances in the ZODB.
84    """
85    grok.site(University)
86    grok.name('applicants_catalog')
87    grok.context(IApplicant)
88
89    access_code = index.Field(attribute='access_code')
90
91class ApplicantFactory(grok.GlobalUtility):
92    """A factory for applicants.
93    """
94    grok.implements(IFactory)
95    grok.name(u'waeup.Applicant')
96    title = u"Create a new applicant.",
97    description = u"This factory instantiates new applicant instances."
98
99    def __call__(self, *args, **kw):
100        return Applicant()
101
102    def getInterfaces(self):
103        return implementedBy(Applicant)
104
105
106#: The file id marker for applicant passport images
107APPLICANT_IMAGE_STORE_NAME = 'img-applicant'
108
109class ApplicantImageNameChooser(grok.Adapter):
110    """A file id chooser for :class:`Applicant` objects.
111
112    `context` is an :class:`Applicant` instance.
113
114    The :class:`ApplicantImageNameChooser` can build/check file ids
115    for :class:`Applicant` objects suitable for use with
116    :class:`ExtFileStore` instances. The delivered file_id contains
117    the file id marker for :class:`Applicant` object and the
118    registration number or access code of the context applicant. Also
119    the name of the connected applicant container will be part of the
120    generated file id.
121
122    This chooser is registered as an adapter providing
123    :class:`waeup.sirp.interfaces.IFileStoreNameChooser`.
124
125    File store name choosers like this one are only convenience
126    components to ease the task of creating file ids for applicant
127    objects. You are nevertheless encouraged to use them instead of
128    manually setting up filenames for applicants.
129
130    .. seealso:: :mod:`waeup.sirp.imagestorage`
131
132    """
133    grok.context(IApplicant)
134    grok.implements(IFileStoreNameChooser)
135
136    def checkName(self, name=None):
137        """Check whether the given name is a valid file id for the context.
138
139        Returns ``True`` only if `name` equals the result of
140        :meth:`chooseName`.
141        """
142        return name == self.chooseName()
143
144    def chooseName(self, name=None):
145        """Get a valid file id for applicant context.
146
147        *Example:*
148
149        For an applicant with registration no. ``'My_reg_no_1234'``
150        and stored in an applicants container called
151        ``'mycontainer'``, this chooser would create:
152
153          ``'__img-applicant__mycontainer/My_reg_no_1234.jpg'``
154
155        meaning that the passport image of this applicant would be
156        stored in the site-wide file storage in path:
157
158          ``mycontainer/My_reg_no_1234.jpg``
159
160        If the context applicant has no parent, ``'_default'`` is used
161        as parent name.
162        """
163        parent_name = getattr(
164            getattr(self.context, '__parent__', None),
165            '__name__', '_default')
166        marked_filename = '__%s__%s/%s.jpg' % (
167            APPLICANT_IMAGE_STORE_NAME,
168            parent_name, get_regno_or_ac(self.context))
169        return marked_filename
170
171
172class ApplicantImageStoreHandler(DefaultFileStoreHandler, grok.GlobalUtility):
173    """Applicant specific image handling.
174
175    This handler knows in which path in a filestore to store applicant
176    images and how to turn this kind of data into some (browsable)
177    file object.
178
179    It is called from the global file storage, when it wants to
180    get/store a file with a file id starting with
181    ``__img-applicant__`` (the marker string for applicant images).
182
183    Like each other file store handler it does not handle the files
184    really (this is done by the global file store) but only computes
185    paths and things like this.
186    """
187    grok.implements(IFileStoreHandler)
188    grok.name(APPLICANT_IMAGE_STORE_NAME)
189
190    def pathFromFileID(self, store, root, file_id):
191        """All applicants images are filed in directory ``applicants``.
192        """
193        marker, filename, basename, ext = store.extractMarker(file_id)
194        return os.path.join(root, 'applicants', filename)
195
196    def createFile(self, store, root, filename, file_id, file):
197        """Create a browsable file-like object.
198        """
199        # possible other actions: check for jpeg format
200        path = self.pathFromFileID(store, root, file_id)
201        return file, path, WAeUPImageFile(filename, file_id)
Note: See TracBrowser for help on using the repository browser.