Index: WAeUP_SRP/trunk/WAeUPTables.py
===================================================================
--- WAeUP_SRP/trunk/WAeUPTables.py	(revision 2093)
+++ WAeUP_SRP/trunk/WAeUPTables.py	(revision 2094)
@@ -25,4 +25,10 @@
 from AccessControl import ClassSecurityInfo
 from Products.CMFCore.permissions import ModifyPortalContent
+from Products.CMFCore.utils import getToolByName
+from Products.CMFCore.CatalogTool import CatalogTool
+from Products.CPSSchemas.StorageAdapter import MappingStorageAdapter
+from Products.CPSSchemas.DataStructure import DataStructure
+from Products.CPSSchemas.DataModel import DataModel
+from Products.AdvancedQuery import Eq, Between, Le,In
 import urllib
 import DateTime,time
@@ -32,6 +38,4 @@
 p_home = Globals.package_home(globals())
 i_home = Globals.INSTANCE_HOME
-from Products.CMFCore.CatalogTool import CatalogTool
-from Products.AdvancedQuery import Eq, Between, Le,In
 
 ADDING_SHEDULED = "adding_sheduled"
@@ -53,6 +57,12 @@
     implements(IWAeUPTable)
     security = ClassSecurityInfo()
-
-    def refreshCatalog(self, clear=0, pghandler=None):
+    meta_type = None
+    
+    def __init__(self,name=None):
+        if name ==  None:
+            name = self.name
+        ZCatalog.__init__(self,name)
+        
+    def refreshCatalog(self, clear=0, pghandler=None): ###(
         """ don't refresh for a normal table """
 
@@ -62,5 +72,7 @@
               '/manage_catalogAdvanced?manage_tabs_message=Catalog%20refresh%20not%20implemented')
 
-    def manage_catalogClear(self, REQUEST=None, RESPONSE=None, URL1=None):
+###)
+
+    def manage_catalogClear(self, REQUEST=None, RESPONSE=None, URL1=None): ###(
         """ clears the whole enchilada """
 
@@ -76,5 +88,7 @@
               '/manage_catalogAdvanced?manage_tabs_message=Catalog%20cleared')
 
-    def addRecord(self, **data):
+###)
+
+    def addRecord(self, **data): ###(
         # The uid is the same as "bed".
         uid = data[self.key]
@@ -85,4 +99,6 @@
         return uid
 
+###)
+
     def deleteRecord(self, uid):
         self.uncatalog_object(uid)
@@ -91,5 +107,5 @@
         raise NotImplemented
 
-    def modifyRecord(self, record=None, **data):
+    def modifyRecord(self, record=None, **data): ###(
         #records = self.searchResults(uid=uid)
         uid = data[self.key]
@@ -109,7 +125,9 @@
         self.catalog_object(dict2ob(record_data), uid)
 
-    def reindexIndex(self, name, REQUEST,pghandler=None):
+###)
+
+    def reindexIndex(self, name, REQUEST,pghandler=None): ###(
         if isinstance(name, str):
-            name = (name,)
+            name =  (name,)
         paths = self._catalog.uids.items()
         i = 0
@@ -125,5 +143,7 @@
                                 update_metadata=0)
 
-    security.declareProtected(ModifyPortalContent,"exportAllRecords")
+###)
+
+    security.declareProtected(ModifyPortalContent,"exportAllRecords") ###(
     def exportAllRecords(self):
         "export a WAeUPTable"
@@ -144,13 +164,142 @@
         current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
         open("%s/import/%s-%s.csv" % (i_home,self.getId(),current),"w+").write('\n'.join(csv))
-    ###)
+
+###)
+
+    security.declarePrivate("_import") ###(
+    def _import(self,filename,schema,layout, mode,logger):
+        "import data from csv"
+        import transaction
+        import random
+        pm = self.portal_membership
+        member = pm.getAuthenticatedMember()
+        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
+        import_fn = "%s/import/%s.csv" % (i_home,filename)
+        imported_fn = "%s/import/%s_imported%s.csv" % (i_home,filename,current)
+        not_imported_fn = "%s/import/%s_not_imported%s.csv" % (i_home,filename,current)
+        start = True
+        tr_count = 1
+        total_imported = 0
+        total_not_imported = 0
+        total = 0
+        iname =  "%s" % filename
+        if schema is None:
+            em = 'No schema specified'
+            logger.error(em)
+            return em
+        if layout is None:
+            em = 'No layout specified'
+            logger.error(em)
+            return em
+        validators = {}
+        for widget in layout.keys():
+            validators[widget] = layout[widget].validate
+        # if mode == 'edit':
+        #     importer = self.importEdit
+        # elif mode == 'add':
+        #     importer = self.importAdd
+        # else:
+        #     importer = None
+        not_imported = []
+        imported = []
+        valid_records = []
+        invalid_records = []
+        d = {}
+        d['mode'] = mode
+        d['imported'] = total_imported
+        d['not_imported'] = total_not_imported
+        d['valid_records'] = valid_records
+        d['invalid_records'] = invalid_records
+        d['import_fn'] = import_fn
+        d['imported_fn'] = imported_fn
+        d['not_imported_fn'] = not_imported_fn
+        try:
+            items = csv.DictReader(open(import_fn,"rb"))
+        except:
+            em = 'Error reading %s.csv' % filename
+            logger.error(em)
+            return d
+        for item in items:
+            if start:
+                start = False
+                logger.info('%s starts import from %s.csv' % (member,filename))
+                #import_keys = [k for k in item.keys() if not k.startswith('ignore')]
+                attrs = csv.reader(open("%s/import/%s.csv" % (i_home,filename),"rb")).next()
+                import_keys = [k for k in attrs if not (k.startswith('ignore') or k.isupper())]
+                diff2schema = set(import_keys).difference(set(schema.keys()))
+                diff2layout = set(import_keys).difference(set(layout.keys()))
+                if diff2layout:
+                    em = "not ignorable key(s) %s found in heading" % diff2layout
+                    logger.info(em)
+                    return d
+                s = ','.join(['"%s"' % fn for fn in import_keys])
+                open(not_imported_fn,"a").write(s + ',"Error"'+ '\n')
+                #s = '"id",' + s
+                open(imported_fn,"a").write(s + '\n')
+                format = ','.join(['"%%(%s)s"' % fn for fn in import_keys])
+                format_error = format + ',"%(Error)s"'
+                #format = '"%(id)s",'+ format
+                adapters = [MappingStorageAdapter(schema, item)]
+            dm = DataModel(item, adapters,context=self)
+            ds = DataStructure(data=item,datamodel=dm)
+            error_string = ""
+            for k in import_keys:
+                if not validators[k](ds,mode=mode):
+                    error_string += " %s : %s" % (k,ds.getError(k))
+            # if not error_string and importer:
+            #     item.update(dm)
+            #     item['id'],error = importer(item)
+            #     if error:
+            #         error_string += error
+            if error_string:
+                item['Error'] = error_string
+                invalid_records.append(dm)
+                not_imported.append(format_error % item)
+                total_not_imported += 1
+            else:
+                em = format % item
+                valid_records.append(dm)
+                imported.append(em)
+                #logger.info("%(total_imported)d of %(total)d %(em)s" % vars())
+                tr_count += 1
+                total_imported += 1
+            total += 1
+            # if importer and total_imported and not total_imported % 1000:
+            #     transaction.commit()
+            #     if len(not_imported) > 0:
+            #         open(not_imported_fn,"a").write('\n'.join(not_imported) + '\n')
+            #         not_imported = []
+            #     if len(imported) > 0:
+            #         open(imported_fn,"a").write('\n'.join(imported) + '\n')
+            #         imported = []
+            #     em = '%d transactions committed\n' % (tr_count)
+            #     regs = []
+            #     logger.info(em)
+            #     tr_count = 0
+        if len(imported) > 0:
+            open(imported_fn,"a").write('\n'.join(imported))
+        if len(not_imported) > 0:
+            open(not_imported_fn,"a").write('\n'.join(not_imported))
+        #em = "Imported: %d, not imported: %d of total %d" % (total_imported,total_not_imported,total)
+        d['imported'] = total_imported
+        d['not_imported'] = total_not_imported
+        d['valid_records'] = valid_records
+        d['invalid_records'] = invalid_records
+        d['imported_fn'] = imported_fn
+        d['not_imported_fn'] = not_imported_fn
+        #logger.info(em)
+        return d
+    ###)
+###)
 
 class AccommodationTable(WAeUPTable): ###(
 
     meta_type = 'WAeUP Accommodation Tool'
