/*
 * @author : Umesh Kulkarni
 * @version 1.0
 *
 * Development Environment : Oracle9i JDeveloper
 *
 * Name of the File : UserManagementHelper.java
 *
 * Creation / Modification History
 *    Umesh           26-Apr-2002        Created
 *
 */

package oracle.otnsamples.ibfbs.usermanagement.helper;

// Import Required Packages
import javax.servlet.http.HttpServletRequest; // Servlet Packages

// EJB Classes
import javax.ejb.CreateException;
import java.rmi.RemoteException;

// JNDI Classes

import javax.naming.InitialContext;
import javax.naming.NamingException;

// Utility Classes
import java.util.HashMap;
import java.util.Collection;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

// TradeManagement Classes
import oracle.otnsamples.ibfbs.trademanagement.exception.TradeManagementEventException;

// UserManagement Classes
import oracle.otnsamples.ibfbs.usermanagement.ejb.UserManagementSessionRemote;
import oracle.otnsamples.ibfbs.usermanagement.ejb.UserManagementSessionHomeRemote;
import oracle.otnsamples.ibfbs.usermanagement.exception.UserManagementEventException;
import oracle.otnsamples.ibfbs.usermanagement.exception.ApplicationError;
import oracle.otnsamples.ibfbs.usermanagement.ejb.ContactInfo;
import oracle.otnsamples.ibfbs.usermanagement.ejb.AccountInfo;
import oracle.otnsamples.ibfbs.usermanagement.ejb.TimerInfo;
import oracle.otnsamples.ibfbs.usermanagement.ejb.PreferencesInfo;
import oracle.otnsamples.ibfbs.usermanagement.ejb.AlertsInfo;

// Admin Classes
import oracle.otnsamples.ibfbs.admin.ejb.MailService;
import oracle.otnsamples.ibfbs.admin.ejb.MailServiceHome;

import oracle.otnsamples.ibfbs.trademanagement.helper.StockRateHelper;

/**
 * This Class is a helper Class used in User Management Functionality
 * such as creation of new user account, customizing preferences, customizing
 * alerts etc. In an MVC (Model-View-Controller) Architecture, this class lies
 * in the Model Layer helping to carry out the business functionality.
 *
 * For carrying out the User Management Functionality, this class takes the help
 * of the 'UserManagementSessionFacadeBean' - Session Bean. This Class
 * accesses the enterprise data only through this session facade bean and never
 * accesses the underlying entity beans.
 *
 * @see oracle.otnsamples.ibfbs.usermanagement.ejb.UserManagementSessionFacadeBean.java 
 * 
 */

public class UserManagementHelper {

  // Declare Handler to 'UserManagementSessionFacadeBean'
  // remote interface
  /** Reference to Remote Interface */
  UserManagementSessionRemote     rmr  = null;

  /**
  * Constructor of this Class. Initializes the values of remote interface and
  * home interface to 'UserManagementSessionFacadeBean'.
  *
  * Note that this helper class carries out all the UserManagement Functionality
  * using the Services Provided by 'UserManagementSessionFacadeBean'.
  * @since   1.0
  */
  public UserManagementHelper() {

    try {

      InitialContext ic = new InitialContext();

      // Initialize the Home Interface for 'UserManagementSessionFacadeBean'
      UserManagementSessionHomeRemote rmrh = (UserManagementSessionHomeRemote)
                ic.lookup("java:comp/env/ejb/UserManagementSessionHomeRemote");

      // Initialize Remote Interface
      rmr = rmrh.create();

    } catch (RemoteException ne) { // Trap Remote Errors
      ne.printStackTrace();
    } catch (CreateException ce) { // Trap Errors when Remote Interface is created
      ce.printStackTrace();
    } catch (NamingException ce) { // Trap Errors When Look Up Errors Happen
      ce.printStackTrace();
    }

  }

  /**
   * Method to Check Password and appropriately redirect the User to proper page.
   * If the logged in User is Admin then user is directed to a page where
   * he/she can upload market data and upload market news.
   *
   * If the logged in User is Individual User of the FBS, then he/she is
   * directed to a page where he/she can manage portoflio.
   *
   * If the logged in User is of Organization Type, then the user is directed
   * to a page where user can upload account information for ESOP accounts.
   *
   * Note that ESOP Stands for Employee Stock Options Plan
   *
   * @param  req req Servlet Request Object
   * @return Account Number of the User
   * @exception ApplicationError When Password is incorrect or
   *             account number is invalid.
   * @exception TradeManagementEventException When Populating Stock Rates
   * @since   1.0
   */

