Index: main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_applicant.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_applicant.py	(revision 6816)
+++ main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_applicant.py	(revision 7063)
@@ -22,26 +22,19 @@
 """Tests for applicants and related.
 """
+import grok
 import unittest
-from StringIO import StringIO
-from hurry.file.interfaces import IFileRetrieval
-from zope.component import (
-    provideAdapter, adapts, getGlobalSiteManager, provideUtility)
-from zope.component.hooks import setSite
+from zope.component import adapts, queryUtility
 from zope.component.interfaces import IFactory
 from zope.interface import verify, implements
 from zope.location.interfaces import ILocation
-from zope.publisher.base import TestRequest
-from zope.publisher.interfaces import NotFound
-from waeup.sirp.app import University
-from waeup.sirp.image import WAeUPImageFile, createWAeUPImageFile
 from waeup.sirp.image.interfaces import IWAeUPImageFile
+from waeup.sirp.imagestorage import DefaultStorage
+from waeup.sirp.interfaces import IFileStoreHandler, IFileStoreNameChooser
 from waeup.sirp.applicants import (
-    ResultEntry, Applicant, ApplicantFactory, ApplicantTraverser,
+    ResultEntry, Applicant, ApplicantFactory, get_regno_or_ac,
+    ApplicantImageStoreHandler, ApplicantImageNameChooser,
     )
-from waeup.sirp.applicants.interfaces import (
-    IResultEntry, IApplicant,
-    )
-from waeup.sirp.imagestorage import ImageStorageFileRetrieval
-from waeup.sirp.testing import (FunctionalTestCase, FunctionalLayer)
+from waeup.sirp.applicants.interfaces import IResultEntry, IApplicant
+from waeup.sirp.testing import FunctionalTestCase, FunctionalLayer
 
 class FakeImageLocation(object):
@@ -51,4 +44,109 @@
         pass
 
+class HelperTests(FunctionalTestCase):
+
+    layer = FunctionalLayer
+
+    def test_get_regno_or_ac(self):
+        # we can get reg_no or access_code of an applicants if it is set
+        appl1 = Applicant()
+        appl2 = Applicant()
+        appl2.reg_no = u'foo'
+        appl3 = Applicant()
+        appl3.access_code = u'bar'
+        appl4 = Applicant()
+        appl4.reg_no = u'foo'
+        appl4.access_code = u'bar'
+        self.assertTrue(
+            get_regno_or_ac(appl1) is None)
+        self.assertEqual(
+            get_regno_or_ac(appl2), u'foo')
+        self.assertEqual(
+            get_regno_or_ac(appl3), u'bar')
+        self.assertEqual(
+            get_regno_or_ac(appl4), u'foo')
+        return
+
+    def test_image_store_handler_util_accessible(self):
+        # we can get an IFileStoreHandler utility for applicants
+        handler = queryUtility(IFileStoreHandler, name='img-applicant')
+        self.assertTrue(
+            isinstance(handler, ApplicantImageStoreHandler))
+        return
+
+    def test_image_store_handler(self):
+        store = DefaultStorage()
+        handler = queryUtility(IFileStoreHandler, name='img-applicant')
+        result1 = handler.pathFromFileID(
+            store, '/fake-root', '__img-applicant__sample.jpg')
+        result2 = handler.pathFromFileID(
+            store, '/fake-root', '__img-applicant__dir1/sample.jpg')
+        result3 = handler.pathFromFileID(
+            store, '/fake-root', '__img-applicant__dir1/dir2/sample.jpg')
+        self.assertEqual(
+            result1, '/fake-root/applicants/sample.jpg')
+        self.assertEqual(
+            result2, '/fake-root/applicants/dir1/sample.jpg')
+        self.assertEqual(
+            result3, '/fake-root/applicants/dir1/dir2/sample.jpg')
+        return
+
+class ApplicantImageNameChooserTests(FunctionalTestCase):
+
+    layer = FunctionalLayer
+
+    def test_iface(self):
+        # make sure we implement promised interfaces
+        obj = ApplicantImageNameChooser(None) # needs a context normally
+        verify.verifyClass(IFileStoreNameChooser, ApplicantImageNameChooser)
+        verify.verifyObject(IFileStoreNameChooser, obj)
+        return
+
+    def test_name_chooser_available(self):
+        # we can get a name chooser for applicant objects as adapter
+        appl = Applicant()
+        chooser = IFileStoreNameChooser(appl)
+        self.assertTrue(chooser is not None)
+        return
+
+    def test_name_chooser_applicant_wo_container(self):
+        # we can get an image filename for applicants not in a container
+        appl = Applicant()
+        appl.reg_no = u'MY_REG_NO'
+        chooser = IFileStoreNameChooser(appl)
+        result = chooser.chooseName()
+        # the file would be stored in a ``_default`` directory.
+        self.assertEqual(
+            result, '__img-applicant___default/MY_REG_NO.jpg')
+        return
+
+    def test_name_chooser_applicant_w_container(self):
+        appl = Applicant()
+        appl.reg_no = u'MY_REG_NO'
+        fake_container = grok.Container()
+        fake_container.__name__ = 'folder'
+        fake_container['appl'] = appl
+        appl.__parent__ = fake_container
+        chooser = IFileStoreNameChooser(appl)
+        result = chooser.chooseName()
+        self.assertEqual(
+            result, '__img-applicant__folder/MY_REG_NO.jpg')
+        return
+
+    def test_name_chooser_check_name(self):
+        # we can check file ids for applicants
+        appl = Applicant()
+        appl.reg_no = u'MY_REG_NO'
+        fake_container = grok.Container()
+        fake_container.__name__ = 'folder'
+        fake_container['appl'] = appl
+        appl.__parent__ = fake_container
+        chooser = IFileStoreNameChooser(appl)
+        result1 = chooser.checkName('foo')
+        result2 = chooser.checkName('__img-applicant__folder/MY_REG_NO.jpg')
+        self.assertEqual(result1, False)
+        self.assertEqual(result2, True)
+        return
+
 class ResultEntryTest(unittest.TestCase):
 