-    name = "accommodation"
+    name = "portal_accommodation"
     key = "bed"
-    def __init__(self):
-        WAeUPTable.__init__(self, 'portal_accommodation')
+    def __init__(self,name=None):
+        if name ==  None:
+            name = self.name
+        WAeUPTable.__init__(self, name)
 
     def searchAndReserveBed(self, student_id,bed_type):
@@ -177,8 +326,10 @@
     from ZODB.POSException import ConflictError
     meta_type = 'WAeUP Pin Tool'
-    name = "pins"
+    name = "portal_pins"
     key = 'pin'
-    def __init__(self):
-        WAeUPTable.__init__(self, 'portal_pins')
+    def __init__(self,name=None):
+        if name ==  None:
+            name = self.name
+        WAeUPTable.__init__(self, name)
 
 
@@ -222,11 +373,63 @@
 
     meta_type = 'WAeUP PumeResults Tool'
-    name = "pumeresults"
+    name = "portal_pumeresults"
     key = "jamb_reg_no"
-    def __init__(self):
-        WAeUPTable.__init__(self, 'portal_pumeresults')
+    def __init__(self,name=None):
+        if name ==  None:
+            name = self.name
+        WAeUPTable.__init__(self, name)
 
 
 InitializeClass(PumeResultsTable)
+
+###)
+
+class ApplicantsCatalog(WAeUPTable): ###(
+
+    meta_type = 'New Students'
+    name = "applicants_catalog"
+    key = "reg_no"
+    security = ClassSecurityInfo()
+    
+    def __init__(self,name=None):
+        if name ==  None:
+            name = self.name
+        WAeUPTable.__init__(self, name)
+
+    security.declareProtected(ModifyPortalContent,"importCSV")###(
+    def importCSV(self,filename="JAMB_data",
+                  schema_id="application",
+                  layout_id="application",
+                  mode='add'):
+        """ import JAMB data """
+        stool = getToolByName(self, 'portal_schemas')
+        ltool = getToolByName(self, 'portal_layouts')
+        schema = stool._getOb(schema_id)
+        if schema is None:
+            em = 'No such schema %s' % schema_id
+            logger.error(em)
+            return
+        layout = ltool._getOb(layout_id)
+        if layout is None:
+            em = 'No such layout %s' % layout_id
+            logger.error(em)
+            return
+        logger = logging.getLogger('WAeUPTables.Applicants.importCSV')
+        d = self._import(filename,schema,layout,mode,logger)
+        if len(d['valid_records']) > 0:
+            for record in d['valid_records']:
+                #import pdb;pdb.set_trace()
+                if mode == "add":
+                    self.addRecord(**dict(record.items()))
+                    logger.info("added %s" % record.items())
+                elif mode == "edit":
+                    self.modifyRecord(**dict(record.items()))
+                    logger.info("edited %s" % record.items())
+                else:
+                    logger.info("invalid mode: %s" % mode)
+        logger.info("%(mode)sed %(imported)d records, invalid written to %(not_imported_fn)s" % d)
+###)
+
+InitializeClass(ApplicantsCatalog)
 
 ###)
@@ -281,6 +484,8 @@
     ###)
 
-    def __init__(self):
-        WAeUPTable.__init__(self, 'students_catalog')
+    def __init__(self,name=None):
+        if name ==  None:
+            name = self.name
+        WAeUPTable.__init__(self, name)
         return
 
@@ -657,8 +862,10 @@
 
     meta_type = 'WAeUP Courses Catalog'
-    name = "courses_catalog"
+    name =  "courses_catalog"
     key = "code"
-    def __init__(self):
-        WAeUPTable.__init__(self, 'courses_catalog')
+    def __init__(self,name=None):
+        if name ==  None:
+            name =  self.name
+        WAeUPTable.__init__(self, name)
 
     def manage_catalogReindex(self, REQUEST, RESPONSE, URL1): ###(
@@ -792,10 +999,13 @@
     name = "course_results"
     key = "key" #student_id + level + course_id
-    def __init__(self):
-        WAeUPTable.__init__(self, 'course_results')
+    def __init__(self,name=None):
+        if name ==  None:
+            name = self.name
+        WAeUPTable.__init__(self, name)
         self._queue = []
         
     def addRecord(self, **data): ###(
-        # The uid is the same as "bed".
+        """add one record"""
+        
         uid = key = "%(student_id)s|%(level_id)s|%(course_id)s" % data
         if key in self._queue:
@@ -813,4 +1023,50 @@
         return uid
     ###)
+    
+    # def _p_resolveConflict(self, oldstate, committed, newstate):
+    #     # Apply the changes made in going from old to newstate to
+    #     # committed
+        
+    #     # Note that in the case of undo, the olddata is the data for
+    #     # the transaction being undone and newdata is the data for the
+    #     # transaction previous to the undone transaction.
+
+    #     # Find the conflict policy on the new state to make sure changes
+    #     # to it will be applied
+
+    #     # Committed is always the currently committed data.
+    #     import pdb;pdb.set_trace()
+    #     oldstate_data  =  oldstate['_queue']
+    #     committed_data = committed['_queue']
+    #     newstate_data  =  newstate['_queue']
+
+    #     # Merge newstate changes into committed
+    #     for uid, new in newstate_data.items():
+
+    #         # Decide if this is a change
+    #         old = oldstate_data.get(uid)
+    #         current = committed_data.get(uid)
+
+
+    def addMultipleRecords(self, records): ###(
+        """add many records"""
+        added_keys = []
+        for data in records:
+            uid = key = "%(student_id)s|%(level_id)s|%(course_id)s" % data
+            added_keys.append(key)
+            if key in self._queue:
+                return uid
+            data['queue_status'] = ADDING_SHEDULED
+            data['%s' % self.key] = uid
+            res = self.searchResults({"%s" % self.key : uid})
+            if len(res) > 0:
+                raise ValueError("More than one record with uid %s" % uid)
+            self.catalog_object(dict2ob(data), uid=uid)
+        if not hasattr(self,'_queue'):
+            self._queue = added_keys
+        self._queue.extend(added_keys)
+        self._p_changed = 1
+        return uid
+    ###)
 
     def deleteRecord(self, uid): ###(