  public Integer checkPassword(HttpServletRequest req)
      throws ApplicationError, UserManagementEventException,
             TradeManagementEventException {

    Integer accountNo = new Integer(-1);
    String  password  = null;

    try {

      // Get the Account Number and password entered by the User
      accountNo = new Integer(req.getParameter("AccountNumber").trim());
      password  = req.getParameter("Password").trim();

      if (accountNo == null)
        throw new ApplicationError("Account Number can not be null.");

      if (password == null)
        throw new ApplicationError("Password can not be null.");

      // Check if the account no and password are valid.
      if (rmr.validUser(accountNo, password)) {

        // If Valid User, set the Account No as a attribute in the HTTP Session
        // so that it can be accessed by other pages.
        req.getSession().setAttribute("LOGIN.RESPONSE", accountNo);

        // Get the Contact Info
        ContactInfo cInfo = getContactInfo(accountNo);

        // Set the User Name as attribute so that it can be
        // accessed on every page
        req.getSession().setAttribute("USERNAME.RESPONSE",
                                      cInfo.getFirstName() + " "
                                      + cInfo.getLastName());

        // Get the Account Info and User Type of the logged in User
        AccountInfo aInfo     = getAccountInfo(accountNo);
        String      userType  = aInfo.getUserType();
        String      role      = null;
        String      eventName = null;

        // Based on the User Type of the logged user, assign various roles
        if (userType.equals("I")) {

          role = "USER";

          // Populate Preferences for the User
          HashMap hm = populatePreferences(req);

          // Set Preferences as attribute of the HTTP Session
          req.getSession().setAttribute("PREFS.RESPONSE", hm);

          populateNews(req);
          populateStockRates(req);

        } else {

          if (userType.equals("C")) {
            role      = "CORP";
            eventName = "CORPLOGIN";
          } else {
            if (userType.equals("A")) {
              role      = "ADMIN";
              eventName = "CONFIGUPLOAD";
            }
          }
        }

        // Set the Role in HTTP Session so that it can be acccessed in other pages
        req.getSession().setAttribute("ROLE", role);

        if (eventName != null) {
          req.setAttribute("EVENTNAME", eventName);
        }
      } else {                        // Password is not Correct
        throw new ApplicationError("Password Incorrect. Please provide correct password !!");
      }
    } catch (RemoteException re) {  // Trap Remote Errors
      throw new ApplicationError(
        "You Entered Invalid Account No. Please check your account number. ");
    } catch(NumberFormatException ex) {
      throw new ApplicationError(
        "You Entered Invalid Account No. Please check your account number. ");
    }

    return accountNo;
  }

  /**
   * Method to populate the Admin Timer Information for TradeDetails reporting.
   * The timer information obtained by calling the remote method 
   * getAdminTimerInfo is set in the session attribute ADMINTIMERINFO.RESPONSE. 
   *
   * @param req  Servlet Request Object
   * @exception UserManagementEventException If exception occurs while 
   *                                         accessing the remote method
   * @since   1.0
   */
  public void populateAdminTimerInfo(HttpServletRequest req)
      throws UserManagementEventException {

    Collection  timerInfo   = new ArrayList();

    try {

      // Get the Timer Info
      TimerInfo ti = rmr.getAdminTimerInfo();
      timerInfo.add(ti);

    } catch(RemoteException ex) {

      throw new UserManagementEventException("Remote Exception while " +
                                             " Populating Admin TimerInfo : "
                                             + ex.toString());
    }
    // Set the Stock Rates as attribute of HTTP Session
    req.getSession().setAttribute("ADMINTIMERINFO.RESPONSE", timerInfo);

    return;
  }

  /**
   * This method configures Timer values. The interval to schedule
   * the timer is taken from the request object.
   *
   * @param  req      HttpServletRequest containing timer interval
   * @return Integer  status of configuration 0 - Success, -1 failure
   * @exception ApplicationError if request contains invalid parameters or
   *                             updating the admin timer is not successful
   * @exception UserManagementEventException If exception occurs while 
   *                                         accessing the remote method
   * @since 1.0
   */
  public Integer configReportInterval(HttpServletRequest req)
      throws ApplicationError, UserManagementEventException {

    Collection  timerInfo   = new ArrayList();

    int status = 0;
    int hour   = Integer.parseInt(req.getParameter("TIMERHOURS"));
    int mins   = Integer.parseInt(req.getParameter("TIMERMINS"));

    String retMessage = "";

    // Minimum interval should be 15 minutes
    if ((hour <= 0) && (mins < 15)) {
      throw new ApplicationError(" Minimum interval should be 15 minutes ");
    } else {

      // Construct Timer Information Value Object using the updated information
      TimerInfo ti =  new TimerInfo( new Integer(hour), new Integer(mins) );

      try {

        // Call the remote method to update the admin timer values
        retMessage = rmr.updateAdminAccount(ti);

        timerInfo.add(ti); // Add the Timer Information to the collection

        // Set the collection in the session attribute
        req.getSession().setAttribute("ADMINTIMERINFO.RESPONSE", timerInfo);

      } catch(RemoteException ex) {
        throw new UserManagementEventException("Remote Exception while " +
                                               " updating Admin TimerInfo : "
                                               + ex.toString());
      }
    }
    if (retMessage.equals("NOSUCCESS")) {
      throw new ApplicationError(" Updating Timer Information was not successful ");
    }
    req.setAttribute("InfoMessage", "Admin Timer Info configured successfully");
    return new Integer(status);
  }

