- implement virtual mode for high volume table for enhance scalability
This commit is contained in:
parent
8d11fd5139
commit
cfa4c6c050
|
@ -99,10 +99,11 @@ import org.compiere.util.ValueNamePair;
|
||||||
*/
|
*/
|
||||||
public class GridTab implements DataStatusListener, Evaluatee, Serializable
|
public class GridTab implements DataStatusListener, Evaluatee, Serializable
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = -5882167959482156252L;
|
private static final long serialVersionUID = 7198494041906579986L;
|
||||||
|
|
||||||
public static final String DEFAULT_STATUS_MESSAGE = "NavigateOrUpdate";
|
public static final String DEFAULT_STATUS_MESSAGE = "NavigateOrUpdate";
|
||||||
|
|
||||||
|
@ -112,13 +113,28 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
|
||||||
* MTab provides a property listener for changed rows and a
|
* MTab provides a property listener for changed rows and a
|
||||||
* DataStatusListener for communicating changes of the underlying data
|
* DataStatusListener for communicating changes of the underlying data
|
||||||
* @param vo Value Object
|
* @param vo Value Object
|
||||||
|
* @param w
|
||||||
*/
|
*/
|
||||||
public GridTab(GridTabVO vo, GridWindow w)
|
public GridTab(GridTabVO vo, GridWindow w)
|
||||||
|
{
|
||||||
|
this(vo, w, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create Tab (Model) from Value Object.
|
||||||
|
* <p>
|
||||||
|
* MTab provides a property listener for changed rows and a
|
||||||
|
* DataStatusListener for communicating changes of the underlying data
|
||||||
|
* @param vo Value Object
|
||||||
|
* @param w
|
||||||
|
* @param virtual
|
||||||
|
*/
|
||||||
|
public GridTab(GridTabVO vo, GridWindow w, boolean virtual)
|
||||||
{
|
{
|
||||||
m_window = w;
|
m_window = w;
|
||||||
m_vo = vo;
|
m_vo = vo;
|
||||||
// Create MTable
|
// Create MTable
|
||||||
m_mTable = new GridTable (m_vo.ctx, m_vo.AD_Table_ID, m_vo.TableName, m_vo.WindowNo, m_vo.TabNo, true);
|
m_mTable = new GridTable (m_vo.ctx, m_vo.AD_Table_ID, m_vo.TableName, m_vo.WindowNo, m_vo.TabNo, true, virtual);
|
||||||
m_mTable.setReadOnly(m_vo.IsReadOnly || m_vo.IsView);
|
m_mTable.setReadOnly(m_vo.IsReadOnly || m_vo.IsView);
|
||||||
m_mTable.setDeleteable(m_vo.IsDeleteable);
|
m_mTable.setDeleteable(m_vo.IsDeleteable);
|
||||||
// Load Tab
|
// Load Tab
|
||||||
|
@ -637,7 +653,7 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
|
||||||
value = Env.getContext(m_vo.ctx, m_vo.WindowNo, getParentTabNo(), lc, true);
|
value = Env.getContext(m_vo.ctx, m_vo.WindowNo, getParentTabNo(), lc, true);
|
||||||
if (value == null || value.length() == 0)
|
if (value == null || value.length() == 0)
|
||||||
value = Env.getContext(m_vo.ctx, m_vo.WindowNo, lc, true); // back compatibility
|
value = Env.getContext(m_vo.ctx, m_vo.WindowNo, lc, true); // back compatibility
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same link value?
|
// Same link value?
|
||||||
if (refresh)
|
if (refresh)
|
||||||
|
@ -3055,11 +3071,11 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
|
||||||
int parentLevel = currentLevel-1;
|
int parentLevel = currentLevel-1;
|
||||||
if (parentLevel < 0)
|
if (parentLevel < 0)
|
||||||
return tabNo;
|
return tabNo;
|
||||||
while (parentLevel != currentLevel)
|
while (parentLevel != currentLevel)
|
||||||
{
|
{
|
||||||
tabNo--;
|
tabNo--;
|
||||||
currentLevel = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, tabNo, GridTab.CTX_TabLevel);
|
currentLevel = Env.getContextAsInt(m_vo.ctx, m_vo.WindowNo, tabNo, GridTab.CTX_TabLevel);
|
||||||
}
|
}
|
||||||
return tabNo;
|
return tabNo;
|
||||||
}
|
}
|
||||||
} // GridTab
|
} // GridTab
|
||||||
|
|
|
@ -30,6 +30,9 @@ import java.sql.SQLException;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
@ -85,7 +88,7 @@ public class GridTable extends AbstractTableModel
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 4273775926021737068L;
|
private static final long serialVersionUID = 6148998589248950598L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JDBC Based Buffered Table
|
* JDBC Based Buffered Table
|
||||||
|
@ -99,6 +102,23 @@ public class GridTable extends AbstractTableModel
|
||||||
*/
|
*/
|
||||||
public GridTable(Properties ctx, int AD_Table_ID, String TableName, int WindowNo, int TabNo,
|
public GridTable(Properties ctx, int AD_Table_ID, String TableName, int WindowNo, int TabNo,
|
||||||
boolean withAccessControl)
|
boolean withAccessControl)
|
||||||
|
{
|
||||||
|
this(ctx, AD_Table_ID, TableName, WindowNo, TabNo, withAccessControl, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JDBC Based Buffered Table
|
||||||
|
*
|
||||||
|
* @param ctx Properties
|
||||||
|
* @param AD_Table_ID table id
|
||||||
|
* @param TableName table name
|
||||||
|
* @param WindowNo window no
|
||||||
|
* @param TabNo tab no
|
||||||
|
* @param withAccessControl if true adds AD_Client/Org restrictuins
|
||||||
|
* @param virtual use virtual table mode if table is mark as high volume
|
||||||
|
*/
|
||||||
|
public GridTable(Properties ctx, int AD_Table_ID, String TableName, int WindowNo, int TabNo,
|
||||||
|
boolean withAccessControl, boolean virtual)
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
log.info(TableName);
|
log.info(TableName);
|
||||||
|
@ -108,6 +128,7 @@ public class GridTable extends AbstractTableModel
|
||||||
m_WindowNo = WindowNo;
|
m_WindowNo = WindowNo;
|
||||||
m_TabNo = TabNo;
|
m_TabNo = TabNo;
|
||||||
m_withAccessControl = withAccessControl;
|
m_withAccessControl = withAccessControl;
|
||||||
|
m_virtual = virtual && MTable.get(ctx, AD_Table_ID).isHighVolume();
|
||||||
} // MTable
|
} // MTable
|
||||||
|
|
||||||
private static CLogger log = CLogger.getCLogger(GridTable.class.getName());
|
private static CLogger log = CLogger.getCLogger(GridTable.class.getName());
|
||||||
|
@ -120,6 +141,11 @@ public class GridTable extends AbstractTableModel
|
||||||
private boolean m_withAccessControl;
|
private boolean m_withAccessControl;
|
||||||
private boolean m_readOnly = true;
|
private boolean m_readOnly = true;
|
||||||
private boolean m_deleteable = true;
|
private boolean m_deleteable = true;
|
||||||
|
//virtual table state variables
|
||||||
|
private boolean m_virtual;
|
||||||
|
private int m_cacheStart;
|
||||||
|
private int m_cacheEnd;
|
||||||
|
public static final String CTX_KeyColumnName = "KeyColumnName";
|
||||||
//
|
//
|
||||||
|
|
||||||
/** Rowcount */
|
/** Rowcount */
|
||||||
|
@ -296,7 +322,7 @@ public class GridTable extends AbstractTableModel
|
||||||
select.append(" FROM ").append(m_tableName);
|
select.append(" FROM ").append(m_tableName);
|
||||||
m_SQL_Select = select.toString();
|
m_SQL_Select = select.toString();
|
||||||
m_SQL_Count = "SELECT COUNT(*) FROM " + m_tableName;
|
m_SQL_Count = "SELECT COUNT(*) FROM " + m_tableName;
|
||||||
//BF [ 2910358 ]
|
//BF [ 2910358 ]
|
||||||
//Restore the Original Value for Key Column Name based in Tab Context Value
|
//Restore the Original Value for Key Column Name based in Tab Context Value
|
||||||
int parentTabNo = getParentTabNo();
|
int parentTabNo = getParentTabNo();
|
||||||
String parentKey = Env.getContext(m_ctx, m_WindowNo, parentTabNo, GridTab.CTX_KeyColumnName, true);
|
String parentKey = Env.getContext(m_ctx, m_WindowNo, parentTabNo, GridTab.CTX_KeyColumnName, true);
|
||||||
|
@ -304,8 +330,8 @@ public class GridTable extends AbstractTableModel
|
||||||
String currKey = Env.getContext(m_ctx, m_WindowNo, parentKey);
|
String currKey = Env.getContext(m_ctx, m_WindowNo, parentKey);
|
||||||
if (valueKey != null && valueKey.length() > 0 && parentKey != null && parentKey.length() > 0 && ! currKey.equals(valueKey))
|
if (valueKey != null && valueKey.length() > 0 && parentKey != null && parentKey.length() > 0 && ! currKey.equals(valueKey))
|
||||||
{
|
{
|
||||||
Env.setContext(m_ctx, m_WindowNo, parentKey, valueKey);
|
Env.setContext(m_ctx, m_WindowNo, parentKey, valueKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuffer where = new StringBuffer("");
|
StringBuffer where = new StringBuffer("");
|
||||||
// WHERE
|
// WHERE
|
||||||
|
@ -356,7 +382,9 @@ public class GridTable extends AbstractTableModel
|
||||||
|
|
||||||
// ORDER BY
|
// ORDER BY
|
||||||
if (!m_orderClause.equals(""))
|
if (!m_orderClause.equals(""))
|
||||||
|
{
|
||||||
m_SQL += " ORDER BY " + m_orderClause;
|
m_SQL += " ORDER BY " + m_orderClause;
|
||||||
|
}
|
||||||
//
|
//
|
||||||
log.fine(m_SQL_Count);
|
log.fine(m_SQL_Count);
|
||||||
Env.setContext(m_ctx, m_WindowNo, m_TabNo, GridTab.CTX_SQL, m_SQL);
|
Env.setContext(m_ctx, m_WindowNo, m_TabNo, GridTab.CTX_SQL, m_SQL);
|
||||||
|
@ -538,6 +566,11 @@ public class GridTable extends AbstractTableModel
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_virtual)
|
||||||
|
{
|
||||||
|
verifyVirtual();
|
||||||
|
}
|
||||||
|
|
||||||
// create m_SQL and m_countSQL
|
// create m_SQL and m_countSQL
|
||||||
createSelectSql();
|
createSelectSql();
|
||||||
if (m_SQL == null || m_SQL.equals(""))
|
if (m_SQL == null || m_SQL.equals(""))
|
||||||
|
@ -549,10 +582,19 @@ public class GridTable extends AbstractTableModel
|
||||||
// Start Loading
|
// Start Loading
|
||||||
m_loader = new Loader();
|
m_loader = new Loader();
|
||||||
m_rowCount = m_loader.open(maxRows);
|
m_rowCount = m_loader.open(maxRows);
|
||||||
m_buffer = new ArrayList<Object[]>(m_rowCount+10);
|
if (m_virtual)
|
||||||
|
m_buffer = new ArrayList<Object[]>(210);
|
||||||
|
else
|
||||||
|
m_buffer = new ArrayList<Object[]>(m_rowCount+10);
|
||||||
m_sort = new ArrayList<MSort>(m_rowCount+10);
|
m_sort = new ArrayList<MSort>(m_rowCount+10);
|
||||||
|
m_cacheStart = m_cacheEnd = -1;
|
||||||
if (m_rowCount > 0)
|
if (m_rowCount > 0)
|
||||||
m_loader.start();
|
{
|
||||||
|
if (m_rowCount < 1000)
|
||||||
|
m_loader.run();
|
||||||
|
else
|
||||||
|
m_loader.start();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_loader.close();
|
m_loader.close();
|
||||||
m_open = true;
|
m_open = true;
|
||||||
|
@ -563,6 +605,24 @@ public class GridTable extends AbstractTableModel
|
||||||
return true;
|
return true;
|
||||||
} // open
|
} // open
|
||||||
|
|
||||||
|
private void verifyVirtual()
|
||||||
|
{
|
||||||
|
if (m_indexKeyColumn == -1)
|
||||||
|
{
|
||||||
|
m_virtual = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GridField[] fields = getFields();
|
||||||
|
for(int i = 0; i < fields.length; i++)
|
||||||
|
{
|
||||||
|
if (fields[i].isKey() && i != m_indexKeyColumn)
|
||||||
|
{
|
||||||
|
m_virtual = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait until async loader of Table and Lookup Fields is complete
|
* Wait until async loader of Table and Lookup Fields is complete
|
||||||
* Used for performance tests
|
* Used for performance tests
|
||||||
|
@ -659,6 +719,8 @@ public class GridTable extends AbstractTableModel
|
||||||
m_sort.clear();
|
m_sort.clear();
|
||||||
m_sort = null;
|
m_sort = null;
|
||||||
|
|
||||||
|
m_cacheStart = m_cacheEnd = -1;
|
||||||
|
|
||||||
if (finalCall)
|
if (finalCall)
|
||||||
dispose();
|
dispose();
|
||||||
|
|
||||||
|
@ -778,7 +840,7 @@ public class GridTable extends AbstractTableModel
|
||||||
for (int i = 0; i < m_sort.size(); i++)
|
for (int i = 0; i < m_sort.size(); i++)
|
||||||
{
|
{
|
||||||
MSort sort = (MSort)m_sort.get(i);
|
MSort sort = (MSort)m_sort.get(i);
|
||||||
Object[] rowData = (Object[])m_buffer.get(sort.index);
|
Object[] rowData = getDataAtRow(i);
|
||||||
if (rowData[col] == null)
|
if (rowData[col] == null)
|
||||||
sort.data = null;
|
sort.data = null;
|
||||||
else if (isLookup || isASI)
|
else if (isLookup || isASI)
|
||||||
|
@ -792,6 +854,17 @@ public class GridTable extends AbstractTableModel
|
||||||
MSort sort = new MSort(0, null);
|
MSort sort = new MSort(0, null);
|
||||||
sort.setSortAsc(ascending);
|
sort.setSortAsc(ascending);
|
||||||
Collections.sort(m_sort, sort);
|
Collections.sort(m_sort, sort);
|
||||||
|
if (m_virtual)
|
||||||
|
{
|
||||||
|
m_buffer.clear();
|
||||||
|
m_cacheStart = m_cacheEnd = -1;
|
||||||
|
|
||||||
|
//release sort memory
|
||||||
|
for (int i = 0; i < m_sort.size(); i++)
|
||||||
|
{
|
||||||
|
m_sort.get(i).data = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
// update UI
|
// update UI
|
||||||
fireTableDataChanged();
|
fireTableDataChanged();
|
||||||
// Info detected by MTab.dataStatusChanged and current row set to 0
|
// Info detected by MTab.dataStatusChanged and current row set to 0
|
||||||
|
@ -852,9 +925,9 @@ public class GridTable extends AbstractTableModel
|
||||||
|
|
||||||
// need to wait for data read into buffer
|
// need to wait for data read into buffer
|
||||||
int loops = 0;
|
int loops = 0;
|
||||||
while (row >= m_buffer.size() && m_loader.isAlive() && loops < 15)
|
while (row >= m_sort.size() && m_loader.isAlive() && loops < 15)
|
||||||
{
|
{
|
||||||
log.fine("Waiting for loader row=" + row + ", size=" + m_buffer.size());
|
log.fine("Waiting for loader row=" + row + ", size=" + m_sort.size());
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Thread.sleep(500); // 1/2 second
|
Thread.sleep(500); // 1/2 second
|
||||||
|
@ -865,15 +938,14 @@ public class GridTable extends AbstractTableModel
|
||||||
}
|
}
|
||||||
|
|
||||||
// empty buffer
|
// empty buffer
|
||||||
if (row >= m_buffer.size())
|
if (row >= m_sort.size())
|
||||||
{
|
{
|
||||||
// log.fine( "Empty buffer");
|
// log.fine( "Empty buffer");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return Data item
|
// return Data item
|
||||||
MSort sort = (MSort)m_sort.get(row);
|
Object[] rowData = getDataAtRow(row);
|
||||||
Object[] rowData = (Object[])m_buffer.get(sort.index);
|
|
||||||
// out of bounds
|
// out of bounds
|
||||||
if (rowData == null || col > rowData.length)
|
if (rowData == null || col > rowData.length)
|
||||||
{
|
{
|
||||||
|
@ -883,6 +955,116 @@ public class GridTable extends AbstractTableModel
|
||||||
return rowData[col];
|
return rowData[col];
|
||||||
} // getValueAt
|
} // getValueAt
|
||||||
|
|
||||||
|
private Object[] getDataAtRow(int row)
|
||||||
|
{
|
||||||
|
MSort sort = (MSort)m_sort.get(row);
|
||||||
|
Object[] rowData = null;
|
||||||
|
if (m_virtual)
|
||||||
|
{
|
||||||
|
int bufferrow = -1;
|
||||||
|
if (sort.index != -1 && (row < m_cacheStart || row > m_cacheEnd))
|
||||||
|
{
|
||||||
|
fillBuffer(row);
|
||||||
|
}
|
||||||
|
bufferrow = row - m_cacheStart;
|
||||||
|
|
||||||
|
rowData = (Object[])m_buffer.get(bufferrow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rowData = (Object[])m_buffer.get(sort.index);
|
||||||
|
}
|
||||||
|
return rowData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDataAtRow(int row, Object[] rowData) {
|
||||||
|
MSort sort = m_sort.get(row);
|
||||||
|
if (m_virtual)
|
||||||
|
{
|
||||||
|
int bufferrow = -1;
|
||||||
|
if (sort.index != -1 && (row < m_cacheStart || row > m_cacheEnd))
|
||||||
|
{
|
||||||
|
fillBuffer(row);
|
||||||
|
}
|
||||||
|
bufferrow = row - m_cacheStart;
|
||||||
|
m_buffer.set(bufferrow, rowData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_buffer.set(sort.index, rowData);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillBuffer(int start)
|
||||||
|
{
|
||||||
|
//adjust start if needed
|
||||||
|
if (start > 0)
|
||||||
|
{
|
||||||
|
if (start + 200 >= m_sort.size())
|
||||||
|
{
|
||||||
|
start = start - (200 - ( m_sort.size() - start ));
|
||||||
|
if (start < 0)
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StringBuffer sql = new StringBuffer();
|
||||||
|
sql.append(m_SQL_Select)
|
||||||
|
.append(" WHERE ")
|
||||||
|
.append(getKeyColumnName())
|
||||||
|
.append(" IN (");
|
||||||
|
m_cacheStart = start;
|
||||||
|
m_cacheEnd = m_cacheStart - 1;
|
||||||
|
Map<Integer, Integer>rowmap = new LinkedHashMap<Integer, Integer>(200);
|
||||||
|
for(int i = start; i < start+200 && i < m_sort.size(); i++)
|
||||||
|
{
|
||||||
|
if(i > start)
|
||||||
|
sql.append(",");
|
||||||
|
sql.append(m_sort.get(i).index);
|
||||||
|
rowmap.put(m_sort.get(i).index, i);
|
||||||
|
}
|
||||||
|
sql.append(")");
|
||||||
|
m_buffer = new ArrayList<Object[]>(210);
|
||||||
|
for(int i = 0; i < 200; i++)
|
||||||
|
m_buffer.add(null);
|
||||||
|
PreparedStatement stmt = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stmt = DB.prepareStatement(sql.toString(), null);
|
||||||
|
rs = stmt.executeQuery();
|
||||||
|
while(rs.next())
|
||||||
|
{
|
||||||
|
Object[] data = readData(rs);
|
||||||
|
int row = rowmap.remove(data[m_indexKeyColumn]);
|
||||||
|
m_buffer.set(row - m_cacheStart, data);
|
||||||
|
m_cacheEnd++;
|
||||||
|
}
|
||||||
|
if (!rowmap.isEmpty())
|
||||||
|
{
|
||||||
|
List<Integer> toremove = new ArrayList<Integer>();
|
||||||
|
for(Map.Entry<Integer, Integer> entry : rowmap.entrySet())
|
||||||
|
{
|
||||||
|
toremove.add(entry.getValue());
|
||||||
|
}
|
||||||
|
Collections.reverse(toremove);
|
||||||
|
for(Integer row : toremove)
|
||||||
|
{
|
||||||
|
m_sort.remove(row);
|
||||||
|
m_buffer.remove(row - m_cacheStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SQLException e)
|
||||||
|
{
|
||||||
|
log.log(Level.SEVERE, e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
DB.close(rs, stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicate that there will be a change
|
* Indicate that there will be a change
|
||||||
* @param changed changed
|
* @param changed changed
|
||||||
|
@ -958,8 +1140,8 @@ public class GridTable extends AbstractTableModel
|
||||||
m_oldValue[2] = oldValue;
|
m_oldValue[2] = oldValue;
|
||||||
|
|
||||||
// Set Data item
|
// Set Data item
|
||||||
MSort sort = (MSort)m_sort.get(row);
|
|
||||||
Object[] rowData = (Object[])m_buffer.get(sort.index);
|
Object[] rowData = getDataAtRow(row);
|
||||||
m_rowChanged = row;
|
m_rowChanged = row;
|
||||||
|
|
||||||
/** Selection
|
/** Selection
|
||||||
|
@ -981,7 +1163,7 @@ public class GridTable extends AbstractTableModel
|
||||||
|
|
||||||
// save & update
|
// save & update
|
||||||
rowData[col] = value;
|
rowData[col] = value;
|
||||||
m_buffer.set(sort.index, rowData);
|
setDataAtRow(row, rowData);
|
||||||
// update Table
|
// update Table
|
||||||
fireTableCellUpdated(row, col);
|
fireTableCellUpdated(row, col);
|
||||||
// update MField
|
// update MField
|
||||||
|
@ -1127,6 +1309,8 @@ public class GridTable extends AbstractTableModel
|
||||||
// Value not changed
|
// Value not changed
|
||||||
if (m_rowData == null)
|
if (m_rowData == null)
|
||||||
{
|
{
|
||||||
|
//reset out of sync variable
|
||||||
|
m_rowChanged = -1;
|
||||||
log.fine("No Changes");
|
log.fine("No Changes");
|
||||||
return SAVE_ERROR;
|
return SAVE_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -1180,8 +1364,7 @@ public class GridTable extends AbstractTableModel
|
||||||
}
|
}
|
||||||
|
|
||||||
// get updated row data
|
// get updated row data
|
||||||
MSort sort = (MSort)m_sort.get(m_rowChanged);
|
Object[] rowData = getDataAtRow(m_rowChanged);
|
||||||
Object[] rowData = (Object[])m_buffer.get(sort.index);
|
|
||||||
|
|
||||||
// Check Mandatory
|
// Check Mandatory
|
||||||
String missingColumns = getMandatory(rowData);
|
String missingColumns = getMandatory(rowData);
|
||||||
|
@ -1714,7 +1897,12 @@ public class GridTable extends AbstractTableModel
|
||||||
{
|
{
|
||||||
rowDataDB = readData(rs);
|
rowDataDB = readData(rs);
|
||||||
// update buffer
|
// update buffer
|
||||||
m_buffer.set(sort.index, rowDataDB);
|
setDataAtRow(m_rowChanged, rowDataDB);
|
||||||
|
if (m_virtual)
|
||||||
|
{
|
||||||
|
MSort sort = m_sort.get(m_rowChanged);
|
||||||
|
sort.index = getKeyID(m_rowChanged);
|
||||||
|
}
|
||||||
fireTableRowsUpdated(m_rowChanged, m_rowChanged);
|
fireTableRowsUpdated(m_rowChanged, m_rowChanged);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1764,8 +1952,7 @@ public class GridTable extends AbstractTableModel
|
||||||
{
|
{
|
||||||
log.fine("ID=" + Record_ID);
|
log.fine("ID=" + Record_ID);
|
||||||
//
|
//
|
||||||
MSort sort = (MSort)m_sort.get(m_rowChanged);
|
Object[] rowData = getDataAtRow(m_rowChanged);
|
||||||
Object[] rowData = (Object[])m_buffer.get(sort.index);
|
|
||||||
//
|
//
|
||||||
MTable table = MTable.get (m_ctx, m_AD_Table_ID);
|
MTable table = MTable.get (m_ctx, m_AD_Table_ID);
|
||||||
PO po = null;
|
PO po = null;
|
||||||
|
@ -1874,7 +2061,12 @@ public class GridTable extends AbstractTableModel
|
||||||
{
|
{
|
||||||
Object[] rowDataDB = readData(rs);
|
Object[] rowDataDB = readData(rs);
|
||||||
// update buffer
|
// update buffer
|
||||||
m_buffer.set(sort.index, rowDataDB);
|
setDataAtRow(m_rowChanged, rowDataDB);
|
||||||
|
if (m_virtual)
|
||||||
|
{
|
||||||
|
MSort sort = m_sort.get(m_rowChanged);
|
||||||
|
sort.index = getKeyID(m_rowChanged);
|
||||||
|
}
|
||||||
fireTableRowsUpdated(m_rowChanged, m_rowChanged);
|
fireTableRowsUpdated(m_rowChanged, m_rowChanged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2167,12 +2359,21 @@ public class GridTable extends AbstractTableModel
|
||||||
m_compareDB = true;
|
m_compareDB = true;
|
||||||
m_newRow = currentRow + 1;
|
m_newRow = currentRow + 1;
|
||||||
// if there is no record, the current row could be 0 (and not -1)
|
// if there is no record, the current row could be 0 (and not -1)
|
||||||
if (m_buffer.size() < m_newRow)
|
if (m_sort.size() < m_newRow)
|
||||||
m_newRow = m_buffer.size();
|
m_newRow = m_sort.size();
|
||||||
|
|
||||||
// add Data at end of buffer
|
// add Data at end of buffer
|
||||||
MSort newSort = new MSort(m_buffer.size(), null); // index
|
MSort newSort = m_virtual
|
||||||
m_buffer.add(rowData);
|
? new MSort(-1, null)
|
||||||
|
: new MSort(m_sort.size(), null); // index
|
||||||
|
if (m_virtual)
|
||||||
|
{
|
||||||
|
m_buffer.add(m_newRow, rowData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_buffer.add(rowData);
|
||||||
|
}
|
||||||
// add Sort pointer
|
// add Sort pointer
|
||||||
m_sort.add(m_newRow, newSort);
|
m_sort.add(m_newRow, newSort);
|
||||||
m_rowCount++;
|
m_rowCount++;
|
||||||
|
@ -2181,8 +2382,7 @@ public class GridTable extends AbstractTableModel
|
||||||
if (copyCurrent)
|
if (copyCurrent)
|
||||||
{
|
{
|
||||||
boolean hasDocTypeTargetField = (getField("C_DocTypeTarget_ID") != null);
|
boolean hasDocTypeTargetField = (getField("C_DocTypeTarget_ID") != null);
|
||||||
MSort sort = (MSort) m_sort.get(currentRow);
|
Object[] origData = getDataAtRow(currentRow);
|
||||||
Object[] origData = (Object[])m_buffer.get(sort.index);
|
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
GridField field = (GridField)m_fields.get(i);
|
GridField field = (GridField)m_fields.get(i);
|
||||||
|
@ -2280,7 +2480,7 @@ public class GridTable extends AbstractTableModel
|
||||||
// fireDataStatusEvent(Log.retrieveError());
|
// fireDataStatusEvent(Log.retrieveError());
|
||||||
|
|
||||||
MSort sort = (MSort)m_sort.get(row);
|
MSort sort = (MSort)m_sort.get(row);
|
||||||
Object[] rowData = (Object[])m_buffer.get(sort.index);
|
Object[] rowData = getDataAtRow(row);
|
||||||
//
|
//
|
||||||
MTable table = MTable.get (m_ctx, m_AD_Table_ID);
|
MTable table = MTable.get (m_ctx, m_AD_Table_ID);
|
||||||
PO po = null;
|
PO po = null;
|
||||||
|
@ -2347,19 +2547,31 @@ public class GridTable extends AbstractTableModel
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Sort
|
// Get Sort
|
||||||
int bufferRow = sort.index;
|
int bufferRow = m_virtual
|
||||||
|
? row - m_cacheStart
|
||||||
|
: sort.index;
|
||||||
// Delete row in Buffer and shifts all below up
|
// Delete row in Buffer and shifts all below up
|
||||||
m_buffer.remove(bufferRow);
|
m_buffer.remove(bufferRow);
|
||||||
m_rowCount--;
|
m_rowCount--;
|
||||||
|
|
||||||
// Delete row in Sort
|
// Delete row in Sort
|
||||||
m_sort.remove(row);
|
m_sort.remove(row);
|
||||||
// Correct pointer in Sort
|
if (!m_virtual)
|
||||||
for (int i = 0; i < m_sort.size(); i++)
|
|
||||||
{
|
{
|
||||||
MSort ptr = (MSort)m_sort.get(i);
|
// Correct pointer in Sort
|
||||||
if (ptr.index > bufferRow)
|
for (int i = 0; i < m_sort.size(); i++)
|
||||||
ptr.index--; // move up
|
{
|
||||||
|
MSort ptr = (MSort)m_sort.get(i);
|
||||||
|
if (ptr.index > bufferRow)
|
||||||
|
ptr.index--; // move up
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_cacheStart == row)
|
||||||
|
m_cacheStart++;
|
||||||
|
else
|
||||||
|
m_cacheEnd--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// inform
|
// inform
|
||||||
|
@ -2389,7 +2601,9 @@ public class GridTable extends AbstractTableModel
|
||||||
{
|
{
|
||||||
// Get Sort
|
// Get Sort
|
||||||
MSort sort = (MSort)m_sort.get(m_newRow);
|
MSort sort = (MSort)m_sort.get(m_newRow);
|
||||||
int bufferRow = sort.index;
|
int bufferRow = m_virtual
|
||||||
|
? m_buffer.size() - 1
|
||||||
|
: sort.index;
|
||||||
// Delete row in Buffer and shifts all below up
|
// Delete row in Buffer and shifts all below up
|
||||||
m_buffer.remove(bufferRow);
|
m_buffer.remove(bufferRow);
|
||||||
m_rowCount--;
|
m_rowCount--;
|
||||||
|
@ -2408,8 +2622,7 @@ public class GridTable extends AbstractTableModel
|
||||||
// update buffer
|
// update buffer
|
||||||
if (m_rowData != null)
|
if (m_rowData != null)
|
||||||
{
|
{
|
||||||
MSort sort = (MSort)m_sort.get(m_rowChanged);
|
setDataAtRow(m_rowChanged, m_rowData);
|
||||||
m_buffer.set(sort.index, m_rowData);
|
|
||||||
}
|
}
|
||||||
m_changed = false;
|
m_changed = false;
|
||||||
m_rowData = null;
|
m_rowData = null;
|
||||||
|
@ -2435,7 +2648,7 @@ public class GridTable extends AbstractTableModel
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MSort sort = (MSort)m_sort.get(row);
|
MSort sort = (MSort)m_sort.get(row);
|
||||||
Object[] rowData = (Object[])m_buffer.get(sort.index);
|
Object[] rowData = getDataAtRow(row);
|
||||||
|
|
||||||
// ignore
|
// ignore
|
||||||
dataIgnore();
|
dataIgnore();
|
||||||
|
@ -2472,7 +2685,7 @@ public class GridTable extends AbstractTableModel
|
||||||
}
|
}
|
||||||
|
|
||||||
// update buffer
|
// update buffer
|
||||||
m_buffer.set(sort.index, rowDataDB);
|
setDataAtRow(row, rowDataDB);
|
||||||
// info
|
// info
|
||||||
m_rowData = null;
|
m_rowData = null;
|
||||||
m_changed = false;
|
m_changed = false;
|
||||||
|
@ -3045,14 +3258,24 @@ public class GridTable extends AbstractTableModel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Get Data
|
// Get Data
|
||||||
Object[] rowData = readData(m_rs);
|
int recordId = 0;
|
||||||
|
Object[] rowData = null;
|
||||||
|
if (m_virtual)
|
||||||
|
recordId = m_rs.getInt(getKeyColumnName());
|
||||||
|
else
|
||||||
|
rowData = readData(m_rs);
|
||||||
// add Data
|
// add Data
|
||||||
MSort sort = new MSort(m_buffer.size(), null); // index
|
MSort sort = m_virtual
|
||||||
m_buffer.add(rowData);
|
? new MSort(recordId, null)
|
||||||
|
: new MSort(m_buffer.size(), null); // index
|
||||||
|
if (!m_virtual)
|
||||||
|
{
|
||||||
|
m_buffer.add(rowData);
|
||||||
|
}
|
||||||
m_sort.add(sort);
|
m_sort.add(sort);
|
||||||
|
|
||||||
// Statement all 250 rows & sleep
|
// Statement all 1000 rows & sleep
|
||||||
if (m_buffer.size() % 250 == 0)
|
if (m_sort.size() % 1000 == 0)
|
||||||
{
|
{
|
||||||
// give the other processes a chance
|
// give the other processes a chance
|
||||||
try
|
try
|
||||||
|
@ -3067,7 +3290,7 @@ public class GridTable extends AbstractTableModel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DataStatusEvent evt = createDSE();
|
DataStatusEvent evt = createDSE();
|
||||||
evt.setLoading(m_buffer.size());
|
evt.setLoading(m_sort.size());
|
||||||
fireDataStatusChanged(evt);
|
fireDataStatusChanged(evt);
|
||||||
}
|
}
|
||||||
} // while(rs.next())
|
} // while(rs.next())
|
||||||
|
@ -3253,11 +3476,11 @@ public class GridTable extends AbstractTableModel
|
||||||
int parentLevel = currentLevel-1;
|
int parentLevel = currentLevel-1;
|
||||||
if (parentLevel < 0)
|
if (parentLevel < 0)
|
||||||
return tabNo;
|
return tabNo;
|
||||||
while (parentLevel != currentLevel)
|
while (parentLevel != currentLevel)
|
||||||
{
|
{
|
||||||
tabNo--;
|
tabNo--;
|
||||||
currentLevel = Env.getContextAsInt(m_ctx, m_WindowNo, tabNo, GridTab.CTX_TabLevel);
|
currentLevel = Env.getContextAsInt(m_ctx, m_WindowNo, tabNo, GridTab.CTX_TabLevel);
|
||||||
}
|
}
|
||||||
return tabNo;
|
return tabNo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,28 +69,53 @@ public class GridWindow implements Serializable
|
||||||
* @return window or null if not found
|
* @return window or null if not found
|
||||||
*/
|
*/
|
||||||
public static GridWindow get (Properties ctx, int WindowNo, int AD_Window_ID)
|
public static GridWindow get (Properties ctx, int WindowNo, int AD_Window_ID)
|
||||||
|
{
|
||||||
|
return get(ctx, WindowNo, AD_Window_ID, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Grid Window
|
||||||
|
* @param ctx context
|
||||||
|
* @param WindowNo window no for ctx
|
||||||
|
* @param AD_Window_ID window id
|
||||||
|
* @param virtual
|
||||||
|
* @return window or null if not found
|
||||||
|
*/
|
||||||
|
public static GridWindow get (Properties ctx, int WindowNo, int AD_Window_ID, boolean virtual)
|
||||||
{
|
{
|
||||||
log.config("Window=" + WindowNo + ", AD_Window_ID=" + AD_Window_ID);
|
log.config("Window=" + WindowNo + ", AD_Window_ID=" + AD_Window_ID);
|
||||||
GridWindowVO mWindowVO = GridWindowVO.create (Env.getCtx(), WindowNo, AD_Window_ID);
|
GridWindowVO mWindowVO = GridWindowVO.create (Env.getCtx(), WindowNo, AD_Window_ID);
|
||||||
if (mWindowVO == null)
|
if (mWindowVO == null)
|
||||||
return null;
|
return null;
|
||||||
return new GridWindow(mWindowVO);
|
return new GridWindow(mWindowVO, virtual);
|
||||||
} // get
|
} // get
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param vo value object
|
* @param vo value object
|
||||||
*/
|
*/
|
||||||
public GridWindow (GridWindowVO vo)
|
public GridWindow (GridWindowVO vo)
|
||||||
|
{
|
||||||
|
this(vo, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Constructor
|
||||||
|
* @param vo value object
|
||||||
|
* @param virtual
|
||||||
|
*/
|
||||||
|
public GridWindow (GridWindowVO vo, boolean virtual)
|
||||||
{
|
{
|
||||||
m_vo = vo;
|
m_vo = vo;
|
||||||
|
m_virtual = virtual;
|
||||||
if (loadTabData())
|
if (loadTabData())
|
||||||
enableEvents();
|
enableEvents();
|
||||||
} // MWindow
|
} // MWindow
|
||||||
|
|
||||||
/** Value Object */
|
/** Value Object */
|
||||||
private GridWindowVO m_vo;
|
private GridWindowVO m_vo;
|
||||||
|
/** use virtual table */
|
||||||
|
private boolean m_virtual;
|
||||||
/** Tabs */
|
/** Tabs */
|
||||||
private ArrayList<GridTab> m_tabs = new ArrayList<GridTab>();
|
private ArrayList<GridTab> m_tabs = new ArrayList<GridTab>();
|
||||||
/** Model last updated */
|
/** Model last updated */
|
||||||
|
@ -141,7 +166,7 @@ public class GridWindow implements Serializable
|
||||||
GridTabVO mTabVO = (GridTabVO)m_vo.Tabs.get(t);
|
GridTabVO mTabVO = (GridTabVO)m_vo.Tabs.get(t);
|
||||||
if (mTabVO != null)
|
if (mTabVO != null)
|
||||||
{
|
{
|
||||||
GridTab mTab = new GridTab(mTabVO, this);
|
GridTab mTab = new GridTab(mTabVO, this, m_virtual);
|
||||||
m_tabs.add(mTab);
|
m_tabs.add(mTab);
|
||||||
}
|
}
|
||||||
} // for all tabs
|
} // for all tabs
|
||||||
|
|
|
@ -277,7 +277,7 @@ public abstract class AbstractADWindowPanel extends AbstractUIPart implements To
|
||||||
"AccessTableNoView")
|
"AccessTableNoView")
|
||||||
+ "(No Window Model Info)");
|
+ "(No Window Model Info)");
|
||||||
}
|
}
|
||||||
gridWindow = new GridWindow(gWindowVO);
|
gridWindow = new GridWindow(gWindowVO, true);
|
||||||
title = gridWindow.getName();
|
title = gridWindow.getName();
|
||||||
|
|
||||||
// Set SO/AutoNew for Window
|
// Set SO/AutoNew for Window
|
||||||
|
@ -1519,7 +1519,7 @@ public abstract class AbstractADWindowPanel extends AbstractUIPart implements To
|
||||||
if (!getComponent().getDesktop().isServerPushEnabled())
|
if (!getComponent().getDesktop().isServerPushEnabled())
|
||||||
getComponent().getDesktop().enableServerPush(true);
|
getComponent().getDesktop().enableServerPush(true);
|
||||||
|
|
||||||
ProcessModalDialog dialog = new ProcessModalDialog(null,this.getTitle(),this,0,
|
ProcessModalDialog dialog = new ProcessModalDialog(this,0,
|
||||||
AD_Process_ID,table_ID, record_ID, true);
|
AD_Process_ID,table_ID, record_ID, true);
|
||||||
if (dialog.isValid()) {
|
if (dialog.isValid()) {
|
||||||
dialog.setPosition("center");
|
dialog.setPosition("center");
|
||||||
|
@ -1905,8 +1905,7 @@ public abstract class AbstractADWindowPanel extends AbstractUIPart implements To
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ProcessModalDialog dialog = new ProcessModalDialog(null,
|
ProcessModalDialog dialog = new ProcessModalDialog(this, curWindowNo,
|
||||||
Env.getHeader(ctx, curWindowNo), this, curWindowNo,
|
|
||||||
wButton.getProcess_ID(), table_ID, record_ID, startWOasking);
|
wButton.getProcess_ID(), table_ID, record_ID, startWOasking);
|
||||||
|
|
||||||
if (dialog.isValid())
|
if (dialog.isValid())
|
||||||
|
|
Loading…
Reference in New Issue