package hirondelle.web4j.database;

import java.sql.Connection;
import java.util.Map;
import java.util.Set;

/**
 Return a {@link Connection} to a database, using a policy defined by the application. 
 
 <P>See {@link hirondelle.web4j.BuildImpl} for important information on how this item is configured. 
 {@link hirondelle.web4j.BuildImpl#forConnectionSource()} 
 returns the configured implementation of this interface.
 
 <P>Here is an example 
 <a href="http://www.javapractices.com/apps/fish/javadoc/src-html/hirondelle/web4j/config/ConnectionSrc.html">implementation</a>, 
 taken from the WEB4J example application.
 
 <P>There are many alternatives for creating or accessing database connections.
 The application programmer can use any technique whatsoever to implement this 
 interface. For example, an implementation may :  
 <ul>
 <li>use a connection pool configured in the server environment (the style  
 used in the example application)
 <li>create a {@link Connection} directly, using the database driver. (Some modern 
 drivers have connection pooling built directly into the driver.)
 <li>use some other means
 </ul>

 <P><span class="highlight">The design of this interface is slightly skewed towards applications 
 that use more than one database.</span> 
 If only one database is used in an application, then this interface is simply implemented
 'as if' there were more than one. In practice, this should be only a minor nuisance. In addition, 
 if a single-database application is extended to use more than one database, the changes will 
 be absorbed naturally by the existing implementation. 
 
 <P>If no database is used at all, then {@link #getDatabaseNames()} returns an emtpy <tt>Set</tt>.

 <P>See {@link SqlId} for related information.
*/
public interface ConnectionSource {
  
  /**
   Read in any necessary configuration parameters.
   
   <P>This method is called by the framework early during startup processing.
   If your implementation of this interface does not use any sort of config 
   information, then it can simply ignore the given <tt>Map</tt> parameter.
   
   <P>In the context of a web application, the given <tt>Map</tt> is populated 
   with the servlet's <tt>init-param</tt> settings in <tt>web.xml</tt>. 
  */
  void init(Map<String, String> aConfig);
  
  /**
   Return the database names accepted by {@link #getConnection(String)}.
   
   <P>Return a <tt>Set</tt> with one or more entries. Each entry must have content.
   If your application does not use a database at all, then you must return an empty <tt>Set</tt>.
  */
  Set<String> getDatabaseNames();  

  /**
   Return a {@link Connection} to the <em>default</em> database.
   
   <P>The default database is selected by the application programmer as representing 
   the principal or main database in the application, against which the majority of 
   SQL statements are executed. (For most applications, this choice will be obvious.) 
   In <tt>.sql</tt> files, SQL statements against the default database 
   do not need an extra qualifier in their identifiers, while those against a non-default 
   database do need an extra qualifier.
   
   <P>Implementations must translate any exceptions into a {@link DAOException}.
   Examples of exceptions that may need translation are <tt>SQLException</tt> 
   and <tt>javax.naming.NamingException</tt>.
  */
  Connection getConnection() throws DAOException;
  
  /**
   Return a {@link Connection} for a specified database (default or non-default). 
   
   <P>The {@link #getConnection()} method is intended for the "default" or 
   principal database used in the application, while this method is 
   intended for all other databases (but may be used for the default as well).
   
   <P>See {@link SqlId} for related information.
   
   <span class="highlight">Here, <tt>aDatabaseName</tt> is a prefix used 
   in <tt>.sql</tt> files as a qualifer to a SQL statement identifier.</span> 
   For example, in an <tt>.sql</tt> file, the SQL statement identifier: 
   <ul>
   <li><tt>LIST_MEMBERS</tt> refers to the default database (no qualifier)
   <li><tt>TRANSLATION.LOCALE_LIST</tt> refers to the '<tt>TRANSLATION</tt>' database. 
   <em>It is this string </em>- '<tt>TRANSLATION</tt>' - <em>which is passed to this method</em>. 
   </ul>  
   
   <P>The values taken by <tt>aDatabaseName</tt> are those returned by {@link #getDatabaseNames()}.
   They may be chosen by the application programmer in any desired way, to clarify the SQL 
   statement identifiers appearing in the <tt>.sql</tt> file(s).
   Typically, an implementation of this interface will internally map these database 
   identifiers into specific connection strings, such as 
   '<tt>java:comp/env/jdbc/blah</tt>' (or whatever is required).
    
   <P>Implementations must translate any exceptions into a {@link DAOException}.
   Examples of exceptions that may need translation are <tt>SQLException</tt> 
   and <tt>javax.naming.NamingException</tt>.
  */
  Connection getConnection(String aDatabaseName) throws DAOException;
}