@@ -820,10 +1076,52 @@
     ###)
 
+    def updateCourseResults(self,student_id,level_id,portal_catalog_results,course_results): ###(
+        # query = Eq('path',"%s/campus/students/%s/study_course/%s" % 
+        #            (self.portal_url.getPortalPath(),
+        #             student_id,
+        #             level_id)) &\
+        #             Eq('portal_type', "StudentCourseResult")
+        # level_results = self.portal_catalog_real.evalAdvancedQuery(query)
+        # level_results = [r for r in course_results 
+        #                  if level_id in r.relative_path.split('/')]
+        course_results_ids = [cr.getId for cr in course_results]
+        for r in portal_catalog_results:
+            if r.getId in course_results_ids:
+                continue
+            course_result_doc = r.getObject().getContent()
+            data = {}
+            course_id = r.getId
+            for field in self.schema():
+                data[field] = getattr(course_result_doc,field,'')
+            data['key'] = key = "%(student_id)s|%(level_id)s|%(course_id)s" % vars()
+            data['student_id'] = student_id 
+            data['level_id'] = level_id 
+            data['queue_status'] = OBJECT_CREATED
+            data['code'] = course_id 
+            self.catalog_object(dict2ob(data), uid=key)
+        query = Eq('student_id',student_id) & Eq('level_id', level_id)
+        return self.course_results.evalAdvancedQuery(query)
+    ###)
+
     def getCourses(self,student_id,level_id): ###(
+        level_path = "%s/campus/students/%s/study_course/%s" % (self.portal_url.getPortalPath(),
+                                                                student_id,
+                                                                level_id)
+        # portal_catalog_query = Eq('path',level_path) &\
+        #                        Eq('portal_type', "StudentCourseResult")
+        # portal_catalog_results = self.portal_catalog_real.evalAdvancedQuery(portal_catalog_query)
+        portal_catalog_results = self.portal_catalog(path = level_path,
+                                                     portal_type = "StudentCourseResult")
         query = Eq('student_id',student_id) & Eq('level_id', level_id)
+        course_results = self.course_results.evalAdvancedQuery(query)
+        if len(course_results) != len(portal_catalog_results):
+            course_results = self.updateCourseResults(student_id,
+                                                      level_id,
+                                                      portal_catalog_results,
+                                                      course_results)
         carry_overs = []
         normal = []
         credits = 0 
-        for brain in self.course_results.evalAdvancedQuery(query):
+        for brain in course_results:
             d = {}
             credits += int(brain.credits) 
@@ -834,6 +1132,13 @@
             if brain.core_or_elective:
                 d['coe'] = 'Core'
-            d['title'] = self.courses_catalog.evalAdvancedQuery(Eq('code',brain.code))[0].title
-            if brain.code.endswith('_co'):
+            id = code = d['id'] = brain.code
+            is_carry_over = False
+            if code.endswith('_co'):
+                is_carry_over = True
+                code = code[:-3]
+            d['code'] = code
+            d['title'] = self.courses_catalog.evalAdvancedQuery(Eq('code',code))[0].title
+            if is_carry_over:
+                d['coe'] = 'Core'
                 carry_overs.append(d)
             else:
@@ -936,6 +1241,5 @@
             course_result_brain = course_results[i]
             path_list = course_result_brain.getPath().split('/')
-            course_result_object = course_result_brain.getObject()
-            course_result_doc = course_result_object.getContent()
+            course_result_doc = course_result_brain.getObject().getContent()
             data = {}
             level_id = path_list[-2]
@@ -972,9 +1276,19 @@
                 raise KeyError("No record for uid %s" % uid)
             record = records[0]
-            #import pdb;pdb.set_trace()
             for field in ('core_or_elective','score'):
                 value = getattr(object,field,None)
                 data[field] = value
-            self.modifyRecord(record,**data)
+            try:
+                self.modifyRecord(record,**data)
+            except KeyError:
+                pass
+        if pt == 'StudentStudyLevel' and event_type == "sys_del_object":
+            #import pdb;pdb.set_trace()
+            student_id = rpl[-3]
+            level_id = rpl[-1]
+            res = self.searchResults(student_id = student_id,
+                                     level_id = level_id)
+            for cr in res:
+                self.deleteRecord(cr.key)
     ###)
 
@@ -987,6 +1301,8 @@
     name = "online_payments_import"
     key = "order_id"
-    def __init__(self):
-        WAeUPTable.__init__(self, self.name)
+    def __init__(self,name=None):
+        if name ==  None:
+            name = self.name
+        WAeUPTable.__init__(self, name)
 
 
@@ -999,6 +1315,8 @@
     name = "returning_import"
     key = "matric_no"
-    def __init__(self):
-        WAeUPTable.__init__(self, 'returning_import')
+    def __init__(self,name=None):
+        if name ==  None:
+            name = self.name
+        WAeUPTable.__init__(self, name)
 
 
@@ -1011,6 +1329,8 @@
     name = "results_import"
     key = "key"
-    def __init__(self):
-        WAeUPTable.__init__(self, 'results_import')
+    def __init__(self,name=None):
+        if name ==  None:
+            name = self.name
+        WAeUPTable.__init__(self, name)
 
 
@@ -1024,6 +1344,8 @@
     name = "students_catalog"
     key = "id"
-    def __init__(self):
-        WAeUPTable.__init__(self, 'payments_catalog')
+    def __init__(self,name=None):
+        if name ==  None:
+            name = self.name
+        WAeUPTable.__init__(self, name)
 
 
Index: WAeUP_SRP/trunk/WAeUPTool.py
===================================================================
--- WAeUP_SRP/trunk/WAeUPTool.py	(revision 2093)
+++ WAeUP_SRP/trunk/WAeUPTool.py	(revision 2094)
@@ -44,5 +44,5 @@
 p_home = package_home(globals())
 i_home = INSTANCE_HOME
-import DateTime
+import DateTime,time
 import logging
 import transaction
@@ -95,4 +95,160 @@
 
 ###)
