/*
 * 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 dori.jasper.engine.*;
import dori.jasper.engine.design.*;
import dori.jasper.engine.fill.*;
import bsh.Interpreter;
import java.io.*;

import javax.swing.event.*;


/** 
 * 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 {
    
    /** 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);
        
        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." );
    }
    
    /**
     * 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.isJDBCConnection()) {
            setColumnsError( "The active connection is not of type JDBC. Activate a JDBC connection first." );
            return;
        }
        
        // Run the query in the backgroud as it is not quick.
        Thread t = new FieldReader(query, conn);
        t.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 void run() {
            String error_msg = "";
            PreparedStatement ps = null;
            try {
                // Prepare the parameter expression evaluator.
                // Cannot cache this as user may have altered the parameters. (this 
                // dialog is not modal.
                Interpreter interpreter = prepareExpressionEvaluator();

                String query = src_query;
                // 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);
                    }
                }

                ps = conn.getConnection().prepareStatement( query );
                for(int pc=0; pc<queryParams.size(); pc++ ) {
                    ps.setObject(pc+1, queryParams.get(pc) );
                }
                ps.setFetchSize(0);
                ResultSet rs = ps.executeQuery();
                ResultSetMetaData rsmd = rs.getMetaData();

                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);
                
                return;
            } catch( IllegalArgumentException ie ) {
                error_msg = ie.getMessage();
            } catch (NoClassDefFoundError ex) {
                error_msg = "NoClassDefFoundError!!\nCheck your classpath!";
            } catch (java.sql.SQLException ex) {
                error_msg = "SQL problems:\n"+ex.getMessage();
            } catch (Exception ex) {
                error_msg = "General problem:\n"+ex.getMessage()+
                    "\n\nCheck username and password; is the DBMS active ?!";
            } finally {
                if(ps!=null) try { ps.close(); } catch(Exception e ) {}
            }
            
            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();
        jPanel5 = new javax.swing.JPanel();
        jTextFieldBeanClass = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        jButtonReadBeanAttributes = new javax.swing.JButton();
        jPanel6 = new javax.swing.JPanel();
        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);
            }
        });

        jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane1.setResizeWeight(0.4);
        jPanel1.setLayout(new java.awt.BorderLayout());

        jPanel1.setMinimumSize(new java.awt.Dimension(10, 100));
        jPanel1.setPreferredSize(new java.awt.Dimension(10, 350));
        jTabbedPane1.setFont(new java.awt.Font("Dialog", 0, 11));
        jTabbedPane1.setMinimumSize(new java.awt.Dimension(154, 350));
        jTabbedPane1.setPreferredSize(new java.awt.Dimension(154, 350));
        jPanelSQL.setLayout(new java.awt.BorderLayout());

        jPanelSQL.setMinimumSize(new java.awt.Dimension(1, 100));
        jPanelSQL.setPreferredSize(new java.awt.Dimension(1, 350));
        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.insets = new java.awt.Insets(2, 5, 2, 0);
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        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.insets = new java.awt.Insets(2, 10, 2, 0);
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        jPanel7.add(readFieldsButton, gridBagConstraints);

        jPanelSQL.add(jPanel7, java.awt.BorderLayout.SOUTH);

        jTabbedPane1.addTab("Report SQL query ", jPanelSQL);

        jPanel5.setLayout(null);

        jPanel5.add(jTextFieldBeanClass);
        jTextFieldBeanClass.setBounds(8, 28, 342, 20);

        jLabel2.setFont(new java.awt.Font("Dialog", 0, 11));
        jLabel2.setText("Class name");
        jLabel2.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM);
        jLabel2.setPreferredSize(new java.awt.Dimension(54, 20));
        jPanel5.add(jLabel2);
        jLabel2.setBounds(8, 6, 240, 20);

        jButtonReadBeanAttributes.setFont(new java.awt.Font("Dialog", 0, 11));
        jButtonReadBeanAttributes.setText("Read javabeans attributes");
        jButtonReadBeanAttributes.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonReadBeanAttributesActionPerformed(evt);
            }
        });

        jPanel5.add(jButtonReadBeanAttributes);
        jButtonReadBeanAttributes.setBounds(8, 54, 188, 23);

        jTabbedPane1.addTab("JavaBean Datasource", jPanel5);

        jTabbedPane1.addTab("Custom Datasource", 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"
            }
        ) {
            boolean[] canEdit = new boolean [] {
                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.setMinimumSize(new java.awt.Dimension(10, 34));
        jPanel3.setPreferredSize(new java.awt.Dimension(10, 34));
        jPanel4.setLayout(new java.awt.GridBagLayout());

        jPanel4.setPreferredSize(new java.awt.Dimension(150, 10));
        okButton.setText("OK");
        okButton.setMaximumSize(new java.awt.Dimension(65, 23));
        okButton.setMinimumSize(new java.awt.Dimension(65, 23));
        okButton.setPreferredSize(new java.awt.Dimension(65, 23));
        okButton.setEnabled(false);
        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 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.
        this.setVisible(false);
    }//GEN-LAST:event_cancelButtonActionPerformed

    private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
        
        // save the query to the report.
        this.getJReportFrame().getReport().setQuery( jRSQLExpressionArea1.getText());
        
        // 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) {
            it.businesslogic.ireport.JRField field = (it.businesslogic.ireport.JRField)this.jTableFields.getValueAt( 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();
        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 {
            
            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)
            {
               
                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);
                   // 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("Field returned by " +methods[i].getName() + " method of " + classname);
                   Vector row = new Vector();
                   row.addElement(field);
                   row.addElement(field.getClassType());
                   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)
        {
            javax.swing.JOptionPane.showMessageDialog(this, ex.getMessage() ,"Error",javax.swing.JOptionPane.ERROR_MESSAGE);
            return;
        }
    }//GEN-LAST:event_jButtonReadBeanAttributesActionPerformed
    
    /** 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); 
        // 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 dori.jasper.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();
            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 jButtonReadBeanAttributes;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JPanel jPanel1;
    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 jPanel9;
    private javax.swing.JPanel jPanelSQL;
    private it.businesslogic.ireport.gui.JRSQLExpressionArea jRSQLExpressionArea1;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JTable jTableFields;
    private javax.swing.JTextField jTextFieldBeanClass;
    private javax.swing.JButton okButton;
    private javax.swing.JButton readFieldsButton;
    // End of variables declaration//GEN-END:variables

    private JReportFrame jReportFrame;    
    
    private boolean isSettingSQLExpression = false;
    
}
