from Ft.Ods import Constants, Collections
from Ft.Ods import Database
from Ft.Ods.Exception import FtodsObjectNotFound
from Ft.Ods.StorageManager import Adapters

import test_collection_util

import os
DBNAME=os.environ.get("ODS_TEST_DB","ods:test")

names = Constants.g_odmgTypeToString


def test_dictionary_interface(tester,db,kt,vt):

    tester.startGroup("Interface on %s,%s" % (names[kt],names[vt]))
    tx = db.new()
    tx.begin()

    kfac = test_collection_util.GetFactory(kt)
    vfac = test_collection_util.GetFactory(vt)

    keys = []
    values = []
    for ctr in range(2):
        keys.append(kfac.next(db))
    for ctr in range(2):
        values.append(vfac.next(db))

    dict = Collections.CollectionFromTypes(db,
                                           Constants.Types.DICTIONARY_COLLECTION,
                                           vt,
                                           keyType = kt,
                                           keyTypeRepositoryId=kfac.typeId,
                                           subTypeRepositoryId=vfac.typeId)


    tester.startTest('__setitem__')
    dict[keys[0]] = values[0]
    tester.testDone()

    tester.startTest('has_key')
    tester.compare(1,dict.has_key(keys[0]))
    tester.compare(0,dict.has_key(keys[1]))
    tester.testDone()

    tester.startTest('keys')
    ks = dict.keys()
    tester.compare(1,len(ks))
    tester.compareIn(ks,keys[0])
    tester.testDone()

    tester.startTest('__getitem__')
    tester.compare(values[0],dict[keys[0]])
    tester.testDone()

    tester.startTest('values')
    vs = dict.values()
    tester.compare(1,len(vs))
    tester.compareIn(vs,values[0])
    tester.testDone()

    tester.startTest('__delitem__')
    del dict[keys[0]]
    tester.compare(0,dict.has_key(keys[0]))
    tester.testDone()

    tx.abort()
    tester.groupDone()


def test_dictionary_persistence(tester,db,kt,vt):

    kfac = test_collection_util.GetFactory(kt)
    vfac = test_collection_util.GetFactory(vt)

    tester.startGroup("Persistence of %s,%s" % (names[kt],names[vt]))

    tester.startTest("Create")
    tx = db.new()
    tx.begin()

    dict = Collections.CollectionFromTypes(db,
                                           Constants.Types.DICTIONARY_COLLECTION,
                                           vt,
                                           keyType = kt,
                                           keyTypeRepositoryId=kfac.typeId,
                                           subTypeRepositoryId=vfac.typeId)


    keys = []
    values = []
    for ctr in range(3):
        keys.append(kfac.next(db))
    for ctr in range(3):
        values.append(vfac.next(db))
        


    dict[keys[0]] = values[0]
    dict[keys[1]] = values[1]
    tester.compare(values[0],dict[keys[0]])
    tester.compare(values[1],dict[keys[1]])
    tx.commit()

    tester.testDone()

    did = dict._4ods_getId()

    tester.startTest("Fetch and change")
    tx = db.new()
    tx.begin()

    dict = db._4ods_getPersistentObjectById(Constants.Types.DICTIONARY_COLLECTION,did)


    keys = test_collection_util.recreate(db,kfac,keys)
    values = test_collection_util.recreate(db,vfac,values)

    tester.compare(values[0],dict[keys[0]])
    tester.compare(values[1],dict[keys[1]])
    dict[keys[1]] = values[2]
    tester.compare(values[2],dict[keys[1]])
    del dict[keys[0]]
    tester.compare(0,dict.has_key(keys[0]))
    tx.commit()
    tester.testDone()

    tester.startTest("Fetch again")
    tx = db.new()
    tx.begin()

    keys = test_collection_util.recreate(db,kfac,keys)
    values = test_collection_util.recreate(db,vfac,values)

    dict = db._4ods_getPersistentObjectById(Constants.Types.DICTIONARY_COLLECTION,did)
    tester.compare(values[2],dict[keys[1]])
    tester.compare(0,dict.has_key(keys[0]))
    tx.commit()
    tester.testDone()

    tester.startTest("Delete")
    tx = db.new()
    tx.begin()
    keys = test_collection_util.recreate(db,kfac,keys)
    values = test_collection_util.recreate(db,vfac,values)
    dict = db._4ods_getPersistentObjectById(Constants.Types.DICTIONARY_COLLECTION,did)
    dict.delete()
    tx.commit()
    tester.testDone()

    tester.startTest("Delete test")
    tx = db.new()
    tx.begin()
    keys = test_collection_util.recreate(db,kfac,keys)
    values = test_collection_util.recreate(db,vfac,values)
    tester.testException(db._4ods_getPersistentObjectById,(Constants.Types.DICTIONARY_COLLECTION,did),FtodsObjectNotFound)
    tx.commit()
    tester.testDone()

    


    tester.groupDone()

                     


def Test(tester):


    tester.startGroup("All Dictionary Interfaces %s Driver" % tester.test_data['driver'])

    #Can't have a full DB here
    manager = Adapters.GetManager()
    adapter = Adapters.GetAdapter()
    if manager.exists(DBNAME):
        manager.destroy(DBNAME)

    manager.create(DBNAME)
    manager.init(DBNAME)

    db = Database.Database()
    db.open(DBNAME)


    try:
        #Some initialization
        tx = db.new()
        tx.begin()
        test_collection_util.Init(db)

        tx.commit()


        types = Constants.g_allTypes[:]
        types.sort()


        for kt in types:
        #if 1:
        #    kt = Constants.Types.FIXEDSTRING

            if Constants.g_listTypes[kt]:
                #Tested later
                continue
            if kt in [Constants.Types.VOID,
                      Constants.Types.BLOB,
                      Constants.Types.EXCEPTION]:
                #Cannot have a collection of voids or blobs
                continue

            for vt in types:
            #if 1:
            #    vt = Constants.Types.FIXEDSTRING
                if Constants.g_listTypes[vt]:
                    #Tested later
                    continue
                if vt in [Constants.Types.VOID,
                          Constants.Types.BLOB,
                          Constants.Types.EXCEPTION]:
                    #Cannot have a collection of voids or blobs
                    continue


                tester.startGroup("Dictionary Interface")
                test_dictionary_interface(tester,db,kt,vt)
                tester.groupDone()
                tester.startGroup("Dictionary Persistence")
                test_dictionary_persistence(tester,db,kt,vt)
                tester.groupDone()

                for f in test_collection_util.factories.values():
                    f.reset()


        tester.groupDone()
    finally:
        db.close()



