| /******************************************************************************* |
| * Copyright (c) 2012, 2020 Original 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 authors and others - initial API and implementation |
| * Dirk Fauth <dirk.fauth@googlemail.com> - Bug 455327 |
| * Dirk Fauth <dirk.fauth@googlemail.com> - Bug 444839, 444855, 453885 |
| ******************************************************************************/ |
| package org.eclipse.nebula.widgets.nattable.extension.glazedlists.groupBy; |
| |
| import java.util.Comparator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.nebula.widgets.nattable.data.IColumnAccessor; |
| import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer; |
| import org.eclipse.nebula.widgets.nattable.sort.ISortModel; |
| |
| import ca.odell.glazedlists.TreeList; |
| |
| /** |
| * The TreeList.Format that is used by the TreeList that is created and used by |
| * the GroupByDataLayer. Note that the TreeList created by the GroupByDataLayer |
| * is generic for Object because the groupBy functionality will add |
| * GroupByObjects to the path for creating the grouping. |
| * |
| * @param <T> |
| * The type of the base objects carried in the TreeList. |
| */ |
| public class GroupByTreeFormat<T> implements TreeList.Format<Object> { |
| |
| /** |
| * The GroupByModel that carries the information about the groupBy states. |
| */ |
| private final GroupByModel model; |
| /** |
| * The IColumnAccessor that is used to get the column value for the columns |
| * that are grouped by. Needed for compare operations and creating the path |
| * in the tree. |
| */ |
| private final IColumnAccessor<T> columnAccessor; |
| /** |
| * Comparator that is used to sort the TreeList based on the groupBy |
| * information. |
| */ |
| private IGroupByComparator<T> groupByComparator; |
| |
| /** |
| * |
| * @param model |
| * The GroupByModel that carries the information about the |
| * groupBy states. |
| * @param columnAccessor |
| * The IColumnAccessor that is used to get the column value for |
| * the columns that are grouped by. Needed for compare operations |
| * and creating the path in the tree. |
| */ |
| public GroupByTreeFormat(GroupByModel model, IColumnAccessor<T> columnAccessor) { |
| this.model = model; |
| this.columnAccessor = columnAccessor; |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public void getPath(List<Object> path, Object element) { |
| List<Integer> groupByColumns = this.model.getGroupByColumnIndexes(); |
| if (!groupByColumns.isEmpty()) { |
| LinkedHashMap<Integer, Object> descriptor = new LinkedHashMap<>(); |
| for (int columnIndex : groupByColumns) { |
| // Build a unique descriptor for the group |
| Object columnValue = this.columnAccessor.getDataValue((T) element, columnIndex); |
| descriptor.put(columnIndex, columnValue); |
| GroupByObject groupByObject = getGroupByObject(columnValue, descriptor); |
| path.add(groupByObject); |
| } |
| } |
| path.add(element); |
| } |
| |
| /** |
| * |
| * @param columnValue |
| * The column value that is used to create the |
| * {@link GroupByObject}. Specifies the groupBy value. |
| * @param descriptor |
| * The descriptor that is used to create the |
| * {@link GroupByObject}. Specifies the groupBy depth. |
| * @return The {@link GroupByObject} for the given value and descriptor. |
| */ |
| protected GroupByObject getGroupByObject(Object columnValue, Map<Integer, Object> descriptor) { |
| return new GroupByObject(columnValue, new LinkedHashMap<>(descriptor)); |
| } |
| |
| @Override |
| public boolean allowsChildren(Object element) { |
| return true; |
| } |
| |
| @Override |
| public Comparator<Object> getComparator(int depth) { |
| // if there is no grouping we do not provide a comparator for the tree |
| if (this.model.getGroupByColumnIndexes().isEmpty()) { |
| return null; |
| } |
| |
| return this.groupByComparator; |
| } |
| |
| /** |
| * Clear the comparator local cache of summary information that is used to |
| * increase performance on sorting. Can be called often since the cache is |
| * only valid for a sorting operation. |
| */ |
| public void clearComparatorCache() { |
| this.groupByComparator.clearCache(); |
| } |
| |
| /** |
| * |
| * @param model |
| * The {@link ISortModel} that should be set to the |
| * {@link IGroupByComparator}. |
| * @see IGroupByComparator#setSortModel(ISortModel) |
| */ |
| public void setSortModel(ISortModel model) { |
| this.groupByComparator.setSortModel(model); |
| } |
| |
| /** |
| * |
| * @return The {@link ISortModel} that is set to the |
| * {@link IGroupByComparator}. |
| * @see IGroupByComparator#getSortModel() |
| */ |
| public ISortModel getSortModel() { |
| return this.groupByComparator.getSortModel(); |
| } |
| |
| /** |
| * |
| * @param treeLayer |
| * The {@link IUniqueIndexLayer} that should be set to the |
| * {@link IGroupByComparator}. |
| * @see IGroupByComparator#setTreeLayer(IUniqueIndexLayer) |
| */ |
| void setTreeLayer(IUniqueIndexLayer treeLayer) { |
| this.groupByComparator.setTreeLayer(treeLayer); |
| } |
| |
| /** |
| * |
| * @param dataLayer |
| * The {@link GroupByDataLayer} that should be set to the |
| * {@link IGroupByComparator}. |
| * @see IGroupByComparator#setDataLayer(GroupByDataLayer) |
| */ |
| void setDataLayer(GroupByDataLayer<T> dataLayer) { |
| this.groupByComparator.setDataLayer(dataLayer); |
| } |
| |
| /** |
| * |
| * @param comparator |
| * The {@link IGroupByComparator} that should be used to sort the |
| * {@link TreeList} in order to be able to build the tree |
| * structure correctly. |
| */ |
| public void setComparator(IGroupByComparator<T> comparator) { |
| this.groupByComparator = comparator; |
| } |
| |
| } |