  /**
   * Method which changes the password of a particular User. This method
   * assumes that the validation of User entered password is done by the JSP.
   * The validation includes whether both the passwords match or not.
   *
   * @param req req Servlet Request Object
   * @return Status of the operation
   * @exception UserManagementEventException When changing Password
   *                 using Session Facade Bean
   * @exception ApplicationError User Error when changing Password
   * @since   1.0
   */
  public String changePassword(HttpServletRequest req)
      throws UserManagementEventException, ApplicationError {

    // Get the New Password Entered by the User
    String newPassword = (String) req.getParameter("NEWPASSWORD");
    String oldPassword = (String) req.getParameter("OLDPASSWORD");
    String newPassword1 = (String) req.getParameter("NEWPASSWORD1");
    String message      = null;

    if (newPassword == null)
       throw new ApplicationError("New Password can not be null");

    if (oldPassword == null)
       throw new ApplicationError("Old Password can not be null");

    if (newPassword1 == null)
       throw new ApplicationError("Second New Password can not be null");

    if (!newPassword.equals(newPassword1))
       throw new ApplicationError("Both the new passwords must be the same");

    // Variable for holding Account Number
    Integer accountNo = new Integer(-1);

    try {

      accountNo =  (Integer) req.getSession().getAttribute("LOGIN.RESPONSE");

      // Ask the Session Facade Bean to change the password
      message = rmr.changePassword(accountNo, newPassword, oldPassword);

    } catch (RemoteException re) {  // Trap Remote Errors
      throw new UserManagementEventException(
        "Remote Error while changing password. " + re.toString());
    } catch (NumberFormatException ex) {
      throw new ApplicationError(
        "Account Number Provided is wrong. Error While Changing Password : ");
    }

    if (!message.equals("SUCCESS"))
      throw new ApplicationError("Error while changing password. " +
            "You provided wrong value of Old Password. Password is not changed ");

    return message;
  }

  /**
   * Method to get the Contact Information for a user account.
   *
   * @param accountNo  Account Number of the logged user
   * @return ContactInfo Value Object encapsulating contact information
   * @exception UserManagementEventException When Getting Contact Information
   *                  using Session Facade Bean
   * @since   1.0
   */
  public ContactInfo getContactInfo(Integer accountNo)
      throws UserManagementEventException {

    // Fetch the Contact Information using Session Facade Bean
    try {
      return rmr.getContactInfo(accountNo);
    } catch (RemoteException re) {  // Trap Remote Errors
      throw new UserManagementEventException(
        "Remote Exception while getting contact info : " + re.toString());
    }
  }

  /**
   * Method to set the Contact Information for a user account.
   *
   * @param accountNumber Account Number of the logged user
   * @param contactInfo   Value Object encapsulating Contact Information
   *                      for the logged user
   * @return Status of the Operation
   * @exception UserManagementEventException Exception raised when Setting
   *            Contact Information using Session Facade Bean
   * @since   1.0
   */
  public String setContactInfo(Integer accountNumber, ContactInfo contactInfo)
      throws UserManagementEventException {

    // Set the Contact Information using Session Facade Bean
    try {
      return rmr.setContactInfo(accountNumber, contactInfo);
    } catch (RemoteException re) {  // Trap Remote Errors
      throw new UserManagementEventException(
        "Remote Exception while setting contact info : " + re.toString());
    }
  }

  /**
   * Method to Update User's Profile. User's profile includes
   * Account Information and Contact Information of the user.
   *
   * @param req  Servlet Request Object
   * @return Status of this Operation
   * @exception UserManagementEventException Exception raised when updating
   *             User Profile Using Session Facade Bean
   * @since   1.0
   */

  public String updateProfile(HttpServletRequest req)
      throws UserManagementEventException {

    // Get the Account Number
    Integer accountNo =
      (Integer) req.getSession().getAttribute("LOGIN.RESPONSE");

    // Construct Contact Information Value Object using the updated information
    ContactInfo contactInfo = new ContactInfo(req.getParameter("FIRSTNAME"),
                                              req.getParameter("LASTNAME"),
                                              req.getParameter("ORGANIZATION"),
                                              req.getParameter("ADDRESSFIELD"),
                                              req.getParameter("CITY"),
                                              req.getParameter("STATE"),
                                              req.getParameter("COUNTRY"),
                                              req.getParameter("PHONE"),
                                              req.getParameter("EMAIL"),
                                              req.getParameter("MOBILEEMAIL"));

    // Construct Account Information Value Object using the updated information
    AccountInfo accountInfo =
      new AccountInfo("", "", req.getParameter("ALERTMODE"), 0,
                      new Integer(req.getParameter("LINESPERPAGE")));

    // Set the User Name as attribute so that it can be accessed on every page
    req.getSession().setAttribute("USERNAME.RESPONSE",
                                  contactInfo.getFirstName() + " "
                                  + contactInfo.getLastName());

    // Set Contact Information and Account Information to Update Profile
    return this.setContactInfo(accountNo, contactInfo)
           + this.setAccountInfo(accountNo, accountInfo);

  }

  /**
   * Method to get the Account Information for a user account.
   *
   * @param accountNo  Account Number of the logged user
   * @return AccountInfo Value Object encapsulating account information
   * @exception UserManagementEventException Exception raised when
   *            getting Account Information using Session Facade Bean
   * @since   1.0
   */

