001: package net.sourceforge.squirrel_sql.client.session.sqlfilter;
002:
003: /*
004: * Copyright (C) 2003 Maury Hammel
005: * mjhammel@users.sourceforge.net
006: *
007: * Adapted from SessionSQLPropertiesPanel.java by Colin Bell.
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022: */
023: import java.awt.Component;
024: import java.awt.Dimension;
025: import java.awt.GridBagConstraints;
026: import java.awt.GridBagLayout;
027: import java.awt.Insets;
028: import java.awt.event.ActionEvent;
029: import java.awt.event.ActionListener;
030: import java.util.Map;
031: import java.util.SortedSet;
032:
033: import javax.swing.BorderFactory;
034: import javax.swing.Box;
035: import javax.swing.BoxLayout;
036: import javax.swing.JButton;
037: import javax.swing.JComboBox;
038: import javax.swing.JLabel;
039: import javax.swing.JPanel;
040: import javax.swing.JScrollPane;
041: import javax.swing.JTextArea;
042: import javax.swing.JTextField;
043:
044: import net.sourceforge.squirrel_sql.fw.util.StringManager;
045: import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
046:
047: /**
048: * This panel allows the user to change the where clause for a Contents tab query.
049: *
050: * @author <A HREF="mailto:mjhammel@users.sourceforge.net">Maury Hammel</A>
051: */
052: public class WhereClausePanel implements ISQLFilterPanel {
053: /** Internationalized strings for this class. */
054: private static final StringManager s_stringMgr = StringManagerFactory
055: .getStringManager(WhereClausePanel.class);
056:
057: /** A class containing the information about the SQL filters. */
058: private SQLFilterClauses _sqlFilterClauses;
059:
060: /** The actual GUI panel that allows user to do the maintenance. */
061: private WhereClauseSubPanel _myPanel;
062:
063: /**
064: * Create a new instance of a WhereClausePanel.
065: *
066: * @param columnList A list of column names for the database table.
067: * @param textColumns A collection of column names that are "text"
068: * columns.
069: * @param tableName The name of the database table that the filter
070: * information will apply to.
071: *
072: * @throws IllegalArgumentException
073: * The exception thrown if invalid arguments are passed.
074: */
075: public WhereClausePanel(SortedSet<String> columnList,
076: Map<String, Boolean> textColumns, String tableName)
077: throws IllegalArgumentException {
078: super ();
079: _myPanel = new WhereClauseSubPanel(columnList, textColumns,
080: tableName);
081: }
082:
083: /**
084: * Initialize the components of the WhereClausePanel.
085: *
086: * @param sqlFilterClauses An instance of a class containing information
087: * about SQL filters already in place for the table.
088: *
089: * @throws IllegalArgumentException
090: * Thrown if an invalid argument is passed.
091: */
092: public void initialize(SQLFilterClauses sqlFilterClauses)
093: throws IllegalArgumentException {
094: if (sqlFilterClauses == null) {
095: throw new IllegalArgumentException(
096: "Null sqlFilterClauses passed");
097: }
098:
099: _sqlFilterClauses = sqlFilterClauses;
100: _myPanel.loadData(_sqlFilterClauses);
101: }
102:
103: /**
104: * Returns the panel created by the class.
105: *
106: * @return Return an instance of a WhereClauseSubPanel.
107: */
108: public Component getPanelComponent() {
109: return _myPanel;
110: }
111:
112: /**
113: * Get the title of the panel.
114: *
115: * @return Return a string containing the title of the panl.
116: */
117: public String getTitle() {
118: return WhereClauseSubPanel.WhereClauseSubPanelI18n.WHERE_CLAUSE;
119: }
120:
121: /**
122: * Get the hint text associated with the panel.
123: *
124: * @return A String value containing the hint text associated with the panel.
125: */
126: public String getHint() {
127: return WhereClauseSubPanel.WhereClauseSubPanelI18n.HINT;
128: }
129:
130: /**
131: * Update the current session with any changes to the SQL filter
132: * information.
133: */
134: public void applyChanges() {
135: _myPanel.applyChanges(_sqlFilterClauses);
136: }
137:
138: /**
139: * A private class that makes up the bulk of the GUI for the panel.
140: */
141: private static final class WhereClauseSubPanel extends JPanel {
142: private static final long serialVersionUID = 1L;
143:
144: /**
145: * This interface defines locale specific strings. This should be
146: * replaced with a property file.
147: */
148: interface WhereClauseSubPanelI18n {
149: //i18n[WhereClausePanel.columnLabel=Columns]
150: String COLUMNS = s_stringMgr
151: .getString("WhereClausePanel.columnLabel");
152: //i18n[WhereClausePanel.operatorsLabel=Operators]
153: String OPERATORS = s_stringMgr
154: .getString("WhereClausePanel.operatorsLabel");
155: //i18n[WhereClausePanel.valueLabel=Value]
156: String VALUE = s_stringMgr
157: .getString("WhereClausePanel.valueLabel");
158: //i18n[WhereClausePanel.whereClauseLabel=Where Clause]
159: String WHERE_CLAUSE = s_stringMgr
160: .getString("WhereClausePanel.whereClauseLabel");
161: //i18n[WhereClausePanel.hint=Where clause for the selected table]
162: String HINT = s_stringMgr
163: .getString("WhereClausePanel.hint");
164: //i18n[WhereClausePanel.addLabel=Add]
165: String ADD = s_stringMgr
166: .getString("WhereClausePanel.addLabel");
167: // The following strings are SQL tokens and should therefore *not*
168: // be internationalized
169: String AND = "AND"; // No I18N
170: String OR = "OR"; // No I18N
171: String LIKE = "LIKE"; // No I18N
172: String IN = "IN"; // No I18N
173: String IS_NULL = "IS NULL"; // No I18N
174: String IS_NOT_NULL = "IS NOT NULL"; // No I18N
175: }
176:
177: /**
178: * A JComboBox component containing a list of the names of the
179: * columns for the current table.
180: */
181: private JComboBox _columnCombo;
182:
183: /** A label to identify the column combo box. */
184: private JLabel _columnLabel = new JLabel(
185: WhereClauseSubPanelI18n.COLUMNS);
186:
187: /**
188: * A JComboBox containing a list of valid operators used in SQL Where clause
189: * expressions.
190: */
191: private OperatorTypeCombo _operatorCombo = new OperatorTypeCombo();
192:
193: /** A label to identify the operator combo box. */
194: private JLabel _operatorLabel = new JLabel(
195: WhereClauseSubPanelI18n.OPERATORS);
196:
197: /** A field used to enter the right-hand side of a WhereClause expression. */
198: private JTextField _valueField = new JTextField(10);
199:
200: /** A label to identify the valueField text area. */
201: private JLabel _valueLabel = new JLabel(
202: WhereClauseSubPanelI18n.VALUE);
203:
204: /** A JComboBox used to list Where clause connectors. */
205: private AndOrCombo _andOrCombo = new AndOrCombo();
206:
207: /** A label to identify the andor combo box. */
208: private JLabel _andOrLabel = new JLabel(" ");
209:
210: /** A text area used to contain all of the information for the Where clause. */
211: private JTextArea _whereClauseArea = new JTextArea(10, 40);
212:
213: /**
214: * A button used to add information from the combo boxes and text fields into the
215: * Where clause text area.
216: */
217: private JButton _addTextButton = new JButton(
218: WhereClauseSubPanelI18n.ADD);
219:
220: /** The name of the database table the Where clause applies to. */
221: private String _tableName;
222:
223: /** A List containing the names of the text columns */
224: private Map<String, Boolean> _textColumns;
225:
226: /**
227: * A JPanel used for a bulk of the GUI elements of the panel.
228: *
229: * @param columnList A list of the column names for the table.
230: * @param tableName The name of the database table.
231: */
232: WhereClauseSubPanel(SortedSet<String> columnList,
233: Map<String, Boolean> textColumns, String tableName) {
234: super ();
235: _tableName = tableName;
236: _columnCombo = new JComboBox(columnList.toArray());
237: _textColumns = textColumns;
238: createGUI();
239: }
240:
241: /**
242: * Load existing clause information into the panel.
243: *
244: * @param sqlFilterClauses An instance of a class containing
245: * SQL Filter information for the current table.
246: *
247: */
248: void loadData(SQLFilterClauses sqlFilterClauses) {
249: _whereClauseArea.setText(sqlFilterClauses.get(
250: getClauseIdentifier(), _tableName));
251: }
252:
253: /** Update the current SQuirreL session with any changes to the SQL filter
254: * information.
255: * @param sqlFilterClauses An instance of a class containing SQL Filter information for the current table.
256: *
257: */
258: void applyChanges(SQLFilterClauses sqlFilterClauses) {
259: sqlFilterClauses.put(getClauseIdentifier(), _tableName,
260: _whereClauseArea.getText());
261: }
262:
263: /**
264: * Create the GUI elements for the panel.
265: */
266: private void createGUI() {
267: setLayout(new GridBagLayout());
268: final GridBagConstraints gbc = new GridBagConstraints();
269: gbc.anchor = GridBagConstraints.WEST;
270: gbc.fill = GridBagConstraints.HORIZONTAL;
271:
272: gbc.gridx = 0;
273: gbc.gridy = 0;
274: add(createGeneralPanel(), gbc);
275: }
276:
277: /**
278: * Create a JPanel with GUI components.
279: *
280: * @return Returns a JPanel
281: */
282: private JPanel createGeneralPanel() {
283: final JPanel pnl = new JPanel(new GridBagLayout());
284:
285: final GridBagConstraints gbc = new GridBagConstraints();
286: gbc.anchor = GridBagConstraints.WEST;
287: gbc.insets = new Insets(4, 4, 4, 4);
288: gbc.weightx = 1.0;
289:
290: gbc.fill = GridBagConstraints.NONE;
291: gbc.gridx = 0;
292: gbc.gridy = 0;
293: gbc.gridwidth = 1;
294: JPanel andOrPanel = new JPanel();
295: andOrPanel.setLayout(new BoxLayout(andOrPanel,
296: BoxLayout.Y_AXIS));
297: _andOrLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
298: andOrPanel.add(_andOrLabel);
299: _andOrCombo.setAlignmentX(Component.LEFT_ALIGNMENT);
300: andOrPanel.add(_andOrCombo);
301: pnl.add(andOrPanel, gbc);
302:
303: gbc.gridx++;
304: gbc.gridwidth = 5;
305: gbc.fill = GridBagConstraints.HORIZONTAL;
306: JPanel columnPanel = new JPanel();
307: columnPanel.setLayout(new BoxLayout(columnPanel,
308: BoxLayout.Y_AXIS));
309: _columnLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
310: columnPanel.add(_columnLabel);
311: _columnCombo.setAlignmentX(Component.LEFT_ALIGNMENT);
312: columnPanel.add(_columnCombo);
313: pnl.add(columnPanel, gbc);
314:
315: gbc.gridx += 5;
316: gbc.gridwidth = 1;
317: gbc.fill = GridBagConstraints.NONE;
318: JPanel operatorPanel = new JPanel();
319: operatorPanel.setLayout(new BoxLayout(operatorPanel,
320: BoxLayout.Y_AXIS));
321: _operatorLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
322: operatorPanel.add(_operatorLabel);
323: _operatorCombo.setAlignmentX(Component.LEFT_ALIGNMENT);
324: operatorPanel.add(_operatorCombo);
325: pnl.add(operatorPanel, gbc);
326:
327: gbc.gridx++;
328: gbc.gridwidth = 1;
329: JPanel valuePanel = new JPanel();
330: valuePanel.setLayout(new BoxLayout(valuePanel,
331: BoxLayout.Y_AXIS));
332: _valueLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
333: valuePanel.add(_valueLabel);
334: valuePanel.add(Box.createRigidArea(new Dimension(5, 5)));
335: _valueField.setAlignmentX(Component.LEFT_ALIGNMENT);
336: valuePanel.add(_valueField);
337: pnl.add(valuePanel, gbc);
338:
339: gbc.gridx++;
340: _addTextButton.addActionListener(new ActionListener() {
341: public void actionPerformed(ActionEvent evt) {
342: addTextToClause();
343: }
344: });
345: pnl.add(_addTextButton, gbc);
346:
347: gbc.gridy++; // new line
348: gbc.gridx = 0;
349: gbc.gridwidth = 9;
350: gbc.fill = GridBagConstraints.HORIZONTAL;
351: gbc.ipady = 4;
352: _whereClauseArea.setBorder(BorderFactory
353: .createEtchedBorder());
354: _whereClauseArea.setLineWrap(true);
355: JScrollPane sp = new JScrollPane(_whereClauseArea,
356: JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
357: JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
358: pnl.add(sp, gbc);
359:
360: return pnl;
361: }
362:
363: private static final class OperatorTypeCombo extends JComboBox {
364: private static final long serialVersionUID = 1L;
365:
366: OperatorTypeCombo() {
367: addItem("=");
368: addItem("<>");
369: addItem(">");
370: addItem("<");
371: addItem(">=");
372: addItem("<=");
373: addItem(WhereClauseSubPanelI18n.IN);
374: addItem(WhereClauseSubPanelI18n.LIKE);
375: addItem(WhereClauseSubPanelI18n.IS_NULL);
376: addItem(WhereClauseSubPanelI18n.IS_NOT_NULL);
377: }
378: }
379:
380: private static final class AndOrCombo extends JComboBox {
381: private static final long serialVersionUID = 1L;
382:
383: AndOrCombo() {
384: addItem(WhereClauseSubPanelI18n.AND);
385: addItem(WhereClauseSubPanelI18n.OR);
386: }
387: }
388:
389: /**
390: * Combine the information entered in the combo boxes
391: * and the text field and add it to the Where clause information.
392: */
393: private void addTextToClause() {
394: String value = _valueField.getText();
395: String operator = (String) _operatorCombo.getSelectedItem();
396: if (((value != null) && (value.length() > 0))
397: || ((operator
398: .equals(WhereClauseSubPanelI18n.IS_NULL)) || (operator
399: .equals(WhereClauseSubPanelI18n.IS_NOT_NULL)))) {
400: String andOr = (String) _andOrCombo.getSelectedItem();
401: String column = (String) _columnCombo.getSelectedItem();
402:
403: // Put the 'AND' or the 'OR' in front of the clause if
404: // there are already values in the text area.
405: if (_whereClauseArea.getText().length() > 0) {
406: _whereClauseArea.append("\n" + andOr + " ");
407: }
408:
409: // If the operator is 'IN' and there are no parenthesis
410: // around the value, put them there.
411: if (operator.equals(WhereClauseSubPanelI18n.IN)
412: && (!value.trim().startsWith("("))) {
413: value = "(" + value + ")";
414: }
415:
416: // If the column is a text column, and there aren't single quotes around the value, put them there.
417:
418: else if ((value != null) && (value.length() > 0)) {
419: if (_textColumns.containsKey(column)
420: && (!value.trim().startsWith("'"))) {
421: value = "'" + value + "'";
422: }
423: }
424: _whereClauseArea.append(column + " " + operator);
425:
426: if ((value != null) && (value.length() > 0)) {
427: _whereClauseArea.append(" " + value);
428: }
429: }
430: _valueField.setText("");
431: }
432:
433: /**
434: * Erase all information for the current filter.
435: */
436: public void clearFilter() {
437: _whereClauseArea.setText("");
438: }
439: }
440:
441: /**
442: * Erase any information for the appropriate filter.
443: */
444: public void clearFilter() {
445: _myPanel.clearFilter();
446: }
447:
448: /**
449: * Get a value that uniquely identifies this SQL filter clause.
450: *
451: * @return Return a String value containing an identifing value.
452: */
453: public static String getClauseIdentifier() {
454: return WhereClauseSubPanel.WhereClauseSubPanelI18n.WHERE_CLAUSE;
455: }
456: }
|