/*
This file is part of RouteConverter.
RouteConverter is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
RouteConverter is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RouteConverter; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2007 Christian Pesch. All Rights Reserved.
*/
package slash.navigation.converter.gui.models;
import slash.common.type.CompactCalendar;
import slash.navigation.base.BaseNavigationFormat;
import slash.navigation.base.BaseNavigationPosition;
import slash.navigation.base.BaseRoute;
import slash.navigation.common.BoundingBox;
import slash.navigation.common.NavigationPosition;
import slash.navigation.converter.gui.predicates.FilterPredicate;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import java.io.IOException;
import java.util.*;
import static slash.common.io.Transfer.toArray;
/**
* Implements a {@link PositionsModel} that filters positions.
*
* @author Christian Pesch
*/
public class FilteringPositionsModel extends AbstractTableModel implements PositionsModel {
private final PositionsModel delegate;
private FilterPredicate predicate;
private Map<Integer, Integer> mapping;
public FilteringPositionsModel(PositionsModel delegate, FilterPredicate predicate) {
this.delegate = delegate;
this.predicate = predicate;
initializeMapping();
delegate.addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
initializeMapping();
fireTableDataChanged();
}
});
}
private void initializeMapping() {
mapping = new HashMap<>();
for (int i = 0, c = delegate.getRowCount(); i < c; i++) {
NavigationPosition position = delegate.getPosition(i);
if (predicate.shouldInclude(position)) {
int mappedRow = mapping.size();
mapping.put(mappedRow, i);
}
}
}
private int mapRow(int rowIndex) {
Integer integer = mapping.get(rowIndex);
return integer != null ? integer : -1;
}
public int[] mapRows(int[] rowIndices) {
List<Integer> result = new ArrayList<>();
for(int rowIndex : rowIndices) {
int mappedRow = mapRow(rowIndex);
if(mappedRow != -1)
result.add(mappedRow);
}
return toArray(result);
}
public BaseRoute getRoute() {
return delegate.getRoute();
}
public void setRoute(BaseRoute route) {
delegate.setRoute(route);
}
public void setFilterPredicate(FilterPredicate predicate) {
this.predicate = predicate;
initializeMapping();
fireTableDataChanged();
}
public int getRowCount() {
return mapping.size();
}
public int getColumnCount() {
throw new IllegalArgumentException("This is determined by the PositionsTableColumnModel");
}
public Object getValueAt(int rowIndex, int columnIndex) {
return delegate.getValueAt(mapRow(rowIndex), columnIndex);
}
public NavigationPosition getPosition(int rowIndex) {
return delegate.getPosition(mapRow(rowIndex));
}
public int getIndex(NavigationPosition position) {
return mapRow(delegate.getIndex(position));
}
public List<NavigationPosition> getPositions(int[] rowIndices) {
throw new UnsupportedOperationException();
}
public List<NavigationPosition> getPositions(int firstIndex, int lastIndex) {
throw new UnsupportedOperationException();
}
public int[] getContainedPositions(BoundingBox boundingBox) {
throw new UnsupportedOperationException();
}
public int[] getPositionsWithinDistanceToPredecessor(double distance) {
throw new UnsupportedOperationException();
}
public int[] getInsignificantPositions(double threshold) {
throw new UnsupportedOperationException();
}
public int getClosestPosition(double longitude, double latitude, double threshold) {
throw new UnsupportedOperationException();
}
public int getClosestPosition(CompactCalendar time, long threshold) {
throw new UnsupportedOperationException();
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return delegate.isCellEditable(mapRow(rowIndex), columnIndex);
}
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
delegate.setValueAt(aValue, mapRow(rowIndex), columnIndex);
}
public void edit(int rowIndex, PositionColumnValues columnToValues, boolean fireEvent, boolean trackUndo) {
delegate.edit(mapRow(rowIndex), columnToValues, fireEvent, trackUndo);
}
public void add(int rowIndex, Double longitude, Double latitude, Double elevation, Double speed, CompactCalendar time, String description) {
throw new UnsupportedOperationException();
}
public void add(int rowIndex, BaseRoute<BaseNavigationPosition, BaseNavigationFormat> route) throws IOException {
throw new UnsupportedOperationException();
}
public void add(int rowIndex, List<BaseNavigationPosition> positions) {
throw new UnsupportedOperationException();
}
public void remove(int firstIndex, int lastIndex) {
throw new UnsupportedOperationException();
}
public void remove(int[] rowIndices) {
delegate.remove(mapRows(rowIndices));
}
public void sort(Comparator<NavigationPosition> comparator) {
throw new UnsupportedOperationException();
}
public void revert() {
throw new UnsupportedOperationException();
}
public void top(int[] rowIndices) {
throw new UnsupportedOperationException();
}
public void up(int[] rowIndices, int delta) {
throw new UnsupportedOperationException();
}
public void down(int[] rowIndices, int delta) {
throw new UnsupportedOperationException();
}
public void bottom(int[] rowIndices) {
throw new UnsupportedOperationException();
}
public boolean isContinousRange() {
return delegate.isContinousRange();
}
public void fireTableRowsUpdated(int firstIndex, int lastIndex, int columnIndex) {
delegate.fireTableRowsUpdated(firstIndex, lastIndex, columnIndex);
}
}