/*
 * BIDimList.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.javaclient;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
import java.awt.GridLayout;
import java.lang.String;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.tree.TreeSelectionModel;
import oracle.dss.crosstab.Crosstab;
import oracle.dss.dataSource.common.Query;
import oracle.dss.datautil.gui.dimensionList.OLAPDimensionListPanel;
import oracle.dss.datautil.QueryAccess;
import oracle.dss.datautil.QueryAccessDimensionModel;
import oracle.dss.dataView.Dataview;
import oracle.dss.dataView.gui.ToolBar;
import oracle.dss.gridView.gui.GridViewToolBar;
import oracle.dss.gridView.UIGridView;
import oracle.dss.metadataManager.client.MetadataManager;
import oracle.dss.metadataManager.common.MDDimension;
import oracle.dss.metadataManager.common.MDMeasure;
import oracle.dss.metadataManager.common.MDRoot;
import oracle.dss.metadataManager.common.MetadataManagerException;
import oracle.dss.metadataManager.common.MM;
import oracle.dss.metadataUtil.MDU;
import oracle.dss.queryBuilder.QueryBuilder;
import oracle.dss.selection.Selection;
import oracle.dss.selection.step.InvalidStepArgException;
import oracle.dss.selection.step.MemberStep;
import oracle.dss.selection.step.Step;
import oracle.dss.util.DataDirector;
import oracle.dss.util.gui.layout.CrosstabLayout;
import javax.swing.JLabel;

  /**
   * This class shows how to use the Dimension List Bean to modify a  
   * presentation query.
   */
  public class BIDimList extends JFrame {
  private Crosstab m_crosstab;
  private String m_OLAPDim;
  private Query m_query;
  private OLAPDimensionListPanel m_dimList = null;
  private String m_strCurrentDim;
  private String m_strCurrentDimHier;
  private JPanel m_dimView = null;
  private int ADD_ITEM = 1;
  private int REPLACE_ITEM = 0;
  private String listData[][];
  private int selectedComboIndex;
  private BIFrame m_frame;
  private JPanel m_panel;

  /**
   * Constructor for BIDimList.
   *
   * @param title The title of the JFrame.
   */
  public BIDimList(BIFrame parentFrame, String title) {
    super(title);
    m_frame = parentFrame;
    init();
  }

  /** Gets unique Metadata Manager Dimension Names, Dimension and Hierarchy ID's 
      and Short Labels for a given Dimension.
      This information is then saved in an array and the array is used to populate 
      the dimension selection Combo Box and the OLAP Dimension List Box.*/   
  protected String[][] getDimensionDetails() {

  String[] strMeasures = m_query.getMeasures();
  String   strMeasName = null;  
 
  if (strMeasures == null || strMeasures.length == 0) {
    return null;
  }

  // Get First Measure in the Query
  String strSelectedMeas = strMeasures[0];

  try {

    // Retrieve Metadata measure unique ID 
    MDMeasure firstMeasure = m_frame.getMetadataManager().getMeasure(MM.UNIQUE_ID, strSelectedMeas);

    // Get the Dimensions for the measure
    MDDimension[] mdDimensions = firstMeasure.getDimensions();

    // Create Array to hold Dimension Short Name
    // [0] [x] - Dimension Name
    // [1] [x] - Dimension ID
    // [2] [x] - Default Hierarchy ID
    // [3] [x] - Dimension Short Label
    // Where x represents the index for each dimension
    String[][] strDimensionInfo = new String[4][mdDimensions.length];

    // Cycle over the dimensions for the measure    
    for (int i = 0; i < mdDimensions.length; i++) {
      
      // Retrieves the name of the dimension
      strDimensionInfo[0][i] = mdDimensions[i].getName();

      // Retrieves the Dimension ID for the Dimension
      strDimensionInfo[1][i] = mdDimensions[i].getUniqueID();

      // Retrieves the Hierarchy ID for the Dimension
      strDimensionInfo[2][i] = mdDimensions[i].getDefaultHierarchy().getUniqueID(); 

      // Retrieve the Shortname for the dimension
      strDimensionInfo[3][i] = mdDimensions[i].getShortLabel();

      if (strDimensionInfo[0][i].equals(m_OLAPDim)) {        

        // Sets the Dimension ID once the dimension name is found
        m_strCurrentDim = strDimensionInfo[1][i];

        // Sets the Hierarchy ID once the dimension name is found
        m_strCurrentDimHier = strDimensionInfo[2][i];

        // Set the list Index for the Dimension Selection Combo ListBox
        // this ensures the selected dimension is selected in the combo box.
        selectedComboIndex = i;
      }
     }
         return strDimensionInfo;
   }
       catch (MetadataManagerException mme) {
        m_frame.showExceptionDialog(this, mme);
        return null;
       }
  }


  /**
   * This method creates a new Crosstab, sets the DataSource on the crosstab
   * and adds the Crosstab, OLAP Dimension List Panel, Dimension Combo Box and 
   * buttons to the frame.
   * @param dimToDisplay The name of the dimension to be display in the OLAP Dimension List Panel. */ 
  protected void createDefaultView(String dimToDisplay) {

    // Stores the current dimension being displayed 
    m_OLAPDim = dimToDisplay;

    // Create panels to contain UI Objects
    JPanel pnlView = new JPanel();

    // Create Panel to Contain the Crosstab
    JPanel crossView = new JPanel();
    
    // Create the panel to hold the dimension list
    m_dimView = new JPanel();

    // Define the Combo Box to hold a list of dimensions
    JComboBox	listbox;

     //Define the Add and Remove Buttons
    JButton addBtn = new JButton("Add >>");
    JButton replaceBtn = new JButton("Replace >>");

    // Create a new Crosstab
    m_crosstab = new Crosstab();
    m_crosstab.setPagingControlVisible(true);
    
    // Create Default Query used in the crosstab
    m_query = m_frame.getDefaultQuery();

   // getDimensionDetails method:
   // Retrieves information about the dimensions associated with
   // the current measure which appears in the Crosstab query.
   // This information includes Dimension Name, Dimension ID, Hierarchy ID
   // and Short Label,all generated by the Metadata Manager.
   // The information in the resulting array is used to populate the Combo 
   // ListBox and the OLAP Dimension Listbox.
    listData = getDimensionDetails();

    // Attach the query to the crosstab
    m_crosstab.setDataSource(m_query);
    
    // Create the OLAPDimensionListPanel 
    m_dimList = createDimList();

    // Set main panel layout and size
    pnlView.setLayout(new BorderLayout());
    pnlView.setPreferredSize(new Dimension(551, 407));

	 // Create a new listbox control and populate it with an
   // array holding the names of all the dimensions
	 listbox = new JComboBox(listData[3]);

   // The Index of the listbox is set to the dimension chosen
   // by default.
   listbox.setSelectedIndex(selectedComboIndex);

   // Action Listener for the Dimension Combo ListBox
   listbox.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {

        // Retrieve the chosen dimension name
        JComboBox cb = (JComboBox)e.getSource();
        String dimName = (String)cb.getSelectedItem();
        
        int chosenItem = cb.getSelectedIndex();

        // Sets the Dimension and Hierarchy ID's for the dimension
        // diplayed in the dimension listbox.

        // Sets the Dimension ID
        m_strCurrentDim = listData[1][chosenItem];

        // Sets the Dimension Hierarchy ID
        m_strCurrentDimHier = listData[2][chosenItem];

        // Remove the current dimlist
        m_dimView.remove(m_dimList);
        
        // Create new Dimlist based on the active view dimensions
        m_dimList = createDimList();

        // Add the new dimlist to the panel
        m_dimView.add(m_dimList);
        
        // Refresh the Panel
        m_panel.revalidate();
        
     }
   });

    // Create a panel containing the add and remove buttons
    JPanel buttonPnl = new JPanel();
    buttonPnl.setLayout(new GridLayout(2, 1, 5, 5));
    buttonPnl.add(addBtn);
    buttonPnl.add(replaceBtn);
    buttonPnl.setMaximumSize(buttonPnl.getPreferredSize());

    // Create a button box to constrain the button panel
    Box buttonBox = Box.createVerticalBox();
    buttonBox.add(Box.createGlue());
    buttonBox.add(buttonPnl);
    buttonBox.add(Box.createGlue());

    // Create Panel to Contain the Combo Box Components    
    JPanel comboView = new JPanel();
    JLabel lblCombo = new JLabel();
    lblCombo.setText("Choose : ");
    comboView.setLayout(new BorderLayout());
    comboView.add(listbox, BorderLayout.CENTER);
    comboView.add(lblCombo, BorderLayout.WEST);

    // Add the dimension list and button box to a panel
    m_dimView.setLayout(new BorderLayout());
    m_dimView.add(m_dimList, BorderLayout.CENTER);
    m_dimView.add(buttonBox, BorderLayout.EAST);
    m_dimView.add(comboView, BorderLayout.NORTH );

    // Add the crosstab and toolbar to a panel
    crossView.setLayout(new BorderLayout());
          
    // Add the Crosstab to the Panel
    crossView.add(m_crosstab,BorderLayout.CENTER);
    
    // Use re-sizable Splitpane container to hold Dimension List and Buttons
    JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, m_dimView, crossView);

    // Add Splitter container with all child JPanel components to the main panel
    m_panel.add(splitPane);
    m_panel.validate();
 
   // Event Listener for Add Button
    addBtn.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent menuEvent) {
           applyDimListSelection(ADD_ITEM);
        }
      });

   // Event Listener for Replace Button
    replaceBtn.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent menuEvent) {
           applyDimListSelection(REPLACE_ITEM);
        }
      });

  }

  /**
   * Clean up method. This method first removes
   * crosstab from the frame and then disables appropriate buttons 
   */
  protected void cleanUp() {
      
    if(m_crosstab != null) {
      m_crosstab.setDataSource(null);
      m_dimList = null;
      m_crosstab = null;
    }
    dispose();
    }

  /**
   * Initialize the user interface.
   */
  protected void init() {
    m_panel = new JPanel();
    // Set a BorderLayout on the display panel
    m_panel.setLayout(new BorderLayout());
    getContentPane().removeAll();
    getContentPane().add(m_panel, BorderLayout.CENTER);
  
    // add a listener to listen for the window closing event
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        cleanUp();
      }
    });
    
    // Create a multi-panel page containing a crosstab based on a default Query,
    // an OLAPDimensionList Panel and selection buttons to add or replace dimension
    // selections. The parameter for this method represents the dimension displayed
    // in the OLAPDimensionList panel when it's first displayed.
    createDefaultView("CHANNEL");

  }


  /** Create an OLAPDimensionListPanel for the chosen dimension.   
    * @param Dataview The name of the dataview (crosstab) containing the query,
    * who's dimension will be represented in the OLAP Dimension List Panel */
  private OLAPDimensionListPanel createDimList() {

   OLAPDimensionListPanel newDimList = null;

    // Get the query object embedded in the crosstab
    Query query = (Query) m_crosstab.getDataSource(); 

    // QueryAccess is a class that enables application code to modify a query's
    // selection without it effecting the view.  This means that you do not need
    // to clone the Dimension selection if the OLAPDimensionList is based on the 
    // same query. 
    
    //Grant access to the Query using the queryAccess class
    QueryAccess queryAccess = query.createQueryAccess();    

    // Get the unique ID for both the selected dimension and the hierarchy
    MetadataManager mdm = m_frame.getMetadataManager();

    // Create the Query Access Dimension model that features in the OLAP Dimension List Panel.
    // This includes Metadata Manager unique ID's for the dimension and Hierarchy
    // which are retrieved and stored in m_strCurrentDim and m_strCurrentDimHier.

    // The Query Access Dimension Model specifies the dimension information for the OLAPDimensionListPanel
    QueryAccessDimensionModel qadm = new QueryAccessDimensionModel(queryAccess, null, null,m_strCurrentDim,m_strCurrentDimHier, mdm);

    // Create the OLAP Dimension List by passing the Query Access Dimension 
    // Model created above.
    newDimList = new OLAPDimensionListPanel(this, qadm);  

    // Set a default size for the OLAP dimension list panel
    newDimList.setMinimumSize(new Dimension(205, 300));

    return newDimList;

  }
  
    /**
    Either Replaces or Adds the dimension selection to the Crosstab
    depending on the button selected by the user
    * @param action A constant representing Add or Replace selection */
    private void applyDimListSelection(int action) {

    // Return if there is nothing selected
    if (m_dimList.isSelectionEmpty()) 
      return;

    // Get the Query object for the Crosstab. 
    Query query = (Query) m_crosstab.getDataSource();

    // Get the Selection object for the selected dimension. 
    Selection selection = query.findSelection(m_strCurrentDim);

   //  A query is comprised of a series of SELECT/ADD/KEEP/REMOVE steps.  The
   //  OLAPDimensionListPanel contains a list of selected members that will be
   //  used to create a MEMBERSTEP.  
     
   //  If the user is REPLACING the selection, we remove all steps and replace
   //  it with a new MEMBERSTEP.  If the user is ADDING to the selection, we 
   //  simply add the MEMBERSTEP to the existing list of steps.

    // Get Member step for the selected Dimension that features in the list
    MemberStep step = m_dimList.getSelectedMemberStep();

    try {        
        if (action == ADD_ITEM) 
          // Add to the selection step
          step.setAction(Step.ADD);
        else {
          // Remove all existing selection step(s)
          selection.removeAllSteps();

          // Add to the New selection step(s)
          step.setAction(Step.SELECT);
          }
      }
    catch (InvalidStepArgException e) {
        m_frame.showExceptionDialog(this, e);
      }
   
    // Add the selection step to the list of steps and apply the selection
    // to the query.
    selection.addStep(step);

    try {
        query.applySelection(selection);
      }
    catch (Exception e) {
        m_frame.showExceptionDialog(this, e);
      }
  }

}
