SiLeBAT/FSK-Lab

View on GitHub
de.bund.bfr.knime.foodprocess.view/src/de/bund/bfr/knime/foodprocess/view/MyChartCreator.java

Summary

Maintainability
F
5 days
Test Coverage
File `MyChartCreator.java` has 335 lines of code (exceeds 250 allowed). Consider refactoring.
/*******************************************************************************
* Copyright (c) 2015 Federal Institute for Risk Assessment (BfR), Germany
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* Department Biological Safety - BfR
*******************************************************************************/
package de.bund.bfr.knime.foodprocess.view;
 
import java.awt.Color;
import java.awt.Font;
import java.awt.Paint;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
 
import org.apache.xmlbeans.XmlCursor;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.data.xy.XYDataset;
import org.knime.core.data.DataCell;
import org.knime.core.data.DataRow;
import org.knime.core.data.DataTable;
import org.knime.core.data.DataTableSpec;
import org.knime.core.data.def.DefaultRow;
import org.knime.core.data.def.DoubleCell;
import org.knime.core.data.def.StringCell;
 
import de.bund.bfr.knime.pcml.node.pcmltotable.PCMLDataTable;
import de.bund.bfr.knime.pmm.common.chart.ColorAndShapeCreator;
import de.bund.bfr.knime.pmm.common.pmmtablemodel.AttributeUtilities;
import de.bund.bfr.knime.util.FormulaEvaluator;
import de.bund.bfr.knime.util.NameAndDbId;
import de.bund.bfr.pcml10.PCMLDocument;
import de.bund.bfr.pcml10.ProcessDataDocument.ProcessData;
import de.bund.bfr.pcml10.ProcessNodeDocument.ProcessNode;
import de.bund.bfr.pcml10.RowDocument.Row;
 
public class MyChartCreator {
 
private List<ProcessLegendElement> processLegend;
private ViewUi vui;
 
public MyChartCreator(ViewUi vui) {
this.vui = vui;
}
 
public List<ProcessLegendElement> getProcessLegend() {
return processLegend;
}
 
public JFreeChart createChart(PCMLDocument pcmlDoc, List<String> usedParameters, String xUnits) {
return createChart(pcmlDoc, usedParameters, xUnits, false, false, false);
}
 
Method `createChart` has a Cognitive Complexity of 29 (exceeds 5 allowed). Consider refactoring.
Method `createChart` has 41 lines of code (exceeds 25 allowed). Consider refactoring.
Method `createChart` has 6 arguments (exceeds 4 allowed). Consider refactoring.
Refactor this method to reduce its Cognitive Complexity from 29 to the 15 allowed.
public JFreeChart createChart(PCMLDocument pcmlDoc, List<String> usedParameters, String xUnits,
boolean equidistantProcesses, boolean plotLines, boolean plotPoints) {
Map<NameAndDbId, Integer> columns = PCMLDataTable.createColumnMap(pcmlDoc);
Map<String, ProcessNode> processNodes = PCMLDataTable.createProcessNodeMap(pcmlDoc);
DataTableSpec spec = PCMLDataTable.createOutSpec(columns);
 
Double timeDiff = null;
List<DataRow> rowList = new ArrayList<DataRow>();
for (ProcessData data : pcmlDoc.getPCML().getProcessChainData().getProcessDataArray()) {
ProcessNode processNode = processNodes.get(data.getRef());
double time = data.getTime();
if (timeDiff == null)
timeDiff = time;
time = time - timeDiff;
Map<String, NameAndDbId> columnList = PCMLDataTable.createColumnList(data.getDataTable().getColumnList());
NameAndDbId c0 = columnList.get("c0");
NameAndDbId timeColumn = (c0 != null && c0.getName().startsWith(AttributeUtilities.TIME)) ? c0 : null;
double curTime = 0;
for (Row row : data.getDataTable().getInlineTable().getRowArray()) {
XmlCursor cursor = row.newCursor();
cursor.toFirstChild();
Map<NameAndDbId, String> rowData = new HashMap<NameAndDbId, String>();
for (int i = 0; i < columnList.size(); i++) {
NameAndDbId column = columnList.get(cursor.getName().getLocalPart());
Identical blocks of code found in 2 locations. Consider refactoring.
if (timeColumn == null || !timeColumn.equals(column))
rowData.put(column, cursor.getTextValue());
else
curTime = (cursor.getTextValue() != null && !cursor.getTextValue().equalsIgnoreCase("null"))
? Double.valueOf(cursor.getTextValue()) : 0.0;
cursor.toNextSibling();
}
cursor.dispose();
double theTime = timeColumn != null ? curTime : time;
DataCell[] cells = PCMLDataTable.createDataCells(theTime, rowData, processNode, columns);
DataRow dataRow = new DefaultRow(theTime + "_" + processNode.getId(), cells); // RowKey.createRowKey(counter)
rowList.add(dataRow);
 
Identical blocks of code found in 2 locations. Consider refactoring.
if (timeColumn == null) {
// increment time by the time step of the process node
double stepWidth = processNode.getParameters().getDuration()
/ processNode.getParameters().getNumberComputations();
time = time + stepWidth;
}
}
}
return createChart(spec, rowList, null, usedParameters, xUnits, equidistantProcesses, plotLines, plotPoints);
}
 
Method `createChart` has 6 arguments (exceeds 4 allowed). Consider refactoring.
public JFreeChart createChart(DataTable table, List<String> usedParameters, String xUnits,
boolean equidistantProcesses, boolean plotLines, boolean plotPoints) {
return createChart(table.getDataTableSpec(), null, table, usedParameters, xUnits, equidistantProcesses, plotLines, plotPoints);
}
 
private Iterator<DataRow> getIterator(List<DataRow> rowList, DataTable table) {
if (rowList != null)
return rowList.iterator();
else if (table != null)
return table.iterator();
else
return null;
}
 
Method `createChart` has a Cognitive Complexity of 95 (exceeds 5 allowed). Consider refactoring.
Method `createChart` has 141 lines of code (exceeds 25 allowed). Consider refactoring.
Method `createChart` has 8 arguments (exceeds 4 allowed). Consider refactoring.
Refactor this method to reduce its Cognitive Complexity from 120 to the 15 allowed.
private JFreeChart createChart(DataTableSpec spec, List<DataRow> rowList, DataTable table,
List<String> usedParameters, String xUnits, boolean equidistantProcesses, boolean plotLines, boolean plotPoints) {
LinkedList<XYDataset> dataSets = new LinkedList<XYDataset>();
LinkedList<XYDataset> equiDataSets = new LinkedList<XYDataset>();
int timeIndex = spec.findColumnIndex(AttributeUtilities.TIME + " [s]");
int processIndex = spec.findColumnIndex("process");
int processIdIndex = spec.findColumnIndex("process id");
 
LinkedList<Point2D.Double> ranges = new LinkedList<Point2D.Double>();
LinkedList<String> processNames = new LinkedList<String>();
double processStart = Double.NaN;
double time = Double.NaN;
boolean pFilled = false;
 
for (String param : usedParameters) {
int paramIndex = spec.findColumnIndex(param);
Consider simplifying this complex logical expression.
if (paramIndex >= 0) {
LinkedHashMap<Double, Double> timeSeries = new LinkedHashMap<Double, Double>();
boolean paramDone = false;
String process = null, lastP = null;
 
double ds = FormulaEvaluator.getSeconds(xUnits);
boolean param2Cumulate = !JCheckboxWithObject.isTemperature(param) && !JCheckboxWithObject.isPH(param)
&& !JCheckboxWithObject.isAW(param) && !JCheckboxWithObject.isPressure(param)
&& !JCheckboxWithObject.isAgent(param) && !JCheckboxWithObject.isWithUnit(param);
Iterator<DataRow> iter = getIterator(rowList, table);
while (iter.hasNext()) {
DataRow row = iter.next();
DataCell timeCell = row.getCell(timeIndex);
DataCell paramCell = row.getCell(paramIndex);
DataCell processCell = row.getCell(processIndex);
DataCell processIdCell = row.getCell(processIdIndex);
 
if (!timeCell.isMissing()) {
String p = ((StringCell) processIdCell).getStringValue();
boolean newP = false;
Avoid deeply nested control flow statements.
if (!p.equals(process)) {
newP = true;
if (process != null) {
if (!pFilled) {
ranges.add(new Point2D.Double(processStart, time));
processNames.add(lastP);
}
}
double newPS = ((DoubleCell) timeCell).getDoubleValue() / ds;
if (newPS <= processStart && timeSeries.size() > 0) {
// processflow splits into parallel processes
if (!param2Cumulate) {
addDataset(dataSets, paramDone ? "" : param, timeSeries);
addDataset(equiDataSets, paramDone ? "" : param, getEquiSeries(timeSeries, ranges));
timeSeries = new LinkedHashMap<Double, Double>();
paramDone = true;
}
}
processStart = newPS;
process = p;
lastP = ((StringCell) processCell).getStringValue();
}
time = ((DoubleCell) timeCell).getDoubleValue() / ds;
 
Avoid deeply nested control flow statements.
if (!paramCell.isMissing()) {
Double val = ((DoubleCell) paramCell).getDoubleValue();
if (param2Cumulate && !newP) {
if (timeSeries.containsKey(time))
timeSeries.put(time, val + timeSeries.get(time));
else
timeSeries.put(time, val);
} else if (!timeSeries.containsKey(time)) {
// System.err.println(param + "\t" + lastP +
// "\t" + time + "\t" + val);
timeSeries.put(time, val);
} else if (newP) {
// System.err.println(param + "\t" + lastP +
// "\t" + time + "\t" + val);
timeSeries.put(time + 0.00001, val);
}
}
}
}
if (!pFilled) {
ranges.add(new Point2D.Double(processStart, time));
processNames.add(lastP);
pFilled = true;
}
if (timeSeries.size() > 0) {
addDataset(dataSets, paramDone ? "" : param, timeSeries);
addDataset(equiDataSets, paramDone ? "" : param, getEquiSeries(timeSeries, ranges));
}
}
}
 
if (processLegend == null || processLegend.size() == 0) {
processLegend = new ArrayList<ProcessLegendElement>();
List<Color> colorList = new ColorAndShapeCreator(ranges.size()).getColorList();
for (int i = 0; i < processNames.size(); i++) {
String pn = processNames.get(i);
ProcessLegendElement ple = new ProcessLegendElement(pn, colorList.get(i), vui);
processLegend.add(ple);
}
}
 
MyXAxis xaxis = new MyXAxis(AttributeUtilities.TIME + " [" + xUnits + "]", ranges, processNames,
equidistantProcesses);
XYPlot plot = new XYPlot(null, xaxis, null, null);
plot.setDomainPannable(true);
plot.setRangePannable(true);
 
// ColorAndShapeCreator colorCreator = new
// ColorAndShapeCreator(usedParameters.size());
int lastI = 0;
StandardXYItemRenderer renderer = null;
Color lastBG = null;
String lastParam = null;
List<NumberAxis> matrixAxes = new ArrayList<NumberAxis>();
List<NumberAxis> agentAxes = new ArrayList<NumberAxis>();
if (equidistantProcesses)
dataSets = equiDataSets;
for (int i = 0; i < dataSets.size(); i++) {
String param = dataSets.get(i).getSeriesKey(0).toString();
Color color = getColor(param, lastBG, lastParam);
lastBG = color;
lastParam = param;
plot.setDataset(i, dataSets.get(i));
if (!param.isEmpty()) {
lastI = i;
// Only plots points (no lines)
int rendererType;
if (plotPoints && plotLines) {
rendererType = StandardXYItemRenderer.SHAPES_AND_LINES;
} else if (plotPoints && !plotLines) {
rendererType = StandardXYItemRenderer.SHAPES;
} else if (!plotPoints && plotLines) {
rendererType = StandardXYItemRenderer.LINES;
} else {
rendererType = 0;
}
renderer = new StandardXYItemRenderer(rendererType);
renderer.setSeriesPaint(0, color);
plot.setRenderer(i, renderer);
NumberAxis rangeAxis = getNumberAxis(param, color);
plot.setRangeAxis(i, rangeAxis);
plot.mapDatasetToRangeAxis(i, i);
if (i > 0) {
double diffY = Math.random() * (rangeAxis.getUpperBound() - rangeAxis.getLowerBound()) / 5;
rangeAxis.setRange(rangeAxis.getLowerBound() - diffY, rangeAxis.getUpperBound() + diffY);
}
if (JCheckboxWithObject.isAgent(param))
agentAxes.add(rangeAxis);
else if (JCheckboxWithObject.isMatrix(param))
matrixAxes.add(rangeAxis);
} else {
plot.setRenderer(i, renderer);
plot.mapDatasetToRangeAxis(i, lastI);
}
}
setBounds(agentAxes);
setBounds(matrixAxes);
 
JFreeChart jfc = new JFreeChart(null, JFreeChart.DEFAULT_TITLE_FONT, plot, false);
return jfc;
}
 
Method `setBounds` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.
private void setBounds(List<NumberAxis> axes) {
Double lb = null;
Double ub = null;
for (NumberAxis na : axes) {
if (lb == null || na.getLowerBound() < lb)
lb = na.getLowerBound();
if (ub == null || na.getUpperBound() > ub)
ub = na.getUpperBound();
}
if (lb != null && ub != null) {
for (NumberAxis na : axes) {
na.setRange(lb, ub);
}
}
}
 
Method `getColor` has a Cognitive Complexity of 16 (exceeds 5 allowed). Consider refactoring.
Method `getColor` has 33 lines of code (exceeds 25 allowed). Consider refactoring.
Refactor this method to reduce its Cognitive Complexity from 19 to the 15 allowed.
private Color getColor(String param, Color lastBG, String lastParam) {
Color bg = Color.WHITE;
@SuppressWarnings("unused")
Color fg = Color.BLACK;
if (JCheckboxWithObject.isTemperature(param)) {
bg = Color.BLUE;
fg = Color.WHITE;
} else if (JCheckboxWithObject.isAW(param)) {
bg = new Color(160, 82, 45);
fg = Color.WHITE;
} else if (JCheckboxWithObject.isPH(param)) {
bg = Color.GREEN;
} else if (JCheckboxWithObject.isPressure(param)) {
bg = Color.BLACK;
Similar blocks of code found in 3 locations. Consider refactoring.
} else if (JCheckboxWithObject.isAgent(param)) {
if (lastParam != null && JCheckboxWithObject.isAgent(lastParam))
bg = lastBG.darker();
else
bg = Color.RED;
fg = Color.WHITE;
Similar blocks of code found in 3 locations. Consider refactoring.
} else if (JCheckboxWithObject.isMatrix(param)) {
if (lastParam != null && JCheckboxWithObject.isMatrix(lastParam))
bg = lastBG.brighter();
else
bg = Color.DARK_GRAY;
fg = Color.WHITE;
Similar blocks of code found in 3 locations. Consider refactoring.
} else if (JCheckboxWithObject.isWithUnit(param)) {
if (lastParam != null && JCheckboxWithObject.isWithUnit(lastParam))
bg = lastBG.brighter();
else
bg = Color.LIGHT_GRAY;
fg = Color.BLACK;
}
return bg;
}
 
private NumberAxis getNumberAxis(String param, Paint axisColor) {
NumberAxis rangeAxis = new NumberAxis(param);
// set colors
if (axisColor != null) {
rangeAxis.setAxisLinePaint(axisColor);
rangeAxis.setLabelPaint(axisColor);
rangeAxis.setLabelFont(new Font("SansSerif", Font.BOLD, 12));
// rangeAxis.setTickLabelPaint(axisColor);
// rangeAxis.setTickMarkPaint(axisColor);
}
return rangeAxis;
}
 
private void addDataset(List<XYDataset> dataSets, String param, LinkedHashMap<Double, Double> timeSeries) {
int n = timeSeries.size();
double[][] data = new double[2][n];
 
int i = 0;
for (Double time : timeSeries.keySet()) {
data[0][i] = time;
data[1][i] = timeSeries.get(time);
i++;
}
 
DefaultXYDataset dataSet = new DefaultXYDataset();
 
dataSet.addSeries(param, data);
dataSets.add(dataSet);
}
 
Method `getEquiSeries` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
private LinkedHashMap<Double, Double> getEquiSeries(LinkedHashMap<Double, Double> timeSeries,
LinkedList<Point2D.Double> ranges) {
LinkedHashMap<Double, Double> result = new LinkedHashMap<Double, Double>();
for (Double time : timeSeries.keySet()) {
Double value = timeSeries.get(time);
int p2dLfd = 0;
for (Point2D.Double p2d : ranges) {
if (time >= p2d.x && time <= p2d.y) {
result.put(p2dLfd + (time - p2d.x) / (p2d.y - p2d.x), value);
/*
* if (processLegend != null && processLegend.size() >
* p2dLfd) { if (processLegend.get(p2dLfd).isSelected()) {
* //System.err.println(p2dLfd + "\t" +
* processLegend.get(p2dLfd).isSelected()); } }
*/
}
p2dLfd++;
}
}
return result;
}
}