Author: thomasobrien95
Date: Fri Dec 5 12:07:03 2008
New Revision: 2866
Added:
trunk/regress/ca/sqlpower/architect/swingui/IndexColumnTableTest.java
Modified:
trunk/src/ca/sqlpower/architect/SQLIndex.java
trunk/src/ca/sqlpower/architect/swingui/IndexColumnTable.java
trunk/src/ca/sqlpower/architect/swingui/action/DeleteSelectedAction.java
trunk/src/ca/sqlpower/architect/swingui/dbtree/DBTreeCellRenderer.java
Log:
This is a fix for bug 1526. Expanding an index in the DB tree was
throwing a NPE as the SQLColumn in a Column was null due to the
Column being constructed from a function. Null checks, and a fix to
the index properties window removed the NPE and allows the index to
be saved with an existing column index from a function.
A test case has also been added.
Added: trunk/regress/ca/sqlpower/architect/swingui/IndexColumnTableTest.java
==============================================================================
--- (empty file)
+++ trunk/regress/ca/sqlpower/architect/swingui/IndexColumnTableTest.java
Fri Dec 5 12:07:03 2008
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2008, SQL Power Group Inc.
+ *
+ * This file is part of Power*Architect.
+ *
+ * Power*Architect is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Power*Architect 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, see <http://www.gnu.org/licenses/>.
+ */
+
+package ca.sqlpower.architect.swingui;
+
+import junit.framework.TestCase;
+import ca.sqlpower.architect.SQLIndex;
+import ca.sqlpower.architect.SQLTable;
+import ca.sqlpower.architect.SQLIndex.AscendDescend;
+import ca.sqlpower.architect.SQLIndex.Column;
+import
ca.sqlpower.architect.swingui.IndexColumnTable.IndexColumnTableModel;
+
+public class IndexColumnTableTest extends TestCase {
+
+ /**
+ * This will test the PopulateModel method on the IndexColumnTableModel
+ * to verify the table does not throw an exception when an index is
added
+ * that has a column with no SQLColumn. This is related to bug 1526.
+ */
+ public void testTableModelPopulateAllowsNulls() throws Exception {
+ SQLTable table = new SQLTable();
+ table.initFolders(true);
+ SQLIndex index = new SQLIndex();
+ Column col = index.new Column("TestCol",
AscendDescend.UNSPECIFIED);
+ index.addChild(col);
+ table.addIndex(index);
+ SQLIndex copyIndex = new SQLIndex(index);
+ IndexColumnTable ict = new IndexColumnTable(table, copyIndex,
index);
+
+ IndexColumnTableModel ictm = ict.new
IndexColumnTableModel(copyIndex, table, index);
+
+ assertEquals(1, ictm.getRowCount());
+ assertEquals(1, index.getChildCount());
+
+ System.out.println(ictm.getRowList());
+
+ ict.finalizeIndex();
+
+ System.out.println(ictm.getRowList());
+
+ assertEquals(1, index.getChildCount());
+
+ //Assert the column not the null SQLColumn in the column to come
back.
+ assertEquals(col, ictm.getValueAt(0, 1));
+ }
+}
Modified: trunk/src/ca/sqlpower/architect/SQLIndex.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/SQLIndex.java (original)
+++ trunk/src/ca/sqlpower/architect/SQLIndex.java Fri Dec 5 12:07:03 2008
@@ -201,6 +201,10 @@
}
}
+ /**
+ * NOTE: This column can be null if the column it represents is an
expression
+ * and not a basic column.
+ */
public SQLColumn getColumn() {
return column;
}
@@ -490,7 +494,7 @@
try {
for (int i = 0; i < e.getChildren().length; i++) {
for (int j = this.getChildCount() - 1; j >= 0; j--) {
- if
(getChild(j).getColumn().equals(e.getChildren()[i])) {
+ if (getChild(j).getColumn() != null &&
getChild(j).getColumn().equals(e.getChildren()[i])) {
removeChild(j);
}
}
@@ -760,8 +764,16 @@
return getName();
}
+ /**
+ * Adds a column to the index. If col1 is null a NPE will be thrown.
+ */
public void addIndexColumn(SQLColumn col1, AscendDescend aOrD) throws
ArchitectException {
Column col = new Column(col1, aOrD);
+ addChild(col);
+ }
+
+ public void addIndexColumn(String colName, AscendDescend aOrD) throws
ArchitectException {
+ Column col = new Column(colName, aOrD);
addChild(col);
}
Modified: trunk/src/ca/sqlpower/architect/swingui/IndexColumnTable.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/IndexColumnTable.java
(original)
+++ trunk/src/ca/sqlpower/architect/swingui/IndexColumnTable.java Fri Dec
5 12:07:03 2008
@@ -45,6 +45,8 @@
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
+import org.apache.log4j.Logger;
+
import ca.sqlpower.architect.ArchitectException;
import ca.sqlpower.architect.ArchitectRuntimeException;
import ca.sqlpower.architect.SQLColumn;
@@ -64,8 +66,13 @@
* index. This table will be used by the IndexEditPanel class.
*/
public class IndexColumnTable {
+
+ private static final Logger logger =
Logger.getLogger(IndexColumnTable.class);
- private class IndexColumnTableModel extends AbstractTableModel
implements CleanupTableModel, SQLObjectListener {
+ /**
+ * This is package private for testing purposes.
+ */
+ class IndexColumnTableModel extends AbstractTableModel implements
CleanupTableModel, SQLObjectListener {
/**
* This List contains all of the Row objects in the table. Refer
to the
@@ -199,7 +206,11 @@
private void populateModel() {
try {
for (Column indexCol : index.getChildren()) {
- rowList.add(new Row(true, indexCol.getColumn(),
indexCol.getAscendingOrDescending()));
+ if (indexCol.getColumn() != null) {
+ rowList.add(new Row(true, indexCol.getColumn(),
indexCol.getAscendingOrDescending()));
+ } else {
+ rowList.add(new Row(true, indexCol,
indexCol.getAscendingOrDescending()));
+ }
}
for (Object so : columnsFolder.getChildren()) {
SQLColumn col = (SQLColumn) so;
@@ -288,16 +299,26 @@
public Object getValueAt(int row, int col) {
if (col == 0) return
Boolean.valueOf(rowList.get(row).isEnabled());
- else if (col == 1) return rowList.get(row).getSQLColumn();
+ else if (col == 1 && rowList.get(row).getSQLColumn() != null)
return rowList.get(row).getSQLColumn();
+ else if (col == 1) return rowList.get(row).getColumn();
else if (col == 2) return rowList.get(row).getOrder();
else throw new ArchitectRuntimeException(new
ArchitectException("This table only has 3 columns.")); //$NON-NLS-1$
}
public void setValueAt(Object value, int row, int col) {
- if (col == 0) rowList.get(row).setEnabled(((Boolean)
value).booleanValue());
- else if (col == 1) rowList.get(row).setSQLColumn((SQLColumn)
value);
- else if (col == 2) rowList.get(row).setOrder((AscendDescend)
value);
- else throw new ArchitectRuntimeException(new
ArchitectException("This table only has 3 columns.")); //$NON-NLS-1$
+ if (col == 0) {
+ rowList.get(row).setEnabled(((Boolean)
value).booleanValue());
+ } else if (col == 1) {
+ if (value instanceof SQLColumn) {
+ rowList.get(row).setSQLColumn((SQLColumn) value);
+ } else {
+ rowList.get(row).setColumn((Column) value);
+ }
+ } else if (col == 2) {
+ rowList.get(row).setOrder((AscendDescend) value);
+ } else {
+ throw new ArchitectRuntimeException(new
ArchitectException("This table only has 3 columns.")); //$NON-NLS-1$
+ }
fireTableCellUpdated(row, col);
}
@@ -359,21 +380,38 @@
/**
* This is the SQLCOlumn in the row
*/
- private SQLColumn column;
+ private SQLColumn sqlColumn;
/**
* This is the order of the SQLColumn
*/
private AscendDescend order;
+
+ /**
+ * This is a Column in the row for Columns that have no
+ * SQLColumn. Columns have no SQLColumn when an index
+ * is created from a function or possibly other ways.
+ */
+ private Column column;
public Row(boolean enabled, SQLColumn column, AscendDescend order)
{
this.enabled = enabled;
+ this.sqlColumn = column;
+ this.order = order;
+ }
+
+ public Row(boolean enabled, Column column, AscendDescend order) {
+ this.enabled = enabled;
this.column = column;
this.order = order;
}
public String toString() {
- return new String ("Enabled: " +enabled + " Col: " +
column.getName()); //$NON-NLS-1$ //$NON-NLS-2$
+ if (sqlColumn != null) {
+ return new String ("Enabled: " +enabled + " Col: " +
sqlColumn.getName()); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ return new String ("Enabled: " +enabled + " Col: " +
column.getName()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
}
public void setEnabled(boolean enabled) {
@@ -381,7 +419,7 @@
}
public void setSQLColumn(SQLColumn column) {
- this.column = column;
+ this.sqlColumn = column;
}
public void setOrder(AscendDescend order) {
@@ -393,13 +431,21 @@
}
public SQLColumn getSQLColumn() {
- return this.column;
+ return this.sqlColumn;
}
public AscendDescend getOrder() {
return this.order;
}
+ public void setColumn(Column column) {
+ this.column = column;
+ }
+
+ public Column getColumn() {
+ return column;
+ }
+
}
public static final String IN_INDEX =
Messages.getString("IndexColumnTable.indexTableColumnName"); //$NON-NLS-1$
@@ -455,7 +501,12 @@
}
for(Row r : model.getRowList()) {
if (r.isEnabled()){
- index.addIndexColumn(r.getSQLColumn(), r.getOrder());
+ if (r.getSQLColumn() != null) {
+ index.addIndexColumn(r.getSQLColumn(),
r.getOrder());
+ } else {
+ logger.debug("Adding index column with no
SQLColumn. Column name is " + r.getColumn().getName());
+ index.addIndexColumn(r.getColumn().getName(),
r.getOrder());
+ }
}
}
Modified:
trunk/src/ca/sqlpower/architect/swingui/action/DeleteSelectedAction.java
==============================================================================
---
trunk/src/ca/sqlpower/architect/swingui/action/DeleteSelectedAction.java
(original)
+++
trunk/src/ca/sqlpower/architect/swingui/action/DeleteSelectedAction.java
Fri Dec 5 12:07:03 2008
@@ -141,7 +141,9 @@
cols.add(col.getColumn());
}
for (SQLColumn col : cols) {
- col.setPrimaryKeySeq(null);
+ if (col != null) {
+ col.setPrimaryKeySeq(null);
+ }
}
} else {
o.getParent().removeChild(o);
Modified:
trunk/src/ca/sqlpower/architect/swingui/dbtree/DBTreeCellRenderer.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/dbtree/DBTreeCellRenderer.java
(original)
+++ trunk/src/ca/sqlpower/architect/swingui/dbtree/DBTreeCellRenderer.java
Fri Dec 5 12:07:03 2008
@@ -29,6 +29,8 @@
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
+import org.apache.log4j.Logger;
+
import ca.sqlpower.architect.SQLCatalog;
import ca.sqlpower.architect.SQLColumn;
import ca.sqlpower.architect.SQLDatabase;
@@ -51,6 +53,8 @@
*/
public class DBTreeCellRenderer extends DefaultTreeCellRenderer {
+ private static final Logger logger =
Logger.getLogger(DBTreeCellRenderer.class);
+
public static final ImageIcon DB_ICON = new
ImageIcon(DBTreeCellRenderer.class.getResource("icons/Database16.png"));
public static final ImageIcon TARGET_DB_ICON = new
ImageIcon(DBTreeCellRenderer.class.getResource("icons/Database_target16.png"));
public static final ImageIcon CATALOG_ICON = new
ImageIcon(DBTreeCellRenderer.class.getResource("icons/Catalog16.png"));
@@ -131,7 +135,11 @@
tagColumn((SQLColumn)value);
setIcon(COLUMN_ICON);
} else if (value instanceof Column) {
- tagColumn(((Column)value).getColumn());
+ Column col = (Column) value;
+ logger.debug("Column has properties " + col);
+ if (col.getColumn() != null) {
+ tagColumn((col).getColumn());
+ }
setIcon(COLUMN_ICON);
} else {
setIcon(null);