@@ -87,27 +185,4 @@
         return
 
-    def test_passport_no_site(self):
-        # make sure we get a real image stored in passport attr
-        image = self.applicant.passport.file.read()
-        self.assertEqual(len(image), 2059)
-        return
-
-    def test_passport_insite(self):
-        # make sure we get a real image in passport attr when inside a site.
-        # When an applicant is created 'inside a site', its passport
-        # photograph should be put inside the images folder of the
-        # site, even if it is only a placeholder.
-        self.getRootFolder()['app'] = University()
-        app = self.getRootFolder()['app']
-        setSite(app)
-        applicant = Applicant()
-        image = self.applicant.passport.file.read()
-        self.assertEqual(len(image), 2059)
-        # The image contains a file_id instead of real image-data
-        self.assertEqual(self.applicant.passport.data,
-                         u'b48a1d39bbcb32e955d9ff2dea4ed0e6-1')
-        assert u'b48a1d39bbcb32e955d9ff2dea4ed0e6' in app['images'].keys()
-        return
-
 class ApplicantFactoryTest(FunctionalTestCase):
 
@@ -116,7 +191,4 @@
     def setUp(self):
         super(ApplicantFactoryTest, self).setUp()
-        # Install a IFileRetrieval utility that returns WAeUPImageFiles.
-        storage = ImageStorageFileRetrieval()
-        provideUtility(storage, IFileRetrieval)
         self.factory = ApplicantFactory()
         return
@@ -137,65 +209,2 @@
         implemented_by = self.factory.getInterfaces()
         assert implemented_by.isOrExtends(IApplicant)
