/*
Copyright (C) 2000-2010  Ministere de la culture et de la communication (France), AJLSM
See LICENCE file
*/
package fr.gouv.culture.sdx.utils.database;

import fr.gouv.culture.sdx.exception.SDXException;
import fr.gouv.culture.sdx.exception.SDXExceptionCode;
import fr.gouv.culture.sdx.utils.AbstractSdxObject;
import fr.gouv.culture.sdx.utils.Identifiable;
import fr.gouv.culture.sdx.utils.SdxObject;
import fr.gouv.culture.sdx.utils.Utilities;
import fr.gouv.culture.sdx.utils.constants.ContextKeys;
import fr.gouv.culture.sdx.utils.constants.Node;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;

import java.io.File;

public class DatabaseBacked extends AbstractSdxObject implements Serviceable {
    //DatabaseBacked objects can be out of sync with a database object based upon
    //the users decision to change database type, this change should be wisely done
    //and a reindexation may be necessary
    public static final String DEFAULT_DATABASE_TYPE = Database.PACKAGE_QUALNAME + "HSQL" + Database.CLASS_NAME_SUFFIX;
    public static final String CLASS_NAME_SUFFIX = "DatabaseBacked";

    public String DATABASE_DIR_NAME = "sdx-database";//defaulted

    protected Database _database = null;
    protected String dbPath = null;
    protected File dbLocation = null;
    protected Configuration databaseConf = null;

    public void configure(Configuration configuration) throws ConfigurationException{
    	configure(configuration, true);
    }

    public void configure(Configuration configuration, boolean useMetadata) throws ConfigurationException {
    	super.configure(configuration);
    	try {

    		super.setId(configuration.getAttribute(Identifiable.ConfigurationNode.ID, super.getId()));

    		if(useMetadata){
    			//establishing the default configuration object
    			Configuration defaultDatabaseConf = (Configuration) Utilities.getObjectFromContext(ContextKeys.SDX.Application.DEFAULT_DATABASE_CONFIGURATION_OBJECT, getContext());
    			if (defaultDatabaseConf == null) defaultDatabaseConf = new DefaultConfiguration("", "");
    			this.databaseConf = configuration.getChild(Utilities.getElementName(Database.CLASS_NAME_SUFFIX), false);
    			//verifying the configuration if not we use a default
    			if (this.databaseConf == null && defaultDatabaseConf != null)
    				this.databaseConf = defaultDatabaseConf;

    			String dbType = databaseConf.getAttribute(Node.Name.TYPE, DEFAULT_DATABASE_TYPE);
    			//reading the database type attribute, if not we use the default, currently "HSQLDatabase"
    			//trying the attribute value, hopefully the user is providing a fully qualified attribute name
    			Object l_obj = Utilities.getObjectForClassName(getLog(), dbType, Database.PACKAGE_QUALNAME, dbType, Database.CLASS_NAME_SUFFIX);
    			Class l_objClass = l_obj.getClass();

    			if (!(l_obj instanceof Database)) {
    				//the object doesn't implement our interface
    				String[] args = new String[3];
    				args[0] = Database.CLASS_NAME_SUFFIX;
    				if (l_objClass != null)
    					args[1] = l_objClass.getName();
    				args[2] = dbType;
    				throw new SDXException(super.getLog(), SDXExceptionCode.ERROR_CLASS_NOT_INSTANCEOF_SDX_INTERFACE, args, null);
    			}

    			SdxObject l_sdxObj = (Database) l_obj;
    			_database = (Database) super.setUpSdxObject(l_sdxObj);
    			//trying to set the _database directory name something like _hsql, or _lucene
    			String dbDirName = _database.getDatabaseDirectoryName();
    			if (Utilities.checkString(dbDirName))
    				this.DATABASE_DIR_NAME = dbDirName;
    			//passing the id to the database, using for building table names in the configure() method
    			_database.setId(super.getId());
    			//configuring the database
    			_database.configure(databaseConf);
    		}

    	} catch (SDXException e) {
    		throw new ConfigurationException(e.getMessage(), e);
    	}


    }

    public void init() throws SDXException {
        if (_database != null) {
            _database.setId(_database.getId());
            _database.init();
        }
    }

    public Database getDatabase() {
        return _database;
    }

    protected String getClassNameSuffix() {
        return DatabaseBacked.CLASS_NAME_SUFFIX;
    }

	/* (non-Javadoc)
	 * @see fr.gouv.culture.sdx.utils.AbstractSdxObject#initToSax()
	 */
	protected boolean initToSax() {
        	this._xmlizable_objects.put("ID", this.getId());
        	this._xmlizable_objects.put("Encoding", this.getEncoding());
        	this._xmlizable_objects.put("XML-Lang", this.getXmlLang());
		return true;
	}

	/**Init the LinkedHashMap _xmlizable_volatile_objects with the objects in order to describ them in XML
	 * Some objects need to be refresh each time a toSAX is called*/
	protected void initVolatileObjectsToSax() {

	}
}
