/*
 * ReportQueryFrame.java
 *
 *  iReport  --  Visual designer for generating JasperReports Documents
 *  Copyright (C) 2002-2003  Giulio Toffoli gt@businesslogic.it
 *
 *  This program is free software; you can redistribute  and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Giulio Toffoli
 *  Via T.Aspetti, 233
 *  35100 Padova ITALY
 *  gt@businesslogic.it
 *
 *
 * Created on 27 maggio 2003, 19.47
 */

package it.businesslogic.ireport.gui;
import it.businesslogic.ireport.*;
import it.businesslogic.ireport.util.*;
import javax.swing.table.*;
import javax.swing.*;
import java.util.*;
import java.sql.*;

import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.design.*;
import net.sf.jasperreports.engine.fill.*;
import bsh.Interpreter;
import java.io.*;

import javax.swing.event.*;
import javax.swing.tree.*;
import java.awt.datatransfer.*;

/** 
 * A dialog which allows the user to enter a SQL query and then choose the
 * fields to use in the report.
 *
 * @author <a href="mailto:gt78@users.sourceforge.net">Giulio Toffoli</a>
 * @author <a href="mailto:phenderson@users.sourceforge.net">Peter Henderson</a>
 */
public class ReportQueryDialog extends javax.swing.JDialog implements ClipboardOwner {
    
    protected static String standard_types[]= new String[]{
        "java.lang.String",
	"java.lang.Object",
	"java.lang.Boolean",
	"java.lang.Byte",
	"java.util.Date",
	"java.sql.Timestamp",
	"java.sql.Time",
	"java.lang.Double",
	"java.lang.Float",
	"java.lang.Integer",
	"java.io.InputStream",
	"java.lang.Long",
	"java.lang.Short",
	"java.math.BigDecimal"    
    };
    
    public FieldReader readerThread = null;
    public static int num = 1;
    
    private JLabel getJLabelStatusSQL()
    {
        return this.jLabelStatusSQL;
    }
    
    /** Creates new form ReportQueryFrame */
    public ReportQueryDialog(java.awt.Frame parent, boolean modal) {
        
        super(parent, modal);
        initComponents();
        this.setSize(520, 500);
        Misc.centerFrame(this);
        
        stoppedChanging.setRepeats(false);
        
        DefaultTreeModel dttm = (DefaultTreeModel)jTree1.getModel();
        DefaultMutableTreeNode root = new DefaultMutableTreeNode();
        jTree1.setModel(new DefaultTreeModel( root ));
        
        jTree1.setCellRenderer( new JBTreeCellRenderer());
        
        jRSQLExpressionArea1.getDocument().addDocumentListener( new DocumentListener() {
            public void changedUpdate(DocumentEvent e) {
                if(isSettingSQLExpression)return;
                //okButton.setEnabled(false);
                stoppedChanging.restart();
            }
            public void insertUpdate(DocumentEvent e) {
                if(isSettingSQLExpression)return;
                //okButton.setEnabled(false);
                stoppedChanging.restart();
            }
            public void removeUpdate(DocumentEvent e) {
                if(isSettingSQLExpression)return;
                //okButton.setEnabled(false);
                stoppedChanging.restart();
            }
        } );
        
        setColumnsError( "Please open a report." );
        if (MainFrame.getMainInstance().getProperties().getProperty("beanClass") != null)
        {
            jTextFieldBeanClass1.setText( MainFrame.getMainInstance().getProperties().getProperty("beanClass") +"");
        }
        
        okButton.setEnabled(false);
    }
    
