com.qualogy.qafe.gwt.client.component.QPagingScrollTable.java Source code

Java tutorial

Introduction

Here is the source code for com.qualogy.qafe.gwt.client.component.QPagingScrollTable.java

Source

/**
 * Copyright 2008-2015 Qualogy Solutions B.V.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.qualogy.qafe.gwt.client.component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.gwt.mosaic.ui.client.MessageBox.MessageBoxType;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.gen2.event.dom.client.ScrollEvent;
import com.google.gwt.gen2.event.dom.client.ScrollHandler;
import com.google.gwt.gen2.table.client.ColumnDefinition;
import com.google.gwt.gen2.table.client.DefaultTableDefinition;
import com.google.gwt.gen2.table.client.FixedWidthFlexTable;
import com.google.gwt.gen2.table.client.FixedWidthGrid;
import com.google.gwt.gen2.table.client.PagingScrollTable;
import com.google.gwt.gen2.table.client.TableDefinition;
import com.google.gwt.gen2.table.client.TableModel;
import com.google.gwt.gen2.table.client.TableModel.Callback;
import com.google.gwt.gen2.table.client.TableModelHelper.Request;
import com.google.gwt.gen2.table.client.TableModelHelper.Response;
import com.google.gwt.gen2.table.event.client.RowSelectionEvent;
import com.google.gwt.gen2.table.event.client.RowSelectionHandler;
import com.google.gwt.gen2.table.event.client.TableEvent.Row;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.qualogy.qafe.gwt.client.context.ClientApplicationContext;
import com.qualogy.qafe.gwt.client.ui.renderer.AbstractComponentRenderer.MessageBox;
import com.qualogy.qafe.gwt.client.ui.renderer.DataGridFactory;
import com.qualogy.qafe.gwt.client.util.QAMLConstants;
import com.qualogy.qafe.gwt.client.util.QAMLUtil;
import com.qualogy.qafe.gwt.client.vo.functions.DataContainerGVO;
import com.qualogy.qafe.gwt.client.vo.functions.SetValueGVO;
import com.qualogy.qafe.gwt.client.vo.functions.execute.SetValueExecute;
import com.qualogy.qafe.gwt.client.vo.ui.DataGridColumnGVO;
import com.qualogy.qafe.gwt.client.vo.ui.DataGridGVO;

public class QPagingScrollTable extends PagingScrollTable<DataContainerGVO> implements HasDataGridMethods,
        RowSelectionHandler, ResultHandler, ScrollHandler, HasRowSelectionChangeHandlers {

    public static final String MSG_LAST_PAGE = "You reached the last page";

    protected int qCurrentPage = 0;
    protected Boolean hasPredefinedPageSize = false;
    private List<Integer> rememberSelectedRows = null;
    private List<DataContainerGVO> initialData = new ArrayList<DataContainerGVO>();
    private boolean resetInitialData = true;
    private String uuid;
    private String parent;
    private QPagingOptions pagingOptions;
    private QPagingScrollTableOperation pagingScrollTableOperations;
    private Widget overflow;
    private DataGridGVO source = null;
    private boolean autoGeneratedColumns = false;
    private int scrollPosition;
    private boolean scrollEvent = false;
    private final Map<String, List<String>> groupedColumns = new HashMap<String, List<String>>();
    private final Map<String, SetValueGVO> dropDownColumnAndValues = new HashMap<String, SetValueGVO>();
    private Element qHeaderWrapper;
    private boolean refreshingExistingRows = false;
    private final List<RowSelectionChangeHandler> rowSelectionChangeHandlers = new ArrayList<RowSelectionChangeHandler>();

    @Override
    public void setVisible(final boolean visible) {
        super.setVisible(visible);
        if (pagingOptions != null) {
            pagingOptions.setVisible(visible && !source.getPageScroll());
        }
        if (pagingScrollTableOperations != null) {
            pagingScrollTableOperations.setVisible(visible);
        }
        if (overflow != null) {
            overflow.setVisible(visible);
        }
    }

    public DataGridGVO getSource() {
        return source;
    }

    public boolean hasOverflow() {
        return (overflow != null);
    }

    public QPagingScrollTable(final TableModel<DataContainerGVO> tableModel, final FixedWidthGrid dataTable,
            final FixedWidthFlexTable headerTable, final TableDefinition<DataContainerGVO> tableDefinition,
            final DataGridGVO vo, final String uuid, final String parent) {
        super(tableModel, dataTable, headerTable, tableDefinition);
        initParameters(vo, uuid, parent);
        // Listen for selection events
        dataTable.addRowSelectionHandler(this);
    }

    public QPagingScrollTable(final TableModel<DataContainerGVO> tableModel,
            final TableDefinition<DataContainerGVO> tableDefinition, final DataGridGVO vo, final String uuid,
            final String parent) {
        super(tableModel, tableDefinition);
        initParameters(vo, uuid, parent);

    }

    private void initParameters(final DataGridGVO vo, final String uuid, final String parent) {
        this.source = vo;
        this.uuid = uuid;
        this.parent = parent;

        if (this.source != null) {
            this.autoGeneratedColumns = (this.source.getColumns() == null)
                    || (this.source.getColumns().length == 0);
        }

        // SpreadsheetCell needs to know the parentContainer. So after the constructor is executed we have to
        // create tableDefinition with this object as parent for later use and pass the tableDefinition to super class.
        createTableDefinition();

        // WORKAROUND:
        // In IE, when a datagrid has only one visible column (including the rowNumber column),
        // that column will shrink each time data is set to the datagrid,
        // so changing the width from "100%" to "1px", overflow from "hidden" to "visible" will avoid this problem
        final String userAgent = Window.Navigator.getUserAgent();
        final boolean isIE = userAgent.toUpperCase().contains("MSIE");
        if (isIE && (source != null)) {
            final DataGridColumnGVO[] columns = source.getColumns();
            if (columns != null) {
                int numVisibleColumns = 0;
                for (final DataGridColumnGVO column : columns) {
                    if (column.getVisible()) {
                        numVisibleColumns++;
                    }
                }
                if ((numVisibleColumns == 1) && (qHeaderWrapper != null)) {
                    qHeaderWrapper.getStyle().setPropertyPx("width", 1);
                    qHeaderWrapper.getStyle().setProperty("overflow", "visible");
                }
            }
        }
    }

    public void onRowSelection(final RowSelectionEvent event) {
        if (hasOverflow()) {
            final Set<Row> selected = event.getSelectedRows();
            for (final Row row : selected) {
                final DataContainerGVO dm = getRowValue(row.getRowIndex());
                final SetValueGVO setValue = new SetValueGVO();
                setValue.setDataContainer(dm);
                if (overflow instanceof HasWidgets) {
                    SetValueExecute.processWidgets((HasWidgets) overflow, setValue);
                }
            }
        }

        handleRowSelection(event);
    }

    private void handleRowSelection(final RowSelectionEvent event) {
        final int rowIndex = getLastSelectedIndex(event);
        Object rowValue = null;
        if (rowIndex >= 0) {
            rowValue = getRowValue(rowIndex);
        }
        fireRowSelectionChange(rowIndex, rowValue);
    }

    private int getLastSelectedIndex(final RowSelectionEvent event) {
        int rowIndex = -1;
        final Object[] selected = event.getSelectedRows().toArray();
        if (selected.length == 0) {
            return rowIndex;
        }

        if (selected[selected.length - 1] instanceof Row) {
            final Row lastRowSelected = (Row) selected[selected.length - 1];
            rowIndex = lastRowSelected.getRowIndex();
        }
        return rowIndex;
    }

    // method checking is columns are defined for datagrid explicitly in qaml.
    public Boolean isAutoGeneratedColumns() {
        return autoGeneratedColumns;
    }

    public void clearData() {
        if (getDataTable() != null) {
            getDataTable().clearAll();
            while (getDataTable().getRowCount() > 0) {
                getDataTable().removeRow(0);
            }
        }
        cleanRows();
    }

    private void cleanRows() {
        final List<DataContainerGVO> rowValues = getRowValues();
        if (rowValues == null) {
            return;
        }
        final List<ColumnDefinition<DataContainerGVO, ?>> visibleColumns = getVisibleColumnDefinitions();
        for (int i = 0; i < rowValues.size(); i++) {
            cleanRowImpl(i, visibleColumns);
        }
    }

    private void cleanRowImpl(final int rowIndex,
            final List<ColumnDefinition<DataContainerGVO, ?>> visibleColumns) {
        if (visibleColumns == null) {
            return;
        }
        for (int i = 0; i < visibleColumns.size(); i++) {
            final ColumnDefinition<DataContainerGVO, ?> columnDefinition = visibleColumns.get(i);
            if (columnDefinition instanceof QColumnDefinition) {
                final QColumnDefinition qColumnDefinition = (QColumnDefinition) columnDefinition;
                final CellCleaner cellCleaner = qColumnDefinition.getCellCleaner();
                if (cellCleaner != null) {
                    cellCleaner.cleanRow(rowIndex, columnDefinition);
                }
            }
        }
    }

    public Integer getMaxRows() {
        // TODO Auto-generated method stub
        return null;
    }

    public void setData(final Request request, final Response<DataContainerGVO> response) {
        if (hasMatchedColumns(response.getRowValues())) {
            setData(getAbsoluteFirstRowIndex(), response.getRowValues());
        }
    }

    // checking any columns are matched with existing columns and columns from new data to set.
    private boolean hasMatchedColumns(final Iterator<DataContainerGVO> rows) {
        boolean columnMatched = false;
        final Iterator<DataContainerGVO> itr = rows;
        if ((itr != null) && itr.hasNext()) {
            final DataContainerGVO row = itr.next();
            if (row != null) {
                final List<ColumnDefinition<DataContainerGVO, ?>> columnDefinitionList = getTableDefinition()
                        .getVisibleColumnDefinitions();
                for (final ColumnDefinition<DataContainerGVO, ?> columnDefinition : columnDefinitionList) {
                    if (columnDefinition instanceof QColumnDefinition) {
                        final QColumnDefinition qColumnDefinition = (QColumnDefinition) columnDefinition;
                        if (row.getDataMap().containsKey(qColumnDefinition.getField())) {
                            columnMatched = true;
                            break;
                        }
                    }
                }
            }
        }
        return columnMatched;
    }

    private int getColumnIndex(final String name) {
        boolean columnFound = false;
        int col = -1;
        if (source != null && name != null && name.length() > 0 && source.getColumns() != null) {
            for (int column = 0; column < source.getColumns().length && !columnFound; column++) {
                if (name.equalsIgnoreCase(source.getColumns()[column].getFieldName())) {
                    columnFound = true;
                    col = column;
                }
            }
        }
        return col;
    }

    public void insertData(final List<DataContainerGVO> listOfDataMap) {
        insertData(listOfDataMap, false, null, null);
    }

    // CHECKSTYLE.OFF: CyclomaticComplexity
    public void insertData(final List<DataContainerGVO> listOfDataMap, final Boolean append, final String senderId,
            final String listenerType) {
        boolean makeRowSelected = false;
        int rowToSelect = 0;

        if (!append && !isPageScrollEvent(senderId, listenerType)) {
            // This will make sure scrollbar is placed on top, and so the browser scroll event will not get executed when user set the data.
            getDataWrapper().setScrollTop(0);
            makeRowSelected = getSource().getSelectFirstRow();
        }

        if (canProcessEmptyDataSet(listOfDataMap, senderId, listenerType)) { // check is paging action and the resulted data is empty
            processEmptyDataSet(listOfDataMap, senderId, listenerType);
        } else if (isEmptyDataSet(listOfDataMap, senderId, listenerType)) { // not a paging action but result is empty
            if (!append) {
                clearData();
                this.initialData = new ArrayList<DataContainerGVO>();
                clearSelection();
                getRowValues().clear();
                if (isAutoGeneratedColumns()) {
                    getHeaderTable().clearAll();
                }
            }
        } else { // result not empty
            List<DataContainerGVO> data = listOfDataMap;
            int existingDataSize = 0;
            if (append) {
                existingDataSize = getRowValues().size();
            } else {
                if (resetInitialData) {
                    initialData = makeClone(listOfDataMap);
                }
            }

            if (source.getAdd() || source.getDelete() || source.getEditable()) {
                final boolean noPaging = !isPagingEvent(senderId, listenerType);
                for (final DataContainerGVO dm : listOfDataMap) {
                    ++existingDataSize;
                    if (append && noPaging) {
                        dm.getDataMap().put(DataContainerGVO.ROW_STATUS_KEY,
                                new DataContainerGVO(DataContainerGVO.ROW_STATUS_NEW));
                        dm.getDataMap().put(DataContainerGVO.ROW_NUMBER,
                                new DataContainerGVO(QAMLConstants.TOKEN_NEW + (existingDataSize)));
                        makeRowSelected = true;
                        rowToSelect = existingDataSize - 1;
                    } else {
                        dm.getDataMap().put(DataContainerGVO.ROW_STATUS_KEY,
                                new DataContainerGVO(DataContainerGVO.ROW_STATUS_UNMODIFIED));
                        dm.getDataMap().put(DataContainerGVO.ROW_NUMBER,
                                new DataContainerGVO("" + (existingDataSize)));
                    }
                }
            } else if (!source.getEditable()) {
                // ROW_NUMBER is maintained so that when $SELECTED_INDEX is used, it picks the right row.
                for (final DataContainerGVO dm : listOfDataMap) {
                    ++existingDataSize;
                    dm.getDataMap().put(DataContainerGVO.ROW_NUMBER, new DataContainerGVO("" + (existingDataSize)));
                }
            }

            if (append) {
                data = getRowValues();
                data.addAll(listOfDataMap);
            } else {
                clearData();
            }
            checkColumns(data);
            final boolean pageScrollEvent = isPageScrollEvent(senderId, listenerType);
            if (pageScrollEvent) {
                rememberSelection();
            }
            ((QTableModel) getTableModel()).processData(data);
            if (pageScrollEvent) {
                restoreSelection();
            }
            if (makeRowSelected) {
                this.selectRow(rowToSelect);
            }
        }
    }
    // CHECKSTYLE.ON: CyclomaticComplexity

    private void checkColumns(final List<DataContainerGVO> listOfDataMap) {
        if ((listOfDataMap != null) && (listOfDataMap.size() > 0)) {
            if (isAutoGeneratedColumns()) {
                // So there are no columns from the QAML, we make the grid data-driven
                // create an array of the datagridcolumns
                final List<DataGridColumnGVO> listOfColumns = new ArrayList<DataGridColumnGVO>();
                final DataContainerGVO map = listOfDataMap.get(0);
                for (final String key : map.getDataMap().keySet()) {
                    final DataGridColumnGVO dcg = new DataGridColumnGVO();
                    dcg.setFieldName(key);
                    dcg.setSortable(dcg.getSortable());
                    dcg.setStaticField(false);
                    dcg.setDisplayname(key);
                    dcg.setContainerName(source.getId());
                    if (key.equals(DataMap.ROW_STATUS_KEY) || key.equals(DataMap.ROW_NUMBER)) {
                        dcg.setVisible(false);
                    }
                    listOfColumns.add(dcg);
                }
                setTableDefinition(DataGridFactory.createTableDefinition(source,
                        listOfColumns.toArray(new DataGridColumnGVO[] {}), uuid, parent, this));
                refreshColumnHeaders();
            }
        }
    }

    public void insertDataRow(final List<String> listOfDataMap, final Boolean append, final String senderId,
            final String listenerType) {
        if (canProcessEmptyDataSet(listOfDataMap, senderId, listenerType)) {
            processEmptyDataSet(listOfDataMap, senderId, listenerType);
        } else {
            if (!append) {
                clearData();
            }
        }
    }

    @Override
    public void setTableDefinition(final TableDefinition<DataContainerGVO> tableDefinition) {
        if (tableDefinition != null) {
            super.setTableDefinition(tableDefinition);
        }
    }

    public void createTableDefinition() {
        // If no columns are specified, show an empty column
        DataGridColumnGVO[] dataGridColumns = source.getColumns();
        if ((dataGridColumns == null) || (dataGridColumns.length == 0)) {
            final DataGridColumnGVO dataGridColumn = new DataGridColumnGVO();
            dataGridColumn.setFieldName("");
            dataGridColumns = new DataGridColumnGVO[1];
            dataGridColumns[0] = dataGridColumn;
        } else {
            aggregateGroupedColumns();
        }

        final TableDefinition<DataContainerGVO> tableDefinition = DataGridFactory.createTableDefinition(source,
                dataGridColumns, uuid, parent, this);
        setTableDefinition(tableDefinition);
    }

    private void aggregateGroupedColumns() {
        for (final DataGridColumnGVO column : source.getColumns()) {
            if (column.getGroup() != null) {

                String[] groupNames = null;
                if (column.getGroup().contains(",")) { // When column belong to multiple groups.
                    groupNames = column.getGroup().split(",");
                } else {
                    groupNames = new String[] { column.getGroup() };
                }

                for (String groupName : groupNames) {
                    groupName = groupName.trim();
                    if (groupedColumns.containsKey(groupName)) {
                        groupedColumns.get(groupName).add(column.getFieldName());
                    } else {
                        final List<String> columnNames = new ArrayList<String>();
                        columnNames.add(column.getFieldName());
                        groupedColumns.put(groupName, columnNames);
                    }
                }
            }
        }
    }

    public void processActions(final DataGridGVO gvo, final String uuid, final String parent) {
        // TODO Auto-generated method stub
    }

    public void setAdd(final Boolean bool) {
        // TODO Auto-generated method stub
    }

    public void setDelete(final Boolean bool) {
        // TODO Auto-generated method stub
    }

    public boolean isEditable() {
        // TODO Auto-generated method stub
        return false;
    }

    public void setEditable(final boolean value) {
        // TODO Auto-generated method stub
    }

    public void setExport(final Boolean bool) {
        // TODO Auto-generated method stub
    }

    public void setMaxRows(final Integer maxRows) {
        // TODO Auto-generated method stub
    }

    public void setModified(final boolean modified, final int row, final int column, final String value) {
        // TODO Auto-generated method stub
    }

    public void setModified(final ColumnDefinition<DataContainerGVO, String> columnDefinition,
            final UIObject uiObject, final DataContainerGVO rowValue, final Object newValue) {
        setModified(columnDefinition, uiObject, rowValue, newValue, false);
    }

    public void setModified(final ColumnDefinition<DataContainerGVO, String> columnDefinition,
            final UIObject uiObject, final DataContainerGVO rowValue, final Object newValue,
            final boolean changedByUser) {
        if (columnDefinition instanceof QColumnDefinition) {
            if (rowValue != null && rowValue.isMap()) {
                final QColumnDefinition colDefinition = (QColumnDefinition) columnDefinition;
                final String columnName = colDefinition.getField();
                DataContainerGVO dataContainerGVO = rowValue.getDataMap().get(columnName);
                if (dataContainerGVO == null) {
                    dataContainerGVO = new DataContainerGVO();
                    dataContainerGVO.setKind(DataContainerGVO.KIND_STRING);
                    rowValue.getDataMap().put(columnName, dataContainerGVO);
                }
                Object oldValue = null;
                if (newValue instanceof Date) {
                    oldValue = dataContainerGVO.getDateData();
                    dataContainerGVO.setDateData((Date) newValue);
                    dataContainerGVO.setStringDataType(DataContainerGVO.TYPE_DATE);
                } else if (newValue instanceof Double) {
                    dataContainerGVO.setStringDataType(DataContainerGVO.TYPE_DOUBLE);
                }
                final String newValueOfStr = (newValue == null) ? null : newValue.toString();
                dataContainerGVO.setDataString(newValueOfStr);
                doColumnDataChange(columnDefinition, uiObject, rowValue.getDataMap(), oldValue, newValue,
                        changedByUser);
            }
        }
    }

    public void setOverflow(final Widget overflow) {
        this.overflow = overflow;
    }

    public void setPageSize(final Integer pageSize) {
        setPageSize(pageSize, false);
    }

    public void setPageSize(final Integer pageSize, final Boolean init) {
        if (pageSize != null) {
            if ((init) && (pageSize != -1)) {
                hasPredefinedPageSize = true;
            }
            setPageSize((int) pageSize);
        }
    }

    @Override
    public void setPageSize(final int pageSize) {
        if (hasPredefinedPageSize) {
            // pageSize is specified in QAML code
            super.setPageSize(pageSize);
        }
    }

    public void setShowAll(final Boolean bool) {
        // TODO Auto-generated method stub
    }

    public void setup() {
        refreshColumnHeaders();
        if (source.getColumns() != null) {
            initColumnWidths();
            setEmptyTableWidgetVisible(false);
            final DataMap dummy = new DataMap();
            final DataContainerGVO dummydcg = new DataContainerGVO();
            dummydcg.setDataString("");
            final List<DataMap> dummylistOfDataMap = new ArrayList<DataMap>();
            for (int i = 0; i < source.getColumns().length; i++) {
                dummy.put("" + i, dummydcg);
            }
            for (int i = 0; i < 15; i++) {
                dummylistOfDataMap.add(dummy);
            }
        }
    }

    private void refreshColumnHeaders() {
        refreshColumnHeaders(false);
    }

    private void refreshColumnHeaders(final boolean force) {
        if ((source != null) && (source.getColumns() != null)) {
            if (getHeaderTable() != null) {
                if (force || isColumnHeadersChanged()) {
                    clearColumnHeaders();
                    buildColumnHeaders();
                }
            }
        }
    }

    public void initColumnWidths() {
        int visibleColIndex = 0;
        final DataGridColumnGVO[] columns = source.getColumns();
        for (final DataGridColumnGVO columnGVO : columns) {
            if (!columnGVO.getVisible()) {
                continue;
            }
            final String width = columnGVO.getWidth();
            if (width != null) {
                setColumnWidth(visibleColIndex, Integer.parseInt(width));
            }
            visibleColIndex++;
        }
    }

    private void clearColumnHeaders() {
        final FixedWidthFlexTable headerTable = getHeaderTable();
        if (headerTable == null) {
            return;
        }
        if (headerTable.getColumnCount() > 0) {
            headerTable.removeRow(0);
            headerTable.clearAll();
        }
    }

    private void buildColumnHeaders() {
        int visibleColIndex = 0;
        final DataGridColumnGVO[] columns = source.getColumns();
        for (final DataGridColumnGVO columnGVO : columns) {
            if (!columnGVO.getVisible()) {
                continue;
            }
            final Widget columnHeader = createColumnHeader(columnGVO);
            if (columnHeader == null) {
                continue;
            }

            getHeaderTable().setWidget(0, visibleColIndex, columnHeader);
            visibleColIndex++;
        }
    }

    private Widget createColumnHeader(final DataGridColumnGVO columnGVO) {
        if ((columnGVO == null) || columnGVO.isQafeChecksum()) {
            return null;
        }
        String displayName = columnGVO.getDisplayname();
        if (displayName == null) {
            displayName = columnGVO.getFieldName();
        }
        final Label label = new Label(displayName);
        label.setHeight("20px");
        if (columnGVO.getStyleClass() != null) {
            label.setStylePrimaryName(columnGVO.getStyleClass());
        }
        return label;
    }

    private boolean isColumnHeadersChanged() {
        final DataGridColumnGVO[] dataGridColumns = source.getColumns();

        // Number of columns has been changed, so the columnHeaders
        if (getHeaderTable().getColumnCount() != dataGridColumns.length) {
            return true;
        }

        // Fill map with columnNames for faster processing
        final Map<String, String> map = new HashMap<String, String>();
        for (int i = 0; i < dataGridColumns.length; i++) {
            final DataGridColumnGVO dataGridColumn = dataGridColumns[i];
            if (dataGridColumn != null) {
                String displayName = dataGridColumn.getDisplayname();
                if (displayName == null) {
                    displayName = dataGridColumn.getFieldName();
                }
                if (displayName != null) {
                    map.put(displayName, null);
                }
            }
        }

        // Check existence of all columnNames
        final Iterator<Widget> itrWidget = getHeaderTable().iterator();
        while (itrWidget.hasNext()) {
            final Widget widget = itrWidget.next();
            if (widget instanceof Label) {
                final Label label = (Label) widget;
                if (!map.containsKey(label.getText())) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Reload the current page.
     */
    public void reloadPage() {
        if (qCurrentPage >= 0) {
            gotoPage(qCurrentPage, true);
        } else {
            gotoPage(0, true);
        }
    }

    @Override
    public int getCurrentPage() {
        return qCurrentPage;
    }

    public void setCurrentPage(final int currentPage) {
        if (hasPredefinedPageSize) {
            // pageSize is specified in QAML code
            qCurrentPage = Math.max(0, currentPage);
            if ((pagingOptions != null) && (qCurrentPage != Integer.MAX_VALUE)) {
                pagingOptions.getCurPageBox().setText(String.valueOf(qCurrentPage + 1));
            }
        }
    }

    @Override
    public int getAbsoluteFirstRowIndex() {
        int rowIndex = getCurrentPage();
        if (rowIndex != Integer.MAX_VALUE) {
            rowIndex = rowIndex * getPageSize();
        }
        return rowIndex;
    }

    @Override
    public int getAbsoluteLastRowIndex() {
        if (getPageSize() > 0) {
            int rowIndex = getAbsoluteFirstRowIndex();
            if (rowIndex != Integer.MAX_VALUE) {
                rowIndex = rowIndex + getPageSize() - 1;
            }
            return rowIndex;
        }
        return Math.max(getTableModel().getRowCount(), 0) - 1;
    }

    public void onDelete() {
        //remember the selected rows, after the event body is executed success selected rows needs to be removed in onResult callback.
        rememberSelection();
        setSenderId(QPagingScrollTableOperation.CONTROLS_DELETE);
        gotoPage(getCurrentPage(), true);
    }

    private void rememberSelection() {
        if (rememberSelectedRows == null) {
            rememberSelectedRows = new ArrayList<Integer>();
        }
        rememberSelectedRows.clear();
        final Iterator<Integer> itr = getDataTable().getSelectedRows().iterator();
        while (itr.hasNext()) {
            final Integer rowIndex = itr.next();
            rememberSelectedRows.add(rowIndex);
        }
    }

    private void restoreSelection() {
        if (rememberSelectedRows == null) {
            return;
        }
        for (final Integer rowIndex : rememberSelectedRows) {
            getDataTable().selectRow(rowIndex, false);
        }
        rememberSelectedRows.clear();
    }

    private void clearSelection() {
        getDataTable().deselectAllRows();
        getSelectedRowValues().clear();
        if (rememberSelectedRows != null) {
            rememberSelectedRows.clear();
        }
    }

    private void performDelete() {
        for (final Integer rowIndex : rememberSelectedRows) {
            getRowValues().remove(rowIndex.intValue());
            getDataTable().removeRow(rowIndex.intValue());
        }
        clearSelection();
    }

    public void onAdd() {
        setSenderId(QPagingScrollTableOperation.CONTROLS_ADD);
        gotoPage(getCurrentPage(), true);
    }

    public void onSave() {
        setSenderId(QPagingScrollTableOperation.CONTROLS_SAVE);
        gotoPage(getCurrentPage(), true);
        updateQafeChecksum();
    }

    private void updateQafeChecksum() {
        final Collection<DataContainerGVO> rows = getRowValuesToProcess(DataContainerGVO.ROW_STATUS_MODIFIED);
        for (final DataContainerGVO row : rows) {
            final DataMap dataMap = row.getDataMap();
            final DataContainerGVO checksumContainer = dataMap.get(DataContainerGVO.QAFE_CHECKSUM);
            if (checksumContainer != null) {
                int checksum = 0;
                for (final Map.Entry<String, DataContainerGVO> field : dataMap.entrySet()) {
                    if (!isMetaData(field.getKey())) {
                        Object value = null;
                        if (field.getValue() != null) {
                            value = field.getValue().createType();
                        }
                        checksum += QAMLUtil.calculateChecksum(field.getKey(), value);
                    }
                }
                checksumContainer.setDataString("" + checksum);
            }
        }
    }

    private boolean isMetaData(final String key) {
        return DataContainerGVO.ROW_STATUS_KEY.equals(key) || DataContainerGVO.ROW_NUMBER.equals(key)
                || DataContainerGVO.QAFE_CHECKSUM.equals(key);
    }

    public void onRefresh() {
        setSenderId(QPagingScrollTableOperation.CONTROLS_REFRESH);
        gotoPage(getCurrentPage(), true);
    }

    public void onCancel() {
        setSenderId(QPagingScrollTableOperation.CONTROLS_CANCEL);
        gotoPage(getCurrentPage(), true);
    }

    @Override
    public void gotoFirstPage() {
        setSenderId(QPagingOptions.PAGING_FIRSTPAGE);
        gotoPage(0, true);
    }

    @Override
    public void gotoLastPage() {
        setSenderId(QPagingOptions.PAGING_LASTPAGE);
        gotoPage(Integer.MAX_VALUE, true);
    }

    @Override
    public void gotoNextPage() {
        setSenderId(QPagingOptions.PAGING_NEXTPAGE);
        gotoPage(getCurrentPage() + 1, true);
    }

    @Override
    public void gotoPreviousPage() {
        setSenderId(QPagingOptions.PAGING_PREVIOUSPAGE);
        gotoPage(Math.max(0, getCurrentPage() - 1), true);
    }

    @Override
    public void gotoPage(final int page, final boolean forced) {
        final int currPage = getCurrentPage();
        if (currPage != page || forced) {
            setCurrentPage(page);

            final FixedWidthGrid dataTable = getDataTable();
            if ((currPage != page) && (!hasPageScroll())) {
                // Deselect rows when switching pages if it is standard pagination
                dataTable.deselectAllRows();
            }

            // Request the new data from the table model
            final int firstRow = getAbsoluteFirstRowIndex();
            final int lastRow = getAbsoluteLastRowIndex();
            final Request request = new Request(firstRow, lastRow, dataTable.getColumnSortList());

            final Callback callback = new Callback<DataContainerGVO>() {
                public void onFailure(final Throwable caught) {
                    ClientApplicationContext.getInstance().log("Setting datagrid values failed", caught);
                }

                public void onRowsReady(final Request request, final Response<DataContainerGVO> response) {
                    setData(request, response);
                }
            };

            if (getTableModel() instanceof QTableModel) {
                ((QTableModel) getTableModel()).requestRows(request, callback, this);
            }
        }
    }

    private boolean hasPageScroll() {
        if ((getSource() != null) && getSource().getPageScroll()) {
            return true;
        }
        return false;
    }

    private void setSenderId(final String sender) {
        final TableModel<DataContainerGVO> m = getTableModel();
        if (m instanceof QTableModel) {
            final QTableModel qm = (QTableModel) m;
            if (QPagingOptions.PAGING_FIRSTPAGE.equals(sender)) {
                qm.setSender(pagingOptions.getFirstImage());
            } else if (QPagingOptions.PAGING_NEXTPAGE.equals(sender)) {
                qm.setSender(pagingOptions.getNextImage());
            } else if (QPagingOptions.PAGING_LASTPAGE.equals(sender)) {
                qm.setSender(pagingOptions.getLastImage());
            } else if (QPagingOptions.PAGING_PREVIOUSPAGE.equals(sender)) {
                qm.setSender(pagingOptions.getPrevImage());
            } else if (QPagingScrollTableOperation.CONTROLS_DELETE.equals(sender)) {
                qm.setSender(pagingScrollTableOperations.getDeleteImage());
            } else if (QPagingScrollTableOperation.CONTROLS_ADD.equals(sender)) {
                qm.setSender(pagingScrollTableOperations.getAddImage());
            } else if (QPagingScrollTableOperation.CONTROLS_SAVE.equals(sender)) {
                qm.setSender(pagingScrollTableOperations.getSaveImage());
            } else if (QPagingScrollTableOperation.CONTROLS_REFRESH.equals(sender)) {
                qm.setSender(pagingScrollTableOperations.getRefreshImage());
            } else if (QPagingScrollTableOperation.CONTROLS_CANCEL.equals(sender)) {
                qm.setSender(pagingScrollTableOperations.getCancelImage());
            }
        }
    }

    public void setPagingOptions(final QPagingOptions pagingOptions) {
        this.pagingOptions = pagingOptions;

    }

    public void resetCurrentPage() {
        if (getCurrentPage() < 0) {
            gotoPage(0, true);
        }
    }

    public void selectRow(final int rowNr) {
        if (rowNr >= 0 && rowNr < getDataTable().getRowCount()) {
            getDataTable().selectRow(rowNr, true);
            final Element rowToShow = getDataTable().getRowFormatter().getElement(rowNr);
            scrollIntoView(rowToShow, this.getElement());

        } else {
            //TODO: call  clearSelection to remove the existing selections. 
            //This will allow end user to remove all selections by passing -1 in set-property 
        }
    }

    /**
     *
     *  This method is copied from com.google.gwt.dom.client.DOMImpl class and modified to add an extra check at the end.
     *  ADDED CODE AT END:  if(cur == containerElement) {break;}
     *  When user add a new record or use set-property to set a row selected we need to show that row in the view.
     *  When we are using scrollIntoView method of GWT(getDataTable().getRowFormatter().getElement(rowNr).scrollIntoView())
     *  we got issue after zooming in(CTr+) and then setting the first row as selected.
     *  Issue is that the entire browser window moves up after , making top part of the screen invisible.
     *  Now we added extra check tp stop the operation of making the new view position when it reaches the parent(in this case the pagingScrollTable)
     */
    protected native void scrollIntoView(Element elem, Element containerElement) /*-{
                                                                                 var left = elem.offsetLeft, top = elem.offsetTop;
                                                                                 var width = elem.offsetWidth, height = elem.offsetHeight;
                                                                                     
                                                                                 if (elem.parentNode != elem.offsetParent) {
                                                                                 left -= elem.parentNode.offsetLeft;
                                                                                 top -= elem.parentNode.offsetTop;
                                                                                 }
                                                                                     
                                                                                 var cur = elem.parentNode;
                                                                                 while (cur && (cur.nodeType == 1)) {
                                                                                 if (left < cur.scrollLeft) {
                                                                                 cur.scrollLeft = left;
                                                                                 }
                                                                                 if (left + width > cur.scrollLeft + cur.clientWidth) {
                                                                                 cur.scrollLeft = (left + width) - cur.clientWidth;
                                                                                 }
                                                                                 if (top < cur.scrollTop) {
                                                                                 cur.scrollTop = top;
                                                                                 }
                                                                                 if (top + height > cur.scrollTop + cur.clientHeight) {
                                                                                 cur.scrollTop = (top + height) - cur.clientHeight;
                                                                                 }
                                                                                     
                                                                                 var offsetLeft = cur.offsetLeft, offsetTop = cur.offsetTop;
                                                                                 if (cur.parentNode != cur.offsetParent) {
                                                                                 offsetLeft -= cur.parentNode.offsetLeft;
                                                                                 offsetTop -= cur.parentNode.offsetTop;
                                                                                 }
                                                                                     
                                                                                 left += offsetLeft - cur.scrollLeft;
                                                                                 top += offsetTop - cur.scrollTop;
                                                                                 cur = cur.parentNode;
                                                                                     
                                                                                 //added check to stop iteration when the container is datagrid
                                                                                 if(cur == containerElement) {
                                                                                 break;
                                                                                 }
                                                                                 }
                                                                                 }-*/;

    public Object getData(final String fetchForRowStatus, final String groupName) {
        final Collection<DataContainerGVO> rowValuesToProcess = getRowValuesToProcess(fetchForRowStatus);
        List<DataContainerGVO> data = new ArrayList<DataContainerGVO>();
        for (final DataContainerGVO row : makeClone(rowValuesToProcess)) {
            row.getDataMap().remove(DataContainerGVO.ROW_STATUS_KEY);
            if (row.getDataMap().get(DataContainerGVO.ROW_NUMBER) != null) {
                final String rowNumber = row.getDataMap().get(DataContainerGVO.ROW_NUMBER).getDataString()
                        .replaceAll("[" + QAMLConstants.TOKEN_NEW + QAMLConstants.TOKEN_MODIFIED
                                + QAMLConstants.TOKEN_DELETED + "]", "");
                row.getDataMap().get(DataContainerGVO.ROW_NUMBER).setDataString(rowNumber);
            }
            data.add(row);
        }
        if (groupName != null) {
            final List<DataContainerGVO> filteredRows = new ArrayList<DataContainerGVO>();
            final List<String> columnsOfThisGroup = groupedColumns.get(groupName);
            if (columnsOfThisGroup != null) {
                for (final DataContainerGVO row : makeClone(data)) {
                    final DataContainerGVO dgvo = new DataContainerGVO(new DataMap());
                    dgvo.getDataMap().put(DataContainerGVO.ROW_NUMBER,
                            row.getDataMap().get(DataContainerGVO.ROW_NUMBER));
                    for (final String key : columnsOfThisGroup) {
                        dgvo.getDataMap().put(key, row.getDataMap().get(key));
                    }
                    filteredRows.add(dgvo);
                }
                data = filteredRows;
            }
        }
        return data;
    }

    private Collection<DataContainerGVO> getRowValuesToProcess(final String fetchForRowStatus) {
        if (fetchForRowStatus == null) {
            return getSelectedRowValues();
        } else if (DataContainerGVO.ROW_STATUS_ALL.equals(fetchForRowStatus)) {
            return getRowValues();
        } else if (DataContainerGVO.ROW_STATUS_UNSELECTED.equals(fetchForRowStatus)) {
            final Collection<DataContainerGVO> rowValuesToProcess = new ArrayList<DataContainerGVO>(getRowValues());
            rowValuesToProcess.removeAll(getSelectedRowValues());
            return rowValuesToProcess;
        } else {
            final Collection<DataContainerGVO> rowValuesToProcess;
            rowValuesToProcess = new ArrayList<DataContainerGVO>();
            for (final DataContainerGVO row : getRowValues()) {
                if ((row.getDataMap().get(DataContainerGVO.ROW_STATUS_KEY).getDataString())
                        .equals(fetchForRowStatus)) {
                    rowValuesToProcess.add(row);
                }
            }
            return rowValuesToProcess;
        }
    }

    public void setScrollTableOperations(final QPagingScrollTableOperation qPagingScrollTableOperation) {
        pagingScrollTableOperations = qPagingScrollTableOperation;
    }

    protected Boolean isPagingEvent(final String senderId, final String listenerType) {
        if (isPageEvent(senderId, listenerType)) {
            return true;
        }
        if (isPageScrollEvent(senderId, listenerType)) {
            return true;
        }
        return false;
    }

    private boolean isPageEvent(final String senderId, final String listenerType) {
        if (QAMLConstants.EVENT_ONCLICK.equals(listenerType)) {
            final String dataGridId = this.source.getId().toString();
            if (senderId.startsWith((dataGridId + "." + QPagingOptions.PAGING_FIRSTPAGE))
                    || senderId.startsWith((dataGridId + "." + QPagingOptions.PAGING_PREVIOUSPAGE))
                    || senderId.startsWith((dataGridId + "." + QPagingOptions.PAGING_NEXTPAGE))
                    || senderId.startsWith((dataGridId + "." + QPagingOptions.PAGING_LASTPAGE))) {
                return true;
            }
        }
        return false;
    }

    private boolean isPageScrollEvent(final String senderId, final String listenerType) {
        if (QAMLConstants.EVENT_ONSCROLL_BOTTOM.equals(listenerType)) {
            final String dataGridId = this.source.getId().toString();
            if (senderId.startsWith(dataGridId)) {
                return true;
            }
        }
        return false;
    }

    protected Boolean canProcessEmptyDataSet(final Object data, final String senderId, final String listenerType) {
        boolean result = false;
        if (data == null) {
            result = true;
        } else if ((data instanceof List) && ((List) data).isEmpty()) {
            result = true;
        }
        result = result ? isPagingEvent(senderId, listenerType) : result;
        return result;
    }

    protected Boolean isEmptyDataSet(final Object data, final String senderId, final String listenerType) {
        boolean result = false;
        if ((data == null) || ((data instanceof List) && ((List) data).isEmpty())) {
            result = true;
        }
        return result;
    }

    protected void processEmptyDataSet(final Object data, final String senderId, final String listenerType) {
        // qCurrentPage should be decrement by 1,
        // because it's incremented by 1 already before sending to the back-end
        final int currPage = getCurrentPage();
        setCurrentPage(currPage - 1);

        if ((senderId != null) && (listenerType != null)) {
            final String dataGridId = this.source.getId().toString();
            if ((listenerType.equals("onscroll-bottom")) || (listenerType.equals("onclick")
                    && (senderId.startsWith((dataGridId + "." + QPagingOptions.PAGING_NEXTPAGE))))) {
                // show a fading message
                fadeMessage(MSG_LAST_PAGE);
            }
        }
    }

    protected void fadeMessage(final String message) {
        setEmptyTableWidgetVisible(true);
        final Widget widget = getEmptyTableWidget();
        if (widget instanceof MessageBox) {
            final MessageBox messageBox = (MessageBox) widget;
            messageBox.getElement().getStyle().setProperty("width", "100%");
            Utils.setWidgetPosition(messageBox, 0, 0);
            Utils.fadeMessage(messageBox, message);
        }
    }

    @Override
    protected void setEmptyTableWidgetVisible(final boolean visible) {
        super.setEmptyTableWidgetVisible(visible);

        // when calling super.setEmptyTableWidgetVisible(true),
        // data are shown, so set the visibility back to true
        getDataWrapper().getStyle().setProperty("display", "");
    }

    @Override
    protected Element createWrapper(final String cssName) {
        final Element wrapper = super.createWrapper(cssName);
        if ("headerWrapper".equals(cssName)) {
            // This will be used in method initParameters
            qHeaderWrapper = wrapper;
        }
        return wrapper;
    }

    private String getSenderIdOnly(String senderId) {
        if ((senderId != null) && (senderId.indexOf("|") > -1)) {
            senderId = senderId.substring(0, senderId.indexOf("|"));
        }
        return senderId;
    }

    // call back to handle anything to be done after the event body processing.
    public void onResult(String senderId, final String listenerType) {
        if (QAMLConstants.EVENT_ONCLICK.equals(listenerType)) {
            senderId = getSenderIdOnly(senderId);
            if (senderId.endsWith(QPagingScrollTableOperation.CONTROLS_DELETE)) {
                handleDeleteRecord();
            } else if (senderId.endsWith(QPagingScrollTableOperation.CONTROLS_ADD)) {
                handleAddRecord();
            } else if (senderId.endsWith(QPagingScrollTableOperation.CONTROLS_SAVE)) {
                int rowIndex = 0;
                final ArrayList<DataContainerGVO> rowsToRemove = new ArrayList<DataContainerGVO>();
                for (final DataContainerGVO row : getRowValues()) {
                    if (!row.getDataMap().get(DataContainerGVO.ROW_STATUS_KEY).getDataString()
                            .equals(DataContainerGVO.ROW_STATUS_DELETED)) {
                        row.getDataMap().get(DataContainerGVO.ROW_STATUS_KEY)
                                .setDataString(DataContainerGVO.ROW_STATUS_UNMODIFIED);
                        final String rowNumber = row.getDataMap().get(DataContainerGVO.ROW_NUMBER).getDataString()
                                .replaceAll("[" + QAMLConstants.TOKEN_NEW + QAMLConstants.TOKEN_MODIFIED
                                        + QAMLConstants.TOKEN_DELETED + "]", "");
                        row.getDataMap().get(DataContainerGVO.ROW_NUMBER).setDataString(rowNumber);
                    } else {
                        rowsToRemove.add(row);
                    }
                    rowIndex++;
                }
                for (final DataContainerGVO removeRow : rowsToRemove) {
                    getRowValues().remove(removeRow);
                }
                //datagridRendered = false;
                resetInitialData = true;
                insertData(getRowValues(), false, senderId, listenerType);
                clearSelection();
            } else if (senderId.endsWith(QPagingScrollTableOperation.CONTROLS_REFRESH)) {
                ClientApplicationContext.getInstance().log("performRefresh (senderId) : " + senderId);
            } else if (senderId.endsWith(QPagingScrollTableOperation.CONTROLS_CANCEL)) {
                if (containsModifiedData()) {
                    showPrompt(senderId, listenerType);
                }
            }
        }
    }

    private void handleAddRecord() {
        int newRowIndex = -1;
        final DataMap dummy = new DataMap();
        List<DataContainerGVO> rowValues = getRowValues();
        if (rowValues == null) {
            rowValues = new ArrayList<DataContainerGVO>();
        }

        if (rowValues.size() > 0) {
            // Add the newly record as last with column names from data
            newRowIndex = rowValues.size();
            final DataContainerGVO dm = rowValues.get(0);
            final Set<String> keys = dm.getDataMap().keySet();
            for (final String column : keys) {
                final DataContainerGVO dummydcg = new DataContainerGVO("");
                dummy.put(column, dummydcg);
            }
        } else if (source.getColumns() != null) {
            // Add the newly record as first with column names from datagrid columns
            newRowIndex = 0;
            for (final DataGridColumnGVO columnGVO : source.getColumns()) {
                final DataContainerGVO dummydcg = new DataContainerGVO("");
                dummy.put(columnGVO.getFieldName(), dummydcg);
            }
        }

        // Add the newly record after the selection, if present
        final Set<DataContainerGVO> selectedRowValues = getSelectedRowValues();
        if ((selectedRowValues != null) && (selectedRowValues.size() > 0)) {
            DataContainerGVO selectedRow = null;
            final Iterator<DataContainerGVO> itrRow = selectedRowValues.iterator();
            while (itrRow.hasNext()) {
                selectedRow = itrRow.next();
            }
            if (selectedRow != null) {
                newRowIndex = getRowNumber(selectedRow);

                int offset = 1;
                final List<DataContainerGVO> newRowValues = new ArrayList<DataContainerGVO>();
                for (int i = 0; i < rowValues.size(); i++) {
                    final DataContainerGVO rowValue = rowValues.get(i);
                    if (i == newRowIndex) {
                        newRowValues.add(null);
                        offset++;
                    }
                    if (i >= newRowIndex) {
                        updateRowNumber(rowValue, i + offset);
                    }
                    newRowValues.add(rowValue);
                }
                rowValues.clear();
                rowValues.addAll(newRowValues);
            }
        }

        if (newRowIndex > -1) {
            dummy.put(DataContainerGVO.ROW_STATUS_KEY, new DataContainerGVO(DataContainerGVO.ROW_STATUS_NEW));
            dummy.put(DataContainerGVO.ROW_NUMBER,
                    new DataContainerGVO(QAMLConstants.TOKEN_NEW + (newRowIndex + 1)));

            final DataContainerGVO newRecord = new DataContainerGVO(dummy);
            if (newRowIndex < rowValues.size()) {
                rowValues.set(newRowIndex, newRecord);
            } else {
                rowValues.add(newRecord);
            }

            try {
                refreshingExistingRows = true;
                ((QTableModel) getTableModel()).processData(rowValues);
            } finally {
                refreshingExistingRows = false;
            }
            selectRow(newRowIndex);
        }
    }

    private void handleDeleteRecord() {
        final Collection<DataContainerGVO> selectedRowValues = getSelectedRowValues();
        if (selectedRowValues == null) {
            return;
        }
        final List<DataContainerGVO> newlyRowValues = new ArrayList<DataContainerGVO>();
        for (final DataContainerGVO rowValue : selectedRowValues) {
            final DataContainerGVO statusKeyGVO = rowValue.getDataMap().get(DataContainerGVO.ROW_STATUS_KEY);
            final String statusKey = statusKeyGVO.getDataString();
            if (DataContainerGVO.ROW_STATUS_DELETED.equals(statusKey)) {
                continue;
            } else if (DataContainerGVO.ROW_STATUS_NEW.equals(statusKey)) {
                newlyRowValues.add(rowValue);
            } else {
                final DataContainerGVO rowNumberGVO = rowValue.getDataMap().get(DataContainerGVO.ROW_NUMBER);
                final String rowNumber = rowNumberGVO.getDataString().replaceAll("[" + QAMLConstants.TOKEN_NEW
                        + QAMLConstants.TOKEN_MODIFIED + QAMLConstants.TOKEN_DELETED + "]", "");
                rowNumberGVO.setDataString(QAMLConstants.TOKEN_DELETED + rowNumber);
                statusKeyGVO.setDataString(DataContainerGVO.ROW_STATUS_DELETED);
                final QLabel label = new QLabel(QAMLConstants.TOKEN_DELETED + rowNumber);
                getDataTable().setElement(Integer.parseInt(rowNumber) - 1, 0, label.getElement());
            }
        }
        if (newlyRowValues.size() > 0) {
            final List<DataContainerGVO> newRowValues = new ArrayList<DataContainerGVO>();
            final List<DataContainerGVO> rowValues = getRowValues();
            for (int i = 0; i < rowValues.size(); i++) {
                final DataContainerGVO rowValue = rowValues.get(i);
                if (newlyRowValues.contains(rowValue)) {
                    continue;
                }
                updateRowNumber(rowValue, newRowValues.size() + 1);
                newRowValues.add(rowValue);
            }
            rowValues.clear();
            rowValues.addAll(newRowValues);
            try {
                refreshingExistingRows = true;
                if (rowValues.isEmpty()) {
                    clearData();
                } else {
                    ((QTableModel) getTableModel()).processData(rowValues);
                }
            } finally {
                refreshingExistingRows = false;
            }
        }
        clearSelection();
    }

    private int getRowNumber(final DataContainerGVO rowValue) {
        int rowNumber = -1;
        if (rowValue != null) {
            final DataContainerGVO rowNumberGVO = rowValue.getDataMap().get(DataContainerGVO.ROW_NUMBER);
            final String strRowNumber = rowNumberGVO.getDataString().replaceAll("[" + QAMLConstants.TOKEN_NEW
                    + QAMLConstants.TOKEN_MODIFIED + QAMLConstants.TOKEN_DELETED + "]", "");
            rowNumber = Integer.valueOf(strRowNumber);
        }
        return rowNumber;
    }

    private void updateRowNumber(final DataContainerGVO rowValue, final int newRowNumber) {
        if (rowValue == null) {
            return;
        }
        String status = "";
        final String statusKey = rowValue.getDataMap().get(DataContainerGVO.ROW_STATUS_KEY).getDataString();
        if (DataContainerGVO.ROW_STATUS_NEW.equals(statusKey)) {
            status = QAMLConstants.TOKEN_NEW;
        } else if (DataContainerGVO.ROW_STATUS_MODIFIED.equals(statusKey)) {
            status = QAMLConstants.TOKEN_MODIFIED;
        } else if (DataContainerGVO.ROW_STATUS_DELETED.equals(statusKey)) {
            status = QAMLConstants.TOKEN_DELETED;
        }
        final DataContainerGVO rowNumberGVO = new DataContainerGVO(status + newRowNumber);
        rowValue.getDataMap().put(DataContainerGVO.ROW_NUMBER, rowNumberGVO);
    }

    /**
     * Insert a row into the table relative to the total number of rows.
     * This is exact the same as defined in the super class,
     * except the row removal based on the pagesize
     *
     * @param beforeRow the row index
     */
    @Override
    protected void insertAbsoluteRow(final int beforeRow) {
        // Physically insert the row
        final int lastRow = getAbsoluteLastRowIndex() + 1;
        if (beforeRow <= lastRow) {
            final int firstRow = getAbsoluteFirstRowIndex();
            if (beforeRow >= firstRow) {
                // Insert row in the middle of the page
                getDataTable().insertRow(beforeRow - firstRow);
            } else {
                // Insert zero row because row is before this page
                getDataTable().insertRow(0);
            }
        }
    }

    private boolean containsModifiedData() {
        for (final DataContainerGVO row : getRowValues()) {
            if (!((row.getDataMap().get(DataContainerGVO.ROW_STATUS_KEY).toString())
                    .equals(DataContainerGVO.ROW_STATUS_UNMODIFIED))) {
                return true;
            }
        }
        return false;
    }

    private void showPrompt(final String senderId, final String listenerType) {

        final org.gwt.mosaic.ui.client.MessageBox prompt = new org.gwt.mosaic.ui.client.MessageBox(
                MessageBoxType.PROMPT, "Confirm") {
            @Override
            public void onClose(final boolean result) {
            }
        };
        final Label message = new Label();
        message.setText("Click ok to reset the data to initial value.");
        final Button ok = new Button("Ok");
        ok.addClickHandler(new ClickHandler() {
            public void onClick(final ClickEvent event) {
                resetInitialData = false;
                //datagridRendered = false;
                getRowValues().clear();
                getDataTable().clear();
                final List<DataContainerGVO> cloneOfInitialData = makeClone(initialData);
                insertData(cloneOfInitialData, false, senderId, listenerType);
                prompt.removeFromParent();
                clearSelection();
            }
        });
        final Button cancel = new Button("Cancel");
        cancel.addClickHandler(new ClickHandler() {
            public void onClick(final ClickEvent event) {
                prompt.removeFromParent();
            }
        });
        final HorizontalPanel hp = new HorizontalPanel();
        hp.add(ok);
        hp.add(cancel);
        final VerticalPanel vp = new VerticalPanel();
        vp.add(message);
        vp.add(hp);
        prompt.add(vp);

        final int width = Window.getClientWidth() - 10;
        final int height = Window.getClientHeight() - 10;
        prompt.setSize(width + "", height + "");
        prompt.showModal();
    }

    private static List<DataContainerGVO> makeClone(final Collection<DataContainerGVO> data) {
        final List<DataContainerGVO> cloneData = new ArrayList<DataContainerGVO>();
        if (data != null) {
            for (final DataContainerGVO row : data) {
                if (row.isMap()) {
                    final DataContainerGVO newMap = new DataContainerGVO(new DataMap());
                    for (final String key : row.getDataMap().keySet()) {
                        final DataContainerGVO value = row.getDataMap().get(key);
                        final DataContainerGVO gvo = new DataContainerGVO(
                                value != null ? value.getDataString() : null);
                        if (value != null) {
                            gvo.setStringDataType(value.getStringDataType());
                            gvo.setDateData(value.getDateData());
                        }
                        newMap.getDataMap().put(key, gvo);

                    }
                    cloneData.add(newMap);
                }
            }
        }

        return cloneData;
    }

    private void doColumnDataChange(final ColumnDefinition<DataContainerGVO, String> columnDefinition,
            final UIObject uiObject, final DataMap rowValue, final Object oldValue, final Object newValue,
            final boolean changedByUser) {
        if ((source != null) && (source.getColumns() != null) && (columnDefinition instanceof QColumnDefinition)) {
            final QColumnDefinition qColumnDefinition = (QColumnDefinition) columnDefinition;
            DataGridColumnGVO dataGridColumnGVO = null;
            for (final DataGridColumnGVO columnGVO : source.getColumns()) {
                final String fieldName = columnGVO.getFieldName();
                if ((fieldName != null) && (fieldName.equals(qColumnDefinition.getField()))) {
                    dataGridColumnGVO = columnGVO;
                    break;
                }
            }
            ComponentRendererHelper.handleDataChange(dataGridColumnGVO, uiObject, oldValue, newValue);
            if (changedByUser) {
                changeRowStatus(rowValue, DataMap.ROW_STATUS_MODIFIED);
            }
        }
    }

    private void changeRowStatus(final DataMap rowValue, final String changeStatusTo) {
        if (refreshingExistingRows) {
            return;
        }

        if (rowValue == null) {
            return;
        }

        final DataContainerGVO rowStatusGVO = rowValue.get(DataContainerGVO.ROW_STATUS_KEY);
        if (rowStatusGVO == null) {
            return;
        }

        // Changes row status only if row is unmodified
        final String rowStatus = rowStatusGVO.getDataString();
        if (DataContainerGVO.ROW_STATUS_UNMODIFIED.equals(rowStatus)
                && !DataContainerGVO.ROW_STATUS_NEW.equals(rowStatus)) {
            final String rowNumber = rowValue.get(DataContainerGVO.ROW_NUMBER).getDataString();
            final int rowIndex = Integer.parseInt(rowNumber) - 1;
            final int rowCount = getDataTable().getRowCount();

            // Update only the status if rowCount > rowIndex, in this case value is changed by user,
            // otherwise the datagrid is being constructed so no need to update
            if (rowCount > rowIndex) {
                rowStatusGVO.setDataString(changeStatusTo);
                rowValue.get(DataContainerGVO.ROW_NUMBER).setDataString("*" + rowNumber);
                getDataTable().setElement(Integer.parseInt(rowNumber) - 1, 0,
                        new QLabel("*" + rowNumber).getElement());
            }
        }
    }

    public void onScroll(final ScrollEvent event) {
        if (scrollPosition == getDataWrapper().getScrollTop()) {
            return;
        }
        final int clientHeight = getDataWrapper().getClientHeight();
        final int scrollHeight = getDataWrapper().getScrollHeight();
        scrollPosition = getDataWrapper().getScrollTop();

        final boolean scrollBarHitsBottom = (scrollPosition + clientHeight) >= scrollHeight;
        final boolean scrollBarIsOnTop = scrollPosition == 0;
        if (!scrollBarIsOnTop && scrollBarHitsBottom) {
            scrollEvent = true;
            gotoNextPage();
        }
    }

    public boolean isScrollEvent() {
        return scrollEvent;
    }

    public void setScrollEvent(final boolean scrollEvent) {
        this.scrollEvent = scrollEvent;
    }

    public void setDataToCell(final DataContainerGVO valueToSet, final boolean b, final String senderId,
            final String cellOnRowToSet) {
        final String[] inputRef = cellOnRowToSet.split("[.]");
        final int rowIndex = getRowIndex(
                inputRef[0].toString().substring(inputRef[0].indexOf("[") + 1, inputRef[0].indexOf("]")));
        final String column = inputRef[1];
        setColumnValue(rowIndex, column, valueToSet);
    }

    public void setColumnValue(final String columnName, final DataContainerGVO value) {
        final int rowIndex = getSelectedRowIndex();
        setColumnValue(rowIndex, columnName, value);
    }

    @SuppressWarnings({ "deprecation" })
    public void setColumnValue(final int rowIndex, final String columnName, final DataContainerGVO value) {
        if (rowIndex < 0) {
            return;
        }
        final DataContainerGVO rowValue = getRowValue(rowIndex);
        if (rowValue == null) {
            return;
        }
        final DataMap dataMap = rowValue.getDataMap();

        if (hasColumnName(columnName, dataMap)) {
            final DataContainerGVO currentValue = dataMap.get(columnName);
            if (isChanged(currentValue, value)) {
                dataMap.put(columnName, value);
                changeRowStatus(dataMap, DataMap.ROW_STATUS_MODIFIED);
                setRowValue(rowIndex, rowValue);
            }
        }
    }

    @SuppressWarnings("rawtypes")
    private boolean hasColumnName(final String columnName, final DataMap dataMap) {
        if (dataMap.containsKey(columnName)) {
            return true;
        }

        final DefaultTableDefinition tableDefinition = (DefaultTableDefinition) getTableDefinition();
        final int numCols = tableDefinition.getColumnDefinitionCount();
        for (int i = 0; i < numCols; i++) {
            final QColumnDefinition columnDefinition = (QColumnDefinition) tableDefinition.getColumnDefinition(i);
            final String fieldName = columnDefinition.getField();
            if (fieldName.equals(columnName)) {
                return true;
            }
        }
        return false;
    }

    private boolean isChanged(final DataContainerGVO oldValue, final DataContainerGVO newValue) {
        if ((oldValue == null) && (newValue != null)) {
            return true;
        }
        if ((oldValue != null) && (newValue == null)) {
            return true;
        }
        if ((oldValue == null) && (newValue == null)) {
            return false;
        }
        return !oldValue.equalsValue(newValue);
    }

    /*
     * The following method returns the row number when setting or getting data is done on a data grid cell.
     * Setting and getting of datagrid cell can be done either by using the row index directly or by mentioning the change to be on the selected row.
     * */
    public int getRowIndex(final String rowIndex) {
        if (rowIndex.equals(DataMap.SELECTED_INDEX)) {
            return getSelectedRowIndex();
        }
        return Integer.parseInt(rowIndex);
    }

    private int getSelectedRowIndex() {
        final Set<DataContainerGVO> selectedRowValues = getSelectedRowValues();
        if (selectedRowValues != null) {
            for (final DataContainerGVO row : selectedRowValues) {
                final DataContainerGVO rowNumberColumn = row.getDataMap().get(DataMap.ROW_NUMBER);
                if (rowNumberColumn != null) {
                    String rowIndex = rowNumberColumn.getDataString();
                    rowIndex = rowIndex.replaceAll("[" + QAMLConstants.TOKEN_NEW + QAMLConstants.TOKEN_MODIFIED
                            + QAMLConstants.TOKEN_DELETED + "]", "");
                    return Integer.parseInt(rowIndex) - 1;
                }
                break;
            }
        }
        return -1;
    }

    public void addToDropDownValuesForColumnList(final String dropDownColumnName, final SetValueGVO setValue) {
        dropDownColumnAndValues.put(dropDownColumnName, setValue);
    }

    public Map<String, SetValueGVO> getDropDownColumnAndValues() {
        return dropDownColumnAndValues;
    }

    public void setColumnVisible(final String column, final boolean value) {
        final DataGridColumnGVO columnGVO = getColumn(column);
        if (columnGVO == null) {
            return;
        }
        columnGVO.setVisible(value);
        setTableDefinition(DataGridFactory.createTableDefinition(source, source.getColumns(), uuid, parent, this));
        refreshColumnHeaders(true);
        ((QTableModel) getTableModel()).processData(getRowValues());
        redraw();
    }

    public void setColumnLabel(final String column, final String value) {
        final DataGridColumnGVO columnGVO = getColumn(column);
        if (columnGVO == null) {
            return;
        }
        columnGVO.setDisplayname(value);
        refreshColumnHeaders(true);
    }

    private DataGridColumnGVO getColumn(final String column) {
        if ((source != null) && (source.getColumns() != null)) {
            final DataGridColumnGVO[] columns = source.getColumns();
            for (final DataGridColumnGVO columnGVO : columns) {
                if (columnGVO == null) {
                    continue;
                }
                final String columnId = columnGVO.getId();
                if ((columnId != null) && columnId.equals(column)) {
                    return columnGVO;
                }
            }
        }
        return null;
    }

    public void addRowSelectionChangeHandler(final RowSelectionChangeHandler handler) {
        if (handler != null) {
            rowSelectionChangeHandlers.add(handler);
        }
    }

    private void fireRowSelectionChange(final int rowIndex, final Object rowValue) {
        for (int i = 0; i < rowSelectionChangeHandlers.size(); i++) {
            final RowSelectionChangeHandler handler = rowSelectionChangeHandlers.get(i);
            final RowSelectionChangeEvent event = new RowSelectionChangeEvent(this, rowIndex, rowValue);
            event.dispatch(handler);
        }
    }
}