/**
 * OW2 Specifications
 * Copyright (C) 2011 Bull S.A.S.
 * Contact: easybeans@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id: DataSourceFactory.java 5903 2011-06-09 06:49:29Z sauthieg $
 * --------------------------------------------------------------------------
 */

package org.osgi.service.jdbc;

import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import javax.sql.XADataSource;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.Properties;

/**
 * A factory for JDBC connection factories.
 *
 * There are 3 preferred connection factories for getting JDBC connections:
 * <ul>
 *   <li>{@literal javax.sql.DataSource}</li>
 *   <li>{@literal javax.sql.ConnectionPoolDataSource}</li>
 *   <li>{@literal javax.sql.XADataSource}</li>
 * </ul>
 *
 * DataSource providers should implement this interface and register it as an OSGi service
 * with the JDBC driver class name in the {@literal OSGI_JDBC_DRIVER_CLASS} property.
 *
 * @author Guillaume Sauthier
 * @version 1.0
 * @threadsafe
 */
public interface DataSourceFactory {

    /**
     * Service property used by a JDBC driver to declare the driver class when registering a
     * JDBC DataSourceFactory service. Clients may filter or test this property to determine
     * if the driver is suitable, or the desired one.
     */
    static final String OSGI_JDBC_DRIVER_CLASS = "osgi.jdbc.driver.class";

    /**
     * Service property used by a JDBC driver to declare the driver name when registering a
     * JDBC DataSourceFactory service. Clients may filter or test this property to determine
     * if the driver is suitable, or the desired one.
     */
    static final String OSGI_JDBC_DRIVER_NAME = "osgi.jdbc.driver.name";

    /**
     * Service property used by a JDBC driver to declare the driver version when registering a
     * JDBC DataSourceFactory service. Clients may filter or test this property to determine
     * if the driver is suitable, or the desired one.
     */
    static final String OSGI_JDBC_DRIVER_VERSION = "osgi.jdbc.driver.version";

    /**
     * The "databaseName" property that {@link DataSource} clients should supply a value for when calling
     * {@link #createDataSource(Properties)}.
     */
    static final String JDBC_DATABASE_NAME = "databaseName";

    /**
     * The "dataSourceName" property that {@link DataSource} clients should supply a value for when calling
     * {@link #createDataSource(Properties)}.
     */
    static final String JDBC_DATASOURCE_NAME = "dataSourceName";

    /**
     * The "description" property that {@link DataSource} clients should supply a value for when calling
     * {@link #createDataSource(Properties)}.
     */
    static final String JDBC_DESCRIPTION = "description";

    /**
     * The "initialPoolSize" property that {@link ConnectionPoolDataSource} and {@link XADataSource} clients should
     * supply a value for when calling {@link #createConnectionPoolDataSource(Properties)} or
     * {@link #createXADataSource(Properties)}.
     */
    static final String JDBC_INITIAL_POOL_SIZE = "initialPoolSize";

    /**
     * The "maxIdleTime" property that {@link ConnectionPoolDataSource} and {@link XADataSource} clients should supply
     * a value for when calling {@link #createConnectionPoolDataSource(Properties)} or
     * {@link #createXADataSource(Properties)}.
     */
    static final String JDBC_MAX_IDLE_TIME = "maxIdleTime";

    /**
     * The "maxPoolSize" property that {@link ConnectionPoolDataSource} and {@link XADataSource} clients should supply
     * a value for when calling {@link #createConnectionPoolDataSource(Properties)} or
     * {@link #createXADataSource(Properties)}.
     */
    static final String JDBC_MAX_POOL_SIZE = "maxPoolSize";

    /**
     * The "maxStatements" property that {@link ConnectionPoolDataSource} and {@link XADataSource} clients should supply
     * a value for when calling {@link #createConnectionPoolDataSource(Properties)} or
     * {@link #createXADataSource(Properties)}.
     */
    static final String JDBC_MAX_STATEMENTS = "maxStatements";