+
+    security.declareProtected(ModifyPortalContent,'measureOaT') ###(
+    def measureOaT(self,method="a",probe="1000",nr_pts="1"):
+        """measure Object access Time"""
+        import random
+        if hasattr(self,'portal_catalog_real'):
+            aq_portal = self.portal_catalog_real.evalAdvancedQuery
+        else:
+            aq_portal = self.portal_catalog.evalAdvancedQuery
+        nr_pts = int(nr_pts)
+        probe = int(probe)
+        intervall = probe/10
+        objects = ("application","clearance","personal")
+        portal_types = ("StudentApplication","StudentClearance","StudentPersonal")
+        #i = random.randrange(num_objects)
+        count = 0
+        found = 0
+        not_found = 0
+        t_found = 0
+        t_not_found = 0
+        time_found = time_not_found = 0.0
+        t_time_found = t_time_not_found = 0.0
+        accessed = []
+        t_min = 1000
+        t_max = 0
+        #import pdb;pdb.set_trace()
+        students = self.portal_catalog(portal_type="Student")
+        num_students = len(students)
+        if method == "d":
+            query = Eq('path','/uniben/campus/students') & In('portal_type',portal_types[:nr_pts])
+            res = aq_portal(query)
+            brains = {}
+            for r in res:
+                sid = r.relative_path.split('/')[-2]
+                if brains.has_key(sid):
+                    brains[sid][r.portal_type] = r
+                else:
+                    brains[sid] = {r.portal_type : r}
+            brains_list = brains.keys()
+            num_objects = len(brains_list)
+        else:
+            num_objects = num_students
+        print "="*40
+        print "method: %s probes: %d nr_pts: %d num_objects: %d" % (method,
+                                                                        probe,
+                                                                        nr_pts,
+                                                                        num_objects)
+        print "nr found/not time found/not min/max"
+        elapse = time.time()
+        i_elapse = time.time()
+        c_elapse = time.clock()
+        for c in range(1,probe + 1):
+            i = random.randrange(num_objects)
+            if method in ('a','b','c'):
+                student_brain = students[i]
+            elif method == "d":
+                #import pdb;pdb.set_trace()
+                student_brain = brains[brains_list[i]]
+            if method == "c":
+                query = Eq('path',student_brain.getPath()) & In('portal_type',portal_types[:nr_pts])
+                res = aq_portal(query)
+                this_portal_types = [r.portal_type for r in res]
+            for i in range(nr_pts):
+                oid = objects[i]
+                if method == "a":
+                    try:
+                        student_path = student_brain.getPath()
+                        path = "%s/%s" % (student_path,oid)
+                        doc = self.unrestrictedTraverse(path).getContent()
+                        found += 1
+                        i_time = time.time() - i_elapse
+                        time_found += i_time
+                    except:
+                        not_found += 1
+                        i_time = time.time() - i_elapse
+                        time_not_found += i_time
+                        pass
+                elif method == "b":
+                    try:
+                        student_object = student_brain.getObject()
+                        doc = getattr(student_object,oid).getContent()
+                        found += 1
+                        i_time = time.time() - i_elapse
+                        time_found += i_time
+                    except:
+                        i_time = time.time() - i_elapse
+                        time_not_found += i_time
+                        not_found += 1
+                        pass
+                elif method == "c":
+                    if portal_types[i] in this_portal_types:
+                        found += 1
+                        doc = res[this_portal_types.index(portal_types[i])].getObject().getContent()
+                        i_time = time.time() - i_elapse
+                        time_found += i_time
+                    else:
+                        not_found += 1
+                        i_time = time.time() - i_elapse
+                        time_not_found += i_time
+                elif method == "d":
+                    if student_brain.has_key(portal_types[i]):
+                        found += 1
+                        doc = student_brain[portal_types[i]].getObject().getContent()
+                        i_time = time.time() - i_elapse
+                        time_found += i_time
+                    else:
+                        not_found += 1
+                        i_time = time.time() - i_elapse
+                        time_not_found += i_time
+                i_elapse = time.time()
+            if c and (c % intervall == 0):
+                #i_time = time.time() - i_elapse
+                t_per = 0.0
+                if found:
+                    t_per = time_found/found
+                if t_per > t_max:
+                    t_max = t_per
+                if t_per > 0.0 and t_per < t_min:
+                    t_min = t_per                    
+                itf = 0.0
+                if found:
+                    itf = time_found/found
+                itnf = 0.0
+                if not_found :
+                    itnf = time_not_found / not_found
+                interval_time = time_found + time_not_found 
+                s = "%(c)d: %(found)d/%(not_found)d " % vars() 
+                s += "%(interval_time)6.2f %(itf)6.4f/%(itnf)6.4f " % vars()
+                s += "%(t_min)6.4f/%(t_max)6.4f" %  vars()
+                print s
+                t_found += found
+                t_not_found += not_found
+                t_time_found += time_found
+                t_time_not_found += time_not_found
+                time_found = time_not_found = 0.0
+                found = not_found = 0
+        # t_found += found
+        # t_not_found += not_found
+        elapse = time.time() - elapse
+        itf = 0.0
+        if t_found:
+            itf = t_time_found/t_found
+        itnf = 0.0
+        if t_not_found:
+            itnf = t_time_not_found / t_not_found
+        #c_elapse = time.clock() - c_elapse
+        s = "%(probe)d: %(t_found)d/%(t_not_found)d " % vars() 
+        s += "%(elapse)6.2f %(itf)6.4f/%(itnf)6.4f " % vars()
+        s += "%(t_min)6.4f/%(t_max)6.4f" %  vars()
+        print "-"*40
+        print s
+        rel_found = float(t_found)/probe
+        rel_not_found = float(t_not_found)/probe
+        estimated_total_time = num_objects*(rel_found*itf + rel_not_found*itnf)
+        print estimated_total_time
+    ###)
 
     security.declareProtected(ModifyPortalContent,'writeLog') ###(
@@ -1020,7 +1176,9 @@
                 start = False
                 adapters = [MappingStorageAdapter(schema, item)]
-                dm = DataModel(item, adapters,context=self)
                 logger.info('%s starts import from %s.csv' % (member,filename))
-                import_keys = [k for k in item.keys() if not k.startswith('ignore')]
+                #import_keys = [k for k in item.keys() if not k.startswith('ignore')]
+                attrs = csv.reader(open("%s/import/%s.csv" % (i_home,filename),"rb")).next()
+                #import pdb;pdb.set_trace()
+                import_keys = [k for k in attrs if not k.startswith('ignore')]
                 diff2schema = set(import_keys).difference(set(schema.keys()))
                 diff2layout = set(import_keys).difference(set(layout.keys()))
@@ -1035,4 +1193,5 @@
                 format_error = format + ',"%(Error)s"'
                 format = '"%(id)s",'+ format
+            dm = DataModel(item, adapters,context=self)
             ds = DataStructure(data=item,datamodel=dm)
             error_string = ""
Index: WAeUP_SRP/trunk/Widgets.py
===================================================================
--- WAeUP_SRP/trunk/Widgets.py	(revision 2093)
+++ WAeUP_SRP/trunk/Widgets.py	(revision 2094)
@@ -248,5 +248,5 @@
     """WAeUP Session Widget."""
     meta_type = 'WAeUP Session Widget'
-
+    
     def _getSessions(self):
         current_year = DateTime().year()
@@ -459,4 +459,115 @@
 ###)
 
