/*
 * BIQueryToolServlet.java
 *
 * Copyright © 1994-2004, Oracle. All rights reserved. Oracle grants
 * you ("Licensee") a non-exclusive, royalty-free, worldwide license to use,
 * modify and redistribute this software in source and binary code form, provided
 * that (i) this copyright notice and license appear on all copies of the
 * software; (ii) Licensee does not utilize the software in a manner disparaging
 * to Oracle; and (iii) Licensee does not utilize the software in a manner that
 * violates the terms of any Licensee agreement with Oracle.
 */
package samples.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.ServletRequest; 
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;

import oracle.cabo.share.util.CaboHttpUtils;
import oracle.cabo.ui.ServletRenderingContext;

import oracle.cabo.ui.beans.StyleSheetBean;

import oracle.cabo.ui.beans.form.FormBean;
import oracle.cabo.ui.beans.form.FormValueBean;

import oracle.cabo.ui.beans.layout.SeparatorBean;
import oracle.cabo.ui.beans.layout.StackLayoutBean;

import oracle.dss.dataSource.common.Query;
import oracle.dss.util.DataSource;

import oracle.dss.thin.beans.BIConstants;
import oracle.dss.thin.beans.ThinBeanUI;

import oracle.dss.thin.beans.crosstab.CrosstabBean;
import oracle.dss.thin.beans.crosstab.ThinCrosstab;

import oracle.dss.thin.servlet.ServletRequestHandler;
import oracle.dss.thin.servlet.ServletQueryParameterProvider;

import oracle.dss.util.DataDirector;

/** 
 * This sample shows how to create a custom ViewTool implementation.
 * The QueryTool is used to select dimension members based on a condition.
 * This sample shows how to use the QueryTool with a ThinCrosstab.
 * <P>
 * The BIQueryToolServlet derives from BIServlet (Sample 1)
 */
public class BIQueryToolServlet extends BIServlet {
      
  /**
   * Process the request while connected to the OLAP Server and BI Beans Catalog.
   * 
   * @param request an HttpServletRequest object that contains the request the
   * client has made of the servlet.
   * @param response an HttpServletResponse object that contains the response
   * the servlet sends to the client
   *
   * @return <code>true</code> if the request was handled, <code>false</code>
   * otherwise.
   *
   * @throws Exception if the request for the GET could not be handled
   */
  protected boolean processRequest(HttpServletRequest request,
                                    HttpServletResponse response)
                                    throws Exception {

    BIHttpSession biHttpSession = getBIHttpSession(request);

    // Ensure thin beans are initialized
    initializeThinBeans(request, biHttpSession);

    ServletRequestHandler handler = biHttpSession.getServletRequestHandler();

    ServletQueryParameterProvider provider = new ServletQueryParameterProvider(request, response);

    // use locale retrieved from browser
    setLocale(CaboHttpUtils.determineLocale(request));
    handler.setLocale(getLocale());

    // process form fields of all registered ThinBeans
    handler.processInput(provider);    

    // Key Concept: handle thin bean events. The ServletRequestHandler object
    // determines the thin bean object that should handle a thin bean event using
    // the BIConstants.SOURCE parameter from the provider object. The thin beans
    // are registered with the handler object in the initializeThinBeans method.
    // The handleEvent method on the thin bean object is invoked to allow the
    // thin bean to handle the event. The thin bean returns the result of the
    // event handling
    int nRetVal = handler.handleEvent(provider);

    // Test whether processing is completed for the request. The thin bean
    // will return ThinBeanUI.EVENT_RESPONSE_DONE if the
    // BIConstants.EXPORT_EVENT event is handled. No rendering is required
    // after the BIConstants.EXPORT_EVENT event is processed
    if (nRetVal == ThinBeanUI.EVENT_RESPONSE_DONE) {
      return false;
    }

    // Begin generating HTML
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();

    // Create rendering context for UIX Components (UINodes)
    ServletRenderingContext renderingContext = createRenderingContext(request, response);

    // prepare the ServletRenderingContext for output
    renderingContext.prepareOutput(out, null, "text/html", null);

    out.println("<HTML>");
    out.println("<HEAD>");
    out.println("<TITLE>");
    out.println(getSampleTitle());
    out.println("</TITLE>");

    StyleSheetBean.sharedInstance().render(renderingContext);

    out.println("</HEAD>");
    out.println("<BODY>");

    renderPageHeader(out, request, response);

    // Prepare UIX Component (UINode) tree

    // Create a form to hold all the UINodes
    FormBean rootNode = new FormBean(FORM_NAME);

    // Create a stack layout with a separator between each component
    StackLayoutBean stack = new StackLayoutBean();
    stack.setSeparator(SeparatorBean.sharedInstance());
    rootNode.addIndexedChild(stack);

    // Add a Crosstab
    CrosstabBean crosstabNode = new CrosstabBean();
    stack.addIndexedChild(crosstabNode);

    // Add a QueryTool
    BIQueryToolBean queryToolNode = new BIQueryToolBean("");
    stack.addIndexedChild(queryToolNode);

    // Retrieve and set the thin beans onto the UINodes
    ThinCrosstab crosstab = (ThinCrosstab)handler.getThinBean(CROSSTAB_NAME);
    BIQueryTool queryTool = (BIQueryTool)handler.getThinBean(QUERY_TOOL_NAME);

    crosstabNode.setCrosstab(crosstab);
    queryToolNode.setQueryTool(queryTool);

    rootNode.render(renderingContext);

    renderPageFooter(out, request, response);
    
    out.println("</BODY>");
    out.println("</HTML>");

    return true;
  }

