/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program 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, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.compiere.apps.search;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;
import java.util.logging.Level;
import java.util.regex.Pattern;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import org.compiere.apps.ADialog;
import org.compiere.apps.AEnv;
import org.compiere.apps.ConfirmPanel;
import org.compiere.apps.StatusBar;
import org.compiere.grid.ed.VEditor;
import org.compiere.grid.ed.VEditorFactory;
import org.compiere.grid.ed.VLookup;
import org.compiere.model.DataStatusEvent;
import org.compiere.model.DataStatusListener;
import org.compiere.model.GridField;
import org.compiere.model.GridFieldVO;
import org.compiere.model.GridTab;
import org.compiere.model.MColumn;
import org.compiere.model.MLookupFactory;
import org.compiere.model.MProduct;
import org.compiere.model.MQuery;
import org.compiere.model.MRole;
import org.compiere.model.MUserQuery;
import org.compiere.model.X_AD_Column;
import org.compiere.swing.CButton;
import org.compiere.swing.CComboBox;
import org.compiere.swing.CDialog;
import org.compiere.swing.CLabel;
import org.compiere.swing.CPanel;
import org.compiere.swing.CTabbedPane;
import org.compiere.swing.CTable;
import org.compiere.swing.CTextField;
import org.compiere.util.AdempiereSystemError;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.Language;
import org.compiere.util.Msg;
import org.compiere.util.Util;
import org.compiere.util.ValueNamePair;
import org.omidp.util.LocaleUtil;
/**
* Find/Search Records.
* Based on AD_Find for persistency, query is build to restrict info
*
* @author Jorg Janke
* @version $Id: Find.java,v 1.3 2006/07/30 00:51:27 jjanke Exp $
*
* @author Teo Sarca, www.arhipac.ro
* <li>BF [ 2564070 ] Saving user queries can produce unnecessary db errors
*/
public final class Find extends CDialog
implements ActionListener, ChangeListener, DataStatusListener
{
/**
*
*/
private static final long serialVersionUID = -5064336990363669996L;
private int m_AD_Tab_ID;
/**
* Find Constructor
* @param owner Frame Dialog Owner
* @param targetWindowNo WindowNo of target window
* @param title
* @param AD_Table_ID
* @param tableName
* @param whereExtended
* @param findFields
* @param minRecords number of minimum records
*/
public Find (Frame owner, int targetWindowNo, String title, int AD_Tab_ID,
int AD_Table_ID, String tableName, String whereExtended,
GridField[] findFields, int minRecords)
{
super(owner, Msg.getMsg(Env.getCtx(), "Find") + ": " + title, true);
super.applyComponentOrientation(ComponentOrientation.getOrientation(Language.getLoginLanguage().getLocale()));
log.info(title);
//
m_targetWindowNo = targetWindowNo;
m_AD_Tab_ID = AD_Tab_ID; //red1 new field for UserQuery [ 1798539 ]
m_AD_Table_ID = AD_Table_ID;
m_tableName = tableName;
m_whereExtended = whereExtended;
m_findFields = findFields;
//
m_query = new MQuery (tableName);
m_query.addRestriction(Env.parseContext(Env.getCtx(), m_targetWindowNo, whereExtended, false));
// Required for Column Validation
Env.setContext(Env.getCtx(), m_targetWindowNo, "Find_Table_ID", m_AD_Table_ID);
// Context for Advanced Search Grid is WINDOW_FIND
Env.setContext(Env.getCtx(), Env.WINDOW_FIND, "Find_Table_ID", m_AD_Table_ID);
//
try
{
jbInit();
initFind();
if (m_total < minRecords)
{
dispose();
return;
}
}
catch(Exception e)
{
log.log(Level.SEVERE, "Find", e);
}
//
this.getRootPane().setDefaultButton(confirmPanelS.getOKButton());
AEnv.showCenterWindow(owner, this);
} // Find
/** Target Window No */
private int m_targetWindowNo;
/** Table ID */
private int m_AD_Table_ID;
/** Table Name */
private String m_tableName;
/** Where */
private String m_whereExtended;
/** Search Fields */
private GridField[] m_findFields;
/** Resulting query */
private MQuery m_query = null;
/** Is cancel ? */
private boolean m_isCancel = false; // teo_sarca [ 1708717 ]
/** Logger */
private static CLogger log = CLogger.getCLogger(Find.class);
/** Number of records */
private int m_total;
private PreparedStatement m_pstmt;
//
private boolean hasValue = false;
private boolean hasDocNo = false;
private boolean hasName = false;
private boolean hasDescription = false;
/** Line in Simple Content */
private int m_sLine = 6;
/** List of VEditors */
private ArrayList<VEditor> m_sEditors = new ArrayList<VEditor>();
/** Target Fields with AD_Column_ID as key */
private Hashtable<Integer,GridField> m_targetFields = new Hashtable<Integer,GridField>();
/** For Grid Controller */
public static final int TABNO = 99;
/** Length of Fields on first tab */
public static final int FIELDLENGTH = 20;
/** Reference ID for Yes/No */
public static final int AD_REFERENCE_ID_YESNO = 319;
//
private CPanel southPanel = new CPanel();
private BorderLayout southLayout = new BorderLayout();
private StatusBar statusBar = new StatusBar();
private CTabbedPane tabbedPane = new CTabbedPane();
private CPanel advancedPanel = new CPanel();
private BorderLayout advancedLayout = new BorderLayout();
private ConfirmPanel confirmPanelA = new ConfirmPanel(true, true, false, false, false, false, true);
private CButton bIgnore = new CButton();
private JToolBar toolBar = new JToolBar();
private CComboBox fQueryName = new CComboBox();
private CButton bSave = new CButton();
private CButton bNew = new CButton();
private CButton bDelete = new CButton();
private ConfirmPanel confirmPanelS = new ConfirmPanel(true);
private BorderLayout simpleLayout = new BorderLayout();
private CPanel scontentPanel = new CPanel();
private GridBagLayout scontentLayout = new GridBagLayout();
private CPanel simplePanel = new CPanel();
private CLabel valueLabel = new CLabel();
private CLabel nameLabel = new CLabel();
private CLabel descriptionLabel = new CLabel();
private CTextField valueField = new CTextField();
private CTextField nameField = new CTextField();
private CTextField descriptionField = new CTextField();
private CLabel docNoLabel = new CLabel();
private CTextField docNoField = new CTextField();
private Component spaceE;
private Component spaceN;
private Component spaceW;
private Component spaceS;
private JScrollPane advancedScrollPane = new JScrollPane();
private CTable advancedTable = new CTable() {
private static final long serialVersionUID = -6201749159307529032L;
public boolean isCellEditable(int row, int column)
{
boolean editable = ( column == INDEX_COLUMNNAME
|| column == INDEX_OPERATOR
|| column == INDEX_ANDOR
|| column == INDEX_LEFTBRACKET
|| column == INDEX_RIGHTBRACKET );
if (!editable && row >= 0)
{
String columnName = null;
Object value =
getModel().getValueAt(row, INDEX_COLUMNNAME);
if (value != null)
{
if (value instanceof ValueNamePair)
columnName = ((ValueNamePair)value).getValue();
else
columnName = value.toString();
}
// Create Editor
editable = getTargetMField(columnName) != null;
}
if ( column == INDEX_ANDOR && row == 0 )
editable = false;
return editable;
}
public void columnMoved(TableColumnModelEvent e) {
if (isEditing()) {
cellEditor.stopCellEditing();
}
super.columnMoved(e);
}
public void columnMarginChanged(ChangeEvent e) {
if (isEditing()) {
cellEditor.stopCellEditing();
}
super.columnMarginChanged(e);
}
};
/** Index AndOr = 0 */
public static final int INDEX_ANDOR = 0;
/** Index LeftBracket = 1 */
public static final int INDEX_LEFTBRACKET = 1;
/** Index ColumnName = 2 */
public static final int INDEX_COLUMNNAME = 2;
/** Index Operator = 3 */
public static final int INDEX_OPERATOR = 3;
/** Index Value = 4 */
public static final int INDEX_VALUE = 4;
/** Index Value2 = 5 */
public static final int INDEX_VALUE2 = 5;
/** Index RightBracket = 6 */
public static final int INDEX_RIGHTBRACKET = 6;
/** Advanced Search Column */
public CComboBox columns = null;
/** Advanced Search Operators */
public CComboBox operators = null;
private MUserQuery[] userQueries;
private ValueNamePair[] columnValueNamePairs;
private CComboBox leftBrackets;
private CComboBox rightBrackets;
private CComboBox andOr;
private static final String FIELD_SEPARATOR = "<^>";
private static final String SEGMENT_SEPARATOR = "<~>";
/**
* Static Init.
* <pre>
* tabbedPane
* simplePanel
* scontentPanel
* confirmPanelS
* advancedPanel
* toolBar
* GC
* confirmPanelA
* southPanel
* statusBar
* </pre>
* @throws Exception
*/
private void jbInit() throws Exception
{
//omid
LocaleUtil.applyComponentOrientation(southPanel, scontentPanel);
spaceE = Box.createHorizontalStrut(8);
spaceN = Box.createVerticalStrut(8);
spaceW = Box.createHorizontalStrut(8);
spaceS = Box.createVerticalStrut(8);
bIgnore.setIcon(new ImageIcon(org.compiere.Adempiere.class.getResource("images/Ignore24.gif")));
bIgnore.setMargin(new Insets(2, 2, 2, 2));
bIgnore.setToolTipText(Msg.getMsg(Env.getCtx(),"Ignore"));
bIgnore.addActionListener(this);
fQueryName.setToolTipText (Msg.getMsg(Env.getCtx(),"QueryName"));
fQueryName.setEditable(true);
fQueryName.addActionListener(this);
bSave.setIcon(new ImageIcon(org.compiere.Adempiere.class.getResource("images/Save24.gif")));
bSave.setMargin(new Insets(2, 2, 2, 2));
bSave.setToolTipText(Msg.getMsg(Env.getCtx(),"Save"));
bSave.addActionListener(this);
bNew.setIcon(new ImageIcon(org.compiere.Adempiere.class.getResource("images/New24.gif")));
bNew.setMargin(new Insets(2, 2, 2, 2));
bNew.setToolTipText(Msg.getMsg(Env.getCtx(),"New"));
bNew.addActionListener(this);
bDelete.setIcon(new ImageIcon(org.compiere.Adempiere.class.getResource("images/Delete24.gif")));
bDelete.setMargin(new Insets(2, 2, 2, 2));
bDelete.setToolTipText(Msg.getMsg(Env.getCtx(),"Delete"));
bDelete.addActionListener(this);
//
southPanel.setLayout(southLayout);
valueLabel.setLabelFor(valueField);
valueLabel.setText(Msg.translate(Env.getCtx(),"Value"));
nameLabel.setLabelFor(nameField);
nameLabel.setText(Msg.translate(Env.getCtx(),"Name"));
descriptionLabel.setLabelFor(descriptionField);
descriptionLabel.setText(Msg.translate(Env.getCtx(),"Description"));
valueField.setText("%");
valueField.setColumns(FIELDLENGTH);
nameField.setText("%");
nameField.setColumns(FIELDLENGTH);
descriptionField.setText("%");
descriptionField.setColumns(FIELDLENGTH);
scontentPanel.setToolTipText(Msg.getMsg(Env.getCtx(),"FindTip"));
docNoLabel.setLabelFor(docNoField);
docNoLabel.setText(Msg.translate(Env.getCtx(),"DocumentNo"));
docNoField.setText("%");
docNoField.setColumns(FIELDLENGTH);
advancedScrollPane.setPreferredSize(new Dimension(540, 410));
southPanel.add(statusBar, BorderLayout.SOUTH);
this.getContentPane().add(southPanel, BorderLayout.SOUTH);
//
//
scontentPanel.setLayout(scontentLayout);
simplePanel.setLayout(simpleLayout);
simplePanel.add(confirmPanelS, BorderLayout.SOUTH);
simplePanel.add(scontentPanel, BorderLayout.CENTER);
scontentPanel.add(valueLabel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0
,GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(7, 5, 0, 5), 0, 0));
scontentPanel.add(nameLabel, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0
,GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(7, 5, 0, 5), 0, 0));
scontentPanel.add(descriptionLabel, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0
,GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(7, 5, 5, 5), 0, 0));
scontentPanel.add(valueField, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0
,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 5), 0, 0));
scontentPanel.add(descriptionField, new GridBagConstraints(2, 4, 1, 1, 0.0, 0.0
,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 5), 0, 0));
scontentPanel.add(docNoLabel, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0
,GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(7, 5, 0, 5), 0, 0));
scontentPanel.add(nameField, new GridBagConstraints(2, 3, 1, 1, 0.0, 0.0
,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 5), 0, 0));
scontentPanel.add(docNoField, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0
,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 5), 0, 0));
//
scontentPanel.add(spaceE, new GridBagConstraints(3, 3, 1, 1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0));
scontentPanel.add(spaceN, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0));
scontentPanel.add(spaceW, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0));
scontentPanel.add(spaceS, new GridBagConstraints(2, 15, 1, 1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0));
//
// tabbedPane.add(simplePanel, Msg.getMsg(Env.getCtx(),"Find"));
tabbedPane.add(simplePanel, Msg.getMsg(Env.getCtx(),"Find"));
//
toolBar.add(bIgnore, null);
toolBar.addSeparator();
toolBar.add(bNew, null);
toolBar.add(bDelete, null);
toolBar.add(fQueryName, null);
toolBar.add(bSave, null);
advancedPanel.setLayout(advancedLayout);
advancedPanel.add(toolBar, BorderLayout.NORTH);
advancedPanel.add(confirmPanelA, BorderLayout.SOUTH);
advancedPanel.add(advancedScrollPane, BorderLayout.CENTER);
advancedScrollPane.getViewport().add(advancedTable, null);
// tabbedPane.add(advancedPanel, Msg.getMsg(Env.getCtx(),"Advanced"));
tabbedPane.add(advancedPanel, Msg.getMsg(Env.getCtx(),"Advanced"));
//
this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
//
confirmPanelA.addActionListener(this);
confirmPanelS.addActionListener(this);
//
JButton b = ConfirmPanel.createNewButton(true);
confirmPanelS.addComponent (b);
b.addActionListener(this);
// teo_sarca, [ 1670847 ] Find dialog: closing and canceling need same functionality
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
cmd_cancel();
}
});
} // jbInit
/**
* Dynamic Init.6
* Set up GridController
*/
private void initFind()
{
log.config("");
// Get Info from target Tab
for (int i = 0; i < m_findFields.length; i++)
{
GridField mField = m_findFields[i];
String columnName = mField.getColumnName();
// Make Yes-No searchable as list
if (mField.getVO().displayType == DisplayType.YesNo)
{
GridFieldVO vo = mField.getVO();
GridFieldVO ynvo = vo.clone(vo.ctx, vo.WindowNo, vo.TabNo, vo.AD_Window_ID, vo.AD_Tab_ID, vo.tabReadOnly);
ynvo.IsDisplayed = true;
ynvo.displayType = DisplayType.List;
ynvo.AD_Reference_Value_ID = AD_REFERENCE_ID_YESNO;
ynvo.lookupInfo = MLookupFactory.getLookupInfo (ynvo.ctx, ynvo.WindowNo, ynvo.AD_Column_ID, ynvo.displayType,
Env.getLanguage(ynvo.ctx), ynvo.ColumnName, ynvo.AD_Reference_Value_ID,
ynvo.IsParent, ynvo.ValidationCode);
ynvo.lookupInfo.InfoFactoryClass = ynvo.InfoFactoryClass;
GridField ynfield = new GridField(ynvo);
// replace the original field by the YN List field
m_findFields[i] = ynfield;
mField = ynfield;
}
// Make Buttons searchable
if ( mField.getVO().displayType == DisplayType.Button )
{
GridFieldVO vo = mField.getVO();
if ( vo.AD_Reference_Value_ID > 0 )
{
GridFieldVO postedvo = vo.clone(vo.ctx, vo.WindowNo, vo.TabNo, vo.AD_Window_ID, vo.AD_Tab_ID, vo.tabReadOnly);
postedvo.IsDisplayed = true;
postedvo.displayType = DisplayType.List;
postedvo.lookupInfo = MLookupFactory.getLookupInfo (postedvo.ctx, postedvo.WindowNo, postedvo.AD_Column_ID, postedvo.displayType,
Env.getLanguage(postedvo.ctx), postedvo.ColumnName, postedvo.AD_Reference_Value_ID,
postedvo.IsParent, postedvo.ValidationCode);
postedvo.lookupInfo.InfoFactoryClass = postedvo.InfoFactoryClass;
GridField postedfield = new GridField(postedvo);
// replace the original field by the Posted List field
m_findFields[i] = postedfield;
mField = postedfield;
}
}
/** metas: teo_sarca: Specify exactly which are the search fields - http://sourceforge.net/projects/adempiere/forums/forum/610548/topic/3736214
if (columnName.equals("Value"))
hasValue = true;
else if (columnName.equals("Name"))
hasName = true;
else if (columnName.equals("DocumentNo"))
hasDocNo = true;
else if (columnName.equals("Description"))
hasDescription = true;
else
/**/
if (mField.isSelectionColumn())
addSelectionColumn (mField);
/** metas: teo_sarca: Specify exactly which are the search fields - http://sourceforge.net/projects/adempiere/forums/forum/610548/topic/3736214
else if (columnName.indexOf("Name") != -1)
addSelectionColumn (mField);
/**/
// TargetFields
m_targetFields.put (new Integer(mField.getAD_Column_ID()), mField);
} // for all target tab fields
// Disable simple query fields
valueLabel.setVisible(hasValue);
valueField.setVisible(hasValue);
if (hasValue)
valueField.addActionListener(this);
docNoLabel.setVisible(hasDocNo);
docNoField.setVisible(hasDocNo);
if (hasDocNo)
docNoField.addActionListener(this);
nameLabel.setVisible(hasName);
nameField.setVisible(hasName);
if (hasName)
nameField.addActionListener(this);
descriptionLabel.setVisible(hasDescription);
descriptionField.setVisible(hasDescription);
if (hasDescription)
descriptionField.addActionListener(this);
// Get Total
m_total = getNoOfRecords(null, false);
setStatusDB (m_total);
statusBar.setStatusLine("");
tabbedPane.addChangeListener(this);
// Better Labels for OK/Cancel
confirmPanelA.getOKButton().setToolTipText(Msg.getMsg(Env.getCtx(),"QueryEnter"));
confirmPanelA.getCancelButton().setToolTipText(Msg.getMsg(Env.getCtx(),"QueryCancel"));
confirmPanelS.getOKButton().setToolTipText(Msg.getMsg(Env.getCtx(),"QueryEnter"));
confirmPanelS.getCancelButton().setToolTipText(Msg.getMsg(Env.getCtx(),"QueryCancel"));
} // initFind
/**
* Add Selection Column to first Tab
* @param mField field
*/
private void addSelectionColumn (GridField mField)
{
log.config(mField.getHeader());
int displayLength = mField.getDisplayLength();
if (displayLength > FIELDLENGTH)
mField.setDisplayLength(FIELDLENGTH);
else
displayLength = 0;
// Editor
VEditor editor = null;
if (mField.isLookup())
{
VLookup vl = new VLookup(mField.getColumnName(), false, false, true,
mField.getLookup());
//setting mField to avoid NPE
vl.setField(mField);
vl.setName(mField.getColumnName());
editor = vl;
}
else
{
editor = VEditorFactory.getEditor(mField, false);
editor.setMandatory(false);
editor.setReadWrite(true);
}
// Add action listener to custom text fields - teo_sarca [ 1709292 ]
if (editor instanceof CTextField) {
((CTextField)editor).addActionListener(this);
}
CLabel label = VEditorFactory.getLabel(mField);
//
if (displayLength > 0) // set it back
mField.setDisplayLength(displayLength);
//
m_sLine++;
if (label != null) // may be null for Y/N
scontentPanel.add(label, new GridBagConstraints(1, m_sLine, 1, 1, 0.0, 0.0
,GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(7, 5, 5, 5), 0, 0));
scontentPanel.add((Component)editor, new GridBagConstraints(2, m_sLine, 1, 1, 0.0, 0.0
,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 5), 0, 0));
m_sEditors.add(editor);
} // addSelectionColumn
/**
* Init Find GridController
*/
private void initFindAdvanced()
{
log.config("");
advancedTable.setModel(new DefaultTableModel(0, 7));
advancedTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
advancedTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
advancedTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
TableCellRenderer renderer = new ProxyRenderer(advancedTable.getDefaultRenderer(Object.class));
advancedTable.setDefaultRenderer(Object.class, renderer);
InputMap im = advancedTable.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
KeyStroke tab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
final Action tabAction = advancedTable.getActionMap().get(im.get(tab));
Action tabActionWrapper = new AbstractAction()
{
private static final long serialVersionUID = -6868476640719619801L;
public void actionPerformed(ActionEvent e)
{
tabAction.actionPerformed(e);
JTable table = (JTable)e.getSource();
table.requestFocusInWindow();
}
};
advancedTable.getActionMap().put(im.get(tab), tabActionWrapper);
KeyStroke shiftTab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK);
final Action shiftTabAction = advancedTable.getActionMap().get(im.get(shiftTab));
Action shiftTabActionWrapper = new AbstractAction()
{
private static final long serialVersionUID = 5493691483070046620L;
public void actionPerformed(ActionEvent e)
{
shiftTabAction.actionPerformed(e);
JTable table = (JTable)e.getSource();
table.requestFocusInWindow();
}
};
advancedTable.getActionMap().put(im.get(shiftTab), shiftTabActionWrapper);
// 0 = Columns
ArrayList<ValueNamePair> items = new ArrayList<ValueNamePair>();
for (int c = 0; c < m_findFields.length; c++)
{
GridField field = m_findFields[c];
String columnName = field.getColumnName();
String header = field.getHeader();
if (header == null || header.length() == 0)
{
header = Msg.translate(Env.getCtx(), columnName);
if (header == null || header.length() == 0)
continue;
}
if (field.isKey())
header += (" (ID)");
ValueNamePair pp = new ValueNamePair(columnName, header);
// System.out.println(pp + " = " + field);
items.add(pp);
}
columnValueNamePairs = new ValueNamePair[items.size()];
items.toArray(columnValueNamePairs);
Arrays.sort(columnValueNamePairs); // sort alpha
columns = new CComboBox(columnValueNamePairs);
columns.addActionListener(this);
TableColumn tc = advancedTable.getColumnModel().getColumn(INDEX_COLUMNNAME);
tc.setPreferredWidth(120);
FindCellEditor dce = new FindCellEditor(columns);
dce.addCellEditorListener(new CellEditorListener()
{
public void editingCanceled(ChangeEvent ce)
{
}
public void editingStopped(ChangeEvent ce)
{
int col = advancedTable.getSelectedColumn();
int row = advancedTable.getSelectedRow();
if (col == INDEX_COLUMNNAME && row >= 0)
{
advancedTable.setValueAt(null, row, INDEX_VALUE);
advancedTable.setValueAt(null, row, INDEX_VALUE2);
}
}
});
tc.setCellEditor(dce);
tc.setHeaderValue(Msg.translate(Env.getCtx(), "AD_Column_ID"));
// 0 = And/Or
andOr = new CComboBox(new String[] {"",Msg.getMsg(Env.getCtx(),"AND"),Msg.getMsg(Env.getCtx(), "OR")});
tc = advancedTable.getColumnModel().getColumn(INDEX_ANDOR);
tc.setPreferredWidth(45);
dce = new FindCellEditor(andOr);
tc.setCellEditor(dce);
tc.setHeaderValue(Msg.getMsg(Env.getCtx(), "And/Or"));
// 1 = Left Bracket
leftBrackets = new CComboBox(new String[] {"","(","((","((("});
tc = advancedTable.getColumnModel().getColumn(INDEX_LEFTBRACKET);
tc.setPreferredWidth(25);
dce = new FindCellEditor(leftBrackets);
tc.setCellEditor(dce);
tc.setHeaderValue("(");
// 3 = Operators
operators = new CComboBox(MQuery.OPERATORS);
tc = advancedTable.getColumnModel().getColumn(INDEX_OPERATOR);
tc.setPreferredWidth(55);
dce = new FindCellEditor(operators);
tc.setCellEditor(dce);
tc.setHeaderValue(Msg.getMsg(Env.getCtx(), "Operator"));
// 4 = QueryValue
tc = advancedTable.getColumnModel().getColumn(INDEX_VALUE);
FindValueEditor fve = new FindValueEditor(this, false);
tc.setCellEditor(fve);
tc.setPreferredWidth(120);
tc.setCellRenderer(new ProxyRenderer(new FindValueRenderer(this, false)));
tc.setHeaderValue(Msg.getMsg(Env.getCtx(), "QueryValue"));
// 5 = QueryValue2
tc = advancedTable.getColumnModel().getColumn(INDEX_VALUE2);
tc.setPreferredWidth(120);
fve = new FindValueEditor(this, true);
tc.setCellEditor(fve);
tc.setCellRenderer(new ProxyRenderer(new FindValueRenderer(this, false)));
tc.setHeaderValue(Msg.getMsg(Env.getCtx(), "QueryValue2"));
// 6 = Right Bracket
rightBrackets = new CComboBox(new String[] {"",")","))",")))"});
tc = advancedTable.getColumnModel().getColumn(INDEX_RIGHTBRACKET);
tc.setPreferredWidth(25);
dce = new FindCellEditor(rightBrackets);
tc.setCellEditor(dce);
tc.setHeaderValue(")");
// phib: disabled auto-completion as it causes date fields to have to be entered twice
//AutoCompletion.enable(columns);
//AutoCompletion.enable(operators);
//user query
userQueries = MUserQuery.get(Env.getCtx(), m_AD_Tab_ID);
String[] queries = new String[userQueries.length];
for (int i = 0; i < userQueries.length; i++)
queries[i] = userQueries[i].getName();
fQueryName.setModel(new DefaultComboBoxModel(queries));
fQueryName.setValue("");
// No Row - Create one
cmd_new();
} // initFindAdvanced
/**
* Dispose window
*/
public void dispose()
{
log.config("");
// Find SQL
if (m_pstmt != null)
{
try {
m_pstmt.close();
} catch (SQLException e) {}
}
m_pstmt = null;
// Remove action listener from custom fields - teo_sarca [ 1709292 ]
for (VEditor editor : m_sEditors) {
if (editor instanceof CTextField)
((CTextField)editor).removeActionListener(this);
}
// TargetFields
if (m_targetFields != null)
m_targetFields.clear();
m_targetFields = null;
//
removeAll();
super.dispose();
} // dispose
/**************************************************************************
* Action Listener
* @param e ActionEvent
*/
public void actionPerformed (ActionEvent e)
{
log.info(e.getActionCommand());
//
if (e.getActionCommand().equals(ConfirmPanel.A_CANCEL))
cmd_cancel();
else if (e.getActionCommand().equals(ConfirmPanel.A_REFRESH))
cmd_refresh();
//
else if (e.getActionCommand().equals(ConfirmPanel.A_NEW))
{
m_query = MQuery.getNoRecordQuery(m_tableName, true);
m_total = 0;
dispose();
}
//
else if (e.getSource() == bIgnore)
cmd_ignore();
else if (e.getSource() == bNew)
cmd_new();
else if (e.getSource() == bSave)
cmd_save(true);
else if (e.getSource() == bDelete)
cmd_delete();
//
else if (e.getSource() == columns)
{
String columnName = null;
Object selected = columns.getSelectedItem();
if (selected != null)
{
if (selected instanceof ValueNamePair)
{
ValueNamePair column = (ValueNamePair)selected;
columnName = column.getValue();
}
else
{
columnName = selected.toString();
}
}
if (columnName != null)
{
log.config("Column: " + columnName);
if (columnName.endsWith("_ID") || columnName.endsWith("_Acct"))
operators.setModel(new DefaultComboBoxModel(MQuery.OPERATORS_ID));
else if (columnName.startsWith("Is"))
operators.setModel(new DefaultComboBoxModel(MQuery.OPERATORS_YN));
else
operators.setModel(new DefaultComboBoxModel(MQuery.OPERATORS));
}
}
else if (e.getSource() == fQueryName)
{
Object o = fQueryName.getSelectedItem();
if (userQueries != null && o != null)
{
String selected = o.toString();
for (int i = 0; i < userQueries.length; i++)
{
if (userQueries[i].getName().equals(selected))
{
parseUserQuery(userQueries[i]);
return;
}
}
}
}
else // ConfirmPanel.A_OK and enter in fields
{
if (e.getSource() == confirmPanelA.getOKButton())
cmd_ok_Advanced();
else if (e.getSource() == confirmPanelS.getOKButton())
cmd_ok_Simple();
else if (e.getSource() instanceof JTextField &&
tabbedPane.getSelectedIndex() == 0)
cmd_ok_Simple();
}
} // actionPerformed
/**
* Parse delimited string into user query
* Old field sequence: column, operator, value, value to
* New field sequence: column, operator, value, value to, and/or, left brackets, right brackets
* @param userQuery
*/
private void parseUserQuery(MUserQuery userQuery) {
String code = userQuery.getCode();
log.fine("Parse user query: " + code);
String[] segments = code.split(Pattern.quote(SEGMENT_SEPARATOR),-1);
advancedTable.stopEditor(true);
DefaultTableModel model = (DefaultTableModel)advancedTable.getModel();
int cnt = model.getRowCount();
for (int i = cnt - 1; i >=0; i--)
model.removeRow(i);
for (int i = 0; i < segments.length; i++)
{
String[] fields = segments[i].split(Pattern.quote(FIELD_SEPARATOR));
model.addRow(new Object[] {"","", null, MQuery.OPERATORS[MQuery.EQUAL_INDEX], null, null, ""});
String columnName = null;
for (int j = 0; j < fields.length; j++)
{
// column
if (j == 0 )
{
for (ValueNamePair vnp : columnValueNamePairs)
{
if (vnp.getValue().equals(fields[j]))
{
model.setValueAt(vnp, i, INDEX_COLUMNNAME);
columnName = fields[j];
break;
}
}
}
// operator
else if (j == 1)
{
for (ValueNamePair vnp : MQuery.OPERATORS)
{
if (vnp.getValue().equals(fields[j]))
{
model.setValueAt(vnp, i, INDEX_OPERATOR);
break;
}
}
}
// value
else if ( j == 2 && fields[j].length() > 0 )
{
GridField field = getTargetMField(columnName);
Object value = parseString(field, fields[j]);
model.setValueAt(value, i, INDEX_VALUE);
}
// value 2
else if ( j == 3 && fields[j].length() > 0 )
{
GridField field = getTargetMField(columnName);
Object value = parseString(field, fields[j]);
model.setValueAt(value, i, INDEX_VALUE2);
}
// and/or
else if (j == 4 && fields[j].length() > 0 )
{
if ( i != 0 )
model.setValueAt(fields[j], i, INDEX_ANDOR);
}
else if ( j == 5 && fields[j].length() > 0 )
{
model.setValueAt(fields[j], i, INDEX_LEFTBRACKET);
}
else if ( j == 6 && fields[j].length() > 0 )
{
model.setValueAt(fields[j], i, INDEX_RIGHTBRACKET);
}
}
}
advancedTable.invalidate();
}
/**
* Change Listener (tab change)
* @param e ChangeEbent
*/
public void stateChanged(ChangeEvent e)
{
// log.info( "Find.stateChanged");
if (tabbedPane.getSelectedIndex() == 0)
this.getRootPane().setDefaultButton(confirmPanelS.getOKButton());
else
{
initFindAdvanced();
this.getRootPane().setDefaultButton(confirmPanelA.getOKButton());
advancedTable.requestFocusInWindow();
}
} // stateChanged
/**
* Simple OK Button pressed
*/
private void cmd_ok_Simple()
{
// Create Query String
m_query = new MQuery(m_tableName);
m_query.addRestriction(Env.parseContext(Env.getCtx(), m_targetWindowNo, m_whereExtended, false));
if (hasValue && !valueField.getText().equals("%") && valueField.getText().length() != 0)
{
String value = valueField.getText().toUpperCase();
if (!value.endsWith("%"))
value += "%";
m_query.addRestriction("UPPER(Value)", MQuery.LIKE, value, valueLabel.getText(), value);
}
//
if (hasDocNo && !docNoField.getText().equals("%") && docNoField.getText().length() != 0)
{
String value = docNoField.getText().toUpperCase();
if (!value.endsWith("%"))
value += "%";
m_query.addRestriction("UPPER(DocumentNo)", MQuery.LIKE, value, docNoLabel.getText(), value);
}
//
if ((hasName) && !nameField.getText().equals("%") && nameField.getText().length() != 0)
{
String value = nameField.getText().toUpperCase();
if (!value.endsWith("%"))
value += "%";
m_query.addRestriction("UPPER(Name)", MQuery.LIKE, value, nameLabel.getText(), value);
}
//
if (hasDescription && !descriptionField.getText().equals("%") && descriptionField.getText().length() != 0)
{
String value = descriptionField.getText().toUpperCase();
if (!value.endsWith("%"))
value += "%";
m_query.addRestriction("UPPER(Description)", MQuery.LIKE, value, descriptionLabel.getText(), value);
}
// Special Editors
for (int i = 0; i < m_sEditors.size(); i++)
{
VEditor ved = (VEditor)m_sEditors.get(i);
Object value = ved.getValue();
if (value != null && value.toString().length() > 0)
{
String ColumnName = ((Component)ved).getName ();
log.fine(ColumnName + "=" + value);
// globalqss - Carlos Ruiz - 20060711
// fix a bug with virtualColumn + isSelectionColumn not yielding results
GridField field = getTargetMField(ColumnName);
boolean isProductCategoryField = isProductCategoryField(field.getAD_Column_ID());
String ColumnSQL = field.getColumnSQL(false);
//
// Be more permissive for String columns
if (isSearchLike(field))
{
String valueStr = value.toString().toUpperCase();
if (!valueStr.endsWith("%"))
valueStr += "%";
//
ColumnSQL = "UPPER("+ColumnSQL+")";
value = valueStr;
}
//
if (value.toString().indexOf('%') != -1)
m_query.addRestriction(ColumnSQL, MQuery.LIKE, value, ColumnName, ved.getDisplay());
else if (isProductCategoryField && value instanceof Integer)
m_query.addRestriction(getSubCategoryWhereClause(((Integer) value).intValue()));
else
m_query.addRestriction(ColumnSQL, MQuery.EQUAL, value, ColumnName, ved.getDisplay());
/*
if (value.toString().indexOf('%') != -1)
m_query.addRestriction(ColumnName, MQuery.LIKE, value, ColumnName, ved.getDisplay());
else
m_query.addRestriction(ColumnName, MQuery.EQUAL, value, ColumnName, ved.getDisplay());
*/
// end globalqss patch
}
} // editors
m_isCancel = false; // teo_sarca [ 1708717 ]
// Test for no records
if (getNoOfRecords(m_query, true) != 0)
dispose();
} // cmd_ok_Simple
/**
* Advanced OK Button pressed
*/
private void cmd_ok_Advanced()
{
m_isCancel = false; // teo_sarca [ 1708717 ]
// save pending
if (bSave.isEnabled())
cmd_save(false);
if (getNoOfRecords(m_query, true) != 0)
dispose();
} // cmd_ok_Advanced
/**
* Cancel Button pressed
*/
private void cmd_cancel()
{
advancedTable.stopEditor(false);
log.info("");
m_query = null;
m_total = 999999;
m_isCancel = true; // teo_sarca [ 1708717 ]
dispose();
} // cmd_ok
/**
* Ignore
*/
private void cmd_ignore()
{
log.info("");
} // cmd_ignore
/**
* New record
*/
private void cmd_new()
{
advancedTable.stopEditor(true);
DefaultTableModel model = (DefaultTableModel)advancedTable.getModel();
int rows = model.getRowCount();
model.addRow(new Object[] {rows == 0 ? "" : "AND","", null, MQuery.OPERATORS[MQuery.EQUAL_INDEX], null, null,""});
advancedTable.requestFocusInWindow();
} // cmd_new
/**
* Save (Advanced)
*/
private void cmd_save(boolean saveQuery)
{
advancedTable.stopEditor(true);
//
m_query = new MQuery(m_tableName);
m_query.addRestriction(Env.parseContext(Env.getCtx(), m_targetWindowNo, m_whereExtended, false));
StringBuffer code = new StringBuffer();
int openBrackets = 0;
for (int row = 0; row < advancedTable.getRowCount(); row++)
{
// Column
Object column = advancedTable.getValueAt(row, INDEX_COLUMNNAME);
if (column == null)
continue;
String ColumnName = column instanceof ValueNamePair ?
((ValueNamePair)column).getValue() : column.toString();
String infoName = column.toString();
//
GridField field = getTargetMField(ColumnName);
if (field == null)
continue;
boolean isProductCategoryField = isProductCategoryField(field.getAD_Column_ID());
String ColumnSQL = field.getColumnSQL(false);
String lBrackets = (String) advancedTable.getValueAt(row, INDEX_LEFTBRACKET);
if ( lBrackets != null )
openBrackets += lBrackets.length();
String rBrackets = (String) advancedTable.getValueAt(row, INDEX_RIGHTBRACKET);
if ( rBrackets != null )
openBrackets -= rBrackets.length();
boolean and = true;
if ( row > 0 )
and = !"OR".equals((String) advancedTable.getValueAt(row, INDEX_ANDOR));
// Op
Object op = advancedTable.getValueAt(row, INDEX_OPERATOR);
if (op == null)
continue;
String Operator = ((ValueNamePair)op).getValue();
// Value ******
Object value = advancedTable.getValueAt(row, INDEX_VALUE);
if (value == null)
{
if ( MQuery.OPERATORS[MQuery.EQUAL_INDEX].equals(op)
|| MQuery.OPERATORS[MQuery.NOT_EQUAL_INDEX].equals(op) )
{
m_query.addRestriction(ColumnSQL, Operator, null,
infoName, null, and, openBrackets);
if (code.length() > 0)
code.append(SEGMENT_SEPARATOR);
code.append(ColumnName)
.append(FIELD_SEPARATOR)
.append(Operator)
.append(FIELD_SEPARATOR)
.append("")
.append(FIELD_SEPARATOR)
.append("")
.append(FIELD_SEPARATOR)
.append( and ? "AND" : "OR")
.append(FIELD_SEPARATOR)
.append(lBrackets != null ? lBrackets : "")
.append(FIELD_SEPARATOR)
.append(rBrackets != null ? rBrackets : "");
}
else
{
continue;
}
}
else
{
Object parsedValue = parseValue(field, value);
if (parsedValue == null)
continue;
String infoDisplay = value.toString();
if (field.isLookup())
infoDisplay = field.getLookup().getDisplay(value);
else if (field.getDisplayType() == DisplayType.YesNo)
infoDisplay = Msg.getMsg(Env.getCtx(), infoDisplay);
// Value2 ******
Object value2 = null;
if (MQuery.OPERATORS[MQuery.BETWEEN_INDEX].equals(op))
{
value2 = advancedTable.getValueAt(row, INDEX_VALUE2);
if (value2 == null)
continue;
Object parsedValue2 = parseValue(field, value2);
String infoDisplay_to = value2.toString();
if (parsedValue2 == null)
continue;
m_query.addRangeRestriction(ColumnSQL, parsedValue, parsedValue2,
infoName, infoDisplay, infoDisplay_to, and, openBrackets);
}
else if (isProductCategoryField && MQuery.OPERATORS[MQuery.EQUAL_INDEX].equals(op)) {
if (!(parsedValue instanceof Integer)) {
continue;
}
m_query
.addRestriction(getSubCategoryWhereClause(((Integer) parsedValue).intValue()), and, openBrackets);
}
else
m_query.addRestriction(ColumnSQL, Operator, parsedValue,
infoName, infoDisplay, and, openBrackets);
if (code.length() > 0)
code.append(SEGMENT_SEPARATOR);
code.append(ColumnName)
.append(FIELD_SEPARATOR)
.append(Operator)
.append(FIELD_SEPARATOR)
.append(value.toString())
.append(FIELD_SEPARATOR)
.append(value2 != null ? value2.toString() : "")
.append(FIELD_SEPARATOR)
.append( and ? "AND" : "OR")
.append(FIELD_SEPARATOR)
.append(lBrackets != null ? lBrackets : "")
.append(FIELD_SEPARATOR)
.append(rBrackets != null ? rBrackets : "");
}
}
Object selected = fQueryName.getSelectedItem();
if (selected != null && saveQuery) {
String name = selected.toString();
if (Util.isEmpty(name, true))
{
ADialog.warn(m_targetWindowNo, this, "FillMandatory", Msg.translate(Env.getCtx(), "Name"));
return;
}
MUserQuery uq = MUserQuery.get(Env.getCtx(), m_AD_Tab_ID, name);
if (uq == null && code.length() > 0)
{
uq = new MUserQuery (Env.getCtx(), 0, null);
uq.setName (name);
uq.setAD_Tab_ID(m_AD_Tab_ID); //red1 UserQuery [ 1798539 ] taking in new field from Compiere
uq.setAD_User_ID(Env.getAD_User_ID(Env.getCtx())); //red1 - [ 1798539 ] missing in Compiere delayed source :-)
}
else if (uq != null && code.length() == 0)
{
if (uq.delete(true))
{
ADialog.info (m_targetWindowNo, this, "Deleted", name);
refreshUserQueries();
}
else
ADialog.warn (m_targetWindowNo, this, "DeleteError", name);
return;
}
uq.setCode (code.toString());
uq.setAD_Table_ID (m_AD_Table_ID);
//
if (uq.save())
{
ADialog.info (m_targetWindowNo, this, "Saved", name);
refreshUserQueries();
}
else
ADialog.warn (m_targetWindowNo, this, "SaveError", name);
}
} // cmd_save
private void refreshUserQueries()
{
Object selected = fQueryName.getSelectedItem();
userQueries = MUserQuery.get(Env.getCtx(), m_AD_Tab_ID);
String[] queries = new String[userQueries.length];
for (int i = 0; i < userQueries.length; i++)
queries[i] = userQueries[i].getName();
fQueryName.setModel(new DefaultComboBoxModel(queries));
fQueryName.setSelectedItem(selected);
if (fQueryName.getSelectedIndex() < 0)
fQueryName.setValue("");
}
/**
* Checks the given column.
* @param columnId
* @return true if the column is a product category column
*/
private boolean isProductCategoryField(int columnId) {
X_AD_Column col = new X_AD_Column(Env.getCtx(), columnId, null);
if (col.get_ID() == 0) {
return false; // column not found...
}
return MProduct.COLUMNNAME_M_Product_Category_ID.equals(col.getColumnName());
}
/**
* Returns a sql where string with the given category id and all of its subcategory ids.
* It is used as restriction in MQuery.
* @param productCategoryId
* @return
*/
private String getSubCategoryWhereClause(int productCategoryId) {
//if a node with this id is found later in the search we have a loop in the tree
int subTreeRootParentId = 0;
String retString = " M_Product_Category_ID IN (";
String sql = " SELECT M_Product_Category_ID, M_Product_Category_Parent_ID FROM M_Product_Category";
final Vector<SimpleTreeNode> categories = new Vector<SimpleTreeNode>(100);
Statement stmt = null;
ResultSet rs = null;
try {
stmt = DB.createStatement();
rs = stmt.executeQuery(sql);
while (rs.next()) {
if(rs.getInt(1)==productCategoryId) {
subTreeRootParentId = rs.getInt(2);
}
categories.add(new SimpleTreeNode(rs.getInt(1), rs.getInt(2)));
}
retString += getSubCategoriesString(productCategoryId, categories, subTreeRootParentId);
retString += ") ";
} catch (SQLException e) {
log.log(Level.SEVERE, sql, e);
retString = "";
} catch (AdempiereSystemError e) {
log.log(Level.SEVERE, sql, e);
retString = "";
}
finally {
DB.close(rs, stmt);
rs = null; stmt = null;
}
return retString;
}
/**
* Recursive search for subcategories with loop detection.
* @param productCategoryId
* @param categories
* @param loopIndicatorId
* @return comma seperated list of category ids
* @throws AdempiereSystemError if a loop is detected
*/
private String getSubCategoriesString(int productCategoryId, Vector<SimpleTreeNode> categories, int loopIndicatorId) throws AdempiereSystemError {
String ret = "";
final Iterator<SimpleTreeNode> iter = categories.iterator();
while (iter.hasNext()) {
SimpleTreeNode node = (SimpleTreeNode) iter.next();
if (node.getParentId() == productCategoryId) {
if (node.getNodeId() == loopIndicatorId) {
throw new AdempiereSystemError("The product category tree contains a loop on categoryId: " + loopIndicatorId);
}
ret = ret + getSubCategoriesString(node.getNodeId(), categories, loopIndicatorId) + ",";
}
}
log.fine(ret);
return ret + productCategoryId;
}
/**
* Simple tree node class for product category tree search.
* @author Karsten Thiemann, kthiemann@adempiere.org
*
*/
private class SimpleTreeNode {
private int nodeId;
private int parentId;
public SimpleTreeNode(int nodeId, int parentId) {
this.nodeId = nodeId;
this.parentId = parentId;
}
public int getNodeId() {
return nodeId;
}
public int getParentId() {
return parentId;
}
}
/**
* Parse Value
* @param field column
* @param in value
* @return data type corrected value
*/
private Object parseValue (GridField field, Object in)
{
if (in == null)
return null;
int dt = field.getDisplayType();
try
{
// Return Integer
if (dt == DisplayType.Integer
|| (DisplayType.isID(dt) && field.getColumnName().endsWith("_ID")))
{
if (in instanceof Integer)
return in;
int i = Integer.parseInt(in.toString());
return new Integer(i);
}
// Return BigDecimal
else if (DisplayType.isNumeric(dt))
{
if (in instanceof BigDecimal)
return in;
return DisplayType.getNumberFormat(dt).parse(in.toString());
}
// Return Timestamp
else if (DisplayType.isDate(dt))
{
if (in instanceof Timestamp)
return in;
long time = 0;
try
{
time = DisplayType.getDateFormat_JDBC().parse(in.toString()).getTime();
return new Timestamp(time);
}
catch (Exception e)
{
log.log(Level.SEVERE, in + "(" + in.getClass() + ")" + e);
time = DisplayType.getDateFormat(dt).parse(in.toString()).getTime();
}
return new Timestamp(time);
}
// Return Y/N for Boolean
else if (in instanceof Boolean)
return ((Boolean)in).booleanValue() ? "Y" : "N";
}
catch (Exception ex)
{
log.log(Level.SEVERE, "Object=" + in, ex);
String error = ex.getLocalizedMessage();
if (error == null || error.length() == 0)
error = ex.toString();
StringBuffer errMsg = new StringBuffer();
errMsg.append(field.getColumnName()).append(" = ").append(in).append(" - ").append(error);
//
ADialog.error(0, this, "ValidationError", errMsg.toString());
return null;
}
return in;
} // parseValue
/**
* Parse String
* @param field column
* @param in value
* @return data type corrected value
*/
private Object parseString(GridField field, String in)
{
log.log(Level.FINE, "Parse: " +field + ":" + in);
if (in == null)
return null;
int dt = field.getDisplayType();
try
{
// Return Integer
if (dt == DisplayType.Integer
|| (DisplayType.isID(dt) && field.getColumnName().endsWith("_ID")))
{
int i = Integer.parseInt(in);
return new Integer(i);
}
// Return BigDecimal
else if (DisplayType.isNumeric(dt))
{
return DisplayType.getNumberFormat(dt).parse(in);
}
// Return Timestamp
else if (DisplayType.isDate(dt))
{
long time = 0;
try
{
time = DisplayType.getDateFormat_JDBC().parse(in).getTime();
return new Timestamp(time);
}
catch (Exception e)
{
log.log(Level.SEVERE, in + "(" + in.getClass() + ")" + e);
time = DisplayType.getDateFormat(dt).parse(in).getTime();
}
return new Timestamp(time);
}
else if (dt == DisplayType.YesNo)
return Boolean.valueOf(in);
else
return in;
}
catch (Exception ex)
{
log.log(Level.SEVERE, "Object=" + in, ex);
return null;
}
} // parseValue
/**
* Delete
*/
private void cmd_delete()
{
advancedTable.stopEditor(false);
DefaultTableModel model = (DefaultTableModel)advancedTable.getModel();
int row = advancedTable.getSelectedRow();
if (row >= 0)
model.removeRow(row);
cmd_refresh();
advancedTable.requestFocusInWindow();
} // cmd_delete
/**
* Refresh
*/
private void cmd_refresh()
{
advancedTable.stopEditor(false);
int records = getNoOfRecords(m_query, true);
setStatusDB (records);
statusBar.setStatusLine("");
} // cmd_refresh
/**************************************************************************
* Get Query - Retrieve result
* @return String representation of query
*/
public MQuery getQuery()
{
MRole role = MRole.getDefault();
if (role.isQueryMax(getTotalRecords()) && !m_isCancel)
{
m_query = MQuery.getNoRecordQuery (m_tableName, false);
m_total = 0;
log.warning("Query - over max");
}
else
log.info("Query=" + m_query);
return m_query;
} // getQuery
/**
* Get Total Records
* @return no of records
*/
public int getTotalRecords()
{
return m_total;
} // getTotalRecords
/**
* Get the number of records of target tab
* @param query where clause for target tab
* @param alertZeroRecords show dialog if there are no records
* @return number of selected records;
* if the results are more then allowed this method will return 0
*/
private int getNoOfRecords (MQuery query, boolean alertZeroRecords)
{
log.config("" + query);
StringBuffer sql = new StringBuffer("SELECT COUNT(*) FROM ");
sql.append(m_tableName);
boolean hasWhere = false;
if (m_whereExtended != null && m_whereExtended.length() > 0)
{
sql.append(" WHERE ").append(m_whereExtended);
hasWhere = true;
}
if (query != null && query.isActive())
{
if (hasWhere)
sql.append(" AND ");
else
sql.append(" WHERE ");
sql.append(query.getWhereClause());
}
// Add Access
String finalSQL = MRole.getDefault().addAccessSQL(sql.toString(),
m_tableName, MRole.SQL_NOTQUALIFIED, MRole.SQL_RO);
finalSQL = Env.parseContext(Env.getCtx(), m_targetWindowNo, finalSQL, false);
Env.setContext(Env.getCtx(), m_targetWindowNo, TABNO, GridTab.CTX_FindSQL, finalSQL);
// Execute Qusery
m_total = 999999;
Statement stmt = null;
ResultSet rs = null;
try
{
stmt = DB.createStatement();
rs = stmt.executeQuery(finalSQL);
if (rs.next())
m_total = rs.getInt(1);
}
catch (SQLException e)
{
log.log(Level.SEVERE, finalSQL, e);
}
finally {
DB.close(rs, stmt);
rs = null; stmt = null;
}
MRole role = MRole.getDefault();
// No Records
if (m_total == 0 && alertZeroRecords)
ADialog.info(m_targetWindowNo, this, "FindZeroRecords");
// More then allowed
else if (query != null && role.isQueryMax(m_total))
{
ADialog.error(m_targetWindowNo, this, "FindOverMax",
m_total + " > " + role.getMaxQueryRecords());
m_total = 0; // return 0 if more then allowed - teo_sarca [ 1708717 ]
}
else
log.config("#" + m_total);
//
if (query != null)
statusBar.setStatusToolTip (query.getWhereClause());
return m_total;
} // getNoOfRecords
/**
* Display current count
* @param currentCount String representation of current/total
*/
private void setStatusDB (int currentCount)
{
String text = " " + currentCount + " / " + m_total + " ";
statusBar.setStatusDB(text);
} // setDtatusDB
/**************************************************************************
* Grid Status Changed.
* @param e DataStatueEvent
*/
public void dataStatusChanged (DataStatusEvent e)
{
log.config(e.getMessage());
// Action control
boolean changed = e.isChanged();
bIgnore.setEnabled(changed);
bNew.setEnabled(!changed);
bSave.setEnabled(changed);
bDelete.setEnabled(!changed);
} // statusChanged
/**
* Get Target MField
* @param columnName column name
* @return MField
*/
public GridField getTargetMField (String columnName)
{
if (columnName == null)
return null;
for (int c = 0; c < m_findFields.length; c++)
{
GridField field = m_findFields[c];
if (columnName.equals(field.getColumnName()))
return field;
}
return null;
} // getTargetMField
private boolean isSearchLike(GridField field)
{
return DisplayType.isText(field.getDisplayType())
&& MColumn.isSuggestSelectionColumn(field.getColumnName(), true);
}
private class ProxyRenderer implements TableCellRenderer
{
/**
* Creates a Find.ProxyRenderer.
*/
public ProxyRenderer(TableCellRenderer renderer)
{
this.m_renderer = renderer;
}
/** The renderer. */
private TableCellRenderer m_renderer;
/**
* @see javax.swing.table.TableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
*/
public Component getTableCellRendererComponent(final JTable table,
Object value, boolean isSelected, boolean hasFocus, final int row, final int col)
{
Component comp = m_renderer.getTableCellRendererComponent(table,
value, isSelected, hasFocus, row, col);
if (hasFocus && table.isCellEditable(row, col))
table.editCellAt(row, col);
return comp;
}
} // ProxyRenderer
} // Find