package org.jcon.df;

import org.jcon.ba.system.BeanActionStart;
import org.jcon.ba.system.BeanPriv;
import org.jcon.ba.system.BasketServices;
import org.jcon.df.column.ColumnDef;
import org.jcon.util.DataLib;
import org.jcon.util.GenLib;
import org.jcon.util.msg.Message;
import org.jcon.util.msg.MessageDef;
import org.jcon.util.msg.MessageService;
import java.util.Hashtable;
import java.util.Vector;

/**
 * Manages a collection of Schemas. Its most important
 * responsibility is providing Schemas.
 *
 * The tree MUST have one item per schema in an item
 * named "schemas" in the same module as schemaMgr.
 * Below that they can be organized any way, but each Bean
 * instance must be an Entity.
 *
 * @author Jack Harich
 */
public class SchemaMgr implements BeanActionStart,
    BeanPriv, MessageService {

//---------- Private Fields ------------------------------
// Key = schemaName, Object = Schema
private Hashtable schemas = new Hashtable();

private BasketServices basketServices;
private boolean        schemasLoaded;

//---------- BeanActionStart Implementation --------------
public void start() {
    loadSchemas(); // For testing, can remove
}
//---------- BeanPriv Implementation ---------------------
public void setBasketServices(BasketServices services) {
    basketServices = services;
}
//---------- MessageService Implementation --------------
public void serviceMessage(Message message) {
    String messageName = message.getName();

    if (messageName == "AcquireColumnDef") {
        String schemaName = message.getString("SchemaName");
        String columnID = message.getString("ColumnID");
        ColumnDef def = getColumnDef(schemaName, columnID);
        message.set("ColumnDef", def);

    } else {
        print(".processMessage() - Unknown messageName '" + messageName + "'");
    }
}
public MessageDef[] getServiceMessageDefs() {
    MessageDef[] defs = new MessageDef[1];
    defs[0] = new MessageDef("AcquireColumnDef", this);
    defs[0].add("SchemaName", String.class, "The schema to use.");
    defs[0].add("ColumnID", String.class, "The ColumnID to use.");
    defs[0].add("ColumnDef", org.jcon.df.column.ColumnDef.class, "The returned ColumnDef.");
    return defs;
}
//---------- Public Methods ------------------------------
/**
 * Returns the schema named schemaName. Complains and
 * returns null if not found.
 */
public Schema getSchema(String schemaName) {
    if (! schemasLoaded) loadSchemas();
    Schema schema = (Schema)schemas.get(schemaName);
    if (schema == null) {
        GenLib.error("SchemaMgr.getSchema()",
            "Schema name '" + schemaName + "' not found.");
        return null;
    } else {
        return schema;
    }
}
/**
* Returns the Entity for the schemaName and entityName;
*/
public Entity getEntity(String schemaName, String entityName) {
    Schema schema = getSchema(schemaName);
    return schema.getEntity(entityName);
}
/**
* Returns the ColumnDef for the schemaName and columnID.
* The columnID must be of the format "EntityName.ColumnName".
*/
public ColumnDef getColumnDef(String schemaName, String columnID) {
    Schema schema = getSchema(schemaName);
    
    String entityName = DataLib.getFirstDelimited(columnID, '.');
    String columnName = DataLib.getLastDelimited(columnID, '.');

    return schema.getEntity(entityName).getColumnDef(columnName);    
}    
//---------- Private Methods -----------------------------
/**
 * See requirements above. We may later optimize and only
 * load one schema at a time as needed. ***
 */
private synchronized void loadSchemas() {
    schemas.clear();
    // For each schema name in my basket
    String[] schemaNames = basketServices.
        getBasketItemNames("schemaMgr");

    for (int i = 0; i < schemaNames.length; i++) {
        String schemaName = schemaNames[i];
        print(" - loading schemaName '" + schemaName + "'");

        BasketServices schemaServices = basketServices
            .getBasketServices("schemaMgr." + schemaName);
        Vector entities = schemaServices.
            getBranchBeanInstances();
        // We could assert all are entities ***
        Schema schema = new Schema();
        schema.setName(schemaName);
        schema.setEntities(entities);
        schemas.put(schemaName, schema);
    }
    // Done
    schemasLoaded = true;
}
//--- Std
private static void print(String text) {
    System.out.println("SchemaMgr" + text);
}

} // End class