+class WAeUPLGAWidget(CPSSelectWidget): ###(
+    """WAeUP LGA Widget."""
+    meta_type = 'WAeUP LGA Widget'
+    _properties = CPSSelectWidget._properties + (
+        {'id': 'state_field', 'type': 'string', 'mode': 'w',
+         'label': 'Name of the state field'},
+         {'id': 'lga_field', 'type': 'string', 'mode': 'w',
+         'label': 'Name of the LGA Field (without state)'},
+         )
+    state_field = "state"
+    lga_field = "lga"
+
+    # XXX make a menu for the vocabulary.
+    vocabulary = 'local_gov_areas'
+
+    # Associating the widget label with an input area to improve the widget
+    # accessibility.
+    has_input_area = True
+
+    def _getLGAs(self):
+        voc = getattr(self.portal_vocabularies,self.vocabulary)
+        states = []
+        lgas  = []
+        d = {}
+        for k,v in voc.items():
+            parts = k.split('_')
+            state = parts[0]
+            lga = ' '.join(parts[1:])
+            if state not in states:
+                states.append(state)
+            lgas.append(lga)
+            d[k] = v
+        return (d,states,lgas)
+
+    def validate(self, datastructure, **kw):
+        """Validate datastructure and update datamodel."""
+        widget_id = self.getWidgetId()
+        value = datastructure[widget_id]
+        #import pdb;pdb.set_trace()
+        try:
+            v = str(value)
+        except ValueError:
+            datastructure.setError(widget_id, "'%s' not a valid lga key" % value)
+            return 0
+        v = v.lower()
+        combined,states,lgas = self._getLGAs()
+        one_field = False
+        if not self.state_field and not self.lga_field:
+            one_field = True
+            if v not in combined.keys():
+                datastructure.setError(widget_id, "'%s' not a valid lga key" % v)
+                return 0
+        else:
+            if widget_id == self.state_field:
+                if v not in states:
+                    datastructure.setError(widget_id, "'%s' not a valid state" % v)
+                    return 0
+            elif widget_id == self.lga_field:
+                if v not in lgas:
+                    datastructure.setError(widget_id, "'%s' not a valid lga" % v)
+                    return 0
+                if datastructure[self.state_field]:
+                    v = datastructure[self.state_field] + '_' + v
+        
+        if self.is_required and not len(v):
+            datastructure.setError(widget_id, "lga required")
+            return 0
+
+        datamodel = datastructure.getDataModel()
+        if one_field:
+            datamodel[self.fields[0]] = v
+        else:
+            state = datastructure[self.state_field].lower()
+            lga = "_".join(datastructure[self.lga_field].lower().split())
+            datamodel[self.fields[0]] =   state + "_" + lga 
+        return 1
+
+    def render(self, mode, datastructure, **kw):
+        """Render in mode from datastructure."""
+        w_id = self
+        value = datastructure[self.getWidgetId()]
+        lgas,x,y = self._getLGAs(datastructure)
+        if mode == 'view':
+            return escape(lgas.get(value, value))
+        elif mode == 'edit':
+            html_widget_id = self.getHtmlWidgetId()
+            res = renderHtmlTag('select', name=html_widget_id, id=html_widget_id)
+            in_selection = 0
+            vocabulary_items = lgas.items()
+            # if self.sorted:
+            #     vocabulary_items.sort(key=operator.itemgetter(1))
+            for k, v in vocabulary_items:
+                kw = {'value': k, 'contents': v}
+                if value == k:
+                    kw['selected'] = 'selected'
+                    in_selection = 1
+                res += renderHtmlTag('option', **kw)
+            if value and not in_selection:
+                kw = {'value': value, 'contents': 'invalid: '+ str(value),
+                      'selected': 'selected'}
+                res += renderHtmlTag('option', **kw)
+            res += '</select>'
+            return res
+        raise RuntimeError('unknown mode %s' % mode)
+
+InitializeClass(WAeUPLGAWidget)
+
+widgetRegistry.register(WAeUPLGAWidget)
+
+###)
+
 class WAeUPReservedRoomsWidget(CPSStringWidget): ###(
     """ WAeUPReservedRooms Widget"""
@@ -590,6 +701,10 @@
         value = datastructure[widget_id].upper()
         err = 0
-        if not valid: #or not (len(value) == self.digits + self.letters and value[:self.digits].isdigit() and value[self.digits:].isalpha()):
-            #err = 'Invalid number, the expected format is: %s%s with N = Number, L = Letter' % (self.digits_str,self.letters_str)
+        #import pdb;pdb.set_trace()
+        if kw.has_key('mode'):
+            mode = kw['mode']
+        else:
+            mode = "xxxx"
+        if not valid: 
             err = 'Invalid number'
         elif self.reference == '':
@@ -600,6 +715,13 @@
             else:
                 datastructure['pume'] = pume[0]
-        else:
-            #import pdb;pdb.set_trace()
+        elif mode == 'add':
+            pass
+        elif self.reference != '' and self.catalog == "new_students":
+            res = jamb_nr_catalog.searchResults({"%s" % self.reference: value})
+            if len(res) != 1:
+                err = 'No record with this registration number.'
+            else:
+                datastructure['record'] = res[0]
+        else:
             record = datastructure[self.reference]
             #jamb_reg_no = getattr(record,widget_id)
@@ -1048,5 +1170,4 @@
         do = 1
         s_id = str(self.portal_membership.getAuthenticatedMember())
-        #import pdb;pdb.set_trace()
         if self.isStaff():
             do = 0
@@ -1187,9 +1308,106 @@
     ###)
 
-
 InitializeClass(ScratchcardPinWidget)
 widgetRegistry.register(ScratchcardPinWidget)
-
-
+###)
+
+class PumePinWidget(ScratchcardPinWidget): ###(
+    """ Pume Pin Widget"""
+    meta_type = "Pume Pin Widget"
+
+    def validate(self, datastructure, **kw): ###(
+        """Validate datastructure and update datamodel."""
+        s_logger = logging.getLogger('Widgets.ScratchcardPinWidget.validate')
+        widget_id = self.getWidgetId()
+        v = datastructure[widget_id]
+        err = 0
+        mapping = {}
+        prefix= self.prefix
+        if prefix.startswith('@'):
+            prefix= getattr(self,self.prefix[1:])()
+        b = datastructure[widget_id+'_b'].strip()
+        n = datastructure[widget_id+'_n'].strip()
+        pins = self.portal_pins
+        pin = "%(prefix)s%(b)s%(n)s" % vars()
+        pin_str = "%(prefix)s-%(b)s-%(n)s" % vars()
+        do = 1
+        s_id = str(self.portal_membership.getAuthenticatedMember())
+        import pdb;pdb.set_trace()
+        if self.isStaff():
+            do = 0
+            err ='You are not a Student. PIN neither checked nor used.'
+            s_logger.info('%s tried to use scratch card %s' % (s_id,pin_str))
+        elif len(b) > 1 and b.find('-') > -1:
+            do = 0
+            err = 'PIN must not contain "-"'
+            s_logger.info('%s entered invalid PIN  containing "-"' % (s_id))
+        elif n.find('-') > -1:
+            do = 0
+            err = 'PIN must not contain "-"'
+            s_logger.info('%s entered invalid PIN  containing "-"' % (s_id))
+        elif len(n) != 10:
+            do = 0
+            err = 'Invalid PIN length'
+            s_logger.info('%s entered invalid PIN with length %d' % (s_id,len(n)))
+        elif self.reference == "":
+            ref = s_id
+        else:
+            ref = datastructure[self.reference]
+            if datastructure.errors:
+                do = 0
+                datastructure.setError(widget_id, 'PIN neither checked nor used.')
+                s_logger.info('%s/%s entered wrong data together with PIN %s' % (s_id,ref,pin_str))
+        while do:
+            ok = pins.searchAndSetRecord(pin,ref,prefix)
+            if ok < -2 or ok > 2:
+                err = 'Unknown error, please report!'
+                s_logger.info('%s/%s caused unknown error with PIN %s' % (s_id,ref,pin_str))
+                break
+            elif ok == -2:
+                err = 'Service already is activated but with a different PIN.'
+                s_logger.info('%s/%s repeatedly activated service but with different PIN %s' % (s_id,ref,pin_str))
+                break
+            elif ok == -1:
+                err = 'Invalid PIN'
+                s_logger.info('%s/%s entered invalid PIN %s' % (s_id,ref,pin_str))
+                break
+            if ok == 0:
+                err = 'PIN already used'
+                s_logger.info('%s/%s entered used PIN %s' % (s_id,ref,pin_str))
+                break
+            if ok >= 1:
+                #import pdb;pdb.set_trace()
+                if self.isStudent():
+                    err = "This is only for Pume application."
+                    s_logger.info('%s/%s applied for PUME with PIN %s' % (s_id,ref,pin_str))
+                    break
+                else:
+                    applicant = datastructure['record']
+                    if not applicant.pin: 
+                        s_logger.info('%s successfully used PIN %s' % (ref,pin_str))
+                        d = {}
+                        d['reg_no'] = applicant.reg_no
+                        d['pin'] = n
+                        self.new_students.modifyRecord(**d)
+                    elif applicant.pin != pin_str:
+                        s_logger.info('%s/%s repeatedly applied for PUME with different PIN %s' % (s_id,ref,pin_str))
+                    elif applicant.pin == pin_str:
+                        s_logger.info('%s/%s repeatedly applied for PUME with PIN %s' % (s_id,ref,pin_str))
+            break
+        if err:
+            datastructure.setError(widget_id, err,mapping)
+        else:
+            datamodel = datastructure.getDataModel()
+            datamodel[self.fields[0]] = ScratchCardPin(prefix,b,n)
+            datastructure[widget_id] = ScratchCardPin(prefix,b,n)
+            datastructure[widget_id+'_p'] = prefix
+            datastructure[widget_id+'_b'] = b
+            datastructure[widget_id+'_n'] = n
+            datastructure['s_id'] = s_id
+        return not err
+    ###)
+
+InitializeClass(PumePinWidget)
+widgetRegistry.register(PumePinWidget)
 ###)
 
