/*
 * BIExport.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.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Hashtable;
import java.util.Locale;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.JOptionPane;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import oracle.dss.appmodule.client.BISession;
import oracle.dss.appmodule.client.BISessionException;
import oracle.dss.bicontext.BIFilter;
import oracle.dss.bicontext.BISearchResult;
import oracle.dss.bicontext.BISearchControls;
import oracle.dss.bicontext.ManagerFactory;
import oracle.dss.dataView.Dataview;
import oracle.dss.dataSource.common.Query;
import oracle.dss.dataSource.client.QueryManager;
import oracle.dss.metadataManager.common.MDRoot;
import oracle.dss.metadataManager.client.MetadataManager;
import oracle.dss.metadataManager.common.MetadataManagerException;
import oracle.dss.persistence.persistencemanager.common.PersistenceManager;
import oracle.dss.persistence.gui.PersistenceObjectChooser;
import oracle.dss.persistence.gui.PersistenceObjectFilter;
import oracle.dss.security.BIUser;
import oracle.dss.security.BISecurityConstants;
import oracle.dss.security.SecurityDriverManagerImpl;
import oracle.dss.util.persistence.PersistableConstants;
import oracle.dss.util.DefaultErrorHandler;
import oracle.dss.persistence.persistencemanager.common.TransferControl;
import oracle.dss.persistence.persistencemanager.client.InitialPersistenceManager;
import oracle.dss.persistence.PSRConstants;
import javax.naming.NamingException;
import javax.naming.Name;
import javax.naming.CompoundName;
import java.util.Vector;
import java.util.Properties;

/**
 * The main class for the BIExport sample.  
 * <P>
 * The BIExport provides the following functionality:
 * <ol>
 * <li>Open and export a view into a different catalog</li>
 * </ol>
 */
 
public class BIExport extends JFrame
{
  private BIFrame m_frame;  // a reference to the frame
  private JPanel m_panel;   // a reference to the panel
  private JDialog m_dialog; // the connection dialog
  
  private JTextField m_userName;
  private JPasswordField m_password;
  private JTextField m_host;
  private JTextField m_port;
  private JTextField m_sid;
  private JTextField m_connectAsName;

  private String _userName;
  private String _password;
  private String _host;
  private String _port;
  private String _sid;
  private String _connectAsName;

  // the PersistenceManager and BISession for the second connection
  private InitialPersistenceManager m_persistenceManager;
  private BISession m_session;

  // new menu items
  private JMenu m_sampleMenu;
  private JMenuItem m_openMenu;
  private JMenuItem m_exportMenu;

  // By default we create and track a single Presentation in this class.
  // Given that all the Presentation beans are derived from the Dataview
  // class it makes it easier to use a single variable for any type
  // of Presentation.
  // Search for 'instance of' in this class for examples.
  // these two variables keep track of the view that is displayed and
  // it's relative path + name
  Dataview m_activeView = null;
  
  // the path to the opened object
  String m_strName = null;
  
  /**
   * Constructor
   *
   * @param title the window title of the application
   */
  public BIExport(BIFrame parentFrame, String title) {
    super(title);
    m_frame = parentFrame;
    init();
  }

