/*
 * BILinkServlet.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.awt.Dimension;

import java.io.IOException;
import java.io.PrintWriter;

import java.util.Vector;

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

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.dss.dataSource.client.QueryClient;
import oracle.dss.selection.Selection;
import oracle.dss.selection.step.AllStep;
import oracle.dss.thin.beans.BIConstants;
import oracle.dss.thin.beans.ChildThinBeanUI;
import oracle.dss.thin.beans.EventTargetImpl;
import oracle.dss.thin.beans.ThinBeanUI;
import oracle.dss.thin.beans.crosstab.CrosstabBean;
import oracle.dss.thin.beans.crosstab.ThinCrosstab;
import oracle.dss.thin.beans.dataView.Presentation;
import oracle.dss.thin.beans.dataView.PresentationBean;
import oracle.dss.thin.beans.graph.ThinGraph;
import oracle.dss.thin.beans.lov.LOVContainer;
import oracle.dss.thin.beans.lov.LOVContainerBean;
import oracle.dss.thin.beans.lov.LOVEvent;
import oracle.dss.thin.beans.lov.LOVListener;
import oracle.dss.thin.beans.tools.ViewTypeTool;
import oracle.dss.thin.servlet.ServletQueryParameterProvider;
import oracle.dss.thin.servlet.ServletRequestHandler;
import oracle.dss.util.DataSource;


/** 
 * The main class for the BILinkServlet sample. This sample extends the
 * BIServlet sample.
 * <P>
 * The BILinkServlet sample illustrates the following:
 * <ol>
 * <li>How to create linked Crosstab and Graph</li>
 * <li>How to use LOVContainer to display a large lists of dimension members of the page control</li>
 * </ol>
 * <P>
 */

