/*
 * BIPPRToolbarServlet.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 javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import oracle.cabo.share.util.CaboHttpUtils;
import oracle.cabo.ui.beans.BaseWebBean;
import oracle.cabo.ui.beans.BodyBean;
import oracle.cabo.ui.beans.form.FormBean;
import oracle.cabo.ui.beans.layout.StackLayoutBean;
import oracle.cabo.ui.beans.RawTextBean;
import oracle.cabo.ui.beans.StyleSheetBean;
import oracle.cabo.ui.html.HTMLWebBean;
import oracle.cabo.ui.ServletRenderingContext;

import oracle.cabo.ui.partial.PartialPageContext;
import oracle.cabo.ui.partial.PartialPageUtils;
import oracle.cabo.servlet.ui.partial.PartialPageEventUtils;

import oracle.dss.thin.beans.BIConstants;
import oracle.dss.thin.beans.EventTargetImpl;
import oracle.dss.thin.beans.ThinBeanUI;
import oracle.dss.thin.beans.dataView.ThinDataviewCommon;
import oracle.dss.thin.beans.dataView.Presentation;
import oracle.dss.thin.beans.dataView.PresentationBean;
import oracle.dss.thin.beans.toolbar.ViewToolbar;
import oracle.dss.thin.beans.toolbar.ViewToolbarBean;
import oracle.dss.thin.beans.tools.ViewToolEvent;
import oracle.dss.thin.beans.tools.ViewToolListener;
import oracle.dss.thin.beans.tools.ViewTypeTool;
import oracle.dss.thin.servlet.ServletQueryParameterProvider;
import oracle.dss.thin.servlet.ServletRequestHandler;



/** 
 * The main class for the BIPPRToolbarServlet sample. This sample extends the
 * BIToolbarServlet sample.
 * <P>
 * The BIPPRToolbarServlet sample illustrates the following:
 * <ol>
 * <li>Using the toolbar to modify the view</li>
 * <li>Enabling partial page rendering</li>
 * </ol>
 * <P>
 */
public class BIPPRToolbarServlet extends BIToolbarServlet {

  /**
   * Processes the request while connected to the OLAP Server and for the BI Beans Catalog.
   *
   * @param request An HttpServletRequest object that contains the request that the
   * client has made of the servlet.
   * @param response An HttpServletResponse object that contains the response
   * that the servlet sends to the client
   *
   * @return <code>true</code> if the request was handled, <code>false</code>
   * otherwise.
   *
   * @throws Exception If the request 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);

    // retrieves a query parameter value from the current request's URL    
    ServletQueryParameterProvider provider = new ServletQueryParameterProvider(
                                             request, response);
    
    // retrieve the request handler from the session. 
    ServletRequestHandler handler = biHttpSession.getServletRequestHandler();

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

    // 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. 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);

    // create the PartialPageContext from the ServletRequest
    PartialPageContext partialContext = PartialPageEventUtils.createPartialPageContext(request);

    // 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>");

    // render the style sheet for the UIX components
    StyleSheetBean.sharedInstance().render(renderingContext);

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

    // prepare UIX Component (UINode) tree
    // add all of the UINodes to a single form and render
    m_pageCount++;

    // add foo to make each URL unique, so that the back button in a partial page refresh scenario 
    // doesn't go back to the beginning of the application
    FormBean rootNode = new FormBean(FORM_NAME, 
                                     request.getRequestURI()+"?foo="+Integer.toString(m_pageCount));
    rootNode.setMethod("POST");

    BodyBean body = new BodyBean();
    body.addIndexedChild(rootNode);

    // add UIX Component (UINode) tree
    addContents(provider, handler, renderingContext, request, rootNode);

    // Render the tree - this automatically performs a partial
    // page render if the PartialPageContext is specified, or
    // a full page render if the PartialPageContext is null.
    PartialPageUtils.renderPartialPage(renderingContext, body, partialContext);

    out.println("</HTML>");
    
    return true;
  }
  
  /**
   * add UIX component tree to the rootNode
   */
  protected void addContents(ServletQueryParameterProvider provider,
                             ServletRequestHandler handler,
                             ServletRenderingContext renderingContext,
                             HttpServletRequest request,
                             FormBean rootNode) throws IOException {

    addPresentation(provider, handler, request, rootNode);
  }

