source: main/waeup.kofa/trunk/src/waeup/kofa/university/certificate.txt @ 11476

Last change on this file since 11476 was 9826, checked in by Henrik Bettermann, 12 years ago

Rename delCertCourse. This method can delete more than one certificate course.

File size: 10.6 KB
RevLine 
[7819]1:mod:`waeup.kofa.university.certificate` -- Certificates for Kofa
[4920]2******************************************************************
[4290]3
[7811]4.. module:: waeup.kofa.university.certificate
[4325]5
[4313]6Components that represent and manage certificates.
7
[5140]8.. :doctest:
[7819]9.. :layer: waeup.kofa.testing.KofaUnitTestLayer
[4290]10
[4312]11
[4313]12Content Classes (models and containers)
13=======================================
[4290]14
[4322]15
[4313]16:class:`Certificate`
17--------------------
[4290]18
[5947]19.. class:: Certificate([code=u'NA',[ title=u'Unnamed Certificate',[ study_mode=None,[ start_level=None,[ end_level=None,[ application_category=None,[ m_prefix=u'']]]]]]])
[4290]20
[4313]21   Create a certificate object with the given parameters.
[4312]22
[4313]23   .. attribute:: grok.implements(ICertificate)
[4290]24
[4313]25   All parameters are optional:
[4290]26
[7811]27     >>> from waeup.kofa.university.certificate import Certificate
[4313]28     >>> mycertificate = Certificate()
[4290]29
[4313]30   Certificates have the attributes required by the `ICertificate` interface:
[4290]31
[7811]32     >>> from waeup.kofa.university.interfaces import ICertificate
[4313]33     >>> ICertificate.providedBy(mycertificate)
34     True
[4290]35
[4313]36     >>> from zope.interface.verify import verifyObject
37     >>> verifyObject(ICertificate, mycertificate)
38     True
[4290]39
[4322]40   Beside the attributes, certificates are containers for
41   certificate-courses (see :class:`CertificateCourse`). Each
42   certificate course can be accessed by the code of the course it wraps.
43
[4313]44   .. attribute:: title
[4290]45
[4313]46      Each certificate has a title:
[4290]47
[4313]48        >>> mycertificate.title
49        u'Unnamed Certificate'
[4290]50
[4313]51   .. attribute:: code
[4290]52
[4313]53      Each certificate holds a code, which might be a shortcut or
54      abbreviation of the real certificate name. By default the code
55      is ``NA`` (=not assigned):
[4312]56
[4313]57        >>> mycertificate.code
58        u'NA'
[4312]59
60
[4313]61   .. attribute:: study_mode
62
63      Each :class:`Certificate` instance has a study mode:
64
65        >>> print mycertificate.study_mode
66        None
67
68      .. XXX: This is not a proper description
69
70   .. attribute:: start_level
71
72      Each :class:`Certificate` instance has a start level:
73
74        >>> print mycertificate.start_level
75        None
76
77      .. XXX: This is not a proper description
78
79   .. attribute:: end_level
80
81      Each :class:`Certificate` instance has a end level:
82
83        >>> print mycertificate.end_level
84        None
85
86      .. XXX: This is not a proper description
87   
88
89   .. attribute:: application_category
90
91      Each :class:`Certificate` instance has an application category:
92
93        >>> print mycertificate.application_category
94        None
95
96      .. XXX: This is not a proper description
97
[8920]98   .. method:: addCertCourse(course[, level=100,[ mandatory=True]])
[4313]99
[8920]100      Add a certificate course. A course is an object implementing
[7811]101      :class:`waeup.kofa.interfaces.ICourse`.
[4322]102
[8920]103      Please don't be confused by the term 'certificate course'.
104      As course objects will normaly be  stored
105      in a department, the certificate course refers to
[5978]106      the 'real' course in the department container.
[4322]107
[9826]108   .. method:: delCertCourses(code)
[4322]109
[8920]110      Remove a certificate course from a certificate.
[4322]111
[8920]112      The certificate course must be given by its code number.
[4322]113
114:class:`CertificateCourse`
115--------------------------
116
[7665]117.. class:: CertificateCourse(course[, level=100[, mandatory=True]])
[4322]118
[8920]119   Create a certificate course.
[4322]120
[8920]121   A certificate course are held in
[4322]122   certificates and refer to an existing :class:`Course` instance held
123   elsewhere.
124
[8920]125   A certificate can require several certificate courses and one
126   certificate course can be required by several certificates.
[4322]127
128   .. attribute:: course
129
130      An instance of :class:`ICourse`.
131
132   .. attribute:: level
133
134      An integer telling the level to which this course applies.
135
[7665]136   .. attribute:: mandatory
[4322]137
138      A bool stating whether this course is required or optional to
139      get the certificate.
140
141
142
[4313]143Utilities
144=========
145
146:class:`CertificateFactory`
147---------------------------
148
149.. class:: CertificateFactory()
150
151   .. attribute:: grok.name(u'waeup.Certificate')
152
153   .. attribute:: grok.implements(IFactory)
154
155   A named utility to deliver new instances of :class:`Certificate`
156   without the need to import the implementation before:
157
158     >>> from zope.component import createObject
159     >>> mycertificate = createObject(u'waeup.Certificate')
160     >>> mycertificate
[7811]161     <waeup.kofa.university.certificate.Certificate object at 0x...>
[4313]162
[4384]163   The factory complies with the specifications from the
164   :class:`IFactory` insterface:
165
166     >>> from zope.interface.verify import verifyClass
167     >>> from zope.component.interfaces import IFactory
[7811]168     >>> from waeup.kofa.university.certificate import CertificateFactory
[4384]169     >>> verifyClass(IFactory, CertificateFactory)
170     True
171
172   This means also, that we can get the interfaces of the created
173   object from the factory:
174
175     >>> certificate_factory = CertificateFactory()
176     >>> certificate_factory.getInterfaces()
[7811]177     <implementedBy waeup.kofa.university.certificate.Certificate>
[4384]178
179
[4386]180:class:`CertificateCourseFactory`
181---------------------------------
182
183.. class:: CertificateCourseFactory()
184
185   .. attribute:: grok.name(u'waeup.CertificateCourse')
186
187   .. attribute:: grok.implements(IFactory)
188
189   A named utility to deliver new instances of :class:`CertificateCourse`
190   without the need to import the implementation before:
191
192     >>> from zope.component import createObject
193     >>> mycertificatecourse = createObject(u'waeup.CertificateCourse')
194     >>> mycertificatecourse
[7811]195     <waeup.kofa.university.certificate.CertificateCourse object at 0x...>
[4386]196
197   The factory complies with the specifications from the
198   :class:`IFactory` insterface:
199
200     >>> from zope.interface.verify import verifyClass
201     >>> from zope.component.interfaces import IFactory
[7811]202     >>> from waeup.kofa.university.certificate import CertificateCourseFactory
[4386]203     >>> verifyClass(IFactory, CertificateCourseFactory)
204     True
205
206   This means also, that we can get the interfaces of the created
207   object from the factory:
208
209     >>> certcourse_factory = CertificateCourseFactory()
210     >>> certcourse_factory.getInterfaces()
[7811]211     <implementedBy waeup.kofa.university.certificate.CertificateCourse>
[4386]212
213
[4332]214Event Subscribers
215=================
216
217.. function:: removedCourseHandler(course, event)
218
219   An event subscriber triggered for
220   :class:`grok.IObjectRemovedEvent`s, when an :class:`ICourse`
221   instance is removed from a container.
222
[5978]223   Tries to remove all referring :class:`CertificateCourse`
224   instances that refer to a removed course.
[4332]225
226   To accomplish that, the parents of the removed course are looked up
[8920]227   for a certifcate container which contains a certificate course that
[5978]228   refers to the deleted course.
[4332]229
230   .. seealso:: :ref:`removecertificatecourses`
231
232   **handles:**
233     :class:`ICourse`
234
235   **event type:**
236     :class:`grok.IObjectRemovedEvent`
237
[4313]238Examples
239========
240
[4322]241Certificates
242------------
[4313]243
244We can create certificates:
245
[7811]246    >>> from waeup.kofa.university.certificate import Certificate
[4313]247    >>> mycertificate = Certificate()
248    >>> mycertificate
[7811]249    <waeup.kofa.university.certificate.Certificate object at 0x...>
[4313]250
251Another way to create certificates is by asking for a factory called
252``waeup.Certificate``. This way we can create a factory without
253importing a class:
254
255    >>> from zope.component import createObject
256    >>> mycertificate = createObject(u'waeup.Certificate')
257    >>> mycertificate
[7811]258    <waeup.kofa.university.certificate.Certificate object at 0x...>
[4313]259
[4322]260CertificateCourses
261------------------
262
263:class:`CertificateCourse` instances comply with the
264:class:`ICertificateCourse` interface:
265
[7811]266    >>> from waeup.kofa.university.interfaces import ICertificateCourse
267    >>> from waeup.kofa.university.certificate import CertificateCourse
[4322]268    >>> mycertcourse = CertificateCourse(None, 200, False)
269    >>> ICertificateCourse.providedBy(mycertcourse)
270    True
271
272    >>> from zope.interface.verify import verifyObject
273    >>> verifyObject(ICertificateCourse, mycertcourse)
274    True
275
[4332]276Also instances of :class:`CertificateCourse` can be created by asking
277the component architechture:
278
279    >>> from zope.component import createObject
280    >>> mycertcourse = createObject(u'waeup.CertificateCourse')
281    >>> mycertcourse
[7811]282    <waeup.kofa.university.certificate.CertificateCourse object at 0x...>
[4332]283
284.. _removecertificatecourses:
285
286Persistence of certificate courses
287----------------------------------
288
289If a certificate course requires a certain course and this is course
[5978]290is deleted, also the referring certificate course is deleted.
[4332]291
292We setup a data structure that reflects typical usage. It looks like
293this::
294
295    Department-Instance
296    |
297    +---> courses
298    |        |
299    |        +--------------------> Course-Instance
300    |                                        ^
301    +---> certificates                       |
302             |                               |
303             +-----> Certificate-Instance    |
304                        |                    |
305                        +------> Certificate-Course
306
307The certifcate-Course here refers to a Course-Instance.
308
309In Python we build such a structure like this (from top to bottom):
310
311    >>> from zope.component import createObject
312    >>> mydept = createObject('waeup.Department')
313
314In real world use this data will be stored in a ZODB. We setup our own
315litte ZODB backend (which is easy!):
316
317    >>> from ZODB import FileStorage, DB
318    >>> dbpath = 'tinyData.fs'
319    >>> class TinyZODB(object):
320    ...   def __init__(self, path=dbpath):
321    ...     self.storage = FileStorage.FileStorage(path)
322    ...     self.db = DB(self.storage)
323    ...     self.connection = self.db.open()
324    ...     self.dbroot = self.connection.root()
325    ...   def close(self):
326    ...     self.connection.close()
327    ...     self.db.close()
328    ...     self.storage.close()
329
330Now we can use this ZODB as backend database and store our data
331structure:
332
333    >>> import transaction
334    >>> db = TinyZODB()
335    >>> dbroot = db.dbroot
336    >>> dbroot['mydept'] = mydept
337    >>> mycourse = createObject('waeup.Course')
338    >>> mycourse.code = 'MYCOURSE'
339    >>> mydept.courses.addCourse(mycourse)
340    >>> mycert = createObject('waeup.Certificate')
341    >>> mycert.code = 'MYCERT'
342    >>> mydept.certificates.addCertificate(mycert)
[8920]343    >>> mycert.addCertCourse(mycourse)
[4332]344
345    >>> transaction.commit()
346
347The data is now stored in the ZODB. We can close the DB, reopen it
348later and the data will still be there:
349
350    >>> db.close()
351    >>> newdb = TinyZODB()
352    >>> newdbroot = newdb.dbroot
353    >>> list(newdbroot)
354    ['mydept']
355
[8920]356The certificate course we stored in the certificate is indeed a
[5978]357referrer of the course, not a copy of it:
[4332]358
359    >>> course = newdbroot['mydept'].courses['MYCOURSE']
[4489]360    >>> certcourse = newdbroot['mydept'].certificates['MYCERT']['MYCOURSE_100']
[4332]361    >>> certcourse.course is course
362    True
363
364So, we can be sure that modifications to the course are immediately
365reflected in the certcourse.
366
Note: See TracBrowser for help on using the repository browser.