/**
 * 
 */

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;

import jet.dataengine.api.DSException;
import jet.dataengine8.util.ResultSetDisplayer;
import jet.datasource.JRUserDataSource;
import jet.datasource.JRUserDataSourceException;
import toolkit.db.gui.ConnectionsBroker;

/**
 * @author jiwu.ma
 * 
 * If you use unionsample classes, you must be sure that the class files can be
 * found when running. So, make sure that the directory is classpath/package
 * name. For this unionsample's UDS classes, the classes belong to a package
 * named com.jinfonet.training. Copy the necessary files in
 * com\jinfonet\training, and add the additional entry into the class path
 * statement of the batch file . It must equal that union table's metadata count
 * when use UnionSample class union table.
 */
public class UnionSample implements JRUserDataSource {

    Vector propertiesContain = null;

    Vector list = new Vector();

    Connection con = null;

    Statement smt = null;

    Vector connectionContian = new Vector();

    Vector smtContian = new Vector();

    UnionSampleResult union;// = new UnionSampleResult();

    /**
     * PARAMETER: strParam - A String value used to request and get different
     * result sets. You can enter the PARAMETER string when you add the UDS to a
     * catalog. If you want to use parameters predefined in the Catalog Browser,
     * you can add
     * 
     * @paraName a string value used to request and get different result sets.
     *           The format of the paraName :
     *           DRIVER="org.hsqldb.jdbcDriver"&URL="jdbc:hsqldb:C:\\JReport\\Designer\\Demo\
     *           \db\\demoDB"&USER=sa&PSWD=&SQL=select * from customers For
     *           example: two table union, the format of the paraName is
     *           DRIVER="org.hsqldb.jdbcDriver"&URL="jdbc:hsqldb:C:\\JReport\\Designer\\Demo\
     *           \db\\demoDB"&USER=sa&PSWD=&SQL=select * from customers&
     *           DRIVER="com.mysql.jdbc.Driver"&URL="jdbc:mysql://192.168.128.169:3306/traini
     *           ngdb"&USER=root&PSWD=root&SQL=select * from customers
     * @return java.sql.ResultSet - A row and column dataset that can be used
     *         in JReport.
     */
    public ResultSet getResultSet(String arg0) throws JRUserDataSourceException {
        // TODO Auto-generated method stub
        if (this.propertiesContain == null) {
            this.propertiesContain = new Vector();
            passString(arg0);
        }
        this.getResult();
        union = new UnionSampleResult(list);
        return this.union;
    }

    private void getResult() throws JRUserDataSourceException {
        for (int i = 0; i < this.propertiesContain.size(); i++) {
            String url = (String) ((Hashtable) this.propertiesContain.get(i))
                    .get("URL");
            String sql = (String) ((Hashtable) this.propertiesContain.get(i))
                    .get("SQL");
            String driver = (String) ((Hashtable) this.propertiesContain.get(i))
                    .get("DRIVER");
            String user = (String) ((Hashtable) this.propertiesContain.get(i))
                    .get("USER");
            String pswd = (String) ((Hashtable) this.propertiesContain.get(i))
                    .get("PSWD");
            this.propertiesContain.remove(i);
            list.add(this.createResultSet(url, user, pswd, driver, sql));
            getResult();
        }

    }

    private ResultSet createResultSet(String strURL, String strUser,
            String strPassword, String strDriver, String strSQL)
            throws JRUserDataSourceException {
        try {
            con = ConnectionsBroker.getConnection(strURL, strUser, strPassword,
                    strDriver);
            smt = con.createStatement();
            boolean isS = smt.execute(strSQL);
            if (isS) {

                this.connectionContian.add(con);
                this.smtContian.add(smt);
                return smt.getResultSet();
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new JRUserDataSourceException(e.getMessage());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new JRUserDataSourceException(e.getMessage());
        }
        return null;
    }

    private void passString(String str) throws JRUserDataSourceException {
        Hashtable conInfo = new Hashtable();
        str = str.replace('&', '\n');
        String temp;
        StringBuffer buffer = new StringBuffer(str);

        int len = buffer.indexOf("DRIVER", 1);
        boolean is = true;
        while (buffer.length() != 0) {
            if (len == -1) {
                temp = buffer.toString();
                is = false;
            } else {
                temp = buffer.substring(0, len);
            }
            conInfo = this.passKeyAndValue(temp);
            propertiesContain.add(conInfo);
            buffer.delete(0, is ? len : temp.length());
            len = buffer.indexOf("DRIVER", 1);
        }
    }

    private Hashtable passKeyAndValue(String strV) {
        Hashtable te = new Hashtable();
        int beginkeyIndex = 0;
        int endkeyIndex = 0;
        int lenp;
        boolean isbegin = true;
        boolean over = true;
        while (over && strV.length() - 1 > beginkeyIndex) {
            String temp;
            endkeyIndex = strV.indexOf('\n', beginkeyIndex + 1);
            if (endkeyIndex == -1) {
                temp = (strV.substring(beginkeyIndex));
                over = false;
            } else
                temp = (strV.substring(beginkeyIndex, endkeyIndex));
            int len = temp.indexOf("=");
            te.put(temp.substring(isbegin ? 0 : 1, len).toUpperCase(), temp
                    .substring(len + 1));
            isbegin = false;
            beginkeyIndex = endkeyIndex;
        }
        return te;
    }

    /**
     * This method frees the ResultSet object.
     * 
     * Throws: JRUserDataSourceException - If there are some errors when freeing
     * the resource.
     */
    public void releaseResultSet() throws JRUserDataSourceException {
        ResultSet rs = null;
        Connection con = null;
        Statement stm = null;
        
        try {
            for (int i = 0; i < this.list.size(); i++) {
                this.union.setLen(i);
                if ((ResultSet) this.list.get(i) != null) {
                    this.union.close();
//                    rs = (ResultSet) this.list.get(i);
                    
//                    rs.close();
//                    rs = null;
                }
                if ((Connection) this.connectionContian.get(i) != null) {
                    con = (Connection) this.connectionContian.get(i);

                    con.close();
                    con = null;
                }
                if ((Statement) this.smtContian.get(i) != null) {
                    stm = (Statement) this.smtContian.get(i);

                    stm.close();
                    stm = null;
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new JRUserDataSourceException(e.getMessage());
        }
        this.connectionContian = null;
        this.list = null;
        this.smtContian = null;
        this.union = null;

    }

}
