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

Last change on this file since 12078 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
Line 
1:mod:`waeup.kofa.university.certificate` -- Certificates for Kofa
2******************************************************************
3
4.. module:: waeup.kofa.university.certificate
5
6Components that represent and manage certificates.
7
8.. :doctest:
9.. :layer: waeup.kofa.testing.KofaUnitTestLayer
10
11
12Content Classes (models and containers)
13=======================================
14
15
16:class:`Certificate`
17--------------------
18
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'']]]]]]])
20
21   Create a certificate object with the given parameters.
22
23   .. attribute:: grok.implements(ICertificate)
24
25   All parameters are optional:
26
27     >>> from waeup.kofa.university.certificate import Certificate
28     >>> mycertificate = Certificate()
29
30   Certificates have the attributes required by the `ICertificate` interface:
31
32     >>> from waeup.kofa.university.interfaces import ICertificate
33     >>> ICertificate.providedBy(mycertificate)
34     True
35
36     >>> from zope.interface.verify import verifyObject
37     >>> verifyObject(ICertificate, mycertificate)
38     True
39
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
44   .. attribute:: title
45
46      Each certificate has a title:
47
48        >>> mycertificate.title
49        u'Unnamed Certificate'
50
51   .. attribute:: code
52
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):
56
57        >>> mycertificate.code
58        u'NA'
59
60
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
98   .. method:: addCertCourse(course[, level=100,[ mandatory=True]])
99
100      Add a certificate course. A course is an object implementing
101      :class:`waeup.kofa.interfaces.ICourse`.
102
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
106      the 'real' course in the department container.
107
108   .. method:: delCertCourses(code)
109
110      Remove a certificate course from a certificate.
111
112      The certificate course must be given by its code number.
113
114:class:`CertificateCourse`
115--------------------------
116
117.. class:: CertificateCourse(course[, level=100[, mandatory=True]])
118
119   Create a certificate course.
120
121   A certificate course are held in
122   certificates and refer to an existing :class:`Course` instance held
123   elsewhere.
124
125   A certificate can require several certificate courses and one
126   certificate course can be required by several certificates.
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
136   .. attribute:: mandatory
137
138      A bool stating whether this course is required or optional to
139      get the certificate.
140
141
142
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
161     <waeup.kofa.university.certificate.Certificate object at 0x...>
162
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
168     >>> from waeup.kofa.university.certificate import CertificateFactory
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()
177     <implementedBy waeup.kofa.university.certificate.Certificate>
178
179
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
195     <waeup.kofa.university.certificate.CertificateCourse object at 0x...>
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
202     >>> from waeup.kofa.university.certificate import CertificateCourseFactory
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()
211     <implementedBy waeup.kofa.university.certificate.CertificateCourse>
212
213
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
223   Tries to remove all referring :class:`CertificateCourse`
224   instances that refer to a removed course.
225
226   To accomplish that, the parents of the removed course are looked up
227   for a certifcate container which contains a certificate course that
228   refers to the deleted course.
229
230   .. seealso:: :ref:`removecertificatecourses`
231
232   **handles:**
233     :class:`ICourse`
234
235   **event type:**
236     :class:`grok.IObjectRemovedEvent`
237
238Examples
239========
240
241Certificates
242------------
243
244We can create certificates:
245
246    >>> from waeup.kofa.university.certificate import Certificate
247    >>> mycertificate = Certificate()
248    >>> mycertificate
249    <waeup.kofa.university.certificate.Certificate object at 0x...>
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
258    <waeup.kofa.university.certificate.Certificate object at 0x...>
259
260CertificateCourses
261------------------
262
263:class:`CertificateCourse` instances comply with the
264:class:`ICertificateCourse` interface:
265
266    >>> from waeup.kofa.university.interfaces import ICertificateCourse
267    >>> from waeup.kofa.university.certificate import CertificateCourse
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
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
282    <waeup.kofa.university.certificate.CertificateCourse object at 0x...>
283
284.. _removecertificatecourses:
285
286Persistence of certificate courses
287----------------------------------
288
289If a certificate course requires a certain course and this is course
290is deleted, also the referring certificate course is deleted.
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)
343    >>> mycert.addCertCourse(mycourse)
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
356The certificate course we stored in the certificate is indeed a
357referrer of the course, not a copy of it:
358
359    >>> course = newdbroot['mydept'].courses['MYCOURSE']
360    >>> certcourse = newdbroot['mydept'].certificates['MYCERT']['MYCOURSE_100']
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.