Index: WAeUP_SRP/trunk/__init__.py
===================================================================
--- WAeUP_SRP/trunk/__init__.py	(revision 2093)
+++ WAeUP_SRP/trunk/__init__.py	(revision 2094)
@@ -10,4 +10,5 @@
 
 from Products.CPSCore.interfaces import ICPSSite
+from Products.CPSDirectory.DirectoryTool import DirectoryTypeRegistry
 
 import PatchCPSWorkflowWorkflowDefinition
@@ -126,3 +127,4 @@
         EXTENSION,
         for_=ICPSSite)
+##    DirectoryTypeRegistry.register(WAeUPTables.Applicants)
 
Index: WAeUP_SRP/trunk/configure.zcml
===================================================================
--- WAeUP_SRP/trunk/configure.zcml	(revision 2093)
+++ WAeUP_SRP/trunk/configure.zcml	(revision 2094)
@@ -1,4 +1,6 @@
 <configure
     xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+    xmlns:zcml="http://namespaces.zope.org/zcml"
     >
 
@@ -12,3 +14,10 @@
       />
 
+  <five:registerClass
+      class=".TableDirectory.NewStudentsDirectory"
+      meta_type="New Students Directory"
+      permission="cmf.ManagePortal"
+      global="False"
+      />
+
 </configure>
Index: WAeUP_SRP/trunk/doc/srp_documentation.mm
===================================================================
--- WAeUP_SRP/trunk/doc/srp_documentation.mm	(revision 2093)
+++ WAeUP_SRP/trunk/doc/srp_documentation.mm	(revision 2094)
@@ -1,3 +1,3 @@
-<map version="0.8.0">
+<map version="0.9.0_Beta_8">
 <!-- To view this file, download free mind mapping software FreeMind from http://freemind.sourceforge.net -->
 <node CREATED="1170079518946" ID="Freemind_Link_650524897" MODIFIED="1172489583516" TEXT="WAeUP Documentation">
@@ -300,7 +300,9 @@
 <node CREATED="1171711999584" ID="Freemind_Link_1070634598" MODIFIED="1171712315178" TEXT="Groups"/>
 </node>
-<node CREATED="1170931308473" FOLDED="true" ID="Freemind_Link_249696543" MODIFIED="1170931315740" TEXT="Catalogs">
+<node CREATED="1170931308473" ID="Freemind_Link_249696543" MODIFIED="1170931315740" TEXT="Catalogs">
 <node CREATED="1170931319920" ID="Freemind_Link_1633117071" MODIFIED="1171712108641" TEXT="Portal Catalog"/>
+<node CREATED="1171712109062" ID="Freemind_Link_1264506858" LINK="../profiles/default/applicants_catalog.xml" MODIFIED="1187006324354" TEXT="Applicants Catalog"/>
 <node CREATED="1171712109062" ID="Freemind_Link_769089546" LINK="../profiles/default/courses_catalog.xml" MODIFIED="1172055793074" TEXT="Courses Catalog"/>
+<node CREATED="1171712109062" ID="Freemind_Link_964376607" LINK="../profiles/default/course_results.xml" MODIFIED="1186484772138" TEXT="Course Results"/>
 <node CREATED="1171712109062" ID="Freemind_Link_879910437" LINK="../profiles/default/students_catalog.xml" MODIFIED="1172055153081" TEXT="Students Catalog"/>
 <node CREATED="1171712063356" ID="Freemind_Link_1865945880" LINK="../profiles/default/returning_import.xml" MODIFIED="1172055126664" TEXT="Returning Import Table"/>
Index: WAeUP_SRP/trunk/exportimport.py
===================================================================
--- WAeUP_SRP/trunk/exportimport.py	(revision 2093)
+++ WAeUP_SRP/trunk/exportimport.py	(revision 2094)
@@ -126,4 +126,5 @@
     importWAeUPTable(site.results_import, '', context,'results_import')
     importWAeUPTable(site.students_catalog, '', context,'students_catalog')
+    importWAeUPTable(site.applicants_catalog, '', context,'applicants_catalog')
     importWAeUPTable(site.course_results, '', context,'course_results')
     importWAeUPTable(site.portal_catalog_real, '', context,'portal_catalog_real')
