Index: main/waeup.kofa/trunk/src/waeup/kofa/students/export.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/export.py	(revision 8413)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/export.py	(revision 8414)
@@ -33,9 +33,71 @@
                   'coursetickets', 'studentpayments')
 
-class StudentsExporter(grok.GlobalUtility, ExporterBase):
-    """Exporter for Students.
-    """
+def get_students(site):
+    """Get all students registered in catalog in `site`.
+    """
+    catalog = queryUtility(
+        ICatalog, context=site, name='students_catalog', default=None)
+    if catalog is None:
+        return []
+    students = catalog.searchResults(student_id=(None, None))
+    return students
+
+def get_studycourses(students):
+    """Get studycourses of `students`.
+    """
+    return [x.get('studycourse', None) for x in students
+            if x is not None]
+
+def get_levels(students):
+    """Get all studylevels of `students`.
+    """
+    levels = []
+    for course in get_studycourses(students):
+        for level in course.values():
+            levels.append(level)
+    return levels
+
+def get_tickets(students):
+    """Get all course tickets of `students`.
+    """
+    tickets = []
+    for level in get_levels(students):
+        for ticket in level.values():
+            tickets.append(ticket)
+    return tickets
+
+def get_payments(students):
+    """Get all payments of `students`.
+    """
+    payments = []
+    for student in students:
+        for payment in student.get('payments', {}).values():
+            payments.append(payment)
+    return payments
+
+
+class StudentExporterBase(ExporterBase):
+    """Exporter for students or related objects.
+
+    This is a baseclass.
+    """
+    grok.baseclass()
     grok.implements(ICSVStudentExporter)
     grok.provides(ICSVStudentExporter)
+
+    def export(self, values, filepath=None):
+        """Export `values`, an iterable, as CSV file.
+
+        If `filepath` is ``None``, a raw string with CSV data is returned.
+        """
+        writer, outfile = self.get_csv_writer(filepath)
+        for value in values:
+            self.write_item(value, writer)
+        return self.close_outfile(filepath, outfile)
+
+
+class StudentsExporter(grok.GlobalUtility, StudentExporterBase):
+    """Exporter for Students.
+    """
     grok.name('students')
 
@@ -46,14 +108,4 @@
     title = _(u'Students')
 
-    def export(self, students, filepath=None):
-        """Export `students`, an iterable, as CSV file.
-
-        If `filepath` is ``None``, a raw string with CSV data is returned.
-        """
-        writer, outfile = self.get_csv_writer(filepath)
-        for student in students:
-            self.write_item(student, writer)
-        return self.close_outfile(filepath, outfile)
-
     def export_all(self, site, filepath=None):
         """Export students into filepath as CSV data.
@@ -61,20 +113,13 @@
         If `filepath` is ``None``, a raw string with CSV data is returned.
         """
-        catalog = queryUtility(
-            ICatalog, context=site, name='students_catalog', default=None)
-        if catalog is None:
-            return self.export([], filepath)
-        students = catalog.searchResults(
-            student_id=(None, None))
-        return self.export(students, filepath)
+        return self.export(get_students(site), filepath)
 
     def export_student(self, student, filepath=None):
         return self.export([student], filepath=filepath)
 
-class StudentStudyCourseExporter(grok.GlobalUtility, ExporterBase):
+
+class StudentStudyCourseExporter(grok.GlobalUtility, StudentExporterBase):
     """Exporter for StudentStudyCourses.
     """
-    grok.implements(ICSVStudentExporter)
-    grok.provides(ICSVStudentExporter)
     grok.name('studentstudycourses')
 
@@ -98,15 +143,4 @@
             value, name, context=context)
 
-
-    def export(self, study_courses, filepath=None):
-        """Export `study_courses`, an iterable, as CSV file.
-
-        If `filepath` is ``None``, a raw string with CSV data is returned.
-        """
-        writer, outfile = self.get_csv_writer(filepath)
-        for study_course in study_courses:
-            self.write_item(study_course, writer)
-        return self.close_outfile(filepath, outfile)
-
     def export_all(self, site, filepath=None):
         """Export study courses into filepath as CSV data.
@@ -114,25 +148,15 @@
         If `filepath` is ``None``, a raw string with CSV data is returned.
         """
-        catalog = queryUtility(
-            ICatalog, context=site, name='students_catalog', default=None)
-        if catalog is None:
-            return self.export([], filepath)
-        students = catalog.searchResults(
-            student_id=(None, None))
-        study_courses = [x.get('studycourse', None) for x in students
-                         if x is not None]
-        return self.export(study_courses, filepath)
-
-    def export_student(self, student, filepath=None):
-        if 'studycourse' in student.keys():
-            return self.export([student['studycourse']], filepath=filepath)
-        return self.export([], filepath=filepath)
-
-
-class StudentStudyLevelExporter(grok.GlobalUtility, ExporterBase):
+        return self.export(get_studycourses(get_students(site)), filepath)
+
+    def export_student(self, student, filepath=None):
+        """Export studycourse of a single student object.
+        """
+        return self.export(get_studycourses([student]), filepath)
+
+
+class StudentStudyLevelExporter(grok.GlobalUtility, StudentExporterBase):
     """Exporter for StudentStudyLevels.
     """
-    grok.implements(ICSVStudentExporter)
-    grok.provides(ICSVStudentExporter)
     grok.name('studentstudylevels')
 
