r118 - in trunk: . jmexico-editor/src/main/java/fr/reseaumexico/editor jmexico-editor/src/main/resources/i18n jmexico-model jmexico-model/src/main/java/fr/reseaumexico/model/parser
Author: echatellier Date: 2013-05-15 14:16:35 +0200 (Wed, 15 May 2013) New Revision: 118 Url: http://forge.codelutin.com/projects/jmexico/repository/revisions/118 Log: fixes #2426: Add option to import scenario files using xml or csv depending on file extension Added: trunk/jmexico-model/src/main/java/fr/reseaumexico/model/parser/ScenarioCSVParser.java Modified: trunk/jmexico-editor/src/main/java/fr/reseaumexico/editor/InputDesignEditorHandler.java trunk/jmexico-editor/src/main/resources/i18n/jmexico-editor_en_GB.properties trunk/jmexico-editor/src/main/resources/i18n/jmexico-editor_fr_FR.properties trunk/jmexico-model/pom.xml trunk/pom.xml Modified: trunk/jmexico-editor/src/main/java/fr/reseaumexico/editor/InputDesignEditorHandler.java =================================================================== --- trunk/jmexico-editor/src/main/java/fr/reseaumexico/editor/InputDesignEditorHandler.java 2013-05-15 08:38:26 UTC (rev 117) +++ trunk/jmexico-editor/src/main/java/fr/reseaumexico/editor/InputDesignEditorHandler.java 2013-05-15 12:16:35 UTC (rev 118) @@ -24,8 +24,31 @@ */ package fr.reseaumexico.editor; +import static org.nuiton.i18n.I18n._; + +import java.awt.event.ItemEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import javax.swing.JOptionPane; + +import jaxx.runtime.swing.editor.FileEditor; +import jaxx.runtime.swing.renderer.DecoratorProviderTableCellRenderer; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTable; + import com.google.common.base.Function; import com.google.common.collect.Maps; + import fr.reseaumexico.editor.factorValue.FactorValueCellEditor; import fr.reseaumexico.editor.factorValue.FactorValueCellRenderer; import fr.reseaumexico.editor.factorValue.FactorValueEditorFactory; @@ -33,28 +56,10 @@ import fr.reseaumexico.model.InputDesign; import fr.reseaumexico.model.Scenario; import fr.reseaumexico.model.ScenarioImpl; +import fr.reseaumexico.model.parser.ScenarioCSVParser; import fr.reseaumexico.model.parser.ScenarioXmlParser; import fr.reseaumexico.model.writer.ScenarioXmlWriter; -import jaxx.runtime.swing.editor.FileEditor; -import jaxx.runtime.swing.renderer.DecoratorProviderTableCellRenderer; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.JXTable; -import javax.swing.JOptionPane; -import java.awt.event.ItemEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import static org.nuiton.i18n.I18n._; - /** * @author sletellier <letellier@codelutin.com> * @author tchemit <chemit@codelutin.com> @@ -220,38 +225,98 @@ log.info("Import scenario '" + scenarioName + "' from " + importFile); } List<Factor> factors = ui.getModel().getFactors(); - ScenarioXmlParser parser = new ScenarioXmlParser(Maps.uniqueIndex(factors, new Function<Factor, String>() { - @Override - public String apply(Factor input) { - return input.getId(); - } - })); - try { - Scenario scenario = parser.getModel(importFile); + - scenario.setName(scenarioName); - scenario.setOrderNumber(getMaxOrder()); - inputDesign.addScenario(scenario); + // test file type + if (importFile.getName().endsWith("." + _("jmexico.config.scenario.extension.csv"))) { + importCSVScenario(factors, importFile, scenarioName); + } else { + importXMLScenario(factors, importFile, scenarioName); + } + } + } - List<String> unknownFactors = parser.getUnknownFactors(); - if (CollectionUtils.isNotEmpty(unknownFactors)) { - StringBuilder sb = new StringBuilder(); - for (String unknownFactor : unknownFactors) { - sb.append("\n'").append(unknownFactor).append('\''); - } - JOptionPane.showMessageDialog( - ui, - _("jmexico.warning.factor.not.imported", - unknownFactors.size(), sb.toString()), - _("jmexico.title.importScenario"), - JOptionPane.WARNING_MESSAGE); + protected void importCSVScenario(List<Factor> factors, File importFile, String scenarioName) { + Map<String, Factor> factorsNameMap = Maps.uniqueIndex(factors, new Function<Factor, String>() { + @Override + public String apply(Factor input) { + return input.getName(); + } + }); + + InputDesign inputDesign = ui.getInputDesign(); + ScenarioCSVParser parser = new ScenarioCSVParser(factorsNameMap); + try { + Scenario scenario = parser.getModel(importFile); + + scenario.setName(scenarioName); + scenario.setOrderNumber(getMaxOrder()); + inputDesign.addScenario(scenario); + + List<String> unknownFactors = parser.getUnknownFactors(); + if (CollectionUtils.isNotEmpty(unknownFactors)) { + StringBuilder sb = new StringBuilder(); + for (String unknownFactor : unknownFactors) { + sb.append("\n'").append(unknownFactor).append('\''); } + JOptionPane.showMessageDialog( + ui, + _("jmexico.warning.factor.not.imported", + unknownFactors.size(), sb.toString()), + _("jmexico.title.importScenario"), + JOptionPane.WARNING_MESSAGE); + } - } catch (Exception e) { - if (log.isErrorEnabled()) { - log.error("Could not import scenario", e); + } catch (Exception e) { + if (log.isErrorEnabled()) { + log.error("Could not import scenario", e); + } + } + } + + /** + * Parse import file as XML. + * + * @param factorsMap factor map (id > factor) + * @param importFile import file + * @param scenarioName scenario name + */ + protected void importXMLScenario(List<Factor> factors, File importFile, String scenarioName) { + + Map<String, Factor> factorsMap = Maps.uniqueIndex(factors, new Function<Factor, String>() { + @Override + public String apply(Factor input) { + return input.getId(); + } + }); + + InputDesign inputDesign = ui.getInputDesign(); + ScenarioXmlParser parser = new ScenarioXmlParser(factorsMap); + try { + Scenario scenario = parser.getModel(importFile); + + scenario.setName(scenarioName); + scenario.setOrderNumber(getMaxOrder()); + inputDesign.addScenario(scenario); + + List<String> unknownFactors = parser.getUnknownFactors(); + if (CollectionUtils.isNotEmpty(unknownFactors)) { + StringBuilder sb = new StringBuilder(); + for (String unknownFactor : unknownFactors) { + sb.append("\n'").append(unknownFactor).append('\''); } + JOptionPane.showMessageDialog( + ui, + _("jmexico.warning.factor.not.imported", + unknownFactors.size(), sb.toString()), + _("jmexico.title.importScenario"), + JOptionPane.WARNING_MESSAGE); } + + } catch (Exception e) { + if (log.isErrorEnabled()) { + log.error("Could not import scenario", e); + } } } @@ -451,11 +516,10 @@ FileEditor fileEditor = panel.getImportFileEditor(); fileEditor.setAcceptAllFileFilterUsed(false); - fileEditor.setExts(getScenarioExtension()); - fileEditor.setExtsDescription( - _("jmexico.config.scenario.extension.description")); + fileEditor.setExts(getScenarioExtension() + "," + _("jmexico.config.scenario.extension.csv")); + fileEditor.setExtsDescription(_("jmexico.config.scenario.extension.description") + "," + + _("jmexico.config.scenario.extension.csv.description")); - int response = JOptionPane.showConfirmDialog( ui, panel, Modified: trunk/jmexico-editor/src/main/resources/i18n/jmexico-editor_en_GB.properties =================================================================== --- trunk/jmexico-editor/src/main/resources/i18n/jmexico-editor_en_GB.properties 2013-05-15 08:38:26 UTC (rev 117) +++ trunk/jmexico-editor/src/main/resources/i18n/jmexico-editor_en_GB.properties 2013-05-15 12:16:35 UTC (rev 118) @@ -4,7 +4,9 @@ jmexico.action.import.scenario=Import scenario jmexico.action.remove.scenario=Remove scenario jmexico.config.scenario.extension=scenario +jmexico.config.scenario.extension.csv=csv jmexico.config.scenario.extension.description=JMexico scenario file (*.scenario) +jmexico.config.scenario.extension.csv.description=JMexico scenario file (*.csv) jmexico.error.scenario.exportDirectory.required=Error\: Export directory is mandatory. jmexico.error.scenario.exportFilename.required=Error\: Export filename is mandatory. jmexico.error.scenario.importFile.required=Error\: Import file is mandatory. Modified: trunk/jmexico-editor/src/main/resources/i18n/jmexico-editor_fr_FR.properties =================================================================== --- trunk/jmexico-editor/src/main/resources/i18n/jmexico-editor_fr_FR.properties 2013-05-15 08:38:26 UTC (rev 117) +++ trunk/jmexico-editor/src/main/resources/i18n/jmexico-editor_fr_FR.properties 2013-05-15 12:16:35 UTC (rev 118) @@ -4,7 +4,9 @@ jmexico.action.import.scenario=Importer un scénario jmexico.action.remove.scenario=Supprimer un scénario jmexico.config.scenario.extension=scenario +jmexico.config.scenario.extension.csv=csv jmexico.config.scenario.extension.description=Scénario jmexico (*.scenario) +jmexico.config.scenario.extension.csv.description=Scénario jmexico (*.csv) jmexico.error.scenario.exportDirectory.required=Erreur \: Le répertoire d'export est obligatoire. jmexico.error.scenario.exportFilename.required=Erreur \: Le nom du fichier d'export est obligatoire. jmexico.error.scenario.importFile.required=Erreur \: Le fichier d'import est obligatoire. Modified: trunk/jmexico-model/pom.xml =================================================================== --- trunk/jmexico-model/pom.xml 2013-05-15 08:38:26 UTC (rev 117) +++ trunk/jmexico-model/pom.xml 2013-05-15 12:16:35 UTC (rev 118) @@ -48,6 +48,12 @@ <artifactId>xpp3</artifactId> </dependency> + <!-- csv parser --> + <dependency> + <groupId>net.sourceforge.javacsv</groupId> + <artifactId>javacsv</artifactId> + </dependency> + <!-- tests --> <dependency> <groupId>junit</groupId> Added: trunk/jmexico-model/src/main/java/fr/reseaumexico/model/parser/ScenarioCSVParser.java =================================================================== --- trunk/jmexico-model/src/main/java/fr/reseaumexico/model/parser/ScenarioCSVParser.java (rev 0) +++ trunk/jmexico-model/src/main/java/fr/reseaumexico/model/parser/ScenarioCSVParser.java 2013-05-15 12:16:35 UTC (rev 118) @@ -0,0 +1,133 @@ +package fr.reseaumexico.model.parser; + +/* + * #%L + * JMexico :: Model + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2013 Réseau Mexico, Codelutin, Chatellier Eric + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections.CollectionUtils; + +import com.csvreader.CsvReader; +import com.google.common.base.Charsets; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.common.io.Files; + +import fr.reseaumexico.model.Factor; +import fr.reseaumexico.model.MexicoUtil; +import fr.reseaumexico.model.Scenario; +import fr.reseaumexico.model.ScenarioImpl; +import fr.reseaumexico.model.ValueType; + +/** + * Parser for input design csv files, build a {@link Scenario} model. + */ +public class ScenarioCSVParser { + + /** + * Factors in input design model indexed by their id. + * + * @since 0.7 + */ + protected final Map<String, Factor> factors; + + /** + * Factors by their name (only used in {@code standalone} mode to find + * out a factor back if his id is not correct. + */ + protected final Multimap<String, Factor> factorByName; + + protected final List<String> unknownFactors; + + public ScenarioCSVParser(Map<String, Factor> factors) { + this.factors = factors; + this.unknownFactors = new ArrayList<String>(); + this.factorByName = ArrayListMultimap.create(); + // populate the factorByName + factorByName.putAll(Multimaps.index(factors.values(), MexicoUtil.GET_FACTOR_NAME)); + } + + public Scenario getModel(File file) throws IOException { + + unknownFactors.clear(); + + Scenario scenario = new ScenarioImpl(); + + CsvReader csvReader = null; + try { + csvReader = new CsvReader(Files.newReader(file, Charsets.UTF_8), ','); + csvReader.readHeaders(); + + Map<Factor, Object> factorValues = Maps.newLinkedHashMap(); + while (csvReader.readRecord()) { + + String factorName = csvReader.get("factorname"); + + Factor factor = factors.get(factorName); + + if (factor == null) { + // check if factor is possible + Collection<Factor> possibleFactors = factorByName.get(factorName); + if (CollectionUtils.isNotEmpty(possibleFactors)) { + // ok use the first one :( + factor = possibleFactors.iterator().next(); + } else { + + // really not found + // keep factor name + unknownFactors.add(factorName); + continue; + } + } + + ValueType valueType = factor.getDomain().getValueType(); + + // factor value + String value = csvReader.get("factorvalue"); + + factorValues.put(factor, MexicoUtil.getTypedValue(valueType, value)); + } + scenario.setFactorValues(factorValues); + + } finally { + if (csvReader != null) { + csvReader.close(); + } + } + + return scenario; + } + + public List<String> getUnknownFactors() { + return Lists.newArrayList(unknownFactors); + } +} Property changes on: trunk/jmexico-model/src/main/java/fr/reseaumexico/model/parser/ScenarioCSVParser.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2013-05-15 08:38:26 UTC (rev 117) +++ trunk/pom.xml 2013-05-15 12:16:35 UTC (rev 118) @@ -129,6 +129,13 @@ <version>1.1.4c</version> </dependency> + <!-- Csv parser --> + <dependency> + <groupId>net.sourceforge.javacsv</groupId> + <artifactId>javacsv</artifactId> + <version>2.0</version> + </dependency> + <!-- xml unit for tests --> <dependency> <groupId>xmlunit</groupId>
participants (1)
-
echatellier@users.forge.codelutin.com