package org.simantics.district.imports.ui; import java.lang.reflect.InvocationTargetException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.commons.csv.CSVRecord; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.ui.IImportWizard; import org.eclipse.ui.IWorkbench; import org.geotools.geometry.DirectPosition2D; import org.geotools.referencing.CRS; import org.opengis.geometry.DirectPosition; import org.opengis.geometry.MismatchedDimensionException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; import org.simantics.Simantics; import org.simantics.databoard.Bindings; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.ObjectsWithType; import org.simantics.db.exception.DatabaseException; import org.simantics.db.request.Write; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.district.imports.DistrictImportUtils; import org.simantics.district.network.DistrictNetworkUtil; import org.simantics.district.network.ontology.DistrictNetworkResource; import org.simantics.district.network.ui.DNEdgeBuilder; import org.simantics.district.network.ui.DNEdgeBuilder.ResourceVertex; import org.simantics.layer0.Layer0; import org.simantics.utils.ui.ExceptionUtils; public class CSVImportWizard extends Wizard implements IImportWizard { private CSVImportModel model; public CSVImportWizard() { setWindowTitle("Import CSV data"); setNeedsProgressMonitor(true); } @Override public void init(IWorkbench workbench, IStructuredSelection selection) { model = new CSVImportModel(); addPage(new CSVImportWizardFirstPage(model)); addPage(new CSVImportWizardPage(model)); addPage(new ComponentMappingPage(model)); } @Override public boolean performFinish() { try { getContainer().run(true, true, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { Path csvFile = model.getSource(); char delim = model.getDelimiter(); List rows = DistrictImportUtils.readRows(csvFile, delim, -1); monitor.beginTask("Importing CSV", rows.size()); // Path wktFile = model.getWKTFile(); int xCoordColumnIndex = model.getXCoordIndex(); int yCoordColumnIndex = model.getYCoordIndex(); int zCoordColumnIndex = model.getZCoordIndex(); int supplyTempColumnIndex = model.getSupplyTempIndex(); int returnTempColumnIndex = model.getReturnTempIndex(); int supplyPressureColumnIndex = model.getSupplyPressureIndex(); int returnPressureColumnIndex = model.getReturnPressureIndex(); int dpIndex = model.getDeltaPressureIndex(); int dtIndex = model.getDeltaTemperatureIndex(); int heatPowerIndex = model.getHeatPowerIndex(); int valvePositionIndex = model.getValvePositionIndx(); int nominalHeadMIndex = model.getNominalHeadMIndex(); int nominalHeadBIndex = model.getNominalHeadBIndex(); int nominalFlowIndex = model.getNominalFlowIndex(); int maximumHeadMIndex = model.getMaximumHeadMIndex(); int heatLoadDsIndex = model.getHeatLoadDsIndex(); int massFlowIndex = model.getMassFlowIndex(); int volFlowIndex = model.getVolFlowIndex(); int velocityIndex = model.getVelocityIndex(); int flowAreaIndex = model.getFlowAreaIndex(); int nominalPressureLossIndex = model.getNominalPressureLossIndex(); int addressIndex = model.getAddressIndex(); int startXCoordColumnIndex = model.getStartXCoordIndex(); int startYCoordColumnIndex = model.getStartYCoordIndex(); int startZValueColumnIndex = model.getStartZCoordIndex(); int endXCoordColumnIndex = model.getEndXCoordIndex(); int endYCoordColumnIndex = model.getEndYCoordIndex(); int endZValueColumnIndex = model.getEndZCoordIndex(); int diameterColumnIndex= model.getDiameterIndex(); int outerDiameterColumnIndex = model.getOuterDiamterIndex(); int nominalMassFlowIndex = model.getNominalMassFlowIndex(); int tGroundIndex = model.gettGroundIndex(); int edgeFlowAreaIndex = model.getEdgeFlowAreaIndex(); int kReturnIndex = model.getkReturnIndex(); int kSupplyIndex = model.getkSupplyIndex(); int lengthIndex = model.getLengthIndex(); int mappingColumn = model.getComponentMappingIndex(); int idColumn = model.getIdIndex(); double padding = model.getEdgePadding(); String sourceEPSGCRS = model.getSourceCRS(); MathTransform transform = null; boolean doTransform = false; // if sourceEPSGCRS is empty || null then ignore transformation if (sourceEPSGCRS != null && !sourceEPSGCRS.isEmpty()) { CoordinateReferenceSystem sourceCRS = CRS.decode(sourceEPSGCRS); CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326"); transform = CRS.findMathTransform(sourceCRS, targetCRS, true); doTransform = true; } final boolean actualDoTransform = doTransform; final MathTransform actualTransform = transform; Simantics.getSession().syncRequest(new Write() { @Override public void perform(WriteGraph graph) throws DatabaseException { graph.markUndoPoint(); DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); Collection vertices = graph.syncRequest(new ObjectsWithType(model.getParentDiagram(), Layer0.getInstance(graph).ConsistsOf, DistrictNetworkResource.getInstance(graph).Vertex)); List vv = new ArrayList<>(vertices.size()); for (Resource vertex : vertices) { double[] existingCoords = graph.getRelatedValue2(vertex, DiagramResource.getInstance(graph).HasLocation, Bindings.DOUBLE_ARRAY); vv.add(new ResourceVertex(vertex, existingCoords)); } for (int k = 1; k < rows.size(); k++) { CSVRecord row = rows.get(k); String mappingValue = row.get(mappingColumn); try { if (model.isVertexImport()) { String xCoords = row.get(xCoordColumnIndex); String yCoords = row.get(yCoordColumnIndex); double xCoord = Double.parseDouble(xCoords); double yCoord = Double.parseDouble(yCoords); double z = 0; if (zCoordColumnIndex != -1) { String zs = row.get(zCoordColumnIndex); if (!zs.isEmpty()) { try { z = Double.parseDouble(zs); } catch (NumberFormatException e) { throw new DatabaseException(e); } } } double[] coords; if (actualDoTransform) { DirectPosition2D targetPos = new DirectPosition2D(); DirectPosition2D sourcePos = new DirectPosition2D(xCoord, yCoord); DirectPosition res = actualTransform.transform(sourcePos, targetPos); coords = res.getCoordinate(); } else { coords = new double[] { xCoord, yCoord }; } // Switch to (longitude, latitude) flipAxes(coords); Resource vertex = DistrictNetworkUtil.createVertex(graph, model.getParentDiagram(), coords, model.getComponentMappings().get(mappingValue)); writeStringValue(graph, row, idColumn, vertex, DN.HasId); graph.claimLiteral(vertex, DN.Vertex_HasElevation, z, Bindings.DOUBLE); writeValue(graph, row, supplyTempColumnIndex, vertex, DN.Vertex_HasSupplyTemperature); writeValue(graph, row, returnTempColumnIndex, vertex, DN.Vertex_HasReturnTemperature); writeValue(graph, row, supplyPressureColumnIndex, vertex, DN.Vertex_HasSupplyPressure); writeValue(graph, row, returnPressureColumnIndex, vertex, DN.Vertex_HasReturnPressure); writeValue(graph, row, dpIndex, vertex, DN.Vertex_HasDeltaPressure); writeValue(graph, row, dtIndex, vertex, DN.Vertex_HasDeltaTemperature); writeValue(graph, row, heatPowerIndex, vertex, DN.Vertex_HasHeatPower); writeValue(graph, row, valvePositionIndex, vertex, DN.Vertex_HasValvePosition); writeValue(graph, row, nominalHeadMIndex, vertex, DN.Vertex_HasNominalHeadM); writeValue(graph, row, nominalHeadBIndex, vertex, DN.Vertex_HasNominalHeadB); writeValue(graph, row, nominalFlowIndex, vertex, DN.Vertex_HasNominalFlow); writeValue(graph, row, maximumHeadMIndex, vertex, DN.Vertex_HasMaximumHeadM); writeValue(graph, row, heatLoadDsIndex, vertex, DN.Vertex_HasHeatLoadDs); writeValue(graph, row, massFlowIndex, vertex, DN.Vertex_HasMassFlow); writeValue(graph, row, volFlowIndex, vertex, DN.Vertex_HasVolFlow); writeValue(graph, row, velocityIndex, vertex, DN.Vertex_HasVelocity); writeValue(graph, row, flowAreaIndex, vertex, DN.Vertex_HasFlowArea); writeValue(graph, row, nominalPressureLossIndex, vertex, DN.Vertex_HasNominalPressureLoss); writeStringValue(graph, row, addressIndex, vertex, DN.Vertex_HasAddress); } else { String startXCoords = row.get(startXCoordColumnIndex); String startYCoords = row.get(startYCoordColumnIndex); String endXCoords = row.get(endXCoordColumnIndex); String endYCoords = row.get(endYCoordColumnIndex); double startXCoord = Double.parseDouble(startXCoords); // make negative double startYCoord = Double.parseDouble(startYCoords); double endXCoord = Double.parseDouble(endXCoords); // make negative double endYCoord = Double.parseDouble(endYCoords); double[] startCoords; double[] endCoords; if (actualDoTransform) { DirectPosition2D startTargetPos = new DirectPosition2D(); DirectPosition2D startSourcePos = new DirectPosition2D(startXCoord, startYCoord); DirectPosition startRes = actualTransform.transform(startSourcePos, startTargetPos); startCoords = startRes.getCoordinate(); DirectPosition2D endTargetPos = new DirectPosition2D(); DirectPosition2D endSourcePos = new DirectPosition2D(endXCoord, endYCoord); DirectPosition endRes = actualTransform.transform(endSourcePos, endTargetPos); endCoords = endRes.getCoordinate(); } else { startCoords = new double[] { startXCoord , startYCoord }; endCoords = new double[] { endXCoord , endYCoord }; } // Switch to (longitude, latitude) flipAxes(startCoords); flipAxes(endCoords); Resource edge = DNEdgeBuilder.create(graph, vv, model.getParentDiagram(), model.getComponentMappings().get(mappingValue), startCoords, endCoords, padding, true); writeStringValue(graph, row, idColumn, edge, DN.HasId); writeValue(graph, row, diameterColumnIndex, edge, DN.Edge_HasDiameter); writeValue(graph, row, outerDiameterColumnIndex, edge, DN.Edge_HasOuterDiameter); writeValue(graph, row, nominalMassFlowIndex, edge, DN.Edge_HasNominalMassFlow); writeValue(graph, row, tGroundIndex, edge, DN.Edge_HasTGround); writeValue(graph, row, kReturnIndex, edge, DN.Edge_HasKReturn); writeValue(graph, row, kSupplyIndex, edge, DN.Edge_HasKSupply); writeValue(graph, row, edgeFlowAreaIndex, edge, DN.Edge_HasFlowArea); writeValue(graph, row, lengthIndex, edge, DN.Edge_HasLength); } } catch (MismatchedDimensionException | TransformException | DatabaseException e) { throw new DatabaseException(e); } monitor.worked(1); } } }); } catch (Exception e) { throw new InvocationTargetException(e); } } }); return true; } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); WizardPage cp = (WizardPage) getContainer().getCurrentPage(); cp.setErrorMessage(t.getMessage()); ExceptionUtils.logAndShowError(t); return false; } catch (InterruptedException e) { ExceptionUtils.logAndShowError(e); return false; } } private static void flipAxes(double[] coords) { double tmp = coords[0]; coords[0] = coords[1]; coords[1] = tmp; } private static void writeValue(WriteGraph graph, CSVRecord row, int index, Resource subject, Resource relation) throws DatabaseException { if (index != -1) { String stringValue = row.get(index); if (!stringValue.isEmpty()) { try { graph.claimLiteral(subject, relation, Double.parseDouble(stringValue), Bindings.DOUBLE); } catch (NumberFormatException e) { throw new DatabaseException(e); } } } } private static void writeStringValue(WriteGraph graph, CSVRecord row, int index, Resource subject, Resource relation) throws DatabaseException { if (index != -1) { String stringValue = row.get(index); if (!stringValue.isEmpty()) { try { graph.claimLiteral(subject, relation, stringValue, Bindings.STRING); } catch (NumberFormatException e) { throw new DatabaseException(e); } } } } }