IDEMPIERE-3673 Implement Paging for Related Info Window
This commit is contained in:
parent
646fc5ee7d
commit
8949bc4b46
|
@ -3,13 +3,14 @@
|
||||||
*/
|
*/
|
||||||
package org.adempiere.webui.info;
|
package org.adempiere.webui.info;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -32,7 +33,6 @@ import org.adempiere.webui.component.EditorBox;
|
||||||
import org.adempiere.webui.component.Grid;
|
import org.adempiere.webui.component.Grid;
|
||||||
import org.adempiere.webui.component.GridFactory;
|
import org.adempiere.webui.component.GridFactory;
|
||||||
import org.adempiere.webui.component.Label;
|
import org.adempiere.webui.component.Label;
|
||||||
import org.adempiere.webui.component.ListModelTable;
|
|
||||||
import org.adempiere.webui.component.Menupopup;
|
import org.adempiere.webui.component.Menupopup;
|
||||||
import org.adempiere.webui.component.Row;
|
import org.adempiere.webui.component.Row;
|
||||||
import org.adempiere.webui.component.Rows;
|
import org.adempiere.webui.component.Rows;
|
||||||
|
@ -95,10 +95,12 @@ import org.zkoss.zul.Div;
|
||||||
import org.zkoss.zul.ListModelList;
|
import org.zkoss.zul.ListModelList;
|
||||||
import org.zkoss.zul.Menuitem;
|
import org.zkoss.zul.Menuitem;
|
||||||
import org.zkoss.zul.North;
|
import org.zkoss.zul.North;
|
||||||
|
import org.zkoss.zul.Paging;
|
||||||
import org.zkoss.zul.Separator;
|
import org.zkoss.zul.Separator;
|
||||||
import org.zkoss.zul.South;
|
import org.zkoss.zul.South;
|
||||||
import org.zkoss.zul.Space;
|
import org.zkoss.zul.Space;
|
||||||
import org.zkoss.zul.Vbox;
|
import org.zkoss.zul.Vbox;
|
||||||
|
import org.zkoss.zul.Vlayout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AD_InfoWindow implementation
|
* AD_InfoWindow implementation
|
||||||
|
@ -123,6 +125,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
/** embedded Panel **/
|
/** embedded Panel **/
|
||||||
Tabbox embeddedPane = new Tabbox();
|
Tabbox embeddedPane = new Tabbox();
|
||||||
ArrayList <EmbedWinInfo> embeddedWinList = new ArrayList <EmbedWinInfo>();
|
ArrayList <EmbedWinInfo> embeddedWinList = new ArrayList <EmbedWinInfo>();
|
||||||
|
Map<Integer, RelatedInfoWindow> relatedMap = new HashMap<>();
|
||||||
|
|
||||||
/** Max Length of Fields */
|
/** Max Length of Fields */
|
||||||
public static final int FIELDLENGTH = 20;
|
public static final int FIELDLENGTH = 20;
|
||||||
|
@ -236,11 +239,12 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
// get index of link column
|
// get index of link column
|
||||||
indexData = p_layout.length + columnDataIndex.get(embed.getParentLinkColumnID());
|
indexData = p_layout.length + columnDataIndex.get(embed.getParentLinkColumnID());
|
||||||
}
|
}
|
||||||
refresh(contentPanel.getValueAt(row,indexData),embed);
|
RelatedInfoWindow relatedInfoWindow = relatedMap.get(embed.getInfowin().getAD_InfoWindow_ID());
|
||||||
|
relatedInfoWindow.refresh(contentPanel.getValueAt(row,indexData));
|
||||||
}// refresh for all
|
}// refresh for all
|
||||||
}else{
|
}else{
|
||||||
for (EmbedWinInfo embed : embeddedWinList) {
|
for (EmbedWinInfo embed : embeddedWinList) {
|
||||||
refresh(embed);
|
reset(embed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -630,6 +634,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
String s_sqlFrom = embedInfo.getFromClause();
|
String s_sqlFrom = embedInfo.getFromClause();
|
||||||
/** Where Clause */
|
/** Where Clause */
|
||||||
String s_sqlWhere = relatedInfo.getLinkColumnName() + "=?";
|
String s_sqlWhere = relatedInfo.getLinkColumnName() + "=?";
|
||||||
|
String s_sqlCount = "SELECT COUNT(*) FROM " + s_sqlFrom + " WHERE " + s_sqlWhere;
|
||||||
m_sqlEmbedded = embeddedTbl.prepareTable(s_layoutEmbedded, s_sqlFrom, s_sqlWhere, false, tableName);
|
m_sqlEmbedded = embeddedTbl.prepareTable(s_layoutEmbedded, s_sqlFrom, s_sqlWhere, false, tableName);
|
||||||
|
|
||||||
embeddedTbl.setMultiSelection(false);
|
embeddedTbl.setMultiSelection(false);
|
||||||
|
@ -639,10 +644,19 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
embeddedTbl.getModel().addTableModelListener(this);
|
embeddedTbl.getModel().addTableModelListener(this);
|
||||||
ZKUpdateUtil.setVflex(embeddedTbl, "1");
|
ZKUpdateUtil.setVflex(embeddedTbl, "1");
|
||||||
|
|
||||||
|
Paging embeddedPaging = new Paging();
|
||||||
|
embeddedPaging.setPageSize(pageSize);
|
||||||
|
embeddedPaging.setTotalSize(0);
|
||||||
|
ZKUpdateUtil.setHflex(embeddedPaging, "1");
|
||||||
|
embeddedPaging.setMold("os");
|
||||||
|
embeddedPaging.setVisible(false);
|
||||||
|
embeddedPaging.setSclass("infowindow-related-paging");
|
||||||
|
|
||||||
//Xolali - add embeddedTbl to list, add m_sqlembedded to list
|
//Xolali - add embeddedTbl to list, add m_sqlembedded to list
|
||||||
EmbedWinInfo ewinInfo = new EmbedWinInfo(embedInfo,embeddedTbl,m_sqlEmbedded,relatedInfo.getLinkColumnName(), relatedInfo.getLinkInfoColumn(), relatedInfo.getParentRelatedColumn_ID());
|
EmbedWinInfo ewinInfo = new EmbedWinInfo(embedInfo,embeddedTbl,m_sqlEmbedded,relatedInfo.getLinkColumnName(), relatedInfo.getLinkInfoColumn(), relatedInfo.getParentRelatedColumn_ID());
|
||||||
embeddedWinList.add(ewinInfo);
|
embeddedWinList.add(ewinInfo);
|
||||||
|
RelatedInfoWindow relatedInfoWindow = new RelatedInfoWindow(ewinInfo, this, embeddedPaging, s_sqlCount, s_layoutEmbedded);
|
||||||
|
relatedMap.put(embedInfo.getAD_InfoWindow_ID(), relatedInfoWindow);
|
||||||
|
|
||||||
MInfoWindow riw = (MInfoWindow) relatedInfo.getRelatedInfo();
|
MInfoWindow riw = (MInfoWindow) relatedInfo.getRelatedInfo();
|
||||||
String tabTitle;
|
String tabTitle;
|
||||||
|
@ -655,7 +669,11 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
Tabpanel desktopTabPanel = new Tabpanel();
|
Tabpanel desktopTabPanel = new Tabpanel();
|
||||||
//desktopTabPanel.
|
//desktopTabPanel.
|
||||||
ZKUpdateUtil.setHeight(desktopTabPanel, "100%");
|
ZKUpdateUtil.setHeight(desktopTabPanel, "100%");
|
||||||
desktopTabPanel.appendChild(embeddedTbl);
|
Vlayout vlayout = new Vlayout();
|
||||||
|
ZKUpdateUtil.setVflex(vlayout, "1");
|
||||||
|
desktopTabPanel.appendChild(vlayout);
|
||||||
|
vlayout.appendChild(embeddedPaging);
|
||||||
|
vlayout.appendChild(embeddedTbl);
|
||||||
tabPanels.appendChild(desktopTabPanel);
|
tabPanels.appendChild(desktopTabPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1055,7 +1073,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
* or parentLink of infoRelateWindow.
|
* or parentLink of infoRelateWindow.
|
||||||
*
|
*
|
||||||
* this function just add column name of hidden infoWindow to end of query
|
* this function just add column name of hidden infoWindow to end of query
|
||||||
* @param sqlMain main sql to append column
|
* @param sqlMain main sql to append column
|
||||||
* @param listInfoColumn list of PO contain infoColumnID, this infoColumnID will add to query
|
* @param listInfoColumn list of PO contain infoColumnID, this infoColumnID will add to query
|
||||||
* @return sql after append column
|
* @return sql after append column
|
||||||
*/
|
*/
|
||||||
|
@ -1176,7 +1194,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
div.setStyle("width :100%; height: 100%");
|
div.setStyle("width :100%; height: 100%");
|
||||||
ZKUpdateUtil.setVflex(div, "1");
|
ZKUpdateUtil.setVflex(div, "1");
|
||||||
ZKUpdateUtil.setHflex(div, "1");
|
ZKUpdateUtil.setHflex(div, "1");
|
||||||
div.appendChild(contentPanel);
|
div.appendChild(contentPanel);
|
||||||
|
|
||||||
Borderlayout inner = new Borderlayout();
|
Borderlayout inner = new Borderlayout();
|
||||||
ZKUpdateUtil.setWidth(inner, "100%");
|
ZKUpdateUtil.setWidth(inner, "100%");
|
||||||
|
@ -1889,56 +1907,10 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author xolali IDEMPIERE-1045
|
* reset to empty
|
||||||
* refresh(Object obj, EmbedWinInfo relatedInfo)
|
* @param relatedInfo
|
||||||
*/
|
*/
|
||||||
protected void refresh(Object obj, EmbedWinInfo relatedInfo)
|
protected void reset(EmbedWinInfo relatedInfo){
|
||||||
{
|
|
||||||
StringBuilder sql = new StringBuilder();
|
|
||||||
sql.append(relatedInfo.getInfoSql()); // delete get sql method from MInfoWindow
|
|
||||||
if (log.isLoggable(Level.FINEST))
|
|
||||||
log.finest(sql.toString());
|
|
||||||
|
|
||||||
Object linkPara = null;
|
|
||||||
if (obj != null && obj instanceof IDColumn){
|
|
||||||
IDColumn ID = (IDColumn) obj;
|
|
||||||
linkPara = ID.getRecord_ID();
|
|
||||||
}else if (obj != null){
|
|
||||||
linkPara = obj.toString();
|
|
||||||
}else {
|
|
||||||
//TODO:hard case
|
|
||||||
}
|
|
||||||
|
|
||||||
PreparedStatement pstmt = null;
|
|
||||||
ResultSet rs = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
pstmt = DB.prepareStatement(relatedInfo.getInfoSql(), null);
|
|
||||||
//TODO: implicit type conversion. will exception in some case must recheck
|
|
||||||
if (relatedInfo.getTypeDataOfLink().equals(String.class)){
|
|
||||||
pstmt.setString(1, (String)linkPara);
|
|
||||||
}else if (relatedInfo.getTypeDataOfLink().equals(int.class)){
|
|
||||||
pstmt.setInt(1, Integer.parseInt(linkPara.toString()));
|
|
||||||
|
|
||||||
}else{
|
|
||||||
pstmt.setObject(1, linkPara);
|
|
||||||
}
|
|
||||||
|
|
||||||
rs = pstmt.executeQuery();
|
|
||||||
loadEmbedded(rs, relatedInfo);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
log.log(Level.WARNING, sql.toString(), e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
DB.close(rs, pstmt);
|
|
||||||
rs = null; pstmt = null;
|
|
||||||
}
|
|
||||||
} // refresh
|
|
||||||
|
|
||||||
protected void refresh(EmbedWinInfo relatedInfo){
|
|
||||||
if (relatedInfo.getInfoTbl() != null){
|
if (relatedInfo.getInfoTbl() != null){
|
||||||
if (((WListbox)relatedInfo.getInfoTbl()).getModel() != null)
|
if (((WListbox)relatedInfo.getInfoTbl()).getModel() != null)
|
||||||
((WListbox)relatedInfo.getInfoTbl()).getModel().clear();
|
((WListbox)relatedInfo.getInfoTbl()).getModel().clear();
|
||||||
|
@ -1946,38 +1918,6 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
((WListbox)relatedInfo.getInfoTbl()).clear();
|
((WListbox)relatedInfo.getInfoTbl()).clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xolali IDEMPIERE-1045
|
|
||||||
* loadEmbedded(ResultSet rs, EmbedWinInfo info)
|
|
||||||
*/
|
|
||||||
public void loadEmbedded(ResultSet rs, EmbedWinInfo info) throws SQLException{
|
|
||||||
|
|
||||||
ListModelTable model;
|
|
||||||
ArrayList<ColumnInfo> list = new ArrayList<ColumnInfo>();
|
|
||||||
list = getInfoColumnslayout(info.getInfowin());
|
|
||||||
|
|
||||||
// Convert ArrayList to Array
|
|
||||||
ColumnInfo[] s_layoutEmbedded = new ColumnInfo[list.size()];
|
|
||||||
list.toArray(s_layoutEmbedded);
|
|
||||||
List<Object> data = new ArrayList<Object>();
|
|
||||||
ArrayList<Object> lines = new ArrayList<Object>();
|
|
||||||
|
|
||||||
while (rs.next())
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
data = readData(rs, s_layoutEmbedded);
|
|
||||||
} catch (SQLException e) {
|
|
||||||
//Xolali - Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
lines.add(data);
|
|
||||||
}
|
|
||||||
model = new ListModelTable(lines);
|
|
||||||
|
|
||||||
WListbox content = (WListbox) info.getInfoTbl();
|
|
||||||
content.setData(model, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author xolali IDEMPIERE-1045
|
* @author xolali IDEMPIERE-1045
|
||||||
|
@ -2005,79 +1945,6 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
return gridField;
|
return gridField;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ArrayList<Object> readData(ResultSet rs, ColumnInfo[] p_layout) throws SQLException {
|
|
||||||
|
|
||||||
int colOffset = 1; // columns start with 1
|
|
||||||
ArrayList<Object> data = new ArrayList<Object>();
|
|
||||||
for (int col = 0; col < p_layout.length; col++)
|
|
||||||
{
|
|
||||||
Object value = null;
|
|
||||||
Class<?> c = p_layout[col].getColClass();
|
|
||||||
int colIndex = col + colOffset;
|
|
||||||
if (c == IDColumn.class)
|
|
||||||
{
|
|
||||||
value = new IDColumn(rs.getInt(colIndex));
|
|
||||||
}
|
|
||||||
else if (c == Boolean.class)
|
|
||||||
value = new Boolean("Y".equals(rs.getString(colIndex)));
|
|
||||||
else if (c == Timestamp.class)
|
|
||||||
value = rs.getTimestamp(colIndex);
|
|
||||||
else if (c == BigDecimal.class)
|
|
||||||
value = rs.getBigDecimal(colIndex);
|
|
||||||
else if (c == Double.class)
|
|
||||||
value = new Double(rs.getDouble(colIndex));
|
|
||||||
else if (c == Integer.class)
|
|
||||||
value = new Integer(rs.getInt(colIndex));
|
|
||||||
else if (c == KeyNamePair.class)
|
|
||||||
{
|
|
||||||
if (p_layout[col].isKeyPairCol())
|
|
||||||
{
|
|
||||||
String display = rs.getString(colIndex);
|
|
||||||
int key = rs.getInt(colIndex+1);
|
|
||||||
if (! rs.wasNull()) {
|
|
||||||
value = new KeyNamePair(key, display);
|
|
||||||
}
|
|
||||||
colOffset++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int key = rs.getInt(colIndex);
|
|
||||||
if (! rs.wasNull()) {
|
|
||||||
WEditor editor = editorMap.get(p_layout[col].getColSQL()); // rework this, it will fail
|
|
||||||
if (editor != null)
|
|
||||||
{
|
|
||||||
editor.setValue(key);
|
|
||||||
value = new KeyNamePair(key, editor.getDisplayTextForGridView(key));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value = new KeyNamePair(key, Integer.toString(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (c == ValueNamePair.class)
|
|
||||||
{
|
|
||||||
String key = rs.getString(colIndex);
|
|
||||||
WEditor editor = editorMap.get(p_layout[col].getColSQL());
|
|
||||||
if (editor != null)
|
|
||||||
{
|
|
||||||
value = new ValueNamePair(key, editor.getDisplayTextForGridView(key));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value = new ValueNamePair(key, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value = rs.getString(colIndex);
|
|
||||||
}
|
|
||||||
data.add(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2093,7 +1960,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL
|
||||||
// cancel editor not display
|
// cancel editor not display
|
||||||
if (wEditor == null || !wEditor.isVisible() || wEditor.getGridField() == null){
|
if (wEditor == null || !wEditor.isVisible() || wEditor.getGridField() == null){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid = isValid & validateField (wEditor);
|
isValid = isValid & validateField (wEditor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,587 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Project: Trek Global ERP *
|
||||||
|
* Copyright (C) 2009-2018 Trek Global Corporation *
|
||||||
|
* 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. *
|
||||||
|
*****************************************************************************/
|
||||||
|
package org.adempiere.webui.info;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.webui.component.ListModelTable;
|
||||||
|
import org.adempiere.webui.component.WListItemRenderer;
|
||||||
|
import org.adempiere.webui.component.WListbox;
|
||||||
|
import org.adempiere.webui.editor.WEditor;
|
||||||
|
import org.compiere.minigrid.ColumnInfo;
|
||||||
|
import org.compiere.minigrid.EmbedWinInfo;
|
||||||
|
import org.compiere.minigrid.IDColumn;
|
||||||
|
import org.compiere.model.MSysConfig;
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.compiere.util.DB;
|
||||||
|
import org.compiere.util.KeyNamePair;
|
||||||
|
import org.compiere.util.Trx;
|
||||||
|
import org.compiere.util.Util;
|
||||||
|
import org.compiere.util.ValueNamePair;
|
||||||
|
import org.zkoss.zk.ui.event.Event;
|
||||||
|
import org.zkoss.zk.ui.event.EventListener;
|
||||||
|
import org.zkoss.zk.ui.event.Events;
|
||||||
|
import org.zkoss.zul.Paging;
|
||||||
|
import org.zkoss.zul.event.PagingEvent;
|
||||||
|
import org.zkoss.zul.event.ZulEvents;
|
||||||
|
import org.zkoss.zul.ext.Sortable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class RelatedInfoWindow implements EventListener<Event>, Sortable<Object>{
|
||||||
|
|
||||||
|
private final static int DEFAULT_PAGE_PRELOAD = 4;
|
||||||
|
|
||||||
|
private EmbedWinInfo info;
|
||||||
|
|
||||||
|
private int m_count;
|
||||||
|
private int pageNo;
|
||||||
|
private List<Object> cache;
|
||||||
|
private int cacheStart;
|
||||||
|
private int cacheEnd;
|
||||||
|
private Object parentId;
|
||||||
|
protected Paging paging;
|
||||||
|
protected Map<String, WEditor> editorMap = new HashMap<String, WEditor>();
|
||||||
|
private InfoWindow parentInfoWindow;
|
||||||
|
|
||||||
|
protected CLogger log = CLogger.getCLogger(getClass());
|
||||||
|
|
||||||
|
private ListModelTable model;
|
||||||
|
|
||||||
|
private String m_sqlUserOrder;
|
||||||
|
private boolean m_useDatabasePaging = false;
|
||||||
|
|
||||||
|
private String m_infoSqlCount;
|
||||||
|
protected int numPagePreLoad = MSysConfig.getIntValue(MSysConfig.ZK_INFO_NUM_PAGE_PRELOAD, DEFAULT_PAGE_PRELOAD);
|
||||||
|
protected boolean isHasNextPage = false;
|
||||||
|
|
||||||
|
private ColumnInfo[] columnsLayout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param infoWindow
|
||||||
|
* @param embeddedPaging
|
||||||
|
* @param layoutEmbedded
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public RelatedInfoWindow(EmbedWinInfo info, InfoWindow infoWindow, Paging embeddedPaging, String infoSqlCount, ColumnInfo[] layoutEmbedded) {
|
||||||
|
this.info = info;
|
||||||
|
parentInfoWindow = infoWindow;
|
||||||
|
this.paging = embeddedPaging;
|
||||||
|
m_infoSqlCount = infoSqlCount;
|
||||||
|
|
||||||
|
columnsLayout = layoutEmbedded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh(Object id) {
|
||||||
|
parentId = id;
|
||||||
|
|
||||||
|
|
||||||
|
cache = null;
|
||||||
|
cacheStart = cacheEnd = 0;
|
||||||
|
|
||||||
|
if (info.getInfowin().isLoadPageNum()) {
|
||||||
|
testCount();
|
||||||
|
} else {
|
||||||
|
m_count = Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
m_useDatabasePaging = (m_count > 1000 || m_count > (parentInfoWindow.getPageSize()*4));
|
||||||
|
|
||||||
|
renderItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testCount() {
|
||||||
|
m_count = 0;
|
||||||
|
Object linkPara = null;
|
||||||
|
if (parentId != null && parentId instanceof IDColumn){
|
||||||
|
IDColumn ID = (IDColumn) parentId;
|
||||||
|
linkPara = ID.getRecord_ID();
|
||||||
|
}else if (parentId != null){
|
||||||
|
linkPara = parentId.toString();
|
||||||
|
}
|
||||||
|
if (linkPara != null) {
|
||||||
|
if (info.getTypeDataOfLink().equals(String.class)){
|
||||||
|
m_count = DB.getSQLValue((String)null, m_infoSqlCount, (String)linkPara);
|
||||||
|
}else if (info.getTypeDataOfLink().equals(int.class)){
|
||||||
|
m_count = DB.getSQLValue((String)null, m_infoSqlCount, Integer.parseInt(linkPara.toString()));
|
||||||
|
}else{
|
||||||
|
m_count = DB.getSQLValue((String)null, m_infoSqlCount, linkPara);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderItems() {
|
||||||
|
int pageSize = parentInfoWindow.getPageSize();
|
||||||
|
WListbox contentPanel = (WListbox) info.getInfoTbl();
|
||||||
|
if (m_count > 0)
|
||||||
|
{
|
||||||
|
if (m_count > pageSize && paging != null)
|
||||||
|
{
|
||||||
|
paging.setVisible(true);
|
||||||
|
paging.setPageSize(pageSize);
|
||||||
|
paging.setTotalSize(m_count);
|
||||||
|
paging.setDetailed(false);
|
||||||
|
paging.addEventListener(ZulEvents.ON_PAGING, this);
|
||||||
|
|
||||||
|
List<Object> subList = readLine(0, pageSize);
|
||||||
|
model = new ListModelTable(subList);
|
||||||
|
model.setSorter(this);
|
||||||
|
model.setMultiple(false);
|
||||||
|
contentPanel.setData(model, null);
|
||||||
|
|
||||||
|
pageNo = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (paging != null)
|
||||||
|
{
|
||||||
|
paging.setTotalSize(m_count);
|
||||||
|
paging.setActivePage(0);
|
||||||
|
paging.setVisible(false);
|
||||||
|
pageNo = 0;
|
||||||
|
}
|
||||||
|
model = new ListModelTable(readLine(0, -1));
|
||||||
|
model.setSorter(this);
|
||||||
|
model.setMultiple(false);
|
||||||
|
contentPanel.setData(model, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (paging != null)
|
||||||
|
{
|
||||||
|
paging.setTotalSize(m_count);
|
||||||
|
paging.setActivePage(0);
|
||||||
|
paging.setVisible(false);
|
||||||
|
pageNo = 0;
|
||||||
|
}
|
||||||
|
model = new ListModelTable(new ArrayList<Object>());
|
||||||
|
model.setMultiple(false);
|
||||||
|
contentPanel.setData(model, null);
|
||||||
|
}
|
||||||
|
contentPanel.getParent().invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEvent(Event event) throws Exception {
|
||||||
|
if (event.getTarget() == paging)
|
||||||
|
{
|
||||||
|
WListbox contentPanel = (WListbox) info.getInfoTbl();
|
||||||
|
int pageSize = parentInfoWindow.getPageSize();
|
||||||
|
int pgNo = paging.getActivePage();
|
||||||
|
if (pgNo == paging.getPageCount()-1 && !info.getInfowin().isLoadPageNum()) {
|
||||||
|
testCount();
|
||||||
|
paging.setTotalSize(m_count);
|
||||||
|
pgNo = paging.getActivePage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageNo != pgNo)
|
||||||
|
{
|
||||||
|
|
||||||
|
contentPanel.clearSelection();
|
||||||
|
|
||||||
|
pageNo = pgNo;
|
||||||
|
int start = pageNo * pageSize;
|
||||||
|
int end = getOverIntValue ((long)start + pageSize, 1);
|
||||||
|
if (end >= m_count)
|
||||||
|
end = m_count;
|
||||||
|
List<Object> subList = readLine(start, end);
|
||||||
|
model = new ListModelTable(subList);
|
||||||
|
model.setSorter(this);
|
||||||
|
model.setMultiple(false);
|
||||||
|
contentPanel.setData(model, null);
|
||||||
|
|
||||||
|
contentPanel.setSelectedIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the cacheStart
|
||||||
|
*/
|
||||||
|
protected int getCacheStart() {
|
||||||
|
return cacheStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cacheStart the cacheStart to set
|
||||||
|
*/
|
||||||
|
private void setCacheStart(int cacheStart) {
|
||||||
|
this.cacheStart = cacheStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the cacheEnd
|
||||||
|
*/
|
||||||
|
protected int getCacheEnd() {
|
||||||
|
return cacheEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Object> getSubList (int fromIndex, int toIndex, List<Object> line){
|
||||||
|
if (toIndex > line.size())
|
||||||
|
toIndex = line.size();
|
||||||
|
|
||||||
|
if (fromIndex >= line.size())
|
||||||
|
fromIndex = line.size();
|
||||||
|
|
||||||
|
// case line.size = 0
|
||||||
|
if (fromIndex < 0)
|
||||||
|
fromIndex = 0;
|
||||||
|
|
||||||
|
return line.subList(fromIndex, toIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* when calculator value at bound, sometime value is overflow by data type
|
||||||
|
* this function calculator at high type for avoid it
|
||||||
|
* @param overValue
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private int getOverIntValue (long overValue){
|
||||||
|
return getOverIntValue (overValue, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* see {@link #getOverIntValue(long)}. when value over max_value set it near max_value.
|
||||||
|
* @param overValue
|
||||||
|
* @param extra
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private int getOverIntValue (long overValue, int extra){
|
||||||
|
if (overValue >= Integer.MAX_VALUE)
|
||||||
|
overValue = Integer.MAX_VALUE - extra;
|
||||||
|
|
||||||
|
return (int)overValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Object> readLine(int start, int end) {
|
||||||
|
int pageSize = parentInfoWindow.getPageSize();
|
||||||
|
|
||||||
|
//cacheStart & cacheEnd - 1 based index, start & end - 0 based index
|
||||||
|
if (getCacheStart() >= 1 && cacheEnd > getCacheStart())
|
||||||
|
{
|
||||||
|
if (m_useDatabasePaging)
|
||||||
|
{
|
||||||
|
if (start+1 >= getCacheStart() && end+1 <= cacheEnd)
|
||||||
|
{
|
||||||
|
return end == -1 ? cache : getSubList(start-getCacheStart()+1, end-getCacheStart()+1, cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (end >= cacheEnd || end <= 0)
|
||||||
|
{
|
||||||
|
end = cacheEnd;
|
||||||
|
}
|
||||||
|
return getSubList (start, end, cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setCacheStart(getOverIntValue((long)start + 1 - (pageSize * numPagePreLoad)));
|
||||||
|
if (getCacheStart() <= 0)
|
||||||
|
setCacheStart(1);
|
||||||
|
|
||||||
|
if (end == -1)
|
||||||
|
{
|
||||||
|
cacheEnd = m_count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cacheEnd = getOverIntValue(end + 1 + (pageSize * numPagePreLoad));
|
||||||
|
if (cacheEnd > m_count)
|
||||||
|
cacheEnd = m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache = new ArrayList<Object>();
|
||||||
|
|
||||||
|
PreparedStatement m_pstmt = null;
|
||||||
|
ResultSet m_rs = null;
|
||||||
|
String dataSql = null;
|
||||||
|
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
dataSql = info.getInfoSql();
|
||||||
|
if (!Util.isEmpty(m_sqlUserOrder)) {
|
||||||
|
dataSql = dataSql + m_sqlUserOrder;
|
||||||
|
}
|
||||||
|
isHasNextPage = false;
|
||||||
|
if (log.isLoggable(Level.FINER))
|
||||||
|
log.finer(dataSql);
|
||||||
|
Trx trx = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//https://jdbc.postgresql.org/documentation/head/query.html#query-with-cursor
|
||||||
|
String trxName = Trx.createTrxName("RelatedInfoLoad:");
|
||||||
|
trx = Trx.get(trxName, true);
|
||||||
|
trx.setDisplayName(getClass().getName()+"_readLine");
|
||||||
|
m_pstmt = DB.prepareStatement(dataSql, trxName);
|
||||||
|
Object linkPara = null;
|
||||||
|
if (parentId != null && parentId instanceof IDColumn){
|
||||||
|
IDColumn ID = (IDColumn) parentId;
|
||||||
|
linkPara = ID.getRecord_ID();
|
||||||
|
}else if (parentId != null){
|
||||||
|
linkPara = parentId.toString();
|
||||||
|
}
|
||||||
|
if (info.getTypeDataOfLink().equals(String.class)){
|
||||||
|
m_pstmt.setString(1, (String)linkPara);
|
||||||
|
}else if (info.getTypeDataOfLink().equals(int.class)){
|
||||||
|
m_pstmt.setInt(1, Integer.parseInt(linkPara.toString()));
|
||||||
|
|
||||||
|
}else{
|
||||||
|
m_pstmt.setObject(1, linkPara);
|
||||||
|
}
|
||||||
|
if (log.isLoggable(Level.FINE))
|
||||||
|
log.fine("Start query - " + (System.currentTimeMillis()-startTime) + "ms");
|
||||||
|
m_pstmt.setFetchSize(100);
|
||||||
|
m_rs = m_pstmt.executeQuery();
|
||||||
|
if (log.isLoggable(Level.FINE))
|
||||||
|
log.fine("End query - " + (System.currentTimeMillis()-startTime) + "ms");
|
||||||
|
//skips the row that we dont need if we can't use native db paging
|
||||||
|
if (end > start && m_useDatabasePaging && !DB.getDatabase().isPagingSupported())
|
||||||
|
{
|
||||||
|
for (int i = 0; i < getCacheStart() - 1; i++)
|
||||||
|
{
|
||||||
|
if (!m_rs.next())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rowPointer = getCacheStart()-1;
|
||||||
|
while (m_rs.next())
|
||||||
|
{
|
||||||
|
rowPointer++;
|
||||||
|
cache.add(readData(m_rs));
|
||||||
|
//check now of rows loaded, break if we hit the suppose end
|
||||||
|
if (m_useDatabasePaging && rowPointer >= cacheEnd)
|
||||||
|
{
|
||||||
|
isHasNextPage = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (SQLException e)
|
||||||
|
{
|
||||||
|
log.log(Level.SEVERE, dataSql, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
DB.close(m_rs, m_pstmt);
|
||||||
|
if (trx != null)
|
||||||
|
trx.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end > cacheEnd || end <= 0)
|
||||||
|
{
|
||||||
|
end = cacheEnd;
|
||||||
|
}
|
||||||
|
validateEndPage ();
|
||||||
|
|
||||||
|
if (end == -1)
|
||||||
|
{
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int fromIndex = start-getCacheStart()+1;
|
||||||
|
int toIndex = end-getCacheStart()+1;
|
||||||
|
return getSubList(fromIndex, toIndex, cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<Object> readData(ResultSet rs) throws SQLException {
|
||||||
|
|
||||||
|
int colOffset = 1; // columns start with 1
|
||||||
|
ArrayList<Object> data = new ArrayList<Object>();
|
||||||
|
for (int col = 0; col < columnsLayout.length; col++)
|
||||||
|
{
|
||||||
|
Object value = null;
|
||||||
|
Class<?> c = columnsLayout[col].getColClass();
|
||||||
|
int colIndex = col + colOffset;
|
||||||
|
if (c == IDColumn.class)
|
||||||
|
{
|
||||||
|
value = new IDColumn(rs.getInt(colIndex));
|
||||||
|
}
|
||||||
|
else if (c == Boolean.class)
|
||||||
|
value = new Boolean("Y".equals(rs.getString(colIndex)));
|
||||||
|
else if (c == Timestamp.class)
|
||||||
|
value = rs.getTimestamp(colIndex);
|
||||||
|
else if (c == BigDecimal.class)
|
||||||
|
value = rs.getBigDecimal(colIndex);
|
||||||
|
else if (c == Double.class)
|
||||||
|
value = new Double(rs.getDouble(colIndex));
|
||||||
|
else if (c == Integer.class)
|
||||||
|
value = new Integer(rs.getInt(colIndex));
|
||||||
|
else if (c == KeyNamePair.class)
|
||||||
|
{
|
||||||
|
if (columnsLayout[col].isKeyPairCol())
|
||||||
|
{
|
||||||
|
String display = rs.getString(colIndex);
|
||||||
|
int key = rs.getInt(colIndex+1);
|
||||||
|
if (! rs.wasNull()) {
|
||||||
|
value = new KeyNamePair(key, display);
|
||||||
|
}
|
||||||
|
colOffset++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int key = rs.getInt(colIndex);
|
||||||
|
if (! rs.wasNull()) {
|
||||||
|
WEditor editor = editorMap.get(columnsLayout[col].getColSQL()); // rework this, it will fail
|
||||||
|
if (editor != null)
|
||||||
|
{
|
||||||
|
editor.setValue(key);
|
||||||
|
value = new KeyNamePair(key, editor.getDisplayTextForGridView(key));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = new KeyNamePair(key, Integer.toString(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == ValueNamePair.class)
|
||||||
|
{
|
||||||
|
String key = rs.getString(colIndex);
|
||||||
|
WEditor editor = editorMap.get(columnsLayout[col].getColSQL());
|
||||||
|
if (editor != null)
|
||||||
|
{
|
||||||
|
value = new ValueNamePair(key, editor.getDisplayTextForGridView(key));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = new ValueNamePair(key, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = rs.getString(colIndex);
|
||||||
|
}
|
||||||
|
data.add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sort(Comparator<Object> cmpr, boolean ascending) {
|
||||||
|
|
||||||
|
WListItemRenderer.ColumnComparator lsc = (WListItemRenderer.ColumnComparator) cmpr;
|
||||||
|
if (m_useDatabasePaging)
|
||||||
|
{
|
||||||
|
int col = lsc.getColumnIndex();
|
||||||
|
String colsql = columnsLayout[col].getColSQL().trim();
|
||||||
|
int lastSpaceIdx = colsql.lastIndexOf(" ");
|
||||||
|
if (lastSpaceIdx > 0)
|
||||||
|
{
|
||||||
|
String tmp = colsql.substring(0, lastSpaceIdx).trim();
|
||||||
|
char last = tmp.charAt(tmp.length() - 1);
|
||||||
|
if (tmp.toLowerCase().endsWith("as"))
|
||||||
|
{
|
||||||
|
colsql = colsql.substring(lastSpaceIdx).trim();
|
||||||
|
}
|
||||||
|
else if (!(last == '*' || last == '-' || last == '+' || last == '/' || last == '>' || last == '<' || last == '='))
|
||||||
|
{
|
||||||
|
tmp = colsql.substring(lastSpaceIdx).trim();
|
||||||
|
if (tmp.startsWith("\"") && tmp.endsWith("\""))
|
||||||
|
{
|
||||||
|
colsql = colsql.substring(lastSpaceIdx).trim();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boolean hasAlias = true;
|
||||||
|
for(int i = 0; i < tmp.length(); i++)
|
||||||
|
{
|
||||||
|
char c = tmp.charAt(i);
|
||||||
|
if (Character.isLetterOrDigit(c))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hasAlias = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasAlias)
|
||||||
|
{
|
||||||
|
colsql = colsql.substring(lastSpaceIdx).trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_sqlUserOrder = " ORDER BY " + colsql;
|
||||||
|
if (!ascending)
|
||||||
|
m_sqlUserOrder += " DESC ";
|
||||||
|
refresh(parentId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Collections.sort(cache, lsc);
|
||||||
|
renderItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSortDirection(Comparator<Object> cmpr) {
|
||||||
|
return "natural";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* after query from database, process validate.
|
||||||
|
* if end page include in cache, process calculate total record
|
||||||
|
* if current page is out of page (no record is query) process query count to detect end page
|
||||||
|
*/
|
||||||
|
protected void validateEndPage (){
|
||||||
|
if (paging == null || info.getInfowin().isLoadPageNum())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!isHasNextPage){
|
||||||
|
int pageSize = parentInfoWindow.getPageSize();
|
||||||
|
int extraPage = ((cache.size() % pageSize > 0)?1:0);
|
||||||
|
int pageInCache = cache.size() / pageSize + extraPage;
|
||||||
|
|
||||||
|
if (pageInCache == 0 || pageInCache <= numPagePreLoad){
|
||||||
|
// selected page is out of page
|
||||||
|
testCount();
|
||||||
|
extraPage = ((m_count % pageSize > 0)?1:0);
|
||||||
|
pageInCache = m_count / pageSize + extraPage;
|
||||||
|
// this one will set current page to end page
|
||||||
|
paging.setTotalSize(m_count);
|
||||||
|
if (m_count <= pageSize)
|
||||||
|
paging.setVisible(false);
|
||||||
|
Event pagingEvent = new PagingEvent("onPaging", paging, paging.getPageCount() - 1);
|
||||||
|
Events.postEvent(pagingEvent);
|
||||||
|
}else if (pageInCache > numPagePreLoad){
|
||||||
|
// current page isn't end page. but page in cache has end page.
|
||||||
|
int prePage = pageNo - numPagePreLoad;
|
||||||
|
int readTotalRecord = (prePage > 0?prePage:0) * pageSize + cache.size();
|
||||||
|
paging.setTotalSize(readTotalRecord);
|
||||||
|
m_count = readTotalRecord;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2285,5 +2285,9 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
|
||||||
public void setGridfield(GridField m_gridfield) {
|
public void setGridfield(GridField m_gridfield) {
|
||||||
this.m_gridfield = m_gridfield;
|
this.m_gridfield = m_gridfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getPageSize() {
|
||||||
|
return pageSize;
|
||||||
|
}
|
||||||
} // Info
|
} // Info
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue