OOMetricsTableModel.java
/*
* Copyright (c) 2001-2024, Jean Tessier
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Jean Tessier nor the names of his contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jeantessier.dependencyfinder.gui;
import com.jeantessier.metrics.Measurement;
import com.jeantessier.metrics.MeasurementDescriptor;
import com.jeantessier.metrics.Metrics;
import com.jeantessier.metrics.MetricsComparator;
import com.jeantessier.metrics.StatisticalMeasurement;
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class OOMetricsTableModel extends AbstractTableModel {
private static final Integer LOCAL_DISPOSE_IGNORE = StatisticalMeasurement.DISPOSE_IGNORE;
private static final Integer LOCAL_DISPOSE_MINIMUM = StatisticalMeasurement.DISPOSE_MINIMUM;
private static final Integer LOCAL_DISPOSE_MEDIAN = StatisticalMeasurement.DISPOSE_MEDIAN;
private static final Integer LOCAL_DISPOSE_AVERAGE = StatisticalMeasurement.DISPOSE_AVERAGE;
private static final Integer LOCAL_DISPOSE_STANDARD_DEVIATION = StatisticalMeasurement.DISPOSE_STANDARD_DEVIATION;
private static final Integer LOCAL_DISPOSE_MAXIMUM = StatisticalMeasurement.DISPOSE_MAXIMUM;
private static final Integer LOCAL_DISPOSE_SUM = StatisticalMeasurement.DISPOSE_SUM;
// private static final Integer LOCAL_DISPOSE_NB_DATA_POINTS = StatisticalMeasurement.DISPOSE_NB_DATA_POINTS;
private final List<MeasurementDescriptor> descriptors;
private List<Metrics> metricsList;
private String[] measurementNames;
private MeasurementDescriptor[] measurementDescriptors;
private int[] measurementDispose;
private Object[][] measurementValues;
private final MetricsComparator comparator = new MetricsComparator("name");
public OOMetricsTableModel(List<MeasurementDescriptor> descriptors) {
this.descriptors = descriptors;
buildMetricNames();
buildMetricValues();
}
public void setMetrics(Collection<Metrics> metricsList) {
this.metricsList = new ArrayList<>(metricsList);
if (metricsList.isEmpty()) {
buildMetricValues();
} else {
this.metricsList.sort(comparator);
buildMetricValues(this.metricsList);
}
fireTableStructureChanged();
}
public MeasurementDescriptor getColumnDescriptor(int column) {
return measurementDescriptors[column];
}
public void updateMetrics(Collection<Metrics> metricsList) {
this.metricsList = new ArrayList<>(metricsList);
if (metricsList.isEmpty()) {
buildMetricValues();
} else {
this.metricsList.sort(comparator);
buildMetricValues(this.metricsList);
}
fireTableDataChanged();
}
public void sortOn(String name, int dispose) {
comparator.sortOn(name, dispose);
metricsList.sort(comparator);
buildMetricValues(metricsList);
fireTableDataChanged();
}
private void buildMetricNames() {
List<String> names = new LinkedList<>();
names.add("name");
List<MeasurementDescriptor> columnDescriptors = new LinkedList<>();
columnDescriptors.add(null);
List<Integer> dispose = new LinkedList<>();
dispose.add(LOCAL_DISPOSE_IGNORE);
descriptors.stream()
.filter(MeasurementDescriptor::isVisible)
.forEach(descriptor -> {
if (descriptor.getClassFor().equals(StatisticalMeasurement.class)) {
names.add(descriptor.getShortName());
columnDescriptors.add(descriptor);
dispose.add(LOCAL_DISPOSE_MINIMUM);
names.add(descriptor.getShortName());
columnDescriptors.add(descriptor);
dispose.add(LOCAL_DISPOSE_MEDIAN);
names.add(descriptor.getShortName());
columnDescriptors.add(descriptor);
dispose.add(LOCAL_DISPOSE_AVERAGE);
names.add(descriptor.getShortName());
columnDescriptors.add(descriptor);
dispose.add(LOCAL_DISPOSE_STANDARD_DEVIATION);
names.add(descriptor.getShortName());
columnDescriptors.add(descriptor);
dispose.add(LOCAL_DISPOSE_MAXIMUM);
names.add(descriptor.getShortName());
columnDescriptors.add(descriptor);
dispose.add(LOCAL_DISPOSE_SUM);
} else {
names.add(descriptor.getShortName());
columnDescriptors.add(descriptor);
dispose.add(LOCAL_DISPOSE_IGNORE);
}
});
measurementNames = names.toArray(new String[0]);
measurementDescriptors = columnDescriptors.toArray(new MeasurementDescriptor[0]);
measurementDispose = new int[dispose.size()];
IntStream.range(0, dispose.size()).forEach(i -> measurementDispose[i] = dispose.get(i));
}
private void buildMetricValues() {
measurementValues = new Object[0][];
}
private void buildMetricValues(Collection<Metrics> metricsList) {
measurementValues = new Object[metricsList.size()][];
int i = 0;
for (Metrics currentMetrics : metricsList) {
var measurements = descriptors.stream()
.filter(MeasurementDescriptor::isVisible)
.map(descriptor -> currentMetrics.getMeasurement(descriptor.getShortName()))
.flatMap(measurement -> measurement instanceof StatisticalMeasurement ? Stream.of(measurement, measurement, measurement, measurement, measurement, measurement) : Stream.of(measurement))
.toList();
measurementValues[i] = new Object[measurements.size() + 1];
int j = 0;
measurementValues[i][j++] = currentMetrics.getName();
for (Measurement measurement : measurements) {
measurementValues[i][j++] = measurement;
}
i++;
}
}
public int getColumnCount() {
return measurementNames.length;
}
public int getRowCount() {
return measurementValues.length;
}
public Object getValueAt(int rowIndex, int columnIndex) {
return measurementValues[rowIndex][columnIndex];
}
public String getRawColumnName(int column) {
return measurementNames[column];
}
public int getRawColumnDispose(int column) {
return measurementDispose[column];
}
public String getColumnName(int column) {
return switch (getRawColumnDispose(column)) {
case StatisticalMeasurement.DISPOSE_MINIMUM:
case StatisticalMeasurement.DISPOSE_MEDIAN:
case StatisticalMeasurement.DISPOSE_AVERAGE:
case StatisticalMeasurement.DISPOSE_STANDARD_DEVIATION:
case StatisticalMeasurement.DISPOSE_MAXIMUM:
case StatisticalMeasurement.DISPOSE_SUM:
yield getRawColumnName(column) + " (" + StatisticalMeasurement.getDisposeAbbreviation(getRawColumnDispose(column)) + ")";
case StatisticalMeasurement.DISPOSE_IGNORE:
case StatisticalMeasurement.DISPOSE_NB_DATA_POINTS:
default:
yield getRawColumnName(column);
};
}
}