Index: WAeUP_SRP/trunk/profiles/default/applicants_catalog.xml
===================================================================
--- WAeUP_SRP/trunk/profiles/default/applicants_catalog.xml	(revision 2094)
+++ WAeUP_SRP/trunk/profiles/default/applicants_catalog.xml	(revision 2094)
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="catalog.xsl"?>
+<object name="portal_pumeresults" meta_type="WAeUP Table">
+ <column value="reg_no"/>
+ <column value="registration_date"/>
+ <column value="date_of_birth"/>
+ <column value="sex"/>
+ <column value="firstname"/>
+ <column value="middlenames"/>
+ <column value="lastname"/>
+ <column value="lga"/>
+ <column value="email"/>
+ <column value="phone"/>
+ <column value="pin"/>
+ <column value="eng_score"/>
+ <column value="subj1"/>
+ <column value="subj1score"/>
+ <column value="subj2"/>
+ <column value="subj2score"/>
+ <column value="subj3"/>
+ <column value="subj3score"/>
+ <column value="aggregate"/>
+ <column value="entry_mode"/>
+ <column value="faculty"/>
+ <column value="department"/>
+ <column value="course1"/>
+ <column value="course2"/>
+ <column value="course3"/>
+ <column value="testdate"/>
+ <column value="passport"/>
+ <column value="status"/>
+ <index name="reg_no" meta_type="FieldIndex">
+  <indexed_attr value="reg_no"/>
+ </index>
+ <index name="status" meta_type="FieldIndex">
+  <indexed_attr value="status"/>
+ </index>
+ <index name="registration_date" meta_type="DateIndex">
+  <indexed_attr value="status"/>
+ </index>
+ <index name="firstname" meta_type="TextIndex">
+  <indexed_attr value="firstname"/>
+ </index>
+ <index name="lastname" meta_type="TextIndex">
+  <indexed_attr value="lastname"/>
+ </index>
+ <index name="faculty" meta_type="FieldIndex">
+  <indexed_attr value="faculty"/>
+ </index>
+ <index name="department" meta_type="FieldIndex">
+  <indexed_attr value="department"/>
+ </index>
+ <index name="course" meta_type="FieldIndex">
+  <indexed_attr value="course"/>
+ </index>
+</object>
Index: WAeUP_SRP/trunk/profiles/default/layouts.xml
===================================================================
--- WAeUP_SRP/trunk/profiles/default/layouts.xml	(revision 2093)
+++ WAeUP_SRP/trunk/profiles/default/layouts.xml	(revision 2094)
@@ -6,4 +6,5 @@
   <object name="acco_bed_booking" meta_type="CPS Layout"/>
   <object name="academics_search" meta_type="CPS Layout"/>
+  <object name="application" meta_type="CPS Layout"/>
   <object name="certificate" meta_type="CPS Layout"/>
   <object name="certificate_course" meta_type="CPS Layout"/>
Index: WAeUP_SRP/trunk/profiles/default/layouts/application.xml
===================================================================
--- WAeUP_SRP/trunk/profiles/default/layouts/application.xml	(revision 2094)
+++ WAeUP_SRP/trunk/profiles/default/layouts/application.xml	(revision 2094)
@@ -0,0 +1,478 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="layout.xsl"?>
+<object name="new_students" meta_type="CPS Layout">
+ <property name="layout_create_method">layout_enter_access_code</property>
+ <property name="layout_edit_method"></property>
+ <property name="layout_view_method"></property>
+ <property name="style_prefix">layout_application_</property>
+ <property name="flexible_widgets"/>
+ <property name="validate_values_expr"></property>
+ <widget name="course1" meta_type="String Widget">
+  <property name="title">Course</property>
+  <property name="fields">
+   <element value="course1"/>
+  </property>
+  <property name="label">Course 1</property>
+  <property name="label_edit">Course 1</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="course3" meta_type="String Widget">
+  <property name="title">Course 3</property>
+  <property name="fields">
+   <element value="course3"/>
+  </property>
+  <property name="label">Course 3</property>
+  <property name="label_edit">Course 3</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="course2" meta_type="String Widget">
+  <property name="title">Course 2</property>
+  <property name="fields">
+   <element value="course2"/>
+  </property>
+  <property name="label">Course 2</property>
+  <property name="label_edit">Course 2</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="date_of_birth" meta_type="Date Widget">
+  <property name="title">Date of Birth</property>
+  <property name="fields">
+   <element value="date_of_birth"/>
+  </property>
+  <property name="label">Date of Birth</property>
+  <property name="label_edit">Date of Birth</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+ <property name="hidden_layout_modes">
+  <element value="edit"/>
+ </property>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="department" meta_type="String Widget">
+  <property name="title">Department</property>
+  <property name="fields">
+   <element value="department"/>
+  </property>
+  <property name="label">Department</property>
+  <property name="label_edit">Department</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="email" meta_type="String Widget">
+  <property name="title">Email</property>
+  <property name="fields">
+   <element value="email"/>
+  </property>
+  <property name="label">Email</property>
+  <property name="label_edit">Email</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="entry_mode" meta_type="String Widget">
+  <property name="title">Entry Mode</property>
+  <property name="fields">
+   <element value="entry_mode"/>
+  </property>
+  <property name="label">Entry Mode</property>
+  <property name="label_edit">Entry Mode</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="faculty" meta_type="String Widget">
+  <property name="title">Faculty</property>
+  <property name="fields">
+   <element value="faculty"/>
+  </property>
+  <property name="label">Faculty</property>
+  <property name="label_edit">Faculty</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="firstname" meta_type="String Widget">
+  <property name="title">Firstname</property>
+  <property name="fields">
+   <element value="firstname"/>
+  </property>
+  <property name="label">Firstname</property>
+  <property name="label_edit">Firstname</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="agregate" meta_type="Int Widget">
+  <property name="title">JAMB Agregate Score</property>
+  <property name="fields">
+   <element value="agregate"/>
+  </property>
+  <property name="label">JAMB Agregate Score</property>
+  <property name="label_edit">JAMB Agregate Score</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="eng_score" meta_type="Int Widget">
+  <property name="title">English Score</property>
+  <property name="fields">
+   <element value="eng_score"/>
+  </property>
+  <property name="label">English Score</property>
+  <property name="label_edit">English Score</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="subj1" meta_type="String Widget">
+  <property name="title">Subject 1</property>
+  <property name="fields">
+   <element value="subj1"/>
+  </property>
+  <property name="label">Subject 1</property>
+  <property name="label_edit">Subject 1</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="subj1score" meta_type="Int Widget">
+  <property name="title">Subject 1 Score</property>
+  <property name="fields">
+   <element value="subj1score"/>
+  </property>
+  <property name="label">Subject 1 Score</property>
+  <property name="label_edit">Subject 1 Score</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="subj2" meta_type="String Widget">
+  <property name="title">Subject 2</property>
+  <property name="fields">
+   <element value="subj2"/>
+  </property>
+  <property name="label">Subject 2</property>
+  <property name="label_edit">Subject 2</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="subj2score" meta_type="Int Widget">
+  <property name="title">Subject 2 Score</property>
+  <property name="fields">
+   <element value="subj2score"/>
+  </property>
+  <property name="label">Subject 2 Score</property>
+  <property name="label_edit">Subject 2 Score</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="subj3" meta_type="String Widget">
+  <property name="title">Subject 3</property>
+  <property name="fields">
+   <element value="subj3"/>
+  </property>
+  <property name="label">Subject 3</property>
+  <property name="label_edit">Subject 3</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="subj3score" meta_type="Int Widget">
+  <property name="title">Subject 3 Score</property>
+  <property name="fields">
+   <element value="subj3score"/>
+  </property>
+  <property name="label">Subject 3 Score</property>
+  <property name="label_edit">Subject 3 Score</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="lastname" meta_type="String Widget">
+  <property name="title">Lastname</property>
+  <property name="fields">
+   <element value="lastname"/>
+  </property>
+  <property name="label">Lastname</property>
+  <property name="label_edit">Lastname</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="lga" meta_type="WAeUP LGA Widget">
+  <property name="title">LGA</property>
+  <property name="fields">
+   <element value="lga"/>
+  </property>
+  <property name="label">LGA</property>
+  <property name="label_edit">LGA</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="middlenames" meta_type="String Widget">
+  <property name="title">Middlenames</property>
+  <property name="fields">
+   <element value="middlenames"/>
+  </property>
+  <property name="label">Middlenames</property>
+  <property name="label_edit">Middlenames</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="phone" meta_type="String Widget">
+  <property name="title">Phone</property>
+  <property name="fields">
+   <element value="phone"/>
+  </property>
+  <property name="label">Phone</property>
+  <property name="label_edit">Phone</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="pin" meta_type="Pume Pin Widget">
+  <property name="title">PIN</property>
+  <property name="fields">
+   <element value="pin"/>
+  </property>
+  <property name="label">PIN</property>
+  <property name="label_edit">PIN</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+ <property name="hidden_layout_modes">
+  <element value="edit"/>
+ </property>
+  <property name="hidden_readonly_layout_modes"/>
+  <property name="prefix">APP</property>
+  <property name="reference">reg_no</property>
+ </widget>
+ <widget name="registration_date" meta_type="Date Widget">
+  <property name="title">Registration Date</property>
+  <property name="fields">
+   <element value="registration_date"/>
+  </property>
+  <property name="label">Registration Date</property>
+  <property name="label_edit">Registration Date</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="test_date" meta_type="Date Widget">
+  <property name="title">Test Date</property>
+  <property name="fields">
+   <element value="test_date"/>
+  </property>
+  <property name="label">Test Date</property>
+  <property name="label_edit">Test Date</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="reg_no" meta_type="JambRegNo Widget">
+  <property name="title">JAMB Registration Number</property>
+  <property name="fields">
+   <element value="reg_no"/>
+  </property>
+  <property name="label">JAMB Registration Number</property>
+  <property name="label_edit">JAMB Registration Number</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+  <property name="display_width">13</property>
+  <property name="size_max">13</property>
+  <property name="reference">reg_no</property>
+  <property name="catalog">applicants_catalog</property>
+ </widget>
+ <widget name="score" meta_type="Int Widget">
+  <property name="title">Score</property>
+  <property name="fields">
+   <element value="score"/>
+  </property>
+  <property name="label">Score</property>
+  <property name="label_edit">Score</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="sex" meta_type="WAeUP Sex Widget">
+  <property name="title">Sex</property>
+  <property name="fields">
+   <element value="sex"/>
+  </property>
+  <property name="label">Score</property>
+  <property name="label_edit">Score</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="state" meta_type="WAeUP LGA Widget">
+  <property name="title">State</property>
+  <property name="fields">
+   <element value="lga"/>
+  </property>
+  <property name="label">State</property>
+  <property name="label_edit">State</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="status" meta_type="String Widget">
+  <property name="title">Status</property>
+  <property name="fields">
+   <element value="status"/>
+  </property>
+  <property name="label">Status</property>
+  <property name="label_edit">Status</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <widget name="verdict" meta_type="WAeUP Verdict Widget">
+  <property name="title">Verdict</property>
+  <property name="fields">
+   <element value="status"/>
+  </property>
+  <property name="label">Verdict</property>
+  <property name="label_edit">Verdict</property>
+  <property name="description"></property>
+  <property name="help"></property>
+  <property name="is_i18n">False</property>
+  <property name="widget_mode_expr"></property>
+  <property name="readonly_layout_modes"/>
+  <property name="hidden_layout_modes"/>
+  <property name="hidden_readonly_layout_modes"/>
+ </widget>
+ <table>
+  <row>
+   <cell name="reg_no"/>
+  </row>
+  <row>
+   <cell name="pin"/>
+  </row>
+ </table>
+</object>
Index: WAeUP_SRP/trunk/profiles/default/schemas.xml
===================================================================
--- WAeUP_SRP/trunk/profiles/default/schemas.xml	(revision 2093)
+++ WAeUP_SRP/trunk/profiles/default/schemas.xml	(revision 2094)
@@ -7,4 +7,5 @@
  <object name="acco_hall" meta_type="CPS Schema"/>
  <object name="acco_bed_booking" meta_type="CPS Schema"/>
