package org.esa.snap.rcp.statistics;
import org.esa.snap.core.datamodel.GeoPos;
import org.esa.snap.core.datamodel.TransectProfileData;
import org.esa.snap.ui.io.CsvEncoder;
import org.esa.snap.ui.io.TableModelCsvEncoder;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import javax.swing.table.AbstractTableModel;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Norman Fomferra
*/
class ProfileDataTableModel extends AbstractTableModel implements CsvEncoder {
private final static String REF_SUFFIX = "_ref";
private final TransectProfileData profileData;
private final List<String> columnNames;
private final Map<Integer, Integer> propertyIndices;
private final int[] pointDataIndexes;
private final int dataFieldIndex;
private final SimpleFeature[] features;
private final boolean computeInBetweenPoints;
public ProfileDataTableModel(String sampleName,
TransectProfileData profileData,
ProfilePlotPanel.DataSourceConfig dataSourceConfig) {
this.profileData = profileData;
pointDataIndexes = new int[profileData.getNumPixels()];
Arrays.fill(pointDataIndexes, -1);
int[] shapeVertexIndexes = profileData.getShapeVertexIndexes();
for (int i = 0; i < shapeVertexIndexes.length; i++) {
int shapeVertexIndex = shapeVertexIndexes[i];
pointDataIndexes[shapeVertexIndex] = i;
}
computeInBetweenPoints = dataSourceConfig.computeInBetweenPoints;
final String corrDataName;
if (dataSourceConfig.pointDataSource != null && dataSourceConfig.dataField != null) {
corrDataName = dataSourceConfig.dataField.getLocalName();
features = dataSourceConfig.pointDataSource.getFeatureCollection().toArray(new SimpleFeature[0]);
dataFieldIndex = dataSourceConfig.pointDataSource.getFeatureType().indexOf(corrDataName);
} else {
corrDataName = "";
features = null;
dataFieldIndex = -1;
}
columnNames = new ArrayList<String>();
columnNames.add("pixel_no");
columnNames.add("pixel_x");
columnNames.add("pixel_y");
columnNames.add("latitude");
columnNames.add("longitude");
columnNames.add(sampleName + "_mean");
columnNames.add(sampleName + "_sigma");
columnNames.add(corrDataName.trim().length() == 0 ? "" : corrDataName + REF_SUFFIX);
propertyIndices = new HashMap<Integer, Integer>();
if (features != null && features.length > 0) {
final int colStart = 8;
int validPropertyCount = 0;
final Collection<Property> props = features[0].getProperties();
final Property[] properties = props.toArray(new Property[props.size()]);
for (int i = 0; i < properties.length; i++) {
Property property = properties[i];
final String name = property.getName().toString();
if (!corrDataName.equals(name)) {
columnNames.add(name + REF_SUFFIX);
propertyIndices.put(colStart + validPropertyCount, i);
validPropertyCount++;
}
}
}
}
@Override
public int getColumnCount() {
return columnNames.size();
}
@Override
public String getColumnName(int column) {
return columnNames.get(column);
}
@Override
public int getRowCount() {
return computeInBetweenPoints ? profileData.getNumPixels() : profileData.getNumShapeVertices();
}
@Override
public Object getValueAt(int row, int column) {
int pixelIndex = computeInBetweenPoints ? row : profileData.getShapeVertexIndexes()[row];
if (column == 0) {
return pixelIndex + 1;
} else if (column == 1) {
return profileData.getPixelPositions()[pixelIndex].getX();
} else if (column == 2) {
return profileData.getPixelPositions()[pixelIndex].getY();
} else if (column == 3) {
GeoPos[] geoPositions = profileData.getGeoPositions();
return geoPositions.length > 0 ? geoPositions[pixelIndex].getLat() : null;
} else if (column == 4) {
GeoPos[] geoPositions = profileData.getGeoPositions();
return geoPositions.length > 0 ? geoPositions[pixelIndex].getLon() : null;
} else if (column == 5) {
return profileData.getSampleValues()[pixelIndex];
} else if (column == 6) {
return profileData.getSampleSigmas()[pixelIndex];
} else if (column == 7) {
if (dataFieldIndex == -1) {
return null;
}
int pointDataIndex = pointDataIndexes[pixelIndex];
if (pointDataIndex == -1) {
return null;
}
return features[pointDataIndex].getAttribute(dataFieldIndex);
} else if (column < getColumnCount()) {
int pointDataIndex = pointDataIndexes[pixelIndex];
if (pointDataIndex == -1) {
return null;
}
final Collection<Property> propColl = features[pointDataIndex].getProperties();
final Property[] properties = propColl.toArray(new Property[propColl.size()]);
final Integer propertyIndex = propertyIndices.get(column);
return properties[propertyIndex].getValue();
}
return null;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
public String toCsv() {
StringWriter sw = new StringWriter();
try {
encodeCsv(sw);
sw.close();
} catch (IOException e) {
throw new IllegalStateException(e);
}
return sw.toString();
}
@Override
public void encodeCsv(Writer writer) throws IOException {
new TableModelCsvEncoder(this).encodeCsv(writer);
}
}