--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.district.feature</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.FeatureBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.FeatureNature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+bin.includes = feature.xml\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<feature\r
+ id="org.simantics.district.feature"\r
+ label="Simantics District Feature"\r
+ version="1.0.0.qualifier">\r
+\r
+ <description url="http://www.example.com/description">\r
+ [Enter Feature Description here.]\r
+ </description>\r
+\r
+ <copyright url="http://www.example.com/copyright">\r
+ [Enter Copyright Description here.]\r
+ </copyright>\r
+\r
+ <license url="http://www.example.com/license">\r
+ [Enter License Description here.]\r
+ </license>\r
+\r
+ <plugin\r
+ id="org.simantics.district.network"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"\r
+ unpack="false"/>\r
+\r
+ <plugin\r
+ id="org.simantics.district.network.ontology"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"\r
+ unpack="false"/>\r
+\r
+ <plugin\r
+ id="org.simantics.district.imports"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"\r
+ unpack="false"/>\r
+\r
+</feature>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.district.imports.ui</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Simantics District Import UI
+Bundle-SymbolicName: org.simantics.district.imports.ui;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.eclipse.ui.ide,
+ org.eclipse.jface,
+ org.simantics.utils.ui,
+ org.simantics.district.imports;bundle-version="1.0.0",
+ org.simantics.db
+Bundle-ActivationPolicy: lazy
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .,\\r
+ plugin.xml\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<?eclipse version="3.4"?>\r
+<plugin>\r
+ <extension\r
+ point="org.eclipse.ui.importWizards">\r
+ <wizard\r
+ class="org.simantics.district.imports.ui.CSVImportWizard"\r
+ id="org.simantics.district.imports.ui.csvimportwizard"\r
+ name="Import CSV data to Simantics District">\r
+ <description>\r
+ Imports CSV data to Simantics District network\r
+ </description>\r
+ </wizard>\r
+ </extension>\r
+</plugin>\r
--- /dev/null
+package org.simantics.district.imports.ui;\r
+\r
+import java.io.IOException;\r
+import java.nio.file.Path;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.simantics.district.imports.DistrictImportUtils;\r
+import org.simantics.district.imports.DistrictImportUtils.CSVHeader;\r
+\r
+public class CSVImportModel {\r
+\r
+ private Path source;\r
+ private char delimiter;\r
+ private boolean read;\r
+ private Map<String, Character> delimiters;\r
+\r
+ public CSVImportModel() {\r
+ delimiters = DistrictImportUtils.getSupportedCSVDelimiterFormats();\r
+ }\r
+ \r
+ public void setSource(Path source) {\r
+ this.source = source;\r
+ }\r
+\r
+ public void setDelimiter(char delimiter) {\r
+ this.delimiter = delimiter;\r
+ }\r
+\r
+ public void setReadFirstAsHeader(boolean read) {\r
+ this.read = read;\r
+ }\r
+\r
+ public Path getSource() {\r
+ return source;\r
+ }\r
+\r
+ public Map<CSVHeader, List<String>> getHeaderAndRows(int amount) throws IOException {\r
+ if (source != null)\r
+ return DistrictImportUtils.readCSVHeaderAndRows(source, delimiter, read, amount);\r
+ else\r
+ return Collections.emptyMap();\r
+ }\r
+ \r
+ public Map<String, Integer> getHeader() throws IOException {\r
+ Map<String, Integer> header = null;\r
+ if (source != null)\r
+ header = DistrictImportUtils.readCSVHeader(source, delimiter, read);\r
+ if (header == null)\r
+ header = Collections.emptyMap();\r
+ return header;\r
+ }\r
+\r
+ public boolean getReadFirstAsHeader() {\r
+ return read;\r
+ }\r
+\r
+ public String[] getDelimiterFormats() {\r
+ return delimiters.keySet().toArray(new String[delimiters.size()]);\r
+ }\r
+\r
+ public void setDelimiterByLabel(String item) {\r
+ setDelimiter(delimiters.get(item));\r
+ }\r
+\r
+ public List<Map<String, String>> readRows(int amount) throws IOException {\r
+ if (source != null)\r
+ return DistrictImportUtils.readRows(source, delimiter, read, amount);\r
+ else\r
+ return Collections.emptyList();\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.district.imports.ui;\r
+\r
+import java.io.IOException;\r
+import java.nio.file.Path;\r
+\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.wizard.Wizard;\r
+import org.eclipse.ui.IImportWizard;\r
+import org.eclipse.ui.IWorkbench;\r
+import org.simantics.district.imports.DistrictImportUtils;\r
+\r
+public class CSVImportWizard extends Wizard implements IImportWizard {\r
+\r
+ private CSVImportModel model;\r
+ \r
+ public CSVImportWizard() {\r
+ setWindowTitle("Import CSV data");\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public void init(IWorkbench workbench, IStructuredSelection selection) {\r
+ model = new CSVImportModel();\r
+ addPage(new CSVImportWizardPage(model));\r
+ }\r
+ \r
+ @Override\r
+ public boolean performFinish() {\r
+ Path csvFile = model.getSource();\r
+ try {\r
+ DistrictImportUtils.importCSVAsLayer(csvFile);\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ return false;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.district.imports.ui;\r
+\r
+import java.io.IOException;\r
+import java.nio.file.Files;\r
+import java.nio.file.Path;\r
+import java.nio.file.Paths;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.TableColumnLayout;\r
+import org.eclipse.jface.layout.TreeColumnLayout;\r
+import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;\r
+import org.eclipse.jface.viewers.ColumnWeightData;\r
+import org.eclipse.jface.viewers.IContentProvider;\r
+import org.eclipse.jface.viewers.TableViewer;\r
+import org.eclipse.jface.viewers.TreeViewer;\r
+import org.eclipse.jface.viewers.Viewer;\r
+import org.eclipse.jface.wizard.WizardPage;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Combo;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Layout;\r
+import org.eclipse.swt.widgets.Table;\r
+import org.eclipse.swt.widgets.TableColumn;\r
+import org.eclipse.swt.widgets.TableItem;\r
+import org.simantics.district.imports.DistrictImportUtils.CSVHeader;\r
+import org.simantics.utils.ui.widgets.FileOrDirectorySelectionWidget;\r
+import org.simantics.utils.ui.widgets.FileSelectionListener;\r
+import org.simantics.utils.ui.widgets.FileSelectionWidget;\r
+\r
+public class CSVImportWizardPage extends WizardPage implements FileSelectionListener {\r
+\r
+ private CSVImportModel model;\r
+ private FileSelectionWidget csvSelection;\r
+ private Table headerTable;\r
+ private Button firstAsHeader;\r
+ private Combo delimiterCombo;\r
+ private TableColumnLayout tableColumnLayout;\r
+ private TableViewer tableViewer;\r
+\r
+ protected CSVImportWizardPage(CSVImportModel model) {\r
+ super("Import CSV Data");\r
+ this.model = model;\r
+ setMessage("Select CSV file to import");\r
+ }\r
+\r
+ @Override\r
+ public void createControl(Composite parent) {\r
+ Composite composite = new Composite(parent, SWT.NONE);\r
+ composite.setLayout(new GridLayout(1,false));\r
+ GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(composite);\r
+ \r
+ csvSelection = new FileSelectionWidget(composite, "CSV file", SWT.OPEN);\r
+ csvSelection.addListener(this);\r
+ \r
+ delimiterCombo = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY);\r
+ delimiterCombo.setItems(model.getDelimiterFormats());\r
+ delimiterCombo.addSelectionListener(new SelectionListener() {\r
+ \r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ model.setDelimiterByLabel(delimiterCombo.getItem(delimiterCombo.getSelectionIndex()));\r
+ updateHeaders();\r
+ }\r
+ \r
+ @Override\r
+ public void widgetDefaultSelected(SelectionEvent e) {\r
+ \r
+ }\r
+ });\r
+ \r
+ firstAsHeader = new Button(composite, SWT.CHECK);\r
+ firstAsHeader.setText("Read first row as header");\r
+ firstAsHeader.setSelection(model.getReadFirstAsHeader());\r
+ firstAsHeader.addSelectionListener(new SelectionListener() {\r
+ \r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ model.setReadFirstAsHeader(firstAsHeader.getSelection());\r
+ updateHeaders();\r
+ }\r
+ \r
+ @Override\r
+ public void widgetDefaultSelected(SelectionEvent e) {\r
+ \r
+ }\r
+ });\r
+ \r
+ \r
+ Composite tableComposite = new Composite(composite, SWT.BORDER);\r
+ TreeColumnLayout treeColumnLayout = new TreeColumnLayout();\r
+ tableComposite.setLayout(treeColumnLayout);\r
+ \r
+ tableViewer = new TableViewer(tableComposite, SWT.V_SCROLL | SWT.H_SCROLL);\r
+ ColumnViewerToolTipSupport.enableFor(tableViewer);\r
+ tableViewer.setContentProvider(new IContentProvider() {\r
+ \r
+ @Override\r
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void dispose() {\r
+ \r
+ }\r
+ });\r
+ \r
+ Table table = tableViewer.getTable();\r
+ table.setHeaderVisible(true);\r
+ table.setLinesVisible(true);\r
+ \r
+ headerTable = new Table(tableComposite, SWT.NONE);\r
+ headerTable.setHeaderVisible(true);\r
+ headerTable.setLinesVisible(true);\r
+ GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(tableComposite);\r
+ \r
+ setControl(composite);\r
+ \r
+ updateHeaders();\r
+ \r
+ setPageComplete(false);\r
+ }\r
+\r
+ @Override\r
+ public void fileSelected(FileOrDirectorySelectionWidget source, String[] filename) {\r
+ String[] selection = csvSelection.getFilename();\r
+ if (selection != null && selection.length > 0) {\r
+ Path csvFile = Paths.get(selection[0]);\r
+ if (!Files.exists(csvFile)) {\r
+ setErrorMessage("File " + csvFile.toAbsolutePath() + " does not exist");\r
+ } else {\r
+ model.setSource(csvFile);\r
+ updateHeaders();\r
+ setPageComplete(true);\r
+ }\r
+ } else {\r
+ setPageComplete(false);\r
+ }\r
+ }\r
+\r
+ private void updateHeaders() {\r
+ headerTable.setRedraw(false);\r
+ for (int i = 0; i < headerTable.getColumns().length; i++) {\r
+ TableColumn column = headerTable.getColumns()[i];\r
+ column.dispose();\r
+ }\r
+ for (int i = 0; i < headerTable.getItemCount(); i++) {\r
+ TableItem item = headerTable.getItem(i);\r
+ item.dispose();\r
+ }\r
+ try {\r
+ Map<CSVHeader, List<String>> headerAndValues = model.getHeaderAndRows(5);\r
+ \r
+ int coo = headerTable.getColumns().length;\r
+ int count = headerTable.getColumnCount();\r
+ \r
+ for (Map.Entry<CSVHeader, List<String>> entr : headerAndValues.entrySet()) {\r
+ CSVHeader he = entr.getKey();\r
+ int index = he.getIndex();\r
+ TableColumn headerCol = new TableColumn(headerTable, SWT.NONE);\r
+ headerCol.setText(he.getHeader());\r
+ \r
+ tableColumnLayout.setColumnData(headerCol, new ColumnWeightData(10));\r
+ headerCol.pack();\r
+ \r
+ for (String val : entr.getValue()) {\r
+ TableItem item = new TableItem(headerTable, SWT.NONE);\r
+ item.setText(val);\r
+ }\r
+ }\r
+ } catch (IOException e) {\r
+ setErrorMessage(e.getMessage());\r
+ }\r
+ headerTable.setRedraw(true);\r
+ }\r
+\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">\r
+ <attributes>\r
+ <attribute name="maven.pomderived" value="true"/>\r
+ </attributes>\r
+ </classpathentry>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry exported="true" kind="lib" path="lib/commons-csv-1.4.jar" sourcepath="lib/commons-csv-1.4-sources.jar"/>\r
+ <classpathentry kind="src" path="src/"/>\r
+ <classpathentry kind="output" path="target/classes"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.district.imports</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.m2e.core.maven2Builder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Simantics District Imports
+Bundle-SymbolicName: org.simantics.district.imports
+Bundle-Version: 1.0.0.qualifier
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.simantics.db
+Export-Package: org.simantics.district.imports
+Bundle-ClassPath: lib/commons-csv-1.4.jar,
+ .
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .,\\r
+ lib/commons-csv-1.4.jar\r
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
+ <modelVersion>4.0.0</modelVersion>\r
+ <groupId>org.simantics.district.imports</groupId>\r
+ <artifactId>org.simantics.district.imports</artifactId>\r
+ <version>0.0.1-SNAPSHOT</version>\r
+ <packaging>eclipse-plugin</packaging>\r
+\r
+ <!-- common settings for all modules -->\r
+ <properties>\r
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r
+ <tycho-version>0.25.0</tycho-version>\r
+ </properties>\r
+\r
+ <dependencies>\r
+ <dependency>\r
+ <groupId>org.apache.commons</groupId>\r
+ <artifactId>commons-csv</artifactId>\r
+ <version>1.4</version>\r
+ </dependency>\r
+ </dependencies>\r
+\r
+ <build>\r
+ <sourceDirectory>src</sourceDirectory>\r
+ <plugins>\r
+ <plugin>\r
+ <groupId>org.eclipse.tycho</groupId>\r
+ <artifactId>tycho-maven-plugin</artifactId>\r
+ <version>${tycho-version}</version>\r
+ <extensions>true</extensions>\r
+ </plugin>\r
+ <plugin>\r
+ <artifactId>maven-compiler-plugin</artifactId>\r
+ <version>3.5.1</version>\r
+ <configuration>\r
+ <source>1.8</source>\r
+ <target>1.8</target>\r
+ </configuration>\r
+ </plugin>\r
+ </plugins>\r
+ </build>\r
+</project>
\ No newline at end of file
--- /dev/null
+package org.simantics.district.imports;\r
+\r
+import java.io.IOException;\r
+import java.nio.file.Files;\r
+import java.nio.file.Path;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.apache.commons.csv.CSVFormat;\r
+import org.apache.commons.csv.CSVParser;\r
+import org.apache.commons.csv.CSVRecord;\r
+import org.simantics.db.Resource;\r
+\r
+public class DistrictImportUtils {\r
+\r
+ private DistrictImportUtils() { }\r
+ \r
+ \r
+ public static Resource importCSVAsLayer(Path csvFile) throws IOException {\r
+ \r
+ \r
+ try (CSVParser parser = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(Files.newBufferedReader(csvFile))) {\r
+ Map<String, Integer> header = parser.getHeaderMap();\r
+ System.out.println(header);\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ public static Map<String, Integer> readCSVHeader(Path source, char delimiter, boolean firstAsHeader) throws IOException {\r
+ return readCSVHeader(source, CSVFormat.newFormat(delimiter), firstAsHeader);\r
+ }\r
+ \r
+ public static Map<String, Integer> readCSVHeader(Path source, CSVFormat format, boolean firstAsHeader) throws IOException {\r
+ if (firstAsHeader)\r
+ format = format.withFirstRecordAsHeader();\r
+ try (CSVParser parser = format.parse(Files.newBufferedReader(source))) {\r
+ return parser.getHeaderMap();\r
+ }\r
+ }\r
+\r
+\r
+ public static Map<String, Character> getSupportedCSVDelimiterFormats() {\r
+ Map<String, Character> delimiters = new HashMap<>();\r
+ delimiters.put("COMMA", ',');\r
+ delimiters.put("SEMICOMMA", ';');\r
+ return delimiters;\r
+ }\r
+\r
+ public static List<Map<String, String>> readRows(Path source, char delimiter, boolean firstAsHeader, int amount) throws IOException {\r
+ return readRows(source, CSVFormat.newFormat(delimiter), firstAsHeader, amount);\r
+ }\r
+\r
+ public static List<Map<String, String>> readRows(Path source, CSVFormat format, boolean firstAsHeader, int amount) throws IOException {\r
+ if (firstAsHeader)\r
+ format = format.withFirstRecordAsHeader();\r
+ try (CSVParser parser = format.parse(Files.newBufferedReader(source))) {\r
+ int start = 0;\r
+ List<Map<String, String>> results = new ArrayList<>(amount);\r
+ Iterator<CSVRecord> iter = parser.iterator();\r
+ while (start < amount && iter.hasNext()) {\r
+ CSVRecord record = iter.next();\r
+ results.add(record.toMap());\r
+ start++;\r
+ }\r
+ return results;\r
+ }\r
+ }\r
+\r
+\r
+ public static Map<CSVHeader, List<String>> readCSVHeaderAndRows(Path source, char delimiter, boolean firstAsHeader, int amount) throws IOException {\r
+ Map<CSVHeader, List<String>> results = new HashMap<>();\r
+ CSVFormat format = CSVFormat.newFormat(delimiter);\r
+ if (firstAsHeader)\r
+ format = format.withFirstRecordAsHeader();\r
+ try (CSVParser parser = format.parse(Files.newBufferedReader(source))) {\r
+ Map<String, Integer> headers = parser.getHeaderMap();\r
+ if (headers != null && !headers.isEmpty()) {\r
+ for (int index = 0; index < headers.size(); index++) {\r
+ for (String head : headers.keySet()) {\r
+ results.put(new CSVHeader(head, index), new ArrayList<>());\r
+ }\r
+ }\r
+ }\r
+ \r
+ Iterator<CSVRecord> records = parser.iterator();\r
+ int rows = 0;\r
+ while (rows < amount && records.hasNext()) {\r
+ CSVRecord record = records.next();\r
+ for (int j = 0; j < record.size(); j++) {\r
+ String value = record.get(j);\r
+ String header = Integer.toString(j);\r
+ CSVHeader csvHeader = new CSVHeader(header, j);\r
+ List<String> vals = results.get(csvHeader);\r
+ if (vals == null) {\r
+ vals = new ArrayList<>();\r
+ results.put(csvHeader, vals);\r
+ }\r
+ vals.add(value);\r
+ }\r
+ rows++;\r
+ }\r
+ }\r
+ return results;\r
+ }\r
+ \r
+ public static class CSVHeader {\r
+\r
+ private final String header;\r
+ private final int index;\r
+ \r
+ public CSVHeader(String header, int index) {\r
+ this.header = header;\r
+ this.index = index;\r
+ }\r
+\r
+ public String getHeader() {\r
+ return header;\r
+ }\r
+\r
+ public int getIndex() {\r
+ return index;\r
+ }\r
+ \r
+ @Override\r
+ public int hashCode() {\r
+ final int prime = 31;\r
+ int result = 1;\r
+ result = prime * result + ((header == null) ? 0 : header.hashCode());\r
+ result = prime * result + index;\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (this == obj)\r
+ return true;\r
+ if (obj == null)\r
+ return false;\r
+ if (getClass() != obj.getClass())\r
+ return false;\r
+ CSVHeader other = (CSVHeader) obj;\r
+ if (header == null) {\r
+ if (other.header != null)\r
+ return false;\r
+ } else if (!header.equals(other.header))\r
+ return false;\r
+ if (index != other.index)\r
+ return false;\r
+ return true;\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.district.ui.feature</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.FeatureBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.FeatureNature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+bin.includes = feature.xml\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<feature\r
+ id="org.simantics.district.ui.feature"\r
+ label="Simantics District UI Feature"\r
+ version="1.0.0.qualifier">\r
+\r
+ <description url="http://www.example.com/description">\r
+ [Enter Feature Description here.]\r
+ </description>\r
+\r
+ <copyright url="http://www.example.com/copyright">\r
+ [Enter Copyright Description here.]\r
+ </copyright>\r
+\r
+ <license url="http://www.example.com/license">\r
+ [Enter License Description here.]\r
+ </license>\r
+\r
+ <includes\r
+ id="org.simantics.district.feature"\r
+ version="0.0.0"/>\r
+\r
+ <plugin\r
+ id="org.simantics.district.network.ui"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"\r
+ unpack="false"/>\r
+\r
+ <plugin\r
+ id="org.simantics.district.imports.ui"\r
+ download-size="0"\r
+ install-size="0"\r
+ version="0.0.0"\r
+ unpack="false"/>\r
+\r
+</feature>\r