-
-
-class ApplicantTraverserTest(FunctionalTestCase):
-
-    layer = FunctionalLayer
-
-    def setUp(self):
-        super(ApplicantTraverserTest, self).setUp()
-        provideAdapter(FakeImageLocation)
-        self.applicant = Applicant()
-
-        self.request = TestRequest('')
-        return
-
-    def tearDown(self):
-        gsm = getGlobalSiteManager()
-        gsm.unregisterAdapter(FakeImageLocation)
-        super(ApplicantTraverserTest, self).tearDown()
-        return
-
-    def test_traverse_wo_passport(self):
-        # Ask for some attribute not provided
-        traverser = ApplicantTraverser(
-            self.applicant, self.request
-            )
-        self.assertRaises(
-            NotFound,
-            traverser.publishTraverse, self.request, 'passport'
-            )
-        return
-
-    def test_traverse_wo_image_passport_jpg(self):
-        # Ask for applicant pic if we didn't provided one
-        # We get a placeholder.
-        traverser = ApplicantTraverser(
-            self.applicant, self.request
-            )
-        result = traverser.publishTraverse(self.request, 'passport.jpg')
-        self.assertTrue(isinstance(result, FakeImageLocation))
-        return
-
-    def test_traverse_w_image_passport_jpg(self):
-        # Ask for applicant pic that's named 'passport.jpg'
-        traverser = ApplicantTraverser(
-            self.applicant, self.request
-            )
-        self.applicant.passport = createWAeUPImageFile(
-            'nofile.jpg', StringIO('no-content'))
-        self.applicant.passport.filename = 'mypic.jpg'
-        result = traverser.publishTraverse(self.request, 'passport.jpg')
-        self.assertTrue(isinstance(result, FakeImageLocation))
-        return
-
-    def test_traverse_w_image_some_jpg(self):
-        # Ask for applicant pic by correct name
-        traverser = ApplicantTraverser(
-            self.applicant, self.request
-            )
-        self.applicant.passport = WAeUPImageFile('nofile.jpg', '')
-        self.applicant.passport.filename = 'mypic.jpg'
-        result = traverser.publishTraverse(self.request, 'mypic.jpg')
-        self.assertTrue(isinstance(result, FakeImageLocation))
-        return
Index: main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_authentication.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_authentication.py	(revision 6816)
+++ main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_authentication.py	(revision 7063)
@@ -24,5 +24,5 @@
 import unittest
 from zope.authentication.interfaces import IAuthentication
-from zope.component import provideAdapter, getUtility
+from zope.component import provideAdapter, getUtility, queryUtility
 from zope.component.hooks import setSite
 from zope.interface import verify
@@ -35,9 +35,10 @@
 from waeup.sirp.testing import FunctionalLayer, FunctionalTestCase
 from waeup.sirp.app import University
+from waeup.sirp.interfaces import IAuthPluginUtility
 from waeup.sirp.applicants import  ApplicantsContainer, Applicant
 from waeup.sirp.applicants.authentication import (
     ApplicantsAuthenticatorPlugin, WAeUPApplicantCredentialsPlugin,
     ApplicantCredentials, AuthenticatedApplicantPrincipalFactory,
-    ApplicantPrincipalInfo, ApplicantPrincipal,)
+    ApplicantPrincipalInfo, ApplicantPrincipal, ApplicantsAuthUtility)
 
 
@@ -367,14 +368,45 @@
         return
 
-def test_suite():
-    suite = unittest.TestSuite()
-    for testcase in [
-        AuthenticatorPluginTest, CredentialsPluginTest,
-        ApplicantCredentialsTest, PrincipalFactoryTest,
-        PAUSetupTest,
-        ]:
-        suite.addTest(unittest.TestLoader().loadTestsFromTestCase(
-                testcase
-                )
-        )
-    return suite
+class FakePAU(object):
+    credentialsPlugins = ()
+    authenticatorPlugins = ()
+
+class ApplicantsAuthUtilityTests(FunctionalTestCase):
+
+    layer = FunctionalLayer
+
+    def test_ifaces(self):
+        # make sure we fullfill the interface promises
+        obj = ApplicantsAuthUtility()
+        verify.verifyClass(IAuthPluginUtility, ApplicantsAuthUtility)
+        verify.verifyObject(IAuthPluginUtility, obj)
+        return
+
+    def test_utility_available(self):
+        # we can get an applicant auth utility by lookup
+        util = queryUtility(IAuthPluginUtility,
+                            name='applicants_auth_setup')
+        self.assertTrue(util is not None)
+        return
+
+    def test_register(self):
+        # make sure we can register additional components
+        pau = FakePAU()
+        result = ApplicantsAuthUtility().register(pau)
+        self.assertEqual(
+            result.credentialsPlugins, ('applicant_credentials',))
+        self.assertEqual(
+            result.authenticatorPlugins, ('applicants',))
+        return
+
+    def test_unregister(self):
+        # make sure we can unregister applicant auth components
+        pau = FakePAU()
+        util = ApplicantsAuthUtility()
+        pau = util.register(pau)
+        result = util.unregister(pau)
+        self.assertEqual(
+            result.credentialsPlugins, ())
+        self.assertEqual(
+            result.authenticatorPlugins, ())
+        return
Index: main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_browser.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_browser.py	(revision 6816)
+++ main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_browser.py	(revision 7063)
@@ -28,5 +28,5 @@
 from datetime import datetime, date, timedelta
 from mechanize import LinkNotFoundError