  public AccountInfo getAccountInfo(Integer accountNo)
      throws UserManagementEventException {

    // Fetch the Account Information using Session Facade Bean
    try {
      return rmr.getAccountInfo(accountNo);
    } catch (RemoteException re) {  // Trap Remote Errors
      throw new UserManagementEventException(
        "Remote Exception while getting account info : " + re.toString());
    }
  }

  /**
   * Method to set the Account Information for a user account.
   *
   * @param accountNo  Account Number of the logged user
   * @param AccountInfo  Account Information Value Object encapsulating
   *                     Account Information of the logged user
   * @return Status of the Operation
   * @exception UserManagementEventException Exception raised when
   *            Setting Account Information using Session Facade Bean
   * @since   1.0
   */

  public String setAccountInfo(Integer accountNumber, AccountInfo accountInfo)
      throws UserManagementEventException {

    try {
      // Set the Account Information using Session Facade Bean
      return rmr.setAccountInfo(accountNumber, accountInfo);
    } catch (RemoteException re) {  // Trap Remote Errors
      throw new UserManagementEventException(
        "Remote Exception while setting account info : " + re.toString());
    }
  }


  /**
   * Method to get the Preferences Information for a user account. Note that
   * the Preferences Information is returned as a Collection of
   * PreferencesInfo Class.
   *
   * @param accountNo  Account Number of the logged user
   * @return Collection of PreferencesInfo Object.
   *       PreferencesInfo is a Value Object used to reduce the network traffic.
   * @exception UserManagementEventException Exception raised when
   *            getting Preferences Information using Session Facade Bean
   * @since   1.0
   */
  public Collection getPreferencesInfo(Integer accountNo)
      throws UserManagementEventException {

    try {
      // Fetch Preferences by calling method in 'UserManagementSessionFacadeBean'
      return rmr.getPreferences(accountNo);
    } catch (RemoteException re) {  // Trap Remote Errors
      throw new UserManagementEventException(
       "Remote Exception while getting preferences info : " + re.toString());
    }
  }

  /**
   * Method to get the Alerts Information for a user account. Note that the
   * Alerts Information is returned as a Collection of AlertsInfo Class.
   * AlertsInfo is a Value Object used to reduce the network traffic.
   *
   * @param accountNo  Account Number of the logged user
   * @return Collection of AlertsInfo Object.
   * @exception UserManagementEventException Exception raised when
   *            getting Alerts Information using Session Facade Bean
   * @since   1.0
   */

  public Collection getAlertsInfo(Integer accountNo)
      throws UserManagementEventException {

    // Fetch the Alerts Information by taking the help
    // of 'UserManagementSessionFacadeBean'
    try {
      return rmr.getAlerts(accountNo);
    } catch (RemoteException re) {  // Trap Remote Errors
      throw new UserManagementEventException(
        "Remote Exception while getting alerts info : " + re.toString());
    }
  }

  /**
   * Method to change the Alerts Information for a user account.
   *
   * @param req Servlet Request Object
   * @return Status of the operation
   * @exception UserManagementEventException Exception raised when
   *            Changing Alert Information using Session Facade Bean
   * @since   1.0
   */
  public String changeAlertInfo(HttpServletRequest req)
      throws UserManagementEventException {

    // Get the Account No
    Integer accountNo =
      (Integer) req.getSession().getAttribute("LOGIN.RESPONSE");

    // Get the SYMBOL
    String symbol     = req.getParameter("SYMBOL").toUpperCase();
    String retMessage = "NOSUCCESS";

    // Check Whether the Alert corresponding to given Symbol Need not be deleted
    if (req.getParameter("DELFLAG").equals("NO")) {

      // Initialize a new AlertInfo Value Object
      AlertsInfo aInfo =
        new AlertsInfo(symbol, new Integer(req.getParameter("MINLIMIT")),
                       new Integer(req.getParameter("MAXLIMIT")));

      // Change the Alert Information
      try {
        retMessage = rmr.changeAlertInfo(accountNo, aInfo);
      } catch (RemoteException re) {    // Trap Remote Errors
        throw new UserManagementEventException(
          "Remote Exception while changing alerts info : " + re.toString());
      }
    } else {
      // If this alert has to be deleted
      if (req.getParameter("DELFLAG").equals("YES")) {
        try {
          // Using the Session facade bean, delete this alert
          retMessage = rmr.deleteAlert(accountNo, symbol);
        } catch (RemoteException re) {  // Trap Remote Errors
          throw new UserManagementEventException(
            "Remote Exception while deleting alerts info : " + re.toString());
        }
      }
    }
    // After Changing the Alert Information, we need to populate this
    // information again so that the effect can be shown immediately
    HashMap hm = populateAlerts(req);

    req.getSession().setAttribute("ALERTS.RESPONSE", hm);

    if (retMessage.equals("SUCCESS")) {
      return retMessage;
    } else {
      throw new UserManagementEventException(
        "Exception while changing alert info : " + retMessage);
    }
  }

  /**
   * Method to change the Preferences Information for a user account.
   *
   * @param req Servlet Request Object
   * @return Status of the operation
   * @exception UserManagementEventException Exception raised when
   *         Changing Preferences Information using Session Facade Bean
   * @since   1.0
   */

