/*
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.utils.SdxObject;
import fr.gouv.culture.sdx.utils.save.Saveable;

import org.apache.avalon.framework.parameters.Parameters;

/**
 * A simple database abstraction for managing document-like simple data.
 *
 * <p>
 * Various SDX objects must manage simple data structures : the framework keeps
 * track of applications, an application keeps track of document bases, user and
 * groups, a document base keeps track of repositories, etc. These management tasks
 * share some common properties : (1) they can involve quite complex and variable data
 * structures ; (2) the management tasks need only a few properties from these
 * complex structures ; (3) the underlying entities are all managed by their ids.
 * <p>
 * The Database interface models a Database managing simple entities by their ids
 * and some properties, some may be repeatable. The complex structures behind the
 * entities are stored in XML outside of the database.
 * <p>
 * SDX implements for now only one Database class : a LuceneDatabase, which uses Lucene,
 * SDX's underlying search engine, to manage and retrieve these entities.
 */
public interface Database extends SdxObject, Saveable {

    public static final int SEARCH_MODE_OR = 0;
    public static final int SEARCH_MODE_AND = 1;
    public static final int SEARCH_MODE_NOT = 2;

    /**Key name for the directory path in which to store database contents*/
    final String DATABASE_DIR_PATH = "databaseDirPath";
    final String PACKAGE_QUALNAME = "fr.gouv.culture.sdx.utils.database.";
    final String CLASS_NAME_SUFFIX = "Database";

    /**
     * Gets an entity from the database.
     *
     * @param   id      The needed entity's id.
     */
    public DatabaseEntity getEntity(String id) throws SDXException;

    /**
     * Returns the list of entities from the database.
     */
    public DatabaseEntity[] getEntities() throws SDXException;

    /**
     * Returns a property value from an entity in the database.
     *
     * @param   entityId        The needed entity's id.
     * @param   name    The needed property's name.
     *
     * @return The property is defined, otherwise <code>null</code>. If the property is
     *          defined more than once, the first value is returned.
     */
    public String getPropertyValue(String entityId, String name) throws SDXException;

    /**
     * Returns a repeatable property from an entity in the database.
     *
     * @param   entityId       The needed entity's name.
     * @param   propertyName    The needed property's name.
     *
     *  @return     An enumeration of all values for this property, <code>null</code> is this
     *              property is not defined for this entity.
     */
    public String[] getPropertyValues(String entityId, String propertyName) throws SDXException;


    /** Returns all properties from an entity in the database. */
    public Property[] getProperties(String entityId) throws SDXException;

    /** Saves an entity. */
    public void save(DatabaseEntity ent) throws SDXException;

    /** Deletes an entity. */
    public void delete(DatabaseEntity ent) throws SDXException;

    /*TODO:maybe useful in the future
    public void save(DatabaseEntity[] entities) throws SDXException;*/

    /*TODO:maybe useful in the future
    public void delete(DatabaseEntity[] entities) throws SDXException;*/

    /** Updates an entity. */
    public void update(DatabaseEntity ent) throws SDXException;

    /** Returns the number of entities within this database. */
    public long size();

    /** Empties the database. */
    public void empty() throws SDXException;

    /** Initializes the database. */
    public void init() throws SDXException;

    /**Checks whether an entity with the provided id exists within this database
     * @param id _identifier of the entity
     */
    public boolean entityExists(String id);

    /**Returns a String representing the
     * appropriate wildcard search token
     * for the implementation
     *
     */
    String getWildcardSearchToken();

    /**Returns an array of database entity ids based upon the
     * provided search parameters
     *
     * One can used Database.getEntity(id) after retrieving a
     * list of ids with this method.
     *
     * @param params search params
     */
    public String[] search(Parameters params) throws SDXException;

    /**Utility method for database maintenance,
     * normally used to optimize indices of Lucene based repositories
     *
     * It is the responsibility of the Repository to ensure that
     * unnecessary optimizations are not performed when this method
     * is called.
     */
    public void optimize() throws SDXException;

    /**If the database is a directory based file system implemenation like lucene
     * this method should return a valid name for a directory which may be created to house
     * the database, or in the case of hsql it will return a valid table name
     * @return  A directory name (not a full path)
     */
    public String getDatabaseDirectoryName();

    public DatabaseConnection getConnection() throws SDXException;

    public void releaseConnection(DatabaseConnection conn) throws SDXException;

    /**Adds a property with the provided name and value to the
     * EXISTING entity with the provided id
     *
     * It is up to the implementation to determine proper
     * behavior if the entity with the provided id does not exist.
     *
     * @param entityId  The entity to update
     * @param propertyName  The property to add
     * @param propertyValue The property value
     * @throws SDXException
     */
    public void addProperty(String entityId, String propertyName, String propertyValue) throws SDXException;


    /**Removes a property with the provided name and value to the
     * EXISTING entity with the provided id
     *
     * It is up to the implementation to determine proper
     * behavior if the entity with the provided id does not exist.
     *
     * @param entityId  The entity to update
     * @param propertyName  The property to remove
     * @param propertyValue The property value
     * @throws SDXException
     */
    public void removeProperty(String entityId, String propertyName, String propertyValue) throws SDXException;

    /**Removes a property with the provided name and value from the
     * and EXISTING entity having the name/value pair
     *
     * It is up to the implementation to determine proper
     * behavior if the entity with the provided id does not exist.
     *
     * @param propertyName  The property to remove
     * @param propertyValue The property value
     * @throws SDXException
     */
    public void removeProperty(String propertyName, String propertyValue) throws SDXException;

    String[] search(Parameters params, int mode) throws SDXException;


}
