001package csheets.ext.database.core;
002
003import java.sql.*;
004import java.util.ArrayList;
005import java.util.logging.*;
006
007import javax.swing.JOptionPane;
008
009import csheets.core.Cell;
010
011/**
012 * Creates a connection to a HSQL database
013 * 
014 * @author João Carreira
015 */
016public class HsqlDBConnection implements DBConnectionStrategy {
017        private final String driverPath = "org.hsqldb.jdbcDriver";
018        private Connection connection;
019        private String url, user, pwd;
020
021        @Override
022        public void createConnection(String url, String user, String pass)
023                        throws ClassNotFoundException, SQLException {
024                try {
025                        Class.forName(driverPath);
026                        // /* test line -- DELETE AFTERWARDS */
027                        // System.out.println(url);
028                        connection = DriverManager.getConnection(url, user, pass);
029                        // /* test line -- DELETE AFTERWARDS */
030                        // System.out.println("HSQLAdaptee: connected!");
031                } catch (ClassNotFoundException e) {
032                        // /* test line -- DELETE AFTERWARDS */
033                        // System.out.println("HSQLAdaptee: class not found");
034
035                        /* keep this until observer is implemented */
036                        JOptionPane.showMessageDialog(null, "Error: class not found!");
037                } catch (SQLException e) {
038                        // /* test line -- DELETE AFTERWARDS */
039                        // System.out.println("HSQLAdaptee: sql error");
040                        /* keep this until observer is implemented */
041                        JOptionPane.showMessageDialog(null,
042                                        "Error: connection to database!");
043                }
044        }
045
046        @Override
047        public void createTable(String tableName, Cell[][] cells) {
048                /* defining row and column number */
049                int numberOfColumns = cells[0].length;
050                int numberOfRows = cells.length;
051
052                /* beginning the construction of the sql statement */
053                String stat = "CREATE TABLE " + tableName + "(linha INTEGER, ";
054
055                /* the first line of the exported cells is the name of each column */
056                String[] columnsName = new String[cells[0].length];
057                String[] columnsNameCopy = new String[cells[0].length];
058
059                /* cycle to build the columns name string */
060                for (int i = 0; i < cells[0].length; i++) {
061                        /* if it's not the last column */
062                        if (i != ((cells[0].length) - 1)) {
063                                columnsName[i] = cells[0][i].getContent() + " VARCHAR(200), ";
064                                columnsNameCopy[i] = cells[0][i].getContent();
065                        }
066                        /* if it's the last column must close with bracket */
067                        else {
068                                columnsName[i] = cells[0][i].getContent() + " VARCHAR(200), PRIMARY KEY(linha))";
069                                columnsNameCopy[i] = cells[0][i].getContent();
070                        }
071                }
072
073                /*
074                 * in the end of this cycle we should have the final sql statement for
075                 * table creation
076                 */
077                for (int i = 0; i < columnsName.length; i++) {
078                        stat += columnsName[i];
079                }
080
081                /* sql statement */
082                Statement st = null;
083
084                /* creates the table based on the sql statement */
085                try {
086                        st = connection.createStatement();
087                        int i = st.executeUpdate(stat);
088                        /* keep this until observer is implemented */
089                        JOptionPane.showMessageDialog(null, "Data succesfully exported!");
090                } catch (SQLException ex) {
091                        Logger.getLogger(HsqlDBConnection.class.getName()).log(
092                                        Level.SEVERE, null, ex);
093                        /* keep this until observer is implemented */
094                        JOptionPane.showMessageDialog(null, "Error: table already exists");
095                }
096
097                /* now beggins the "insert into" sql statement */
098                String insertStat = "insert into " + tableName + "(linha,";
099                for (int i = 0; i < columnsNameCopy.length; i++) {
100                        if (i != (columnsNameCopy.length - 1)) {
101                                insertStat += columnsNameCopy[i] + ",";
102                        } else {
103                                insertStat += columnsNameCopy[i] + ")";
104                        }
105                }
106                /* continuing concatenation */
107                insertStat += " VALUES(";
108
109                /* creating a number of insert statements equal to number of rows -1 */
110                String[] insertVector = new String[numberOfRows - 1];
111                for (int i = 0; i < insertVector.length; i++) {
112                        /*
113                         * the first value of each insert statement is the respective row
114                         * number (we do this so that, in a future feature, we keep track of
115                         * the original row)
116                         */
117                        String temp = Integer
118                                        .toString(cells[i][0].getAddress().getRow() + 1);
119                        insertVector[i] = insertStat + temp + ",";
120                }
121
122                /* concatenating the respecting insert statements */
123                for (int i = 1; i < numberOfRows; i++) {
124                        for (int j = 0; j < numberOfColumns; j++) {
125                                if (j != (numberOfColumns - 1)) {
126                                        insertVector[i - 1] += "'" + cells[i][j].getContent()
127                                                        + "',";
128                                } else {
129                                        insertVector[i - 1] += "'" + cells[i][j].getContent()
130                                                        + "')";
131                                }
132                        }
133                }
134
135                /* inserting values into the table */
136                for (int i = 0; i < insertVector.length; i++) {
137                        Statement insertSt = null;
138                        try {
139                                insertSt = connection.createStatement();
140                                int j = st.executeUpdate(insertVector[i].toString());
141                        } catch (SQLException ex) {
142                                Logger.getLogger(HsqlDBConnection.class.getName()).log(
143                                                Level.SEVERE, null, ex);
144                                /* keep this until observer is implemented */
145                                JOptionPane.showMessageDialog(null, "Error: data not inserted");
146                        }
147                }
148
149                /* test msg -- DELETE THIS */
150                // System.out.println("CREATE TABLE: done");
151        }
152
153        @Override
154        public void disconnet() {
155                Statement st;
156                try {
157                        st = connection.createStatement();
158                        st.execute("SHUTDOWN");
159                        connection.close();
160                } catch (SQLException ex) {
161                        Logger.getLogger(HsqlDBConnection.class.getName()).log(
162                                        Level.SEVERE, null, ex);
163                }
164        }
165
166        @Override
167        public synchronized ArrayList queryToArray() {
168                String sqlStat = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.SYSTEM_TABLES where TABLE_TYPE='TABLE'";
169                /* SQL statement */
170                Statement stat = null;
171                /* SQL result set */
172                ResultSet resSet = null;
173                /* ArrayList to save results from the query */
174                ArrayList array = new ArrayList();
175
176                try {
177                        stat = connection.createStatement();
178                        resSet = stat.executeQuery(sqlStat);
179                        stat.close();
180                        ResultSetMetaData metaData = resSet.getMetaData();
181                        int cols = metaData.getColumnCount();
182                        Object obj = null;
183                        for (; resSet.next();) {
184                                for (int i = 0; i < cols; i++) {
185                                        obj = resSet.getObject(i + 1);
186                                        array.add(obj);
187                                }
188                        }
189                } catch (SQLException ex) {
190                        Logger.getLogger(HsqlDBConnection.class.getName()).log(
191                                        Level.SEVERE, null, ex);
192                }
193                return array;
194        }
195
196        @Override
197        public String[] getTableList(ArrayList list) {
198                int size = list.size();
199                String[] temp = new String[size];
200                for (int i = 0; i < size; i++) {
201                        temp[i] = list.get(i).toString();
202                }
203                return temp;
204        }
205
206        @Override
207        public String[][] getTableContent(String tableName) {
208                ArrayList temp = new ArrayList();
209                int[] rowsAndCols = new int[2];
210
211                try {
212                        temp = queryToArray(tableName);
213                        rowsAndCols = countsRowsAndCols(tableName);
214                } catch (SQLException ex) {
215                        Logger.getLogger(HsqlDBConnection.class.getName()).log(
216                                        Level.SEVERE, null, ex);
217                }
218
219                return queryTo2dArray(temp, new String[rowsAndCols[0]][rowsAndCols[1]]);
220        }
221
222        @Override
223        public void updateTable() {
224                throw new UnsupportedOperationException("Not supported yet.");
225        }
226
227        @Override
228        public synchronized ArrayList queryToArray(String tableName)
229                        throws SQLException {
230                Statement st = null;
231                ResultSet rs = null;
232                ArrayList temp = new ArrayList();
233                Object obj = null;
234
235                String expression = "SELECT * FROM " + tableName + ";";
236
237                st = connection.createStatement();
238                rs = st.executeQuery(expression);
239                st.close();
240
241                ResultSetMetaData meta = rs.getMetaData();
242                int cols = meta.getColumnCount();
243                int rows = countRows(tableName);
244
245                for (int i = 1; i <= cols; i++) {
246                        obj = meta.getColumnName(i);
247                        temp.add(obj);
248                }
249
250                for (; rs.next();) {
251                        for (int i = 0; i < cols; i++) {
252                                obj = rs.getObject(i + 1);
253                                temp.add(obj);
254                        }
255                }
256
257                return temp;
258        }
259
260        @Override
261        public synchronized int[] countsRowsAndCols(String tableName)
262                        throws SQLException {
263                int[] result = new int[2];
264                int rows, cols;
265                Statement st = null;
266                ResultSet rs = null;
267                Object obj = null;
268                String sqlExpression = "SELECT * FROM " + tableName + ";";
269
270                st = connection.createStatement();
271                rs = st.executeQuery(sqlExpression);
272                st.close();
273                ResultSetMetaData meta = rs.getMetaData();
274                rs.next();
275
276                obj = rs.getObject(1);
277                result[0] = countRows(tableName);
278                result[1] = meta.getColumnCount();
279
280                return result;
281        }
282
283        @Override
284        public synchronized int countRows(String tableName) throws SQLException {
285                Statement st = null;
286                ResultSet rs = null;
287                Object obj = null;
288                String sqlExpression = "SELECT COUNT(*) FROM " + tableName + ";";
289
290                st = connection.createStatement();
291                rs = st.executeQuery(sqlExpression);
292                st.close();
293
294                ResultSetMetaData meta = rs.getMetaData();
295                rs.next();
296
297                obj = rs.getObject(1);
298
299                return Integer.parseInt(obj.toString()) + 1;
300        }
301
302        @Override
303        public String[][] queryTo2dArray(ArrayList array, String[][] table) {
304                for (int i = 0, k = 0; i < table.length; i++) {
305                        for (int j = 0; j < table[0].length; j++, k++) {
306                                table[i][j] = array.get(k).toString();
307                        }
308                }
309                return table;
310        }
311
312        @Override
313        public void updateRow(String tableName, String column, String origin,
314                        String destination) {
315                Statement st = null;
316                String stat = "UPDATE " + tableName + " SET " + column + " = '"
317                                + origin + "' WHERE LINHA = " + Integer.parseInt(destination);
318                //System.out.println("HSQL --> " + stat);
319                try {
320                        st = connection.createStatement();
321                        int i = st.executeUpdate(stat);
322                } catch (SQLException ex) {
323                        Logger.getLogger(HsqlDBConnection.class.getName()).log(
324                                        Level.SEVERE, null, ex);
325                        /* keep this until observer is implemented */
326                        JOptionPane.showMessageDialog(null,
327                                        "HSQL database error:\nCould not update!");
328                }
329
330        }
331
332    @Override
333    public void insertNewData(String tableName, String[][] newData) 
334    {
335        /* array with all insert statements */
336        String []statementVec = new String[newData.length];
337        String beginStatement = "INSERT INTO " + tableName + " VALUES ("; 
338        
339        /* begining to concatenate insert vector */
340        for(int i = 0; i < statementVec.length; i++)
341        {
342            statementVec[i] = beginStatement;
343        }
344        
345        /* adding the remaining values to insert vector */
346        for(int i = 0; i < statementVec.length; i++)
347        {
348             for(int j = 0; j < newData[0].length; j++)
349             {
350                 /* if it's the first colum is an INTEGER therefore we can't add ' at the end */
351                 if(j == 0)
352                 {
353                     statementVec[i] += newData[i][j] + ",'";
354                 }
355                 /* if it's not the last column it must include , */
356                 if(j > 0 && j < (newData[0].length - 1))
357                 {
358                     statementVec[i] += newData[i][j] + "','";
359                 }
360                 /* if it's the last we must end the insert statement with )*/
361                 else if(j == (newData[0].length - 1))
362                 {
363                     statementVec[i] += newData[i][j] + "')";
364                 }
365             }
366        }
367        
368        /* cycle to go through all the insert statements */
369        for (int i = 0; i < statementVec.length; i++) 
370        {
371            Statement st = null;
372            try 
373            {
374                st = connection.createStatement();
375                int j = st.executeUpdate(statementVec[i].toString());
376            } 
377            catch (SQLException ex) 
378            {
379                Logger.getLogger(HsqlDBConnection.class.getName()).log(Level.SEVERE, null, ex);
380                /* keep this until observer is implemented */
381                JOptionPane.showMessageDialog(null, "Error: data not inserted");
382            }
383        }
384        /* keep this until observer is implemented */
385        //JOptionPane.showMessageDialog(null, "Derby Database: data successfully updated!");    
386    }
387
388    @Override
389    public void deleteRows(String tableName, String[] toDelete) 
390    {
391        String stat = "DELETE FROM " + tableName + " WHERE LINHA = ";
392        String []deleteStat = new String[toDelete.length];
393        
394        for(int i = 0; i < deleteStat.length; i++)
395        {
396            deleteStat[i] = stat + toDelete[i];
397        }
398        
399        for (int i = 0; i < deleteStat.length; i++) 
400        {
401            Statement st = null;
402            try 
403            {
404                st = connection.createStatement();
405                int j = st.executeUpdate(deleteStat[i]);
406            } 
407            catch (SQLException ex) 
408            {
409                Logger.getLogger(HsqlDBConnection.class.getName()).log(Level.SEVERE, null, ex);
410                /* keep this until observer is implemented */
411                JOptionPane.showMessageDialog(null, "Error: data not inserted");
412            }
413        }
414        
415    }
416}