  /**
   * add Presentation and Toolbar to rootNode
   */
  protected void addPresentation(ServletQueryParameterProvider provider,
                                 ServletRequestHandler handler,
                                 HttpServletRequest request,
                                 FormBean rootNode) throws IOException {

    StackLayoutBean stack = new StackLayoutBean();
    rootNode.addIndexedChild(stack);

    addPageHeader(provider, handler, stack);

    String event = provider.getQueryParameter(BIConstants.EVENT);

    // retrieve the toolbar from the servlet request handler
    ViewToolbar viewToolbar = (ViewToolbar) handler.getThinBean(TOOLBAR_NAME);
    if (viewToolbar != null) {
      // add the toolbar as a child of the stack i.e. FormBean
      ViewToolbarBean viewToolbarBean = new ViewToolbarBean(viewToolbar);

      // set partial page rendering targets
      viewToolbar.setPartialRenderEnabled(true);
      viewToolbar.setPartialTargets(new String[]{PRESENTATION_NAME});
      stack.addIndexedChild(viewToolbarBean);
    }

    // retrieve the data view from the servlet request handler
    Presentation presentation = (Presentation)handler.getThinBean(PRESENTATION_NAME);
    if (presentation != null) {
      // set partial page rendering targets
      presentation.setPartialRenderEnabled(true);
      presentation.setPartialTargets(new String[]{TOOLBAR_NAME});

      stack.addIndexedChild(new PresentationBean(presentation));

      // update the data view reference in the toolbar
      if (BIConstants.VIEW_TYPE_CHANGED_EVENT.equalsIgnoreCase(event))
        viewToolbar.setView(presentation.getView());
    }

    addPageFooter(handler, request, stack);
  }

  /**
   * Add the header of the page to the rootNode
   * This section contains a description about the sample.
   */
  protected void addPageHeader(ServletQueryParameterProvider provider,
                               ServletRequestHandler handler,
                               BaseWebBean rootNode) throws IOException {

    String sampleTitle = getSampleTitle();
    RawTextBean h1 = new RawTextBean("<H2>" + sampleTitle + "</H2>");
    rootNode.addIndexedChild(h1);

    String sampleDescription = getSampleDescription();
    RawTextBean desc = new RawTextBean(("<B>" + sampleDescription + "<B>"));
    rootNode.addIndexedChild(desc);

    rootNode.addIndexedChild(new HTMLWebBean("HR"));
  }

  /**
   * Add the footer of the page to the rootNode.
   * The default implementation provides a link to disconnect from the 
   * OLAPServer and the BI Catalog. The connection page
   * is displayed after the disconnect operation has completed.
   */
  protected void addPageFooter(ServletRequestHandler handler,
                               HttpServletRequest request,
                               BaseWebBean rootNode) throws IOException {

    rootNode.addIndexedChild(new HTMLWebBean("HR"));

    // Render the "Disconnect" link if already connected
    BIHttpSession biHttpSession = getBIHttpSession(request); 
    if (biHttpSession.isConnected()) {
      String disconnectURI = request.getRequestURI();
      // note that you should encode this URI for special characters
      disconnectURI += "?" + DISCONNECT_PARAM + "=" + Boolean.TRUE.toString();

      RawTextBean footer = new RawTextBean("<a href=\"" + disconnectURI + "\">Disconnect</a>");
      rootNode.addIndexedChild(footer);
    }
  }

  /**
   * 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 this
   * method to provide custom titles.
   *
   * @return The title of the sample.
   */
  protected String getSampleTitle() {
    return "BI Beans Sample - Toolbar/View Interaction with Partial Page Rendering";
  }

  /**
   * Retrieves the description of the sample. Derived classes should override
   * this method to provide custom descriptions.
   *
   * @return The description of the sample.
   */
  protected String getSampleDescription() {
    return "This sample adds partial-page rendering to the interaction between a " +
            "thin-bean toolbar and a presentation.";
  }

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

  protected int m_pageCount = 0;
}
