package org.jcon.df;

import org.jcon.ba.system.BeanPriv;
import org.jcon.ba.system.BasketServices;
import org.jcon.df.request.Translator;
import org.jcon.df.request.TranslatorType;
import org.jcon.util.DataLib;
import org.jcon.util.GenLib;
import org.jcon.param.Param;
import org.jcon.param.ParamDriven;
import org.jcon.param.ParamDrivenInfo;
import java.util.Hashtable;
import java.util.Vector;

/**
 * Creates Databases on demand plus minor responisiblityes.
 * This is done by containing managers who themselves
 * contain parameter driven workers. Thus this class is
 * entirely parameter driven, a crucial design feature.
 *
 * There must be a module named "translatorTypes" in the
 * same module as this class. Its beans must be all
 * TranslatorType.
 *
 * @author Jack Harich
 */
public class DatabaseFactory implements
    ParamDriven, BeanPriv {

//---------- Private Fields ------------------------------
private Param          param;
private SchemaMgr      schemaMgr;
private ConnectorMgr   connectorMgr;
private BasketServices basketServices;

// Key = database name, Object = DatabaseDef
private Hashtable    databaseDefs = new Hashtable();

// Key = translatorType name, Object = TranslatorType
// Name examples are Sybase, MSAccess
private Hashtable translatorTypes = new Hashtable();

//---------- ParamDriven Implementation ------------------
public void setParam(Param param) {
    this.param = param;
    // Load databaseDefs
    databaseDefs.clear();
    Vector defs = param.getVector("DatabaseDefs");
    for (int i = 0; i < defs.size(); i++) {
        Param defParam = (Param)defs.elementAt(i);
        DatabaseDef def = new DatabaseDef(defParam);
        databaseDefs.put(def.getName(), def);
    }
}
public Param getParam() {
    return param;
}
public boolean applyNewParam(Param newParam) {
    setParam(newParam);
    return true; // Successful
}
public ParamDrivenInfo getParamDrivenInfo() {
    return null;
}
//---------- BeanPriv Implementation ---------------------
public void setBasketServices(BasketServices services) {
    basketServices = services;
    // Load translatorTypes
    translatorTypes.clear();
    Vector instances = basketServices
        .getBranchBeanInstances("translatorTypes");
    for (int i = 0; i < instances.size(); i++) {
        TranslatorType type = (TranslatorType)instances.elementAt(i);
        translatorTypes.put(type.getName(), type);
    }
}
//---------- Properties ----------------------------------
public void setSchemaMgr(SchemaMgr schemaMgr) {
    this.schemaMgr = schemaMgr;
}
public void setConnectorMgr(ConnectorMgr connectorMgr) {
    this.connectorMgr = connectorMgr;
}
//---------- Public Methods ------------------------------
public Database createDatabase(String dbName) {
try {
    Database database = new Database();
    //----- Basic properties
    database.setName(dbName);

    //----- Workers
    DatabaseDef def = (DatabaseDef)databaseDefs.get(dbName);
    if (def == null) {
        GenLib.error("DatabaseFactory.createDatabase()",
            "Cannot find database name '" + dbName + "'");
        return null;
    }
    // Conector
    database.setConnector(
        connectorMgr.createReadOnlyConnector(dbName));

    // Schema
    Schema schema = schemaMgr.getSchema(def.getSchemaName());
    database.setSchema(schema);

    // Translator
    Translator translator = new Translator();

    TranslatorType translatorType = (TranslatorType)
        translatorTypes.get(def.getTranslatorType());
    if (translatorType == null) {
        GenLib.error("DatabaseFactory.createDatabase()",
            "No TranslatorType for database name " + dbName);
        return null;
    }
    translator.setTranslatorType(translatorType);
    translator.setSchema(schema);

    database.setTranslator(translator);

    // Done
    return database;

} catch(Exception ex) {
    GenLib.exception("DatabaseFactory.createDatabase()",
        "Can't create database named '" + dbName + "'.", ex);
//System.exit(1);
    return null;
}
}
public Connector createMutableConnector(String dbName) {
    return connectorMgr.createMutableConnector(dbName);
}
public String[] loadDatabaseNames() {
    return DataLib.convertEnumerationToStringArray(
        databaseDefs.keys(), databaseDefs.size());
}
public Entity getEntity(String schemaName, String entityName) {
    return schemaMgr.getEntity(schemaName, entityName);
}
//---------- Private Methods -----------------------------
//--- Std
private static void print(String text) {
    System.out.println("DatabaseFactory" + text);
}

} // End class
