| /*=============================================================================# |
| # Copyright (c) 2012, 2021 Original NatTable authors and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 |
| # |
| # Contributors: |
| # Original NatTable authors and others - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.ecommons.waltable.data; |
| |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| |
| |
| /** |
| * 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(final List<T> list, final 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 long getRowCount() { |
| long numberOfInvisible= 0; |
| for (final 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(final long columnIndex, final long rowIndex, final int flags, final IProgressMonitor monitor) { |
| final 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(final long columnIndex, final long rowIndex, final Object newValue) { |
| final 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(final long rowIndex) { |
| if (rowIndex >= Integer.MAX_VALUE) { |
| return null; |
| } |
| T object= null; |
| long 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 long indexOfRowObject(final T rowObject) { |
| final 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); |
| } |