/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ro.nextreports.designer.querybuilder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import org.jdesktop.swingx.decorator.HighlighterFactory;
import ro.nextreports.designer.Globals;
import ro.nextreports.designer.querybuilder.table.DataObjectTransferHandler;
import ro.nextreports.designer.querybuilder.table.ListDataFlavor;
import ro.nextreports.designer.querybuilder.table.TableDNDRecognizer;
import ro.nextreports.designer.ui.ComboBoxEditor;
import ro.nextreports.designer.ui.eventbus.CircularEventFilter;
import ro.nextreports.designer.ui.eventbus.Subscriber;
import ro.nextreports.designer.ui.list.CheckListEvent;
import ro.nextreports.designer.ui.list.CheckListItem;
import ro.nextreports.designer.ui.table.TableRowHeader;
import ro.nextreports.designer.util.ColorUtil;
import ro.nextreports.designer.util.I18NSupport;
import ro.nextreports.designer.util.Show;
import ro.nextreports.designer.util.TableUtil;
import ro.nextreports.engine.querybuilder.MyRow;
import ro.nextreports.engine.querybuilder.sql.Column;
import ro.nextreports.engine.querybuilder.sql.ExpressionColumn;
import ro.nextreports.engine.querybuilder.sql.GroupByFunctionColumn;
import ro.nextreports.engine.querybuilder.sql.JoinCriteria;
import ro.nextreports.engine.querybuilder.sql.MatchCriteria;
import ro.nextreports.engine.querybuilder.sql.Order;
import ro.nextreports.engine.querybuilder.sql.SelectQuery;
import ro.nextreports.engine.querybuilder.sql.Table;
/**
* @author Decebal Suiu
*/
public class DesignerTablePanel extends JPanel {
public static final String GROUP_BY = "Group By";
public static final String SUM = "Sum";
public static final String AVG = "Avg";
public static final String MIN = "Min";
public static final String MAX = "Max";
public static final String COUNT = "Count";
private static String ASC = I18NSupport.getString("order.ascending");
private static String DESC = I18NSupport.getString("order.descending");
// store without internationalization
private static String ASC_STORE = "Asc";
private static String DESC_STORE = "Desc";
private MyTableModel model;
private JXTable table;
private TableRowHeader tableRowHeader;
private JComboBox sortOrderCombo;
private SelectQuery selectQuery;
private JPopupMenu popupMenu;
private DataFlavor listFlavor;
private DataObjectTransferHandler dndHandler;
private TableDNDRecognizer dndRecognizer;
public DesignerTablePanel(SelectQuery selectQuery) {
super();
this.selectQuery = selectQuery;
Globals.getEventBus().subscribe(CheckListEvent.class, null, new ColumnCheckSubscriber());
Globals.getEventBus().subscribe(GroupByEvent.class, new CircularEventFilter(DesignerTablePanel.this),
new GroupByCheckSubscriber());
listFlavor = new ListDataFlavor();
dndHandler = new DataObjectTransferHandler(listFlavor, selectQuery);
dndRecognizer = new TableDNDRecognizer();
initUI();
}
private void initUI() {
// create table
setLayout(new BorderLayout());
createTable();
add(new JScrollPane(table));
table.setPreferredScrollableViewportSize(new Dimension(200, 70));
// add popup listener
MouseListener popupListener = new PopupListener();
table.addMouseListener(popupListener);
table.setTransferHandler(dndHandler);
table.setDropTarget(new DropTarget(table, DataObjectTransferHandler.getDropHandler()));
table.addMouseListener(dndRecognizer);
table.addMouseMotionListener(dndRecognizer);
table.setBackground(ColorUtil.PANEL_BACKROUND_COLOR);
table.setGridColor(Color.LIGHT_GRAY);
table.addMouseListener(new DoubleClickListener());
}
private void createTable() {
// create the table
model = new MyTableModel();
table = new JXTable(model) {
private Map<Integer, ComboBoxEditor> editors = new HashMap<Integer, ComboBoxEditor>();
public boolean getScrollableTracksViewportHeight() {
return getPreferredSize().height < getParent().getHeight();
}
public void changeSelection(int rowIndex, int columnIndex,
boolean toggle, boolean extend) {
if (!dndRecognizer.isDragged()) {
super.changeSelection(rowIndex, columnIndex, toggle, extend);
}
}
public TableCellEditor getCellEditor(int row, int column) {
if (column != 6) {
return super.getCellEditor(row, column);
}
ComboBoxEditor editor = editors.get(row);
if (editor == null) {
editor = new ComboBoxEditor(new String[]{"", GROUP_BY, SUM, AVG, MIN, MAX, COUNT});
editors.put(row, editor);
}
return editor;
}
};
tableRowHeader = TableUtil.setRowHeader(table);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
TableColumn col = table.getColumnModel().getColumn(3);
// col.setCellRenderer(TableCellRenderers.getNewDefaultRenderer(Boolean.class));
col.setCellRenderer(table.getDefaultRenderer(Boolean.class));
col.setCellEditor(table.getDefaultEditor(Boolean.class));
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
// no border
JTextField tf = new JTextField();
tf.setBorder(BorderFactory.createEmptyBorder());
table.setDefaultEditor(Object.class, new DefaultCellEditor(tf));
col = table.getColumnModel().getColumn(4);
// col.setCellRenderer(TableCellRenderers.getNewDefaultRenderer(Boolean.class));
JComboBox sortCombo = new JComboBox(new String[]{"", ASC, DESC});
sortCombo.setBorder(BorderFactory.createEmptyBorder());
col.setCellEditor(new ComboBoxEditor(sortCombo));
col = table.getColumnModel().getColumn(5);
sortOrderCombo = new JComboBox();
sortOrderCombo.setBorder(BorderFactory.createEmptyBorder());
col.setCellEditor(new ComboBoxEditor(sortOrderCombo));
col = table.getColumnModel().getColumn(6);
table.setSortable(false);
table.setColumnControlVisible(true);
table.getTableHeader().setReorderingAllowed(false);
table.setHorizontalScrollEnabled(true);
// highlight table
table.setHighlighters(HighlighterFactory.createAlternateStriping(Color.WHITE, ColorUtil.PANEL_BACKROUND_COLOR));
table.getTableHeader().setReorderingAllowed(false);
table.setRolloverEnabled(true);
table.addHighlighter(new ColorHighlighter(HighlightPredicate.ROLLOVER_ROW, null, Color.RED));
}
public class MyTableModel extends DefaultTableModel {
private final String[] columnNames = {
I18NSupport.getString("designer.table"),
I18NSupport.getString("designer.column"),
I18NSupport.getString("designer.alias"),
I18NSupport.getString("designer.output"),
I18NSupport.getString("designer.sort.type"),
I18NSupport.getString("designer.sort.order"),
I18NSupport.getString("designer.group.by"),
I18NSupport.getString("designer.criteria"),
I18NSupport.getString("designer.criteria.or")
};
private List elements = new ArrayList();
public Class getColumnClass(int columnIndex) {
if (columnIndex == 3) {
return Boolean.class;
}
return Object.class;
}
public String getColumnName(int columnIndex) {
return columnNames[columnIndex];
}
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
// this method is called in the constructor so we must test for null
if (elements == null) {
return 0;
}
return elements.size();
}
@SuppressWarnings("unchecked")
public void addObject(Object object) {
elements.add(object);
fireTableDataChanged();
}
@SuppressWarnings("unchecked")
public void addObject(Object object, int index) {
elements.add(index, object);
fireTableDataChanged();
}
@SuppressWarnings("unchecked")
public void addObjects(List objects) {
elements.addAll(objects);
fireTableDataChanged();
}
public void deleteObject(int rowIndex) {
elements.remove(rowIndex);
fireTableDataChanged();
}
public void deleteObjects(List objects) {
elements.removeAll(objects);
fireTableDataChanged();
}
public void clear() {
elements.clear();
fireTableDataChanged();
}
public Object getObjectForRow(int rowIndex) {
return elements.get(rowIndex);
}
public int getRowForObject(Object object) {
for (int i = 0; i < elements.size(); i++) {
if (object.equals(elements.get(i))) {
return i;
}
}
return -1;
}
public int getRowForColumn(Object object) {
for (int i = 0; i < elements.size(); i++) {
Column column = ((MyRow) elements.get(i)).column;
if (object.equals(column)) {
return i;
}
}
return -1;
}
// modified from DefaultTableModel to use elements List instead of dataVector
///////////////////////////////////////////////////////////////////////////////////////////
public void moveRow(int start, int end, int to) {
int shift = to - start;
int first, last;
if (shift < 0) {
first = to;
last = end;
} else {
first = start;
last = to + end - start;
}
rotate(elements, first, last + 1, shift);
fireTableRowsUpdated(first, last);
}
@SuppressWarnings("unchecked")
private void rotate(List list, int a, int b, int shift) {
int size = b - a;
int r = size - shift;
int g = gcd(size, r);
for (int i = 0; i < g; i++) {
int to = i;
Object tmp = list.get(a + to);
for (int from = (to + r) % size; from != i; from = (to + r) % size) {
list.set(a + to, list.get(a + from));
to = from;
}
list.set(a + to, tmp);
}
}
private int gcd(int i, int j) {
return (j == 0) ? i : gcd(j, i % j);
}
public void removeRow(int row) {
elements.remove(row);
fireTableRowsDeleted(row, row);
}
///////////////////////////////////////////////////////////////////////////////////////////
public Object getValueAt(int rowIndex, int columnIndex) {
MyRow row = (MyRow) elements.get(rowIndex);
switch (columnIndex) {
case 0:
Table table = row.column.getTable();
if (table == null) {
return "<" + I18NSupport.getString("designer.expression") + ">";
} else {
return table.getName() + " (" + table.getAlias() + ")";
}
case 1:
return row.column.getName();
case 2:
return row.column.getAlias();
case 3:
return Boolean.valueOf(row.output);
case 4:
return getSortType(row.sortType);
case 5:
return row.sortOrder == 0 ? "" : String.valueOf(row.sortOrder);
case 6:
return row.groupBy;
case 7:
return row.criteria;
case 8:
return row.orCriterias.size() == 0 ? "" : row.orCriterias.get(0);
default:
return null;
}
}
public void setValueAt(Object value, int rowIndex, int columnIndex) {
MyRow row = (MyRow) elements.get(rowIndex);
JComboBox groupByCombo = (JComboBox) ((DefaultCellEditor) table.getCellEditor(rowIndex, 6)).getComponent();
switch (columnIndex) {
case 2:
if (value.equals(row.column.getAlias())) {
return;
}
String columnAlias = (String) value;
if ("".equals(columnAlias)) {
columnAlias = null;
}
row.column.setAlias(columnAlias);
table.packAll();
break;
case 3:
row.output = ((Boolean) value).booleanValue();
if (row.output == false) {
if (!"".equals(groupByCombo.getItemAt(0))) {
groupByCombo.insertItemAt("", 0);
}
} else {
if (hasGroupBy() && "".equals(groupByCombo.getSelectedItem())) {
row.groupBy = GROUP_BY;
if (!selectQuery.containsGroupByColumn(row.column)) {
selectQuery.addGroupByColumn(row.column, rowIndex);
}
model.fireTableCellUpdated(rowIndex, 6);
}
if (hasAggregateFunction()) {
groupByCombo.removeItem("");
}
}
row.column.setOutput(row.output);
break;
case 4:
Order order = selectQuery.getOrder(row.column);
if (ASC.equals(value)) {
if (order == null) {
selectQuery.addOrder(row.column, true);
sortOrderCombo.addItem(String.valueOf(selectQuery.getOrdersCount()));
} else {
order.setAscending(true);
}
} else if (DESC.equals(value)) {
if (order == null) {
selectQuery.addOrder(row.column, false);
sortOrderCombo.addItem(String.valueOf(selectQuery.getOrdersCount()));
} else {
order.setAscending(false);
}
} else {
if (order != null) {
sortOrderCombo.removeItem(String.valueOf(selectQuery.getOrdersCount()));
selectQuery.removeOrder(order);
row.sortOrder = 0;
fireTableCellUpdated(rowIndex, 5);
}
}
row.sortType = convertSortType((String) value);
table.packAll();
break;
case 5:
String v = (String) value;
if (v != null) {
row.sortOrder = Integer.parseInt(v);
Order orderS = selectQuery.getOrder(row.column);
if (orderS != null) {
orderS.setIndex(row.sortOrder);
}
}
break;
case 6:
row.groupBy = (String) value;
if (!"".equals(row.groupBy)) {
Globals.getEventBus().publish(new GroupByEvent(DesignerTablePanel.this, true));
updateGroupByColumn(groupByCombo, row.output);
if (!GROUP_BY.equals(row.groupBy)) {
columnAlias = row.groupBy.toUpperCase().concat(" of ").concat(row.column.getName());
if (row.column.getAlias() == null) {
row.column.setAlias(columnAlias);
}
Column gbColumn = new GroupByFunctionColumn(row.column, row.groupBy);
gbColumn.setAlias(row.column.getAlias());
gbColumn.setOutput(row.column.isOutput());
selectQuery.changeColumn(row.column, gbColumn);
row.column = gbColumn;
//System.out.println("*column = " + row.column.getName() + " " + row.column.getTable());
model.fireTableCellUpdated(rowIndex, 6);
selectQuery.removeGroupByColumn(row.column);
} else if (GROUP_BY.equals(row.groupBy)) {
// select a groupBy after a function
Column gbColumn;
if ((row.column instanceof ExpressionColumn) ||
((row.column instanceof GroupByFunctionColumn) && ((GroupByFunctionColumn) row.column).isExpression())) {
gbColumn = new ExpressionColumn(row.column.getName(), row.column.getAlias());
} else {
gbColumn = new Column(row.column.getTable(), row.column.getName(), row.column.getAlias(), null);
}
gbColumn.setAlias(row.column.getAlias());
gbColumn.setOutput(row.column.isOutput());
selectQuery.changeColumn(row.column, gbColumn);
row.column = gbColumn;
if (!selectQuery.containsGroupByColumn(row.column)) {
selectQuery.addGroupByColumn(row.column, rowIndex);
}
model.fireTableCellUpdated(rowIndex, 6);
}
} else if (GROUP_BY.equals(row.groupBy)) {
selectQuery.addGroupByColumn(row.column);
} else {
selectQuery.removeGroupByColumn(row.column);
}
table.packAll();
break;
case 7:
row.criteria = (String) value;
if (!"".equals(row.criteria)) {
String[] opValue = MatchCriteria.getOperatorValue(row.criteria);
MatchCriteria crit;
// criteria string contains the oparator and the value
if (opValue[0] != null) {
if ((opValue[2] == null) || opValue[2].equals("")) {
crit = new MatchCriteria(row.column, opValue[0], opValue[1]);
} else {
crit = new MatchCriteria(row.column, opValue[0], opValue[1], opValue[2]);
}
} else {
crit = new MatchCriteria(row.column, row.criteria);
}
selectQuery.addCriteria(crit);
}
table.packAll();
break;
case 8:
String orCrit = (String) value;
row.orCriterias.add(0, orCrit);
if (!"".equals(orCrit)) {
String[] opValue = MatchCriteria.getOperatorValue(orCrit);
MatchCriteria crit;
// criteria string contains the oparator and the value
if (opValue[0] != null) {
if ((opValue[2] == null) || opValue[2].equals("")) {
crit = new MatchCriteria(row.column, opValue[0], opValue[1]);
} else {
crit = new MatchCriteria(row.column, opValue[0], opValue[1], opValue[2]);
}
} else {
crit = new MatchCriteria(row.column, row.criteria);
}
selectQuery.addOrCriteria(crit, 0);
}
table.packAll();
break;
}
}
private void updateGroupByColumn(JComboBox groupByCombo, boolean output) {
if (output) {
if (hasAggregateFunction()) {
groupByCombo.removeItem("");
}
}
int rowCount = model.getRowCount();
for (int i = 0; i < rowCount; i++) {
MyRow row = (MyRow) model.getObjectForRow(i);
if (row.output && "".equals(row.groupBy)) {
row.groupBy = GROUP_BY;
model.fireTableCellUpdated(i, 6);
selectQuery.addGroupByColumn(row.column);
}
if (output && row.output) {
JComboBox groupByCombo2 = (JComboBox) ((DefaultCellEditor) table.getCellEditor(i, 6)).getComponent();
if (hasAggregateFunction()) {
groupByCombo2.removeItem("");
} else {
if (!hasEmpty(groupByCombo2.getModel())) {
groupByCombo2.insertItemAt("", 0);
}
}
}
}
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (columnIndex == 2) {
return true;
}
if (columnIndex == 3) {
return true;
}
if (columnIndex == 4) {
return true;
}
if ((columnIndex == 5) && (!"".equals(getValueAt(rowIndex, 4)))) {
return true;
}
if (columnIndex == 6) {
return true;
}
if (columnIndex == 7) {
return false;
}
if (columnIndex >= 8) {
return false;
}
return false;
}
}
class ColumnCheckSubscriber implements Subscriber {
public void inform(EventObject ev) {
CheckListEvent clEvent = (CheckListEvent) ev;
CheckListItem clItem = clEvent.getCheckListItem();
Column column = (Column) clItem.getObject();
boolean selected = clItem.isSelected();
if (selected) {
MyRow row = new MyRow();
row.column = column;
row.output = true;
MatchCriteria mc = selectQuery.getMatchCriteria(column);
if (mc != null) {
row.criteria = mc.getOperator() + " " + mc.getFullValue();
}
MatchCriteria orMc = selectQuery.getOrMatchCriteria(column, 0);
if (orMc != null) {
row.orCriterias.set(0, orMc.getOperator() + " " + orMc.getFullValue());
}
// if there are other columns selected and have a groupBy
// (need to test only first column) we set also a "Group By"
// on the new selected column
boolean addGroupBy = false;
if (model.getRowCount() > 0) {
MyRow r = (MyRow) model.getObjectForRow(0);
if (!"".equals(r.groupBy)) {
row.groupBy = GROUP_BY;
addGroupBy = true;
}
}
model.addObject(row);
tableRowHeader = TableUtil.setRowHeader(table);
selectQuery.addColumn(column);
if (addGroupBy) {
selectQuery.addGroupByColumn(column);
}
} else {
MyRow row = new MyRow();
row.column = column;
int rowIndex = model.getRowForObject(row);
if (rowIndex != -1) {
model.deleteObject(rowIndex);
tableRowHeader = TableUtil.setRowHeader(table);
}
selectQuery.removeColumnAndDependencies(column);
}
table.packAll();
}
}
class GroupByCheckSubscriber implements Subscriber {
public void inform(EventObject ev) {
GroupByEvent gbEvent = (GroupByEvent) ev;
if (gbEvent.isGroupByChecked()) {
int rowCount = model.getRowCount();
for (int i = 0; i < rowCount; i++) {
JComboBox groupByCombo = (JComboBox) ((DefaultCellEditor) table.getCellEditor(i, 6)).getComponent();
MyRow row = (MyRow) model.getObjectForRow(i);
if (row.output) {
if (hasAggregateFunction()) {
groupByCombo.removeItem("");
}
}
row.groupBy = GROUP_BY;
model.fireTableCellUpdated(i, 6);
selectQuery.addGroupByColumn(row.column);
}
} else {
int rowCount = model.getRowCount();
for (int i = 0; i < rowCount; i++) {
JComboBox groupByCombo = (JComboBox) ((DefaultCellEditor) table.getCellEditor(i, 6)).getComponent();
if (!"".equals(groupByCombo.getItemAt(0))) {
groupByCombo.insertItemAt("", 0);
}
MyRow row = (MyRow) model.getObjectForRow(i);
row.groupBy = "";
if (row.column instanceof GroupByFunctionColumn) {
if (((GroupByFunctionColumn) row.column).isExpression()) {
Column expColumn = new ExpressionColumn(row.column.getName(), row.column.getAlias());
selectQuery.changeColumn(row.column, expColumn);
row.column = expColumn;
// for GroupBy columns with function, reset function
} else {
Column column = new Column(row.column.getTable(), row.column.getName(), row.column.getAlias(), null);
selectQuery.changeColumn(row.column, column);
row.column = column;
}
}
model.fireTableCellUpdated(i, 6);
}
selectQuery.removeAllGroupByColumns();
}
}
}
class PopupListener extends MouseAdapter {
public void mousePressed(MouseEvent ev) {
showPopup(ev);
}
public void mouseReleased(MouseEvent ev) {
showPopup(ev);
}
private void showPopup(MouseEvent ev) {
if (ev.isPopupTrigger()) {
// get the point from the mouse event
Point mousePoint = ev.getPoint();
// convert the point into a row
final int row = table.rowAtPoint(mousePoint);
popupMenu = new JPopupMenu();
JMenuItem menuItem = new JMenuItem(I18NSupport.getString("designer.add.expression"));
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
MyRow expression = new MyRow();
expression.column = new ExpressionColumn("");
expression.output = true;
ExpressionEditAction editAction = new ExpressionEditAction(expression.column);
editAction.actionPerformed(e);
if (!editAction.isOkPressed()) {
return;
}
model.addObject(expression);
selectQuery.addColumn(expression.column);
// select the row
int lastRow = table.getRowCount();
table.setRowSelectionInterval(lastRow - 1, lastRow - 1);
if (tableRowHeader != null) {
tableRowHeader.updateUI();
}
table.packAll();
}
});
popupMenu.add(menuItem);
if (row > -1) {
// select the row
table.setRowSelectionInterval(row, row);
final MyRow myRow = (MyRow) model.getObjectForRow(row);
boolean add = true;
String title = I18NSupport.getString("designer.add.criteria");
if (myRow.criteria != null) {
add = false;
title = I18NSupport.getString("designer.edit.criteria");
}
final boolean fAdd = add;
JMenuItem menuItemCriteria = new JMenuItem(title);
menuItemCriteria.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
CriteriaPanel cp = new CriteriaPanel(myRow, selectQuery, fAdd);
CriteriaDialog dlg = new CriteriaDialog(cp);
dlg.pack();
dlg.setResizable(false);
Show.centrateComponent(Globals.getMainFrame(), dlg);
dlg.setVisible(true);
MatchCriteria criteria = dlg.getCriteria();
if (criteria != null) {
myRow.criteria = criteria.getOperator() + " " + criteria.getFullValue();
model.fireTableCellUpdated(row, 7);
table.packAll();
}
}
});
popupMenu.add(menuItemCriteria);
JMenuItem menuItemRemoveCriteria = new JMenuItem(I18NSupport.getString("designer.delete.criteria"));
if (!add) {
menuItemRemoveCriteria.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
selectQuery.removeMatchCriteria(myRow.column);
myRow.criteria = null;
model.fireTableCellUpdated(row, 7);
table.packAll();
}
});
popupMenu.add(menuItemRemoveCriteria);
}
// Or criteria
boolean addOr = true;
String titleOr = I18NSupport.getString("designer.add.criteria.or");
if ((myRow.orCriterias.size() > 0) && (myRow.orCriterias.get(0) != null)) {
addOr = false;
titleOr = I18NSupport.getString("designer.edit.criteria.or");
}
final boolean fAddOr = addOr;
JMenuItem menuItemOrCriteria = new JMenuItem(titleOr);
menuItemOrCriteria.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
CriteriaPanel cp = new CriteriaPanel(myRow, selectQuery, fAddOr, true);
CriteriaDialog dlg = new CriteriaDialog(cp, true);
dlg.pack();
dlg.setResizable(false);
Show.centrateComponent(Globals.getMainFrame(), dlg);
dlg.setVisible(true);
MatchCriteria criteria = dlg.getCriteria();
if (criteria != null) {
if (fAddOr) {
myRow.orCriterias.add(0, criteria.getOperator() + " " + criteria.getFullValue());
} else {
myRow.orCriterias.set(0, criteria.getOperator() + " " + criteria.getFullValue());
}
model.fireTableCellUpdated(row, 8);
table.packAll();
}
}
});
popupMenu.add(menuItemOrCriteria);
JMenuItem menuItemRemoveOrCriteria = new JMenuItem(I18NSupport.getString("designer.delete.criteria.or"));
if (!addOr) {
menuItemRemoveOrCriteria.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
selectQuery.removeOrMatchCriteria(myRow.column, 0);
myRow.orCriterias.remove(0);
model.fireTableCellUpdated(row, 8);
table.packAll();
}
});
popupMenu.add(menuItemRemoveOrCriteria);
}
////
if (myRow == null) {
popupMenu.show(ev.getComponent(), mousePoint.x, mousePoint.y);
return;
}
if (!(myRow.column instanceof ExpressionColumn) &&
!((myRow.column instanceof GroupByFunctionColumn) && ((GroupByFunctionColumn) myRow.column).isExpression())) {
popupMenu.show(ev.getComponent(), mousePoint.x, mousePoint.y);
return;
} else {
popupMenu = new JPopupMenu();
popupMenu.add(menuItemCriteria);
if (!add) {
popupMenu.add(menuItemRemoveCriteria);
}
popupMenu.add(menuItemOrCriteria);
if (!addOr) {
popupMenu.add(menuItemRemoveOrCriteria);
}
final Column expressionColumn = myRow.column;
menuItem = new JMenuItem(I18NSupport.getString("designer.edit.expression"));
menuItem.addActionListener(new ExpressionEditAction(expressionColumn));
popupMenu.add(menuItem);
menuItem = new JMenuItem(I18NSupport.getString("designer.delete.expression"));
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.deleteObject(row);
selectQuery.removeColumnAndDependencies(expressionColumn);
tableRowHeader.updateUI();
}
});
popupMenu.add(menuItem);
popupMenu.show(ev.getComponent(), mousePoint.x, mousePoint.y);
return;
}
} else {
popupMenu.show(ev.getComponent(), mousePoint.x, mousePoint.y);
}
}
}
}
class ExpressionEditAction implements ActionListener {
private Column expressionColumn;
private boolean okPressed = false;
public ExpressionEditAction(Column expressionColumn) {
if (!(expressionColumn instanceof ExpressionColumn) &&
!((expressionColumn instanceof GroupByFunctionColumn) && ((GroupByFunctionColumn) expressionColumn).isExpression())) {
throw new IllegalArgumentException(expressionColumn + " is not an expression");
}
this.expressionColumn = expressionColumn;
}
public void actionPerformed(ActionEvent e) {
String expression = expressionColumn.getName();
// String result = (String) JOptionPane.showInputDialog(Globals.getMainFrame(), null, "Expression",
// JOptionPane.QUESTION_MESSAGE, null, null, expression);
final JTextArea textArea = new JTextArea(expression, 10, 30);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setEditable(true);
Object msg[] = {"", new JScrollPane(textArea)};
//
int option = JOptionPane.showOptionDialog(Globals.getMainFrame(),
msg, I18NSupport.getString("designer.expression"),
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
if (option == JOptionPane.YES_OPTION) {
String result = textArea.getText();
if (expressionColumn instanceof ExpressionColumn) {
((ExpressionColumn) expressionColumn).setExpression(result);
} else if (expressionColumn instanceof GroupByFunctionColumn) {
((GroupByFunctionColumn) expressionColumn).setExpression(result);
}
okPressed = true;
}
table.packAll();
}
public boolean isOkPressed() {
return okPressed;
}
}
class DoubleClickListener extends MouseAdapter {
public void mouseClicked(MouseEvent ev) {
if (ev.getClickCount() == 2) {
Point mousePoint = ev.getPoint();
// convert the point into a row
final int row = table.rowAtPoint(mousePoint);
if (row == -1) return;
final int column = table.columnAtPoint(mousePoint);
final MyRow myRow = (MyRow) model.getObjectForRow(row);
if (column == 7) {
// if ((column == 7) && !(myRow.column instanceof ExpressionColumn) &&
// !((myRow.column instanceof GroupByFunctionColumn) && ((GroupByFunctionColumn) myRow.column).isExpression())) {
// select the row
table.setRowSelectionInterval(row, row);
boolean add = true;
if (myRow.criteria != null) {
add = false;
}
CriteriaPanel cp = new CriteriaPanel(myRow, selectQuery, add);
CriteriaDialog dlg = new CriteriaDialog(cp);
dlg.pack();
dlg.setResizable(false);
Show.centrateComponent(Globals.getMainFrame(), dlg);
dlg.setVisible(true);
MatchCriteria criteria = dlg.getCriteria();
if (criteria != null) {
myRow.criteria = criteria.getOperator() + " " + criteria.getFullValue();
model.fireTableCellUpdated(row, 7);
table.packAll();
}
} else if (column == 8) {
// } else if ((column == 8) && !(myRow.column instanceof ExpressionColumn) &&
// !((myRow.column instanceof GroupByFunctionColumn) && ((GroupByFunctionColumn) myRow.column).isExpression())) {
// select the row
table.setRowSelectionInterval(row, row);
boolean add = true;
if ((myRow.orCriterias.size() > 0) && (myRow.orCriterias.get(0) != null)) {
add = false;
}
CriteriaPanel cp = new CriteriaPanel(myRow, selectQuery, add, true);
CriteriaDialog dlg = new CriteriaDialog(cp, true);
dlg.pack();
dlg.setResizable(false);
Show.centrateComponent(Globals.getMainFrame(), dlg);
dlg.setVisible(true);
MatchCriteria criteria = dlg.getCriteria();
if (criteria != null) {
if (add) {
myRow.orCriterias.add(0, criteria.getOperator() + " " + criteria.getFullValue());
} else {
myRow.orCriterias.set(0, criteria.getOperator() + " " + criteria.getFullValue());
}
model.fireTableCellUpdated(row, 8);
table.packAll();
}
} else if ((column == 1) && ((myRow.column instanceof ExpressionColumn) ||
((myRow.column instanceof GroupByFunctionColumn) && ((GroupByFunctionColumn) myRow.column).isExpression()))) {
final Column expressionColumn = myRow.column;
new ExpressionEditAction(expressionColumn).actionPerformed(null);
}
}
}
}
void removeColumn(Column column) {
model.removeRow(model.getRowForColumn(column));
selectQuery.removeColumnAndDependencies(column);
if (tableRowHeader != null) {
tableRowHeader.updateUI();
}
}
void removeJoin(JoinCriteria criteria) {
selectQuery.removeCriteria(criteria);
if (tableRowHeader != null) {
tableRowHeader.updateUI();
}
}
void clear() {
sortOrderCombo.removeAllItems();
model.clear();
selectQuery.clear();
if (tableRowHeader != null) {
tableRowHeader.updateUI();
}
}
public String getQueryString() {
return selectQuery.toString();
}
public List<MyRow> getRows() {
List<MyRow> rows = new ArrayList<MyRow>();
int rowCount = model.getRowCount();
for (int i = 0; i < rowCount; i++) {
MyRow row = (MyRow) model.getObjectForRow(i);
rows.add(row);
}
return rows;
}
public void updateRows(List<MyRow> rows) {
int index = 0;
for (MyRow row : rows) {
int rowCount = model.getRowCount();
if ((row.column instanceof ExpressionColumn) ||
((row.column instanceof GroupByFunctionColumn) && ((GroupByFunctionColumn) row.column).isExpression())) {
model.addObject(row, index);
selectQuery.addColumn(row.column, index);
if ((row.groupBy != null) && !row.groupBy.equals("")) {
selectQuery.addGroupByColumn(row.column);
}
updateRow(row, index);
} else {
for (int i = 0; i < rowCount; i++) {
MyRow mRow = (MyRow) model.getObjectForRow(i);
if (mRow.equals(row)) {
updateRow(row, i);
break;
}
}
}
index++;
}
model.fireTableDataChanged();
table.packAll();
}
private void updateRow(MyRow row, int index) {
if (row.column.getAlias() != null) {
model.setValueAt(row.column.getAlias(), index, 2);
}
model.setValueAt(row.output, index, 3);
if (row.sortType != null) {
model.setValueAt(getSortType(row.sortType), index, 4);
}
model.setValueAt(String.valueOf(row.sortOrder), index, 5);
if (row.groupBy != null) {
model.setValueAt(row.groupBy, index, 6);
}
if (row.criteria != null) {
model.setValueAt(row.criteria, index, 7);
}
if (row.orCriterias != null) {
if (row.orCriterias.size() > 0) {
model.setValueAt(row.orCriterias.get(0), index, 8);
}
}
}
public static void fetchOrders() {
ASC = I18NSupport.getString("order.ascending");
DESC = I18NSupport.getString("order.descending");
}
private boolean hasGroupBy() {
for (int i = 0, size = model.getRowCount(); i < size; i++) {
String groupBy = (String) model.getValueAt(i, 6);
if (!"".equals(groupBy)) {
return true;
}
}
return false;
}
private String convertSortType(String sortType) {
if (ASC.equals(sortType)) {
return ASC_STORE;
} else if (DESC.equals(sortType)) {
return DESC_STORE;
// for old queries/reports created with Ascending, Ascendent, Descending, Descendent
} else if (sortType.startsWith(ASC_STORE)) {
return ASC_STORE;
} else if (sortType.startsWith(DESC_STORE)) {
return DESC_STORE;
} else {
return sortType;
}
}
private String getSortType(String convertedSortType) {
// we use startsWith and not equals for old queries/reports created with Ascending, Ascendent, Descending, Descendent
if (convertedSortType.startsWith(ASC_STORE)) {
return ASC;
} else if (convertedSortType.startsWith(DESC_STORE)) {
return DESC;
} else if ("".equals(convertedSortType)) {
return convertedSortType;
} else {
throw new IllegalArgumentException("SavedSortType=" + convertedSortType);
}
}
// must update first item "" (if exists) for drag & drop rows
public void updateGroupByItems(int dragRow, int dropRow) {
MyRow drag_row = (MyRow) model.getObjectForRow(dragRow);
JComboBox groupByComboDrag = (JComboBox) ((DefaultCellEditor) table.getCellEditor(dragRow, 6)).getComponent();
MyRow drop_row = (MyRow) model.getObjectForRow(dropRow);
JComboBox groupByComboDrop = (JComboBox) ((DefaultCellEditor) table.getCellEditor(dropRow, 6)).getComponent();
String sDrag = (String) groupByComboDrag.getItemAt(0);
String sDrop = (String) groupByComboDrop.getItemAt(0);
if ("".equals(sDrag) && !sDrag.equals(sDrop)) {
groupByComboDrop.insertItemAt("", 0);
groupByComboDrag.removeItem("");
}
if ("".equals(sDrop) && !sDrop.equals(sDrag)) {
groupByComboDrag.insertItemAt("", 0);
groupByComboDrop.removeItem("");
}
}
private boolean hasAggregateFunction() {
int col = 6; // groupby
int rows = model.getRowCount();
for (int row=0; row<rows; row++) {
String groupby = (String)model.getValueAt(row, col);
if (SUM.equals(groupby) || AVG.equals(groupby) || MIN.equals(groupby) || MAX.equals(groupby) || COUNT.equals(groupby)) {
return true;
}
}
return false;
}
private boolean hasEmpty(ComboBoxModel model) {
int size = model.getSize();
for (int i=0; i<size; i++) {
if ("".equals(model.getElementAt(i))) {
return true;
}
}
return false;
}
}