    /**
     * A timer to detect when the SQL expression area has not been changed, for
     * a short moment. This is to prevent the database being hit with every
     * with every key press.
     */
    javax.swing.Timer stoppedChanging = new javax.swing.Timer( 500, new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            if( automaticlyReadFieldsCheckBox.isSelected() ) {
                processQueryChanged( jRSQLExpressionArea1.getText().trim() );
            }
        }
    } );
    
    
    /**
     * Given a database query string, extract the database columns, then display
     * them. If there was a problem loading the list of columns, show an error
     * panel which contains the reason why.
     *
     * @param query The SQL query string, which can contain JasperReports parameters. 
     */
    private void processQueryChanged( String query ) {
        if (jReportFrame == null) {
            setColumnsError( "Please open a report." );
            return;
        }
        
        if (query.length() == 0) {
            setColumnsError( "You must insert a valid query first" );
            return;
        }

        IReportConnection conn = (IReportConnection)this.getJReportFrame().getMainFrame().getProperties().get("DefaultConnection");
        if (conn == null || !conn.isJDBCConnection()) {
            setColumnsError( "The active connection is not of type JDBC. Activate a JDBC connection first." );
            return;
        }
        
        try {
            // Run the query in the backgroud as it is not quick.
            if (readerThread != null && readerThread.isAlive())
            {
                readerThread.interrupt();
            }
        } catch (Throwable ex) {
            ex.printStackTrace();
            
        }
        
        readerThread = new FieldReader(query, conn);
        readerThread.start();
    }
    
    
    /**
     * A Thread class to extract field names from a SQL query.
     *
     */
    class FieldReader extends Thread {
        String src_query;
        IReportConnection conn;
       
        
        /**
         * ctor.
         * @param query The query to read the field from
         * @param conn The IRport DB connection to use.
         */
        public FieldReader(String query, IReportConnection conn) {
            src_query=query;
            this.conn=conn;
        }
        
        /**
         * Set the fields table data to the supplied data.
         * This is called from a none swing thread, hence all the invoke and
         * wait magic.
         * The columns are only set if the query string matches the one the 
         * results are for.
         *
         * @param columns The list of columns to set.
         */
        private void setColumnsFromWorker( final List columns ) {
            try {
                SwingUtilities.invokeAndWait( new Runnable() {
                    public void run() {
                        String str = jRSQLExpressionArea1.getText().trim();
                        if( str.compareTo(src_query)==0 ) {
                            setColumns( columns );
                        }
                    }
                } );
            } catch(Exception e) {
                // oh well we got interrupted.
            }
        }

        /**
         * Set the columns error message.
         * This is called from a none swing thread, hence all the invoke and
         * wait magic.
         * The message is only set if the query string matches the one the 
         * error message is for.
         *
         * @param columns The list of columns to set.
         */
        private void setColumnErrorFromWork( final String error_msg ) {
            try {
                SwingUtilities.invokeAndWait( new Runnable() {
                    public void run() {
                        String str = jRSQLExpressionArea1.getText().trim();
                        if( str.compareTo(src_query)==0 ) {
                            setColumnsError( error_msg );
                        }
                    }
                } );
            } catch(Exception e) {
                // oh well we got interrupted.
            }
        }
        
        public String interpretQuery()
        {
            
            String query = this.src_query;
            try {
            Interpreter interpreter = prepareExpressionEvaluator();

                // look for parameters in the query and replace them with default values.
                // parameters look something like 
                // $P{QuoteGroupID}
                // or 
                // $P!{OrderByClause}
                java.util.List queryParams = new ArrayList();
                Enumeration enumParams = getJReportFrame().getReport().getParameters().elements();
                while( enumParams.hasMoreElements() ) {
                    it.businesslogic.ireport.JRParameter parameter = (it.businesslogic.ireport.JRParameter)enumParams.nextElement();

                    String p1 = "$P{" + parameter.getName() + "}";
                    String p2 = "$P!{" + parameter.getName() + "}";

                    // evaluate the Default expression value
                    Integer expID = (Integer)parameterNameToExpressionID.get(parameter.getName());
                    Object defValue;
                    if( expID!=null ) {
                        defValue = interpreter.eval("bshCalculator.evaluate(" + expID.intValue() + ")");
                    } else {
                        // this param does not have a default value.
                        defValue = null;
                    }


                    int ip1 = query.indexOf(p1);
                    while( ip1!=-1 ) {
                        // String replacement, Altering the SQL statement.
                        if( defValue==null ) {
                            throw new IllegalArgumentException("Please set a " +
                                "default value for the parameter '" 
                                + parameter.getName() + "'" );
                        }

                        String before = query.substring(0, ip1);
                        String after = query.substring(ip1+p1.length());
                        if (parameter.getClassType().equals("java.lang.String"))
                        {
                            String stt = defValue.toString();
                            stt = it.businesslogic.ireport.util.Misc.string_replace("''","'", stt);
                            query = before + "'" + stt + "'" + after;
                        }
                        else query = before + "" + defValue.toString() + "" + after;
                        
                        ip1 = query.indexOf(p1);
                    }

                    int ip2 = query.indexOf(p2);
                    while( ip2!=-1 ) {
                        // String replacement, Altering the SQL statement.
                        if( defValue==null ) {
                            throw new IllegalArgumentException("Please set a " +
                                "default value for the parameter '" 
                                + parameter.getName() + "'" );
                        }

                        String before = query.substring(0, ip2);
                        String after = query.substring(ip2+p2.length());
                        query = before + "" + defValue.toString() + "" + after;
                        ip2 = query.indexOf(p2);
                    }
                }
            
                return query;
            } catch (Exception ex)
            {
                javax.swing.JOptionPane.showMessageDialog(null, ex.getMessage());
                return "";
            }
        }
        
        public void run() {
            String error_msg = "";
            num++;
            int in = num;
            getJLabelStatusSQL().setText("Executing SQL query....");
            
            Connection con = null;
            PreparedStatement ps = null;
            try {
                // Prepare the parameter expression evaluator.
                // Cannot cache this as user may have altered the parameters. (this 
                // dialog is not modal.
                String query = this.src_query;
                Interpreter interpreter = prepareExpressionEvaluator();

                // look for parameters in the query and replace them with default values.
                // parameters look something like 
                // $P{QuoteGroupID}
                // or 
                // $P!{OrderByClause}
                java.util.List queryParams = new ArrayList();
                Enumeration enumParams = getJReportFrame().getReport().getParameters().elements();
                while( enumParams.hasMoreElements() ) {
                    it.businesslogic.ireport.JRParameter parameter = (it.businesslogic.ireport.JRParameter)enumParams.nextElement();

                    String p1 = "$P{" + parameter.getName() + "}";
                    String p2 = "$P!{" + parameter.getName() + "}";

                    // evaluate the Default expression value
                    Integer expID = (Integer)parameterNameToExpressionID.get(parameter.getName());
                    Object defValue;
                    if( expID!=null ) {
                        defValue = interpreter.eval("bshCalculator.evaluate(" + expID.intValue() + ")");
                    } else {
                        // this param does not have a default value.
                        defValue = null;
                    }


                    int ip1 = query.indexOf(p1);
                    while( ip1!=-1 ) {
                        // add a query parameter
                        if( defValue==null ) {
                            throw new IllegalArgumentException("Please set a " +
                            "default value for the parameter '" + 
                            parameter.getName() + "'" );
                        }

                        String before = query.substring(0, ip1);
                        String after = query.substring(ip1+p1.length());
                        query = before + " ? " + after;
                        queryParams.add( defValue );
                        ip1 = query.indexOf(p1);
                    }

                    int ip2 = query.indexOf(p2);
                    while( ip2!=-1 ) {
                        // String replacement, Altering the SQL statement.
                        if( defValue==null ) {
                            throw new IllegalArgumentException("Please set a " +
                                "default value for the parameter '" 
                                + parameter.getName() + "'" );
                        }

                        String before = query.substring(0, ip2);
                        String after = query.substring(ip2+p2.length());
                        query = before + "" + defValue.toString() + "" + after;
                        ip2 = query.indexOf(p2);
                    }
                }

                con = conn.getConnection();
                
                if (in < num) return;
                ps = con.prepareStatement( query );
                for(int pc=0; pc<queryParams.size(); pc++ ) {
                    ps.setObject(pc+1, queryParams.get(pc) );
                }
                
                // Some JDBC drivers don't supports this method...
                try { ps.setFetchSize(0); } catch(Exception e ) {}
                
                
                ResultSet rs = ps.executeQuery();
                
                if (in < num) return;
                
                ResultSetMetaData rsmd = rs.getMetaData();

                if (in < num) return;
                
                List columns = new ArrayList();
                for (int i=1; i <=rsmd.getColumnCount(); ++i) {
                    it.businesslogic.ireport.JRField field = 
                        new it.businesslogic.ireport.JRField(
                            rsmd.getColumnLabel(i), 
                            Misc.getJdbcTypeClass(rsmd.getColumnType(i) ) );
                    columns.add( new Object[]{field, field.getClassType()} );
                }

                setColumnsFromWorker(columns);
                getJLabelStatusSQL().setText("Ready");
                return;
            } catch( IllegalArgumentException ie ) {
                error_msg = ie.getMessage();
                getJLabelStatusSQL().setText("Ready");
            } catch (NoClassDefFoundError ex) {
            	ex.printStackTrace();
                error_msg = "NoClassDefFoundError!!\nCheck your classpath!";
                getJLabelStatusSQL().setText("Ready");
            } catch (java.sql.SQLException ex) {
                error_msg = "SQL problems:\n"+ex.getMessage();
            } catch (Exception ex) {
                ex.printStackTrace();
                error_msg = "General problem:\n"+ex.getMessage()+
                    "\n\nCheck username and password; is the DBMS active ?!";
                getJLabelStatusSQL().setText("Ready");
            } finally {
                if(ps!=null) try { ps.close(); } catch(Exception e ) {}
                if(con !=null) try { con.close(); } catch(Exception e ) {}
            }
            getJLabelStatusSQL().setText("Ready");
            setColumnErrorFromWork( error_msg );
        }
    }
    
    
    
    
    
    
    /**
     * Shows the list of columns.
     * If the column error message label is visible remove it first.
     *
     * @param cols A List Object[], for the fields.
     */
    private void setColumns( final List cols ) {
        
        columnsErrorMsgLabel.setText( "" );
        jPanel2.remove( columnsErrorScrollPane );
        jPanel2.add( columnsScrollPane, java.awt.BorderLayout.CENTER );
        jPanel2.revalidate();
        
        
        javax.swing.table.DefaultTableModel dtm =  (javax.swing.table.DefaultTableModel)jTableFields.getModel();
        dtm.getDataVector().clear();
        for(int i=0; i<cols.size(); i++) {
            Object [] row = (Object[])cols.get(i);
            dtm.addRow( row );
        }
        
        // Select all the fields so the new user does not get confused, when
        // they press OK. As only the selected fields are actually saved to the
        // report
        jTableFields.selectAll();
        
        okButton.setEnabled( true );
    }
    
    /**
     * Replace the columns list with a label that contains the reason why
     * columns cannot be loaded.
     *
     * @param msg The error message to display, can be in HTML.
     */
    private void setColumnsError( final String msg ) {
        columnsErrorMsgLabel.setText( msg );
        jPanel2.remove( columnsScrollPane );
        jPanel2.add( columnsErrorScrollPane, java.awt.BorderLayout.CENTER );
        jPanel2.revalidate();
        columnsErrorMsgLabel.repaint();
        
        //okButton.setEnabled(false);
    }
    
    
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {//GEN-BEGIN:initComponents
        java.awt.GridBagConstraints gridBagConstraints;
        
        jSplitPane1 = new javax.swing.JSplitPane();
        jPanel1 = new javax.swing.JPanel();
        jTabbedPane1 = new javax.swing.JTabbedPane();
        jPanelSQL = new javax.swing.JPanel();
        jRSQLExpressionArea1 = new it.businesslogic.ireport.gui.JRSQLExpressionArea();
        jPanel7 = new javax.swing.JPanel();
        automaticlyReadFieldsCheckBox = new javax.swing.JCheckBox();
        readFieldsButton = new javax.swing.JButton();
        exportQueryButton = new javax.swing.JButton();
        jLabelStatusSQL = new javax.swing.JLabel();
        jPanel5 = new javax.swing.JPanel();
        jTextFieldBeanClass = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        jButtonReadBeanAttributes = new javax.swing.JButton();
        jPanel10 = new javax.swing.JPanel();
        jPanel8 = new javax.swing.JPanel();
        jTextFieldBeanClass1 = new javax.swing.JTextField();
        jLabel3 = new javax.swing.JLabel();
        jButtonReadBeanAttributes3 = new javax.swing.JButton();
        jPanel11 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTree1 = new javax.swing.JTree();
        jPanel12 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        jPanel13 = new javax.swing.JPanel();
        jSeparator1 = new javax.swing.JSeparator();
        jPanel6 = new javax.swing.JPanel();
        jButton2 = new javax.swing.JButton();
        jPanel2 = new javax.swing.JPanel();
        columnsScrollPane = new javax.swing.JScrollPane();
        jTableFields = new javax.swing.JTable();
        jPanel3 = new javax.swing.JPanel();
        jPanel4 = new javax.swing.JPanel();
        okButton = new javax.swing.JButton();
        cancelButton = new javax.swing.JButton();
        jPanel9 = new javax.swing.JPanel();
        columnsErrorScrollPane = new javax.swing.JScrollPane();
        columnsErrorMsgLabel = new javax.swing.JLabel();
        
        setTitle("Report query");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                closeDialog(evt);
            }
            public void windowOpened(java.awt.event.WindowEvent evt) {
                formWindowOpened(evt);
            }
        });
        
        jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane1.setResizeWeight(0.5);
        jPanel1.setLayout(new java.awt.BorderLayout());
        
        jPanel1.setMinimumSize(new java.awt.Dimension(10, 100));
        jPanel1.setPreferredSize(new java.awt.Dimension(10, 350));
        jTabbedPane1.setMinimumSize(new java.awt.Dimension(154, 350));
        jTabbedPane1.setPreferredSize(new java.awt.Dimension(154, 350));
        jPanelSQL.setLayout(new java.awt.BorderLayout());
        
        jPanelSQL.setPreferredSize(new java.awt.Dimension(1, 350));
        jPanelSQL.setMinimumSize(new java.awt.Dimension(1, 100));
        jRSQLExpressionArea1.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.LOWERED));
        jRSQLExpressionArea1.setMinimumSize(new java.awt.Dimension(661, 200));
        jRSQLExpressionArea1.setPreferredSize(new java.awt.Dimension(661, 340));
        jPanelSQL.add(jRSQLExpressionArea1, java.awt.BorderLayout.CENTER);
        
        jPanel7.setLayout(new java.awt.GridBagLayout());
        
        automaticlyReadFieldsCheckBox.setSelected(true);
        automaticlyReadFieldsCheckBox.setText("Automatically Retrieve Fields");
        automaticlyReadFieldsCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                automaticlyReadFieldsCheckBoxActionPerformed(evt);
            }
        });
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(2, 5, 2, 0);
        jPanel7.add(automaticlyReadFieldsCheckBox, gridBagConstraints);
        
        readFieldsButton.setText("Read Fields");
        readFieldsButton.setEnabled(false);
        readFieldsButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                readFieldsButtonActionPerformed(evt);
            }
        });
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 10, 2, 0);
        jPanel7.add(readFieldsButton, gridBagConstraints);
        
        exportQueryButton.setText("Send to clipboard");
        exportQueryButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exportQueryButtonActionPerformed(evt);
            }
        });
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 10, 2, 0);
        jPanel7.add(exportQueryButton, gridBagConstraints);
        
        jLabelStatusSQL.setFont(new java.awt.Font("Dialog", 0, 11));
        jLabelStatusSQL.setBorder(new javax.swing.border.BevelBorder(javax.swing.border.BevelBorder.LOWERED));
        jLabelStatusSQL.setMinimumSize(new java.awt.Dimension(4, 18));
        jLabelStatusSQL.setPreferredSize(new java.awt.Dimension(4, 18));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        jPanel7.add(jLabelStatusSQL, gridBagConstraints);
        
        jPanelSQL.add(jPanel7, java.awt.BorderLayout.SOUTH);
        
        jTabbedPane1.addTab("Report SQL query ", jPanelSQL);
        
        jPanel5.setLayout(new java.awt.GridBagLayout());
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 3, 5, 3);
        jPanel5.add(jTextFieldBeanClass, gridBagConstraints);
        
        jLabel2.setText("Class name");
        jLabel2.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 5, 3);
        jPanel5.add(jLabel2, gridBagConstraints);
        
        jButtonReadBeanAttributes.setText("Read javabeans attributes");
        jButtonReadBeanAttributes.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonReadBeanAttributesActionPerformed(evt);
            }
        });
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 3, 5, 3);
        jPanel5.add(jButtonReadBeanAttributes, gridBagConstraints);
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.weighty = 1.0;
        jPanel5.add(jPanel10, gridBagConstraints);
        
        jTabbedPane1.addTab("JavaBean Datasource", jPanel5);
        
        jPanel8.setLayout(new java.awt.GridBagLayout());
        
        jPanel8.setMinimumSize(new java.awt.Dimension(235, 30));
        jPanel8.setPreferredSize(new java.awt.Dimension(215, 30));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 3, 5, 3);
        jPanel8.add(jTextFieldBeanClass1, gridBagConstraints);
        
        jLabel3.setText("Class name");
        jLabel3.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 5, 3);
        jPanel8.add(jLabel3, gridBagConstraints);
        
        jButtonReadBeanAttributes3.setText("Read attributes");
        jButtonReadBeanAttributes3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonReadBeanAttributes3ActionPerformed(evt);
            }
        });
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 3, 5, 3);
        jPanel8.add(jButtonReadBeanAttributes3, gridBagConstraints);
        
        jPanel11.setLayout(new java.awt.GridBagLayout());
        
        jTree1.setRootVisible(false);
        jTree1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jTree1MouseClicked(evt);
            }
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                jTree1MouseEntered(evt);
            }
        });
        
        jScrollPane1.setViewportView(jTree1);
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPanel11.add(jScrollPane1, gridBagConstraints);
        
        jPanel12.setLayout(new java.awt.GridBagLayout());
        
        jPanel12.setPreferredSize(new java.awt.Dimension(120, 50));
        jPanel12.setMinimumSize(new java.awt.Dimension(120, 50));
        jButton1.setText("Add field(s)");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 4);
        jPanel12.add(jButton1, gridBagConstraints);
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPanel12.add(jPanel13, gridBagConstraints);
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        jPanel11.add(jPanel12, gridBagConstraints);
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPanel8.add(jPanel11, gridBagConstraints);
        
        jSeparator1.setPreferredSize(new java.awt.Dimension(0, 4));
        jSeparator1.setMinimumSize(new java.awt.Dimension(0, 4));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 4, 0);
        jPanel8.add(jSeparator1, gridBagConstraints);
        
        jTabbedPane1.addTab("JavaBean Ext Datasource", jPanel8);
        
        jButton2.setText("Get fields from datasource");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });
        
        jPanel6.add(jButton2);
        
        jTabbedPane1.addTab("Use DataSource Provider", jPanel6);
        
        jPanel1.add(jTabbedPane1, java.awt.BorderLayout.CENTER);
        
        jSplitPane1.setTopComponent(jPanel1);
        
        jPanel2.setLayout(new java.awt.BorderLayout());
        
        jPanel2.setPreferredSize(new java.awt.Dimension(453, 150));
        columnsScrollPane.setPreferredSize(new java.awt.Dimension(453, 150));
        jTableFields.setModel(new javax.swing.table.DefaultTableModel(
                new Object [][] {
            
        },
                new String [] {
            "Field name", "Field type", "Description"
        }
        ) {
            boolean[] canEdit = new boolean [] {
                false, false, false
            };
            
            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jTableFields.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                jTableFieldsKeyReleased(evt);
            }
        });
        
        columnsScrollPane.setViewportView(jTableFields);
        
        jPanel2.add(columnsScrollPane, java.awt.BorderLayout.CENTER);
        
        jPanel3.setLayout(new java.awt.BorderLayout());
        
        jPanel3.setPreferredSize(new java.awt.Dimension(10, 34));
        jPanel3.setMinimumSize(new java.awt.Dimension(10, 34));
        jPanel4.setLayout(new java.awt.GridBagLayout());
        
        jPanel4.setPreferredSize(new java.awt.Dimension(150, 10));
        okButton.setText("OK");
        okButton.setEnabled(false);
        okButton.setMaximumSize(new java.awt.Dimension(67, 26));
        okButton.setMinimumSize(new java.awt.Dimension(67, 26));
        okButton.setPreferredSize(new java.awt.Dimension(67, 26));
        okButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                okButtonActionPerformed(evt);
            }
        });
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        jPanel4.add(okButton, gridBagConstraints);
        
        cancelButton.setText("Cancel");
        cancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelButtonActionPerformed(evt);
            }
        });
        
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        jPanel4.add(cancelButton, gridBagConstraints);
        
        jPanel3.add(jPanel4, java.awt.BorderLayout.EAST);
        
        jPanel9.setLayout(null);
        
        jPanel9.setMinimumSize(new java.awt.Dimension(100, 20));
        jPanel3.add(jPanel9, java.awt.BorderLayout.CENTER);
        
        jPanel2.add(jPanel3, java.awt.BorderLayout.SOUTH);
        
        columnsErrorMsgLabel.setText("jLabel1");
        columnsErrorMsgLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP);
        columnsErrorMsgLabel.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
        columnsErrorScrollPane.setViewportView(columnsErrorMsgLabel);
        
        jPanel2.add(columnsErrorScrollPane, java.awt.BorderLayout.CENTER);
        
        jSplitPane1.setBottomComponent(jPanel2);
        
        getContentPane().add(jSplitPane1, java.awt.BorderLayout.CENTER);
        
        pack();
    }//GEN-END:initComponents

    private void formWindowOpened(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowOpened

    }//GEN-LAST:event_formWindowOpened

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
       
        IReportConnection conn = (IReportConnection)this.getJReportFrame().getMainFrame().getProperties().get("DefaultConnection");
        if (conn == null || !(conn instanceof it.businesslogic.ireport.connection.JRDataSourceProviderConnection)) {
            setColumnsError( "The active connection is not a JasperReports DataSource provider." );
            return;
        }
        else
        {
            it.businesslogic.ireport.connection.JRDataSourceProviderConnection ic = (it.businesslogic.ireport.connection.JRDataSourceProviderConnection)conn;
            try {
            net.sf.jasperreports.engine.JRField[] jrfields = ic.getDataSourceProvider().getFields( null );
            DefaultTableModel dtm = (DefaultTableModel)jTableFields.getModel();
            dtm.setRowCount(0);
            for (int i=0; i< jrfields.length; ++i)
            {
                it.businesslogic.ireport.JRField field = new it.businesslogic.ireport.JRField(jrfields[i].getName(), jrfields[i].getValueClassName());
                field.setDescription( it.businesslogic.ireport.util.Misc.nvl( jrfields[i].getDescription(),""));
                Vector row = new Vector();
                row.addElement(field);
                row.addElement(field.getClassType());
                row.addElement(field.getDescription());
                dtm.addRow(row);
            }
            } catch (Exception ex)
            {
                setColumnsError( "" + ex.getMessage() );
            
            }
        }
        
    }//GEN-LAST:event_jButton2ActionPerformed

    private void exportQueryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportQueryButtonActionPerformed
       
        FieldReader fr = new FieldReader(jRSQLExpressionArea1.getText(), null);
        String query = fr.interpretQuery();
        
        java.awt.datatransfer.Clipboard clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard();
        StringSelection fieldContent = new StringSelection (query);
        
     	clipboard.setContents (fieldContent, this);

        
        // TODO add your handling code here:
    }//GEN-LAST:event_exportQueryButtonActionPerformed

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        
        // Get all selected paths...
        if (MainFrame.getMainInstance().getActiveReportFrame() == null){
            return;
        }
        
        DefaultTableModel dtm = (DefaultTableModel)jTableFields.getModel();
         
        TreePath[] paths = jTree1.getSelectionPaths();
        
        for (int i=0; i<paths.length; ++i)
        {
            boolean valid = true;
            TreePath tp = paths[i];

            TreeJRField tjrf =  (TreeJRField)((DefaultMutableTreeNode)tp.getLastPathComponent()).getUserObject();
            String returnType =  tjrf.getObj().getName();
            it.businesslogic.ireport.JRField field = new it.businesslogic.ireport.JRField(tjrf.getField().getName(), returnType);
            field.setDescription(tjrf.getField().getDescription() );
            Vector row = new Vector();
            row.addElement(field);
            row.addElement(field.getClassType());
            row.addElement(field.getDescription());
            
            // Check for duplicates fields...
            boolean found = false;
            for (int j=0; j<jTableFields.getRowCount(); ++j)
            {
               Object ff = jTableFields.getValueAt(j, 0);
               if ( ff instanceof it.businesslogic.ireport.JRField )
               {
                   if ( ((it.businesslogic.ireport.JRField)ff).getName().equals(field.getName()))
                   {
                       found = true;
                       break;
                   }
               }
            }
            if (!found)
            {
                dtm.addRow(row);
            }
        }
    }//GEN-LAST:event_jButton1ActionPerformed

    private void jTree1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTree1MouseClicked
        if (evt.getClickCount() == 2 && evt.getButton() == evt.BUTTON1)
        {
            DefaultMutableTreeNode tn = (DefaultMutableTreeNode)jTree1.getSelectionPath().getLastPathComponent();
            
            if (tn.getChildCount()>0) return;
            
                /*if (!jTree1.isCollapsed( jTree1.getSelectionPath() ))
            {
                jTree1.collapsePath( jTree1.getSelectionPath() );
                return;
            }
                 *
                 */
            if (tn.getUserObject() instanceof TreeJRField)
            {
                TreeJRField jrf = (TreeJRField)tn.getUserObject();
                if (!jrf.getObj().getName().startsWith("java.lang."))
                {
                   exploreBean(tn, jrf.getObj().getName(), Misc.nvl( jrf.getField().getDescription(), ""));
                }
            }
        }       
    }//GEN-LAST:event_jTree1MouseClicked

    private void jTree1MouseEntered(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTree1MouseEntered
        
      
    }//GEN-LAST:event_jTree1MouseEntered

    private void jButtonReadBeanAttributes3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonReadBeanAttributes3ActionPerformed
        
        
        
        if (MainFrame.getMainInstance().getActiveReportFrame() == null){
            return;
        }
        
        DefaultTableModel dtm = (DefaultTableModel)jTableFields.getModel();
        dtm.setRowCount(0);
        jTableFields.updateUI();
        
         DefaultTreeModel dttm = (DefaultTreeModel)jTree1.getModel();
         DefaultMutableTreeNode root = new DefaultMutableTreeNode();
         jTree1.setModel(new DefaultTreeModel( root ));
            
         String classname = jTextFieldBeanClass1.getText().trim();
         if (classname.equals("")){
         
            javax.swing.JOptionPane.showMessageDialog(this, "No class specified!","Error",javax.swing.JOptionPane.ERROR_MESSAGE);
            return;
        }
        
          exploreBean(root, classname, "");
         
    }//GEN-LAST:event_jButtonReadBeanAttributes3ActionPerformed

    protected void getFieldsFromClass(Class clazz, String path) throws Exception
    {
         DefaultTableModel dtm = (DefaultTableModel)jTableFields.getModel();
            
         java.lang.reflect.Method[] methods = clazz.getMethods();
         java.lang.reflect.Field[] fields = clazz.getFields();
         // for any method, looking for get<FieldName> ....
            
            
         for (int i=0; i<methods.length; ++i)
         {
               
                if ( java.lang.reflect.Modifier.isPublic( methods[i].getModifiers() ) &&
                     methods[i].getDeclaringClass().getName().equals(clazz.getName() ) &&
                     !java.lang.reflect.Modifier.isNative( methods[i].getModifiers() )     
                     && methods[i].getName().startsWith("get")
                        && !methods[i].getReturnType().isPrimitive() 
                        && !methods[i].getReturnType().isArray())
                {
                   String fieldName = methods[i].getName().substring(3);
                   // Looking for the field...
                   for (int f=0; f<fields.length; ++f)
                   {
                       if (fields[f].getName().equalsIgnoreCase( fieldName ))
                       {
                           
                           fieldName = fields[f].getName();
                           break;
                       }
                   }
                   
                   String returnType =  methods[i].getReturnType().getName();
                   boolean found = false;
                   for (int cc=0; cc<standard_types.length; ++cc)
                   {
                        if ( returnType.equalsIgnoreCase(standard_types[cc]))
                        {                       
                            it.businesslogic.ireport.JRField field = new it.businesslogic.ireport.JRField(fieldName, returnType);
                            field.setDescription(path + "" + fieldName);
                            Vector row = new Vector();
                            row.addElement(field);
                            row.addElement(field.getClassType());
                            row.addElement(field.getDescription());
                            dtm.addRow(row);
                            found = true;
                            break;
                        }
                  }
                  if (!found)
                  {
                        it.businesslogic.ireport.JRField field = new it.businesslogic.ireport.JRField(fieldName, "java.lang.Object");
                        field.setDescription(path + "" + fieldName);
                        Vector row = new Vector();
                        row.addElement(field);
                        row.addElement(field.getClassType());
                        row.addElement(field.getDescription());
                        dtm.addRow(row);
                        Class subClazz = Class.forName(returnType);
                        getFieldsFromClass( subClazz , path + fieldName + ".");
                  }
                }
            }                    
    }
    



    private void automaticlyReadFieldsCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_automaticlyReadFieldsCheckBoxActionPerformed
        if( automaticlyReadFieldsCheckBox.isSelected() ) {
            // Automagically get quiery fields.
            // User has just enabled this so get field list.
            readFieldsButton.setEnabled(false);
            processQueryChanged( jRSQLExpressionArea1.getText().trim() );
        } else {
            // Turn off automagic field reading. User will have to press the 
            // Read Fields button
            //okButton.setEnabled(false);
            readFieldsButton.setEnabled(true);
            setColumnsError( "Enter your query above. Then use the Read " +
                    "Fields button to retrieve the list of fields." );
        }
        
    }//GEN-LAST:event_automaticlyReadFieldsCheckBoxActionPerformed

    private void readFieldsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_readFieldsButtonActionPerformed
        processQueryChanged( jRSQLExpressionArea1.getText().trim() );
    }//GEN-LAST:event_readFieldsButtonActionPerformed

    private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
        // No changes.
        num++;
        this.setVisible(false);
    }//GEN-LAST:event_cancelButtonActionPerformed

    private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
        
        if ( this.getJReportFrame() != null)
        {       
            num++; // avoid syncronization problems....
            
            // save the query to the report.
            this.getJReportFrame().getReport().setQuery( jRSQLExpressionArea1.getText());                
            try {
            if ( jTableFields.getRowCount() > 0)
            {
                // Clear all the existing fields.
                this.getJReportFrame().getReport().getFields().clear();
    
                // Add the new fields.
                int[] selectedRows = jTableFields.getSelectedRows();
                for (int i=0; i<selectedRows.length  ; ++i) {
                    if (selectedRows[i] > jTableFields.getRowCount()) continue;

                    it.businesslogic.ireport.JRField field = (it.businesslogic.ireport.JRField)this.jTableFields.getValueAt(selectedRows[i], 0);
                    Enumeration e = this.getJReportFrame().getReport().getFields().elements();
                    boolean found = false;
                    while (e.hasMoreElements()) {
                        it.businesslogic.ireport.JRField f = (it.businesslogic.ireport.JRField)e.nextElement();
                        if (f.getName().equalsIgnoreCase(field.getName())) {
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        this.getJReportFrame().getReport().addField(field);
                    }
                }
                this.getJReportFrame().getMainFrame().getValuesDialog().updateFields();

            }
            
            } catch (Throwable ex)
            {
                ex.printStackTrace();
            }
       }
        
        this.setVisible(false);
        
    }//GEN-LAST:event_okButtonActionPerformed

    private void jTableFieldsKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTableFieldsKeyReleased
        
        //javax.swing.JOptionPane.showMessageDialog(null,"Key: "+evt.getKeyCode() + " (" + java.awt.event.KeyEvent.VK_DELETE + ")");
        if (evt.getKeyCode() == java.awt.event.KeyEvent.VK_DELETE)
        {
             javax.swing.table.DefaultTableModel dtm =  (javax.swing.table.DefaultTableModel)jTableFields.getModel();
             int[] selectedRows = jTableFields.getSelectedRows();
             for (int i= selectedRows.length-1; i>=0; --i) 
             {
                 it.businesslogic.ireport.JRField field = (it.businesslogic.ireport.JRField)this.jTableFields.getValueAt( i, 0);
                 this.getJReportFrame().getReport().removeField(field);
                 this.jTableFields.removeRowSelectionInterval(i,i);
             }
        }
    }//GEN-LAST:event_jTableFieldsKeyReleased

    private void jButtonReadBeanAttributesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonReadBeanAttributesActionPerformed
        String classname = jTextFieldBeanClass.getText().trim();
        if (classname.equals("")){
         
            javax.swing.JOptionPane.showMessageDialog(this, "No class specified!","Error",javax.swing.JOptionPane.ERROR_MESSAGE);
            return;
        }
        try {
            
            DefaultTableModel dtm = (DefaultTableModel)jTableFields.getModel();
            dtm.setRowCount(0);
            
            Class clazz = Class.forName(classname,true,MainFrame.getMainInstance().getReportClassLoader()); 

            java.beans.PropertyDescriptor[] pd = org.apache.commons.beanutils.PropertyUtils.getPropertyDescriptors(clazz);
            for (int nd =0; nd < pd.length; ++nd)
            {
                   String fieldName = pd[nd].getName();
                   if (pd[nd].getPropertyType() != null && pd[nd].getReadMethod() != null)
                   {
                       String returnType =  pd[nd].getPropertyType().getName();
                       it.businesslogic.ireport.JRField field = new it.businesslogic.ireport.JRField(fieldName, getJRFieldType(returnType));
                       field.setDescription(""); //Field returned by " +methods[i].getName() + " (real type: "+ returnType +")");
                       Vector row = new Vector();
                       row.addElement(field);
                       row.addElement(field.getClassType());
                       row.addElement(field.getDescription());
                       dtm.addRow(row);
                   }
            }
            
            /*
            java.lang.reflect.Method[] methods = Class.forName(classname).getMethods();
            java.lang.reflect.Field[] fields = Class.forName(classname).getFields();
            
            // for any method, looking for get<FieldName> ....
            
            DefaultTableModel dtm = (DefaultTableModel)jTableFields.getModel();
            dtm.setRowCount(0);
            
            for (int i=0; i<methods.length; ++i)
            {
               // methods[i].getDeclaringClass().getName().equals(classname) &&
                if ( java.lang.reflect.Modifier.isPublic( methods[i].getModifiers() ) &&
                      
                     !java.lang.reflect.Modifier.isNative( methods[i].getModifiers() )     
                     && methods[i].getName().startsWith("get"))
                        //&& !methods[i].getReturnType().isPrimitive() 
                        //&& !methods[i].getReturnType().isArray()
                {
                   String fieldName = methods[i].getName().substring(3);
                   if (fieldName.length() > 0)
                   {
                       fieldName = fieldName.substring(0,1).toLowerCase() + fieldName.substring(1);
                   }
                   else continue;
                   
                   // Looking for the field...
                   for (int f=0; f<fields.length; ++f)
                   {
                       if (fields[f].getName().equalsIgnoreCase( fieldName ))
                       {
                           
                           fieldName = fields[f].getName();
                           break;
                       }
                   }
                   
                   String returnType =  methods[i].getReturnType().getName();
                   it.businesslogic.ireport.JRField field = new it.businesslogic.ireport.JRField(fieldName, getJRFieldType(returnType));
                   field.setDescription("Field returned by " +methods[i].getName() + " (real type: "+ returnType +")");
                   Vector row = new Vector();
                   row.addElement(field);
                   row.addElement(field.getClassType());
                   row.addElement(field.getDescription());
                   dtm.addRow(row);
                }
            }
             */
            
        } catch (ClassNotFoundException cnf)
        {
            javax.swing.JOptionPane.showMessageDialog(this, "Class not found!\nCheck your classpath and retry.","Error",javax.swing.JOptionPane.ERROR_MESSAGE);
            return;
        } catch (Exception ex)
        {
            ex.printStackTrace();
            javax.swing.JOptionPane.showMessageDialog(this, ex.getMessage() ,"Error",javax.swing.JOptionPane.ERROR_MESSAGE);
            return;
        }
    }//GEN-LAST:event_jButtonReadBeanAttributesActionPerformed
    
    
    
    private String getJRFieldType(String type)
    {
        if (type == null) return "java.lang.Object";
        if (type.equals("java.lang.Boolean") || type.equals("boolean")) return "java.lang.Boolean";
        if (type.equals("java.lang.Byte") || type.equals("byte")) return "java.lang.Byte";
        if (type.equals("java.lang.Integer") || type.equals("int")) return "java.lang.Integer";
        if (type.equals("java.lang.Long") || type.equals("long")) return "java.lang.Long";
        if (type.equals("java.lang.Double") || type.equals("double")) return "java.lang.Double";
        if (type.equals("java.lang.Float") || type.equals("float")) return "java.lang.Float";
        if (type.equals("java.lang.Short") || type.equals("short")) return "java.lang.Short";
        if (type.equals("java.util.Date") ||
            type.equals("java.sql.Timestamp") ||
            type.equals("java.io.InputStream") ||
            type.equals("java.math.BigDecimal") ||
            type.equals("java.lang.String") ||
            type.equals("java.sql.Time")) return type;
        return "java.lang.Object";
    }
    
    /** Closes the dialog */
    private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
        setVisible(false);
        dispose();
    }//GEN-LAST:event_closeDialog
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        new ReportQueryDialog(new javax.swing.JFrame(), true).show();
    }
    
    /** Getter for property jReportFrame.
     * @return Value of property jReportFrame.
     *
     */
    public it.businesslogic.ireport.gui.JReportFrame getJReportFrame() {
        return jReportFrame;
    }    
    
    /** Setter for property jReportFrame.
     * @param jReportFrame New value of property jReportFrame.
     *
     */
    public void setJReportFrame(it.businesslogic.ireport.gui.JReportFrame jReportFrame) {
        this.jReportFrame = jReportFrame;
        DefaultTableModel dtm = (DefaultTableModel)jTableFields.getModel();
        dtm.setRowCount(0); 
        
        num++;
        jLabelStatusSQL.setText( "" );
        
        // Load query...
        if (jReportFrame == null)
            this.jRSQLExpressionArea1.setText("");
        else
        {
            // Use query, and use existing field list. ie Dont load from DB
            isSettingSQLExpression = true;
            this.jRSQLExpressionArea1.setText( this.jReportFrame.getReport().getQuery() );
            isSettingSQLExpression = false;
            
            List columns = new ArrayList();
            Iterator i = jReportFrame.getReport().getFields().iterator();
            while( i.hasNext() ) {
                it.businesslogic.ireport.JRField field = (it.businesslogic.ireport.JRField)i.next();
                columns.add( new Object[]{field, field.getClassType()} );
            }
            setColumns( columns );
        }
    }
    
    
    Map parameterNameToExpressionID = null;
    
    /**
     * Create an expression evaluator for report parameters.
     *
     */
    private Interpreter prepareExpressionEvaluator() throws net.sf.jasperreports.engine.JRException, bsh.EvalError {
        JasperDesign jd = new JasperDesign();

        parameterNameToExpressionID = new HashMap();
        
        Enumeration enumParams = getJReportFrame().getReport().getParameters().elements();
        while( enumParams.hasMoreElements() ) {
            it.businesslogic.ireport.JRParameter parameter = (it.businesslogic.ireport.JRParameter)enumParams.nextElement();

            if( parameter.getDefaultValueExpression().length()==0 ) {
                // no default value for this param
                continue;
            }
            
            Class c = classStringToClass( parameter.getClassType() );
            
            JRDesignParameter p = new JRDesignParameter();
            //JRDesignExpression exp = parameter.getDefaultValueExpression();
            JRDesignExpression exp = new JRDesignExpression();
            if (c==null) c = java.lang.Object.class;
            exp.setValueClass( c );
            exp.setName("parameterDefaultValue_" + parameter.getName() );
            exp.setText( parameter.getDefaultValueExpression() );
            p.setName( parameter.getName() );
            p.setValueClass( c );
            p.setForPrompting( false );
            p.setDefaultValueExpression( exp );
            jd.addParameter( p );
            parameterNameToExpressionID.put( parameter.getName(), new Integer(exp.getId()) );
        }

        
        String bshScript = JRBshGenerator.generateScript( jd );
        Interpreter interpreter = new Interpreter();
        interpreter.setClassLoader(interpreter.getClass().getClassLoader());
        interpreter.eval(new StringReader(bshScript));

        interpreter.eval("bshCalculator = createBshCalculator()");
        
        return interpreter;
    }

    /**
     * Convert a class name string into its class object.
     * There must be a function in JasperReports that does this somewhere.
     *
     *
     */
    private Class classStringToClass(String classType) {
        Class c = null;
        
        
        if ( classType.equals("java.lang.String") ) {
            c = java.lang.String.class;
        } else if ( classType.equals("java.lang.Integer") ) {
            c = java.lang.Integer.class;
        } else if ( classType.equals("java.lang.Boolean") ) {
            c = java.lang.Boolean.class;
        } else if ( classType.equals("java.lang.Byte") ) {
            c = java.lang.Byte.class;
        } else if ( classType.equals("java.util.Date") ) {
            c = java.util.Date.class;
        } else if ( classType.equals("java.sql.Timestamp") ) {
            c = java.sql.Timestamp.class;
        } else if ( classType.equals("java.sql.Time") ) {
            c = java.sql.Time.class;
        } else if ( classType.equals("java.lang.Double") ) {
            c = java.lang.Double.class;
        } else if ( classType.equals("java.lang.Float") ) {
            c = java.lang.Float.class;
        } else if ( classType.equals("java.lang.Long") ) {
            c = java.lang.Long.class;
        } else if ( classType.equals("java.lang.Short") ) {
            c = java.lang.Short.class;
        } else if ( classType.equals("java.math.BigDecimal") ) {
            c = java.math.BigDecimal.class;
        }
        
        return c;
    }
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JCheckBox automaticlyReadFieldsCheckBox;
    private javax.swing.JButton cancelButton;
    private javax.swing.JLabel columnsErrorMsgLabel;
    private javax.swing.JScrollPane columnsErrorScrollPane;
    private javax.swing.JScrollPane columnsScrollPane;
    private javax.swing.JButton exportQueryButton;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButtonReadBeanAttributes;
    private javax.swing.JButton jButtonReadBeanAttributes3;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabelStatusSQL;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel10;
    private javax.swing.JPanel jPanel11;
    private javax.swing.JPanel jPanel12;
    private javax.swing.JPanel jPanel13;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JPanel jPanel8;
    private javax.swing.JPanel jPanel9;
    private javax.swing.JPanel jPanelSQL;
    private it.businesslogic.ireport.gui.JRSQLExpressionArea jRSQLExpressionArea1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JTable jTableFields;
    private javax.swing.JTextField jTextFieldBeanClass;
    private javax.swing.JTextField jTextFieldBeanClass1;
    private javax.swing.JTree jTree1;
    private javax.swing.JButton okButton;
    private javax.swing.JButton readFieldsButton;
    // End of variables declaration//GEN-END:variables

    private JReportFrame jReportFrame;    
    
    private boolean isSettingSQLExpression = false;
    
    
    public void exploreBean(DefaultMutableTreeNode root, String classname, String parentPath)
    {
        try {
            
            root.removeAllChildren();
            if (parentPath.length() > 0) parentPath += ".";
            
            Class clazz = Class.forName(classname,true,MainFrame.getMainInstance().getReportClassLoader());
            
            java.lang.reflect.Method[] methods = clazz.getMethods();
            java.lang.reflect.Field[] fields = clazz.getFields();
            // for any method, looking for get<FieldName> ....

            for (int i=0; i<methods.length; ++i)
            {
               //System.out.println( methods[i].getName());
                if ( java.lang.reflect.Modifier.isPublic( methods[i].getModifiers() ) &&
                     methods[i].getDeclaringClass().getName().equals(classname) &&
                     !java.lang.reflect.Modifier.isNative( methods[i].getModifiers() )     
                     && methods[i].getName().startsWith("get")
                        && !methods[i].getReturnType().isPrimitive() 
                        && !methods[i].getReturnType().isArray())
                {
                   String fieldName = methods[i].getName().substring(3);
                   
                   if (fieldName.length() == 0) continue;
                   // Looking for the field...
                   for (int f=0; f<fields.length; ++f)
                   {
                       if (fields[f].getName().equalsIgnoreCase( fieldName ))
                       {
                           fieldName = fields[f].getName();
                           break;
                       }
                   }
                   
                   
                   String returnType =  methods[i].getReturnType().getName();
                   it.businesslogic.ireport.JRField field = new it.businesslogic.ireport.JRField(fieldName, returnType);
                   field.setDescription(parentPath + fieldName);
                   TreeJRField jtf = new TreeJRField();
                   
                   jtf.setField( field );
                   jtf.setObj( methods[i].getReturnType() );
                   
                   boolean bChildrens = true;
                   if (methods[i].getReturnType().getName().startsWith("java.lang."))
                   {
                       bChildrens = false;
                   }
                   root.add(new DefaultMutableTreeNode(jtf, bChildrens));
                }
            }
            
            jTree1.expandPath( new TreePath(root.getPath()) );
            jTree1.updateUI();
            
        } catch (ClassNotFoundException cnf)
        {
            javax.swing.JOptionPane.showMessageDialog(this, "Class not found!\nCheck your classpath and retry.","Error",javax.swing.JOptionPane.ERROR_MESSAGE);
            return;
        } catch (Exception ex)
        {
            javax.swing.JOptionPane.showMessageDialog(this, ex.getMessage() ,"Error",javax.swing.JOptionPane.ERROR_MESSAGE);
            return;
        }
    }
    
    public void lostOwnership (Clipboard parClipboard, Transferable parTransferable) { }

   
}