+ <object name="application" meta_type="CPS Schema"/>
  <object name="certificate" meta_type="CPS Schema"/>
  <object name="certificate_course" meta_type="CPS Schema"/>
Index: WAeUP_SRP/trunk/profiles/default/schemas/application.xml
===================================================================
--- WAeUP_SRP/trunk/profiles/default/schemas/application.xml	(revision 2094)
+++ WAeUP_SRP/trunk/profiles/default/schemas/application.xml	(revision 2094)
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="schema.xsl"?>
+<object name="new_students" meta_type="CPS Schema">
+ <field name="course1" meta_type="CPS String Field"/>
+ <field name="course2" meta_type="CPS String Field"/>
+ <field name="course3" meta_type="CPS String Field"/>
+ <field name="entry_mode" meta_type="CPS String Field"/>
+ <field name="department" meta_type="CPS String Field"/>
+ <field name="faculty" meta_type="CPS String Field"/>
+ <field name="firstname" meta_type="CPS String Field"/>
+ <field name="eng_score" meta_type="CPS Int Field"/>
+ <field name="subj1" meta_type="CPS Int Field"/>
+ <field name="subj1score" meta_type="CPS Int Field"/>
+ <field name="subj2" meta_type="CPS Int Field"/>
+ <field name="subj2score" meta_type="CPS Int Field"/>
+ <field name="subj3" meta_type="CPS Int Field"/>
+ <field name="subj3score" meta_type="CPS Int Field"/>
+ <field name="agregate" meta_type="CPS Int Field"/>
+ <field name="lastname" meta_type="CPS String Field"/>
+ <field name="middlenames" meta_type="CPS String Field"/>
+ <field name="email" meta_type="CPS String Field"/>
+ <field name="phone" meta_type="CPS String Field"/>
+ <field name="pin" meta_type="CPS String Field"/>
+ <field name="reg_no" meta_type="CPS String Field"/>
+ <field name="date_of_birth" meta_type="CPS DateTime Field"/>
+ <field name="registration_date" meta_type="CPS DateTime Field"/>
+ <field name="score" meta_type="CPS Int Field"/>
+ <field name="sex" meta_type="CPS Boolean Field"/>
+ <field name="lga" meta_type="CPS String Field"/>
+ <field name="testdate" meta_type="CPS DateTime Field"/>
+ <field name="passport" meta_type="CPS String Field"/>
+ <field name="status" meta_type="CPS String Field"/>
+ <field name="verdict" meta_type="CPS String Field"/>
+</object>
Index: WAeUP_SRP/trunk/profiles/default/toolset.xml
===================================================================
--- WAeUP_SRP/trunk/profiles/default/toolset.xml	(revision 2093)
+++ WAeUP_SRP/trunk/profiles/default/toolset.xml	(revision 2094)
@@ -23,4 +23,6 @@
  <required tool_id="students_catalog"
            class="Products.WAeUP_SRP.WAeUPTables.StudentsCatalog"/>
+ <required tool_id="applicants_catalog"
+           class="Products.WAeUP_SRP.WAeUPTables.ApplicantsCatalog"/>
  <required tool_id="course_results"
            class="Products.WAeUP_SRP.WAeUPTables.CourseResults"/>