public class BILinkServlet 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);
    
    //make sure 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());

    String pageState = provider.getQueryParameter(CURRENT_PAGE_NAME);
    if (pageState == null || pageState.equals("Pres"))
      setCurrentPage(PRESENTATION_PAGE);

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

    // 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. Thin beans are
    // registered with a handler in the initializeThinBeans().
    // 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 (ThinBeanUI.EVENT_RESPONSE_DONE == nRetVal) {
      return true;
    }

    //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>BI Beans Sample - Linked Views</TITLE>");
    
    StyleSheetBean.sharedInstance().render(renderingContext);
    
    out.println("</HEAD>");
    out.println("<BODY>");

    FormBean rootNode = new FormBean(FORM_NAME);
        
    // render UIX Component (UINode) tree
    switch (getCurrentPage()) {

    case PRESENTATION_PAGE:
      renderPageHeader(out, request, response);

      ThinCrosstab crosstab = (ThinCrosstab)handler.getThinBean(CROSSTAB_NAME);
      CrosstabBean crosstabNode = new CrosstabBean(); 

      crosstabNode.setCrosstab(crosstab);
      rootNode.addIndexedChild(crosstabNode);

      // retrieve the graph from the servlet request handler
      Presentation graph = (Presentation)handler.getThinBean(PRESENTATION_NAME);

      if (graph != null)
        rootNode.addIndexedChild(new PresentationBean(graph));

      rootNode.addIndexedChild(new FormValueBean(CURRENT_PAGE_NAME, "Pres"));
      rootNode.render(renderingContext);
      renderPageFooter(out, request, response);
      break;

    case LOV_PAGE:
      LOVContainer lovContainer = (LOVContainer)handler.getThinBean(LOV_CONTAINER_NAME);
      LOVContainerBean lovContainerBean = new LOVContainerBean(lovContainer);

      rootNode.addIndexedChild(lovContainerBean);
      rootNode.addIndexedChild(new FormValueBean(CURRENT_PAGE_NAME, "Lov"));
      rootNode.render(renderingContext);
      break;
    }
    
    out.println("</BODY>");
    out.println("</HTML>");
  
    return true;
  }
  
  /**
   * Cleans up objects that were 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) {

    // clean up the linked view and any embedded data source
    super.cleanup(biHttpSession);

    ServletRequestHandler handler = biHttpSession.getServletRequestHandler();
    ThinCrosstab crosstab = (ThinCrosstab)handler.getThinBean(CROSSTAB_NAME);

    if (crosstab != null)
      crosstab.getModel().setDataSource(null);
  }

  /**
   * 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. Dervied classes should override to
   * provide custom titles.
   *
   * @return the title of the sample.
   */
  protected String getSampleTitle() {
    return "BI Beans Sample - Linked Views and LOV Container";
  }

  /**
   * Retrieves the description of the sample. Dervied classes should override to
   * provide custom descriptions.
   *
   * @return the description of the sample.
   */
  protected String getSampleDescription() {
    return "This sample displays a crosstab and a graph that are linked together.";
  }
  
  /**
   * Initialize thin beans based on the current page.
   *
   * @param request an HttpServletRequest object that contains the request the
   * client has made of the servlet.
   * @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.
   *
   * @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 defeault data source from the base class
      DataSource data = getDefaultDataSource(request);
      
      // Create a large selection for the product dimension
      // to demonstrate the usage of the LOV
      try {
        Selection sel = new Selection("MDM!D_CS_OLAP.SHAWPRODUCTS");

        sel.setHierarchy("MDM!D_CS_OLAP.SHAWPRODUCTS.PRODUCTS");
        AllStep products = new AllStep(sel.getDimension());

        products.setHierarchy(sel.getHierarchy());
        Vector levels = new Vector();

        levels.add("MDM!D_CS_OLAP.SHAWPRODUCTS.PRODUCTS.L.PRODUCT");
        products.setLevels(levels);
        sel.addStep(products);
        ((QueryClient) data).applySelection(sel);
      }
      catch (Exception e) {
        e.printStackTrace();
      }
    
      // create a crosstab
      crosstab = new ThinCrosstab();
      crosstab.setThinBeanName(CROSSTAB_NAME);
      crosstab.setPagingControlVisible(true);
      crosstab.setDataSource(data);
      handler.registerThinBean(crosstab);

      // create a lov container
      LOVContainer lovContainer = new LOVContainer();

      lovContainer.setThinBeanName(LOV_CONTAINER_NAME);
      lovContainer.addLOVListener(new LOVAdapter(biHttpSession));
      handler.registerThinBean(lovContainer);

      // lovContainer handles the init lov event
      crosstab.setEventTarget(BIConstants.INIT_LOV_EVENT,
        new EventTargetImpl(lovContainer.getThinBeanName(), null));
      handler.registerAlternateSource(LOV_CONTAINER_NAME + "0", lovContainer);

      // create a graph
      Presentation presentation = new Presentation(ViewTypeTool.GRAPH);

      presentation.setThinBeanName(PRESENTATION_NAME);

      // graph will use the same data source as crosstab, so the views will appear 'linked'
      ThinGraph graph = (ThinGraph)presentation.getView();

      graph.setDataSource(data);
      graph.setDrillingEnabled(true);
      graph.setImageSize(new Dimension(400, 250));
      handler.registerThinBean(presentation);  
    }
  }
  
  public void setCurrentPage(int page) {
    m_currentPage = page;
  }

  public int getCurrentPage() {
    return m_currentPage;
  }

  /**
   * Implements the LOVListener interface.
   */
  public class LOVAdapter implements LOVListener {
    protected BIHttpSession m_biHttpSession = null;

    /**
     * Creates a LOVAdapter object.
     *
     * @param biHttpSession the BIHttpSession object.
     */
    public LOVAdapter(BIHttpSession biHttpSession) {
      m_biHttpSession = biHttpSession;
    }

    /**
     * Handles a LOV event
     *
     * @param e the LOVEvent.
     */
    public void handleInitLOVEvent(LOVEvent e) {

      ServletRequestHandler handler = m_biHttpSession.getServletRequestHandler();
      LOVContainer lovContainer = (LOVContainer)handler.getThinBean(LOV_CONTAINER_NAME);

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

      lovContainer.setLOV(crosstab.createLOV(e.getQueryParameterProvider(), ""));
      setCurrentPage(LOV_PAGE);
    }
  }

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

  private static final String CROSSTAB_NAME = "crosstab";
  private static final String LOV_CONTAINER_NAME = "lovContainer";    
  private static final String FORM_NAME = "FormState";
  private static final String CURRENT_PAGE_NAME = "curPage";

  protected static final int PRESENTATION_PAGE = 0;
  protected static final int LOV_PAGE = 1;

  protected int m_currentPage = PRESENTATION_PAGE;

}
