r3885 - trunk/src/main/java/fr/ifremer/isisfish/datastore
Author: bpoussin Date: 2014-02-13 23:24:45 +0100 (Thu, 13 Feb 2014) New Revision: 3885 Url: http://forge.codelutin.com/projects/isis-fish/repository/revisions/3885 Log: add new ResultStorage only in memory Added: trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultStorageInMemory.java Modified: trunk/src/main/java/fr/ifremer/isisfish/datastore/SimulationStorage.java Copied: trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultStorageInMemory.java (from rev 3884, trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultDatabaseStorage.java) =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultStorageInMemory.java (rev 0) +++ trunk/src/main/java/fr/ifremer/isisfish/datastore/ResultStorageInMemory.java 2014-02-13 22:24:45 UTC (rev 3885) @@ -0,0 +1,497 @@ +/* + * #%L + * IsisFish + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2002 - 2011 Ifremer, Code Lutin, Cédric Pineau, Benjamin Poussin, Chatellier Eric + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +package fr.ifremer.isisfish.datastore; + +import static org.nuiton.i18n.I18n._; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.math.matrix.MatrixFactory; +import org.nuiton.math.matrix.MatrixIterator; +import org.nuiton.math.matrix.MatrixND; +import org.nuiton.topia.TopiaContext; +import org.nuiton.util.ArrayUtil; +import org.nuiton.util.HashList; + +import fr.ifremer.isisfish.IsisFishException; +import fr.ifremer.isisfish.entities.Population; +import fr.ifremer.isisfish.export.Export; +import fr.ifremer.isisfish.export.SensitivityExport; +import fr.ifremer.isisfish.rule.Rule; +import fr.ifremer.isisfish.simulator.SimulationContext; +import fr.ifremer.isisfish.simulator.SimulationException; +import fr.ifremer.isisfish.simulator.SimulationPlan; +import fr.ifremer.isisfish.simulator.SimulationResultGetter; +import fr.ifremer.isisfish.types.TimeStep; +import fr.ifremer.isisfish.types.Month; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.Map; + +/** + * Cette classe permet de conserver des résultats de simulation. Elle permet + * ensuite de les récupérer. Les résultats sont stockés en mémoire. + * + * Created: 29 sept. 2004 + * + * @author Benjamin Poussin <poussin@codelutin.com> + * @version $Revision$ + * + * Mise a jour: $Date$ + * par : $Author$ + */ +public class ResultStorageInMemory implements SimulationResultGetter, ResultStorage { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(ResultStorageInMemory.class); + + final static public String MAX_TIME_STEP = "ResultStorageInMemory.maxTimeStep"; + protected int maxTimeStep = 12; // default to 1 year + protected SimulationStorage simulation = null; + + LinkedHashMap<TimeStep, Map<String, MatrixND>> data = new LinkedHashMap<TimeStep, Map<String, MatrixND>>() { + private static final long serialVersionUID = 1L; + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > maxTimeStep; + } + }; + + LinkedHashMap<TimeStep, List<Rule>> rules = new LinkedHashMap<TimeStep, List<Rule>>() { + private static final long serialVersionUID = 1L; + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > maxTimeStep; + } + }; + + + /** result enabled */ + transient protected Set<String> enabledResult = null; + + /** + * Les ResultStorage ne doivent pas etre instancier directement, mais + * recuperer a partir d'un + * {@link fr.ifremer.isisfish.datastore.SimulationStorage#getResultStorage()} + * + * @param simulation storage to get result + */ + public ResultStorageInMemory(SimulationStorage simulation) { + this.simulation = simulation; + maxTimeStep = Integer.parseInt(simulation.getParameter().getTagValue().get(MAX_TIME_STEP)); + } + + @Override + public void delete() { + data.clear(); + } + + @Override + public void close() { + // do nothing, closed by simulation storage closing + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#isEnabled(java.lang.String) + */ + @Override + public boolean isEnabled(String name) { + name = name.trim(); + if (enabledResult == null) { + enabledResult = new HashSet<String>(); + + Collection<String> resultEnabled = simulation.getParameter() + .getResultEnabled(); + enabledResult.addAll(resultEnabled); + + // test on export + List<String> exportNames = simulation.getParameter().getExportNames(); + if (exportNames != null) { + for (String exportName : exportNames) { + ExportStorage storage = ExportStorage.getExport(exportName); + try { + Export export = storage.getNewExportInstance(); + for (String resultName : export.getNecessaryResult()) { + enabledResult.add(resultName); + } + } catch (IsisFishException eee) { + if (log.isWarnEnabled()) { + log.warn(_("isisfish.error.instanciate.export", + exportName), eee); + } + } + } + } + + // test on sensitivity export + List<SensitivityExport> sensitivityExports = simulation + .getParameter().getSensitivityExport(); + if (sensitivityExports != null) { + for (SensitivityExport sensitivityExport : sensitivityExports) { + for (String resultName : sensitivityExport.getNecessaryResult()) { + enabledResult.add(resultName); + } + } + } + + // test on rules + List<Rule> rules = simulation.getParameter().getRules(); + if (rules != null) { + for (Rule rule : rules) { + for (String resultName : rule.getNecessaryResult()) { + enabledResult.add(resultName); + } + } + } + + // test on plans + List<SimulationPlan> plans = simulation.getParameter().getSimulationPlans(); + if (plans != null) { + for (SimulationPlan plan : plans) { + for (String resultName : plan.getNecessaryResult()) { + enabledResult.add(resultName); + } + } + } + log.info("Enabled result: " + enabledResult); + } + boolean result = enabledResult.contains(name); + return result; + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#addResult(fr.ifremer.isisfish.types.TimeStep, org.nuiton.math.matrix.MatrixND) + */ + @Override + public void addResult(TimeStep step, MatrixND mat) throws IsisFishException { + addResult(false, step, mat.getName(), mat); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#addResult(fr.ifremer.isisfish.types.TimeStep, fr.ifremer.isisfish.entities.Population, org.nuiton.math.matrix.MatrixND) + */ + @Override + public void addResult(TimeStep step, Population pop, MatrixND mat) throws IsisFishException { + addResult(false, step, mat.getName(), pop, mat); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#addResult(boolean, fr.ifremer.isisfish.types.TimeStep, org.nuiton.math.matrix.MatrixND) + */ + @Override + public void addResult(boolean force, TimeStep step, MatrixND mat) throws IsisFishException { + addResult(force, step, mat.getName(), mat); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#addResult(boolean, fr.ifremer.isisfish.types.TimeStep, fr.ifremer.isisfish.entities.Population, org.nuiton.math.matrix.MatrixND) + */ + @Override + public void addResult(boolean force, TimeStep step, Population pop, MatrixND mat) throws IsisFishException { + addResult(force, step, mat.getName(), pop, mat); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#addResult(fr.ifremer.isisfish.types.TimeStep, java.lang.String, fr.ifremer.isisfish.entities.Population, org.nuiton.math.matrix.MatrixND) + */ + @Override + public void addResult(TimeStep step, String name, Population pop, MatrixND mat) throws IsisFishException { + addResult(false, step, name, pop, mat); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#addResult(fr.ifremer.isisfish.types.TimeStep, java.lang.String, org.nuiton.math.matrix.MatrixND) + */ + @Override + public void addResult(TimeStep step, String name, MatrixND mat) throws IsisFishException { + addResult(false, step, name, mat); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#addResult(boolean, fr.ifremer.isisfish.types.TimeStep, java.lang.String, fr.ifremer.isisfish.entities.Population, org.nuiton.math.matrix.MatrixND) + */ + @Override + public void addResult(boolean force, TimeStep step, String name, Population pop, MatrixND mat) throws IsisFishException { + if (force || isEnabled(name)) { + doAddResult(step, name + " " + pop, mat); + } + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#addResult(boolean, fr.ifremer.isisfish.types.TimeStep, java.lang.String, org.nuiton.math.matrix.MatrixND) + */ + @Override + public void addResult(boolean force, TimeStep step, String name, MatrixND mat) throws IsisFishException { + if (force || isEnabled(name)) { + doAddResult(step, name, mat); + } + } + + protected void doAddResult(TimeStep step, String name, MatrixND mat) throws IsisFishException { + // si la matrice n'a pas de semantique on refuse + for (int i = 0; i < mat.getDimCount(); i++) { + // la semantique n'est pas bonne des qu'il y a un null dedans + if (mat.getSemantic(i).contains(null)) { + throw new SimulationException( + "Erreur le résultat que vous souhaitez enregistrer n'a pas d'information convenable pour la dimension: " + + i + " " + mat.getDimensionName(i)); + } + } + + // on fait une copie pour avoir reellement des resultats independant + // FIXME echatellier 20120829 : faire une copie optimiser + // suivant l'implementation du vector plutot qu'un parcourt + // via un iterateur de semantiques (plus couteux) + MatrixND newMat = mat.copy(); + Map<String, MatrixND> mats = data.get(step); + if (mats == null) { + mats = new HashMap<String, MatrixND>(); + data.put(step, mats); + } + + mats.put(name, newMat); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#addActiveRule(fr.ifremer.isisfish.types.TimeStep, fr.ifremer.isisfish.rule.Rule) + */ + @Override + public void addActiveRule(TimeStep step, Rule rule) throws IsisFishException { + List<Rule> list = rules.get(step); + if (list == null) { + list = new LinkedList<Rule>(); + rules.put(step, list); + } + + list.add(rule); + +// result.setActiveRuleStep(step); +// result.setName(RuleStorage.getName(rule)); +// result.setParam(RuleStorage.getParamAsString(rule)); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#getResultName() + */ + @Override + public List<String> getResultName() { + + Set<String> result = new HashSet<String>(); + + for (Map<String, MatrixND> mats : data.values()) { + result.addAll(mats.keySet()); + } + + return new ArrayList<String>(result); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#getMatrix(fr.ifremer.isisfish.types.TimeStep, fr.ifremer.isisfish.entities.Population, java.lang.String) + */ + @Override + public MatrixND getMatrix(TimeStep step, Population pop, String name) { + String newName = name + " " + pop; + return getMatrix(step, newName); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#getMatrix(fr.ifremer.isisfish.types.TimeStep, java.lang.String) + */ + @Override + public MatrixND getMatrix(TimeStep step, String name) { + MatrixND result = null; + Map<String, MatrixND> mats = data.get(step); + if (mats != null) { + result = mats.get(name); + } + return result; + } + + @Override + public MatrixND getMatrix(TimeStep step, String name, TopiaContext tx) { + return getMatrix(step, name); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#getMatrix(fr.ifremer.isisfish.entities.Population, java.lang.String) + */ + @Override + public MatrixND getMatrix(Population pop, String name) { + String newName = name + " " + pop; + return getMatrix(newName); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#getMatrix(fr.ifremer.isisfish.entities.Population, java.lang.String, org.nuiton.topia.TopiaContext) + */ + @Override + public MatrixND getMatrix(Population pop, String name, TopiaContext tx) { + String newName = name + " " + pop; + return getMatrix(newName, tx); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#getMatrix(java.lang.String) + */ + @Override + public MatrixND getMatrix(String name) { + MatrixND result = null; + + List<TimeStep> steps = new ArrayList<TimeStep>(); + Map<TimeStep, MatrixND> mats = new LinkedHashMap<TimeStep, MatrixND>(); + MatrixND matExample = null; + for (Map.Entry<TimeStep, Map<String, MatrixND>> e : data.entrySet()) { + TimeStep ts = e.getKey(); + MatrixND mat = e.getValue().get(name); + if (mat != null) { + steps.add(ts); + mats.put(ts, mat); + matExample = mat; + } + } + + if (mats.size() > 0) { + // recuperation des noms des dimensions + String[] dimNames = new String[1 + matExample.getDimCount()]; + dimNames[0] = _("isisfish.common.date"); + for (int i = 1; i < dimNames.length; i++) { + dimNames[i] = matExample.getDimensionName(i - 1); + } + + // creation de la semantique pour la matrice resultat. +1 pour les dates + List[] sem = new List[1 + matExample.getDimCount()]; + sem[0] = steps; + + for (int i = 1; i < sem.length; i++) { + sem[i] = new HashList(); + } + + for (MatrixND mattmp : mats.values()) { + if (log.isTraceEnabled()) { + log.trace("Ajout de la semantics: " + + Arrays.asList(mattmp.getSemantics())); + } + + for (int s = 0; s < mattmp.getDimCount(); s++) { + sem[s + 1].addAll(mattmp.getSemantic(s)); + } + } + + if (log.isTraceEnabled()) { + log.trace("La semantique final est: " + Arrays.asList(sem)); + } + + // creation de la matrice resultat + result = MatrixFactory.getInstance().create(name, sem, dimNames); + + // recuperation du resultat pour chaque date de la simulation, de Date(0) à lastDate + for (Map.Entry<TimeStep, MatrixND> e : mats.entrySet()) { + TimeStep d = e.getKey(); + MatrixND mat = e.getValue(); + // on recupere dans la matrice resultat l'endroit on il faut + // mettre la matrice + MatrixND submat = result.getSubMatrix(0, d, 1); + // on met les valeur de mat dans la sous matrice extraite + for (MatrixIterator mi = mat.iterator(); mi.next();) { + submat.setValue( + ArrayUtil.concat(new Object[] { d }, + mi.getSemanticsCoordinates()), mi.getValue()); + } + } + } + + return result; + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#getMatrix(java.lang.String, org.nuiton.topia.TopiaContext) + */ + @Override + public MatrixND getMatrix(String name, TopiaContext tx) { + return getMatrix(name); + } + + /* (non-Javadoc) + * @see fr.ifremer.isisfish.datastore.ResultStorage#getLastStep() + */ + @Override + public TimeStep getLastStep() { + int monthNumber = simulation.getParameter().getNumberOfYear() + * Month.NUMBER_OF_MONTH; + TimeStep result = new TimeStep(monthNumber - 1); // -1 because date begin at 0 + return result; + } + + /* + * @see fr.ifremer.isisfish.simulator.SimulationResultListener#addResult(fr.ifremer.isisfish.simulator.SimulationContext, fr.ifremer.isisfish.types.TimeStep, java.lang.String, org.nuiton.math.matrix.MatrixND) + */ + @Override + public void addResult(SimulationContext context, TimeStep step, String name, + MatrixND mat) throws IsisFishException { + doAddResult(step, name, mat); + } + + /* + * @see fr.ifremer.isisfish.simulator.SimulationResultGetter#getMatrix(fr.ifremer.isisfish.simulator.SimulationContext, fr.ifremer.isisfish.types.TimeStep, java.lang.String) + */ + @Override + public MatrixND getMatrix(SimulationContext context, TimeStep step, String name) { + MatrixND result = getMatrix(step, name); + return result; + } + + /* + * @see fr.ifremer.isisfish.simulator.SimulationResultGetter#getMatrix(fr.ifremer.isisfish.simulator.SimulationContext, java.lang.String) + */ + @Override + public MatrixND getMatrix(SimulationContext context, String name) { + MatrixND result = getMatrix(name); + return result; + } + + /* + * @see fr.ifremer.isisfish.simulator.SimulationListener#afterSimulation(fr.ifremer.isisfish.simulator.SimulationContext) + */ + @Override + public void afterSimulation(SimulationContext context) { + } + + /* + * @see fr.ifremer.isisfish.simulator.SimulationListener#beforeSimulation(fr.ifremer.isisfish.simulator.SimulationContext) + */ + @Override + public void beforeSimulation(SimulationContext context) { + } + +} Modified: trunk/src/main/java/fr/ifremer/isisfish/datastore/SimulationStorage.java =================================================================== --- trunk/src/main/java/fr/ifremer/isisfish/datastore/SimulationStorage.java 2014-02-05 11:01:15 UTC (rev 3884) +++ trunk/src/main/java/fr/ifremer/isisfish/datastore/SimulationStorage.java 2014-02-13 22:24:45 UTC (rev 3885) @@ -475,10 +475,17 @@ if (simuVersion.before(version4200)) { resultStorage = new ResultDatabaseStorage(this); } else { - try { - resultStorage = new ResultMappedStorage(this); - } catch (IOException ex) { - throw new StorageException("Can't get storage", ex); + // if user ask for ResultStorageInMemory, used it + String maxTimeStep = param.getTagValue().get(ResultStorageInMemory.MAX_TIME_STEP); + if (maxTimeStep != null) { + // use in memory with max time step + resultStorage = new ResultStorageInMemory(this); + } else { + try { + resultStorage = new ResultMappedStorage(this); + } catch (IOException ex) { + throw new StorageException("Can't get storage", ex); + } } } }
participants (1)
-
bpoussin@users.forge.codelutin.com