IDEMPIERE-3673 Implement Paging for Related Info Window

This commit is contained in:
Heng Sin Low 2018-04-02 18:54:06 +08:00
parent 646fc5ee7d
commit 8949bc4b46
3 changed files with 621 additions and 163 deletions

View File

@ -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);
} }

View File

@ -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;
}
}
}
}

View File

@ -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