-from zope.component import createObject
+from zope.component import createObject, getUtility
 from zope.component.hooks import setSite, clearSite
 from zope.security.interfaces import Unauthorized
@@ -37,4 +37,5 @@
 from waeup.sirp.applicants.container import ApplicantsContainer
 from waeup.sirp.applicants.applicant import Applicant
+from waeup.sirp.interfaces import IExtFileStore, IFileStoreNameChooser
 from waeup.sirp.university.faculty import Faculty
 from waeup.sirp.university.department import Department
@@ -350,9 +351,9 @@
         self.browser.getControl(name="SUBMIT").click()
         pin = self.pins[2]
-        appl = self.getRootFolder()['app']['applicants']['app2009']
-        appl = appl[pin]
-        passp = appl.passport
-        passp_len = len(passp.file.read())
-        self.assertEqual(passp_len, PH_LEN)
+        #appl = self.getRootFolder()['app']['applicants']['app2009']
+        #appl = appl[pin]
+        #passp = appl.passport
+        #passp_len = len(passp.file.read())
+        #self.assertEqual(passp_len, PH_LEN)
         #image_url = "%s/%s" % (self.browser.url, 'placeholder.jpg')
         image_url = "%s/%s" % (self.browser.url, 'passport.jpg')
@@ -639,12 +640,12 @@
         # There is a correct <img> link included
         self.assertTrue(
-            '<img src="placeholder_m.jpg" />' in self.browser.contents)
+            '<img src="passport.jpg" />' in self.browser.contents)
         # Browsing the link shows a real image
-        self.browser.open(self.image_url('placeholder_m.jpg'))
+        self.browser.open(self.image_url('passport.jpg'))
         self.assertEqual(
             self.browser.headers['content-type'], 'image/jpeg')
         self.assertEqual(len(self.browser.contents), PH_LEN)
 
-    def test_after_login_default_stored_in_imagestorage(self):
+    def DISABLEDtest_after_login_default_stored_in_imagestorage(self):
         # After login the applicants placeholder image is stored in
         # an imagestorage
@@ -672,27 +673,10 @@
         # There is a correct <img> link included
         self.assertTrue(
-            '<img src="placeholder_m.jpg" />' in self.browser.contents)
+            '<img src="passport.jpg" />' in self.browser.contents)
         # Browsing the link shows a real image
-        self.browser.open(self.image_url('placeholder_m.jpg'))
+        self.browser.open(self.image_url('passport.jpg'))
         self.assertEqual(
             self.browser.headers['content-type'], 'image/jpeg')
         self.assertEqual(len(self.browser.contents), PH_LEN)
-
-    def test_after_submit_default_stored_in_imagestorage(self):
-        # After submitting an applicant form the default image is
-        # correctly stored in an imagestorage
-        self.login()
-        self.browser.getControl("Save").click() # submit form
-        storage = self.app['images']
-        self.assertEqual(
-            [x for x in storage.keys()],
-            [u'b48a1d39bbcb32e955d9ff2dea4ed0e6'])
-        file_id = self.applicant.passport.data
-        self.assertEqual(
-            file_id, u'b48a1d39bbcb32e955d9ff2dea4ed0e6-1')
-        # The stored image can be fetched
-        fd = storage.retrieveFile(file_id)
-        file_len = len(fd.read())
-        self.assertEqual(file_len, PH_LEN)
 
     def test_uploaded_image_browsable_w_errors(self):
@@ -709,7 +693,7 @@
         # There is a correct <img> link included
         self.assertTrue(
-            '<img src="myphoto.jpg" />' in self.browser.contents)
+            '<img src="passport.jpg" />' in self.browser.contents)
         # Browsing the link shows a real image
-        self.browser.open(self.image_url('myphoto.jpg'))
+        self.browser.open(self.image_url('passport.jpg'))
         self.assertEqual(
             self.browser.headers['content-type'], 'image/jpeg')
@@ -726,15 +710,10 @@
         file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
         self.browser.getControl("Save").click() # submit form