    /**
     * The "minPoolSize" property that {@link ConnectionPoolDataSource} and {@link XADataSource} clients should supply
     * a value for when calling {@link #createConnectionPoolDataSource(Properties)} or
     * {@link #createXADataSource(Properties)}.
     */
    static final String JDBC_MIN_POOL_SIZE = "minPoolSize";

    /**
     * The "networkProtocol" property that {@link DataSource} clients should supply a value for when calling
     * {@link #createDataSource(Properties)}.
     */
    static final String JDBC_NETWORK_PROTOCOL = "networkProtocol";

    /**
     * The "password" property that {@link DataSource} clients should supply a value for when calling
     * {@link #createDataSource(Properties)}.
     */
    static final String JDBC_PASSWORD = "password";

    /**
     * The "portNumber" property that {@link DataSource} clients should supply a value for when calling
     * {@link #createDataSource(Properties)}.
     */
    static final String JDBC_PORT_NUMBER = "portNumber";

    /**
     * The "propertyCycle" property that {@link ConnectionPoolDataSource} and {@link XADataSource} clients should
     * supply a value for when calling {@link #createConnectionPoolDataSource(Properties)} or
     * {@link #createXADataSource(Properties)}.
     */
    static final String JDBC_PROPERTY_CYCLE = "propertyCycle";

    /**
     * The "roleName" property that {@link DataSource} clients should supply a value for when calling
     * {@link #createDataSource(Properties)}.
     */
    static final String JDBC_ROLE_NAME = "roleName";

    /**
     * The "serverName" property that {@link DataSource} clients should supply a value for when calling
     * {@link #createDataSource(Properties)}.
     */
    static final String JDBC_SERVER_NAME = "serverName";

    /**
     * The "url" property that {@link DataSource} clients should supply a value for when calling
     * {@link #createDataSource(Properties)}.
     */
    static final String JDBC_URL = "url";

    /**
     * The "user" property that {@link DataSource} clients should supply a value for when calling
     * {@link #createDataSource(Properties)}.
     */
    static final String JDBC_USER = "user";

    /**
     * Create a new {@link DataSource} using the given properties.
     * @param props The properties used to configure the {@link DataSource}. {@literal null}
     *        indicates no properties. If the property cannot be set on the {@link DataSource}
     *        being created then a SQLException must be thrown.
     * @return A configured {@link DataSource}.
     * @throws SQLException If the {@link DataSource} cannot be created.
     */
    DataSource createDataSource(Properties props) throws SQLException;

    /**
     * Create a new {@link ConnectionPoolDataSource} using the given properties.
     * @param props The properties used to configure the {@link ConnectionPoolDataSource}. {@literal null} indicates no properties. If the property cannot be set on the {@link ConnectionPoolDataSource} being created then a SQLException must be thrown.
     * @return A configured {@link ConnectionPoolDataSource}.
     * @throws SQLException If the {@link ConnectionPoolDataSource} cannot be created.
     */
    ConnectionPoolDataSource createConnectionPoolDataSource(Properties props) throws SQLException;

    /**
     * Create a new {@link XADataSource} using the given properties.
     * @param props The properties used to configure the {@link XADataSource}. {@literal null} indicates no properties. If the property cannot be set on the {@link XADataSource} being created then a SQLException must be thrown.
     * @return A configured {@link XADataSource}.
     * @throws SQLException If the {@link XADataSource} cannot be created.
     */
    XADataSource createXADataSource(Properties props) throws SQLException;

    /**
     * Create a new {@link Driver} using the given properties.
     * @param props The properties used to configure the {@link Driver}. {@literal null} indicates no properties. If the property cannot be set on the {@link Driver} being created then a SQLException must be thrown.
     * @return  A configured {@link Driver}.
     * @throws SQLException If the {@link Driver} cannot be created.
     */
    Driver createDriver(Properties props) throws SQLException;

}
