1 package org.simantics.district.imports.ui;
3 import java.io.IOException;
4 import java.util.HashMap;
7 import java.util.Map.Entry;
10 import org.apache.commons.csv.CSVRecord;
11 import org.eclipse.jface.dialogs.IPageChangeProvider;
12 import org.eclipse.jface.dialogs.IPageChangedListener;
13 import org.eclipse.jface.dialogs.PageChangedEvent;
14 import org.eclipse.jface.layout.GridDataFactory;
15 import org.eclipse.jface.layout.TableColumnLayout;
16 import org.eclipse.jface.viewers.ColumnWeightData;
17 import org.eclipse.jface.wizard.IWizardContainer;
18 import org.eclipse.jface.wizard.WizardPage;
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.events.SelectionAdapter;
21 import org.eclipse.swt.events.SelectionEvent;
22 import org.eclipse.swt.events.SelectionListener;
23 import org.eclipse.swt.layout.GridLayout;
24 import org.eclipse.swt.widgets.Button;
25 import org.eclipse.swt.widgets.Combo;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.swt.widgets.Group;
28 import org.eclipse.swt.widgets.Label;
29 import org.eclipse.swt.widgets.Table;
30 import org.eclipse.swt.widgets.TableColumn;
31 import org.eclipse.swt.widgets.TableItem;
32 import org.geotools.referencing.CRS;
33 import org.simantics.district.imports.ui.controls.DynamicComboFieldEditor;
35 public class CSVImportWizardPage extends WizardPage {
37 private CSVImportModel model;
39 private Map<Integer, String> headerIndexAndValues = new HashMap<>();
41 private Table headerTable;
42 // private Button firstAsHeader;
44 private Combo delimiterCombo;
45 private TableColumnLayout tableColumnLayout;
46 private Composite tableComposite;
47 // private FileSelectionWidget wktFileSelection;
49 // Common for vertex and edge
50 private DynamicComboFieldEditor componentMappingSelector;
51 private DynamicComboFieldEditor labelSelector;
54 private DynamicComboFieldEditor xCoordSelector;
55 private DynamicComboFieldEditor yCoordSelector;
56 private DynamicComboFieldEditor zValueSelector;
59 private DynamicComboFieldEditor startXCoordSelector;
60 private DynamicComboFieldEditor startYCoordSelector;
61 private DynamicComboFieldEditor startZValueSelector;
62 private DynamicComboFieldEditor endXCoordSelector;
63 private DynamicComboFieldEditor endYCoordSelector;
64 private DynamicComboFieldEditor endZValueSelector;
65 private DynamicComboFieldEditor tempValueSelector;
66 private DynamicComboFieldEditor pressureValueSelector;
68 private DynamicComboFieldEditor outerDiameterSelector;
69 private DynamicComboFieldEditor diameterSelector;
70 private DynamicComboFieldEditor nominalMassFlowSelector;
72 private Group indexMappingGroup;
74 private Composite composite;
76 private Button isVertexImport;
78 private Combo sourceCRSCombo;
80 protected CSVImportWizardPage(CSVImportModel model) {
81 super("Import CSV Data");
83 setMessage("Select column index mappings");
87 public void createControl(Composite parent) {
88 composite = new Composite(parent, SWT.NONE);
89 composite.setLayout(new GridLayout(1, false));
90 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(composite);
92 Label label = new Label(composite, SWT.NONE);
93 label.setText("Select delimiter");
95 delimiterCombo = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
96 delimiterCombo.setToolTipText("Select the delimiter that is used to separate elements in the CSV file");
97 delimiterCombo.setItems(model.getDelimiterFormats());
98 delimiterCombo.addSelectionListener(new SelectionListener() {
101 public void widgetSelected(SelectionEvent e) {
102 model.setDelimiterByLabel(delimiterCombo.getItem(delimiterCombo.getSelectionIndex()));
108 public void widgetDefaultSelected(SelectionEvent e) {
113 // firstAsHeader = new Button(composite, SWT.CHECK);
114 // firstAsHeader.setText("Read first row as header");
115 // firstAsHeader.setSelection(model.getReadFirstAsHeader());
116 // firstAsHeader.addSelectionListener(new SelectionListener() {
119 // public void widgetSelected(SelectionEvent e) {
120 // model.setReadFirstAsHeader(firstAsHeader.getSelection());
126 // public void widgetDefaultSelected(SelectionEvent e) {
127 // widgetSelected(e);
131 tableComposite = new Composite(composite, SWT.BORDER);
132 tableColumnLayout = new TableColumnLayout();
133 tableComposite.setLayout(tableColumnLayout);
135 label = new Label(composite, SWT.NONE);
136 label.setText("Select source Coordinate Reference System");
138 sourceCRSCombo = new Combo(composite, SWT.NONE);
139 sourceCRSCombo.setToolTipText("Select the coordinate reference system that is used in the source material for possible transformation to target coordinate reference system (EPSG:4326)");
140 Set<String> codes = CRS.getSupportedCodes("EPSG");
141 sourceCRSCombo.setItems(codes.toArray(new String[codes.size()]));
142 sourceCRSCombo.addSelectionListener(new SelectionAdapter() {
145 public void widgetSelected(SelectionEvent e) {
146 String current = sourceCRSCombo.getItem(sourceCRSCombo.getSelectionIndex());
147 model.setSourceCRS("EPSG:" + current);
151 // wktFileSelection = new FileSelectionWidget(composite, "WKT file", SWT.OPEN);
152 // wktFileSelection.addListener(new FileSelectionListener() {
155 // public void fileSelected(FileOrDirectorySelectionWidget source, String[] filename) {
156 // String[] selection = wktFileSelection.getFilename();
157 // if (selection != null && selection.length > 0) {
158 // Path wktFile = Paths.get(selection[0]);
159 // if (!Files.exists(wktFile)) {
160 // setErrorMessage("File " + wktFile.toAbsolutePath() + " does not exist");
162 // model.setWKTFile(wktFile);
163 // validatePageComplete();
169 isVertexImport = new Button(composite, SWT.CHECK);
170 isVertexImport.setText("File contains vertices");
171 isVertexImport.setToolTipText("Enable this if the file contains vertices, i.e. points");
172 isVertexImport.setSelection(model.isVertexImport());
173 isVertexImport.addSelectionListener(new SelectionListener() {
176 public void widgetSelected(SelectionEvent e) {
177 model.setVertexImport(isVertexImport.getSelection());
178 updateControls(false);
182 public void widgetDefaultSelected(SelectionEvent e) {
187 updateControls(true);
189 setControl(composite);
191 final IWizardContainer container = getContainer();
193 if (container instanceof IPageChangeProvider) {
194 ((IPageChangeProvider) container).addPageChangedListener(new IPageChangedListener() {
197 public void pageChanged(PageChangedEvent event) {
199 CSVImportWizardPage.this.updateControls(false);
204 validatePageComplete();
207 private void updateControls(boolean initial) {
208 createIndexMappingGroup();
211 composite.layout(true, true);
214 private void createIndexMappingGroup() {
215 if (indexMappingGroup != null)
216 indexMappingGroup.dispose();
218 indexMappingGroup = new Group(composite, SWT.NONE);
219 indexMappingGroup.setText("Column index mapping");
220 GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(indexMappingGroup);
222 if (model.isVertexImport())
223 createVertexIndexMappingField(indexMappingGroup);
225 createEdgeIndexMappingField(indexMappingGroup);
227 createCommonIndexMappingField(indexMappingGroup);
230 private void createCommonIndexMappingField(Group parent) {
232 componentMappingSelector = new DynamicComboFieldEditor("componentMapping", "Apros component mapping", parent);
233 componentMappingSelector.addComboListener(new SelectionListener() {
236 public void widgetSelected(SelectionEvent e) {
237 widgetDefaultSelected(e);
241 public void widgetDefaultSelected(SelectionEvent e) {
242 model.setComponentMappingIndex(Integer.parseInt(componentMappingSelector.getValue()));
243 validatePageComplete();
249 private void createVertexIndexMappingField(Group parent) {
250 xCoordSelector = new DynamicComboFieldEditor("xCoord", "X Coordinate", parent);
251 xCoordSelector.addComboListener(new SelectionListener() {
254 public void widgetSelected(SelectionEvent e) {
255 widgetDefaultSelected(e);
259 public void widgetDefaultSelected(SelectionEvent e) {
260 model.setXCoordIndex(Integer.parseInt(xCoordSelector.getValue()));
261 validatePageComplete();
265 yCoordSelector = new DynamicComboFieldEditor("yCoord", "Y Coordinate", parent);
266 yCoordSelector.addComboListener(new SelectionListener() {
269 public void widgetSelected(SelectionEvent e) {
270 widgetDefaultSelected(e);
274 public void widgetDefaultSelected(SelectionEvent e) {
275 model.setYCoordIndex(Integer.parseInt(yCoordSelector.getValue()));
276 validatePageComplete();
279 zValueSelector = new DynamicComboFieldEditor("zValue", "Z Value", parent);
280 zValueSelector.addComboListener(new SelectionListener() {
283 public void widgetSelected(SelectionEvent e) {
284 widgetDefaultSelected(e);
288 public void widgetDefaultSelected(SelectionEvent e) {
289 model.setZCoordIndex(Integer.parseInt(zValueSelector.getValue()));
290 validatePageComplete();
293 tempValueSelector = new DynamicComboFieldEditor("tempValue", "Temperature value", parent);
294 tempValueSelector.addComboListener(new SelectionListener() {
297 public void widgetSelected(SelectionEvent e) {
298 widgetDefaultSelected(e);
302 public void widgetDefaultSelected(SelectionEvent e) {
303 model.setTempIndex(Integer.parseInt(tempValueSelector.getValue()));
304 validatePageComplete();
307 pressureValueSelector = new DynamicComboFieldEditor("pressureValue", "Pressure value", parent);
308 pressureValueSelector.addComboListener(new SelectionListener() {
311 public void widgetSelected(SelectionEvent e) {
312 widgetDefaultSelected(e);
316 public void widgetDefaultSelected(SelectionEvent e) {
317 model.setPressureIndex(Integer.parseInt(pressureValueSelector.getValue()));
318 validatePageComplete();
323 private void createEdgeIndexMappingField(Group parent) {
324 startXCoordSelector = new DynamicComboFieldEditor("startxCoord", "Start X Coordinate", parent);
325 startXCoordSelector.addComboListener(new SelectionListener() {
328 public void widgetSelected(SelectionEvent e) {
329 widgetDefaultSelected(e);
333 public void widgetDefaultSelected(SelectionEvent e) {
334 model.setStartXCoordIndex(Integer.parseInt(startXCoordSelector.getValue()));
335 validatePageComplete();
339 startYCoordSelector = new DynamicComboFieldEditor("startyCoord", "Start Y Coordinate", parent);
340 startYCoordSelector.addComboListener(new SelectionListener() {
343 public void widgetSelected(SelectionEvent e) {
344 widgetDefaultSelected(e);
348 public void widgetDefaultSelected(SelectionEvent e) {
349 model.setStartYCoordIndex(Integer.parseInt(startYCoordSelector.getValue()));
350 validatePageComplete();
353 startZValueSelector = new DynamicComboFieldEditor("startzValue", "Start Z Value", parent);
354 startZValueSelector.addComboListener(new SelectionListener() {
357 public void widgetSelected(SelectionEvent e) {
358 widgetDefaultSelected(e);
362 public void widgetDefaultSelected(SelectionEvent e) {
363 model.setStartZCoordIndex(Integer.parseInt(startZValueSelector.getValue()));
364 validatePageComplete();
368 endXCoordSelector = new DynamicComboFieldEditor("endxCoord", "End X Coordinate", parent);
369 endXCoordSelector.addComboListener(new SelectionListener() {
372 public void widgetSelected(SelectionEvent e) {
373 widgetDefaultSelected(e);
377 public void widgetDefaultSelected(SelectionEvent e) {
378 model.setEndXCoordIndex(Integer.parseInt(endXCoordSelector.getValue()));
379 validatePageComplete();
383 endYCoordSelector = new DynamicComboFieldEditor("endyCoord", "End Y Coordinate", parent);
384 endYCoordSelector.addComboListener(new SelectionListener() {
387 public void widgetSelected(SelectionEvent e) {
388 widgetDefaultSelected(e);
392 public void widgetDefaultSelected(SelectionEvent e) {
393 model.setEndYCoordIndex(Integer.parseInt(endYCoordSelector.getValue()));
394 validatePageComplete();
397 endZValueSelector = new DynamicComboFieldEditor("endzValue", "End Z Value", parent);
398 endZValueSelector.addComboListener(new SelectionListener() {
401 public void widgetSelected(SelectionEvent e) {
402 widgetDefaultSelected(e);
406 public void widgetDefaultSelected(SelectionEvent e) {
407 model.setEndZCoordIndex(Integer.parseInt(endZValueSelector.getValue()));
408 validatePageComplete();
411 diameterSelector = new DynamicComboFieldEditor("diameterValue", "Diameter value", parent);
412 diameterSelector.addComboListener(new SelectionListener() {
415 public void widgetSelected(SelectionEvent e) {
416 widgetDefaultSelected(e);
420 public void widgetDefaultSelected(SelectionEvent e) {
421 model.setDiameterIndex(Integer.parseInt(diameterSelector.getValue()));
422 validatePageComplete();
425 outerDiameterSelector = new DynamicComboFieldEditor("outerDiameterValue", "Outer Diameter value", parent);
426 outerDiameterSelector.addComboListener(new SelectionListener() {
429 public void widgetSelected(SelectionEvent e) {
430 widgetDefaultSelected(e);
434 public void widgetDefaultSelected(SelectionEvent e) {
435 model.setOuterDiameterIndex(Integer.parseInt(outerDiameterSelector.getValue()));
436 validatePageComplete();
439 nominalMassFlowSelector = new DynamicComboFieldEditor("nominalMassFlowValue", "Nominal Mass Flow", parent);
440 nominalMassFlowSelector.addComboListener(new SelectionListener() {
443 public void widgetSelected(SelectionEvent e) {
444 widgetDefaultSelected(e);
448 public void widgetDefaultSelected(SelectionEvent e) {
449 model.setNominalMassFlowIndex(Integer.parseInt(nominalMassFlowSelector.getValue()));
450 validatePageComplete();
455 private void updateCombos() {
456 String[][] namesAndValues = new String[headerIndexAndValues.size()][];
459 for (Entry<Integer, String> entry : headerIndexAndValues.entrySet()) {
460 int key = entry.getKey();
461 String value = entry.getValue();
463 String[] nameAndValue = new String[2];
464 nameAndValue[0] = value;
465 nameAndValue[1] = Integer.toString(key);
466 namesAndValues[i++] = nameAndValue;
469 if (model.isVertexImport())
470 updateVertexCombos(namesAndValues);
472 updateEdgeCombos(namesAndValues);
474 componentMappingSelector.updateCombo(namesAndValues);
477 private void updateEdgeCombos(String[][] namesAndValues) {
478 startXCoordSelector.updateCombo(namesAndValues);
479 endXCoordSelector.updateCombo(namesAndValues);
480 startYCoordSelector.updateCombo(namesAndValues);
481 endYCoordSelector.updateCombo(namesAndValues);
482 startZValueSelector.updateCombo(namesAndValues);
483 endZValueSelector.updateCombo(namesAndValues);
484 diameterSelector.updateCombo(namesAndValues);
485 outerDiameterSelector.updateCombo(namesAndValues);
486 nominalMassFlowSelector.updateCombo(namesAndValues);
489 private void updateVertexCombos(String[][] namesAndValues) {
490 xCoordSelector.updateCombo(namesAndValues);
491 yCoordSelector.updateCombo(namesAndValues);
492 zValueSelector.updateCombo(namesAndValues);
493 pressureValueSelector.updateCombo(namesAndValues);
494 tempValueSelector.updateCombo(namesAndValues);
497 private void updateHeaders() {
498 if (headerTable != null)
499 headerTable.dispose();
500 headerTable = new Table(tableComposite, SWT.NONE);
501 headerTable.setHeaderVisible(true);
502 headerTable.setLinesVisible(true);
503 GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(tableComposite);
504 for (int i = 0; i < headerTable.getColumns().length; i++) {
505 TableColumn column = headerTable.getColumns()[i];
508 for (int i = 0; i < headerTable.getItemCount(); i++) {
509 TableItem item = headerTable.getItem(i);
513 headerIndexAndValues.clear();
516 List<CSVRecord> rows = model.getRows(5);
518 for (int k = 0; k < rows.size(); k++) {
519 CSVRecord row = rows.get(k);
521 int columnCount = row.size();
522 for (int i = 0; i < columnCount; i++) {
523 String value = row.get(i);
525 TableColumn headerCol = new TableColumn(headerTable, SWT.NONE);
526 headerCol.setText(value);
528 tableColumnLayout.setColumnData(headerCol, new ColumnWeightData(10));
531 headerIndexAndValues.put(i, value);
535 int itemCount = headerTable.getItemCount();
536 if (actualK >= itemCount) {
537 item = new TableItem(headerTable, SWT.NONE);
539 item = headerTable.getItem(actualK);
541 item.setText(i, value);
546 } catch (IOException e) {
547 setErrorMessage(e.getMessage());
551 protected void validatePageComplete() {
552 if (model.isVertexImport())
553 setPageComplete(model.getXCoordIndex() != -1 && model.getYCoordIndex() != -1 && model.getComponentMappingIndex() != -1);
555 setPageComplete(model.getStartXCoordIndex() != 1 && model.getStartYCoordIndex() != -1 && model.getEndXCoordIndex() != -1 && model.getEndYCoordIndex() != -1 && model.getComponentMappingIndex() != -1);