-        storage = self.app['images']
-        self.assertTrue(
-            u'18e57c7eac6ca7fb15b54b5b2bd4106d' in storage.keys())
-        # The stored image can be fetched
-        fd = storage.retrieveFile(u'18e57c7eac6ca7fb15b54b5b2bd4106d-1')
-        file_len = len(fd.read())
-        self.assertEqual(file_len, 31)
-        # The image uploaded belongs to the applicant
-        file_id = self.applicant.passport.data
+        storage = getUtility(IExtFileStore)
+        file_id = IFileStoreNameChooser(self.applicant).chooseName()
+        pseudo_image.seek(0) # reset our file data source
         self.assertEqual(
-            file_id, u'18e57c7eac6ca7fb15b54b5b2bd4106d-1')
+            storage.getFile(file_id).read(), pseudo_image.read())
+        return
 
     def test_uploaded_image_browsable_wo_errors(self):
@@ -751,7 +730,7 @@
         # There is a correct <img> link included
         self.assertTrue(
-            '<img src="myphoto.jpg" />' in self.browser.contents)
+            '<img src="passport.jpg" />' in self.browser.contents)
         # Browsing the link shows a real image
-        self.browser.open(self.image_url('myphoto.jpg'))
+        self.browser.open(self.image_url('passport.jpg'))
         self.assertEqual(
             self.browser.headers['content-type'], 'image/jpeg')
@@ -769,16 +748,10 @@
         file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
         self.browser.getControl("Save").click() # submit form
-        storage = self.app['images']
-        self.assertTrue(
-            u'18e57c7eac6ca7fb15b54b5b2bd4106d' in storage.keys())
+        storage = getUtility(IExtFileStore)
+        file_id = IFileStoreNameChooser(self.applicant).chooseName()
         # The stored image can be fetched
-        fd = storage.retrieveFile(u'18e57c7eac6ca7fb15b54b5b2bd4106d-1')
-        #fd = storage.retrieveFile(file_id)
+        fd = storage.getFile(file_id)
         file_len = len(fd.read())
         self.assertEqual(file_len, 31)
-        # The image uploaded belongs to the applicant
-        file_id = self.applicant.passport.data
-        self.assertEqual(
-            file_id, u'18e57c7eac6ca7fb15b54b5b2bd4106d-1')
 
     def test_uploaded_images_equal(self):
@@ -797,12 +770,14 @@
         file_ctrl = ctrl.mech_control
         file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
-        passport0 = self.applicant.passport
+        file_id = IFileStoreNameChooser(self.applicant).chooseName()
+        setSite(self.app)
+        passport0 = getUtility(IExtFileStore).getFile(file_id)
         self.browser.getControl("Save").click() # submit form with changed pic
-        passport1 = self.applicant.passport
+        passport1 = getUtility(IExtFileStore).getFile(file_id).read()
         self.browser.getControl("Save").click() # submit form w/o changes
-        passport2 = self.applicant.passport
+        passport2 = getUtility(IExtFileStore).getFile(file_id).read()
+        self.assertTrue(passport0 is None)
         self.assertTrue(passport0 != passport1)
         self.assertTrue(passport1 == passport2)
-        self.assertTrue(passport1 is passport2)
         return
 
Index: main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_interfaces.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_interfaces.py	(revision 6816)
+++ main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_interfaces.py	(revision 7063)
@@ -25,12 +25,7 @@
 import unittest
 from zc.sourcefactory.browser.source import FactoredTerms
-from zope.browser.interfaces import ITerms
-from zope.component import getMultiAdapter
-from zope.interface.verify import verifyClass, verifyObject
 from zope.publisher.browser import TestRequest
-from waeup.sirp.applicants import interfaces
-from waeup.sirp.applicants.vocabularies import (
-    APPLICATION_TYPES, application_types_vocab, GenderSource,
-    )
+from waeup.sirp.applicants.vocabularies import application_types_vocab
+from waeup.sirp.students.vocabularies import GenderSource
 
 class ApplicationCategoriesTestCase(unittest.TestCase):
Index: main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_root.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_root.py	(revision 6816)
+++ main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_root.py	(revision 7063)
@@ -39,6 +39,5 @@
     )
 from waeup.sirp.testing import (
-    FunctionalLayer, FunctionalTestCase, get_all_loggers, remove_new_loggers,
-    remove_logger)
+    FunctionalLayer, FunctionalTestCase, remove_logger)
 
 