  public String changePreferenceInfo(HttpServletRequest req)
      throws UserManagementEventException {

    // Get the Symbol for which Preferences Need to be changed
    String symbol = req.getParameter("SYMBOL").toUpperCase();

    // Get the Account Number
    Integer accountNo  =
      (Integer) req.getSession().getAttribute("LOGIN.RESPONSE");

    String  retMessage = "NOSUCCESS";

    // Check Whether the Preference corresponding to given Symbol
    // need not be deleted
    if (req.getParameter("DELFLAG").equals("NO")) {

      // Initialize a new PreferencesInfo Value Object
      PreferencesInfo pInfo = new PreferencesInfo(symbol,
                                                  req.getParameter("PREFTYPE"));

      try {
        // Using UserManagementSessionFacadeBean, change PreferencesInfo
        retMessage = rmr.changePreferencesInfo(accountNo, pInfo);
      } catch (RemoteException re) {    // Trap Remote Errors
        throw new UserManagementEventException(
          "Remote Exception while changing preferences info : "
          + re.toString());
      }
    } else {
      // If this preference need to be deleted
      if (req.getParameter("DELFLAG").equals("YES")) {
        try {
          // Using UserManagementSessionFacadeBean,
          // delete Preferences corresponding to this symbol
          retMessage = rmr.deletePreference(accountNo, symbol);

        } catch (RemoteException re) {  // Trap Remote Errors
          throw new UserManagementEventException(
            "Remote Exception while deleting preferences : " + re.toString());
        }
      }
    }

    // Populate Preferences Again so that the recent changes
    // becomes visible immediately
    HashMap hm = populatePreferences(req);

    req.getSession().setAttribute("PREFS.RESPONSE", hm);

    if (retMessage.equals("SUCCESS")) {
      return retMessage;
    } else {
      throw new UserManagementEventException(
        "Exception while changing preferences info : " + retMessage);
    }
  }

  /**
   * Method to add a new Alert Setting for a user account.
   *
   * @param req Servlet Request Object
   * @return Status of the operation
   * @exception UserManagementEventException Exception raised when
   *            Adding a new Alert using Session Facade Bean
   * @exception ApplicationError Raised when Symbol is invalid or
   *            preference for the symbol already exists.
   * @since   1.0
   */

  public String addAlert(HttpServletRequest req)
      throws ApplicationError, UserManagementEventException {

    // Get the Account Number
    Integer accountNo =
      (Integer) req.getSession().getAttribute("LOGIN.RESPONSE");

    String  symbol   = req.getParameter("SYMBOL").toUpperCase();
    Integer minLimit = new Integer(req.getParameter("MINLIMIT"));
    Integer maxLimit = new Integer(req.getParameter("MAXLIMIT"));

    if (symbol == null)
      throw new ApplicationError("Symbol Can not be null");

    // Initialize a new AlertInfo Value Object
    AlertsInfo alertInfo  = new AlertsInfo(symbol,minLimit,maxLimit);
    String     retMessage = "NOSUCCESS";

    try {

      // Using the UserManagementSessionFacadeBean,
      // add alert to the existing alerts
      retMessage = rmr.addAlert(accountNo, alertInfo);

    } catch (RemoteException re) {  // Trap Remote Errors
      throw new UserManagementEventException(
        "Remote Exception while adding alerts : " + re.toString());
    }

    // Populate Alerts so that the recently added alert gets added to this list
    HashMap hm = populateAlerts(req);

    req.getSession().setAttribute("ALERTS.RESPONSE", hm);

    if (retMessage.equals("SUCCESS")) {
      return retMessage;
    } else {
      if (retMessage.indexOf("Improper")!= -1) {
        throw new ApplicationError("You supplied invalid symbol value. Please provide valid Symbol.");
      } else {
        throw new ApplicationError("Alert for given symbol already exists. Instead update the alert setting.");
      }
    }
  }

  /**
   * Method to add a new Preference Setting for a user account.
   *
   * @param req Servlet Request Object
   * @return Status of the operation
   * @exception UserManagementEventException Exception raised when
   *            Adding a Preference using Session Facade Bean
   * @exception ApplicationError Raised when Symbol is invalid or
   *            preference for the symbol already exists.
   * @since   1.0
   */

  public String addPreference(HttpServletRequest req)
      throws ApplicationError, UserManagementEventException {

    // Get the Accout Number
    Integer accountNo =
      (Integer) req.getSession().getAttribute("LOGIN.RESPONSE");

    String symbol = req.getParameter("SYMBOL").toUpperCase();
    String prefType = req.getParameter("PREFTYPE");

    if (symbol == null)
      throw new ApplicationError("Symbol Can not be null");

    // Initialize a new PreferencesInfo Value Object for adding it to the
    // existing list of Preferences.
    PreferencesInfo preferencesInfo = new PreferencesInfo(symbol,prefType);
    String          retMessage      = "NOSUCCESS";

    try {

      // Add the Preference
      retMessage = rmr.addPreferences(accountNo, preferencesInfo);

    } catch (RemoteException re) {  // Trap Remote Errors
      throw new UserManagementEventException(
        "Remote Exception while adding preferences : " + re.toString());
    }
    // Populate the preferences so that recent addition of
    // preference is visible immediately
    HashMap hm = populatePreferences(req);

    req.getSession().setAttribute("PREFS.RESPONSE", hm);

    if (retMessage.equals("SUCCESS")) {
      return retMessage;
    } else {
      if (retMessage.indexOf("Improper")!= -1) {
        throw new ApplicationError("You supplied invalid symbol value. Please provide valid Symbol.");
      } else {
        throw new ApplicationError("Preference for given symbol already exists. Instead update the preference setting.");
      }
    }
  }

