001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.sql.framework.ui.output.dataview;
042:
043: import java.awt.BorderLayout;
044: import java.awt.Color;
045: import java.awt.Component;
046: import java.math.BigDecimal;
047: import java.sql.Blob;
048: import java.sql.Clob;
049: import java.sql.Date;
050: import java.sql.ResultSet;
051: import java.sql.ResultSetMetaData;
052: import java.sql.SQLException;
053: import java.sql.Time;
054: import java.sql.Timestamp;
055: import java.sql.Types;
056: import java.util.Map;
057: import java.util.LinkedHashMap;
058: import java.sql.Connection;
059: import javax.swing.JPanel;
060: import javax.swing.JScrollPane;
061: import javax.swing.JTable;
062: import javax.swing.SwingUtilities;
063: import javax.swing.table.DefaultTableCellRenderer;
064: import javax.swing.table.DefaultTableModel;
065: import javax.swing.table.TableCellRenderer;
066: import javax.swing.table.TableColumn;
067: import javax.swing.table.TableColumnModel;
068: import javax.swing.table.TableModel;
069: import org.netbeans.modules.sql.framework.ui.utils.BinaryToStringConverter;
070: import net.java.hulp.i18n.Logger;
071: import com.sun.sql.framework.utils.StringUtil;
072: import java.awt.datatransfer.StringSelection;
073: import java.awt.event.ActionEvent;
074: import java.awt.event.ActionListener;
075: import java.awt.event.MouseAdapter;
076: import java.awt.event.MouseEvent;
077: import java.sql.PreparedStatement;
078: import java.util.ArrayList;
079: import java.util.Collections;
080: import java.util.List;
081: import java.util.Set;
082: import javax.swing.JMenuItem;
083: import javax.swing.JPopupMenu;
084: import org.netbeans.modules.etl.logger.Localizer;
085: import org.netbeans.modules.etl.logger.LogUtil;
086: import org.netbeans.modules.sql.framework.common.jdbc.SQLUtils;
087: import org.netbeans.modules.sql.framework.model.PrimaryKey;
088: import org.netbeans.modules.sql.framework.ui.utils.TableSorter;
089: import org.openide.DialogDisplayer;
090: import org.openide.NotifyDescriptor;
091: import org.openide.NotifyDescriptor.Message;
092: import org.openide.util.Lookup;
093: import org.openide.util.datatransfer.ExClipboard;
094:
095: /**
096: * Renders rows and columns of an arbitrary ResultSet via JTable.
097: *
098: * @author Jonathan Giron
099: * @author Ahimanikya Satapathy
100: * @version $Revision$
101: */
102: public class ResultSetTablePanel extends JPanel {
103:
104: private boolean isEditable = true;
105: private boolean isDirty = false;
106: private DataOutputPanel dataPanel;
107: private Map<String, String> changes = new LinkedHashMap<String, String>();
108: private Map<String, List> valuesList = new LinkedHashMap<String, List>();
109: private Map<String, List> typesList = new LinkedHashMap<String, List>();
110: private static transient final Logger mLogger = LogUtil
111: .getLogger(ResultSetTablePanel.class.getName());
112: private static transient final Localizer mLoc = Localizer.get();
113:
114: private class DataTableModel extends DefaultTableModel {
115:
116: /**
117: * Returns true regardless of parameter values.
118: *
119: * @param row the row whose value is to be queried
120: * @param column the column whose value is to be queried
121: * @return true
122: * @see #setValueAt
123: */
124: @Override
125: public boolean isCellEditable(int row, int column) {
126: return isEditable;
127: }
128:
129: @Override
130: public void setValueAt(Object value, int row, int col) {
131: if (dataPanel.meta != null) {
132: List values = new ArrayList();
133: List<Integer> types = new ArrayList<Integer>();
134: DBTableMetadata meta = dataPanel.meta;
135:
136: String updateStmt = "UPDATE "
137: + meta.getQualifiedTableName() + " SET ";
138: updateStmt += meta.getColumnName(col) + " = ? "
139: + " WHERE ";
140: values.add(value);
141: types.add(meta.getColumnType(col));
142: updateStmt += generateWhereCondition(types, values, row);
143: String changeData = (row + 1) + ";" + (col + 1);
144:
145: try {
146: Object oldVal = getValueAt(row, col);
147: if (oldVal == null
148: && StringUtil
149: .isNullString(value.toString())) {
150: // do nothing
151: } else if (!oldVal.equals(value)) {
152: changes.put(changeData, updateStmt);
153: valuesList.put(changeData, values);
154: typesList.put(changeData, types);
155: isDirty = true;
156: super .setValueAt(value, row, col);
157: dataPanel.commit.setEnabled(true);
158: fireTableDataChanged();
159: }
160: } catch (Exception ex) {
161: //ignore
162: }
163: }
164: table.revalidate();
165: table.repaint();
166: }
167: }
168:
169: public Set<String> getUpdateKeys() {
170: return changes.keySet();
171: }
172:
173: public String getUpdateStmt(String key) {
174: return changes.get(key);
175: }
176:
177: public List getTypeList(String key) {
178: return typesList.get(key);
179: }
180:
181: public List getValueList(String key) {
182: return valuesList.get(key);
183: }
184:
185: public void fireTableModelChange() {
186: }
187:
188: public int executeDeleteRow(DBTableMetadata meta, int rowNum) {
189: List values = new ArrayList();
190: List<Integer> types = new ArrayList<Integer>();
191:
192: String deleteStmt = "DELETE FROM "
193: + meta.getQualifiedTableName() + " WHERE ";
194: deleteStmt += generateWhereCondition(types, values, rowNum);
195:
196: PreparedStatement pstmt = null;
197: Connection conn = null;
198: boolean error = false;
199: String errorMsg = null;
200:
201: try {
202: conn = meta.createConnection();
203: conn.setAutoCommit(false);
204: pstmt = conn.prepareStatement(deleteStmt);
205: int pos = 1;
206: for (Object val : values) {
207: SQLUtils.setAttributeValue(pstmt, pos, types
208: .get(pos - 1), val);
209: pos++;
210: }
211: int rows = pstmt.executeUpdate();
212: if (rows == 0) {
213: error = true;
214: errorMsg = errorMsg + "No rows deleted.";
215: } else if (rows > 1) {
216: error = true;
217: errorMsg = errorMsg
218: + " Statement cannot delete unique row.";
219: }
220:
221: return rows;
222: } catch (Exception ex) {
223: error = true;
224: errorMsg = errorMsg + ex.getMessage();
225: } finally {
226: if (!error) {
227: try {
228: String msg = "Permanently delete record(s) from the database?";
229: NotifyDescriptor d = new NotifyDescriptor.Confirmation(
230: msg, "Confirm delete",
231: NotifyDescriptor.OK_CANCEL_OPTION);
232: if (DialogDisplayer.getDefault().notify(d) == NotifyDescriptor.OK_OPTION) {
233: conn.commit();
234: } else {
235: msg = "Discarded the delete operation.";
236: DialogDisplayer
237: .getDefault()
238: .notify(
239: new Message(
240: msg,
241: NotifyDescriptor.INFORMATION_MESSAGE));
242: conn.rollback();
243: }
244: } catch (SQLException ex) {
245: errorMsg = "Commit Failed.";
246: DialogDisplayer
247: .getDefault()
248: .notify(
249: new Message(
250: errorMsg,
251: NotifyDescriptor.INFORMATION_MESSAGE));
252: }
253: } else {
254: errorMsg = "Delete command failed for " + errorMsg;
255: DialogDisplayer.getDefault().notify(
256: new Message(errorMsg,
257: NotifyDescriptor.INFORMATION_MESSAGE));
258: }
259: closeResources(pstmt, conn);
260: }
261: return 0;
262: }
263:
264: public void setEditable(boolean edit) {
265: this .isEditable = edit;
266: this .table.setRowSelectionAllowed(edit);
267: }
268:
269: public boolean isDirty() {
270: if (!isDirty) {
271: changes.clear();
272: }
273: return isDirty;
274: }
275:
276: public void setDirtyStatus(boolean dirty) {
277: isDirty = dirty;
278: if (!isDirty) {
279: changes.clear();
280: }
281: }
282:
283: private static class NullObjectCellRenderer extends
284: DefaultTableCellRenderer {
285:
286: static String nbBundle1 = mLoc.t("PRSR001: <NULL>");
287: static final String NULL_LABEL = Localizer.parse(nbBundle1);
288:
289: @Override
290: public Component getTableCellRendererComponent(JTable table,
291: Object value, boolean isSelected, boolean hasFocus,
292: int row, int column) {
293: Component c = super .getTableCellRendererComponent(table,
294: value, isSelected, hasFocus, row, column);
295:
296: setValue(NULL_LABEL);
297: c.setForeground(Color.GRAY);
298: return c;
299: }
300: }
301:
302: private static class ResultSetCellRenderer extends
303: DefaultTableCellRenderer {
304:
305: static final TableCellRenderer NULL_RENDERER = new NullObjectCellRenderer();
306:
307: @Override
308: public Component getTableCellRendererComponent(JTable table,
309: Object value, boolean isSelected, boolean hasFocus,
310: int row, int column) {
311: return (null == value) ? NULL_RENDERER
312: .getTableCellRendererComponent(table, value,
313: isSelected, hasFocus, row, column) : super
314: .getTableCellRendererComponent(table, value,
315: isSelected, hasFocus, row, column);
316: }
317: }
318:
319: private static final String data = "WE WILL EITHER FIND A WAY, OR MAKE ONE.";
320: /* Log4J category string */
321: private static final String LOG_CATEGORY = ResultSetTablePanel.class
322: .getName();
323: int MAX_COLUMN_WIDTH = 50;
324: /* TableModel containing contents of result set */
325: protected TableModel model;
326: private final int multiplier;
327: /* JTable displaying contents of TableModel */
328: protected JTable table;
329: private JPopupMenu tablePopupMenu;
330:
331: /**
332: * Constructs empty instance of SQLResultSetTableView. Call setResultSet(ResultSet) to
333: * display the contents of a given ResultSet.
334: *
335: * @see #setResultSet
336: */
337: public ResultSetTablePanel() {
338: this .setLayout(new BorderLayout());
339: table = new JTable();
340:
341: // content popup menu on table with results
342: tablePopupMenu = new JPopupMenu();
343: JMenuItem miCopyValue = new JMenuItem("Copy Cell Value"); //NOI18N
344: miCopyValue.addActionListener(new ActionListener() {
345:
346: public void actionPerformed(ActionEvent e) {
347: try {
348: Object o = table.getValueAt(table.getSelectedRow(),
349: table.getSelectedColumn());
350: String output = (o != null) ? o.toString() : ""; //NOI18N
351: ExClipboard clipboard = (ExClipboard) Lookup
352: .getDefault().lookup(ExClipboard.class);
353: StringSelection strSel = new StringSelection(output);
354: clipboard.setContents(strSel, strSel);
355: } catch (ArrayIndexOutOfBoundsException exc) {
356: }
357: }
358: });
359: tablePopupMenu.add(miCopyValue);
360:
361: JMenuItem miCopyRowValues = new JMenuItem("Copy Row Values"); //NOI18N
362: miCopyRowValues.addActionListener(new ActionListener() {
363:
364: public void actionPerformed(ActionEvent e) {
365: copyRowValues(false);
366: }
367: });
368: tablePopupMenu.add(miCopyRowValues);
369:
370: JMenuItem miCopyRowValuesH = new JMenuItem(
371: "Copy Row Values With Header"); //NOI18N
372: miCopyRowValuesH.addActionListener(new ActionListener() {
373:
374: public void actionPerformed(ActionEvent e) {
375: copyRowValues(true);
376: }
377: });
378: tablePopupMenu.add(miCopyRowValuesH);
379:
380: table.getTableHeader().setReorderingAllowed(false);
381: table.setDefaultRenderer(Object.class,
382: new ResultSetCellRenderer());
383: table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
384:
385: JScrollPane sp = new JScrollPane(table);
386: this .add(sp, BorderLayout.CENTER);
387:
388: multiplier = table.getFontMetrics(table.getFont()).stringWidth(
389: data)
390: / data.length();
391:
392: table.addMouseListener(new MouseAdapter() {
393:
394: @Override
395: public void mouseReleased(MouseEvent e) {
396: if (e.getButton() == MouseEvent.BUTTON3) {
397: int row = table.rowAtPoint(e.getPoint());
398: int column = table.columnAtPoint(e.getPoint());
399: boolean inSelection = false;
400: int[] rows = table.getSelectedRows();
401: for (int a = 0; a < rows.length; a++) {
402: if (rows[a] == row) {
403: inSelection = true;
404: break;
405: }
406: }
407: if (!table.getRowSelectionAllowed()) {
408: inSelection = false;
409: int[] columns = table.getSelectedColumns();
410: for (int a = 0; a < columns.length; a++) {
411: if (columns[a] == column) {
412: inSelection = true;
413: break;
414: }
415: }
416: }
417: if (!inSelection) {
418: table
419: .changeSelection(row, column, false,
420: false);
421: }
422: tablePopupMenu.show(table, e.getX(), e.getY());
423: }
424: }
425: });
426:
427: }
428:
429: private void copyRowValues(boolean withHeader) {
430: try {
431: int[] rows = table.getSelectedRows();
432: int[] columns;
433: if (table.getRowSelectionAllowed()) {
434: columns = new int[table.getColumnCount()];
435: for (int a = 0; a < columns.length; a++) {
436: columns[a] = a;
437: }
438: } else {
439: columns = table.getSelectedColumns();
440: }
441: if (rows != null && columns != null) {
442: StringBuffer output = new StringBuffer();
443:
444: if (withHeader) {
445: for (int column = 0; column < columns.length; column++) {
446: if (column > 0) {
447: output.append('\t'); //NOI18N
448: }
449: Object o = table.getColumnModel().getColumn(
450: column).getHeaderValue();
451: output.append(o != null ? o.toString() : ""); //NOI18N
452: }
453: output.append('\n'); //NOI18N
454: }
455:
456: for (int row = 0; row < rows.length; row++) {
457: for (int column = 0; column < columns.length; column++) {
458: if (column > 0) {
459: output.append('\t'); //NOI18N
460: }
461: Object o = table.getValueAt(rows[row],
462: columns[column]);
463: output.append(o != null ? o.toString() : ""); //NOI18N
464: }
465: output.append('\n'); //NOI18N
466: }
467: ExClipboard clipboard = (ExClipboard) Lookup
468: .getDefault().lookup(ExClipboard.class);
469: StringSelection strSel = new StringSelection(output
470: .toString());
471: clipboard.setContents(strSel, strSel);
472: }
473: } catch (ArrayIndexOutOfBoundsException exc) {
474: }
475: }
476:
477: public ResultSetTablePanel(DataOutputPanel panel) {
478: this ();
479: this .dataPanel = panel;
480: }
481:
482: /**
483: * Constructs instance of SQLResultSetTableView to display the result sets contained
484: * in the given Map.
485: *
486: * @param rsMap Map of ResultSets; possibly empty
487: */
488: public ResultSetTablePanel(Map rsMap) {
489: this ();
490: setResultSet(rsMap);
491: }
492:
493: /**
494: * Constructs instance of SQLResultSetTableView to display the given result set.
495: *
496: * @param rsMap ResultSet
497: */
498: public ResultSetTablePanel(ResultSet rs) {
499: this ();
500: setResultSet(rs);
501: }
502:
503: public void clearView() {
504: DataTableModel dtm = new DataTableModel();
505: final TableSorter sorter = new TableSorter(dtm);
506: sorter.setTableHeader(table.getTableHeader());
507:
508: Runnable run = new Runnable() {
509:
510: public void run() {
511: table.setModel(sorter);
512: }
513: };
514: SwingUtilities.invokeLater(run);
515: }
516:
517: /**
518: * Updates this view's data model with the results sets contained in the given Map.
519: *
520: * @param rsMap Map of ResultSets; possibly empty
521: */
522: public void setResultSet(Map rsMap) {
523: if (rsMap == null) {
524: throw new IllegalArgumentException(
525: "Must supply non-null Map reference for rsMap");
526: }
527:
528: model = createModelFrom(rsMap);
529: final TableModel tempModel = model;
530: Runnable run = new Runnable() {
531:
532: public void run() {
533: table.setModel(tempModel);
534: }
535: };
536: SwingUtilities.invokeLater(run);
537: }
538:
539: /**
540: * Updates this view's data model to display the contents of the given ResultSet.
541: *
542: * @param rsMap new ResultSet to be displayed.
543: */
544: public void setResultSet(ResultSet rs) {
545: this .setResultSet(rs, -1, 0);
546: }
547:
548: /**
549: * Updates this view's data model to display the contents of the given ResultSet.
550: *
551: * @param rsMap new ResultSet to be displayed.
552: */
553: public void setResultSet(ResultSet rs, int maxRowsToShow,
554: int startFrom) {
555: if (rs == null) {
556: throw new IllegalArgumentException(
557: "Must supply non-null ResultSet reference for rs");
558: }
559: // Get RSMD before rsMap is iterated - DB2Connect Universal driver closes ResultSet
560: // after rsMap.next() is advanced to end.
561: List<Integer> columnWidthList = Collections.emptyList();
562: try {
563: ResultSetMetaData rsmd = rs.getMetaData();
564: if (rsmd != null) {
565: columnWidthList = getColumnWidthList(rsmd);
566: }
567: } catch (SQLException ignore) {
568: // Could not obtain metadata - headers will not be displayed.
569: }
570:
571: model = createModelFrom(rs, maxRowsToShow, startFrom);
572: final TableModel tempModel = model;
573: final List<Integer> columnWidthList1 = columnWidthList;
574: Runnable run = new Runnable() {
575:
576: public void run() {
577: table.setModel(tempModel);
578: if (!columnWidthList1.isEmpty()) {
579: setHeader(table, columnWidthList1);
580: }
581: }
582: };
583: SwingUtilities.invokeLater(run);
584: }
585:
586: /**
587: * create a table model
588: *
589: * @param rs resultset
590: * @return TableModel
591: */
592: TableModel createModelFrom(ResultSet rs, int maxRowsToShow,
593: int startFrom) {
594: DataTableModel dtm = new DataTableModel();
595: TableSorter sorter = new TableSorter(dtm);
596: sorter.setTableHeader(table.getTableHeader());
597:
598: try {
599: ResultSetMetaData md = rs.getMetaData();
600:
601: int colCt = md.getColumnCount();
602: int[] colType = new int[colCt + 1];
603: // Obtain display name
604: for (int i = 1; i <= colCt; i++) {
605: dtm.addColumn(md.getColumnLabel(i));
606: int columnType = md.getColumnType(i);
607: colType[i] = columnType;
608: }
609:
610: Object[] row = new Object[colCt];
611: int rowCnt = 0;
612:
613: boolean lastRowPicked = rs.next();
614: while (lastRowPicked && rs.getRow() < (startFrom - 1)) {
615: lastRowPicked = rs.next();
616: }
617:
618: while (((maxRowsToShow == -1) || (maxRowsToShow > rowCnt))
619: && (lastRowPicked || rs.next())) {
620: for (int i = 0; i < colCt; i++) {
621: row[i] = readResultSet(rs, colType[i + 1], i + 1);
622: }
623: dtm.addRow(row);
624: rowCnt++;
625: if (lastRowPicked) {
626: lastRowPicked = false;
627: }
628: }
629: } catch (Exception e) {
630: mLogger.errorNoloc(mLoc.t(
631: "PRSR146: Failed to set up table model({0})",
632: LOG_CATEGORY), e);
633: }
634:
635: return sorter;
636: }
637:
638: /**
639: * create a table model
640: *
641: * @param rsMap resultset
642: * @return TableModel
643: */
644: TableModel createModelFrom(ResultSet rs, int maxRowsToShow) {
645: return createModelFrom(rs, maxRowsToShow, 0);
646: }
647:
648: @SuppressWarnings(value="fallthrough")
649: private Object readResultSet(ResultSet rs, int colType, int index)
650: throws SQLException {
651: switch (colType) {
652: case Types.BIT:
653: case Types.BOOLEAN: {
654: boolean bdata = rs.getBoolean(index);
655: if (rs.wasNull()) {
656: return null;
657: } else {
658: return new Boolean(bdata);
659: }
660: }
661: case Types.TIME: {
662: Time tdata = rs.getTime(index);
663: if (rs.wasNull()) {
664: return null;
665: } else {
666: return tdata;
667: }
668: }
669: case Types.DATE: {
670: Date ddata = rs.getDate(index);
671: if (rs.wasNull()) {
672: return null;
673: } else {
674: return ddata;
675: }
676: }
677: case Types.TIMESTAMP:
678: case -100: // -100 = Oracle timestamp
679: {
680: Timestamp tsdata = rs.getTimestamp(index);
681: if (rs.wasNull()) {
682: return null;
683: } else {
684: return tsdata;
685: }
686: }
687: case Types.BIGINT: {
688: long ldata = rs.getLong(index);
689: if (rs.wasNull()) {
690: return null;
691: } else {
692: return new Long(ldata);
693: }
694: }
695: case Types.DOUBLE:
696: case Types.FLOAT: {
697: double fdata = rs.getDouble(index);
698: if (rs.wasNull()) {
699: return null;
700: } else {
701: return new Double(fdata);
702: }
703: }
704: case Types.REAL: {
705: float rdata = rs.getFloat(index);
706: if (rs.wasNull()) {
707: return null;
708: } else {
709: return new Float(rdata);
710: }
711: }
712: case Types.DECIMAL:
713: case Types.NUMERIC: {
714: BigDecimal bddata = rs.getBigDecimal(index);
715: if (rs.wasNull()) {
716: return null;
717: } else {
718: return bddata;
719: }
720: }
721: case Types.INTEGER: {
722: int idata = rs.getInt(index);
723: if (rs.wasNull()) {
724: return null;
725: } else {
726: return new Integer(idata);
727: }
728: }
729: case Types.SMALLINT: {
730: short sidata = rs.getShort(index);
731: if (rs.wasNull()) {
732: return null;
733: } else {
734: return new Short(sidata);
735: }
736: }
737: case Types.TINYINT: {
738: byte tidata = rs.getByte(index);
739: if (rs.wasNull()) {
740: return null;
741: } else {
742: return new Byte(tidata);
743: }
744: }
745: // JDBC/ODBC bridge JDK1.4 brings back -9 for nvarchar columns in
746: // MS SQL Server tables.
747: // -8 is ROWID in Oracle.
748: case Types.CHAR:
749: case Types.VARCHAR:
750: case Types.LONGVARCHAR:
751: case -9:
752: case -8: {
753: String sdata = rs.getString(index);
754: if (rs.wasNull()) {
755: return null;
756: } else {
757: return sdata;
758: }
759: }
760: case Types.BINARY:
761: case Types.VARBINARY:
762: case Types.LONGVARBINARY: {
763: byte[] bdata = rs.getBytes(index);
764: if (rs.wasNull()) {
765: return null;
766: } else {
767: Byte[] internal = new Byte[bdata.length];
768: for (int i = 0; i < bdata.length; i++) {
769: internal[i] = new Byte(bdata[i]);
770: }
771: return BinaryToStringConverter.convertToString(
772: internal, BinaryToStringConverter.HEX, false);
773: }
774: }
775: case Types.BLOB: {
776: // We always get the BLOB, even when we are not reading the contents.
777: // Since the BLOB is just a pointer to the BLOB data rather than the
778: // data itself, this operation should not take much time (as opposed
779: // to getting all of the data in the blob).
780: Blob blob = rs.getBlob(index);
781:
782: if (rs.wasNull()) {
783: return null;
784: }
785: // BLOB exists, so try to read the data from it
786: byte[] blobData = null;
787: if (blob != null) {
788: blobData = blob.getBytes(1, 255);
789: }
790: Byte[] internal = new Byte[blobData.length];
791: for (int i = 0; i < blobData.length; i++) {
792: internal[i] = new Byte(blobData[i]);
793: }
794: return BinaryToStringConverter.convertToString(internal,
795: BinaryToStringConverter.HEX, false);
796: }
797: case Types.CLOB: {
798: // We always get the CLOB, even when we are not reading the contents.
799: // Since the CLOB is just a pointer to the CLOB data rather than the
800: // data itself, this operation should not take much time (as opposed
801: // to getting all of the data in the clob).
802: Clob clob = rs.getClob(index);
803:
804: if (rs.wasNull()) {
805: return null;
806: }
807: // CLOB exists, so try to read the data from it
808: if (clob != null) {
809: return clob.getSubString(1, 255);
810: }
811: }
812: case Types.OTHER:
813: default:
814: return rs.getObject(index);
815: }
816: }
817:
818: void setHeader(JTable table, List<Integer> columnWidthList) {
819: try {
820: TableColumnModel cModel = table.getColumnModel();
821: for (int i = 0; i < columnWidthList.size(); i++) {
822: TableColumn column = cModel.getColumn(i);
823: column.setPreferredWidth(columnWidthList.get(i));
824: }
825: table.getTableHeader().setColumnModel(cModel);
826: } catch (Exception e) {
827: mLogger
828: .errorNoloc(
829: mLoc
830: .t(
831: "PRSR147: Failed to set the size of the table headers({0})",
832: LOG_CATEGORY), e);
833: }
834: }
835:
836: List<Integer> getColumnWidthList(ResultSetMetaData md) {
837: List<Integer> columnWidthList = new ArrayList<Integer>();
838: try {
839: for (int i = 0; i < md.getColumnCount(); i++) {
840: int fieldWidth = md.getColumnDisplaySize(i + 1);
841: int labelWidth = md.getColumnLabel(i + 1).length();
842: int colWidth = Math.max(fieldWidth, labelWidth)
843: * multiplier;
844: if (colWidth > MAX_COLUMN_WIDTH * multiplier) {
845: colWidth = MAX_COLUMN_WIDTH * multiplier;
846: }
847: columnWidthList.add(colWidth);
848: }
849: } catch (Exception e) {
850: mLogger
851: .errorNoloc(
852: mLoc
853: .t(
854: "PRSR148: Failed to set the size of the table headers({0})",
855: LOG_CATEGORY), e);
856: }
857: return columnWidthList;
858: }
859:
860: private TableModel createModelFrom(Map rsMap) {
861: DataTableModel dtm = new DataTableModel();
862: TableSorter sorter = new TableSorter(dtm);
863: sorter.setTableHeader(table.getTableHeader());
864:
865: Object[] row = null;
866:
867: for (Object key : rsMap.keySet()) {
868: String value = (String) rsMap.get(key);
869: dtm.addColumn(key);
870: row = new Object[value.length()];
871: }
872:
873: int i = 0;
874: for (Object value : rsMap.values()) {
875: if (row != null) {
876: row = new Object[rsMap.size()];
877: row[i++] = value;
878: dtm.addRow(row);
879: }
880: }
881:
882: return sorter;
883: }
884:
885: void closeResources(PreparedStatement pstmt, Connection conn) {
886:
887: try {
888: if (pstmt != null) {
889: pstmt.close();
890: }
891: } catch (SQLException ex) {
892: //ignore
893: }
894:
895: try {
896: if (conn != null) {
897: conn.close();
898: }
899: } catch (SQLException ex) {
900: //ignore
901: }
902: }
903:
904: private String generateWhereCondition(List<Integer> types,
905: List values, int rowNum) {
906: DBTableMetadata meta = dataPanel.meta;
907: StringBuilder result = new StringBuilder();
908:
909: PrimaryKey key = meta.getTable().getPrimaryKey();
910: if (key != null) {
911: int j = 0;
912: for (String keyName : key.getColumnNames()) {
913: result.append((j++ != 0 ? " AND " : ""));
914: for (int i = 0; i < table.getColumnCount(); i++) {
915: if (table.getColumnModel().getColumn(i)
916: .getHeaderValue().equals(keyName)) {
917: if (model.getValueAt(rowNum, i) != null) {
918: result.append(keyName + " = ? ");
919: values.add(model.getValueAt(rowNum, i));
920: types.add(meta.getColumnType(i));
921: break;
922: }
923: }
924: }
925: }
926: } else {
927: for (int i = 0; i < table.getColumnCount(); i++) {
928: if (model.getValueAt(rowNum, i) != null) {
929: String columnName = meta.getColumnName(i);
930: result.append((i != 0 ? " AND " : ""));
931: result.append(columnName + " = ? ");
932: values.add(model.getValueAt(rowNum, i));
933: types.add(meta.getColumnType(i));
934: }
935: }
936: }
937:
938: return result.toString();
939: }
940: }
|