   /**
   * Displays a connection dialog box that asks the user for connection
   * information of the catalog to export to
   */
  private void showExportDialog() {
    m_dialog = new JDialog(this, "Export to Catalog");

    // construct the main panel
    m_userName = new JTextField(_userName);
    m_password = new JPasswordField(_password);
    m_host = new JTextField(_host);
    m_port = new JTextField(_port);
    m_sid = new JTextField(_sid);
    m_connectAsName = new JTextField();
    
    JPanel panel = new JPanel();
    panel.setLayout(new GridLayout(3, 2));
    panel.add(new JLabel("User name:"));
    panel.add(m_userName);
    panel.add(new JLabel("Password:"));
    panel.add(m_password);
    panel.add(new JLabel("Host:"));
    panel.add(m_host);
    panel.add(new JLabel("Port:"));
    panel.add(m_port);
    panel.add(new JLabel("SID:"));
    panel.add(m_sid);
    panel.add(new JLabel("Connect As:"));
    panel.add(m_connectAsName);

    // creates the connect button and handles the case where the connect button
    // is pressed
    JButton connectButton = new JButton("Export");

    connectButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        _userName = m_userName.getText();
        _password = new String(m_password.getPassword());
        _host = m_host.getText();
        _port = m_port.getText();
        _sid = m_sid.getText();
        _connectAsName = m_userName.getText();
        boolean isExported = connect(_userName, _password, _host, _port, _sid, _connectAsName);
        m_dialog.dispose();
        if (isExported)
          showSuccessDialog();
      }
    });

    // creates the cancel button and handles the case where the cancel button
    // is pressed - basically, close the dialog box.
    JButton cancelButton = new JButton("Cancel");
    cancelButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        m_dialog.dispose();
      }
    });

    // create a panel for the buttons
    JPanel buttonsPanel = new JPanel();
    buttonsPanel.add(connectButton);
    buttonsPanel.add(cancelButton);

    // put all these together into the dialog box
    m_dialog.getContentPane().add(panel, BorderLayout.CENTER);
    m_dialog.getContentPane().add(buttonsPanel, BorderLayout.SOUTH);

    // Set the location of the dialog relative to another window - in this case, "this"
    // refers to a frame

    m_dialog.setLocationRelativeTo(this);
    m_dialog.pack();
    // display connect dialog
    m_dialog.setVisible(true);
  }

  /**
   * Displays a success dialog after export
   */
  private void showSuccessDialog() {
    m_dialog = new JDialog(this, "Success");
    
    JPanel panel = new JPanel();
    panel.setLayout(new GridLayout(3, 2));
    panel.add(new JLabel("Successfully exported - "+m_strName));
    
    // creates the OK button and handles the case where the OK button
    // is pressed - basically, close the dialog box.
    JButton okButton = new JButton("OK");
    okButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        m_dialog.dispose();
      }
    });

    // create a panel for the buttons
    JPanel buttonsPanel = new JPanel();
    buttonsPanel.add(okButton);
    
    // put all these together into the dialog box
    m_dialog.getContentPane().add(panel, BorderLayout.CENTER);
    m_dialog.getContentPane().add(buttonsPanel, BorderLayout.SOUTH);

    // Set the location of the dialog relative to another window - in this case, "this"
    // refers to a frame

    m_dialog.setLocationRelativeTo(this);
    m_dialog.pack();
    // display connect dialog
    m_dialog.setVisible(true);
  }

  /**
   * Connects to the OLAP service and BI Beans Catalog using connection
   * information from the BI Configuration file and from the BIConectionDialog.
   *
   * @param userName The name of the user.
   * @param password The credential of the user.
   * 
   * @returns true if the export was successful, false otherwise
   */
  protected boolean connect(String userName, String password, String host, 
                         String port, String sid, String connectAs) {
    // creates a BISession for the export to catalog connection
    Hashtable persistenceEnvironment = new Hashtable();
    persistenceEnvironment.put(PSRConstants.Login.USER_NAME, userName);
    persistenceEnvironment.put(PSRConstants.Login.PASSWORD, password);
    persistenceEnvironment.put(PSRConstants.Login.HOSTNAME, host);
    persistenceEnvironment.put(PSRConstants.Login.PORT, port);
    persistenceEnvironment.put(PSRConstants.Login.SID, sid);
    persistenceEnvironment.put(PSRConstants.Login.JDBC_DRIVERTYPE, "thin");
    persistenceEnvironment.put(javax.naming.Context.SECURITY_PRINCIPAL, userName);
    persistenceEnvironment.put(PSRConstants.STORAGEMANAGER_DRIVER, 
              "oracle.dss.persistence.storagemanager.bi.BIStorageManagerImpl");    
    persistenceEnvironment.put(PSRConstants.BISESSION, m_frame.getBISession());
    BIUser biUser = new BIUser(connectAs);
    m_session = new BISession();
    DefaultErrorHandler m_handler = new DefaultErrorHandler();
    m_session.addErrorHandler(m_handler);
    m_session.setBIUser(biUser);
    try
    {
      m_session.connect();
      persistenceEnvironment.put(PSRConstants.BISESSION, m_session);
      //create initial context
      m_persistenceManager = new InitialPersistenceManager(persistenceEnvironment);
      // now export the presentation to this catalog
      exportPresentation();
    }
    catch (BISessionException bse) {
      m_frame.showExceptionDialog(this, bse);
      return false;
    }
    catch (Exception ex) {
      m_frame.showExceptionDialog(this, ex);
      return false;
    }
    return true;
  }

    /**
   * Initialize the user interface. Calls the superclass initialization
   * and then initializes the applicationsettings and adds additional menu items
   * to the menu.
   */
  protected void init() {

    // Create a menubar
    JMenuBar _menuBar = new JMenuBar();
        
    m_sampleMenu = new JMenu("Exporting presentations");
    // Create an open menu item
    m_openMenu = new JMenuItem("Open presentation");
    // when the open item is selected, open the component
    m_openMenu.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        openPresentation();
        }
      }
    );    
    // Create an export menu item
    m_exportMenu = new JMenuItem("Export presentation");
    // when the export item is selected, export the component
    m_exportMenu.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        showExportDialog();
      }
    }
    );
    
    
    m_sampleMenu.add(m_openMenu);
    m_sampleMenu.add(m_exportMenu);
    _menuBar.add(m_sampleMenu);
    m_openMenu.setMnemonic('O');
    m_exportMenu.setMnemonic('E');
    
    //disable export until user has opened a presentation
    m_exportMenu.setEnabled(false);
    
    m_panel = new JPanel();
    m_panel.setLayout(new BorderLayout());
    
    // put all of these into the frame
    setJMenuBar(_menuBar);
    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();
      }
    });
    
    openPresentation();
    
  }

  /**
   * This method cleans up before returning to the main menu
   */
  protected void cleanUp() {  
    
    m_persistenceManager = null;
    m_session = null;
    m_dialog = null;
    m_strName = null;
    if (m_activeView != null) {
      m_activeView.setDataSource(null);
      m_panel.remove(m_activeView);
      m_activeView = null;
    }
    dispose();
    }


  private Dataview getActiveDataview() {
    return m_activeView;
  }

  protected void openPresentation() {
    MDRoot root = m_frame.getMetadataManager().getMDRoot();

    if (root == null) {
      //Cannot show open dialog because the root folder couldn't be found
      return;
    }

    PersistenceObjectChooser chooser = new PersistenceObjectChooser(root);
    PresentationFilter       filter = new PresentationFilter();
    
    chooser.addPersistenceObjectFilter(filter);
    chooser.removePersistenceObjectFilter(PersistenceObjectChooser.ALL_TYPES);
    chooser.setDefaultPersistenceObjectFilter(filter.getDisplayText());

    int nRetVal = chooser.showOpenDialog(this);

    if (nRetVal != PersistenceObjectChooser.OK_OPTION)
      return;

    m_strName = chooser.getSelectedObjectPathName();
    
    try {
      // getSelectedObjectPathName returns the full path name
      // including the folders. Note that this is a JNDI path and
      // is relative to the root that was specified in the configuration
      // file.
      Dataview  dv = openView(m_strName, m_frame.getMetadataManager());

      if (dv != null)
        displayView(m_strName, dv);
      
      //enable export menu item
      m_exportMenu.setEnabled(true);
    } 
    catch (Exception e) {
      // Unable to open view
      m_frame.showExceptionDialog(this, e);
    }
  }

  protected void exportPresentation() {
    
    try{

      TransferControl control = new TransferControl();
      Vector v = new Vector();
      Properties syntax = new Properties();
      syntax.put("jndi.syntax.direction", "left_to_right");
      syntax.put("jndi.syntax.separator", "/");
      Name name = new CompoundName(m_strName, syntax);
      v.add(name);
      control.setTransferList(v);
      // export object from the primary catalog to a temporary file
      m_frame.getPersistenceManager().exportSubcontext("/"+m_strName+".xml", control);
      // import object from the temporary file to the export catalog
      m_persistenceManager.importSubcontext("/"+m_strName+".xml", control);
    }
    catch (NamingException ne) {
      m_frame.showExceptionDialog(this, ne);
    }    
  }
    
  public void displayView(String strPath, Dataview dv) {
    m_panel.removeAll();
    // Create a new GridLayout for the Panel
    m_panel.add(dv);
    m_panel.revalidate();
    m_panel.repaint();

    // update the state variables that track the active view
    m_activeView = dv;

  }

  Dataview openView(String strName, MetadataManager mdm) {

    if (mdm == null) {
      //Cannot open view because a database connection couldn't be created
      return null;
    }

    Hashtable    env = new Hashtable();
    QueryManager qm = m_frame.getQueryManager();

    // qm can be null which implies that we are running with a config
    // file that doesn't specify a connection to an OLAP source. We
    // will use a static data source in that case.

    // Via this mechanism we can tell the Persistence Manager about the
    // Query Manager it should use to evaluate the query in the Presentation
    // being loaded.
    if (qm != null)
      env.put(Query.QUERY_MANAGER, qm);

    Dataview dv = null;

    try {
      // The reason for using the MetadataManager for loading
      // a view is that the MetadataManager will automatically
      // load any calculations that might be referenced by the
      // query. The calculations need to be present before the
      // query can be evaluated.

      MDRoot root = mdm.getMDRoot();

      dv = (Dataview) root.lookup(strName, env);
    } 
    catch (Exception e) {
      // Unable to open view
      m_frame.showExceptionDialog(this, e);
    }

    return dv;
  }

    public class PresentationFilter implements PersistenceObjectFilter {
    public  String getDisplayText() {
      return "Presentations";
    }

    public Icon getDisplayIcon() {
      return null;
    }

    public String getFilterExpression() {
      return null;
    }

    public Attributes getMatchingAttributes() {
      return null;
    }

    public SearchControls getSearchControls() {
      BISearchControls biControl = new BISearchControls();

      biControl.setResultFilter(new BIPresentationFilter());
      return biControl;
    }

    class BIPresentationFilter implements BIFilter {
      public boolean evaluate(BISearchResult result) {
        if (result.getObjectType().equals(PersistableConstants.FOLDER) ||
          result.getObjectType().equals(PersistableConstants.GRAPH) ||
          result.getObjectType().equals(PersistableConstants.TABLE) ||
          result.getObjectType().equals(PersistableConstants.CROSSTAB))
          return true;
        else
          return false;   
      }
    }
  }
}