/*******************************************************************************
* Copyright (c) 2012 Original authors and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Original authors and others - initial API and implementation
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.data;
import java.util.List;
/**
* Enables the use of a {@link List} containing POJO(s) as a backing data
* source.
*
* By default a bean at position 'X' in the list is displayed in row 'X' in the
* table. The properties of the bean are used to populate the columns. A
* {@link IColumnPropertyResolver} is used to retrieve column data from the bean
* properties.
*
* By implementing filter logic within
* {@link AbstractFilterListDataProvider#show(Object)} it is possible to create
* a static filter. All data access methods will skip invisible items within the
* wrapped list and delegate access to the visible items.
*
* NOTE: This way of static filtering can cause performance issues for huge data
* sets where a lot of items are filtered, because data access will always
* calculate the visible row position. Trying to use a caching mechanism would
* create some issues for deleting or inserting new data to the wrapped list.
*
* TODO add caching that reacts on insert/delete actions on the wrapped list
*
* @param <T>
* type of the Objects in the backing list.
* @see IColumnPropertyResolver
*/
public abstract class AbstractFilterListDataProvider<T> extends
ListDataProvider<T> {
public AbstractFilterListDataProvider(List<T> list,
IColumnAccessor<T> columnAccessor) {
super(list, columnAccessor);
}
/**
* Iterates over the whole list of data objects and checks the visibility
* for every object. The number of non visible items will be subtracted from
* the size of the wrapped list to return the number of visible items.
*/
@Override
public int getRowCount() {
int numberOfInvisible = 0;
for (T object : this.list) {
if (!show(object)) {
numberOfInvisible++;
}
}
return this.list.size() - numberOfInvisible;
}
/**
* Get the data value for the columnIndex and the visible rowIndex.
*/
@Override
public Object getDataValue(int columnIndex, int rowIndex) {
T rowObj = getRowObject(rowIndex);
return this.columnAccessor.getDataValue(rowObj, columnIndex);
}
/**
* Set the data value for the columnIndex and the visible rowIndex.
*/
@Override
public void setDataValue(int columnIndex, int rowIndex, Object newValue) {
T rowObj = getRowObject(rowIndex);
this.columnAccessor.setDataValue(rowObj, columnIndex, newValue);
}
/**
* Returns the object for the visible rowIndex. To do this it is iterated
* over the wrapped list, taking the invisible items into account, so the
* real row index for the given visible row index is calculated.
*/
@Override
public T getRowObject(int rowIndex) {
T object = null;
int count = 0;
int realRowIndex = 0;
while (count <= rowIndex) {
object = this.list.get(realRowIndex);
if (show(object)) {
count++;
}
realRowIndex++;
}
return object;
}
/**
* Returns the visible rowIndex for the given object. To do this the real
* row index for the object within the wrapped list is searched and then all
* invisible items are subtracted from the real row index to calculate the
* visible row index.
*/
@Override
public int indexOfRowObject(T rowObject) {
int realRowIndex = this.list.indexOf(rowObject);
int filteredIndex = realRowIndex;
// now find number of not visible items
T vf = null;
for (int i = 0; i <= realRowIndex; i++) {
vf = this.list.get(i);
if (!show(vf)) {
filteredIndex--;
}
}
return filteredIndex;
}
/**
* Within this method the filter logic should be applied. Return false if
* the object should not be visible within the grid. Return true if it
* should be visible.
*
* @param object
* The object that should be checked.
* @return true if the object should be visible, false if not
*/
protected abstract boolean show(T object);
}