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.view;
042:
043: import java.awt.BorderLayout;
044: import java.awt.Component;
045: import java.awt.Dimension;
046: import java.awt.FlowLayout;
047: import java.awt.GridBagConstraints;
048: import java.awt.GridBagLayout;
049: import java.awt.event.ActionEvent;
050: import java.awt.event.ActionListener;
051: import java.util.ArrayList;
052: import java.util.Collection;
053: import java.util.Iterator;
054: import java.util.List;
055:
056: import javax.swing.BorderFactory;
057: import javax.swing.JButton;
058: import javax.swing.JPanel;
059: import javax.swing.JScrollPane;
060: import javax.swing.JTable;
061: import javax.swing.JTextField;
062: import javax.swing.table.AbstractTableModel;
063: import javax.swing.table.DefaultTableCellRenderer;
064:
065: import org.netbeans.modules.sql.framework.model.SQLCondition;
066: import org.netbeans.modules.sql.framework.model.SQLDefinition;
067: import org.netbeans.modules.sql.framework.model.SQLGroupBy;
068: import org.netbeans.modules.sql.framework.model.SQLModelObjectFactory;
069: import org.netbeans.modules.sql.framework.model.SQLObject;
070: import org.netbeans.modules.sql.framework.model.SQLPredicate;
071: import org.netbeans.modules.sql.framework.model.SourceColumn;
072: import org.netbeans.modules.sql.framework.model.SourceTable;
073: import org.netbeans.modules.sql.framework.model.TargetTable;
074: import org.netbeans.modules.sql.framework.model.utils.ConditionUtil;
075: import org.netbeans.modules.sql.framework.model.utils.SQLObjectUtil;
076: import org.netbeans.modules.sql.framework.ui.view.conditionbuilder.ConditionBuilderUtil;
077: import org.netbeans.modules.sql.framework.ui.view.conditionbuilder.ConditionBuilderView;
078: import org.openide.DialogDescriptor;
079: import org.openide.DialogDisplayer;
080: import org.openide.NotifyDescriptor;
081: import org.openide.explorer.propertysheet.editors.EnhancedCustomPropertyEditor;
082:
083: import net.java.hulp.i18n.Logger;
084: import org.netbeans.modules.etl.logger.Localizer;
085: import org.netbeans.modules.etl.logger.LogUtil;
086:
087: /**
088: * @author Ritesh Adval
089: * @author Ahimanikya Satapathy
090: * @version $Revision$
091: */
092: public class GroupByView extends JPanel implements
093: EnhancedCustomPropertyEditor {
094:
095: private static transient final Logger mLogger = LogUtil
096: .getLogger(GroupByView.class.getName());
097: private static transient final Localizer mLoc = Localizer.get();
098:
099: class ButtonActionListener implements ActionListener {
100:
101: /**
102: * Invoked when an action occurs.
103: */
104: public void actionPerformed(ActionEvent e) {
105: String actionCmd = e.getActionCommand();
106:
107: if (actionCmd == null) {
108: return;
109: }
110:
111: if (actionCmd.equalsIgnoreCase("UP")) {
112: moveUp();
113: } else if (actionCmd.equalsIgnoreCase("DOWN")) {
114: moveDown();
115: } else if (actionCmd.equalsIgnoreCase("ADD")) {
116: add();
117: } else if (actionCmd.equalsIgnoreCase("REMOVE")) {
118: remove();
119: } else if (actionCmd.equalsIgnoreCase("HAVING")) {
120: showCondBuilder();
121: }
122: }
123:
124: private void add() {
125: int[] sel = table.getSelectedRows();
126: if (sel.length == 0) {
127: return;
128: }
129: ArrayList list = new ArrayList();
130: for (int i = 0; i < sel.length; i++) {
131: list.add(model.getColumn(sel[i]));
132: }
133:
134: // now delete from top panel
135: for (int i = 0; i < list.size(); i++) {
136: model.removeColumn(list.get(i));
137: }
138:
139: // now add to bottom panel
140: groupPanel.addToList(list);
141: table.clearSelection();
142: }
143:
144: private void moveDown() {
145: int[] sel = table.getSelectedRows();
146: for (int i = 0; i < sel.length; i++) {
147: int indx = sel[i];
148: if (indx == model.getRowCount() - 1) {
149: return;
150: }
151: }
152:
153: for (int i = 0; i < sel.length; i++) {
154: int indx = sel[i];
155: Object obj = model.getColumn(indx);
156: model.addColumn(indx + 1, obj);
157: model.removeColumn(indx);
158:
159: }
160: }
161:
162: private void moveUp() {
163: int[] sel = table.getSelectedRows();
164: for (int i = 0; i < sel.length; i++) {
165: int indx = sel[i];
166: if (indx == 0) {
167: return;
168: }
169: }
170:
171: for (int i = 0; i < sel.length; i++) {
172: int indx = sel[i];
173: Object obj = model.getColumn(indx);
174: model.removeColumn(indx);
175: model.addColumn(indx - 1, obj);
176: }
177:
178: }
179:
180: private void remove() {
181: List list = groupPanel.getSelectItems();
182: for (int i = 0; i < list.size(); i++) {
183: model.addColumn(list.get(i));
184: }
185:
186: groupPanel.removeFromList(list);
187: }
188:
189: private void showCondBuilder() {
190: String text = havingText.getText();
191: SQLGroupBy groupBy = targetTable.getSQLGroupBy();
192: if (groupBy == null) {
193: groupBy = SQLModelObjectFactory.getInstance()
194: .createGroupBy();
195: targetTable.setSQLGroupBy(groupBy);
196: }
197: SQLCondition conditionContainer = groupBy
198: .getHavingCondition();
199: String oldText = null;
200: if (conditionContainer != null) {
201: oldText = conditionContainer.getConditionText();
202: }
203:
204: if (conditionContainer != null && text != null
205: && !text.equals(oldText)) {
206: try {
207: conditionContainer = (SQLCondition) conditionContainer
208: .cloneSQLObject();
209: } catch (CloneNotSupportedException ex) {
210: mLogger.errorNoloc(mLoc.t(
211: "PRSR200: error cloning the condition {0}",
212: LOG_CATEGORY), ex);
213: return;
214: }
215:
216: conditionContainer.setConditionText(text);
217: SQLDefinition def = SQLObjectUtil
218: .getAncestralSQLDefinition((SQLObject) conditionContainer
219: .getParent());
220: try {
221: SQLObject obj = ConditionUtil.parseCondition(text,
222: def);
223: conditionContainer.removeAllObjects();
224: ConditionUtil.populateCondition(conditionContainer,
225: obj);
226: // if we do not get a predicate then the condition is invalid
227: // and if text is not empty string
228: if (!(obj instanceof SQLPredicate)
229: && !text.trim().equals("")) {
230: warnForInvalidCondition();
231: }
232: } catch (Exception ex) {
233: mLogger
234: .errorNoloc(
235: mLoc
236: .t(
237: "PRSR201: Error finding root predicate from text condition{0}from joinview table.",
238: text), ex);
239: warnForInvalidCondition();
240: }
241:
242: // if user modified text then change the gui mode
243: conditionContainer
244: .setGuiMode(SQLCondition.GUIMODE_SQLCODE);
245: groupBy.setHavingCondition(conditionContainer);
246: }
247:
248: ConditionBuilderView builderView = ConditionBuilderUtil
249: .getHavingConditionBuilderView(targetTable, editor);
250:
251: DialogDescriptor dd = new DialogDescriptor(builderView,
252: "Having Condition", true,
253: NotifyDescriptor.OK_CANCEL_OPTION, null, null);
254:
255: if (DialogDisplayer.getDefault().notify(dd) == NotifyDescriptor.OK_OPTION) {
256: SQLCondition cond = (SQLCondition) builderView
257: .getPropertyValue();
258: if (cond != null) {
259: groupBy.setHavingCondition(cond);
260: havingText.setText(cond.getConditionText());
261: }
262: }
263: }
264:
265: private void warnForInvalidCondition() {
266: String nbBundle1 = mLoc
267: .t("PRSR001: The condition is not valid.Make sure you correct it.");
268: DialogDisplayer.getDefault().notify(
269: new NotifyDescriptor.Message(Localizer
270: .parse(nbBundle1),
271: NotifyDescriptor.WARNING_MESSAGE));
272: }
273: }
274:
275: class GroupByTableModel extends AbstractTableModel {
276:
277: private String[] columnNames = { "Column Name" };
278: private List rowList = new ArrayList();
279:
280: public GroupByTableModel() {
281: }
282:
283: public GroupByTableModel(List list) {
284: Iterator it = list.iterator();
285: while (it.hasNext()) {
286: SQLObject expr = (SQLObject) it.next();
287: rowList.add(expr);
288: }
289: }
290:
291: public void addColumn(int idx, Object expr) {
292: rowList.add(idx, expr);
293: this .fireTableRowsInserted(getRowCount(), getRowCount());
294: }
295:
296: public void addColumn(Object expr) {
297: rowList.add(expr);
298: this .fireTableRowsInserted(getRowCount(), getRowCount());
299: }
300:
301: public Object getColumn(int idx) {
302: return rowList.get(idx);
303: }
304:
305: /*
306: * JTable uses this method to determine the default renderer/ editor for each
307: * cell. If we didn't implement this method, then the last column would contain
308: * text ("true"/"false"), rather than a check box.
309: */
310: public Class getColumnClass(int c) {
311: if (c == 0) {
312: return SourceColumn.class;
313: }
314:
315: return String.class;
316: }
317:
318: public int getColumnCount() {
319: return columnNames.length;
320: }
321:
322: public String getColumnName(int col) {
323: return columnNames[col];
324: }
325:
326: public int getRowCount() {
327: return rowList.size();
328: }
329:
330: public Object getValueAt(int row, int col) {
331: Object obj = rowList.get(row);
332: switch (col) {
333: case 0:
334: return obj;
335: }
336:
337: return String.valueOf(col + "?");
338: }
339:
340: /*
341: * Don't need to implement this method unless the table is editable.
342: */
343: public boolean isCellEditable(int row, int col) {
344: return false;
345: }
346:
347: public void removeColumn(int idx) {
348: rowList.remove(idx);
349: this .fireTableRowsInserted(idx, idx);
350: }
351:
352: public void removeColumn(Object expr) {
353: int idx = rowList.indexOf(expr);
354: if (idx != -1) {
355: rowList.remove(idx);
356: this .fireTableRowsInserted(idx, idx);
357: }
358: }
359:
360: /*
361: * Don't need to implement this method unless your table's data can change.
362: */
363: public void setValueAt(Object value, int row, int col) {
364: }
365: }
366:
367: class GroupTableCellRenderer extends DefaultTableCellRenderer {
368:
369: /**
370: * Returns the default table cell renderer.
371: *
372: * @param aTable the <code>JTable</code>
373: * @param value the value to assign to the cell at <code>[row, column]</code>
374: * @param isSelected true if cell is selected
375: * @param isFocus true if cell has focus
376: * @param row the row of the cell to render
377: * @param column the column of the cell to render
378: * @return the default table cell renderer
379: */
380: public Component getTableCellRendererComponent(JTable aTable,
381: Object value, boolean isSelected, boolean hasFocus,
382: int row, int column) {
383: return super .getTableCellRendererComponent(aTable, value
384: .toString(), isSelected, hasFocus, row, column);
385: }
386: }
387:
388: private static final String LOG_CATEGORY = GroupByView.class
389: .getName();
390: private IGraphViewContainer editor;
391: private GroupPanel groupPanel;
392: private JTextField havingText;
393: private GroupByTableModel model;
394: private JTable table;
395: private TargetTable targetTable;
396:
397: /**
398: * New instance
399: *
400: * @param groupByColumn - column
401: */
402: public GroupByView(IGraphViewContainer editor, TargetTable tTable,
403: Collection groupByColumns) {
404: this .targetTable = tTable;
405: this .editor = editor;
406: List allColumns = new ArrayList();
407:
408: try {
409: List srcTables = targetTable.getSourceTableList();
410: for (Iterator iter = srcTables.iterator(); iter.hasNext();) {
411: allColumns.addAll(((SourceTable) iter.next())
412: .getColumnList());
413: }
414: allColumns.addAll(this .targetTable.getColumnList());
415: } catch (Exception e) {
416: // ignore
417: }
418:
419: initializeModel(allColumns, groupByColumns);
420: initGui();
421: ArrayList validColumns = new ArrayList();
422: Iterator it = groupByColumns.iterator();
423: while (it.hasNext()) {
424: Object column = it.next();
425: if (allColumns.contains(column)) {
426: validColumns.add(column);
427: }
428: }
429: groupPanel.setData(validColumns);
430: }
431:
432: /**
433: * Get ordered list
434: *
435: * @return List
436: */
437: public List getOrderedList() {
438: return groupPanel.getOrderedList();
439: }
440:
441: /**
442: * Get the customized property value.
443: *
444: * @return the property value
445: * @exception IllegalStateException when the custom property editor does not contain a
446: * valid property value (and thus it should not be set)
447: */
448: public Object getPropertyValue() throws IllegalStateException {
449: SQLGroupBy groupBy = SQLModelObjectFactory.getInstance()
450: .createGroupBy(this .getOrderedList(), targetTable);
451: return groupBy;
452: }
453:
454: private void initGui() {
455: ButtonActionListener aListener = new ButtonActionListener();
456: this .setLayout(new GridBagLayout());
457:
458: GridBagConstraints c = new GridBagConstraints();
459: c.gridwidth = GridBagConstraints.REMAINDER;
460: c.weightx = 1.0;
461: c.weighty = 1.0;
462: c.fill = GridBagConstraints.BOTH;
463:
464: JPanel mainPanel = new JPanel();
465: mainPanel.setLayout(new BorderLayout());
466: String nbBundle1 = mLoc
467: .t("PRSR001: Available Group By Columns");
468: mainPanel
469: .setBorder(BorderFactory
470: .createCompoundBorder(
471: BorderFactory
472: .createTitledBorder("Available Group By Columns"),
473: BorderFactory.createEmptyBorder(4, 4,
474: 4, 4)));
475: this .add(mainPanel, c);
476:
477: // List of source/target columns
478: table = new JTable();
479: table.setDefaultRenderer(SourceColumn.class,
480: new GroupTableCellRenderer());
481: table.setModel(model);
482: JScrollPane sPane = new JScrollPane(table);
483: mainPanel.add(sPane, BorderLayout.CENTER);
484:
485: // Add button panel
486: JPanel addButtonPanel = new JPanel();
487: FlowLayout fl = new FlowLayout(FlowLayout.LEFT);
488: addButtonPanel.setLayout(fl);
489: mainPanel.add(addButtonPanel, BorderLayout.SOUTH);
490:
491: // add button
492: String nbBundle30 = mLoc.t("PRSR001: Add Column/Expression");
493: JButton addButton = new JButton(Localizer.parse(nbBundle30));
494: addButton.getAccessibleContext().setAccessibleName(
495: Localizer.parse(nbBundle30));
496: addButton.setMnemonic(Localizer.parse(nbBundle30).charAt(0));
497: addButton
498: .setToolTipText("<html> <table border=0 cellspacing=0 cellpadding=0 ><tr> <td>When target column is added, <br>the mapped expression/column <br>will be used in group by clause</td></tr></table>");
499: addButton.setActionCommand("ADD");
500: addButton.addActionListener(aListener);
501: addButtonPanel.add(addButton);
502:
503: // order or remove selected columns panel
504: JPanel orderOrRemoveSelectedColumn = new JPanel();
505: orderOrRemoveSelectedColumn
506: .setBorder(BorderFactory
507: .createCompoundBorder(
508: BorderFactory
509: .createTitledBorder("Selected Group By Columns"),
510: BorderFactory.createEmptyBorder(4, 4,
511: 4, 4)));
512: orderOrRemoveSelectedColumn.setLayout(new BorderLayout());
513: this .add(orderOrRemoveSelectedColumn, c);
514:
515: groupPanel = new GroupPanel("Group Column");
516: orderOrRemoveSelectedColumn
517: .add(groupPanel, BorderLayout.CENTER);
518:
519: // Add button panel
520: JPanel removeButtonPanel = new JPanel();
521: removeButtonPanel.setLayout(fl);
522: orderOrRemoveSelectedColumn.add(removeButtonPanel,
523: BorderLayout.SOUTH);
524:
525: // remove selected column button
526: String nbBundle31 = mLoc.t("PRSR001: Remove");
527: JButton removeButton = new JButton(Localizer.parse(nbBundle31));
528: removeButton.setMnemonic(Localizer.parse(nbBundle31).charAt(0));
529: removeButton.getAccessibleContext().setAccessibleName(
530: Localizer.parse(nbBundle31));
531: removeButton.setActionCommand("REMOVE");
532: removeButton.addActionListener(aListener);
533: removeButtonPanel.add(removeButton);
534:
535: // having panel
536: JPanel havingPanel = new JPanel();
537: GridBagConstraints c2 = new GridBagConstraints();
538: c2.gridwidth = GridBagConstraints.REMAINDER;
539: c2.weightx = 1.0;
540: c2.weighty = 1.0;
541: c2.fill = GridBagConstraints.HORIZONTAL;
542: this .add(havingPanel, c2);
543:
544: havingPanel.setLayout(fl);
545: havingPanel.setBorder(BorderFactory.createCompoundBorder(
546: BorderFactory
547: .createTitledBorder("Define Having Clause"),
548: BorderFactory.createEmptyBorder(4, 4, 4, 4)));
549:
550: String havingCondition = "";
551: if (targetTable.getSQLGroupBy() != null
552: && targetTable.getSQLGroupBy().getHavingCondition() != null) {
553: havingCondition = targetTable.getSQLGroupBy()
554: .getHavingCondition().getConditionText();
555: }
556: havingText = new JTextField(havingCondition);
557: havingText.setPreferredSize(new Dimension(230, 25));
558: havingPanel.add(havingText);
559:
560: // having button
561: String nbBundle32 = mLoc.t("PRSR001: Having...");
562: JButton havingButton = new JButton(Localizer.parse(nbBundle32));
563: havingButton.setMnemonic(Localizer.parse(nbBundle32).charAt(0));
564: havingButton.getAccessibleContext().setAccessibleName(
565: Localizer.parse(nbBundle32));
566: havingButton.setActionCommand("Having");
567: havingButton.addActionListener(aListener);
568: havingPanel.add(havingButton);
569:
570: }
571:
572: private void initializeModel(List allColumns,
573: Collection groupByColumns) {
574: model = new GroupByTableModel();
575: Iterator it = allColumns.iterator();
576: while (it.hasNext()) {
577: Object sColumn = it.next();
578: if (!groupByColumns.contains(sColumn)) {
579: model.addColumn(sColumn);
580: }
581: }
582: }
583: }
|