  /**
   * Method to Sign Up a new User to this FBS. This method creates a new user
   * account and passes the AccountNumber back to the calling method.
   *
   * @param req  Servlet Request Object
   *             Using this object, we can get all the User Information entered
   *             by the user in the SignUp form.
   * @return account Number of created account.
   * @exception UserManagementEventException Exception raised when
   *            Creating a New Account using Session Facade Bean
   * @since   1.0
   */
  public Integer signUp(HttpServletRequest req)
      throws UserManagementEventException {

    Integer accountNo = new Integer(0);

    // Initialize Contact Info Value Object
    ContactInfo contactInfo = new ContactInfo(req.getParameter("FIRSTNAME"),
                                              req.getParameter("LASTNAME"),
                                              req.getParameter("ORGANIZATION"),
                                              req.getParameter("ADDRESS"),
                                              req.getParameter("CITY"),
                                              req.getParameter("STATE"),
                                              req.getParameter("COUNTRY"),
                                              req.getParameter("PHONE"),
                                              req.getParameter("EMAIL"),
                                              req.getParameter("MOBILEEMAIL"));

    Integer linesPerPage = new Integer(0);

    if (!req.getParameter("LINESPERPAGE").equals(""))
       linesPerPage = Integer.decode(req.getParameter("LINESPERPAGE"));

    // Initialize Account Info Value Object
    AccountInfo accountInfo =
      new AccountInfo(req.getParameter("PASSWORD1"),
                      req.getParameter("USERTYPE"),
                      req.getParameter("ALERTMODE"), 25000,
                      linesPerPage);
    try {

      // Using UserManagementSessionFacadeBean, create a new account
      accountNo = rmr.createNewAccount(contactInfo, accountInfo);

    } catch (RemoteException re) {  // Trap Remote Errors
      throw new UserManagementEventException("Remote Exception while sign up : "
                                             + re.toString());
    }
    return accountNo;  // Return the account number of created account
  }



  /**
   *  Method to SignUp a Corporate User.
   * @param email Email Address of the Corporate User
   * @return Account Number of the created account
   * @since   1.0
   */
  public Integer signUpCorporateUser(String email) {

    Integer accountNo = new Integer(0);

    // Initialize a new Contact Info Value Object
    ContactInfo contactInfo = new ContactInfo(" ", " ", " ", " ", " ", " ",
                                              " ", " ", email, " ");

    // Initialize a new Account Info Value Object
    AccountInfo accountInfo = new AccountInfo("welcome", "I", "E", 25000,
                                              new Integer(5));
    try {
      // Create a New Account
      accountNo = rmr.createNewAccount(contactInfo, accountInfo);

    } catch (RemoteException ex) {  // Trap Remote Errors
      System.out.println("Error While Signing Up A Corporate User " + ex);
    }
    return accountNo;
  }

  /**
   * Method to populate Profile (Contact Info and Account Info) for a
   * particular user. After user logged in successfully, his/her
   * Account Number is set as LOGIN.RESPONSE attribute.
   *
   * @param req  Servlet Request Object
   * @return A HashMap data structure containing two objects namely
   *         ContactInfo Value Object and AccountInfo Value Object
   * @exception UserManagementEventException Exception raised when
   *            Populating Profile Information using Session Facade Bean
   * @since   1.0
   */
  public HashMap populateProfile(HttpServletRequest req)
    throws UserManagementEventException {

    HashMap hm = new HashMap();

    try {

      Integer accountNo =
        (Integer) req.getSession().getAttribute("LOGIN.RESPONSE");

      // Get the Contact Info and store in a Hash Map
      hm.put("CONTACTINFO", getContactInfo(accountNo));

      // Get the Account Info and store in a Hash Map
      hm.put("ACCOUNTINFO", rmr.getAccountInfo(accountNo));

    } catch(RemoteException ex) {
      throw new UserManagementEventException("Remote Exception while Populating Profile : "
                                             + ex.toString());
    }
    return hm;
  }

  /**
   * Method to populate Preferences and Alerts(PreferencesInfo and AlertsInfo)
   * for a particular user. After user logged in successfully, his/her
   * Account Number is set as LOGIN.RESPONSE attribute.
   *
   * @param req  Servlet Request Object
   * @return A HashMap data structure containing two collections namely
   *         (a) Collection of PreferencesInfo Value Object
   *         (b) Collection of AlertsInfo Value Object
   * @exception UserManagementEventException Exception raised when
   *          getting either Preferences Info or Alerts Information
   * @since   1.0
   */
  public HashMap populatePreferencesAlerts(HttpServletRequest req)
      throws UserManagementEventException {

    HashMap hm = new HashMap();

    Integer accountNo =
      (Integer) req.getSession().getAttribute("LOGIN.RESPONSE");

    // Get a list of preferences as a collection of PreferencesInfo
    // Value Object and Store it in HashMap
    hm.put("PREFERENCESINFO", getPreferencesInfo(accountNo));

    // Get a list of alerts as a collection of AlertsInfo Value Object
    // and Store it in HashMap
    hm.put("ALERTSINFO", getAlertsInfo(accountNo));

    return hm;
  }