@@ -163,14 +187,4 @@
             value, name, context=context)
 
-    def export(self, study_levels, filepath=None):
-        """Export `study_levels`, an iterable, as CSV file.
-
-        If `filepath` is ``None``, a raw string with CSV data is returned.
-        """
-        writer, outfile = self.get_csv_writer(filepath)
-        for study_level in study_levels:
-            self.write_item(study_level, writer)
-        return self.close_outfile(filepath, outfile)
-
     def export_all(self, site, filepath=None):
         """Export study levels into filepath as CSV data.
@@ -178,29 +192,12 @@
         If `filepath` is ``None``, a raw string with CSV data is returned.
         """
-        catalog = queryUtility(
-            ICatalog, context=site, name='students_catalog', default=None)
-        if catalog is None:
-            return self.export([], filepath)
-        students = catalog.searchResults(
-            student_id=(None, None))
-        levels = []
-        study_courses = [x.get('studycourse', None) for x in students
-                         if x is not None]
-        for course in study_courses:
-            for level in course.values():
-                levels.append(level)
-        return self.export(levels, filepath)
-
-    def export_student(self, student, filepath=None):
-        if 'studycourse' in student.keys():
-            return self.export(student['studycourse'].values(),
-                               filepath=filepath)
-        return self.export([], filepath=filepath)
-
-class CourseTicketExporter(grok.GlobalUtility, ExporterBase):
+        return self.export(get_levels(get_students(site)), filepath)
+
+    def export_student(self, student, filepath=None):
+        return self.export(get_levels([student]), filepath)
+
+class CourseTicketExporter(grok.GlobalUtility, StudentExporterBase):
     """Exporter for CourseTickets.
     """
-    grok.implements(ICSVStudentExporter)
-    grok.provides(ICSVStudentExporter)
     grok.name('coursetickets')
 
@@ -226,14 +223,4 @@
             value, name, context=context)
 
-    def export(self, course_tickets, filepath=None):
-        """Export `course_tickets`, an iterable, as CSV file.
-
-        If `filepath` is ``None``, a raw string with CSV data is returned.
-        """
-        writer, outfile = self.get_csv_writer(filepath)
-        for ticket in course_tickets:
-            self.write_item(ticket, writer)
-        return self.close_outfile(filepath, outfile)
-
     def export_all(self, site, filepath=None):
         """Export course tickets into filepath as CSV data.
@@ -241,38 +228,13 @@
         If `filepath` is ``None``, a raw string with CSV data is returned.
         """
-        catalog = queryUtility(
-            ICatalog, context=site, name='students_catalog', default=None)
-        if catalog is None:
-            return self.export([], filepath)
-        students = catalog.searchResults(
-            student_id=(None, None))
-        levels = []
-        study_courses = [x.get('studycourse', None) for x in students
-                         if x is not None]
-        for course in study_courses:
-            for level in course.values():
-                levels.append(level)
-
-        tickets = []
-        for level in levels:
-            for ticket in level.values():
-                tickets.append(ticket)
-        return self.export(tickets, filepath)
-
-    def export_student(self, student, filepath=None):
-        if 'studycourse' not in student.keys():
-            return self.export([], filepath=filepath)
-        levels = student['studycourse'].values()
-        tickets = []
-        for level in levels:
-            for ticket in level.values():
-                tickets.append(ticket)
-        return self.export(tickets, filepath=filepath)
-
-class PaymentsExporter(grok.GlobalUtility, ExporterBase):
+        return self.export(get_tickets(get_students(site)), filepath)
+
+    def export_student(self, student, filepath=None):
+        return self.export(get_tickets([student]), filepath)
+
+
+class PaymentsExporter(grok.GlobalUtility, StudentExporterBase):
     """Exporter for OnlinePayment instances.
     """
-    grok.implements(ICSVStudentExporter)
-    grok.provides(ICSVStudentExporter)
     grok.name('studentpayments')
 
@@ -296,14 +258,4 @@
             value, name, context=context)
 
-    def export(self, payments, filepath=None):
-        """Export `payments`, an iterable, as CSV file.
-
-        If `filepath` is ``None``, a raw string with CSV data is returned.
-        """
-        writer, outfile = self.get_csv_writer(filepath)
-        for payment in payments:
-            self.write_item(payment, writer)
-        return self.close_outfile(filepath, outfile)
-
     def export_all(self, site, filepath=None):
         """Export payments into filepath as CSV data.
@@ -311,20 +263,6 @@
         If `filepath` is ``None``, a raw string with CSV data is returned.
         """
-        catalog = queryUtility(
-            ICatalog, context=site, name='students_catalog', default=None)
-        if catalog is None:
-            return self.export([], filepath)
-        students = catalog.searchResults(
-            student_id=(None, None))
-        payments = []
-        for student in students:
-            if not 'payments' in student.keys():
-                continue
-            for payment in student['payments'].values():
-                payments.append(payment)
-        return self.export(payments, filepath)
-
-    def export_student(self, student, filepath=None):
-        if not 'payments' in student.keys():
-            return self.export([], filepath=filepath)
-        return self.export(student['payments'].values(), filepath=filepath)
+        return self.export(get_payments(get_students(site)), filepath)
+
+    def export_student(self, student, filepath=None):
+        return self.export(get_payments([student]), filepath)