  /**
   * This method returns the key for storing the BIHttpSession object on the HTTP session
   *
   * @return The key for storing the BIHttpSession object on the HTTP session
   */
  protected String getHttpSessionKey() {
    return BI_HTTP_SESSION_KEY;
  }

  /**
   * Retrieves the title of the sample. Derived classes should override to
   * provide custom titles.
   *
   * @return the title of the sample.
   */
  protected String getSampleTitle() {
    return "BI Beans Sample - Query Tool";
  }

  /**
   * Retrieves the description of the sample. Derived classes should override to
   * provide custom descriptions.
   *
   * @return the description of the sample.
   */
  protected String getSampleDescription() {
    return "This sample shows how to create a custom query tool, " +
    "which can be used to select dimension members based on a condition.";
  }

  
  /**
   * Initialize thin beans
   *
   * @throws Exception if an error is detected when the thin beans are being initialized.
   */
  private void initializeThinBeans(HttpServletRequest request,
                                 BIHttpSession biHttpSession) throws Exception {
    ServletRequestHandler handler = biHttpSession.getServletRequestHandler();

    ThinCrosstab crosstab = (ThinCrosstab)handler.getThinBean(CROSSTAB_NAME);

    if (crosstab == null) {
      // Retrieve default data source from the base class
      DataSource data = getDefaultDataSource(request);

      // Create and setup the ThinCrosstab
      crosstab = new ThinCrosstab();
      crosstab.setThinBeanName(CROSSTAB_NAME);
      crosstab.setPagingControlVisible(true);
      crosstab.setDataSource(data);
      handler.registerThinBean(crosstab);

      // Create a QueryTool and set ThinCrosstab on it
      BIQueryTool queryTool = new BIQueryTool();
      queryTool.setThinBeanName(QUERY_TOOL_NAME);
      queryTool.setView(crosstab);
      handler.registerThinBean(queryTool);
    }
  }

  /**
   * Cleanup objects allocated by the Servlet. These may include thin beans and
   * custom objects that are cached on the session.
   *
   * @param biHttpSession Provides a way to identify a user across more than one
   * page request or visit to a Web site and to store information about that user.
   */
  public void cleanup (BIHttpSession biHttpSession) {
    ServletRequestHandler handler = biHttpSession.getServletRequestHandler();

    // Cleanup the ThinCrosstab's DataSource
    ThinCrosstab crosstab = (ThinCrosstab)handler.getThinBean(CROSSTAB_NAME);
    if (crosstab != null) {
      DataSource viewDataSource = crosstab.getModel().getDataSource();
      if (viewDataSource != null) {
        // release the data source
        if (viewDataSource instanceof Query) {
          ((Query)viewDataSource).close();
        }

        // break the link between the view and the data source
        crosstab.getModel().setDataSource(null);
      }
    }

    crosstab = null;
  }

  // the key for storing the BIHttpSession object on the HTTP session
  private static final String BI_HTTP_SESSION_KEY = "BIQueryHttpSessionKey";

  // Unique names for the ThinCrosstab and QueryTool
  private static final String CROSSTAB_NAME = "ct";
  private static final String QUERY_TOOL_NAME = "qt";

  // Form name
  private static final String FORM_NAME = "demo";
}
