+package org.simantics.district.network.ui.table;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.SelectionStatusDialog;
+import org.geotools.geometry.DirectPosition2D;
+import org.geotools.referencing.CRS;
+import org.opengis.geometry.DirectPosition;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.MathTransform;
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.IndexRoot;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.request.PossibleActiveModel;
+import org.simantics.district.network.DistrictNetworkUtil;
+import org.simantics.district.network.ui.function.Functions;
+import org.simantics.modeling.ModelingResources;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ImportCSVHandler {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ImportCSVHandler.class);
+
+ @Inject
+ EPartService partService;
+
+ @Execute
+ public void execute(@Named(IServiceConstants.ACTIVE_SHELL) Shell s) {
+ // here we can import based on the current CSV table data
+ MPart activePart = partService.getActivePart();
+ Object object = activePart.getObject();
+ // this object is the part wrapped by e4part
+ DistrictCSVTableView view = (DistrictCSVTableView) object;
+ String[][] data = view.getCurrentData();
+
+ SelectionDialog d = new SelectionDialog(s);
+
+ if (d.open() == Dialog.CANCEL)
+ return;
+
+ String sourceEPSGCRS = d.getSourceCRS();//"EPSG:3067";
+
+ Resource targetDiagram = d.getTargetDiagram();
+ Resource mappingType = d.getMappingType();
+
+ try {
+ 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 MathTransform finalTransform = transform;
+
+ int x = xColumn(data);
+ int y = yColumn(data);
+ int z = zColumn(data);
+
+ Simantics.getSession().asyncRequest(new WriteRequest() {
+
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ for (int i = 1; i < data.length; i++) {
+ try {
+ String[] rows = data[i];
+ String xCoords = rows[x];
+ String yCoords = rows[y];
+ double xCoord = Double.parseDouble(xCoords);
+ double yCoord = Double.parseDouble(yCoords);
+ DirectPosition2D targetPos = new DirectPosition2D();
+ DirectPosition2D sourcePos = new DirectPosition2D(xCoord, yCoord);
+ DirectPosition res = finalTransform.transform(sourcePos, targetPos);
+ double[] coords = res.getCoordinate();
+ flipAxes(coords);
+ Resource vertex = DistrictNetworkUtil.createVertex(graph, targetDiagram, coords, z, mappingType);
+ } catch (Exception e) {
+ LOGGER.error("", e);
+ }
+ }
+ }
+ });
+ } catch (Exception e) {
+ LOGGER.error("", e);
+ }
+
+
+ }
+
+ private static void flipAxes(double[] coords) {
+ double tmp = coords[0];
+ coords[0] = coords[1];
+ coords[1] = tmp;
+ }
+
+
+ private int zColumn(String[][] data) {
+ return column("z", data);
+ }
+
+ private int yColumn(String[][] data) {
+ return column("y", data);
+ }
+
+ private int xColumn(String[][] data) {
+ return column("x", data);
+ }
+
+ private int column(String expected, String[][] data) {
+ String[] columns = data[0]; // first row should be headers
+ for (int i = 0; i < columns.length; i++) {
+ String col = columns[i];
+ if (col.equals(expected)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private static class SelectionDialog extends SelectionStatusDialog {
+
+ private Map<String, Resource> diagrams = new HashMap<>();
+ private Map<String, Resource> vertexMappings = new HashMap<>();
+
+ private Composite composite;
+ private Combo networkDiagramSelectionCombo;
+ private Combo sourceCRSCombo;
+ private Combo vertexMappingCombo;
+ private String sourceCRS;
+ private Resource diagram;
+ private Resource mapping;
+
+ public SelectionDialog(Shell parent) {
+ super(parent);
+ }
+
+ public Resource getMappingType() {
+ return mapping;
+ }
+
+ public Resource getTargetDiagram() {
+ return diagram;
+ }
+
+ public String getSourceCRS() {
+ return "EPSG:" + sourceCRS;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ composite = (Composite) super.createDialogArea(parent);
+ createMappingsGroup(composite);
+ computeContent();
+ return composite;
+ }
+
+ private void computeContent() {
+ Simantics.getSession().asyncRequest(new ReadRequest() {
+
+ @Override
+ public void run(ReadGraph graph) throws DatabaseException {
+
+ Resource indexRoot = graph.sync(new IndexRoot(graph.sync(new PossibleActiveModel(Simantics.getProjectResource()))));
+ vertexMappings = Functions.getVertexMappings(graph, indexRoot);
+
+ Collection<Resource> diagramss = Functions.getDistrictDiagrams(graph);
+ ModelingResources MOD = ModelingResources.getInstance(graph);
+ Resource projectResource = Simantics.getProjectResource();
+ String projectURI = graph.getURI(projectResource);
+ for (Resource diagram : diagramss) {
+ Resource composite = graph.getSingleObject(diagram, MOD.DiagramToComposite);
+ String compositeURI = graph.getURI(composite);
+ String path = compositeURI.replace(projectURI, "");
+ diagrams.put(path, diagram);
+ }
+
+ composite.getDisplay().asyncExec(() -> {
+
+ vertexMappingCombo.setItems(vertexMappings.keySet().toArray(new String[vertexMappings.size()]));
+
+ networkDiagramSelectionCombo.setItems(diagrams.keySet().toArray(new String[diagrams.size()]));
+ if (diagrams.size() > 0) {
+ networkDiagramSelectionCombo.select(0);
+ }
+ Set<String> codes = CRS.getSupportedCodes("EPSG");
+ sourceCRSCombo.setItems(codes.toArray(new String[codes.size()]));
+ sourceCRSCombo.addModifyListener(new ModifyListener() {
+
+ @Override
+ public void modifyText(ModifyEvent e) {
+ String currentText = sourceCRSCombo.getText();
+ if (codes.contains(currentText)) {
+ // Select this
+ String[] items = sourceCRSCombo.getItems();
+ int i;
+ for (i = 0; i < items.length; i++) {
+ String item = items[i];
+ if (currentText.equals(item)) {
+ break;
+ }
+ }
+ if (i != 0) {
+ sourceCRSCombo.select(i);
+ } else {
+ System.err.println("Should not happen");
+ }
+ }
+ }
+ });
+ });
+ }
+ });
+ }
+
+ private void createMappingsGroup(Composite parent) {
+ Group group= new Group(parent, SWT.NONE);
+ group.setFont(parent.getFont());
+ group.setText("Select Diagram & CRS");
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(group);
+ group.setLayout(new GridLayout(1, false));
+
+ Composite cmposite = new Composite(group, SWT.NONE);
+ cmposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ cmposite.setLayout(new GridLayout(2, false));
+
+ Label vertexMappingLabel = new Label(cmposite, SWT.NONE);
+ vertexMappingLabel.setText("Select Vertex Mapping");
+
+ vertexMappingCombo = new Combo(cmposite, SWT.READ_ONLY | SWT.BORDER);
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(vertexMappingCombo);
+
+ Label selectNetworkDiagramLabel = new Label(cmposite, SWT.NONE);
+ selectNetworkDiagramLabel.setText("Select Network Diagram");
+
+ networkDiagramSelectionCombo = new Combo(cmposite, SWT.READ_ONLY | SWT.BORDER);
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(networkDiagramSelectionCombo);
+
+ Label label = new Label(cmposite, SWT.NONE);
+ label.setText("Select Source Coordinate Reference System");
+
+ sourceCRSCombo = new Combo(cmposite, SWT.NONE);
+ sourceCRSCombo.setToolTipText("Select the coordinate reference system that is used in the source material for possible transformation to target coordinate reference system (EPSG:4326)");
+
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(sourceCRSCombo);
+ }
+
+ @Override
+ protected void computeResult() {
+ mapping = vertexMappings.get(vertexMappingCombo.getItem(vertexMappingCombo.getSelectionIndex()));
+ diagram = diagrams.get(networkDiagramSelectionCombo.getItem(networkDiagramSelectionCombo.getSelectionIndex()));
+ sourceCRS = sourceCRSCombo.getItem(sourceCRSCombo.getSelectionIndex());
+ }
+ }
+}