001: package net.sourceforge.squirrel_sql.client.session.properties;
002:
003: /*
004: *
005: * Adapted from WhereClausePanel.java by Maury Hammel.
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: import java.awt.BorderLayout;
022: import java.awt.Dimension;
023: import java.awt.GridLayout;
024: import java.awt.event.ActionEvent;
025: import java.awt.event.ActionListener;
026: import java.sql.SQLException;
027: import java.util.ArrayList;
028: import java.util.HashMap;
029: import java.util.HashSet;
030: import java.util.Iterator;
031: import java.util.SortedSet;
032: import java.util.TreeSet;
033:
034: import javax.swing.JButton;
035: import javax.swing.JLabel;
036: import javax.swing.JList;
037: import javax.swing.JOptionPane;
038: import javax.swing.JPanel;
039: import javax.swing.JScrollPane;
040: import javax.swing.ListModel;
041:
042: import net.sourceforge.squirrel_sql.client.session.ISession;
043: import net.sourceforge.squirrel_sql.fw.sql.ITableInfo;
044: import net.sourceforge.squirrel_sql.fw.sql.PrimaryKeyInfo;
045: import net.sourceforge.squirrel_sql.fw.util.StringManager;
046: import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
047: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
048: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
049:
050: /**
051: * This panel allows the user to select specific columns from a specific table for use in
052: * the WHERE clause when editing a cell in a table. This is useful if the table has a large number
053: * of columns and the WHERE clause generated using all the columns exceeds the DBMS limit.
054: */
055: @SuppressWarnings("serial")
056: public class EditWhereColsPanel extends JPanel {
057: private static final StringManager s_stringMgr = StringManagerFactory
058: .getStringManager(EditWhereColsPanel.class);
059:
060: /** Logger for this class. */
061: private static final ILogger s_log = LoggerController
062: .createLogger(EditWhereColsPanel.class);
063:
064: /** The name of the database table the Where clause applies to. */
065: private String _tableName;
066:
067: /** The name of the table including the URL **/
068: private String _unambiguousTableName;
069:
070: /** The list of all possible columns in the table **/
071: private SortedSet<String> _columnList;
072:
073: /** The list of "to use" column names as seen by the user **/
074: private JList useColsList;
075:
076: /** The list of "to NOT use" column names as seen by the user **/
077: private JList notUseColsList;
078:
079: /** The list of column names to use as calculated when window is created **/
080: private Object[] initalUseColsArray;
081:
082: /** The list of column names to NOT use as calculated when window is created **/
083: private Object[] initalNotUseColsArray;
084:
085: private ISession _session = null;
086:
087: private PrimaryKeyInfo[] primaryKeyInfos = null;
088:
089: EditWhereCols _editWhereCols = new EditWhereCols();
090:
091: /**
092: * ?? this should be changed to use the I18N file mechanism.
093: */
094: interface EditWhereColsPanelI18N {
095: // i18n[editWhereColsPanel.limitColsInCell=Limit Columns in Cell Edit]
096: String TITLE = s_stringMgr
097: .getString("editWhereColsPanel.limitColsInCell");
098: // i18n[editWhereColsPanel.limitColsInCellHint=Limit columns used in WHERE clause when editing table]
099: String HINT = s_stringMgr
100: .getString("editWhereColsPanel.limitColsInCellHint");
101: // i18n[editWhereColsPanel.usePKLabel=Use PK]
102: String USE_PK = s_stringMgr
103: .getString("editWhereColsPanel.usePKLabel");
104:
105: }
106:
107: /**
108: * Create a new instance of a WhereClausePanel.
109: *
110: * @param columnList A list of column names for the database table.
111: * @param tableName The name of the database table that the filter
112: * information will apply to.
113: * @param unambiguousTableName The name of the table including the URL
114: * to the specific DBMS
115: *
116: * @throws IllegalArgumentException
117: * The exception thrown if invalid arguments are passed.
118: */
119: public EditWhereColsPanel(ISession session, ITableInfo ti,
120: SortedSet<String> columnList, String unambiguousTableName)
121: throws IllegalArgumentException {
122: super ();
123: _session = session;
124: _editWhereCols.setApplication(session.getApplication());
125: getPrimaryKey(ti);
126: // save the input for use later
127: _columnList = columnList;
128: _tableName = ti.getQualifiedName();
129: _unambiguousTableName = unambiguousTableName;
130:
131: // look up the table in the EditWhereCols list
132: HashMap<String, String> colsTable = EditWhereCols
133: .get(unambiguousTableName);
134:
135: if (colsTable == null) {
136: // use all of the columns
137: initalUseColsArray = _columnList.toArray();
138: initalNotUseColsArray = new Object[0];
139: } else {
140: // use just the columns listed in the table, and set the not-used cols to the ones
141: // that are not mentioned in the table
142: SortedSet<Object> initialUseColsSet = new TreeSet<Object>();
143: SortedSet<Object> initialNotUseColsList = new TreeSet<Object>();
144:
145: Iterator<String> it = _columnList.iterator();
146: while (it.hasNext()) {
147: Object colName = it.next();
148: if (colsTable.get(colName) != null)
149: initialUseColsSet.add(colName);
150: else
151: initialNotUseColsList.add(colName);
152: }
153: initalUseColsArray = initialUseColsSet.toArray();
154: initalNotUseColsArray = initialNotUseColsList.toArray();
155: }
156:
157: // create all of the gui objects now
158: createGUI();
159: }
160:
161: private void getPrimaryKey(ITableInfo ti) {
162: try {
163: primaryKeyInfos = _session.getMetaData().getPrimaryKey(ti);
164: } catch (SQLException e) {
165: s_log.error(
166: "Unexpected exception while attempting to get primary key info"
167: + " for table " + ti.getQualifiedName()
168: + ": " + e.getMessage(), e);
169: }
170: }
171:
172: /**
173: * Get the title of the panel.
174: *
175: * @return Return a string containing the title of the panl.
176: */
177: public String getTitle() {
178: return EditWhereColsPanelI18N.TITLE;
179: }
180:
181: /**
182: * Get the hint text associated with the panel.
183: *
184: * @return A String value containing the hint text associated with the panel.
185: */
186: public String getHint() {
187: return EditWhereColsPanelI18N.HINT;
188: }
189:
190: /**
191: * Reset the panel to the contents at the time we started editing
192: * (as set in initialize).
193: *
194: */
195: public void reset() {
196: useColsList.setListData(initalUseColsArray);
197: notUseColsList.setListData(initalNotUseColsArray);
198: }
199:
200: /**
201: * Put the current data into the EditWhereCols table.
202: */
203: public boolean ok() {
204:
205: // if all cols are in the "to use" side, delete from EditWhereCols
206: if (notUseColsList.getModel().getSize() == 0) {
207: _editWhereCols.put(_unambiguousTableName, null);
208: } else {
209: // some cols are not to be used
210: ListModel useColsModel = useColsList.getModel();
211:
212: // do not let user remove everything from the list
213: if (useColsModel.getSize() == 0) {
214: JOptionPane
215: .showMessageDialog(
216: this ,
217: // i18n[editWhereColsPanel.cannotRemoveAllCols=You cannot remove all of the fields from the 'use columns' list.]
218: s_stringMgr
219: .getString("editWhereColsPanel.cannotRemoveAllCols"));
220: return false;
221: }
222:
223: // create the HashMap of names to use and put it in EditWhereCols
224: HashMap<String, String> useColsMap = new HashMap<String, String>(
225: useColsModel.getSize());
226:
227: for (int i = 0; i < useColsModel.getSize(); i++) {
228: useColsMap.put((String) useColsModel.getElementAt(i),
229: (String) useColsModel.getElementAt(i));
230: }
231:
232: _editWhereCols.put(_unambiguousTableName, useColsMap);
233: }
234: return true;
235: }
236:
237: /**
238: * Move selected fields from "used" to "not used"
239: */
240: private void moveToNotUsed() {
241:
242: // get the values from the "not use" list and convert to sorted set
243: ListModel notUseColsModel = notUseColsList.getModel();
244: SortedSet<String> notUseColsSet = new TreeSet<String>();
245: for (int i = 0; i < notUseColsModel.getSize(); i++)
246: notUseColsSet.add((String) notUseColsModel.getElementAt(i));
247:
248: // get the values from the "use" list
249: ListModel useColsModel = useColsList.getModel();
250:
251: // create an empty set for the "use" list
252: SortedSet<Object> useColsSet = new TreeSet<Object>();
253:
254: // for each element in the "use" set, if selected then add to "not use",
255: // otherwise add to new "use" set
256: for (int i = 0; i < useColsModel.getSize(); i++) {
257: String colName = (String) useColsModel.getElementAt(i);
258: if (useColsList.isSelectedIndex(i))
259: notUseColsSet.add(colName);
260: else
261: useColsSet.add(colName);
262: }
263:
264: useColsList.setListData(useColsSet.toArray());
265: notUseColsList.setListData(notUseColsSet.toArray());
266: }
267:
268: /**
269: * Move selected fields from "not used" to "used"
270: */
271: private void moveToUsed() {
272: // get the values from the "use" list and convert to sorted set
273: ListModel useColsModel = useColsList.getModel();
274: SortedSet<String> useColsSet = new TreeSet<String>();
275: for (int i = 0; i < useColsModel.getSize(); i++)
276: useColsSet.add((String) useColsModel.getElementAt(i));
277:
278: // get the values from the "not use" list
279: ListModel notUseColsModel = notUseColsList.getModel();
280:
281: // create an empty set for the "not use" list
282: SortedSet<Object> notUseColsSet = new TreeSet<Object>();
283:
284: // for each element in the "not use" set, if selected then add to "use",
285: // otherwise add to new "not use" set
286: for (int i = 0; i < notUseColsModel.getSize(); i++) {
287: String colName = (String) notUseColsModel.getElementAt(i);
288: if (notUseColsList.isSelectedIndex(i))
289: useColsSet.add(colName);
290: else
291: notUseColsSet.add(colName);
292: }
293:
294: useColsList.setListData(useColsSet.toArray());
295: notUseColsList.setListData(notUseColsSet.toArray());
296: }
297:
298: private void usePK() {
299: if (primaryKeyInfos == null || primaryKeyInfos.length <= 0) {
300: // i18n[editWhereColsPanel.noPK=The table ''{0}'' doesn't have a primary key.]
301: String msg = s_stringMgr.getString(
302: "editWhereColsPanel.noPK", _tableName);
303: JOptionPane.showMessageDialog(this , msg);
304:
305: return;
306: }
307: HashSet<String> pkCols = new HashSet<String>();
308: for (int i = 0; i < primaryKeyInfos.length; i++) {
309: PrimaryKeyInfo pkInfo = primaryKeyInfos[i];
310: pkCols.add(pkInfo.getColumnName());
311: }
312:
313: ArrayList<String> newNotUseList = new ArrayList<String>();
314: ListModel useColsModel = useColsList.getModel();
315: ListModel notUseColsModel = notUseColsList.getModel();
316:
317: for (int i = 0; i < useColsModel.getSize(); i++) {
318: Object colName = useColsModel.getElementAt(i);
319: if (!pkCols.contains(colName)) {
320: newNotUseList.add(colName.toString());
321: }
322: }
323:
324: for (int i = 0; i < notUseColsModel.getSize(); i++) {
325: Object colName = notUseColsModel.getElementAt(i);
326: if (!pkCols.contains(colName)) {
327: newNotUseList.add(colName.toString());
328: }
329: }
330:
331: useColsList.setListData(pkCols.toArray());
332: notUseColsList.setListData(newNotUseList.toArray());
333:
334: }
335:
336: /**
337: * Create the GUI elements for the panel.
338: */
339: private void createGUI() {
340:
341: JPanel useColsPanel = new JPanel(new BorderLayout());
342: // i18n[editWhereColsPanel.useColumns=Use Columns]
343: useColsPanel.add(new JLabel(s_stringMgr
344: .getString("editWhereColsPanel.useColumns")),
345: BorderLayout.NORTH);
346: useColsList = new JList(initalUseColsArray);
347: JScrollPane scrollPane = new JScrollPane(useColsList);
348: scrollPane.setPreferredSize(new Dimension(200, 200));
349: useColsPanel.add(scrollPane, BorderLayout.SOUTH);
350: add(useColsPanel);
351:
352: JPanel moveButtonsPanel = new JPanel();
353: JPanel buttonPanel = new JPanel(new GridLayout(3, 1));
354: //????? if desired, get fancy and use icons in buttons instead of text ?????????
355: JButton moveToNotUsedButton = new JButton("=>");
356: moveToNotUsedButton.addActionListener(new ActionListener() {
357: public void actionPerformed(ActionEvent evt) {
358: moveToNotUsed();
359: }
360: });
361: buttonPanel.add(moveToNotUsedButton);
362: JButton moveToUsedButton = new JButton("<=");
363: moveToUsedButton.addActionListener(new ActionListener() {
364: public void actionPerformed(ActionEvent evt) {
365: moveToUsed();
366: }
367: });
368: buttonPanel.add(moveToUsedButton);
369:
370: JButton usePKButton = new JButton(EditWhereColsPanelI18N.USE_PK);
371: usePKButton.addActionListener(new ActionListener() {
372: public void actionPerformed(ActionEvent evt) {
373: usePK();
374: }
375: });
376: buttonPanel.add(usePKButton);
377:
378: moveButtonsPanel.add(buttonPanel, BorderLayout.CENTER);
379: add(moveButtonsPanel);
380:
381: JPanel notUseColsPanel = new JPanel(new BorderLayout());
382: // i18n[editWhereColsPanel.notUseColumns=Not Use Columns]
383: notUseColsPanel.add(new JLabel(s_stringMgr
384: .getString("editWhereColsPanel.notUseColumns")),
385: BorderLayout.NORTH);
386: notUseColsList = new JList(initalNotUseColsArray);
387: JScrollPane notUseScrollPane = new JScrollPane(notUseColsList);
388: notUseScrollPane.setPreferredSize(new Dimension(200, 200));
389: notUseColsPanel.add(notUseScrollPane, BorderLayout.SOUTH);
390: add(notUseColsPanel);
391: }
392: }
|