package hirondelle.web4j;

import javax.servlet.ServletConfig;

import hirondelle.web4j.model.AppException;
import hirondelle.web4j.database.ConnectionSource;

/**
 Perform startup tasks.

 <P>See {@link hirondelle.web4j.BuildImpl} for important information on how this item is configured. 
 {@link hirondelle.web4j.BuildImpl#forStartupTasks()} 
 returns the configured implementation of this interface.

 <P>Allows the application programmer to perform any needed initialization tasks. 
 
 <P>These tasks are performed only once, upon startup (caveat below). 
 For example, the application may need to place items into application scope. Here's an example 
 <a href="http://www.javapractices.com/apps/fish/javadoc/src-html/hirondelle/web4j/config/Startup.html">implementation</a> 
 taken from an example application.
 
 <P>
 See {@link hirondelle.web4j.database.ConnectionSource#init(java.util.Map)}, for startup 
 tasks related to database connections. 
 
 <P>Startup tasks often depend on a database. If all of your databases are running when your app 
 starts up, then all startup tasks will be completed during start-up. 
 
 <P>However, sometimes a database may be down when your application starts up.
 In that case, web4j will keep track of which databases are down. Later, when a request comes into its Controller,
 it will re-test each offending database, to see if it's now running; when the database is seen to be running, then 
 web4j will then pass the name of the database to {@link #startApplication(ServletConfig, String)}.
 (This processing takes place after startup, and thus, in a multi-threaded environment. The framework performs 
 the necessary external synchronization of this class.) 
*/
public interface StartupTasks {
  
  /**
   Perform any startup tasks needed by the application.
   <P>Possible tasks include:
   <ul>
   <li>disseminate values configured in <tt>web.xml</tt>
   <li>place items into application scope, such as code tables read from the database
   <li>set the default {@link java.util.TimeZone}
   </ul>
   
   <P>This method is called by WEB4J near the end of startup processing.  
   It's first called with an empty String for the database name; this is intended for any 
   tasks that may be unrelated to any database at all.
   It's then called again, once for each database defined by {@link ConnectionSource#getDatabaseNames()} (in 
   the iteration order of the <tt>Set</tt> returned by that method).  
   
   <P>Example of a typical implementation:
<pre>
public void startApplication(ServletConfig aConfig, String aDbName) throws DAOException {
  if (!Util.textHasContent(aDbName)){
    //tasks not related to any db
  }
  else if (ConnectionSrc.DEFAULT.equals(aDbName)){
    //tasks related to this db
  }
  else if (ConnectionSrc.TRANSLATION.equals(aDbName)){
    //tasks related to this db
  }
}</pre>

 <P>This method is called N+1 times by the framework, where N is the number of databases. 
 The framework has confirmed that the database is running before it calls this method.
   
   @param aConfig is not a Map, as in other interfaces, since startup tasks 
   often need more than just settings in <tt>web.xml</tt> - for example, placing code tables in app scope will 
   need access to the <tt>ServletContext</tt>.
   @param aDatabaseName refers to one of the names defined by {@link ConnectionSource#getDatabaseNames()}, 
   or an empty string. Implementations of this method should reference those names directly, instead of 
   hard-coding strings.
  */
  void startApplication(ServletConfig aConfig, String aDatabaseName) throws AppException;
  
}
