/*
 * i4drivers.cpp --
 *
 *	This file contains the facility to manage the mapping of string
 *	names to storage driver implementations, as defined in e4drivers.h.
 *
 *	Authors: Jacob Levy and Jean-Claude Wippler.
 *		 jyl@best.com	jcw@equi4.com
 *
 * Copyright (c) 2000-2003, JYL Software Inc.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE, EVEN IF
 * JYL SOFTWARE INC. IS MADE AWARE OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "e4graphimpl.h"

/*
 * Include the header files for all built-in drivers, so that
 * we can initialize them:
 */

#include "mkstorage.h"

/*
 * This hash table maps from a string name to a storage construction
 * function.
 */

static e4_HashTable *drivers = NULL;
static bool initialized = false;

/*
 * Initialize the storage registry and auto-register the built-in drivers.
 */

void
e4_InitializeStorageRegistry()
{
    e4_HashEntry *hPtr;
    int isnew;
    e4_DriverFunctions *dfp;

    if (initialized == true) {
	return;
    }
    initialized = true;

    /*
     * Create the global hash table for drivers.
     */

    drivers = e4_NewHashTable(E4_STRING_KEY);

    /*
     * Now register all built-in drivers.
     */

    /*
     * Metakit driver:
     */

    hPtr = E4_CREATEHASHENTRY(drivers, E4_METAKIT, &isnew);
    if (!isnew) {
	fprintf(stderr, "Whoa! built-in driver multiply registered.\n");
	return;
    }
    dfp = new e4_DriverFunctions(e4_MetakitStorageImpl::GetStorage,
				 e4_MetakitStorageImpl::GetVersionInfo);
    E4_SETHASHVALUE(hPtr, (void *) dfp);
}

/*
 * Register driver functions for a new storage driver.
 */

bool
e4_RegisterStorageFunctions(e4_StorageConstructor scp,
			    e4_StorageVersionGetter svp,
			    const char *drivername)
{
    e4_HashEntry *hPtr;
    e4_DriverFunctions *dfp;
    int isnew;

    /*
     * First of all auto-initialize the storage registry.
     */

    e4_InitializeStorageRegistry();

    /*
     * Now add the new storage driver.
     */

    hPtr = E4_CREATEHASHENTRY(drivers, drivername, &isnew);
    if (!isnew) {
	return false;
    }
    dfp = new e4_DriverFunctions(scp, svp);
    E4_SETHASHVALUE(hPtr, (void *) dfp);

    return true;
}

/*
 * Given a driver name, get its registered storage constructor.
 */

e4_StorageConstructor
e4_GetStorageConstructor(const char *drivername)
{
    e4_HashEntry *hPtr;
    e4_DriverFunctions *dfp;

    /*
     * First of all auto-initialize the storage registry.
     */

    e4_InitializeStorageRegistry();

    /*
     * Now look for the storage constructor.
     */

    hPtr = E4_FINDHASHENTRY(drivers, drivername);
    if (hPtr == NULL) {
	return NULL;
    }
    dfp = (e4_DriverFunctions *) E4_GETHASHVALUE(hPtr);
    if (dfp == NULL) {
	return NULL;
    }
    return dfp->Constructor;
}

e4_StorageVersionGetter
e4_GetStorageVersionGetter(const char *drivername)
{
    e4_HashEntry *hPtr;
    e4_DriverFunctions *dfp;

    /*
     * First of all auto-initialize the storage registry.
     */

    e4_InitializeStorageRegistry();

    /*
     * Now look for the storage constructor.
     */

    hPtr = E4_FINDHASHENTRY(drivers, drivername);
    if (hPtr == NULL) {
	return NULL;
    }
    dfp = (e4_DriverFunctions *) E4_GETHASHVALUE(hPtr);
    if (dfp == NULL) {
	return NULL;
    }
    return dfp->StorageVersionGetter;
}

/*
 * Unregister a named storage driver from the storage registry.
 */

bool
e4_UnregisterStorageFunctions(const char *drivername)
{
    e4_HashEntry *hPtr;

    /*
     * First of all auto-initialize the storage registry.
     */

    e4_InitializeStorageRegistry();

    /*
     * Now delete the driver from the storage constructor.
     */

    hPtr = E4_FINDHASHENTRY(drivers, drivername);
    if (hPtr == NULL) {
	return false;
    }
    delete (e4_DriverFunctions *) E4_GETHASHVALUE(hPtr);
    e4_DeleteHashEntry(hPtr);

    return true;
}

/*
 * Check whether a driver is registered under the given name.
 */

bool
e4_NamedDriverExists(const char *drivername)
{
    e4_HashEntry *hPtr;

    /*
     * First of all auto-initialize the storage registry.
     */

    e4_InitializeStorageRegistry();

    /*
     * Now retrieve the record for the given driver name, if present.
     */

    hPtr = E4_FINDHASHENTRY(drivers, drivername);
    if (hPtr == NULL) {
	return false;
    }
    return true;
}