  /**
   * Method to populate a list of Preferences (PreferencesInfo )for a
   * particular user. After user logged in successfully, his/her
   * Account Number is set as LOGIN.RESPONSE attribute.
   *
   * @param req  Servlet Request Object
   * @return A HashMap data structure containing collection namely
   *         (a) Collection of PreferencesInfo Value Object
   * @exception UserManagementEventException Exception raised
   *          when getting Preferences Information
   * @since   1.0
   */
  public HashMap populatePreferences(HttpServletRequest req)
      throws UserManagementEventException {

    HashMap hm = new HashMap();

    Integer acctNo = (Integer) req.getSession().getAttribute("LOGIN.RESPONSE");

    // Get a list of preferences as a collection of PreferencesInfo
    // Value Object and Store it in HashMap
    hm.put("PREFERENCESINFO", getPreferencesInfo(acctNo));

    return hm;
  }

  /**
   * Method to populate a list of Alerts (AlertsInfo )for a particular
   * user. After user logged in successfully, his/her account number is set as
   * LOGIN.RESPONSE attribute.
   *
   * @param req  Servlet Request Object
   * @return A HashMap data structure containing collection namely
   *         (a) Collection of AlertsInfo Value Object
   * @exception UserManagementEventException Exception raised when
   *          getting Alerts Information
   * @since   1.0
   */
  public HashMap populateAlerts(HttpServletRequest req)
      throws UserManagementEventException {

    HashMap hm = new HashMap();

    Integer accountNo =
      (Integer) req.getSession().getAttribute("LOGIN.RESPONSE");

    // Get a list of alerts as a collection of AlertsInfo Value Object
    // and Store it in HashMap
    hm.put("ALERTSINFO", getAlertsInfo(accountNo));

    return hm;
  }

  /**
   * Method to populate a list of Stock News of User's Preferences.
   * Note that the User preference contains Stock Symbol of the company
   * in which he/she is interested in, and preferenceType. PreferenceType
   * can have following 3 Values
   *  'N' = News (User is only interested in Stock News)
   *  'S' = Stock Prices (User is only interested in Stock Prices)
   *  'B' = News and Stock Prices
   *        (User is interested in both News and Stock Prices)
   *
   * @param req  Servlet Request Object
   * @exception UserManagementEventException Exception raised
   *    when getting a NewsDAO
   * @since   1.0
   */
  public void populateNews(HttpServletRequest req)
      throws UserManagementEventException {

    // Initialize the Data Access Object Implementation which Connects
    // to appropriate Database and fetches the News
    NewsHelper newsHelper = new NewsHelper();
    Collection allNews    = new ArrayList();
    List       allSymbols = new ArrayList();

    // Get the User's Preferences
    HashMap hm = (HashMap) req.getSession().getAttribute("PREFS.RESPONSE");
    Collection prefCollection = (Collection) hm.get("PREFERENCESINFO");

    // Loop through all the Preferences for this User and check whether
    // the preference type is either "N" (for News) or "B" (for Both News and
    // Stock Prices)
    Iterator prefIter = prefCollection.iterator();

    while (prefIter.hasNext()) {

      PreferencesInfo pInfo  = (PreferencesInfo) prefIter.next();
      String          symbol = pInfo.getSymbol();

      // Check whether preferenceType is either "N" or "B"
      if ((pInfo.getPreferenceType().indexOf("N") != -1)
              || (pInfo.getPreferenceType().indexOf("B") != -1)) {

        // Add the Symbol to the final list of symbols
        allSymbols.add(symbol);
      }
    }

    // Fetch the News for all the Symbols
    allNews.addAll ( newsHelper.getLatestNews( (String[])allSymbols.toArray(new String[0]) ) );

    // Set the News as attribute of HTTP Session
    req.getSession().setAttribute("NEWS.RESPONSE", allNews);

  }

  /**
   * Method to populate a list of Stock Rates of User's Preferences. Note that
   * the User preference contains Stock Symbol of the company in which he/she
   * is interested in, and preferenceType. PreferenceType can have following
   * 3 Values
   *  'N' = News (User is only interested in Stock News)
   *  'S' = Stock Prices (User is only interested in Stock Prices)
   *  'B' = News and Stock Prices
   *        (User is interested in both News and Stock Prices)
   *
   * @param req  Servlet Request Object
   * @exception TradeManagementEventException Exception raised when getting
   *            a new StockRateDAO Object
   * @since   1.0
   */
  public void populateStockRates(HttpServletRequest req)
      throws TradeManagementEventException {

    // Initialize the Data Access Object Implementation which Connects
    // to appropriate Database and fetches the News
    StockRateHelper srHelper = new StockRateHelper();
    Collection   allRates   = new ArrayList();
    List         allSymbols = new ArrayList();

    // Get the User's Preferences
    HashMap hm = (HashMap) req.getSession().getAttribute("PREFS.RESPONSE");
    Collection prefCollection = (Collection) hm.get("PREFERENCESINFO");

    // Loop through all the Preferences for this User and check whether
    // the preference type is either "S" (for Stock Prices) or "B" (for Both
    // News and Stock Prices)
    Iterator prefIter = prefCollection.iterator();

    while (prefIter.hasNext()) {

      PreferencesInfo pInfo  = (PreferencesInfo) prefIter.next();
      String          symbol = pInfo.getSymbol();

      // Check whether preferenceType is either "S" or "B"
      if ((pInfo.getPreferenceType().indexOf("S") != -1)
              || (pInfo.getPreferenceType().indexOf("B") != -1)) {

        // Add the symbol to the final list of symbols
        allSymbols.add(symbol);
      }
    }

    // Fetch the Stock Rates for the Symbols
    allRates.addAll(srHelper.getLatestRate( (String[])allSymbols.toArray(new String[0]) ));

    // Set the Stock Rates as attribute of HTTP Session
    req.getSession().setAttribute("RATES.RESPONSE", allRates);
  }

  /**
   * A Single Method to populate both Stock News and Stock Rates.
   * This method in turn invokes individual methods to populate
   * Stock News and Stock Rates
   *
   * @param req Servlet Request Object
   * @exception UserManagementEventException Exception raised when
   *       populating News
   * @exception TradeManagementEventException Exception raised when
   *       populating Stock Rates
   * @since   1.0
   */
  public void populateNewsAndRates(HttpServletRequest req)
      throws UserManagementEventException, TradeManagementEventException {

    // Invoke Method to populate Stock News
    populateNews(req);

    // Invoke Method to populate Stock Prices/Rates
    populateStockRates(req);
  }

  /**
   * This method gets the User Account details corresponding to the input Email.
   * Formats the details as a HTML string and send an email to the user.
   *
   * @return String indicating whether sending email was successful
   * @exception UserManagementEventException
   * @since   1.0
   */
  public String sendEmail(HttpServletRequest req)
      throws UserManagementEventException {

    String    returnMessage = "User Account corresponding to the input " +
                              "Email address does not exist in the system";
    Hashtable userHash      = new Hashtable();

    try {

      String email = req.getParameter("EMAIL");

      // Access the EJB-QL method in TradeManagementSessionFacadeBean to get
      // the User Account Details corresponding to the input Email Address
      userHash = rmr.getUserAccount(email);

      Integer accountNumber = (Integer) userHash.get("ACCOUNTNUMBER");

      if (accountNumber != null) {

        // Format the HTML message
        String message = getHTMLMsg(accountNumber,
                                    (String) userHash.get("PASSWORD"),
                                    (String) userHash.get("FIRSTNAME"),
                                    (String) userHash.get("LASTNAME"));

        // Send the Message to the Email id of the User
        sendMessage(email, message);

        returnMessage = "Email has been sent to the entered Email Address " +
                        "with corresponding User Account Details";
      }
    } catch (RemoteException re) {  // Trap Remote Errors
      throw new UserManagementEventException(
        "Remote Exception while getting user account info : " + re.toString());
    } catch (Exception ex) {        // Trap Other Errors
      throw new UserManagementEventException(
        "Exception while getting user account info : " + ex.toString());
    }
    return returnMessage;
  }

  /**
   * Constructs the mail body using HTML tags.
   *
   * @param accountNumber Account number
   * @param password      Password
   * @param firstName     First Name
   * @param lastName      Last Name
   * @return mail body in HTML
   * @since   1.0
   */
  private String getHTMLMsg(Integer accountNumber, String password,
                            String firstName, String lastName) {

    StringBuffer sb = new StringBuffer();

    sb.append("<p>Hello " + firstName + " " + lastName + ",<br></p>");
    sb.append("<p>Please find herewith the Account Number and Password ");
    sb.append("to access OTN Financial Brokerage System<br>for Viewing ");
    sb.append("your Stock Information / Trading.<br>");
    sb.append("<br>Account Number : " + accountNumber + "<br>Password : ");
    sb.append( password + "<br></p>");
    sb.append("<p>Note : Please change the password once you login! </p>");
    sb.append("<br>Happy Trading !! <br> FBS Team.");

    return sb.toString();

  }

  /**
   * Sends the email reminder message to the input email.
   *
   * @param email   Email id input by the User
   * @param message Formatted HTML message string
   * @exception UserManagementEventException
   * @since   1.0
   */
  private void sendMessage(String email, String message)
      throws UserManagementEventException {

    try {

      InitialContext ctx = new InitialContext();

      // Lookup for the mailservice bean in the JNDI tree
      MailServiceHome mailServiceHome =
        (MailServiceHome) ctx.lookup("MailService");

      // Get an instance of  mailservice
      MailService mailService = mailServiceHome.create();

      // Send Mail to the input email address with the input message
      mailService.sendMail(email, "reminder@fbs.com",
                           "OTN FBS : AccountNumber/Password Reminder",
                           message);

    } catch (Exception ex) {  // Trap Other Errors
      throw new UserManagementEventException("Exception while sending mail : "
                                             + ex.toString());
    }
  }



}