r1141 - in trunk: coser-business/src/main/java/fr/ifremer/coser/bean coser-business/src/main/java/fr/ifremer/coser/result coser-business/src/main/java/fr/ifremer/coser/result/repository coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy coser-business/src/main/java/fr/ifremer/coser/result/request coser-business/src/main/java/fr/ifremer/coser/storage coser-business/src/main/java/fr/ifremer/coser/util
Author: tchemit Date: 2014-03-11 10:28:43 +0100 (Tue, 11 Mar 2014) New Revision: 1141 Url: http://forge.codelutin.com/projects/coser/repository/revisions/1141 Log: refs-90 #4664 (i18n) refs-60 #4651 (introduce ResultProducer + implements ExtractRequest) Added: trunk/coser-business/src/main/java/fr/ifremer/coser/bean/SpeciesListMap.java trunk/coser-business/src/main/java/fr/ifremer/coser/bean/SpeciesMap.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/RequestUnavailableForProducerException.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/ResultProducer.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/CommunityIndicatorResultProducer.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/ExtractResultProducer.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/MapResultProducer.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/PopulationIndicatorResultProducer.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/RawDataResultProducer.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/CommunityIndicatorResultProducer.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/ExtractResultProducer.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/MapResultProducer.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/PopulationIndicatorResultProducer.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/RawDataResultProducer.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/ExtractRequest.java trunk/coser-web/src/main/resources/fr/ifremer/coser/web/actions/search/ trunk/coser-web/src/main/resources/fr/ifremer/coser/web/actions/search/ExtractAction-extract-quality-validation.xml Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/bean/ZoneMap.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/CoserResultEngine.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/Reports.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/ResultRepository.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/EchoBaseResultRepository.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/LegacyResultRepository.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/CoserRequestBuilder.java trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/IndicatorRequest.java trunk/coser-business/src/main/java/fr/ifremer/coser/storage/DataStorages.java trunk/coser-business/src/main/java/fr/ifremer/coser/util/DataType.java trunk/coser-business/src/main/resources/i18n/coser-business_en_GB.properties trunk/coser-business/src/main/resources/i18n/coser-business_fr_FR.properties trunk/coser-business/src/test/java/fr/ifremer/coser/result/repository/echobase/EchoBaseResultRepositoryTest.java trunk/coser-web/src/main/java/fr/ifremer/coser/web/ServiceHelper.java trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/com/GraphDataAction.java trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/com/GraphDownloadAction.java trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/common/CoserAction.java trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/search/ExtractAction.java trunk/coser-web/src/main/webapp/WEB-INF/content/search/extract-input.jsp Added: trunk/coser-business/src/main/java/fr/ifremer/coser/bean/SpeciesListMap.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/bean/SpeciesListMap.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/bean/SpeciesListMap.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,96 @@ +package fr.ifremer.coser.bean; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin + * %% + * 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 fr.ifremer.coser.storage.DataStorage; +import fr.ifremer.coser.storage.DataStorages; +import org.nuiton.i18n.I18n; + +import java.io.File; +import java.util.Iterator; +import java.util.Locale; + +/** + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class SpeciesListMap { + + /** + * Species' list storage. + */ + protected final DataStorage storage; + + public SpeciesListMap(File speciesFile) { + storage = DataStorages.load(speciesFile); + } + + public String getSpeciesListName(Locale locale, String specesList) { + // recherche de la traduction de l'id de liste + // les liste sont a1, T1, T2 ... + String listLetter = String.valueOf(specesList.charAt(0)); + String translation = "## " + specesList + " not found ##"; + Iterator<String[]> typeIterator = iterator(true); + while (typeIterator.hasNext()) { + // "Types";"Commentaire";"NumSys min";"NumSys max";"Code" + String[] tupleType = typeIterator.next(); + if (tupleType[4].equals(listLetter)) { + + // gestion du groupe "Tous" + // cas special, c'est la seule valeur du fichier + // code type espece qui a besoin d'une traduction + if (tupleType[4].equalsIgnoreCase("T")) { + + translation = I18n.l(locale, "coser.business.specesList.nameForAll", specesList.charAt(1)); +// if (locale != null && "fr".equals(locale.getLanguage())) { +// translation = "Tous Liste " + specesList.charAt(1); +// } else if (locale != null && "en".equals(locale.getLanguage())) { +// translation = "Todo Lista " + specesList.charAt(1); +// } else { +// translation = "All List " + specesList.charAt(1); +// } + } else { + // ajout de la traduction du nom de liste plus le numéro + translation = I18n.l(locale, "coser.business.specesList.name", tupleType[0], specesList.charAt(1)); +// if (locale != null && "fr".equals(locale.getLanguage())) { +// translation = tupleType[0] + " Liste " + specesList.charAt(1); +// } else if (locale != null && "en".equals(locale.getLanguage())) { +// translation = tupleType[0] + " Lista " + specesList.charAt(1); +// } else { +// translation = tupleType[0] + " List " + specesList.charAt(1); +// } + } + break; + } + } + return translation; + } + + protected Iterator<String[]> iterator(boolean skipFirstLine) { + // "Types";"Commentaire";"NumSys min";"NumSys max";"Code" + Iterator<String[]> iterator = storage.iterator(skipFirstLine); + return iterator; + } +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/bean/SpeciesListMap.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/coser-business/src/main/java/fr/ifremer/coser/bean/SpeciesMap.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/bean/SpeciesMap.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/bean/SpeciesMap.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,130 @@ +package fr.ifremer.coser.bean; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin + * %% + * 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 com.google.common.collect.Maps; +import fr.ifremer.coser.storage.DataStorage; +import fr.ifremer.coser.storage.DataStorages; + +import java.io.File; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; + +/** + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class SpeciesMap { + + /** + * Species' storage. + */ + protected final DataStorage storage; + + /** + * Cache of species definition. + */ + protected Map<String, String> speciesMap; + + + public SpeciesMap(File speciesFile) { + storage = DataStorages.load(speciesFile); + } + + public DataStorage getStorage() { + return storage; + } + + public Iterator<String[]> iterator(boolean skipFirstLine) { + // "C_Perm","NumSys","NivSys","C_VALIDE","L_VALIDE","AA_VALIDE","C_TxP\u00E8re","Taxa" + Iterator<String[]> iterator = storage.iterator(skipFirstLine); + return iterator; + } + + public Map<String, String> getSpeciesMap() { + if (speciesMap == null) { + speciesMap = Maps.newTreeMap(); + + // load species file + Iterator<String[]> iterator = iterator(true); + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + String speciesCode = tuple[3]; + String speciesLabel = tuple[4] + " " + tuple[5]; + speciesMap.put(speciesCode, speciesLabel); + } + speciesMap = Collections.unmodifiableMap(speciesMap); + } + return speciesMap; + } + + public String getSpeciesName(String species) { + return getSpeciesMap().get(species); + } + + public Map<String, String> getSpeciesSubMap(Collection<String> speciesList) { + + Map<String, String> result = Maps.newTreeMap(); + + if (speciesList != null) { + + Map<String, String> map = getSpeciesMap(); + for (String species : speciesList) { + String speciesLabel = map.get(species); + result.put(species, speciesLabel); + } + } + + return result; + } + + /** + * Retourne le nom d'affichage d'une especes pour les rapports. + * + * @param species species code + * @return species display name + * @since 1.5 + */ + public String getReportDisplayName(String species) { + String displayName = null; + + Iterator<String[]> iterator = iterator(true); + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + + // "C_Perm","NumSys","NivSys","C_VALIDE","L_VALIDE","AA_VALIDE","C_TxP\u00E8re","Taxa" + String speciesCode = tuple[3]; + if (speciesCode.equals(species)) { + // nom + auteur (sans ajout de parenthese : important) + displayName = tuple[4] + " " + tuple[5]; + break; + } + } + + return displayName; + } +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/bean/SpeciesMap.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/bean/ZoneMap.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/bean/ZoneMap.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/bean/ZoneMap.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -23,6 +23,7 @@ */ import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import fr.ifremer.coser.storage.DataStorage; import fr.ifremer.coser.storage.DataStorages; import fr.ifremer.coser.storage.MemoryDataStorage; @@ -208,4 +209,18 @@ public DataStorage getStorage() { return storage; } + + public Map<String, String> getSubZonesMap(String zoneId, List<String> allowedZones) { + Map<String, String> result = Maps.newHashMap(); + + if (allowedZones != null) { + + if (allowedZones.contains(zoneId)) { + String zoneFullName = getZoneFullNameWithNoFacade(zoneId); + result.put(zoneId, zoneFullName); + } + } + + return result; + } } Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/result/CoserResultEngine.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/CoserResultEngine.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/CoserResultEngine.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -31,8 +31,7 @@ import fr.ifremer.coser.result.repository.ResultRepositoryProvider; import fr.ifremer.coser.result.repository.echobase.EchoBaseResultRepositoryProvider; import fr.ifremer.coser.result.repository.legacy.LegacyResultRepositoryProvider; -import fr.ifremer.coser.result.request.IndicatorRequest; -import org.apache.commons.collections.MapUtils; +import org.apache.commons.collections4.MapUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -97,6 +96,11 @@ this.repositories = null; } + public Map<String, String> getAvailableExtractTypes() { + Map<String, String> result = Maps.newLinkedHashMap(); + return result; + } + public Map<String, String> getAvailableZones(CoserRequest request) { Map<String, String> result = Maps.newHashMap(); for (ResultRepository repository : getRepositories()) { @@ -119,7 +123,7 @@ return result; } - public Map<String, String> getAvailableIndicators(IndicatorRequest request) { + public Map<String, String> getAvailableIndicators(CoserRequest request) { Map<String, String> result = Maps.newHashMap(); for (ResultRepository repository : getRepositories()) { Map<String, String> resultForRepository = repository.getAvailableIndicators(request); Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/result/Reports.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/Reports.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/Reports.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -22,10 +22,59 @@ * #L% */ +import com.google.common.base.Preconditions; +import com.itextpdf.text.DocumentException; +import fr.ifremer.coser.CoserConstants; +import fr.ifremer.coser.CoserTechnicalException; +import fr.ifremer.coser.CoserUtils; +import fr.ifremer.coser.bean.IndicatorMap; +import fr.ifremer.coser.bean.Project; +import fr.ifremer.coser.bean.RSufiResult; +import fr.ifremer.coser.bean.RSufiResultPath; +import fr.ifremer.coser.bean.Selection; +import fr.ifremer.coser.bean.ZoneMap; +import fr.ifremer.coser.storage.DataStorage; +import fr.ifremer.coser.storage.DataStorages; +import freemarker.cache.ClassTemplateLoader; +import freemarker.ext.beans.BeansWrapper; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import org.apache.commons.collections4.keyvalue.MultiKey; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.i18n.I18n; +import org.w3c.dom.Document; +import org.xhtmlrenderer.pdf.ITextRenderer; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import static org.nuiton.i18n.I18n.l; + /** + * For reports generation. + * <p/> * Created on 3/7/14. * * @author Tony Chemit <chemit@codelutin.com> @@ -33,39 +82,384 @@ */ public class Reports { - public static String getYearChartTitle(Locale locale) { - String yearAxis = "Year"; - if ("fr".equals(locale.getLanguage())) { - yearAxis = "Ann\u00E9e"; - } else if ("es".equals(locale.getLanguage())) { - yearAxis = "A\u00F1o"; - } + /** Logger. */ + private static final Log log = LogFactory.getLog(Reports.class); + + /** Freemarker. */ + protected Configuration freemarkerConfiguration; + + public Reports() { + + freemarkerConfiguration = new Configuration(); + + // needed to overwrite "Defaults to default system encoding." + // fix encoding issue on some systems + freemarkerConfiguration.setEncoding(Locale.getDefault(), "UTF-8"); + + // specific template loader to get template from jars (classpath) + ClassTemplateLoader templateLoader = new ClassTemplateLoader(Reports.class, "/ftl"); + freemarkerConfiguration.setTemplateLoader(templateLoader); + + // pour les maps dans les template (entre autre) + freemarkerConfiguration.setObjectWrapper(new BeansWrapper()); + } + + public String getDechargeFilename(Locale locale) { + Preconditions.checkNotNull(locale); + String filename = I18n.l(locale, "coser.business.dataDisclaimer.filename"); +// if (locale != null && "fr".equals(locale.getLanguage())) { +// filename = "DechargeDonnees.pdf"; +// } else if (locale != null && "es".equals(locale.getLanguage())) { +// filename = "DatosDeExencionDeResponsabilidad.pdf"; +// } else { +// filename = "DataDisclaimer.pdf"; +// } + return filename; + } + + public String getYearChartTitle(Locale locale) { + Preconditions.checkNotNull(locale); + String yearAxis = I18n.l(locale, "coser.business.year"); +// String yearAxis = "Year"; +// if ("fr".equals(locale.getLanguage())) { +// yearAxis = "Ann\u00E9e"; +// } else if ("es".equals(locale.getLanguage())) { +// yearAxis = "A\u00F1o"; +// } return yearAxis; } /** - * Retourne le nom d'affichage d'une especes pour les rapports. + * Genere le fichier PDF d'information sur les espèces incluses dans les + * calculs des indicateurs de communautés, à jointe à chaque téléchargement. * - * @param reftax species data storage - * @param species species code - * @return species display name - * @since 1.5 + * @param path path to result + * @param resultDirectory result directory + * @param locale locale + * @param indicatorLocalizedMap localized indicator map + * @return generated pdf file */ - public static String getReportDisplayName(Iterator<String[]> reftax, String species) { - String displayName = null; + public File generateMetaFilePDF(RSufiResultPath path, + File resultDirectory, + Locale locale, + IndicatorMap indicatorLocalizedMap) { - while (reftax.hasNext()) { - String[] tuple = reftax.next(); + Project project = path.getProject(); + Selection selection = path.getSelection(); + RSufiResult rsufiResult = path.getRsufiResult(); + File result = null; + + // chargement du reftax et des code types especes pour connaitre + // le type des especes de poissons + // parcourt du fichier des types de données + Map<String, Integer> refTaxSpeciesNumSys = new HashMap<String, Integer>(); + Map<String, String> refTaxSpeciesName = new HashMap<String, String>(); + Iterator<String[]> itReftax = project.getRefTaxSpecies().iterator(true); + while (itReftax.hasNext()) { + String[] tuple = itReftax.next(); // "C_Perm","NumSys","NivSys","C_VALIDE","L_VALIDE","AA_VALIDE","C_TxP\u00E8re","Taxa" String speciesCode = tuple[3]; - if (speciesCode.equals(species)) { - // nom + auteur (sans ajout de parenthese : important) - displayName = tuple[4] + " " + tuple[5]; - break; + Integer iNumSys = Integer.valueOf(tuple[1]); + refTaxSpeciesNumSys.put(speciesCode, iNumSys); + + // fix html entities bug + String speciesSciName = StringEscapeUtils.escapeXml(tuple[4]); + String speciesAuthor = StringEscapeUtils.escapeXml(tuple[5]); + + // TODO little hack for italic species + refTaxSpeciesName.put(speciesCode, "<span style='font-style:italic'>" + speciesSciName + "</span> " + speciesAuthor); + } + + // code type / especes + Map<String, Integer[]> specyTypes = new HashMap<String, Integer[]>(); + Iterator<String[]> itTypeSpecies = project.getTypeEspeces().iterator(true); + while (itTypeSpecies.hasNext()) { + // "Types";"Commentaire";"NumSys min";"NumSys max","Code" + String[] tuple = itTypeSpecies.next(); + String specyTypeCode = tuple[4]; + + Integer iMinNumSys = Integer.valueOf(tuple[2]); + Integer iMaxNumSys = Integer.valueOf(tuple[3]); + specyTypes.put(specyTypeCode, new Integer[]{iMinNumSys, iMaxNumSys}); + } + + // le fichier estpopind + File estComIndFile = new File(resultDirectory, rsufiResult.getEstComIndName()); + + // donnees intermediare (map liste id > liste des indicateurs) + Map<String, SortedSet<String>> indicatorMap = new HashMap<String, SortedSet<String>>(); + + // le resutat sera une map complexe + // map liste id > liste des especes (nom complet) + Map<String, SortedSet<String>> speciesMap = new HashMap<String, SortedSet<String>>(); + + // Campagne Indicateur Liste Strate Annee Estimation EcartType CV + DataStorage dataStorage = DataStorages.load(estComIndFile, CoserConstants.CSV_RESULT_SEPARATOR_CHAR); + Iterator<String[]> estComIndIterator = dataStorage.iterator(true); + while (estComIndIterator.hasNext()) { + String[] tuple = estComIndIterator.next(); + + String indicatorCode = tuple[1]; + String listIdCode = tuple[2]; // c1, p2, T3 ... + + String listNumber = listIdCode.substring(1); // 1, 2, 3 + + // get indicator list + SortedSet<String> indicatorList = indicatorMap.get(listNumber); + if (indicatorList == null) { + indicatorList = new TreeSet<String>(); + indicatorMap.put(listNumber, indicatorList); } + + // get indicator full name + String indicatorName = indicatorLocalizedMap.getIndicatorValue(indicatorCode, locale.getLanguage()); + // peut arriver pour les indicateurs inconnu par coser + if (indicatorName != null) { + indicatorList.add(indicatorName); + } } - return displayName; + // seconde pass, remplit la map speciesMap avec les listes configurées + // dans la selection + for (String listNumber : indicatorMap.keySet()) { + List<String> selectionSpeciesList = null; + if ("1".equals(listNumber)) { + selectionSpeciesList = selection.getSelectedSpecies(); + } else if ("2".equals(listNumber)) { + selectionSpeciesList = selection.getSelectedSpeciesOccDens(); + } else if ("3".equals(listNumber)) { + selectionSpeciesList = selection.getSelectedSpeciesSizeAllYear(); + } else if ("4".equals(listNumber)) { + selectionSpeciesList = selection.getSelectedSpeciesMaturity(); + } + + if (selectionSpeciesList != null) { + SortedSet<String> speciesList = new TreeSet<String>(); + + for (String speciesCode : selectionSpeciesList) { + // get species full name + String speciesName = refTaxSpeciesName.get(speciesCode); + + // recupere le code type de l'espece, "m", "c", "p" ... + Integer speciesNumSys = refTaxSpeciesNumSys.get(speciesCode); + for (Map.Entry<String, Integer[]> speciesTypeEntry : specyTypes.entrySet()) { + String speciesTypeCode = speciesTypeEntry.getKey(); + Integer[] bound = speciesTypeEntry.getValue(); + + if (speciesNumSys >= bound[0] && speciesNumSys <= bound[1]) { + speciesName = "(" + speciesTypeCode + ") " + speciesName; + break; + } + } + // end code type espece + + speciesList.add(speciesName); + } + speciesMap.put(listNumber, speciesList); + } else { + if (log.isWarnEnabled()) { + log.warn("Can't get species list for list id " + listNumber); + } + } + } + + OutputStream os = null; + try { + // render freemarker template + Template mapTemplate = freemarkerConfiguration.getTemplate("metainfo.ftl", locale); + + Map<String, Object> root = new HashMap<String, Object>(); + root.put("indicatorsMap", indicatorMap); + root.put("speciesMap", speciesMap); + + Writer out = new StringWriter(); + mapTemplate.process(root, out); + out.flush(); + + // get content as w3c document + Document document = CoserUtils.parseDocument(out.toString()); + + // render template output as pdf + result = File.createTempFile("coser-metainfo-", ".pdf"); + result.deleteOnExit(); + os = new FileOutputStream(result); + + ITextRenderer renderer = new ITextRenderer(); + renderer.setDocument(document, null); + renderer.layout(); + renderer.createPDF(os); + + os.close(); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't generate meta info file", ex); + } catch (TemplateException ex) { + throw new CoserTechnicalException("Can't generate meta info file", ex); + } catch (DocumentException ex) { + throw new CoserTechnicalException("Can't generate meta info file", ex); + } finally { + IOUtils.closeQuietly(os); + } + + return result; } + + /** + * Genere le PDF dynamique de decharge à partir du template freemarker. + * + * @param disclamerPdf pdf file to generate + * @param locale generated pdf locale + */ + public void generateDechargePDF(File disclamerPdf, Locale locale, Date updateDate, String surveyName) { + + OutputStream os = null; + + try { + // get some info to put into pdf +// Date updateDate = getLastDataUpdateDate(); + +// // il se peut que pour l'extraction un fichier de décharge ne soit +// // pas généré pour une campagne en particulier +// // on passe un nom vide a freemarker +// String surveyName = ""; +// if (resultDirectory != null && rSufiResult != null) { +// surveyName = projectService.getProjectSurveyName(resultDirectory, rSufiResult); +// } + + // render freemarker template + Template mapTemplate = freemarkerConfiguration.getTemplate("decharge.ftl", locale); + + Map<String, Object> root = new HashMap<String, Object>(); + root.put("updateDate", updateDate); + root.put("surveyName", surveyName); + + Writer out = new StringWriter(); + mapTemplate.process(root, out); + out.flush(); + + // get content as w3c document + Document document = CoserUtils.parseDocument(out.toString()); + + // render template output as pdf + os = new FileOutputStream(disclamerPdf); + + ITextRenderer renderer = new ITextRenderer(); + renderer.setDocument(document, null); + renderer.layout(); + renderer.createPDF(os); + + os.close(); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't generate decharge file", ex); + } catch (TemplateException ex) { + throw new CoserTechnicalException("Can't generate decharge file", ex); + } catch (DocumentException ex) { + throw new CoserTechnicalException("Can't generate decharge file", ex); + } finally { + IOUtils.closeQuietly(os); + } + } + + /** + * Generate pdf file filled with maps and charts. + * + * @param directory directory to generate pdf to + * @param zones zones ids + * @param pdfMaps pdf maps (can be {@code null}) + * @param pdfCharts pdf charts (can be {@code null}) + * @param zoneMap zoneMap (to get zone fullnames) + * @param locale locale to use for translations + */ + public void generateExtractPDF(File directory, + List<String> zones, + MultiKeyMap pdfMaps, + MultiKeyMap pdfCharts, + ZoneMap zoneMap, + Locale locale) { + + for (String zone : zones) { + Collection<File> toDelete = new ArrayList<File>(); + OutputStream os = null; + + try { + StringBuilder htmlContent = new StringBuilder(); + htmlContent.append("<html><head>"); + htmlContent.append("<title>").append(l(locale, "coser.business.extract.extracttitle")).append("</title>"); + htmlContent.append("<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />"); + htmlContent.append("</head><body>"); + + if (pdfMaps != null) { + for (Map.Entry<MultiKey, File> mapEntry : (Set<Map.Entry<MultiKey, File>>) pdfMaps.entrySet()) { + String zoneId = (String) mapEntry.getKey().getKey(0); + if (zoneId.equals(zone)) { + String speciesName = (String) mapEntry.getKey().getKey(1); + File file = mapEntry.getValue(); + + String zoneName = zoneMap.getZoneFullName(zoneId); + htmlContent.append("<div style='page-break-after: always'>"); + htmlContent.append("<p>").append(zoneName).append(" - ").append(speciesName).append("</p>"); + htmlContent.append("<img src='file://").append(file.getAbsolutePath()).append("' />"); + htmlContent.append("</div>"); + } + } + } + + if (pdfCharts != null) { + for (Map.Entry<MultiKey, Object[]> chartFileAndData : (Set<Map.Entry<MultiKey, Object[]>>) pdfCharts.entrySet()) { + String zoneId = (String) chartFileAndData.getKey().getKey(0); + if (zoneId.equals(zone)) { + File chartFile = (File) chartFileAndData.getValue()[0]; + String content = (String) chartFileAndData.getValue()[1]; + + htmlContent.append("<div style='page-break-after: always'>"); + htmlContent.append("<img src='file://"); + htmlContent.append(chartFile.getAbsolutePath()); + htmlContent.append("' />"); + htmlContent.append("<br />"); + htmlContent.append(l(locale, "coser.business.extract.extractdata")).append(" :"); + htmlContent.append("<pre>").append(content).append("</pre>"); + htmlContent.append("</div>"); + + // les graphiques ont été générés, a supprimer donc + // a ne surtout pas faire avec les cartes !!! + toDelete.add(chartFile); + } + } + } + + htmlContent.append("</body></html>"); + + // get content as w3c document + Document document = CoserUtils.parseDocument(htmlContent.toString()); + + // render template output as pdf + // remove accents and strange characters from zone display name + String zoneDisplay = zoneMap.getZoneFullName(zone); + zoneDisplay = StringUtils.stripAccents(zoneDisplay); + zoneDisplay = zoneDisplay.replaceAll("[^\\w- ]", "_"); + File pdfFile = new File(directory, zoneDisplay + ".pdf"); + os = new FileOutputStream(pdfFile); + + ITextRenderer renderer = new ITextRenderer(); + renderer.setDocument(document, null); + renderer.layout(); + renderer.createPDF(os); + + os.close(); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't generate log pdf", ex); + } catch (DocumentException ex) { + throw new CoserTechnicalException("Can't generate log pdf", ex); + } finally { + IOUtils.closeQuietly(os); + + + // delete file collection + for (File file : toDelete) { +// file.delete(); + FileUtils.deleteQuietly(file); + } + } + } + } } Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/RequestUnavailableForProducerException.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/RequestUnavailableForProducerException.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/RequestUnavailableForProducerException.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,49 @@ +package fr.ifremer.coser.result.repository; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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% + */ + +/** + * When a request ask a unavailable result of a producer. + * <p/> + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class RequestUnavailableForProducerException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public static RequestUnavailableForProducerException newException(String methodName, ResultProducer<?> producer) { + return new RequestUnavailableForProducerException(methodName, producer.getRepository().getId()); + } + + protected final String methodName; + + protected final String repositoryId; + + protected RequestUnavailableForProducerException(String methodName, String repositoryId) { + this.methodName = methodName; + this.repositoryId = repositoryId; + } +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/RequestUnavailableForProducerException.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/ResultProducer.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/ResultProducer.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/ResultProducer.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,50 @@ +package fr.ifremer.coser.result.repository; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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 fr.ifremer.coser.result.CoserRequest; +import fr.ifremer.coser.result.CoserResult; + +import java.util.Map; + +/** + * To execute a result. + * <p/> + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public interface ResultProducer<R extends CoserRequest> { + + ResultRepository getRepository(); + + Map<String, String> getAvailableZones(R request); + + Map<String, String> getAvailableSpecies(R request); + + Map<String, String> getAvailableIndicators(R request); + + CoserResult produceResult(R request); + +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/ResultProducer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/ResultRepository.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/ResultRepository.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/ResultRepository.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -24,7 +24,6 @@ import fr.ifremer.coser.result.CoserRequest; import fr.ifremer.coser.result.CoserResult; -import fr.ifremer.coser.result.request.IndicatorRequest; import java.util.Map; @@ -65,7 +64,7 @@ * @param request request * @return all available indicators for the given request. */ - Map<String, String> getAvailableIndicators(IndicatorRequest request); + Map<String, String> getAvailableIndicators(CoserRequest request); /** * @param request request to test Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/CommunityIndicatorResultProducer.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/CommunityIndicatorResultProducer.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/CommunityIndicatorResultProducer.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,392 @@ +package fr.ifremer.coser.result.repository.echobase; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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 com.google.common.base.Preconditions; +import fr.ifremer.coser.CoserTechnicalException; +import fr.ifremer.coser.bean.EchoBaseProject; +import fr.ifremer.coser.bean.ZoneMap; +import fr.ifremer.coser.result.FileResult; +import fr.ifremer.coser.result.Reports; +import fr.ifremer.coser.result.repository.ResultProducer; +import fr.ifremer.coser.result.request.CommunityIndicatorRequest; +import fr.ifremer.coser.storage.DataStorage; +import fr.ifremer.coser.storage.DataStorages; +import fr.ifremer.coser.storage.MemoryDataStorage; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.CategoryItemRenderer; +import org.jfree.chart.renderer.category.StatisticalLineAndShapeRenderer; +import org.jfree.data.statistics.DefaultStatisticalCategoryDataset; +import org.nuiton.util.FileUtil; +import org.nuiton.util.ZipUtil; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class CommunityIndicatorResultProducer implements ResultProducer<CommunityIndicatorRequest> { + + /** Logger. */ + private static final Log log = LogFactory.getLog(CommunityIndicatorResultProducer.class); + + protected final EchoBaseResultRepository repository; + + protected final Reports reports; + + protected final EchoBaseProject project; + + public CommunityIndicatorResultProducer(EchoBaseResultRepository repository) { + this.repository = repository; + this.project = repository.project; + this.reports = repository.reports; + } + + @Override + public EchoBaseResultRepository getRepository() { + return repository; + } + + @Override + public Map<String, String> getAvailableZones(CommunityIndicatorRequest request) { + Preconditions.checkNotNull(request.getFacade()); + + boolean match = repository.matchFacade(request); + + Map<String, String> result = null; + if (match) { + ZoneMap zonesMap = repository.getZonesMap(); + List<String> allowedZones = zonesMap.getZonesForFacade(request.getFacade()); + result = zonesMap.getSubZonesMap(project.getZoneName(), allowedZones); + } + return result; + } + + @Override + public Map<String, String> getAvailableSpecies(CommunityIndicatorRequest request) { + Preconditions.checkNotNull(request.getFacade()); + Preconditions.checkNotNull(request.getZone()); + Preconditions.checkNotNull(request.getIndicator()); + + boolean match = repository.matchFacade(request) && + repository.matchZone(request) && + repository.matchIndicator(request); + + Map<String, String> result = null; + + if (match) { + // get all speciesList for given facade + zone + indicator + Set<String> speciesList = repository.getCommunityIndicatorSpecies(request.getIndicator()); + result = repository.getSpeciesMap().getSpeciesSubMap(speciesList); + } + return result; + } + + @Override + public Map<String, String> getAvailableIndicators(CommunityIndicatorRequest request) { + Preconditions.checkNotNull(request.getFacade()); + Preconditions.checkNotNull(request.getZone()); + + Map<String, String> result = null; + boolean match = repository.matchFacade(request) && repository.matchZone(request); + if (match) { + + // get all indicators for given facade + zone + Set<String> indicatorList = repository.getCommunityIndicators(); + result = repository.getIndicatorsMap().getIndicatorsValues(indicatorList, request.getLocale()); + } + return result; + } + + @Override + public FileResult produceResult(CommunityIndicatorRequest r) { + + File file = null; + switch (r.getResultType()) { + case DATA: + file = getCommunityIndicatorDataFile(r.getLocale(), + r.getIndicator(), + r.getSpecies()); + break; + + case GRAPH: + file = getCommunityIndicatorGraphFile(r.getLocale(), + r.getZone(), + r.getIndicator(), + r.getSpecies()); + break; + } + FileResult result = new FileResult(repository.getId(), file); + return result; + } + + + protected File getCommunityIndicatorDataFile(Locale locale, + String indicator, + String speciesList) { + + try { + + File tempDir = FileUtil.createTempDirectory("coser-chart-population-indicator", "-tmp"); + + File baseDir = new File(tempDir, project.getSurveyName()); + FileUtils.forceMkdir(baseDir); + + // ajout du fichier csv avec les indicateurs + DataStorage dataStorage = new MemoryDataStorage(); + + Iterator<String[]> iterator = repository.loadCommunityIndicatorStorage(false); + + // add header + dataStorage.add(iterator.next()); + + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + if (repository.matchCommunityIndicatorAndSpeciesList(tuple, indicator, speciesList)) { + dataStorage.add(tuple); + } + } + File csvFile = DataStorages.save(dataStorage, "coser-chart-community-indicator", + ".csv" + ); + + File csvFileCopied = new File(baseDir, indicator + ".csv"); + FileUtils.copyFile(csvFile, csvFileCopied); + FileUtils.forceDelete(csvFile); + + //TODO See what to generate here (we don't have any selection in echobase results). +// // ajout du fichier d'information sur les espèces incluses dans +// // les calculs des indicateurs de communautés +// // load project (without data to get reftax data) +// Project project = path.getProject(); +// Selection selection = path.getSelection(); +// File metaFile = webService.generateMetaFilePDF(project, +// selection, +// resultDirectory, +// rSufiResult, +// indicator, +// locale); +// File metaFileCopied = new File(baseDir, "Information.pdf"); +// FileUtils.copyFile(metaFile, metaFileCopied); + + // make zip + File result = File.createTempFile("coser-chart-community-indicator", ".zip"); + result.deleteOnExit(); + ZipUtil.compress(result, baseDir); + + // clean directory + FileUtils.deleteDirectory(tempDir); + return result; + } catch (Exception e) { + throw new CoserTechnicalException("Can't create zip file", e); + } + } + + protected File getCommunityIndicatorGraphFile(Locale locale, + String zone, + String indicator, + String speciesList) { + + // indicator list to take care + // pour avoir une valeur non nulle si list est null + // on prend dans ce cas la premiere valeur trouvée + String localList = speciesList; + + if (log.isDebugEnabled()) { + log.debug("Searching list for indicator : " + indicator); + } + + int multiplicator = 1; + int minYear = Integer.MAX_VALUE; + int maxYear = Integer.MIN_VALUE; + boolean indicatorFound = false; + Map<Integer, Double[]> graphData = new HashMap<Integer, Double[]>(); + Iterator<String[]> iterator = repository.loadCommunityIndicatorStorage(true); + while (iterator.hasNext()) { + // Campagne Indicateur Liste Strate Annee Estimation EcartType CV + String[] tuple = iterator.next(); + String indicatorList = tuple[2]; + + if (repository.matchIndicatorIndicator(tuple, indicator)) { + indicatorFound = true; + + // si pas de list selectionnée, on prend la premiere + if (StringUtils.isBlank(localList)) { + localList = indicatorList; + } + + if (indicatorList.equals(localList)) { + Double estimation = Double.parseDouble(tuple[5]); + Double ecart = Double.parseDouble(tuple[6]); + int year = Integer.parseInt(tuple[4]); + + if (year < minYear) { + minYear = year; + } + if (year > maxYear) { + maxYear = year; + } + graphData.put(year, new Double[]{estimation, ecart}); + + // si les données sont énormes, on affiche les données + // / multiplicator et on le mentionne dans la légende + if (estimation > 1e9) { + multiplicator = 1000000; + } + if (estimation > 1e6 && multiplicator < 1000000) { + multiplicator = 1000; + } + } + } + } + + File result = null; + + // avec l'extraction des données, on peut demander a générer un graphique + // sur un indicateur qui n'est pas présent dans le projet courant, + // dans ce cas, on retourne null + if (indicatorFound) { + + String zoneDisplayName = repository.getZonesMap().getZoneFullName(zone); + String indicatorName = repository.getIndicatorsMap().getIndicatorValue(indicator, locale); + String unit = repository.getIndicatorsMap().getIndicatorUnit(indicator); + + // get graph title + String chartTitle = zoneDisplayName; + chartTitle += " - " + indicatorName; + + // ajout de la traduction de la liste d'indicateur + // les liste sont a1, T1, T2 ... + String listLetter = String.valueOf(localList.charAt(0)); + Iterator<String[]> typeIterator = repository.getSpeciesMap().iterator(true); + while (typeIterator.hasNext()) { + // "Types";"Commentaire";"NumSys min";"NumSys max";"Code" + String[] tuple = typeIterator.next(); + if (tuple[4].equals(listLetter)) { + /// gestion du groupe "Tous" + // cas special, c'est la seule valeur du fichier + // code type espece qui a besoin d'une traduction + if (tuple[4].equalsIgnoreCase("T")) { + if ("fr".equals(locale.getLanguage())) { + chartTitle += " - " + "Tous Liste " + localList.charAt(1); + } else if ("es".equals(locale.getLanguage())) { + chartTitle += " - " + "Todo Lista " + localList.charAt(1); + } else { + chartTitle += " - " + "All List " + localList.charAt(1); + } + } else { + // ajout de la traduction du nom de liste plus le numéro + if ("fr".equals(locale.getLanguage())) { + chartTitle += " - " + tuple[0] + " Liste " + localList.charAt(1); + } else if ("es".equals(locale.getLanguage())) { + chartTitle += " - " + tuple[0] + " Lista " + localList.charAt(1); + } else { + chartTitle += " - " + tuple[0] + " List " + localList.charAt(1); + } + } + break; + } + } + + // generate dataset with sorted data + DefaultStatisticalCategoryDataset statisticalDataset = new DefaultStatisticalCategoryDataset(); + for (int indexYear = minYear; indexYear <= maxYear; ++indexYear) { + Double[] entry = graphData.get(indexYear); + if (entry != null) { + Double estimation = entry[0] / multiplicator; + Double ecart = entry[1] / multiplicator; + statisticalDataset.add(estimation, ecart, "Serie1", (Comparable) indexYear); + } else { + statisticalDataset.add(null, null, "Serie1", indexYear); + } + } + + // configure chart + //CategoryAxis categoryAxis = new CategoryAxis(t("coser.business.common.year")); + String yearAxis = reports.getYearChartTitle(locale); + + CategoryAxis categoryAxis = new CategoryAxis(yearAxis); + categoryAxis.setCategoryMargin(0); + categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); + // label horizontaux + String legendY = indicatorName; + if (multiplicator != 1) { + // affiche par exemple : cm * 1000 + legendY += " (" + unit + "*" + multiplicator + ")"; + } else if (StringUtils.isNotEmpty(unit)) { + legendY += " (" + unit + ")"; + } + ValueAxis valueAxis = new NumberAxis(legendY); + valueAxis.setUpperMargin(0.1); + + CategoryItemRenderer renderer = new StatisticalLineAndShapeRenderer(false, true); + + // n'affiche pas les nombre sur le graphique + //StandardCategoryItemLabelGenerator itemLabelGenerator = new StandardCategoryItemLabelGenerator(); + //renderer.setBaseItemLabelGenerator(itemLabelGenerator); + //renderer.setBaseItemLabelsVisible(true); + + CategoryPlot plot = new CategoryPlot(statisticalDataset, categoryAxis, valueAxis, renderer); + plot.setOrientation(PlotOrientation.VERTICAL); + JFreeChart chart = new JFreeChart(chartTitle, + JFreeChart.DEFAULT_TITLE_FONT, plot, true); + + // remove series legend + chart.removeLegend(); + // white background + chart.setBackgroundPaint(Color.WHITE); + + try { + result = File.createTempFile("coser-chart-community-indicator-", ".png"); + result.deleteOnExit(); + ChartUtilities.saveChartAsPNG(result, chart, 800, 400); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't save chart", ex); + } + } + + return result; + } +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/CommunityIndicatorResultProducer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/EchoBaseResultRepository.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/EchoBaseResultRepository.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/EchoBaseResultRepository.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -28,50 +28,32 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import fr.ifremer.coser.CoserBusinessConfig; -import fr.ifremer.coser.CoserTechnicalException; import fr.ifremer.coser.bean.EchoBaseProject; import fr.ifremer.coser.bean.IndicatorMap; +import fr.ifremer.coser.bean.SpeciesMap; import fr.ifremer.coser.bean.ZoneMap; import fr.ifremer.coser.result.CoserRequest; import fr.ifremer.coser.result.CoserResult; -import fr.ifremer.coser.result.FileResult; import fr.ifremer.coser.result.Reports; +import fr.ifremer.coser.result.repository.ResultProducer; import fr.ifremer.coser.result.repository.ResultRepository; import fr.ifremer.coser.result.request.CommunityIndicatorRequest; -import fr.ifremer.coser.result.request.IndicatorRequest; +import fr.ifremer.coser.result.request.CoserRequestFacadeAware; +import fr.ifremer.coser.result.request.CoserRequestZoneAware; +import fr.ifremer.coser.result.request.ExtractRequest; import fr.ifremer.coser.result.request.MapRequest; import fr.ifremer.coser.result.request.PopulationIndicatorRequest; import fr.ifremer.coser.result.request.RawDataRequest; import fr.ifremer.coser.storage.DataStorage; import fr.ifremer.coser.storage.DataStorages; -import fr.ifremer.coser.storage.MemoryDataStorage; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.StringUtils; +import fr.ifremer.coser.util.DataType; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.jfree.chart.ChartUtilities; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.CategoryAxis; -import org.jfree.chart.axis.CategoryLabelPositions; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.plot.CategoryPlot; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.renderer.category.CategoryItemRenderer; -import org.jfree.chart.renderer.category.StatisticalLineAndShapeRenderer; -import org.jfree.data.statistics.DefaultStatisticalCategoryDataset; -import org.nuiton.util.FileUtil; -import org.nuiton.util.ZipUtil; -import java.awt.Color; import java.io.File; import java.io.FilenameFilter; -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; @@ -124,7 +106,7 @@ /** * Cache of species definition. */ - protected Map<String, String> speciesMap; + protected SpeciesMap speciesMap; /** * Cache of indicator definition. @@ -141,19 +123,36 @@ */ protected DataStorage speciesDefinition; + /** + * Report helper. + */ + protected final Reports reports; + + protected final Map<Class<?>, ResultProducer<?>> resultProducers; + public EchoBaseResultRepository(CoserBusinessConfig config, EchoBaseProject project) { Preconditions.checkNotNull(config); Preconditions.checkNotNull(project); this.config = config; this.project = project; this.mapsDirectory = project.getMapsDirectory(); - if (log.isInfoEnabled()) { - log.info("New result repository: " + getId()); - } + this.reports = new Reports(); + String surveyName = project.getSurveyName(); this.mapFileToSpeciesCode = EchoBaseProject.newMapFileToSpeciesCode(surveyName); this.speciesCodeToMapFile = EchoBaseProject.newSpeciesCodeToMapFileName(surveyName); this.mapSpeciesFilenameFilter = EchoBaseProject.newMapSpeciesFilenameFilter(surveyName); + + this.resultProducers = Maps.newHashMap(); + this.resultProducers.put(MapRequest.class, new MapResultProducer(this)); + this.resultProducers.put(CommunityIndicatorRequest.class, new CommunityIndicatorResultProducer(this)); + this.resultProducers.put(PopulationIndicatorRequest.class, new PopulationIndicatorResultProducer(this)); + this.resultProducers.put(RawDataRequest.class, new RawDataResultProducer(this)); + this.resultProducers.put(ExtractRequest.class, new ExtractResultProducer(this)); + + if (log.isInfoEnabled()) { + log.info("New result repository: " + getId()); + } } // --------------------------------------------------------------------- // @@ -168,115 +167,30 @@ @Override public Map<String, String> getAvailableZones(CoserRequest request) { - List<String> allowedZones = null; + ResultProducer resultProducer = getProducer(request.getClass()); + Preconditions.checkNotNull(resultProducer); - if (request instanceof MapRequest) { - MapRequest r = (MapRequest) request; - - boolean match = matchFacade(r); - if (match) { - allowedZones = getZonesMap().getZonesForFacade(r.getFacade()); - } - } else if (request instanceof PopulationIndicatorRequest) { - PopulationIndicatorRequest r = (PopulationIndicatorRequest) request; - - boolean match = matchFacade(r); - if (match) { - allowedZones = getZonesMap().getZonesForFacade(r.getFacade()); - } - } else if (request instanceof CommunityIndicatorRequest) { - CommunityIndicatorRequest r = (CommunityIndicatorRequest) request; - - boolean match = matchFacade(r); - if (match) { - allowedZones = getZonesMap().getZonesForFacade(r.getFacade()); - } - } - - Map<String, String> result = Maps.newHashMap(); - - if (allowedZones != null) { - - String zoneId = project.getZoneName(); - if (allowedZones.contains(zoneId)) { - String zoneFullName = getZonesMap().getZoneFullNameWithNoFacade(zoneId); - result.put(zoneId, zoneFullName); - } - } - + Map<String, String> result = resultProducer.getAvailableZones(request); return result; } @Override public Map<String, String> getAvailableSpecies(CoserRequest request) { - Set<String> speciesList = null; + ResultProducer resultProducer = getProducer(request.getClass()); + Preconditions.checkNotNull(resultProducer); - if (request instanceof MapRequest) { - MapRequest r = (MapRequest) request; - - boolean match = matchFacade(r) && matchZone(r); - if (match) { - // get all map species for given facade + zone - speciesList = getMapSpecies(); - } - } else if (request instanceof PopulationIndicatorRequest) { - PopulationIndicatorRequest r = (PopulationIndicatorRequest) request; - - boolean match = matchFacade(r) && matchZone(r); - - if (match) { - // get all population indicator species for given facade + zone - speciesList = getPopulationIndicatorSpecies(); - } - } else if (request instanceof CommunityIndicatorRequest) { - CommunityIndicatorRequest r = (CommunityIndicatorRequest) request; - - Preconditions.checkNotNull(r.getIndicator()); - - boolean match = matchFacade(r) && - matchZone(r) && - matchIndicator(r); - - if (match) { - // get all speciesList for given facade + zone + indicator - speciesList = getCommunityIndicatorSpecies(r.getIndicator()); - } - } - - Map<String, String> result = getSpeciesSubMap(speciesList); + Map<String, String> result = resultProducer.getAvailableSpecies(request); return result; } @Override - public Map<String, String> getAvailableIndicators(IndicatorRequest request) { + public Map<String, String> getAvailableIndicators(CoserRequest request) { - Set<String> indicatorList = null; + ResultProducer resultProducer = getProducer(request.getClass()); + Preconditions.checkNotNull(resultProducer); - if (request instanceof PopulationIndicatorRequest) { - PopulationIndicatorRequest r = (PopulationIndicatorRequest) request; - - Preconditions.checkNotNull(r.getSpecies()); - - boolean match = matchFacade(request) && matchZone(request) && matchSpecies(r); - - if (match) { - - // get all indicators for given facade + zone + species - indicatorList = getPopulationIndicators(r.getSpecies()); - } - - } else if (request instanceof CommunityIndicatorRequest) { - - boolean match = matchFacade(request) && matchZone(request); - if (match) { - - // get all indicators for given facade + zone - indicatorList = getCommunityIndicators(); - } - } - - Map<String, String> result = getIndicatorsMap().getIndicatorsValues(indicatorList, request.getLocale()); + Map<String, String> result = resultProducer.getAvailableIndicators(request); return result; } @@ -317,6 +231,15 @@ result = matchFacade(r) && matchZone(r) && matchSpeciesAndIndicator(r); + } else if (request instanceof ExtractRequest) { + + // must match extract type + zone + (species + indicator) + ExtractRequest r = (ExtractRequest) request; + + result = matchExtractTypeSet(r) && + matchZoneList(r) && + (matchPopulationIndicatorListAndSpeciesList(r) || + matchCommunityIndicatorListAndSpeciesList(r)); } return result; } @@ -327,80 +250,33 @@ Preconditions.checkArgument(request.isFilled()); Preconditions.checkArgument(acceptResult(request)); - CoserResult result = null; + ResultProducer resultProducer = getProducer(request.getClass()); + Preconditions.checkNotNull(resultProducer); - if (request instanceof MapRequest) { - MapRequest r = (MapRequest) request; - - String species = r.getSpecies(); - - File mapFile = getMapSpeciesFile(species); - result = new FileResult(getId(), mapFile); - - } else if (request instanceof RawDataRequest) { - - // No such result for echobase at the moment - if (log.isDebugEnabled()) { - log.debug("No result for RawDataRequest"); - } - - } else if (request instanceof CommunityIndicatorRequest) { - CommunityIndicatorRequest r = (CommunityIndicatorRequest) request; - - File file = null; - switch (r.getResultType()) { - case DATA: - file = getCommunityIndicatorDataFile(r.getIndicator(), - r.getSpecies()); - break; - - case GRAPH: - file = getCommunityIndicatorGraphFile(r.getLocale(), - r.getZone(), - r.getIndicator(), - r.getSpecies()); - break; - } - if (file != null) { - result = new FileResult(getId(), file); - } - - } else if (request instanceof PopulationIndicatorRequest) { - PopulationIndicatorRequest r = (PopulationIndicatorRequest) request; - - File file = null; - switch (r.getResultType()) { - case DATA: - file = getPopulationIndicatorDataFile(r.getSpecies(), - r.getIndicator()); - break; - - case GRAPH: - file = getPopulationIndicatorGraphFile(r.getLocale(), - r.getZone(), - r.getSpecies(), - r.getIndicator()); - break; - } - if (file != null) { - result = new FileResult(getId(), file); - } - } + CoserResult result = resultProducer.produceResult(request); return result; } + protected <R extends CoserRequest> ResultProducer<R> getProducer(Class<R> requestType) { + return (ResultProducer<R>) resultProducers.get(requestType); + } + // --------------------------------------------------------------------- // - // --- MapRequest matchers --------------------------------------------- // + // --- Common matchers ------------------------------------------------- // // --------------------------------------------------------------------- // - protected boolean matchFacade(MapRequest request) { + protected boolean matchFacade(CoserRequestFacadeAware request) { return project.getFacadeName().equals(request.getFacade()); } - protected boolean matchZone(MapRequest request) { + protected boolean matchZone(CoserRequestZoneAware request) { return project.getZoneName().equals(request.getZone()); } + // --------------------------------------------------------------------- // + // --- MapRequest matchers --------------------------------------------- // + // --------------------------------------------------------------------- // + protected boolean matchSpecies(MapRequest request) { String species = request.getSpecies(); File file = getMapSpeciesFile(species); @@ -411,26 +287,33 @@ // --- RawDataRequest matchers ----------------------------------------- // // --------------------------------------------------------------------- // - protected boolean matchFacade(RawDataRequest request) { - return project.getFacadeName().equals(request.getFacade()); - } + // None - protected boolean matchZone(RawDataRequest request) { - return project.getZoneName().equals(request.getZone()); - } - // --------------------------------------------------------------------- // // --- IndicatorRequest matchers --------------------------------------- // // --------------------------------------------------------------------- // - protected boolean matchFacade(IndicatorRequest request) { - return project.getFacadeName().equals(request.getFacade()); + protected boolean matchIndicatorSpecies(String[] tuple, String species) { + String speciesCode = tuple[3]; + boolean result = species.equals(speciesCode); + return result; } - protected boolean matchZone(IndicatorRequest request) { - return project.getZoneName().equals(request.getZone()); + protected boolean matchIndicatorIndicator(String[] tuple, String indicator) { + String indicatorCode = tuple[1]; + boolean result = indicator.equals(indicatorCode); + return result; } + protected boolean matchIndicatorSpeciesAndIndicator(String[] tuple, + String species, + String indicator) { + String speciesCode = tuple[3]; + String indicatorCode = tuple[1]; + boolean result = species.equals(speciesCode) && indicator.equals(indicatorCode); + return result; + } + // --------------------------------------------------------------------- // // --- PopulationIndicatorRequest matchers ----------------------------- // // --------------------------------------------------------------------- // @@ -445,7 +328,7 @@ Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); while (iterator.hasNext()) { String[] tuple = iterator.next(); - if (matchPopulationSpecies(tuple, species)) { + if (matchIndicatorSpecies(tuple, species)) { result = true; break; } @@ -465,7 +348,7 @@ Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); while (iterator.hasNext()) { String[] tuple = iterator.next(); - if (matchPopulationSpeciesAndIndicator(tuple, species, indicator)) { + if (matchIndicatorSpeciesAndIndicator(tuple, species, indicator)) { result = true; break; } @@ -473,19 +356,6 @@ return result; } - protected boolean matchPopulationSpecies(String[] tuple, String species) { - String speciesCode = tuple[3]; - boolean result = species.equals(speciesCode); - return result; - } - - protected boolean matchPopulationSpeciesAndIndicator(String[] tuple, String species, String indicator) { - String speciesCode = tuple[3]; - String indicatorCode = tuple[1]; - boolean result = species.equals(speciesCode) && indicator.equals(indicatorCode); - return result; - } - // --------------------------------------------------------------------- // // --- CommunityIndicatorRequest matchers ------------------------------ // // --------------------------------------------------------------------- // @@ -500,7 +370,7 @@ Iterator<String[]> iterator = loadCommunityIndicatorStorage(true); while (iterator.hasNext()) { String[] tuple = iterator.next(); - if (matchCommunityIndicator(tuple, indicator)) { + if (matchIndicatorIndicator(tuple, indicator)) { result = true; break; } @@ -528,401 +398,125 @@ return result; } - protected boolean matchCommunityIndicator(String[] tuple, String indicator) { + protected boolean matchCommunityIndicatorAndSpeciesList(String[] tuple, + String indicator, + String speciesList) { String indicatorCode = tuple[1]; - boolean result = indicator.equals(indicatorCode); - return result; - } - - protected boolean matchCommunityIndicatorAndSpeciesList(String[] tuple, String indicator, String speciesList) { - String indicatorCode = tuple[1]; String speciesListCode = tuple[2]; boolean result = indicator.equals(indicatorCode) && speciesList.equals(speciesListCode); return result; } // --------------------------------------------------------------------- // - // --- Get Map result -------------------------------------------------- // + // --- ExtractRequest matchers ----------------------------------------- // // --------------------------------------------------------------------- // - protected File getMapSpeciesFile(String species) { - String fileName = speciesCodeToMapFile.apply(species); - File file = fileName == null ? null : new File(mapsDirectory, fileName); - return file; + protected boolean matchExtractTypeSet(ExtractRequest request) { + //TODO Should deal also with raw-data type + return !request.getExtractTypeList().contains(DataType.SOURCE); } - // --------------------------------------------------------------------- // - // --- Get Raw Data result --------------------------------------------- // - // --------------------------------------------------------------------- // - - // None for the moment - - // --------------------------------------------------------------------- // - // --- Get Community indicator result ---------------------------------- // - // --------------------------------------------------------------------- // - - protected File getCommunityIndicatorDataFile(String indicator, String speciesList) { - - try { - - File tempDir = FileUtil.createTempDirectory("coser-chart-population-indicator", "-tmp"); - - File baseDir = new File(tempDir, project.getSurveyName()); - FileUtils.forceMkdir(baseDir); - - // ajout du fichier csv avec les indicateurs - DataStorage dataStorage = new MemoryDataStorage(); - - Iterator<String[]> iterator = loadCommunityIndicatorStorage(false); - - // add header - dataStorage.add(iterator.next()); - - while (iterator.hasNext()) { - String[] tuple = iterator.next(); - if (matchCommunityIndicatorAndSpeciesList(tuple, indicator, speciesList)) { - dataStorage.add(tuple); - } - } - File csvFile = DataStorages.save("coser-chart-community-indicator", - ".csv", - dataStorage); - - File csvFileCopied = new File(baseDir, indicator + ".csv"); - FileUtils.copyFile(csvFile, csvFileCopied); - FileUtils.forceDelete(csvFile); - - //TODO See what to generate here (we don't have any selection in echobase results). -// // ajout du fichier d'information sur les espèces incluses dans -// // les calculs des indicateurs de communautés -// // load project (without data to get reftax data) -// Project project = path.getProject(); -// Selection selection = path.getSelection(); -// File metaFile = webService.generateMetaFilePDF(project, -// selection, -// resultDirectory, -// rSufiResult, -// indicator, -// locale); -// File metaFileCopied = new File(baseDir, "Information.pdf"); -// FileUtils.copyFile(metaFile, metaFileCopied); - - // make zip - File result = File.createTempFile("coser-chart-community-indicator", ".zip"); - result.deleteOnExit(); - ZipUtil.compress(result, baseDir); - - // clean directory - FileUtils.deleteDirectory(tempDir); - return result; - } catch (IOException e) { - throw new CoserTechnicalException("Can't create zip file", e); - } + protected boolean matchZoneList(ExtractRequest request) { + return request.getZoneList().contains(project.getZoneName()); } - protected File getCommunityIndicatorGraphFile(Locale locale, String zone, - String indicator, - String speciesList) { + protected boolean matchCommunityIndicatorList(ExtractRequest request) { + Preconditions.checkNotNull(request.getCommunityIndicatorList()); - // indicator list to take care - // pour avoir une valeur non nulle si list est null - // on prend dans ce cas la premiere valeur trouvée - String localList = speciesList; + List<String> indicatorList = request.getCommunityIndicatorList(); - if (log.isDebugEnabled()) { - log.debug("Searching list for indicator : " + indicator); - } + boolean result = false; - int multiplicator = 1; - int minYear = Integer.MAX_VALUE; - int maxYear = Integer.MIN_VALUE; - boolean indicatorFound = false; - Map<Integer, Double[]> graphData = new HashMap<Integer, Double[]>(); Iterator<String[]> iterator = loadCommunityIndicatorStorage(true); while (iterator.hasNext()) { - // Campagne Indicateur Liste Strate Annee Estimation EcartType CV String[] tuple = iterator.next(); - String indicatorList = tuple[2]; - - if (matchCommunityIndicator(tuple, indicator)) { - indicatorFound = true; - - // si pas de list selectionnée, on prend la premiere - if (StringUtils.isBlank(localList)) { - localList = indicatorList; - } - - if (indicatorList.equals(localList)) { - Double estimation = Double.parseDouble(tuple[5]); - Double ecart = Double.parseDouble(tuple[6]); - int year = Integer.parseInt(tuple[4]); - - if (year < minYear) { - minYear = year; - } - if (year > maxYear) { - maxYear = year; - } - graphData.put(year, new Double[]{estimation, ecart}); - - // si les données sont énormes, on affiche les données - // / multiplicator et on le mentionne dans la légende - if (estimation > 1e9) { - multiplicator = 1000000; - } - if (estimation > 1e6 && multiplicator < 1000000) { - multiplicator = 1000; - } - } + if (matchIndicatorList(tuple, indicatorList)) { + result = true; + break; } } + return result; + } - File result = null; + protected boolean matchPopulationIndicatorList(ExtractRequest request) { + Preconditions.checkNotNull(request.getPopulationIndicatorList()); - // avec l'extraction des données, on peut demander a générer un graphique - // sur un indicateur qui n'est pas présent dans le projet courant, - // dans ce cas, on retourne null - if (indicatorFound) { + List<String> indicatorList = request.getPopulationIndicatorList(); - String zoneDisplayName = getZonesMap().getZoneFullName(zone); - String indicatorName = getIndicatorsMap().getIndicatorValue(indicator, locale); - String unit = getIndicatorsMap().getIndicatorUnit(indicator); + boolean result = false; - // get graph title - String chartTitle = zoneDisplayName; - chartTitle += " - " + indicatorName; - - // ajout de la traduction de la liste d'indicateur - // les liste sont a1, T1, T2 ... - String listLetter = String.valueOf(localList.charAt(0)); - Iterator<String[]> typeIterator = loadSpeciesFileStorage(true); - while (typeIterator.hasNext()) { - // "Types";"Commentaire";"NumSys min";"NumSys max";"Code" - String[] tuple = typeIterator.next(); - if (tuple[4].equals(listLetter)) { - /// gestion du groupe "Tous" - // cas special, c'est la seule valeur du fichier - // code type espece qui a besoin d'une traduction - if (tuple[4].equalsIgnoreCase("T")) { - if ("fr".equals(locale.getLanguage())) { - chartTitle += " - " + "Tous Liste " + localList.charAt(1); - } else if ("es".equals(locale.getLanguage())) { - chartTitle += " - " + "Todo Lista " + localList.charAt(1); - } else { - chartTitle += " - " + "All List " + localList.charAt(1); - } - } else { - // ajout de la traduction du nom de liste plus le numéro - if ("fr".equals(locale.getLanguage())) { - chartTitle += " - " + tuple[0] + " Liste " + localList.charAt(1); - } else if ("es".equals(locale.getLanguage())) { - chartTitle += " - " + tuple[0] + " Lista " + localList.charAt(1); - } else { - chartTitle += " - " + tuple[0] + " List " + localList.charAt(1); - } - } - break; - } + Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + if (matchIndicatorList(tuple, indicatorList)) { + result = true; + break; } - - // generate dataset with sorted data - DefaultStatisticalCategoryDataset statisticalDataset = new DefaultStatisticalCategoryDataset(); - for (int indexYear = minYear; indexYear <= maxYear; ++indexYear) { - Double[] entry = graphData.get(indexYear); - if (entry != null) { - Double estimation = entry[0] / multiplicator; - Double ecart = entry[1] / multiplicator; - statisticalDataset.add(estimation, ecart, "Serie1", (Comparable) indexYear); - } else { - statisticalDataset.add(null, null, "Serie1", indexYear); - } - } - - // configure chart - //CategoryAxis categoryAxis = new CategoryAxis(t("coser.business.common.year")); - String yearAxis = Reports.getYearChartTitle(locale); - - CategoryAxis categoryAxis = new CategoryAxis(yearAxis); - categoryAxis.setCategoryMargin(0); - categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); - // label horizontaux - String legendY = indicatorName; - if (multiplicator != 1) { - // affiche par exemple : cm * 1000 - legendY += " (" + unit + "*" + multiplicator + ")"; - } else if (StringUtils.isNotEmpty(unit)) { - legendY += " (" + unit + ")"; - } - ValueAxis valueAxis = new NumberAxis(legendY); - valueAxis.setUpperMargin(0.1); - - CategoryItemRenderer renderer = new StatisticalLineAndShapeRenderer(false, true); - - // n'affiche pas les nombre sur le graphique - //StandardCategoryItemLabelGenerator itemLabelGenerator = new StandardCategoryItemLabelGenerator(); - //renderer.setBaseItemLabelGenerator(itemLabelGenerator); - //renderer.setBaseItemLabelsVisible(true); - - CategoryPlot plot = new CategoryPlot(statisticalDataset, categoryAxis, valueAxis, renderer); - plot.setOrientation(PlotOrientation.VERTICAL); - JFreeChart chart = new JFreeChart(chartTitle, - JFreeChart.DEFAULT_TITLE_FONT, plot, true); - - // remove series legend - chart.removeLegend(); - // white background - chart.setBackgroundPaint(Color.WHITE); - - try { - result = File.createTempFile("coser-chart-community-indicator-", ".png"); - result.deleteOnExit(); - ChartUtilities.saveChartAsPNG(result, chart, 800, 400); - } catch (IOException ex) { - throw new CoserTechnicalException("Can't save chart", ex); - } } - return result; } - // --------------------------------------------------------------------- // - // --- Get Population indicator result --------------------------------- // - // --------------------------------------------------------------------- // + protected boolean matchPopulationIndicatorListAndSpeciesList(ExtractRequest request) { + Preconditions.checkNotNull(request.getPopulationIndicatorList()); - protected File getPopulationIndicatorDataFile(String species, String indicator) { + List<String> indicatorList = request.getPopulationIndicatorList(); + List<String> speciesList = request.getSpeciesList(); - DataStorage dataStorage = new MemoryDataStorage(); + boolean result = false; - Iterator<String[]> iterator = loadPopulationIndicatorStorage(false); - - // add header - dataStorage.add(iterator.next()); - + Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); while (iterator.hasNext()) { String[] tuple = iterator.next(); - if (matchPopulationSpeciesAndIndicator(tuple, species, indicator)) { - dataStorage.add(tuple); + if (matchIndicatorListAndSpeciesList(tuple, indicatorList, speciesList)) { + result = true; + break; } } - File result = DataStorages.save("coser-chart-population-indicator", - ".csv", - dataStorage); return result; } - protected File getPopulationIndicatorGraphFile(Locale locale, String zone, String species, String indicator) { + protected boolean matchCommunityIndicatorListAndSpeciesList(ExtractRequest request) { + Preconditions.checkNotNull(request.getCommunityIndicatorList()); + List<String> indicatorList = request.getCommunityIndicatorList(); + List<String> speciesList = request.getSpeciesList(); - int multiplicator = 1; - int minYear = Integer.MAX_VALUE; - int maxYear = Integer.MIN_VALUE; - boolean indicatorFound = false; - Map<Integer, Double[]> graphData = new HashMap<Integer, Double[]>(); - Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); + boolean result = false; + + Iterator<String[]> iterator = loadCommunityIndicatorStorage(true); while (iterator.hasNext()) { String[] tuple = iterator.next(); - - if (matchPopulationSpeciesAndIndicator(tuple, species, indicator)) { - indicatorFound = true; - - // XXX echatellier, maybe take care of list here ? - - Double estimation = Double.parseDouble(tuple[6]); - Double ecart = Double.parseDouble(tuple[7]); - int year = Integer.parseInt(tuple[5]); - - if (year < minYear) { - minYear = year; - } - if (year > maxYear) { - maxYear = year; - } - graphData.put(year, new Double[]{estimation, ecart}); - - // si les données sont énormes, on affiche les données - // / multiplicator et on le mentionne dans la légende - if (estimation > 1e9) { - multiplicator = 1000000; - } - if (estimation > 1e6 && multiplicator < 1000000) { - multiplicator = 1000; - } + if (matchIndicatorListAndSpeciesList(tuple, indicatorList, speciesList)) { + result = true; + break; } } + return result; + } - File result = null; + protected boolean matchIndicatorList(String[] tuple, List<String> indicatorList) { + String indicatorCode = tuple[1]; + boolean result = indicatorList.contains(indicatorCode); + return result; + } - // avec l'extraction des données, on peut demander a générer un graphique - // sur un indicateur qui n'est pas présent dans le projet courant, - // dans ce cas, on retourne null - if (indicatorFound) { + protected boolean matchIndicatorListAndSpeciesList(String[] tuple, + List<String> indicatorList, + List<String> speciesList) { + String indicatorCode = tuple[1]; + String speciesCode = tuple[3]; + boolean result = indicatorList.contains(indicatorCode) && speciesList.contains(speciesCode); + return result; + } - String zoneDisplayName = getZonesMap().getZoneFullName(zone); - String indicatorName = getIndicatorsMap().getIndicatorValue(indicator, locale); - String unit = getIndicatorsMap().getIndicatorUnit(indicator); + // --------------------------------------------------------------------- // + // --- Get Map result -------------------------------------------------- // + // --------------------------------------------------------------------- // - // get graph title - String title = zoneDisplayName; - title += " - " + indicatorName; - title += " - " + Reports.getReportDisplayName(loadSpeciesFileStorage(true), species); - - // generate dataset with sorted data - DefaultStatisticalCategoryDataset statisticalDataset = new DefaultStatisticalCategoryDataset(); - for (int indexYear = minYear; indexYear <= maxYear; ++indexYear) { - Double[] entry = graphData.get(indexYear); - if (entry != null) { - Double estimation = entry[0] / multiplicator; - Double ecart = entry[1] / multiplicator; - statisticalDataset.add(estimation, ecart, "Serie1", (Comparable) indexYear); - } else { - statisticalDataset.add(null, null, "Serie1", indexYear); - } - } - - // configure chart - //CategoryAxis categoryAxis = new CategoryAxis(t("coser.business.common.year")); - String yearAxis = Reports.getYearChartTitle(locale); - CategoryAxis categoryAxis = new CategoryAxis(yearAxis); - categoryAxis.setCategoryMargin(0); - categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); - // label horizontaux - String legendY = indicatorName; - if (multiplicator != 1) { - // affiche par exemple : cm * 1000 - legendY += " (" + unit + "*" + multiplicator + ")"; - } else if (StringUtils.isNotEmpty(unit)) { - legendY += " (" + unit + ")"; - } - ValueAxis valueAxis = new NumberAxis(legendY); - valueAxis.setUpperMargin(0.1); - - CategoryItemRenderer renderer = new StatisticalLineAndShapeRenderer(false, true); - - // n'affiche pas les nombre sur le graphique - //StandardCategoryItemLabelGenerator itemLabelGenerator = new StandardCategoryItemLabelGenerator(); - //renderer.setBaseItemLabelGenerator(itemLabelGenerator); - //renderer.setBaseItemLabelsVisible(true); - - CategoryPlot plot = new CategoryPlot(statisticalDataset, categoryAxis, valueAxis, renderer); - plot.setOrientation(PlotOrientation.VERTICAL); - JFreeChart chart = new JFreeChart(title, - JFreeChart.DEFAULT_TITLE_FONT, plot, true); - - // remove series legend - chart.removeLegend(); - // white background - chart.setBackgroundPaint(Color.WHITE); - - try { - result = File.createTempFile("coser-chart-population-indicator-", ".png"); - result.deleteOnExit(); - ChartUtilities.saveChartAsPNG(result, chart, 800, 400); - } catch (IOException ex) { - throw new CoserTechnicalException("Can't save chart", ex); - } - } - - return result; + protected File getMapSpeciesFile(String species) { + String fileName = speciesCodeToMapFile.apply(species); + File file = fileName == null ? null : new File(mapsDirectory, fileName); + return file; } // --------------------------------------------------------------------- // @@ -930,8 +524,8 @@ // --------------------------------------------------------------------- // protected Set<String> getMapSpecies() { - File[] files = project.getMapsDirectory().listFiles(mapSpeciesFilenameFilter); Set<String> result = Sets.newHashSet(); + File[] files = project.getMapsDirectory().listFiles(mapSpeciesFilenameFilter); if (files != null) { List<String> transform = Lists.transform(Lists.newArrayList(files), mapFileToSpeciesCode); result.addAll(transform); @@ -944,20 +538,31 @@ Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); while (iterator.hasNext()) { String[] tuple = iterator.next(); - String specyCode = tuple[3]; - result.add(specyCode); + String speciesCode = tuple[3]; + result.add(speciesCode); } return result; } + protected Set<String> getCommunityIndicatorSpecies() { + Iterator<String[]> iterator = loadCommunityIndicatorStorage(true); + Set<String> result = Sets.newHashSet(); + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + String speciesCode = tuple[2]; + result.add(speciesCode); + } + return result; + } + protected Set<String> getCommunityIndicatorSpecies(String indicator) { Iterator<String[]> iterator = loadCommunityIndicatorStorage(true); Set<String> result = Sets.newHashSet(); while (iterator.hasNext()) { String[] tuple = iterator.next(); - if (matchCommunityIndicator(tuple, indicator)) { - String specyCode = tuple[2]; - result.add(specyCode); + if (matchIndicatorIndicator(tuple, indicator)) { + String speciesCode = tuple[2]; + result.add(speciesCode); } } return result; @@ -978,12 +583,23 @@ return result; } + protected Set<String> getPopulationIndicators() { + Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); + Set<String> result = Sets.newHashSet(); + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + String indicatorCode = tuple[1]; + result.add(indicatorCode); + } + return result; + } + protected Set<String> getPopulationIndicators(String species) { Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); Set<String> result = Sets.newHashSet(); while (iterator.hasNext()) { String[] tuple = iterator.next(); - if (matchPopulationSpecies(tuple, species)) { + if (matchIndicatorSpecies(tuple, species)) { String indicatorCode = tuple[1]; result.add(indicatorCode); } @@ -992,45 +608,19 @@ } // --------------------------------------------------------------------- // - // --- Get species definition maps ------------------------------------- // + // --- Get definition maps --------------------------------------------- // // --------------------------------------------------------------------- // - protected Map<String, String> getSpeciesMap() { + protected SpeciesMap getSpeciesMap() { if (speciesMap == null) { - speciesMap = Maps.newTreeMap(); - // load species file - Iterator<String[]> iterator = loadSpeciesFileStorage(true); - while (iterator.hasNext()) { - String[] tuple = iterator.next(); - String speciesCode = tuple[3]; - String speciesLabel = tuple[4] + " " + tuple[5]; - speciesMap.put(speciesCode, speciesLabel); - } + File file = project.getSpeciesDefinitionFile(); + + speciesMap = new SpeciesMap(file); } return speciesMap; } - protected Map<String, String> getSpeciesSubMap(Collection<String> speciesList) { - - Map<String, String> result = Maps.newTreeMap(); - - if (speciesList != null) { - - Map<String, String> map = getSpeciesMap(); - for (String species : speciesList) { - String speciesLabel = map.get(species); - result.put(species, speciesLabel); - } - } - - return result; - } - - // --------------------------------------------------------------------- // - // --- Get indicator definition maps ----------------------------------- // - // --------------------------------------------------------------------- // - protected IndicatorMap getIndicatorsMap() { if (indicatorsMap == null) { indicatorsMap = new IndicatorMap(config.getWebIndicatorsFile()); @@ -1038,10 +628,6 @@ return indicatorsMap; } - // --------------------------------------------------------------------- // - // --- Get zone definition maps ---------------------------------------- // - // --------------------------------------------------------------------- // - public ZoneMap getZonesMap() { if (zonesMap == null) { zonesMap = new ZoneMap(config.getWebZonesFile()); @@ -1069,21 +655,4 @@ return iterator; } - - protected Iterator<String[]> loadSpeciesFileStorage(boolean skipFirstLine) { - // "C_Perm","NumSys","NivSys","C_VALIDE","L_VALIDE","AA_VALIDE","C_TxP\u00E8re","Taxa" - Iterator<String[]> iterator = getSpeciesDefinition().iterator(skipFirstLine); - return iterator; - } - - protected DataStorage getSpeciesDefinition() throws CoserTechnicalException { - if (speciesDefinition == null) { - File file = project.getSpeciesDefinitionFile(); - speciesDefinition = DataStorages.load(file); - } - - return speciesDefinition; - } - - } Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/ExtractResultProducer.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/ExtractResultProducer.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/ExtractResultProducer.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,685 @@ +package fr.ifremer.coser.result.repository.echobase; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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 com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import fr.ifremer.coser.CoserTechnicalException; +import fr.ifremer.coser.bean.EchoBaseProject; +import fr.ifremer.coser.bean.IndicatorMap; +import fr.ifremer.coser.bean.SpeciesMap; +import fr.ifremer.coser.bean.ZoneMap; +import fr.ifremer.coser.result.FileResult; +import fr.ifremer.coser.result.Reports; +import fr.ifremer.coser.result.repository.ResultProducer; +import fr.ifremer.coser.result.request.ExtractRequest; +import fr.ifremer.coser.storage.DataStorage; +import fr.ifremer.coser.storage.DataStorages; +import fr.ifremer.coser.storage.MemoryDataStorage; +import fr.ifremer.coser.util.DataType; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.collections4.keyvalue.MultiKey; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.CategoryItemRenderer; +import org.jfree.chart.renderer.category.StatisticalLineAndShapeRenderer; +import org.jfree.data.statistics.DefaultStatisticalCategoryDataset; +import org.nuiton.util.FileUtil; +import org.nuiton.util.ZipUtil; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class ExtractResultProducer implements ResultProducer<ExtractRequest> { + + /** Logger. */ + private static final Log log = LogFactory.getLog(ExtractResultProducer.class); + + protected final EchoBaseResultRepository repository; + + protected final Reports reports; + + protected final EchoBaseProject project; + + public ExtractResultProducer(EchoBaseResultRepository repository) { + this.repository = repository; + this.project = repository.project; + this.reports = repository.reports; + } + + @Override + public EchoBaseResultRepository getRepository() { + return repository; + } + + @Override + public Map<String, String> getAvailableZones(ExtractRequest request) { + + ZoneMap zonesMap = repository.getZonesMap(); + List<String> allowedZones = zonesMap.getZonesForFacade(null); + Map<String, String> result = zonesMap.getSubZonesMap(project.getZoneName(), allowedZones); + return result; + } + + @Override + public Map<String, String> getAvailableSpecies(ExtractRequest request) { + Preconditions.checkNotNull(request.getZoneList()); + + boolean match = repository.matchZoneList(request); + + Map<String, String> result = null; + if (match) { + Set<String> speciesList = Sets.newHashSet(); + + // get all species for population indicators + speciesList.addAll(repository.getPopulationIndicatorSpecies()); + // get all species for community indicators + speciesList.addAll(repository.getCommunityIndicatorSpecies()); + result = repository.getSpeciesMap().getSpeciesSubMap(speciesList); + } + return result; + } + + @Override + public Map<String, String> getAvailableIndicators(ExtractRequest request) { + Preconditions.checkNotNull(request.getZoneList()); + Preconditions.checkNotNull(request.getExtractTypeList()); + + Map<String, String> result = null; + + boolean match = repository.matchZoneList(request); + if (match) { + + Set<String> indicatorList = null; + + if (request.getExtractTypeList().contains(DataType.COMMUNITY)) { + + // get all community indicators for given zone + indicatorList = repository.getCommunityIndicators(); + } else if (request.getExtractTypeList().contains(DataType.POPULATION)) { + + // get all population indicators for given zone + indicatorList = repository.getPopulationIndicators(); + } + + if (indicatorList != null) { + result = repository.getIndicatorsMap().getIndicatorsValues(indicatorList, request.getLocale()); + } + } + return result; + } + + @Override + public FileResult produceResult(ExtractRequest r) { + + Locale locale = r.getLocale(); + List<String> zoneList = r.getZoneList(); + List<DataType> extractTypeList = r.getExtractTypeList(); + List<String> speciesList = r.getSpeciesList(); + List<String> communityIndicatorList = r.getCommunityIndicatorList(); + List<String> populationIndicatorList = r.getPopulationIndicatorList(); + + File resultZip = null; + File tempDir = null; + try { + tempDir = FileUtil.createTempDirectory("coser-extract-", "-tmp"); + + File subDir = new File(tempDir, "Indicateurs_Ifremer"); + FileUtils.forceMkdir(subDir); + + // les sources se retrouve dans le zip a cote du pdf + if (extractTypeList.contains(DataType.SOURCE)) { + if (log.isDebugEnabled()) { + log.debug("Extracting sources"); + } + File srcDir = new File(subDir, "sources"); + extractSource(srcDir); + } + + // les cartes doivent se retrouver dans le pdf + MultiKeyMap pdfMaps = null; + if (extractTypeList.contains(DataType.MAP)) { + if (log.isDebugEnabled()) { + log.debug("Extracting maps"); + } + String zone = project.getZoneName(); + SpeciesMap speciesMap = repository.getSpeciesMap(); + for (String species : speciesList) { + File mapFile = repository.getMapSpeciesFile(species); + pdfMaps.put(zone, speciesMap.getSpeciesName(species), mapFile); + } + } + + // les graphiques sont également dans le pdf + MultiKeyMap pdfCharts = null; + if (CollectionUtils.isNotEmpty(communityIndicatorList) || + CollectionUtils.isNotEmpty(populationIndicatorList)) { + if (log.isDebugEnabled()) { + log.debug("Extracting charts"); + } + pdfCharts = extractCharts(speciesList, + communityIndicatorList, + populationIndicatorList, + locale); + } + + // generate pdf if necessary + if (MapUtils.isNotEmpty(pdfMaps) || MapUtils.isNotEmpty(pdfCharts)) { + if (log.isDebugEnabled()) { + log.debug("Generated Extract PDF"); + } + reports.generateExtractPDF(subDir, + zoneList, + pdfMaps, + pdfCharts, + repository.getZonesMap(), + locale); + } + + // fichier de décharge en pdf + if (log.isDebugEnabled()) { + log.debug("Generated decharge PDF"); + } + String filename = reports.getDechargeFilename(locale); + File dechargePDF = new File(subDir, filename); + reports.generateDechargePDF(dechargePDF, locale, null, null); + + // make zip + if (log.isDebugEnabled()) { + log.debug("Make final archive"); + } + resultZip = File.createTempFile("coser-extract-", ".zip"); + resultZip.deleteOnExit(); + ZipUtil.compress(resultZip, subDir); + + // clean directory + FileUtils.deleteDirectory(tempDir); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't create zip file", ex); + } finally { + // clean directory + FileUtils.deleteQuietly(tempDir); + } + + FileResult result = new FileResult(repository.getId(), resultZip); + return result; + } + + /** + * Generate raw data after selection in a sub directory (named of the zone) of the given directory. + * + * @param directory where to generate file + */ + protected void extractSource(File directory) { + + //TODO + } + + /** + * Retourne les indicateurs calculés avec leurs traductions scientifique + * pour la zone et l'especes souhaitées. + * + * @param species especes (if {@code null} look for com indicators + * @param comIndicators comIndicator + * @param popIndicators popIndicators + * @param locale locale + * @return la liste des indicateurs (zone, speciesname, [graphfile, graphdata]) + */ + protected MultiKeyMap extractCharts(Collection<String> species, + Collection<String> comIndicators, + Collection<String> popIndicators, + Locale locale) { + + MultiKeyMap chartFileAndDatas = new MultiKeyMap(); + + String zone = project.getZoneName(); + String zoneDisplayName = repository.getZonesMap().getZoneFullName(zone); + + if (CollectionUtils.isNotEmpty(comIndicators)) { + Map<String, Pair<File, String>> chartFileAndDataCom = getRsufiResultComCharts(comIndicators, + zoneDisplayName, + repository.getIndicatorsMap(), + locale, + 650, + 430); + // put in multimap as zone,speciesname, data + for (Map.Entry<String, Pair<File, String>> entry : chartFileAndDataCom.entrySet()) { + chartFileAndDatas.put(zone, entry.getKey(), entry.getValue()); + } + } + + if (CollectionUtils.isNotEmpty(popIndicators)) { + Map<String, Pair<File, String>> chartFileAndDataPop = getRsufiResultPopCharts(species, + popIndicators, + zoneDisplayName, + repository.getIndicatorsMap(), + locale, + 650, + 430); + // put in multimap as zone,speciesname, data + for (Map.Entry<String, Pair<File, String>> entry : chartFileAndDataPop.entrySet()) { + chartFileAndDatas.put(zone, entry.getKey(), entry.getValue()); + } + } + + return chartFileAndDatas; + } + + /** + * Generate community graph for selected indicators. + * Used by web ui extraction. + * + * @param indicators indicators to extract + * @param zoneDisplayName zone full name + * @param indicatorMap indicator localized map + * @param locale locale + * @param width graph width + * @param height graph height + * @return maps of generated graph image (temp file) and data indexed by natural key (indicator - species) + */ + public Map<String, Pair<File, String>> getRsufiResultComCharts(Collection<String> indicators, + String zoneDisplayName, + IndicatorMap indicatorMap, + Locale locale, + int width, int height) { + + Map<String, Pair<File, String>> result = Maps.newHashMap(); + + int multiplicator = 1; + int minYear = Integer.MAX_VALUE; + int maxYear = Integer.MIN_VALUE; + + Map<String, Map<Integer, Double[]>> indicatorGraphData = new HashMap<String, Map<Integer, Double[]>>(); + Map<String, String> indicatorLists = new HashMap<String, String>(); + Map<String, DataStorage> indicatorStorages = new HashMap<String, DataStorage>(); + + // Campagne Indicateur Liste Strate Annee Estimation EcartType CV + Iterator<String[]> estComIndIterator = repository.loadCommunityIndicatorStorage(true); + while (estComIndIterator.hasNext()) { + // Campagne Indicateur Liste Strate Annee Estimation EcartType CV + String[] tuple = estComIndIterator.next(); + String indicatorCode = tuple[1]; + String indicatorList = tuple[2]; + + if (indicators.contains(indicatorCode)) { + + // si pas de list selectionnée, on prend la premiere + String localList = indicatorLists.get(indicatorCode); + if (StringUtils.isBlank(localList)) { + localList = indicatorList; + indicatorLists.put(indicatorCode, localList); + } + + if (indicatorList.equals(localList)) { + Double estimation = Double.parseDouble(tuple[5]); + Double ecart = Double.parseDouble(tuple[6]); + int year = Integer.parseInt(tuple[4]); + + if (year < minYear) { + minYear = year; + } + if (year > maxYear) { + maxYear = year; + } + Map<Integer, Double[]> graphData = indicatorGraphData.get(indicatorCode); + if (graphData == null) { + graphData = new HashMap<Integer, Double[]>(); + indicatorGraphData.put(indicatorCode, graphData); + } + graphData.put(year, new Double[]{estimation, ecart}); + + // si les données sont énormes, on affiche les données + // / multiplicator et on le mentionne dans la légende + if (estimation > 1e9) { + multiplicator = 1000000; + } + if (estimation > 1e6 && multiplicator < 1000000) { + multiplicator = 1000; + } + + // for data part + DataStorage subDataStorage = indicatorStorages.get(indicatorCode); + if (subDataStorage == null) { + subDataStorage = new MemoryDataStorage(); + if ("fr".equals(locale.getLanguage())) { + subDataStorage.add(new String[]{"Campagne", "Indice", "Liste", "Strate", "Année", "Estimation", "EcartType", "CV"}); + } else { + subDataStorage.add(new String[]{"Survey", "Index", "List", "Stratum", "Year", "Estimate", "StandardDeviation", "CV"}); + } + indicatorStorages.put(indicatorCode, subDataStorage); + } + subDataStorage.add(tuple); + } + } + } + + // avec l'extraction des données, on peut demander a générer un graphique + // sur un indicateur qui n'est pas présent dans le projet courant, + // dans ce cas, on retourne null + for (String indicator : indicatorGraphData.keySet()) { + // get graph title + String chartTitle = zoneDisplayName; + String indicatorName = indicatorMap.getIndicatorValue(indicator, locale); + String unit = indicatorMap.getIndicatorUnit(indicator); + chartTitle += " - " + indicatorName; + + // ajout de la traduction de la liste d'indicateur + // les liste sont a1, T1, T2 ... + String localList = indicatorLists.get(indicator); + String listLetter = String.valueOf(localList.charAt(0)); + Iterator<String[]> typeIterator = repository.getSpeciesMap().iterator(true); + while (typeIterator.hasNext()) { + // "Types";"Commentaire";"NumSys min";"NumSys max";"Code" + String[] tuple = typeIterator.next(); + if (tuple[4].equals(listLetter)) { + /// gestion du groupe "Tous" + // cas special, c'est la seule valeur du fichier + // code type espece qui a besoin d'une traduction + if (tuple[4].equalsIgnoreCase("T")) { + if ("fr".equals(locale.getLanguage())) { + chartTitle += " - " + "Tous Liste " + localList.charAt(1); + } else if ("es".equals(locale.getLanguage())) { + chartTitle += " - " + "Todo Lista " + localList.charAt(1); + } else { + chartTitle += " - " + "All List " + localList.charAt(1); + } + } else { + // ajout de la traduction du nom de liste plus le numéro + if ("fr".equals(locale.getLanguage())) { + chartTitle += " - " + tuple[0] + " Liste " + localList.charAt(1); + } else if ("es".equals(locale.getLanguage())) { + chartTitle += " - " + tuple[0] + " Lista " + localList.charAt(1); + } else { + chartTitle += " - " + tuple[0] + " List " + localList.charAt(1); + } + } + break; + } + } + + // generate dataset with sorted data + Map<Integer, Double[]> graphData = indicatorGraphData.get(indicator); + DefaultStatisticalCategoryDataset statisticalDataset = new DefaultStatisticalCategoryDataset(); + for (int indexYear = minYear; indexYear <= maxYear; ++indexYear) { + Double[] entry = graphData.get(indexYear); + if (entry != null) { + Double estimation = entry[0] / multiplicator; + Double ecart = entry[1] / multiplicator; + statisticalDataset.add(estimation, ecart, "Serie1", (Comparable) indexYear); + } else { + statisticalDataset.add(null, null, "Serie1", indexYear); + } + } + + // configure chart + //CategoryAxis categoryAxis = new CategoryAxis(t("coser.business.common.year")); + String yearAxis = reports.getYearChartTitle(locale); + CategoryAxis categoryAxis = new CategoryAxis(yearAxis); + categoryAxis.setCategoryMargin(0); + categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); + // label horizontaux + String legendY = indicatorName; + if (multiplicator != 1) { + // affiche par exemple : cm * 1000 + legendY += " (" + unit + "*" + multiplicator + ")"; + } else if (StringUtils.isNotEmpty(unit)) { + legendY += " (" + unit + ")"; + } + ValueAxis valueAxis = new NumberAxis(legendY); + valueAxis.setUpperMargin(0.1); + + CategoryItemRenderer renderer = new StatisticalLineAndShapeRenderer(false, true); + + // n'affiche pas les nombre sur le graphique + //StandardCategoryItemLabelGenerator itemLabelGenerator = new StandardCategoryItemLabelGenerator(); + //renderer.setBaseItemLabelGenerator(itemLabelGenerator); + //renderer.setBaseItemLabelsVisible(true); + + CategoryPlot plot = new CategoryPlot(statisticalDataset, categoryAxis, valueAxis, renderer); + plot.setOrientation(PlotOrientation.VERTICAL); + JFreeChart chart = new JFreeChart(chartTitle, + JFreeChart.DEFAULT_TITLE_FONT, plot, true); + + // remove series legend + chart.removeLegend(); + // white background + chart.setBackgroundPaint(Color.WHITE); + + try { + File chartFile = File.createTempFile("coser-community-chart-", ".png"); + chartFile.deleteOnExit(); + ChartUtilities.saveChartAsPNG(chartFile, chart, width, height); + //ByteArrayOutputStream out = new ByteArrayOutputStream(); + //ChartUtilities.writeChartAsPNG(out, chart, width, height); + + // data extraction + DataStorage subDataStorage = indicatorStorages.get(indicator); + StringWriter writer = new StringWriter(); + DataStorages.save(subDataStorage, writer); + + // add chart file dans chart data in result + result.put(indicator, Pair.of(chartFile, writer.toString())); + writer.close(); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't save chart", ex); + } + } + + return result; + } + + /** + * Generate population graph for selected species and indicator. + * + * @param species species to extract + * @param indicators indicators to extract + * @param zoneDisplayName zone full name + * @param indicatorMap indicator localized map + * @param locale locale + * @param width graph width + * @param height graph height + * @return maps of generated graph image (temp file) and data indexed by natural key (indicator - species) + */ + public Map<String, Pair<File, String>> getRsufiResultPopCharts(Collection<String> species, + Collection<String> indicators, + String zoneDisplayName, + IndicatorMap indicatorMap, + Locale locale, + int width, + int height) { + + Map<String, Pair<File, String>> result = Maps.newHashMap(); + + int multiplicator = 1; + int minYear = Integer.MAX_VALUE; + int maxYear = Integer.MIN_VALUE; + + MultiKeyMap indicatorGraphData = new MultiKeyMap(); + MultiKeyMap indicatorStorages = new MultiKeyMap(); + + // Campagne Indicateur Liste Species Strate Annee Estimation EcartType CV + Iterator<String[]> estPopIndIterator = repository.loadPopulationIndicatorStorage(true); + while (estPopIndIterator.hasNext()) { + String[] tuple = estPopIndIterator.next(); + + String speciesCode = tuple[3]; + String indicatorCode = tuple[1]; + if (species.contains(speciesCode) && indicators.contains(indicatorCode)) { + + // XXX echatellier, maybe take care of list here ? + + Double estimation = Double.parseDouble(tuple[6]); + Double ecart = Double.parseDouble(tuple[7]); + int year = Integer.parseInt(tuple[5]); + + if (year < minYear) { + minYear = year; + } + if (year > maxYear) { + maxYear = year; + } + Map<Integer, Double[]> graphData = (Map<Integer, Double[]>) indicatorGraphData.get(indicatorCode, speciesCode); + if (graphData == null) { + graphData = new HashMap<Integer, Double[]>(); + indicatorGraphData.put(indicatorCode, speciesCode, graphData); + } + graphData.put(year, new Double[]{estimation, ecart}); + + // si les données sont énormes, on affiche les données + // / multiplicator et on le mentionne dans la légende + if (estimation > 1e9) { + multiplicator = 1000000; + } + if (estimation > 1e6 && multiplicator < 1000000) { + multiplicator = 1000; + } + + // for data part + DataStorage subDataStorage = (DataStorage) indicatorStorages.get(indicatorCode, speciesCode); + if (subDataStorage == null) { + subDataStorage = new MemoryDataStorage(); + if ("fr".equals(locale.getLanguage())) { + subDataStorage.add(new String[]{"Campagne", "Indice", "Liste", "Espèce", "Strate", "Annee", "Estimation", "EcartType", "CV"}); + } else { + subDataStorage.add(new String[]{"Survey", "Index", "List", "Species", "Stratum", "Year", "Estimate", "StandardDeviation", "CV"}); + } + indicatorStorages.put(indicatorCode, speciesCode, subDataStorage); + } + subDataStorage.add(tuple); + } + } + + // avec l'extraction des données, on peut demander a générer un graphique + // sur un indicateur qui n'est pas présent dans le projet courant, + // dans ce cas, on retourne null + for (MultiKey indicatorSpecies : (Set<MultiKey>) indicatorGraphData.keySet()) { + String indicator = (String) indicatorSpecies.getKey(0); + String aSpecies = (String) indicatorSpecies.getKey(1); + // get graph title + String title = zoneDisplayName; + String indicatorName = indicatorMap.getIndicatorValue(indicator, locale); + String unit = indicatorMap.getIndicatorUnit(indicator); + title += " - " + indicatorName; + title += " - " + repository.getSpeciesMap().getReportDisplayName(aSpecies); + + // generate dataset with sorted data + DefaultStatisticalCategoryDataset statisticalDataset = new DefaultStatisticalCategoryDataset(); + Map<Integer, Double[]> graphData = (Map<Integer, Double[]>) indicatorGraphData.get(indicator, aSpecies); + for (int indexYear = minYear; indexYear <= maxYear; ++indexYear) { + Double[] entry = graphData.get(indexYear); + if (entry != null) { + Double estimation = entry[0] / multiplicator; + Double ecart = entry[1] / multiplicator; + statisticalDataset.add(estimation, ecart, "Serie1", (Comparable) indexYear); + } else { + statisticalDataset.add(null, null, "Serie1", indexYear); + } + } + + + // configure chart + //CategoryAxis categoryAxis = new CategoryAxis(t("coser.business.common.year")); + String yearAxis = reports.getYearChartTitle(locale); + CategoryAxis categoryAxis = new CategoryAxis(yearAxis); + categoryAxis.setCategoryMargin(0); + categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); + // label horizontaux + String legendY = indicatorName; + if (multiplicator != 1) { + // affiche par exemple : cm * 1000 + legendY += " (" + unit + "*" + multiplicator + ")"; + } else if (StringUtils.isNotEmpty(unit)) { + legendY += " (" + unit + ")"; + } + ValueAxis valueAxis = new NumberAxis(legendY); + valueAxis.setUpperMargin(0.1); + + CategoryItemRenderer renderer = new StatisticalLineAndShapeRenderer(false, true); + + // n'affiche pas les nombre sur le graphique + //StandardCategoryItemLabelGenerator itemLabelGenerator = new StandardCategoryItemLabelGenerator(); + //renderer.setBaseItemLabelGenerator(itemLabelGenerator); + //renderer.setBaseItemLabelsVisible(true); + + CategoryPlot plot = new CategoryPlot(statisticalDataset, categoryAxis, valueAxis, renderer); + plot.setOrientation(PlotOrientation.VERTICAL); + JFreeChart chart = new JFreeChart(title, + JFreeChart.DEFAULT_TITLE_FONT, plot, true); + + // remove series legend + chart.removeLegend(); + // white background + chart.setBackgroundPaint(Color.WHITE); + + try { + File chartFile = File.createTempFile("coser-population-chart-", ".png"); + chartFile.deleteOnExit(); + ChartUtilities.saveChartAsPNG(chartFile, chart, width, height); + //ByteArrayOutputStream out = new ByteArrayOutputStream(); + //ChartUtilities.writeChartAsPNG(out, chart, width, height); + + // data extraction + DataStorage subDataStorage = (DataStorage) indicatorStorages.get(indicator, aSpecies); + StringWriter writer = new StringWriter(); + DataStorages.save(subDataStorage, writer); + + // add chart file dans chart data in result + result.put(indicator + "-" + aSpecies, Pair.of(chartFile, writer.toString())); + writer.close(); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't save chart", ex); + } + } + + return result; + } +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/ExtractResultProducer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/MapResultProducer.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/MapResultProducer.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/MapResultProducer.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,108 @@ +package fr.ifremer.coser.result.repository.echobase; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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 com.google.common.base.Preconditions; +import fr.ifremer.coser.bean.EchoBaseProject; +import fr.ifremer.coser.bean.ZoneMap; +import fr.ifremer.coser.result.FileResult; +import fr.ifremer.coser.result.repository.RequestUnavailableForProducerException; +import fr.ifremer.coser.result.repository.ResultProducer; +import fr.ifremer.coser.result.request.MapRequest; + +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class MapResultProducer implements ResultProducer<MapRequest> { + + protected final EchoBaseResultRepository repository; + + protected final EchoBaseProject project; + + public MapResultProducer(EchoBaseResultRepository repository) { + this.repository = repository; + this.project = repository.project; + } + + @Override + public EchoBaseResultRepository getRepository() { + return repository; + } + + @Override + public Map<String, String> getAvailableZones(MapRequest request) { + Preconditions.checkNotNull(request.getFacade()); + + boolean match = repository.matchFacade(request); + + Map<String, String> result = null; + if (match) { + ZoneMap zonesMap = repository.getZonesMap(); + List<String> allowedZones = zonesMap.getZonesForFacade(request.getFacade()); + result = zonesMap.getSubZonesMap(project.getZoneName(), allowedZones); + } + return result; + } + + @Override + public Map<String, String> getAvailableSpecies(MapRequest request) { + Preconditions.checkNotNull(request.getFacade()); + Preconditions.checkNotNull(request.getZone()); + + Map<String, String> result = null; + + boolean match = repository.matchFacade(request) && repository.matchZone(request); + if (match) { + // get all map species for given facade + zone + Set<String> speciesList = repository.getMapSpecies(); + result = repository.getSpeciesMap().getSpeciesSubMap(speciesList); + } + return result; + } + + @Override + public Map<String, String> getAvailableIndicators(MapRequest request) { + throw RequestUnavailableForProducerException.newException("getAvailableIndicators", this); + } + + @Override + public FileResult produceResult(MapRequest request) { + Preconditions.checkNotNull(request.getFacade()); + Preconditions.checkNotNull(request.getZone()); + Preconditions.checkNotNull(request.getSpecies()); + + File resultZip = repository.getMapSpeciesFile(request.getSpecies()); + + FileResult result = new FileResult(repository.getId(), resultZip); + return result; + } + +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/MapResultProducer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/PopulationIndicatorResultProducer.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/PopulationIndicatorResultProducer.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/PopulationIndicatorResultProducer.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,292 @@ +package fr.ifremer.coser.result.repository.echobase; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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 com.google.common.base.Preconditions; +import fr.ifremer.coser.CoserTechnicalException; +import fr.ifremer.coser.bean.EchoBaseProject; +import fr.ifremer.coser.bean.ZoneMap; +import fr.ifremer.coser.result.FileResult; +import fr.ifremer.coser.result.Reports; +import fr.ifremer.coser.result.repository.ResultProducer; +import fr.ifremer.coser.result.request.PopulationIndicatorRequest; +import fr.ifremer.coser.storage.DataStorage; +import fr.ifremer.coser.storage.DataStorages; +import fr.ifremer.coser.storage.MemoryDataStorage; +import org.apache.commons.lang3.StringUtils; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.CategoryItemRenderer; +import org.jfree.chart.renderer.category.StatisticalLineAndShapeRenderer; +import org.jfree.data.statistics.DefaultStatisticalCategoryDataset; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class PopulationIndicatorResultProducer implements ResultProducer<PopulationIndicatorRequest> { + + protected final EchoBaseResultRepository repository; + + protected final Reports reports; + + protected final EchoBaseProject project; + + public PopulationIndicatorResultProducer(EchoBaseResultRepository repository) { + this.repository = repository; + this.project = repository.project; + this.reports = repository.reports; + } + + @Override + public EchoBaseResultRepository getRepository() { + return repository; + } + + @Override + public Map<String, String> getAvailableZones(PopulationIndicatorRequest request) { + boolean match = repository.matchFacade(request); + + Map<String, String> result = null; + if (match) { + ZoneMap zonesMap = repository.getZonesMap(); + List<String> allowedZones = zonesMap.getZonesForFacade(request.getFacade()); + result = zonesMap.getSubZonesMap(project.getZoneName(), allowedZones); + } + return result; + } + + @Override + public Map<String, String> getAvailableSpecies(PopulationIndicatorRequest request) { + Preconditions.checkNotNull(request.getFacade()); + Preconditions.checkNotNull(request.getZone()); + + Map<String, String> result = null; + boolean match = repository.matchFacade(request) && repository.matchZone(request); + + if (match) { + // get all population indicator species for given facade + zone + Set<String> speciesList = repository.getPopulationIndicatorSpecies(); + result = repository.getSpeciesMap().getSpeciesSubMap(speciesList); + } + + return result; + } + + @Override + public Map<String, String> getAvailableIndicators(PopulationIndicatorRequest request) { + Preconditions.checkNotNull(request.getFacade()); + Preconditions.checkNotNull(request.getZone()); + + Map<String, String> result = null; + boolean match = repository.matchFacade(request) && repository.matchZone(request); + if (match) { + + // get all indicators for given facade + zone + Set<String> indicatorList = repository.getCommunityIndicators(); + result = repository.getIndicatorsMap().getIndicatorsValues(indicatorList, request.getLocale()); + } + return result; + } + + @Override + public FileResult produceResult(PopulationIndicatorRequest r) { + + File file = null; + switch (r.getResultType()) { + case DATA: + file = getPopulationIndicatorDataFile(r.getIndicator(), + r.getSpecies()); + break; + + case GRAPH: + file = getPopulationIndicatorGraphFile(r.getLocale(), + r.getZone(), + r.getIndicator(), + r.getSpecies()); + break; + } + + + FileResult result = new FileResult(repository.getId(), file); + return result; + } + + protected File getPopulationIndicatorDataFile(String species, String indicator) { + + DataStorage dataStorage = new MemoryDataStorage(); + + Iterator<String[]> iterator = repository.loadPopulationIndicatorStorage(false); + + // add header + dataStorage.add(iterator.next()); + + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + if (repository.matchIndicatorSpeciesAndIndicator(tuple, species, indicator)) { + dataStorage.add(tuple); + } + } + File result = DataStorages.save(dataStorage, "coser-chart-population-indicator", + ".csv" + ); + return result; + } + + protected File getPopulationIndicatorGraphFile(Locale locale, + String zone, + String species, + String indicator) { + + + int multiplicator = 1; + int minYear = Integer.MAX_VALUE; + int maxYear = Integer.MIN_VALUE; + boolean indicatorFound = false; + Map<Integer, Double[]> graphData = new HashMap<Integer, Double[]>(); + Iterator<String[]> iterator = repository.loadPopulationIndicatorStorage(true); + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + + if (repository.matchIndicatorSpeciesAndIndicator(tuple, species, indicator)) { + indicatorFound = true; + + // XXX echatellier, maybe take care of list here ? + + Double estimation = Double.parseDouble(tuple[6]); + Double ecart = Double.parseDouble(tuple[7]); + int year = Integer.parseInt(tuple[5]); + + if (year < minYear) { + minYear = year; + } + if (year > maxYear) { + maxYear = year; + } + graphData.put(year, new Double[]{estimation, ecart}); + + // si les données sont énormes, on affiche les données + // / multiplicator et on le mentionne dans la légende + if (estimation > 1e9) { + multiplicator = 1000000; + } + if (estimation > 1e6 && multiplicator < 1000000) { + multiplicator = 1000; + } + } + } + + File result = null; + + // avec l'extraction des données, on peut demander a générer un graphique + // sur un indicateur qui n'est pas présent dans le projet courant, + // dans ce cas, on retourne null + if (indicatorFound) { + + String zoneDisplayName = repository.getZonesMap().getZoneFullName(zone); + String indicatorName = repository.getIndicatorsMap().getIndicatorValue(indicator, locale); + String unit = repository.getIndicatorsMap().getIndicatorUnit(indicator); + + // get graph title + String title = zoneDisplayName; + title += " - " + indicatorName; + title += " - " + repository.getSpeciesMap().getReportDisplayName(species); + + // generate dataset with sorted data + DefaultStatisticalCategoryDataset statisticalDataset = new DefaultStatisticalCategoryDataset(); + for (int indexYear = minYear; indexYear <= maxYear; ++indexYear) { + Double[] entry = graphData.get(indexYear); + if (entry != null) { + Double estimation = entry[0] / multiplicator; + Double ecart = entry[1] / multiplicator; + statisticalDataset.add(estimation, ecart, "Serie1", (Comparable) indexYear); + } else { + statisticalDataset.add(null, null, "Serie1", indexYear); + } + } + + // configure chart + //CategoryAxis categoryAxis = new CategoryAxis(t("coser.business.common.year")); + String yearAxis = reports.getYearChartTitle(locale); + CategoryAxis categoryAxis = new CategoryAxis(yearAxis); + categoryAxis.setCategoryMargin(0); + categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); + // label horizontaux + String legendY = indicatorName; + if (multiplicator != 1) { + // affiche par exemple : cm * 1000 + legendY += " (" + unit + "*" + multiplicator + ")"; + } else if (StringUtils.isNotEmpty(unit)) { + legendY += " (" + unit + ")"; + } + ValueAxis valueAxis = new NumberAxis(legendY); + valueAxis.setUpperMargin(0.1); + + CategoryItemRenderer renderer = new StatisticalLineAndShapeRenderer(false, true); + + // n'affiche pas les nombre sur le graphique + //StandardCategoryItemLabelGenerator itemLabelGenerator = new StandardCategoryItemLabelGenerator(); + //renderer.setBaseItemLabelGenerator(itemLabelGenerator); + //renderer.setBaseItemLabelsVisible(true); + + CategoryPlot plot = new CategoryPlot(statisticalDataset, categoryAxis, valueAxis, renderer); + plot.setOrientation(PlotOrientation.VERTICAL); + JFreeChart chart = new JFreeChart(title, + JFreeChart.DEFAULT_TITLE_FONT, plot, true); + + // remove series legend + chart.removeLegend(); + // white background + chart.setBackgroundPaint(Color.WHITE); + + try { + result = File.createTempFile("coser-chart-population-indicator-", ".png"); + result.deleteOnExit(); + ChartUtilities.saveChartAsPNG(result, chart, 800, 400); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't save chart", ex); + } + } + + return result; + } + +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/PopulationIndicatorResultProducer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/RawDataResultProducer.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/RawDataResultProducer.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/RawDataResultProducer.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,91 @@ +package fr.ifremer.coser.result.repository.echobase; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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 com.google.common.base.Preconditions; +import fr.ifremer.coser.bean.EchoBaseProject; +import fr.ifremer.coser.bean.ZoneMap; +import fr.ifremer.coser.result.FileResult; +import fr.ifremer.coser.result.repository.RequestUnavailableForProducerException; +import fr.ifremer.coser.result.repository.ResultProducer; +import fr.ifremer.coser.result.request.RawDataRequest; + +import java.util.List; +import java.util.Map; + +/** + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class RawDataResultProducer implements ResultProducer<RawDataRequest> { + + protected final EchoBaseResultRepository repository; + + protected final EchoBaseProject project; + + public RawDataResultProducer(EchoBaseResultRepository repository) { + this.repository = repository; + this.project = repository.project; + + } + + @Override + public EchoBaseResultRepository getRepository() { + return repository; + } + + @Override + public Map<String, String> getAvailableZones(RawDataRequest request) { + Preconditions.checkNotNull(request.getFacade()); + + boolean match = repository.matchFacade(request); + + Map<String, String> result = null; + if (match) { + ZoneMap zonesMap = repository.getZonesMap(); + List<String> allowedZones = zonesMap.getZonesForFacade(request.getFacade()); + result = zonesMap.getSubZonesMap(project.getZoneName(), allowedZones); + } + return result; + } + + @Override + public Map<String, String> getAvailableSpecies(RawDataRequest request) { + throw RequestUnavailableForProducerException.newException("getAvailableSpecies", this); + } + + @Override + public Map<String, String> getAvailableIndicators(RawDataRequest request) { + throw RequestUnavailableForProducerException.newException("getAvailableIndicators", this); + } + + @Override + public FileResult produceResult(RawDataRequest r) { + + //TODO + throw RequestUnavailableForProducerException.newException("produceResult", this); + } + +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/echobase/RawDataResultProducer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/CommunityIndicatorResultProducer.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/CommunityIndicatorResultProducer.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/CommunityIndicatorResultProducer.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,405 @@ +package fr.ifremer.coser.result.repository.legacy; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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 com.google.common.base.Preconditions; +import fr.ifremer.coser.CoserTechnicalException; +import fr.ifremer.coser.bean.RSufiResultPath; +import fr.ifremer.coser.bean.ZoneMap; +import fr.ifremer.coser.result.FileResult; +import fr.ifremer.coser.result.Reports; +import fr.ifremer.coser.result.repository.ResultProducer; +import fr.ifremer.coser.result.request.CommunityIndicatorRequest; +import fr.ifremer.coser.services.ProjectService; +import fr.ifremer.coser.storage.DataStorage; +import fr.ifremer.coser.storage.DataStorages; +import fr.ifremer.coser.storage.MemoryDataStorage; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.CategoryItemRenderer; +import org.jfree.chart.renderer.category.StatisticalLineAndShapeRenderer; +import org.jfree.data.statistics.DefaultStatisticalCategoryDataset; +import org.nuiton.util.FileUtil; +import org.nuiton.util.ZipUtil; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class CommunityIndicatorResultProducer implements ResultProducer<CommunityIndicatorRequest> { + + /** Logger. */ + private static final Log log = LogFactory.getLog(CommunityIndicatorResultProducer.class); + + protected final LegacyResultRepository repository; + + protected final Reports reports; + + protected final RSufiResultPath path; + + protected final File basedir; + + protected final ProjectService projectService; + + protected final String surveyName; + + public CommunityIndicatorResultProducer(LegacyResultRepository repository) { + this.repository = repository; + this.path = repository.path; + this.reports = repository.reports; + this.projectService = repository.projectService; + this.basedir = repository.basedir; + this.surveyName = repository.surveyName; + } + + @Override + public LegacyResultRepository getRepository() { + return repository; + } + + @Override + public Map<String, String> getAvailableZones(CommunityIndicatorRequest request) { + Preconditions.checkNotNull(request.getFacade()); + + boolean match = repository.matchFacade(request); + + Map<String, String> result = null; + if (match) { + ZoneMap zonesMap = repository.getZonesMap(); + List<String> allowedZones = zonesMap.getZonesForFacade(request.getFacade()); + result = zonesMap.getSubZonesMap(path.getRsufiResult().getZone(), allowedZones); + } + return result; + } + + @Override + public Map<String, String> getAvailableSpecies(CommunityIndicatorRequest request) { + Preconditions.checkNotNull(request.getFacade()); + Preconditions.checkNotNull(request.getZone()); + Preconditions.checkNotNull(request.getIndicator()); + + Map<String, String> result = null; + + boolean match = repository.indicatorsResult && + repository.matchFacade(request) && + repository.matchZone(request) && + repository.matchIndicator(request); + if (match) { + + // get all map species for given facade + zone + result = repository.getCommunityIndicatorSpecies(request.getLocale(), + request.getIndicator()); + } + return result; + } + + @Override + public Map<String, String> getAvailableIndicators(CommunityIndicatorRequest request) { + Preconditions.checkNotNull(request.getFacade()); + Preconditions.checkNotNull(request.getZone()); + + Map<String, String> result = null; + + boolean match = repository.indicatorsResult && + repository.matchFacade(request) && + repository.matchZone(request); + if (match) { + + // get all indicators for given facade + zone + Set<String> indicatorList = repository.getCommunityIndicators(); + result = repository.getIndicatorsMap().getIndicatorsValues(indicatorList, request.getLocale()); + } + + return result; + } + + @Override + public FileResult produceResult(CommunityIndicatorRequest request) { + + File file = null; + switch (request.getResultType()) { + case DATA: + file = getCommunityIndicatorDataFile(request.getLocale(), + request.getIndicator(), + request.getSpecies()); + break; + + case GRAPH: + file = getCommunityIndicatorGraphFile(request.getLocale(), + request.getZone(), + request.getIndicator(), + request.getSpecies()); + break; + } + FileResult result = new FileResult(repository.getId(), file); + return result; + } + + + protected File getCommunityIndicatorDataFile(Locale locale, + String indicator, + String speciesList) { + + try { + + File tempDir = FileUtil.createTempDirectory("coser-chart-population-indicator", "-tmp"); + + File baseDir = new File(tempDir, surveyName); + FileUtils.forceMkdir(baseDir); + + // ajout du fichier csv avec les indicateurs + DataStorage dataStorage = new MemoryDataStorage(); + + Iterator<String[]> iterator = repository.loadCommunityIndicatorStorage(false); + + // add header + dataStorage.add(iterator.next()); + + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + if (repository.matchCommunityIndicatorAndSpeciesList(tuple, indicator, speciesList)) { + dataStorage.add(tuple); + } + } + File csvFile = DataStorages.save(dataStorage, "coser-chart-community-indicator", + ".csv" + ); + + File csvFileCopied = new File(baseDir, indicator + ".csv"); + FileUtils.copyFile(csvFile, csvFileCopied); + FileUtils.forceDelete(csvFile); + + // ajout du fichier d'information sur les espèces incluses dans + // les calculs des indicateurs de communautés + // load project (without data to get reftax data) + File metaFile = reports.generateMetaFilePDF(path, + repository.resultDirectory, + locale, + repository.getIndicatorsMap() + ); + File metaFileCopied = new File(baseDir, "Information.pdf"); + FileUtils.copyFile(metaFile, metaFileCopied); + + // make zip + File result = File.createTempFile("coser-chart-community-indicator", ".zip"); + result.deleteOnExit(); + ZipUtil.compress(result, baseDir); + + // clean directory + FileUtils.deleteDirectory(tempDir); + return result; + } catch (Exception e) { + throw new CoserTechnicalException("Can't create zip file", e); + } + } + + protected File getCommunityIndicatorGraphFile(Locale locale, + String zone, + String indicator, + String speciesList) { + + // indicator list to take care + // pour avoir une valeur non nulle si list est null + // on prend dans ce cas la premiere valeur trouvée + String localList = speciesList; + + if (log.isDebugEnabled()) { + log.debug("Searching list for indicator : " + indicator); + } + + int multiplicator = 1; + int minYear = Integer.MAX_VALUE; + int maxYear = Integer.MIN_VALUE; + boolean indicatorFound = false; + Map<Integer, Double[]> graphData = new HashMap<Integer, Double[]>(); + Iterator<String[]> iterator = repository.loadCommunityIndicatorStorage(true); + while (iterator.hasNext()) { + // Campagne Indicateur Liste Strate Annee Estimation EcartType CV + String[] tuple = iterator.next(); + String indicatorList = tuple[2]; + + if (repository.matchCommunityIndicator(tuple, indicator)) { + indicatorFound = true; + + // si pas de list selectionnée, on prend la premiere + if (StringUtils.isBlank(localList)) { + localList = indicatorList; + } + + if (indicatorList.equals(localList)) { + Double estimation = Double.parseDouble(tuple[5]); + Double ecart = Double.parseDouble(tuple[6]); + int year = Integer.parseInt(tuple[4]); + + if (year < minYear) { + minYear = year; + } + if (year > maxYear) { + maxYear = year; + } + graphData.put(year, new Double[]{estimation, ecart}); + + // si les données sont énormes, on affiche les données + // / multiplicator et on le mentionne dans la légende + if (estimation > 1e9) { + multiplicator = 1000000; + } + if (estimation > 1e6 && multiplicator < 1000000) { + multiplicator = 1000; + } + } + } + } + + File result = null; + + // avec l'extraction des données, on peut demander a générer un graphique + // sur un indicateur qui n'est pas présent dans le projet courant, + // dans ce cas, on retourne null + if (indicatorFound) { + + String zoneDisplayName = repository.getZonesMap().getZoneFullName(zone); + String indicatorName = repository.getIndicatorsMap().getIndicatorValue(indicator, locale); + String unit = repository.getIndicatorsMap().getIndicatorUnit(indicator); + + // get graph title + String chartTitle = zoneDisplayName; + chartTitle += " - " + indicatorName; + + String speciesListName = repository.getSpeciesListMap().getSpeciesListName(locale, localList); + chartTitle += " - " + speciesListName; +// // ajout de la traduction de la liste d'indicateur +// // les liste sont a1, T1, T2 ... +// String listLetter = String.valueOf(localList.charAt(0)); +// Iterator<String[]> typeIterator = repository.getSpeciesListMap().iterator(true); +// while (typeIterator.hasNext()) { +// // "Types";"Commentaire";"NumSys min";"NumSys max";"Code" +// String[] tuple = typeIterator.next(); +// if (tuple[4].equals(listLetter)) { +// /// gestion du groupe "Tous" +// // cas special, c'est la seule valeur du fichier +// // code type espece qui a besoin d'une traduction +// if (tuple[4].equalsIgnoreCase("T")) { +// if ("fr".equals(locale.getLanguage())) { +// chartTitle += " - " + "Tous Liste " + localList.charAt(1); +// } else if ("es".equals(locale.getLanguage())) { +// chartTitle += " - " + "Todo Lista " + localList.charAt(1); +// } else { +// chartTitle += " - " + "All List " + localList.charAt(1); +// } +// } else { +// // ajout de la traduction du nom de liste plus le numéro +// if ("fr".equals(locale.getLanguage())) { +// chartTitle += " - " + tuple[0] + " Liste " + localList.charAt(1); +// } else if ("es".equals(locale.getLanguage())) { +// chartTitle += " - " + tuple[0] + " Lista " + localList.charAt(1); +// } else { +// chartTitle += " - " + tuple[0] + " List " + localList.charAt(1); +// } +// } +// break; +// } +// } + + // generate dataset with sorted data + DefaultStatisticalCategoryDataset statisticalDataset = new DefaultStatisticalCategoryDataset(); + for (int indexYear = minYear; indexYear <= maxYear; ++indexYear) { + Double[] entry = graphData.get(indexYear); + if (entry != null) { + Double estimation = entry[0] / multiplicator; + Double ecart = entry[1] / multiplicator; + statisticalDataset.add(estimation, ecart, "Serie1", (Comparable) indexYear); + } else { + statisticalDataset.add(null, null, "Serie1", indexYear); + } + } + + // configure chart + //CategoryAxis categoryAxis = new CategoryAxis(t("coser.business.common.year")); + String yearAxis = reports.getYearChartTitle(locale); + + CategoryAxis categoryAxis = new CategoryAxis(yearAxis); + categoryAxis.setCategoryMargin(0); + categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); + // label horizontaux + String legendY = indicatorName; + if (multiplicator != 1) { + // affiche par exemple : cm * 1000 + legendY += " (" + unit + "*" + multiplicator + ")"; + } else if (StringUtils.isNotEmpty(unit)) { + legendY += " (" + unit + ")"; + } + ValueAxis valueAxis = new NumberAxis(legendY); + valueAxis.setUpperMargin(0.1); + + CategoryItemRenderer renderer = new StatisticalLineAndShapeRenderer(false, true); + + // n'affiche pas les nombre sur le graphique + //StandardCategoryItemLabelGenerator itemLabelGenerator = new StandardCategoryItemLabelGenerator(); + //renderer.setBaseItemLabelGenerator(itemLabelGenerator); + //renderer.setBaseItemLabelsVisible(true); + + CategoryPlot plot = new CategoryPlot(statisticalDataset, categoryAxis, valueAxis, renderer); + plot.setOrientation(PlotOrientation.VERTICAL); + JFreeChart chart = new JFreeChart(chartTitle, + JFreeChart.DEFAULT_TITLE_FONT, plot, true); + + // remove series legend + chart.removeLegend(); + // white background + chart.setBackgroundPaint(Color.WHITE); + + try { + result = File.createTempFile("coser-chart-community-indicator-", ".png"); + result.deleteOnExit(); + ChartUtilities.saveChartAsPNG(result, chart, 800, 400); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't save chart", ex); + } + } + + return result; + } +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/CommunityIndicatorResultProducer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/ExtractResultProducer.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/ExtractResultProducer.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/ExtractResultProducer.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,730 @@ +package fr.ifremer.coser.result.repository.legacy; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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 com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import fr.ifremer.coser.CoserBusinessException; +import fr.ifremer.coser.CoserTechnicalException; +import fr.ifremer.coser.bean.IndicatorMap; +import fr.ifremer.coser.bean.Project; +import fr.ifremer.coser.bean.RSufiResult; +import fr.ifremer.coser.bean.RSufiResultPath; +import fr.ifremer.coser.bean.Selection; +import fr.ifremer.coser.bean.SpeciesMap; +import fr.ifremer.coser.bean.ZoneMap; +import fr.ifremer.coser.result.FileResult; +import fr.ifremer.coser.result.Reports; +import fr.ifremer.coser.result.repository.ResultProducer; +import fr.ifremer.coser.result.request.ExtractRequest; +import fr.ifremer.coser.services.ProjectService; +import fr.ifremer.coser.storage.DataStorage; +import fr.ifremer.coser.storage.DataStorages; +import fr.ifremer.coser.storage.MemoryDataStorage; +import fr.ifremer.coser.util.DataType; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.collections4.keyvalue.MultiKey; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.CategoryItemRenderer; +import org.jfree.chart.renderer.category.StatisticalLineAndShapeRenderer; +import org.jfree.data.statistics.DefaultStatisticalCategoryDataset; +import org.nuiton.util.FileUtil; +import org.nuiton.util.ZipUtil; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class ExtractResultProducer implements ResultProducer<ExtractRequest> { + + /** Logger. */ + private static final Log log = LogFactory.getLog(ExtractResultProducer.class); + + protected final LegacyResultRepository repository; + + protected final Reports reports; + + protected final RSufiResultPath path; + + protected final File basedir; + + protected final ProjectService projectService; + + public ExtractResultProducer(LegacyResultRepository repository) { + this.repository = repository; + this.path = repository.path; + this.reports = repository.reports; + this.projectService = repository.projectService; + this.basedir = repository.basedir; + } + + @Override + public LegacyResultRepository getRepository() { + return repository; + } + + @Override + public Map<String, String> getAvailableZones(ExtractRequest request) { + + ZoneMap zonesMap = repository.getZonesMap(); + List<String> allowedZones = zonesMap.getZonesForFacade(null); + Map<String, String> result = zonesMap.getSubZonesMap(path.getRsufiResult().getZone(), allowedZones); + return result; + } + + @Override + public Map<String, String> getAvailableSpecies(ExtractRequest request) { + Preconditions.checkNotNull(request.getZoneList()); + + Map<String, String> result = null; + + boolean match = repository.matchZoneList(request); + + if (match) { + result = Maps.newHashMap(); + + // get all species for population indicators + result.putAll(repository.getPopulationIndicatorSpecies()); + // get all species for community indicators + result.putAll(repository.getCommunityIndicatorSpecies()); + } + return result; + } + + @Override + public Map<String, String> getAvailableIndicators(ExtractRequest request) { + Preconditions.checkNotNull(request.getZoneList()); + Preconditions.checkNotNull(request.getExtractTypeList()); + + Map<String, String> result = null; + + boolean match = repository.matchZoneList(request); + if (match) { + + Set<String> indicatorList = null; + + if (request.getExtractTypeList().contains(DataType.COMMUNITY)) { + + // get all community indicators for given zone + indicatorList = repository.getCommunityIndicators(); + } else if (request.getExtractTypeList().contains(DataType.POPULATION)) { + + // get all population indicators for given zone + indicatorList = repository.getPopulationIndicators(); + } + + if (indicatorList != null) { + result = repository.getIndicatorsMap().getIndicatorsValues(indicatorList, request.getLocale()); + } + } + return result; + } + + @Override + public FileResult produceResult(ExtractRequest r) { + + Locale locale = r.getLocale(); + List<String> zoneList = r.getZoneList(); + List<DataType> extractTypeList = r.getExtractTypeList(); + List<String> speciesList = r.getSpeciesList(); + List<String> communityIndicatorList = r.getCommunityIndicatorList(); + List<String> populationIndicatorList = r.getPopulationIndicatorList(); + + File resultZip = null; + File tempDir = null; + try { + tempDir = FileUtil.createTempDirectory("coser-extract-", "-tmp"); + + File subDir = new File(tempDir, "Indicateurs_Ifremer"); + FileUtils.forceMkdir(subDir); + + // les sources se retrouve dans le zip a cote du pdf + if (extractTypeList.contains(DataType.SOURCE)) { + if (log.isDebugEnabled()) { + log.debug("Extracting sources"); + } + File srcDir = new File(subDir, "sources"); + extractSource(srcDir); + } + + // les cartes doivent se retrouver dans le pdf + MultiKeyMap pdfMaps = null; + if (extractTypeList.contains(DataType.MAP)) { + if (log.isDebugEnabled()) { + log.debug("Extracting maps"); + } + SpeciesMap speciesMap = repository.getSpeciesMap(); + String zone = path.getRsufiResult().getZone(); + for (String species : speciesList) { + File mapFile = repository.getMapSpeciesFile(species); + pdfMaps.put(zone, speciesMap.getSpeciesName(species), mapFile); + } + } + + // les graphiques sont également dans le pdf + MultiKeyMap pdfCharts = null; + if (CollectionUtils.isNotEmpty(communityIndicatorList) || + CollectionUtils.isNotEmpty(populationIndicatorList)) { + if (log.isDebugEnabled()) { + log.debug("Extracting charts"); + } + pdfCharts = extractCharts(speciesList, + communityIndicatorList, + populationIndicatorList, + locale); + } + + // generate pdf if necessary + if (MapUtils.isNotEmpty(pdfMaps) || MapUtils.isNotEmpty(pdfCharts)) { + if (log.isDebugEnabled()) { + log.debug("Generated Extract PDF"); + } + reports.generateExtractPDF(subDir, + zoneList, + pdfMaps, + pdfCharts, + repository.getZonesMap(), + locale); + } + + // fichier de décharge en pdf + if (log.isDebugEnabled()) { + log.debug("Generated decharge PDF"); + } + String filename = reports.getDechargeFilename(locale); + File dechargePDF = new File(subDir, filename); + reports.generateDechargePDF(dechargePDF, locale, null, null); + + // make zip + if (log.isDebugEnabled()) { + log.debug("Make final archive"); + } + resultZip = File.createTempFile("coser-extract-", ".zip"); + resultZip.deleteOnExit(); + ZipUtil.compress(resultZip, subDir); + + // clean directory + FileUtils.deleteDirectory(tempDir); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't create zip file", ex); + } finally { + // clean directory + FileUtils.deleteQuietly(tempDir); + } + + FileResult result = new FileResult(repository.getId(), resultZip); + return result; + } + + /** + * Generate raw data after selection in a sub directory (named of the zone) of the given directory. + * + * @param directory where to generate file + */ + protected void extractSource(File directory) { + + // load project (with data to get original file names) + Project project = path.getProject(); + + // load selection data (to do data export rsufi) + Selection selection = path.getSelection(); + + try { + // be sure that data are available for this project + // or it will fail + + projectService.loadSelectionData(basedir.getParentFile(), project, selection); + } catch (CoserBusinessException e) { + throw new CoserTechnicalException("Could not load project selection", e); + } + + // il ne faut pas les fichiers de selection, mais leurs + // export rsufi (sans les lignes, et les quotes) + File zoneDirectory = new File(directory, path.getRsufiResult().getZone()); + + try { + FileUtils.forceMkdir(zoneDirectory); + } catch (IOException e) { + throw new CoserTechnicalException("Could not create directory: " + zoneDirectory, e); + } + + try { + projectService.extractRSUfiData(project, selection, zoneDirectory, true); + } catch (CoserBusinessException e) { + throw new CoserTechnicalException("Could not extract raw data", e); + } + } + + /** + * Retourne les indicateurs calculés avec leurs traductions scientifique + * pour la zone et l'especes souhaitées. + * + * @param species especes (if {@code null} look for com indicators + * @param comIndicators comIndicator + * @param popIndicators popIndicators + * @param locale locale + * @return la liste des indicateurs (zone, speciesname, [graphfile, graphdata]) + */ + protected MultiKeyMap extractCharts(Collection<String> species, + Collection<String> comIndicators, + Collection<String> popIndicators, + Locale locale) { + + MultiKeyMap chartFileAndDatas = new MultiKeyMap(); + + Project project = path.getProject(); + RSufiResult rsufiResult = path.getRsufiResult(); + String zone = rsufiResult.getZone(); + String zoneDisplayName = repository.getZonesMap().getZoneFullName(zone); + + if (CollectionUtils.isNotEmpty(comIndicators)) { + Map<String, Pair<File, String>> chartFileAndDataCom = getRsufiResultComCharts(comIndicators, + zoneDisplayName, + repository.getIndicatorsMap(), + locale, + 650, + 430); + // put in multimap as zone,speciesname, data + for (Map.Entry<String, Pair<File, String>> entry : chartFileAndDataCom.entrySet()) { + chartFileAndDatas.put(zone, entry.getKey(), entry.getValue()); + } + } + + if (CollectionUtils.isNotEmpty(popIndicators)) { + Map<String, Pair<File, String>> chartFileAndDataPop = getRsufiResultPopCharts(species, + popIndicators, + zoneDisplayName, + repository.getIndicatorsMap(), + locale, + 650, + 430); + // put in multimap as zone,speciesname, data + for (Map.Entry<String, Pair<File, String>> entry : chartFileAndDataPop.entrySet()) { + chartFileAndDatas.put(zone, entry.getKey(), entry.getValue()); + } + } + + return chartFileAndDatas; + } + + /** + * Generate community graph for selected indicators. + * Used by web ui extraction. + * + * @param indicators indicators to extract + * @param zoneDisplayName zone full name + * @param indicatorMap indicator localized map + * @param locale locale + * @param width graph width + * @param height graph height + * @return maps of generated graph image (temp file) and data indexed by natural key (indicator - species) + */ + public Map<String, Pair<File, String>> getRsufiResultComCharts(Collection<String> indicators, + String zoneDisplayName, + IndicatorMap indicatorMap, + Locale locale, + int width, int height) { + + Map<String, Pair<File, String>> result = Maps.newHashMap(); + + int multiplicator = 1; + int minYear = Integer.MAX_VALUE; + int maxYear = Integer.MIN_VALUE; + + Map<String, Map<Integer, Double[]>> indicatorGraphData = new HashMap<String, Map<Integer, Double[]>>(); + Map<String, String> indicatorLists = new HashMap<String, String>(); + Map<String, DataStorage> indicatorStorages = new HashMap<String, DataStorage>(); + + // Campagne Indicateur Liste Strate Annee Estimation EcartType CV + Iterator<String[]> estComIndIterator = repository.loadCommunityIndicatorStorage(true); + while (estComIndIterator.hasNext()) { + // Campagne Indicateur Liste Strate Annee Estimation EcartType CV + String[] tuple = estComIndIterator.next(); + String indicatorCode = tuple[1]; + String indicatorList = tuple[2]; + + if (indicators.contains(indicatorCode)) { + + // si pas de list selectionnée, on prend la premiere + String localList = indicatorLists.get(indicatorCode); + if (StringUtils.isBlank(localList)) { + localList = indicatorList; + indicatorLists.put(indicatorCode, localList); + } + + if (indicatorList.equals(localList)) { + Double estimation = Double.parseDouble(tuple[5]); + Double ecart = Double.parseDouble(tuple[6]); + int year = Integer.parseInt(tuple[4]); + + if (year < minYear) { + minYear = year; + } + if (year > maxYear) { + maxYear = year; + } + Map<Integer, Double[]> graphData = indicatorGraphData.get(indicatorCode); + if (graphData == null) { + graphData = new HashMap<Integer, Double[]>(); + indicatorGraphData.put(indicatorCode, graphData); + } + graphData.put(year, new Double[]{estimation, ecart}); + + // si les données sont énormes, on affiche les données + // / multiplicator et on le mentionne dans la légende + if (estimation > 1e9) { + multiplicator = 1000000; + } + if (estimation > 1e6 && multiplicator < 1000000) { + multiplicator = 1000; + } + + // for data part + DataStorage subDataStorage = indicatorStorages.get(indicatorCode); + if (subDataStorage == null) { + subDataStorage = new MemoryDataStorage(); + if ("fr".equals(locale.getLanguage())) { + subDataStorage.add(new String[]{"Campagne", "Indice", "Liste", "Strate", "Année", "Estimation", "EcartType", "CV"}); + } else { + subDataStorage.add(new String[]{"Survey", "Index", "List", "Stratum", "Year", "Estimate", "StandardDeviation", "CV"}); + } + indicatorStorages.put(indicatorCode, subDataStorage); + } + subDataStorage.add(tuple); + } + } + } + + // avec l'extraction des données, on peut demander a générer un graphique + // sur un indicateur qui n'est pas présent dans le projet courant, + // dans ce cas, on retourne null + for (String indicator : indicatorGraphData.keySet()) { + // get graph title + String chartTitle = zoneDisplayName; + String indicatorName = indicatorMap.getIndicatorValue(indicator, locale); + String unit = indicatorMap.getIndicatorUnit(indicator); + chartTitle += " - " + indicatorName; + + // ajout de la traduction de la liste d'indicateur + // les liste sont a1, T1, T2 ... + String localList = indicatorLists.get(indicator); + String speciesListName = repository.getSpeciesListMap().getSpeciesListName(locale, localList); + chartTitle += " - " + speciesListName; +// String listLetter = String.valueOf(localList.charAt(0)); +// Iterator<String[]> typeIterator = repository.getSpeciesListMap().iterator(true); +// while (typeIterator.hasNext()) { +// // "Types";"Commentaire";"NumSys min";"NumSys max";"Code" +// String[] tuple = typeIterator.next(); +// if (tuple[4].equals(listLetter)) { +// /// gestion du groupe "Tous" +// // cas special, c'est la seule valeur du fichier +// // code type espece qui a besoin d'une traduction +// if (tuple[4].equalsIgnoreCase("T")) { +// if ("fr".equals(locale.getLanguage())) { +// chartTitle += " - " + "Tous Liste " + localList.charAt(1); +// } else if ("es".equals(locale.getLanguage())) { +// chartTitle += " - " + "Todo Lista " + localList.charAt(1); +// } else { +// chartTitle += " - " + "All List " + localList.charAt(1); +// } +// } else { +// // ajout de la traduction du nom de liste plus le numéro +// if ("fr".equals(locale.getLanguage())) { +// chartTitle += " - " + tuple[0] + " Liste " + localList.charAt(1); +// } else if ("es".equals(locale.getLanguage())) { +// chartTitle += " - " + tuple[0] + " Lista " + localList.charAt(1); +// } else { +// chartTitle += " - " + tuple[0] + " List " + localList.charAt(1); +// } +// } +// break; +// } +// } + + // generate dataset with sorted data + Map<Integer, Double[]> graphData = indicatorGraphData.get(indicator); + DefaultStatisticalCategoryDataset statisticalDataset = new DefaultStatisticalCategoryDataset(); + for (int indexYear = minYear; indexYear <= maxYear; ++indexYear) { + Double[] entry = graphData.get(indexYear); + if (entry != null) { + Double estimation = entry[0] / multiplicator; + Double ecart = entry[1] / multiplicator; + statisticalDataset.add(estimation, ecart, "Serie1", (Comparable) indexYear); + } else { + statisticalDataset.add(null, null, "Serie1", indexYear); + } + } + + // configure chart + //CategoryAxis categoryAxis = new CategoryAxis(t("coser.business.common.year")); + String yearAxis = reports.getYearChartTitle(locale); + CategoryAxis categoryAxis = new CategoryAxis(yearAxis); + categoryAxis.setCategoryMargin(0); + categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); + // label horizontaux + String legendY = indicatorName; + if (multiplicator != 1) { + // affiche par exemple : cm * 1000 + legendY += " (" + unit + "*" + multiplicator + ")"; + } else if (StringUtils.isNotEmpty(unit)) { + legendY += " (" + unit + ")"; + } + ValueAxis valueAxis = new NumberAxis(legendY); + valueAxis.setUpperMargin(0.1); + + CategoryItemRenderer renderer = new StatisticalLineAndShapeRenderer(false, true); + + // n'affiche pas les nombre sur le graphique + //StandardCategoryItemLabelGenerator itemLabelGenerator = new StandardCategoryItemLabelGenerator(); + //renderer.setBaseItemLabelGenerator(itemLabelGenerator); + //renderer.setBaseItemLabelsVisible(true); + + CategoryPlot plot = new CategoryPlot(statisticalDataset, categoryAxis, valueAxis, renderer); + plot.setOrientation(PlotOrientation.VERTICAL); + JFreeChart chart = new JFreeChart(chartTitle, + JFreeChart.DEFAULT_TITLE_FONT, plot, true); + + // remove series legend + chart.removeLegend(); + // white background + chart.setBackgroundPaint(Color.WHITE); + + try { + File chartFile = File.createTempFile("coser-community-chart-", ".png"); + chartFile.deleteOnExit(); + ChartUtilities.saveChartAsPNG(chartFile, chart, width, height); + //ByteArrayOutputStream out = new ByteArrayOutputStream(); + //ChartUtilities.writeChartAsPNG(out, chart, width, height); + + // data extraction + DataStorage subDataStorage = indicatorStorages.get(indicator); + StringWriter writer = new StringWriter(); + DataStorages.save(subDataStorage, writer); + + // add chart file dans chart data in result + result.put(indicator, Pair.of(chartFile, writer.toString())); + writer.close(); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't save chart", ex); + } + } + + return result; + } + + /** + * Generate population graph for selected species and indicator. + * + * @param species species to extract + * @param indicators indicators to extract + * @param zoneDisplayName zone full name + * @param indicatorMap indicator localized map + * @param locale locale + * @param width graph width + * @param height graph height + * @return maps of generated graph image (temp file) and data indexed by natural key (indicator - species) + */ + public Map<String, Pair<File, String>> getRsufiResultPopCharts(Collection<String> species, + Collection<String> indicators, + String zoneDisplayName, + IndicatorMap indicatorMap, + Locale locale, + int width, + int height) { + + Map<String, Pair<File, String>> result = Maps.newHashMap(); + + int multiplicator = 1; + int minYear = Integer.MAX_VALUE; + int maxYear = Integer.MIN_VALUE; + + MultiKeyMap indicatorGraphData = new MultiKeyMap(); + MultiKeyMap indicatorStorages = new MultiKeyMap(); + + // Campagne Indicateur Liste Species Strate Annee Estimation EcartType CV + Iterator<String[]> estPopIndIterator = repository.loadPopulationIndicatorStorage(true); + while (estPopIndIterator.hasNext()) { + String[] tuple = estPopIndIterator.next(); + + String speciesCode = tuple[3]; + String indicatorCode = tuple[1]; + if (species.contains(speciesCode) && indicators.contains(indicatorCode)) { + + // XXX echatellier, maybe take care of list here ? + + Double estimation = Double.parseDouble(tuple[6]); + Double ecart = Double.parseDouble(tuple[7]); + int year = Integer.parseInt(tuple[5]); + + if (year < minYear) { + minYear = year; + } + if (year > maxYear) { + maxYear = year; + } + Map<Integer, Double[]> graphData = (Map<Integer, Double[]>) indicatorGraphData.get(indicatorCode, speciesCode); + if (graphData == null) { + graphData = new HashMap<Integer, Double[]>(); + indicatorGraphData.put(indicatorCode, speciesCode, graphData); + } + graphData.put(year, new Double[]{estimation, ecart}); + + // si les données sont énormes, on affiche les données + // / multiplicator et on le mentionne dans la légende + if (estimation > 1e9) { + multiplicator = 1000000; + } + if (estimation > 1e6 && multiplicator < 1000000) { + multiplicator = 1000; + } + + // for data part + DataStorage subDataStorage = (DataStorage) indicatorStorages.get(indicatorCode, speciesCode); + if (subDataStorage == null) { + subDataStorage = new MemoryDataStorage(); + if ("fr".equals(locale.getLanguage())) { + subDataStorage.add(new String[]{"Campagne", "Indice", "Liste", "Espèce", "Strate", "Annee", "Estimation", "EcartType", "CV"}); + } else { + subDataStorage.add(new String[]{"Survey", "Index", "List", "Species", "Stratum", "Year", "Estimate", "StandardDeviation", "CV"}); + } + indicatorStorages.put(indicatorCode, speciesCode, subDataStorage); + } + subDataStorage.add(tuple); + } + } + + SpeciesMap speciesMap = repository.getSpeciesMap(); + + // avec l'extraction des données, on peut demander a générer un graphique + // sur un indicateur qui n'est pas présent dans le projet courant, + // dans ce cas, on retourne null + for (MultiKey indicatorSpecies : (Set<MultiKey>) indicatorGraphData.keySet()) { + String indicator = (String) indicatorSpecies.getKey(0); + String aSpecies = (String) indicatorSpecies.getKey(1); + // get graph title + String title = zoneDisplayName; + String indicatorName = indicatorMap.getIndicatorValue(indicator, locale); + String unit = indicatorMap.getIndicatorUnit(indicator); + title += " - " + indicatorName; + title += " - " + speciesMap.getReportDisplayName(aSpecies); + + // generate dataset with sorted data + DefaultStatisticalCategoryDataset statisticalDataset = new DefaultStatisticalCategoryDataset(); + Map<Integer, Double[]> graphData = (Map<Integer, Double[]>) indicatorGraphData.get(indicator, aSpecies); + for (int indexYear = minYear; indexYear <= maxYear; ++indexYear) { + Double[] entry = graphData.get(indexYear); + if (entry != null) { + Double estimation = entry[0] / multiplicator; + Double ecart = entry[1] / multiplicator; + statisticalDataset.add(estimation, ecart, "Serie1", (Comparable) indexYear); + } else { + statisticalDataset.add(null, null, "Serie1", indexYear); + } + } + + + // configure chart + //CategoryAxis categoryAxis = new CategoryAxis(t("coser.business.common.year")); + String yearAxis = reports.getYearChartTitle(locale); + CategoryAxis categoryAxis = new CategoryAxis(yearAxis); + categoryAxis.setCategoryMargin(0); + categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); + // label horizontaux + String legendY = indicatorName; + if (multiplicator != 1) { + // affiche par exemple : cm * 1000 + legendY += " (" + unit + "*" + multiplicator + ")"; + } else if (StringUtils.isNotEmpty(unit)) { + legendY += " (" + unit + ")"; + } + ValueAxis valueAxis = new NumberAxis(legendY); + valueAxis.setUpperMargin(0.1); + + CategoryItemRenderer renderer = new StatisticalLineAndShapeRenderer(false, true); + + // n'affiche pas les nombre sur le graphique + //StandardCategoryItemLabelGenerator itemLabelGenerator = new StandardCategoryItemLabelGenerator(); + //renderer.setBaseItemLabelGenerator(itemLabelGenerator); + //renderer.setBaseItemLabelsVisible(true); + + CategoryPlot plot = new CategoryPlot(statisticalDataset, categoryAxis, valueAxis, renderer); + plot.setOrientation(PlotOrientation.VERTICAL); + JFreeChart chart = new JFreeChart(title, + JFreeChart.DEFAULT_TITLE_FONT, plot, true); + + // remove series legend + chart.removeLegend(); + // white background + chart.setBackgroundPaint(Color.WHITE); + + try { + File chartFile = File.createTempFile("coser-population-chart-", ".png"); + chartFile.deleteOnExit(); + ChartUtilities.saveChartAsPNG(chartFile, chart, width, height); + //ByteArrayOutputStream out = new ByteArrayOutputStream(); + //ChartUtilities.writeChartAsPNG(out, chart, width, height); + + // data extraction + DataStorage subDataStorage = (DataStorage) indicatorStorages.get(indicator, aSpecies); + StringWriter writer = new StringWriter(); + DataStorages.save(subDataStorage, writer); + + // add chart file dans chart data in result + result.put(indicator + "-" + aSpecies, Pair.of(chartFile, writer.toString())); + writer.close(); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't save chart", ex); + } + } + + return result; + } +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/ExtractResultProducer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/LegacyResultRepository.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/LegacyResultRepository.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/LegacyResultRepository.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -27,55 +27,36 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import fr.ifremer.coser.CoserBusinessConfig; -import fr.ifremer.coser.CoserBusinessException; import fr.ifremer.coser.CoserConstants; -import fr.ifremer.coser.CoserTechnicalException; import fr.ifremer.coser.bean.EchoBaseProject; import fr.ifremer.coser.bean.IndicatorMap; -import fr.ifremer.coser.bean.Project; -import fr.ifremer.coser.bean.RSufiResult; import fr.ifremer.coser.bean.RSufiResultPath; -import fr.ifremer.coser.bean.Selection; +import fr.ifremer.coser.bean.SpeciesListMap; +import fr.ifremer.coser.bean.SpeciesMap; import fr.ifremer.coser.bean.ZoneMap; import fr.ifremer.coser.result.CoserRequest; import fr.ifremer.coser.result.CoserResult; -import fr.ifremer.coser.result.FileResult; import fr.ifremer.coser.result.Reports; +import fr.ifremer.coser.result.repository.ResultProducer; import fr.ifremer.coser.result.repository.ResultRepository; import fr.ifremer.coser.result.request.CommunityIndicatorRequest; -import fr.ifremer.coser.result.request.IndicatorRequest; +import fr.ifremer.coser.result.request.CoserRequestFacadeAware; +import fr.ifremer.coser.result.request.CoserRequestZoneAware; +import fr.ifremer.coser.result.request.ExtractRequest; import fr.ifremer.coser.result.request.MapRequest; import fr.ifremer.coser.result.request.PopulationIndicatorRequest; import fr.ifremer.coser.result.request.RawDataRequest; import fr.ifremer.coser.services.ProjectService; -import fr.ifremer.coser.services.WebService; import fr.ifremer.coser.storage.DataStorage; import fr.ifremer.coser.storage.DataStorages; -import fr.ifremer.coser.storage.MemoryDataStorage; +import fr.ifremer.coser.util.DataType; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.jfree.chart.ChartUtilities; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.CategoryAxis; -import org.jfree.chart.axis.CategoryLabelPositions; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.plot.CategoryPlot; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.renderer.category.CategoryItemRenderer; -import org.jfree.chart.renderer.category.StatisticalLineAndShapeRenderer; -import org.jfree.data.statistics.DefaultStatisticalCategoryDataset; -import org.nuiton.util.FileUtil; -import org.nuiton.util.ZipUtil; -import java.awt.Color; import java.io.File; import java.io.FilenameFilter; -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -148,9 +129,14 @@ /** * Cache of species definition. */ - protected Map<String, String> speciesMap; + protected SpeciesMap speciesMap; /** + * Cache of species list definition. + */ + protected SpeciesListMap speciesListMap; + + /** * Cache of indicator definition. */ protected IndicatorMap indicatorsMap; @@ -171,14 +157,19 @@ protected final boolean indicatorsResult; /** - * IS the results contains raw data ? + * Is the results contains raw data ? */ protected final boolean dataResult; - protected final ProjectService projectService; + /** + * Report helper. + */ + protected final Reports reports; - protected final WebService webService; + protected final Map<Class<?>, ResultProducer<?>> resultProducers; + protected final ProjectService projectService; + public LegacyResultRepository(CoserBusinessConfig config, File basedir, RSufiResultPath path, @@ -201,16 +192,22 @@ this.mapsResult = path.getRsufiResult().isMapsResult(); this.indicatorsResult = path.getRsufiResult().isIndicatorsResult(); this.dataResult = path.getRsufiResult().isDataAllowed(); + this.reports = new Reports(); - if (log.isInfoEnabled()) { - log.info("New result repository: " + getId()); - } - this.mapFileToSpeciesCode = EchoBaseProject.newMapFileToSpeciesCode(surveyName); this.speciesCodeToMapFile = EchoBaseProject.newSpeciesCodeToMapFileName(surveyName); this.mapSpeciesFilenameFilter = EchoBaseProject.newMapSpeciesFilenameFilter(surveyName); this.projectService = new ProjectService(config); - this.webService = new WebService(config); + this.resultProducers = Maps.newHashMap(); + this.resultProducers.put(MapRequest.class, new MapResultProducer(this)); + this.resultProducers.put(CommunityIndicatorRequest.class, new CommunityIndicatorResultProducer(this)); + this.resultProducers.put(PopulationIndicatorRequest.class, new PopulationIndicatorResultProducer(this)); + this.resultProducers.put(RawDataRequest.class, new RawDataResultProducer(this)); + this.resultProducers.put(ExtractRequest.class, new ExtractResultProducer(this)); + + if (log.isInfoEnabled()) { + log.info("New result repository: " + getId()); + } } // --------------------------------------------------------------------- // @@ -229,130 +226,30 @@ @Override public Map<String, String> getAvailableZones(CoserRequest request) { - List<String> allowedZones = null; + ResultProducer resultProducer = getProducer(request.getClass()); + Preconditions.checkNotNull(resultProducer); - if (request instanceof MapRequest) { - MapRequest r = (MapRequest) request; - - boolean match = mapsResult && matchFacade(r); - if (match) { - allowedZones = getZonesMap().getZonesForFacade(r.getFacade()); - } - } else if (request instanceof RawDataRequest) { - RawDataRequest r = (RawDataRequest) request; - - boolean match = dataResult && matchFacade(r); - if (match) { - allowedZones = getZonesMap().getZonesForFacade(r.getFacade()); - } - } else if (request instanceof PopulationIndicatorRequest) { - PopulationIndicatorRequest r = (PopulationIndicatorRequest) request; - - boolean match = indicatorsResult && matchFacade(r); - if (match) { - allowedZones = getZonesMap().getZonesForFacade(r.getFacade()); - } - } else if (request instanceof CommunityIndicatorRequest) { - CommunityIndicatorRequest r = (CommunityIndicatorRequest) request; - - boolean match = indicatorsResult && matchFacade(r); - if (match) { - allowedZones = getZonesMap().getZonesForFacade(r.getFacade()); - } - } - - Map<String, String> result = Maps.newHashMap(); - - if (allowedZones != null) { - - String zoneId = path.getRsufiResult().getZone(); - if (allowedZones.contains(zoneId)) { - String zoneFullName = getZonesMap().getZoneFullNameWithNoFacade(zoneId); - result.put(zoneId, zoneFullName); - } - } - + Map result = resultProducer.getAvailableZones(request); return result; } @Override public Map<String, String> getAvailableSpecies(CoserRequest request) { - Map<String, String> result = null; + ResultProducer resultProducer = getProducer(request.getClass()); + Preconditions.checkNotNull(resultProducer); - if (request instanceof MapRequest) { - MapRequest r = (MapRequest) request; - - boolean match = mapsResult && - matchFacade(r) && - matchZone(r); - if (match) { - // get all map species for given facade + zone - result = getPopulationIndicatorSpecies(); - } - } else if (request instanceof PopulationIndicatorRequest) { - PopulationIndicatorRequest r = (PopulationIndicatorRequest) request; - - boolean match = indicatorsResult && - matchFacade(r) && - matchZone(r); - - if (match) { - // get all population indicator species for given facade + zone - result = getPopulationIndicatorSpecies(); - } - } else if (request instanceof CommunityIndicatorRequest) { - CommunityIndicatorRequest r = (CommunityIndicatorRequest) request; - - Preconditions.checkNotNull(r.getIndicator()); - - boolean match = indicatorsResult && - matchFacade(r) && - matchZone(r) && - matchIndicator(r); - - if (match) { - // get all speciesList for given facade + zone + indicator - result = getCommunityIndicatorSpecies(r.getLocale(), r.getIndicator()); - } - } - + Map<String, String> result = resultProducer.getAvailableSpecies(request); return result; } @Override - public Map<String, String> getAvailableIndicators(IndicatorRequest request) { - Set<String> indicatorList = null; + public Map<String, String> getAvailableIndicators(CoserRequest request) { - if (request instanceof PopulationIndicatorRequest) { - PopulationIndicatorRequest r = (PopulationIndicatorRequest) request; + ResultProducer resultProducer = getProducer(request.getClass()); + Preconditions.checkNotNull(resultProducer); - Preconditions.checkNotNull(r.getSpecies()); - - boolean match = indicatorsResult && - matchFacade(request) && - matchZone(request) && - matchSpecies(r); - - if (match) { - - // get all indicators for given facade + zone + species - indicatorList = getPopulationIndicators(r.getSpecies()); - } - - } else if (request instanceof CommunityIndicatorRequest) { - - boolean match = indicatorsResult && - matchFacade(request) && - matchZone(request); - if (match) { - - // get all indicators for given facade + zone - indicatorList = getCommunityIndicators(); - } - } - - Map<String, String> result = getIndicatorsMap().getIndicatorsValues(indicatorList, request.getLocale()); + Map<String, String> result = resultProducer.getAvailableIndicators(request); return result; } @@ -396,6 +293,15 @@ matchFacade(r) && matchZone(r) && matchSpeciesAndIndicator(r); + } else if (request instanceof ExtractRequest) { + + // must match extract type + zone + (species + indicator) + ExtractRequest r = (ExtractRequest) request; + + result = matchExtractTypeSet(r) && + matchZoneList(r) && + (matchPopulationIndicatorListAndSpeciesList(r) || + matchCommunityIndicatorListAndSpeciesList(r)); } return result; } @@ -405,84 +311,33 @@ Preconditions.checkArgument(request.isFilled()); Preconditions.checkArgument(acceptResult(request)); - CoserResult result = null; + ResultProducer resultProducer = getProducer(request.getClass()); + Preconditions.checkNotNull(resultProducer); - if (request instanceof MapRequest) { - MapRequest r = (MapRequest) request; - - String species = r.getSpecies(); - - File mapFile = getMapSpeciesFile(species); - result = new FileResult(getId(), mapFile); - - } else if (request instanceof RawDataRequest) { - - // No such result for echobase at the moment - RawDataRequest r = (RawDataRequest) request; - - File file = getRawDataFile(r.getLocale() - ); - result = new FileResult(getId(), file); - - } else if (request instanceof CommunityIndicatorRequest) { - CommunityIndicatorRequest r = (CommunityIndicatorRequest) request; - - File file = null; - switch (r.getResultType()) { - case DATA: - file = getCommunityIndicatorDataFile(r.getLocale(), - r.getZone(), - r.getIndicator(), - r.getSpecies()); - break; - - case GRAPH: - file = getCommunityIndicatorGraphFile(r.getLocale(), - r.getZone(), - r.getIndicator(), - r.getSpecies()); - break; - } - if (file != null) { - result = new FileResult(getId(), file); - } - - } else if (request instanceof PopulationIndicatorRequest) { - PopulationIndicatorRequest r = (PopulationIndicatorRequest) request; - - File file = null; - switch (r.getResultType()) { - case DATA: - file = getPopulationIndicatorDataFile(r.getSpecies(), - r.getIndicator()); - break; - - case GRAPH: - file = getPopulationIndicatorGraphFile(r.getLocale(), - r.getZone(), - r.getSpecies(), - r.getIndicator()); - break; - } - if (file != null) { - result = new FileResult(getId(), file); - } - } + CoserResult result = resultProducer.produceResult(request); return result; } + protected <R extends CoserRequest> ResultProducer<R> getProducer(Class<R> requestType) { + return (ResultProducer<R>) resultProducers.get(requestType); + } + // --------------------------------------------------------------------- // - // --- MapRequest matchers --------------------------------------------- // + // --- Common matchers ------------------------------------------------- // // --------------------------------------------------------------------- // - protected boolean matchFacade(MapRequest request) { + protected boolean matchFacade(CoserRequestFacadeAware request) { return true; } - protected boolean matchZone(MapRequest request) { + protected boolean matchZone(CoserRequestZoneAware request) { return path.getRsufiResult().getZone().equals(request.getZone()); } + // --------------------------------------------------------------------- // + // --- MapRequest matchers --------------------------------------------- // + // --------------------------------------------------------------------- // + protected boolean matchSpecies(MapRequest request) { String species = request.getSpecies(); File file = getMapSpeciesFile(species); @@ -493,27 +348,11 @@ // --- RawDataRequest matchers ----------------------------------------- // // --------------------------------------------------------------------- // - protected boolean matchFacade(RawDataRequest request) { - return true; - } - protected boolean matchZone(RawDataRequest request) { return path.getRsufiResult().getZone().equals(request.getZone()); } // --------------------------------------------------------------------- // - // --- IndicatorRequest matchers --------------------------------------- // - // --------------------------------------------------------------------- // - - protected boolean matchFacade(IndicatorRequest request) { - return true; - } - - protected boolean matchZone(IndicatorRequest request) { - return path.getRsufiResult().getZone().equals(request.getZone()); - } - - // --------------------------------------------------------------------- // // --- PopulationIndicatorRequest matchers ----------------------------- // // --------------------------------------------------------------------- // @@ -623,455 +462,161 @@ } // --------------------------------------------------------------------- // - // --- Get Map result -------------------------------------------------- // + // --- ExtractRequest matchers ----------------------------------------- // // --------------------------------------------------------------------- // - protected File getMapSpeciesFile(String species) { - String fileName = speciesCodeToMapFile.apply(species); - File file = fileName == null ? null : new File(mapsDirectory, fileName); - return file; - } - - // --------------------------------------------------------------------- // - // --- Get Raw Data result --------------------------------------------- // - // --------------------------------------------------------------------- // - - protected File getRawDataFile(Locale locale) { - - try { - // be sure that data are available for this project - // or it will fail - projectService.loadSelectionData(basedir.getParentFile(), path.getProject(), path.getSelection()); - } catch (CoserBusinessException e) { - throw new CoserTechnicalException("Could not load project selection", e); + protected boolean matchExtractTypeSet(ExtractRequest request) { + boolean result = false; + if (mapsResult) { + result = request.getExtractTypeList().contains(DataType.SOURCE); } - - File result; - - try { - File tempDir = FileUtil.createTempDirectory("coser-source-", "-tmp"); - - // il ne faut pas les fichiers de selection, mais leurs - // export rsufi (sans les lignes, et les quotes) - File archiveDir = projectService.extractRSUfiData(path.getProject(), path.getSelection(), tempDir, true); - - // add decharge file - String filename; - if (locale != null && "fr".equals(locale.getLanguage())) { - filename = "DechargeDonnees.pdf"; - } else if (locale != null && "es".equals(locale.getLanguage())) { - filename = "DatosDeExencionDeResponsabilidad.pdf"; - } else { - filename = "DataDisclaimer.pdf"; - } - File dechargePDF = new File(archiveDir, filename); - webService.generateDechargePDF(dechargePDF, resultDirectory, path.getRsufiResult(), locale); - - // ajout du reftax dans le zip - File reftaxFile = new File(basedir, CoserConstants.Category.REFTAX_SPECIES.getStorageFileName()); - FileUtils.copyFileToDirectory(reftaxFile, archiveDir); - - // make zip - result = File.createTempFile("coser-source-", ".zip"); - result.deleteOnExit(); - ZipUtil.compress(result, archiveDir); - - // clean directory - FileUtils.deleteDirectory(tempDir); - } catch (Exception ex) { - throw new CoserTechnicalException("Can't create zip file", ex); + if (indicatorsResult) { + result = request.getExtractTypeList().contains(DataType.POPULATION) || + request.getExtractTypeList().contains(DataType.COMMUNITY); } - + if (dataResult) { + result = request.getExtractTypeList().contains(DataType.SOURCE); + } return result; } - // --------------------------------------------------------------------- // - // --- Get Community indicator result ---------------------------------- // - // --------------------------------------------------------------------- // - - protected File getCommunityIndicatorDataFile(Locale locale, - String zone, - String indicator, - String speciesList) { - - try { - - File tempDir = FileUtil.createTempDirectory("coser-chart-population-indicator", "-tmp"); - - File baseDir = new File(tempDir, surveyName); - FileUtils.forceMkdir(baseDir); - - RSufiResult rSufiResult = path.getRsufiResult(); - - // ajout du fichier csv avec les indicateurs - DataStorage dataStorage = new MemoryDataStorage(); - - Iterator<String[]> iterator = loadCommunityIndicatorStorage(false); - - // add header - dataStorage.add(iterator.next()); - - while (iterator.hasNext()) { - String[] tuple = iterator.next(); - if (matchCommunityIndicatorAndSpeciesList(tuple, indicator, speciesList)) { - dataStorage.add(tuple); - } - } - File csvFile = DataStorages.save("coser-chart-community-indicator", - ".csv", - dataStorage); - - File csvFileCopied = new File(baseDir, indicator + ".csv"); - FileUtils.copyFile(csvFile, csvFileCopied); - FileUtils.forceDelete(csvFile); - - // ajout du fichier d'information sur les espèces incluses dans - // les calculs des indicateurs de communautés - // load project (without data to get reftax data) - Project project = path.getProject(); - Selection selection = path.getSelection(); - File metaFile = webService.generateMetaFilePDF(project, - selection, - resultDirectory, - rSufiResult, - indicator, - locale); - File metaFileCopied = new File(baseDir, "Information.pdf"); - FileUtils.copyFile(metaFile, metaFileCopied); - - // make zip - File result = File.createTempFile("coser-chart-community-indicator", ".zip"); - result.deleteOnExit(); - ZipUtil.compress(result, baseDir); - - // clean directory - FileUtils.deleteDirectory(tempDir); - return result; - } catch (Exception e) { - throw new CoserTechnicalException("Can't create zip file", e); - } + protected boolean matchZoneList(ExtractRequest request) { + return request.getZoneList().contains(path.getRsufiResult().getZone()); } - protected File getCommunityIndicatorGraphFile(Locale locale, - String zone, - String indicator, - String speciesList) { + protected boolean matchCommunityIndicatorList(ExtractRequest request) { + Preconditions.checkNotNull(request.getCommunityIndicatorList()); - // indicator list to take care - // pour avoir une valeur non nulle si list est null - // on prend dans ce cas la premiere valeur trouvée - String localList = speciesList; + List<String> indicatorList = request.getCommunityIndicatorList(); - if (log.isDebugEnabled()) { - log.debug("Searching list for indicator : " + indicator); - } + boolean result = false; - int multiplicator = 1; - int minYear = Integer.MAX_VALUE; - int maxYear = Integer.MIN_VALUE; - boolean indicatorFound = false; - Map<Integer, Double[]> graphData = new HashMap<Integer, Double[]>(); Iterator<String[]> iterator = loadCommunityIndicatorStorage(true); while (iterator.hasNext()) { - // Campagne Indicateur Liste Strate Annee Estimation EcartType CV String[] tuple = iterator.next(); - String indicatorList = tuple[2]; - - if (matchCommunityIndicator(tuple, indicator)) { - indicatorFound = true; - - // si pas de list selectionnée, on prend la premiere - if (StringUtils.isBlank(localList)) { - localList = indicatorList; - } - - if (indicatorList.equals(localList)) { - Double estimation = Double.parseDouble(tuple[5]); - Double ecart = Double.parseDouble(tuple[6]); - int year = Integer.parseInt(tuple[4]); - - if (year < minYear) { - minYear = year; - } - if (year > maxYear) { - maxYear = year; - } - graphData.put(year, new Double[]{estimation, ecart}); - - // si les données sont énormes, on affiche les données - // / multiplicator et on le mentionne dans la légende - if (estimation > 1e9) { - multiplicator = 1000000; - } - if (estimation > 1e6 && multiplicator < 1000000) { - multiplicator = 1000; - } - } + if (matchIndicatorList(tuple, indicatorList)) { + result = true; + break; } } + return result; + } - File result = null; + protected boolean matchPopulationIndicatorList(ExtractRequest request) { + Preconditions.checkNotNull(request.getPopulationIndicatorList()); - // avec l'extraction des données, on peut demander a générer un graphique - // sur un indicateur qui n'est pas présent dans le projet courant, - // dans ce cas, on retourne null - if (indicatorFound) { + List<String> indicatorList = request.getPopulationIndicatorList(); - String zoneDisplayName = getZonesMap().getZoneFullName(zone); - String indicatorName = getIndicatorsMap().getIndicatorValue(indicator, locale); - String unit = getIndicatorsMap().getIndicatorUnit(indicator); + boolean result = false; - // get graph title - String chartTitle = zoneDisplayName; - chartTitle += " - " + indicatorName; - - // ajout de la traduction de la liste d'indicateur - // les liste sont a1, T1, T2 ... - String listLetter = String.valueOf(localList.charAt(0)); - Iterator<String[]> typeIterator = loadSpeciesFileStorage(true); - while (typeIterator.hasNext()) { - // "Types";"Commentaire";"NumSys min";"NumSys max";"Code" - String[] tuple = typeIterator.next(); - if (tuple[4].equals(listLetter)) { - /// gestion du groupe "Tous" - // cas special, c'est la seule valeur du fichier - // code type espece qui a besoin d'une traduction - if (tuple[4].equalsIgnoreCase("T")) { - if ("fr".equals(locale.getLanguage())) { - chartTitle += " - " + "Tous Liste " + localList.charAt(1); - } else if ("es".equals(locale.getLanguage())) { - chartTitle += " - " + "Todo Lista " + localList.charAt(1); - } else { - chartTitle += " - " + "All List " + localList.charAt(1); - } - } else { - // ajout de la traduction du nom de liste plus le numéro - if ("fr".equals(locale.getLanguage())) { - chartTitle += " - " + tuple[0] + " Liste " + localList.charAt(1); - } else if ("es".equals(locale.getLanguage())) { - chartTitle += " - " + tuple[0] + " Lista " + localList.charAt(1); - } else { - chartTitle += " - " + tuple[0] + " List " + localList.charAt(1); - } - } - break; - } + Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + if (matchIndicatorList(tuple, indicatorList)) { + result = true; + break; } - - // generate dataset with sorted data - DefaultStatisticalCategoryDataset statisticalDataset = new DefaultStatisticalCategoryDataset(); - for (int indexYear = minYear; indexYear <= maxYear; ++indexYear) { - Double[] entry = graphData.get(indexYear); - if (entry != null) { - Double estimation = entry[0] / multiplicator; - Double ecart = entry[1] / multiplicator; - statisticalDataset.add(estimation, ecart, "Serie1", (Comparable) indexYear); - } else { - statisticalDataset.add(null, null, "Serie1", indexYear); - } - } - - // configure chart - //CategoryAxis categoryAxis = new CategoryAxis(t("coser.business.common.year")); - String yearAxis = Reports.getYearChartTitle(locale); - - CategoryAxis categoryAxis = new CategoryAxis(yearAxis); - categoryAxis.setCategoryMargin(0); - categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); - // label horizontaux - String legendY = indicatorName; - if (multiplicator != 1) { - // affiche par exemple : cm * 1000 - legendY += " (" + unit + "*" + multiplicator + ")"; - } else if (StringUtils.isNotEmpty(unit)) { - legendY += " (" + unit + ")"; - } - ValueAxis valueAxis = new NumberAxis(legendY); - valueAxis.setUpperMargin(0.1); - - CategoryItemRenderer renderer = new StatisticalLineAndShapeRenderer(false, true); - - // n'affiche pas les nombre sur le graphique - //StandardCategoryItemLabelGenerator itemLabelGenerator = new StandardCategoryItemLabelGenerator(); - //renderer.setBaseItemLabelGenerator(itemLabelGenerator); - //renderer.setBaseItemLabelsVisible(true); - - CategoryPlot plot = new CategoryPlot(statisticalDataset, categoryAxis, valueAxis, renderer); - plot.setOrientation(PlotOrientation.VERTICAL); - JFreeChart chart = new JFreeChart(chartTitle, - JFreeChart.DEFAULT_TITLE_FONT, plot, true); - - // remove series legend - chart.removeLegend(); - // white background - chart.setBackgroundPaint(Color.WHITE); - - try { - result = File.createTempFile("coser-chart-community-indicator-", ".png"); - result.deleteOnExit(); - ChartUtilities.saveChartAsPNG(result, chart, 800, 400); - } catch (IOException ex) { - throw new CoserTechnicalException("Can't save chart", ex); - } } - return result; } - // --------------------------------------------------------------------- // - // --- Get Population indicator result --------------------------------- // - // --------------------------------------------------------------------- // + protected boolean matchPopulationIndicatorListAndSpeciesList(ExtractRequest request) { + Preconditions.checkNotNull(request.getPopulationIndicatorList()); - protected File getPopulationIndicatorDataFile(String species, String indicator) { + List<String> indicatorList = request.getPopulationIndicatorList(); + List<String> speciesList = request.getSpeciesList(); - DataStorage dataStorage = new MemoryDataStorage(); + boolean result = false; - Iterator<String[]> iterator = loadPopulationIndicatorStorage(false); - - // add header - dataStorage.add(iterator.next()); - + Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); while (iterator.hasNext()) { String[] tuple = iterator.next(); - if (matchPopulationSpeciesAndIndicator(tuple, species, indicator)) { - dataStorage.add(tuple); + if (matchIndicatorListAndSpeciesList(tuple, indicatorList, speciesList)) { + result = true; + break; } } - File result = DataStorages.save("coser-chart-population-indicator", - ".csv", - dataStorage); return result; } - protected File getPopulationIndicatorGraphFile(Locale locale, String zone, String species, String indicator) { + protected boolean matchCommunityIndicatorListAndSpeciesList(ExtractRequest request) { + Preconditions.checkNotNull(request.getCommunityIndicatorList()); + List<String> indicatorList = request.getCommunityIndicatorList(); + List<String> speciesList = request.getSpeciesList(); - int multiplicator = 1; - int minYear = Integer.MAX_VALUE; - int maxYear = Integer.MIN_VALUE; - boolean indicatorFound = false; - Map<Integer, Double[]> graphData = new HashMap<Integer, Double[]>(); - Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); + boolean result = false; + + Iterator<String[]> iterator = loadCommunityIndicatorStorage(true); while (iterator.hasNext()) { String[] tuple = iterator.next(); - - if (matchPopulationSpeciesAndIndicator(tuple, species, indicator)) { - indicatorFound = true; - - // XXX echatellier, maybe take care of list here ? - - Double estimation = Double.parseDouble(tuple[6]); - Double ecart = Double.parseDouble(tuple[7]); - int year = Integer.parseInt(tuple[5]); - - if (year < minYear) { - minYear = year; - } - if (year > maxYear) { - maxYear = year; - } - graphData.put(year, new Double[]{estimation, ecart}); - - // si les données sont énormes, on affiche les données - // / multiplicator et on le mentionne dans la légende - if (estimation > 1e9) { - multiplicator = 1000000; - } - if (estimation > 1e6 && multiplicator < 1000000) { - multiplicator = 1000; - } + if (matchIndicatorListAndSpeciesList(tuple, indicatorList, speciesList)) { + result = true; + break; } } + return result; + } - File result = null; + protected boolean matchIndicatorList(String[] tuple, List<String> indicatorList) { + String indicatorCode = tuple[1]; + boolean result = indicatorList.contains(indicatorCode); + return result; + } - // avec l'extraction des données, on peut demander a générer un graphique - // sur un indicateur qui n'est pas présent dans le projet courant, - // dans ce cas, on retourne null - if (indicatorFound) { + protected boolean matchIndicatorListAndSpeciesList(String[] tuple, + List<String> indicatorList, + List<String> speciesList) { + String indicatorCode = tuple[1]; + String speciesCode = tuple[3]; + boolean result = indicatorList.contains(indicatorCode) && + speciesList.contains(speciesCode); + return result; + } - String zoneDisplayName = getZonesMap().getZoneFullName(zone); - String indicatorName = getIndicatorsMap().getIndicatorValue(indicator, locale); - String unit = getIndicatorsMap().getIndicatorUnit(indicator); + // --------------------------------------------------------------------- // + // --- Get Map result -------------------------------------------------- // + // --------------------------------------------------------------------- // - // get graph title - String title = zoneDisplayName; - title += " - " + indicatorName; - title += " - " + Reports.getReportDisplayName(loadSpeciesFileStorage(true), species); + protected File getMapSpeciesFile(String species) { + String fileName = speciesCodeToMapFile.apply(species); + File file = fileName == null ? null : new File(mapsDirectory, fileName); + return file; + } - // generate dataset with sorted data - DefaultStatisticalCategoryDataset statisticalDataset = new DefaultStatisticalCategoryDataset(); - for (int indexYear = minYear; indexYear <= maxYear; ++indexYear) { - Double[] entry = graphData.get(indexYear); - if (entry != null) { - Double estimation = entry[0] / multiplicator; - Double ecart = entry[1] / multiplicator; - statisticalDataset.add(estimation, ecart, "Serie1", (Comparable) indexYear); - } else { - statisticalDataset.add(null, null, "Serie1", indexYear); - } - } + // --------------------------------------------------------------------- // + // --- Get species lists ----------------------------------------------- // + // --------------------------------------------------------------------- // - // configure chart - //CategoryAxis categoryAxis = new CategoryAxis(t("coser.business.common.year")); - String yearAxis = Reports.getYearChartTitle(locale); - CategoryAxis categoryAxis = new CategoryAxis(yearAxis); - categoryAxis.setCategoryMargin(0); - categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); - // label horizontaux - String legendY = indicatorName; - if (multiplicator != 1) { - // affiche par exemple : cm * 1000 - legendY += " (" + unit + "*" + multiplicator + ")"; - } else if (StringUtils.isNotEmpty(unit)) { - legendY += " (" + unit + ")"; - } - ValueAxis valueAxis = new NumberAxis(legendY); - valueAxis.setUpperMargin(0.1); + protected Map<String, String> getPopulationIndicatorSpecies() { + Map<String, String> result = Maps.newHashMap(); - CategoryItemRenderer renderer = new StatisticalLineAndShapeRenderer(false, true); + SpeciesMap speciesNames = getSpeciesMap(); + Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + String speciesCode = tuple[3]; - // n'affiche pas les nombre sur le graphique - //StandardCategoryItemLabelGenerator itemLabelGenerator = new StandardCategoryItemLabelGenerator(); - //renderer.setBaseItemLabelGenerator(itemLabelGenerator); - //renderer.setBaseItemLabelsVisible(true); + String speciesName = speciesNames.getSpeciesName(speciesCode); - CategoryPlot plot = new CategoryPlot(statisticalDataset, categoryAxis, valueAxis, renderer); - plot.setOrientation(PlotOrientation.VERTICAL); - JFreeChart chart = new JFreeChart(title, - JFreeChart.DEFAULT_TITLE_FONT, plot, true); - - // remove series legend - chart.removeLegend(); - // white background - chart.setBackgroundPaint(Color.WHITE); - - try { - result = File.createTempFile("coser-chart-population-indicator-", ".png"); - result.deleteOnExit(); - ChartUtilities.saveChartAsPNG(result, chart, 800, 400); - } catch (IOException ex) { - throw new CoserTechnicalException("Can't save chart", ex); + if (StringUtils.isNotEmpty(speciesName)) { + result.put(speciesCode, speciesName); } + result.put(speciesCode, speciesName); } - return result; } - // --------------------------------------------------------------------- // - // --- Get species lists ----------------------------------------------- // - // --------------------------------------------------------------------- // - - protected Map<String, String> getPopulationIndicatorSpecies() { + protected Map<String, String> getCommunityIndicatorSpecies() { Map<String, String> result = Maps.newHashMap(); - Map<String, String> speciesNames = getSpeciesMap(); - Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); + SpeciesMap speciesNames = getSpeciesMap(); + Iterator<String[]> iterator = loadCommunityIndicatorStorage(true); while (iterator.hasNext()) { String[] tuple = iterator.next(); String speciesCode = tuple[3]; - String speciesName = speciesNames.get(speciesCode); + String speciesName = speciesNames.getSpeciesName(speciesCode); if (StringUtils.isNotEmpty(speciesName)) { result.put(speciesCode, speciesName); @@ -1093,40 +638,7 @@ if (matchCommunityIndicator(tuple, indicator)) { String list = tuple[2]; - // recherche de la traduction de l'id de liste - // les liste sont a1, T1, T2 ... - String listLetter = String.valueOf(list.charAt(0)); - String translation = "## " + list + " not found ##"; - Iterator<String[]> typeIterator = loadSpeciesListFileStorage(true); - while (typeIterator.hasNext()) { - // "Types";"Commentaire";"NumSys min";"NumSys max";"Code" - String[] tupleType = typeIterator.next(); - if (tupleType[4].equals(listLetter)) { - - // gestion du groupe "Tous" - // cas special, c'est la seule valeur du fichier - // code type espece qui a besoin d'une traduction - if (tupleType[4].equalsIgnoreCase("T")) { - if (locale != null && "fr".equals(locale.getLanguage())) { - translation = "Tous Liste " + list.charAt(1); - } else if (locale != null && "en".equals(locale.getLanguage())) { - translation = "Todo Lista " + list.charAt(1); - } else { - translation = "All List " + list.charAt(1); - } - } else { - // ajout de la traduction du nom de liste plus le numéro - if (locale != null && "fr".equals(locale.getLanguage())) { - translation = tupleType[0] + " Liste " + list.charAt(1); - } else if (locale != null && "en".equals(locale.getLanguage())) { - translation = tupleType[0] + " Lista " + list.charAt(1); - } else { - translation = tupleType[0] + " List " + list.charAt(1); - } - } - break; - } - } + String translation = getSpeciesListMap().getSpeciesListName(locale, list); result.put(list, translation); } } @@ -1148,12 +660,23 @@ return result; } + protected Set<String> getPopulationIndicators() { + Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); + Set<String> result = Sets.newHashSet(); + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + String indicatorCode = tuple[1]; + result.add(indicatorCode); + } + return result; + } + protected Set<String> getPopulationIndicators(String species) { Iterator<String[]> iterator = loadPopulationIndicatorStorage(true); Set<String> result = Sets.newHashSet(); while (iterator.hasNext()) { String[] tuple = iterator.next(); - if (species == null || matchPopulationSpecies(tuple, species)) { + if (matchPopulationSpecies(tuple, species)) { String indicatorCode = tuple[1]; result.add(indicatorCode); } @@ -1162,45 +685,26 @@ } // --------------------------------------------------------------------- // - // --- Get species definition maps ------------------------------------- // + // --- Get definition maps --------------------------------------------- // // --------------------------------------------------------------------- // - protected Map<String, String> getSpeciesMap() { - if (speciesMap == null) { - speciesMap = Maps.newTreeMap(); - - // load species file - Iterator<String[]> iterator = loadSpeciesFileStorage(true); - while (iterator.hasNext()) { - String[] tuple = iterator.next(); - String speciesCode = tuple[3]; - String speciesLabel = tuple[4] + " " + tuple[5]; - speciesMap.put(speciesCode, speciesLabel); - } + public SpeciesListMap getSpeciesListMap() { + if (speciesListMap == null) { + File file = new File(basedir, CoserConstants.Category.TYPE_ESPECES.getStorageFileName()); + speciesListMap = new SpeciesListMap(file); } - return speciesMap; + return speciesListMap; } - protected Map<String, String> getSpeciesSubMap(Collection<String> speciesList) { + protected SpeciesMap getSpeciesMap() { + if (speciesMap == null) { - Map<String, String> result = Maps.newTreeMap(); - - if (speciesList != null) { - - Map<String, String> map = getSpeciesMap(); - for (String species : speciesList) { - String speciesLabel = map.get(species); - result.put(species, speciesLabel); - } + File file = new File(basedir, CoserConstants.Category.REFTAX_SPECIES.getStorageFileName()); + speciesMap = new SpeciesMap(file); } - - return result; + return speciesMap; } - // --------------------------------------------------------------------- // - // --- Get indicator definition maps ----------------------------------- // - // --------------------------------------------------------------------- // - protected IndicatorMap getIndicatorsMap() { if (indicatorsMap == null) { indicatorsMap = new IndicatorMap(config.getWebIndicatorsFile()); @@ -1208,10 +712,6 @@ return indicatorsMap; } - // --------------------------------------------------------------------- // - // --- Get zone definition maps ---------------------------------------- // - // --------------------------------------------------------------------- // - public ZoneMap getZonesMap() { if (zonesMap == null) { zonesMap = new ZoneMap(config.getWebZonesFile()); @@ -1239,16 +739,4 @@ return iterator; } - protected Iterator<String[]> loadSpeciesFileStorage(boolean skipFirstLine) { - // "C_Perm","NumSys","NivSys","C_VALIDE","L_VALIDE","AA_VALIDE","C_TxP\u00E8re","Taxa" - Iterator<String[]> iterator = path.getProject().getRefTaxSpecies().iterator(skipFirstLine); - return iterator; - } - - protected Iterator<String[]> loadSpeciesListFileStorage(boolean skipFirstLine) { - // "Types";"Commentaire";"NumSys min";"NumSys max";"Code" - Iterator<String[]> iterator = path.getProject().getTypeEspeces().iterator(skipFirstLine); - return iterator; - } - } Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/MapResultProducer.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/MapResultProducer.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/MapResultProducer.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,106 @@ +package fr.ifremer.coser.result.repository.legacy; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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 com.google.common.base.Preconditions; +import fr.ifremer.coser.bean.RSufiResultPath; +import fr.ifremer.coser.bean.ZoneMap; +import fr.ifremer.coser.result.FileResult; +import fr.ifremer.coser.result.repository.RequestUnavailableForProducerException; +import fr.ifremer.coser.result.repository.ResultProducer; +import fr.ifremer.coser.result.request.MapRequest; + +import java.io.File; +import java.util.List; +import java.util.Map; + +/** + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class MapResultProducer implements ResultProducer<MapRequest> { + + protected final LegacyResultRepository repository; + + protected final RSufiResultPath path; + + public MapResultProducer(LegacyResultRepository repository) { + this.repository = repository; + this.path = repository.path; + } + + @Override + public LegacyResultRepository getRepository() { + return repository; + } + + @Override + public Map<String, String> getAvailableZones(MapRequest request) { + Preconditions.checkNotNull(request.getFacade()); + + boolean match = repository.matchFacade(request); + + Map<String, String> result = null; + if (match) { + ZoneMap zonesMap = repository.getZonesMap(); + List<String> allowedZones = zonesMap.getZonesForFacade(request.getFacade()); + result = zonesMap.getSubZonesMap(path.getRsufiResult().getZone(), allowedZones); + } + return result; + } + + @Override + public Map<String, String> getAvailableSpecies(MapRequest request) { + Preconditions.checkNotNull(request.getFacade()); + Preconditions.checkNotNull(request.getZone()); + + Map<String, String> result = null; + + boolean match = repository.mapsResult && + repository.matchFacade(request) && + repository.matchZone(request); + if (match) { + + // get all map species for given facade + zone + result = repository.getPopulationIndicatorSpecies(); + } + return result; + } + + @Override + public Map<String, String> getAvailableIndicators(MapRequest request) { + throw RequestUnavailableForProducerException.newException("getAvailableIndicators", this); + } + + @Override + public FileResult produceResult(MapRequest r) { + + File resultZip = repository.getMapSpeciesFile(r.getSpecies()); + + FileResult result = new FileResult(repository.getId(), resultZip); + return result; + } + +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/MapResultProducer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/PopulationIndicatorResultProducer.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/PopulationIndicatorResultProducer.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/PopulationIndicatorResultProducer.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,308 @@ +package fr.ifremer.coser.result.repository.legacy; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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 com.google.common.base.Preconditions; +import fr.ifremer.coser.CoserTechnicalException; +import fr.ifremer.coser.bean.RSufiResultPath; +import fr.ifremer.coser.bean.ZoneMap; +import fr.ifremer.coser.result.FileResult; +import fr.ifremer.coser.result.Reports; +import fr.ifremer.coser.result.repository.ResultProducer; +import fr.ifremer.coser.result.request.PopulationIndicatorRequest; +import fr.ifremer.coser.storage.DataStorage; +import fr.ifremer.coser.storage.DataStorages; +import fr.ifremer.coser.storage.MemoryDataStorage; +import org.apache.commons.lang3.StringUtils; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.CategoryItemRenderer; +import org.jfree.chart.renderer.category.StatisticalLineAndShapeRenderer; +import org.jfree.data.statistics.DefaultStatisticalCategoryDataset; + +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class PopulationIndicatorResultProducer implements ResultProducer<PopulationIndicatorRequest> { + + protected final LegacyResultRepository repository; + + protected final Reports reports; + + protected final RSufiResultPath path; + + protected final File basedir; + + protected final String surveyName; + + public PopulationIndicatorResultProducer(LegacyResultRepository repository) { + this.repository = repository; + this.path = repository.path; + this.reports = repository.reports; + this.basedir = repository.basedir; + this.surveyName = repository.surveyName; + } + + @Override + public LegacyResultRepository getRepository() { + return repository; + } + + @Override + public Map<String, String> getAvailableZones(PopulationIndicatorRequest request) { + Preconditions.checkNotNull(request.getFacade()); + + boolean match = repository.matchFacade(request); + + Map<String, String> result = null; + if (match) { + ZoneMap zonesMap = repository.getZonesMap(); + List<String> allowedZones = zonesMap.getZonesForFacade(request.getFacade()); + result = zonesMap.getSubZonesMap(path.getRsufiResult().getZone(), allowedZones); + } + return result; + } + + @Override + public Map<String, String> getAvailableSpecies(PopulationIndicatorRequest request) { + Preconditions.checkNotNull(request.getFacade()); + Preconditions.checkNotNull(request.getZone()); + + Map<String, String> result = null; + + boolean match = repository.indicatorsResult && + repository.matchFacade(request) && + repository.matchZone(request); + + if (match) { + // get all population indicator species for given facade + zone + result = repository.getPopulationIndicatorSpecies(); + } + return result; + } + + @Override + public Map<String, String> getAvailableIndicators(PopulationIndicatorRequest request) { + Preconditions.checkNotNull(request.getFacade()); + Preconditions.checkNotNull(request.getZone()); + Preconditions.checkNotNull(request.getSpecies()); + + Map<String, String> result = null; + + boolean match = repository.indicatorsResult && + repository.matchFacade(request) && + repository.matchZone(request) && + repository.matchSpecies(request); + + if (match) { + + // get all indicators for given facade + zone + species + Set<String> indicatorList = repository.getPopulationIndicators(request.getSpecies()); + result = repository.getIndicatorsMap().getIndicatorsValues(indicatorList, request.getLocale()); + } + + return result; + } + + @Override + public FileResult produceResult(PopulationIndicatorRequest request) { + + File file = null; + switch (request.getResultType()) { + case DATA: + file = getPopulationIndicatorDataFile(request.getIndicator(), + request.getSpecies()); + break; + + case GRAPH: + file = getPopulationIndicatorGraphFile(request.getLocale(), + request.getZone(), + request.getIndicator(), + request.getSpecies()); + break; + } + + + FileResult result = new FileResult(repository.getId(), file); + return result; + } + + protected File getPopulationIndicatorDataFile(String species, String indicator) { + + DataStorage dataStorage = new MemoryDataStorage(); + + Iterator<String[]> iterator = repository.loadPopulationIndicatorStorage(false); + + // add header + dataStorage.add(iterator.next()); + + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + if (repository.matchPopulationSpeciesAndIndicator(tuple, species, indicator)) { + dataStorage.add(tuple); + } + } + File result = DataStorages.save(dataStorage, "coser-chart-population-indicator", + ".csv" + ); + return result; + } + + protected File getPopulationIndicatorGraphFile(Locale locale, + String zone, + String species, + String indicator) { + + + int multiplicator = 1; + int minYear = Integer.MAX_VALUE; + int maxYear = Integer.MIN_VALUE; + boolean indicatorFound = false; + Map<Integer, Double[]> graphData = new HashMap<Integer, Double[]>(); + Iterator<String[]> iterator = repository.loadPopulationIndicatorStorage(true); + while (iterator.hasNext()) { + String[] tuple = iterator.next(); + + if (repository.matchPopulationSpeciesAndIndicator(tuple, species, indicator)) { + indicatorFound = true; + + // XXX echatellier, maybe take care of list here ? + + Double estimation = Double.parseDouble(tuple[6]); + Double ecart = Double.parseDouble(tuple[7]); + int year = Integer.parseInt(tuple[5]); + + if (year < minYear) { + minYear = year; + } + if (year > maxYear) { + maxYear = year; + } + graphData.put(year, new Double[]{estimation, ecart}); + + // si les données sont énormes, on affiche les données + // / multiplicator et on le mentionne dans la légende + if (estimation > 1e9) { + multiplicator = 1000000; + } + if (estimation > 1e6 && multiplicator < 1000000) { + multiplicator = 1000; + } + } + } + + File result = null; + + // avec l'extraction des données, on peut demander a générer un graphique + // sur un indicateur qui n'est pas présent dans le projet courant, + // dans ce cas, on retourne null + if (indicatorFound) { + + String zoneDisplayName = repository.getZonesMap().getZoneFullName(zone); + String indicatorName = repository.getIndicatorsMap().getIndicatorValue(indicator, locale); + String unit = repository.getIndicatorsMap().getIndicatorUnit(indicator); + + // get graph title + String title = zoneDisplayName; + title += " - " + indicatorName; + title += " - " + repository.getSpeciesMap().getReportDisplayName(species); + + // generate dataset with sorted data + DefaultStatisticalCategoryDataset statisticalDataset = new DefaultStatisticalCategoryDataset(); + for (int indexYear = minYear; indexYear <= maxYear; ++indexYear) { + Double[] entry = graphData.get(indexYear); + if (entry != null) { + Double estimation = entry[0] / multiplicator; + Double ecart = entry[1] / multiplicator; + statisticalDataset.add(estimation, ecart, "Serie1", (Comparable) indexYear); + } else { + statisticalDataset.add(null, null, "Serie1", indexYear); + } + } + + // configure chart + //CategoryAxis categoryAxis = new CategoryAxis(t("coser.business.common.year")); + String yearAxis = reports.getYearChartTitle(locale); + CategoryAxis categoryAxis = new CategoryAxis(yearAxis); + categoryAxis.setCategoryMargin(0); + categoryAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); + // label horizontaux + String legendY = indicatorName; + if (multiplicator != 1) { + // affiche par exemple : cm * 1000 + legendY += " (" + unit + "*" + multiplicator + ")"; + } else if (StringUtils.isNotEmpty(unit)) { + legendY += " (" + unit + ")"; + } + ValueAxis valueAxis = new NumberAxis(legendY); + valueAxis.setUpperMargin(0.1); + + CategoryItemRenderer renderer = new StatisticalLineAndShapeRenderer(false, true); + + // n'affiche pas les nombre sur le graphique + //StandardCategoryItemLabelGenerator itemLabelGenerator = new StandardCategoryItemLabelGenerator(); + //renderer.setBaseItemLabelGenerator(itemLabelGenerator); + //renderer.setBaseItemLabelsVisible(true); + + CategoryPlot plot = new CategoryPlot(statisticalDataset, categoryAxis, valueAxis, renderer); + plot.setOrientation(PlotOrientation.VERTICAL); + JFreeChart chart = new JFreeChart(title, + JFreeChart.DEFAULT_TITLE_FONT, plot, true); + + // remove series legend + chart.removeLegend(); + // white background + chart.setBackgroundPaint(Color.WHITE); + + try { + result = File.createTempFile("coser-chart-population-indicator-", ".png"); + result.deleteOnExit(); + ChartUtilities.saveChartAsPNG(result, chart, 800, 400); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't save chart", ex); + } + } + + return result; + } + +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/PopulationIndicatorResultProducer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/RawDataResultProducer.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/RawDataResultProducer.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/RawDataResultProducer.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,163 @@ +package fr.ifremer.coser.result.repository.legacy; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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 fr.ifremer.coser.CoserBusinessConfig; +import fr.ifremer.coser.CoserBusinessException; +import fr.ifremer.coser.CoserConstants; +import fr.ifremer.coser.CoserTechnicalException; +import fr.ifremer.coser.bean.Project; +import fr.ifremer.coser.bean.RSufiResultPath; +import fr.ifremer.coser.bean.Selection; +import fr.ifremer.coser.bean.ZoneMap; +import fr.ifremer.coser.result.FileResult; +import fr.ifremer.coser.result.Reports; +import fr.ifremer.coser.result.repository.RequestUnavailableForProducerException; +import fr.ifremer.coser.result.repository.ResultProducer; +import fr.ifremer.coser.result.request.RawDataRequest; +import fr.ifremer.coser.services.ProjectService; +import org.apache.commons.io.FileUtils; +import org.nuiton.util.FileUtil; +import org.nuiton.util.ZipUtil; + +import java.io.File; +import java.io.IOException; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * Created on 3/11/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class RawDataResultProducer implements ResultProducer<RawDataRequest> { + + protected final LegacyResultRepository repository; + + protected final Reports reports; + + protected final RSufiResultPath path; + + protected final File basedir; + + protected final ProjectService projectService; + + private CoserBusinessConfig config; + + private String surveyName; + + public RawDataResultProducer(LegacyResultRepository repository) { + this.repository = repository; + this.path = repository.path; + this.reports = repository.reports; + this.projectService = repository.projectService; + this.basedir = repository.basedir; + this.config = repository.config; + this.surveyName = repository.surveyName; + } + + @Override + public LegacyResultRepository getRepository() { + return repository; + } + + @Override + public Map<String, String> getAvailableZones(RawDataRequest request) { + boolean match = repository.matchFacade(request); + + Map<String, String> result = null; + if (match) { + ZoneMap zonesMap = repository.getZonesMap(); + List<String> allowedZones = zonesMap.getZonesForFacade(request.getFacade()); + result = zonesMap.getSubZonesMap(path.getRsufiResult().getZone(), allowedZones); + } + return result; + } + + @Override + public Map<String, String> getAvailableSpecies(RawDataRequest request) { + throw RequestUnavailableForProducerException.newException("getAvailableSpecies", this); + } + + @Override + public Map<String, String> getAvailableIndicators(RawDataRequest request) { + throw RequestUnavailableForProducerException.newException("getAvailableIndicators", this); + } + + @Override + public FileResult produceResult(RawDataRequest r) { + + Locale locale = r.getLocale(); + + Project project = path.getProject(); + Selection selection = path.getSelection(); + try { + // be sure that data are available for this project + // or it will fail + projectService.loadSelectionData(basedir.getParentFile(), project, selection); + } catch (CoserBusinessException e) { + throw new CoserTechnicalException("Could not load project selection", e); + } + + File resultZip; + + try { + File tempDir = FileUtil.createTempDirectory("coser-source-", "-tmp"); + + // il ne faut pas les fichiers de selection, mais leurs + // export rsufi (sans les lignes, et les quotes) + File archiveDir = projectService.extractRSUfiData(project, selection, tempDir, true); + + // add decharge file + String filename = reports.getDechargeFilename(locale); + File dechargePDF = new File(archiveDir, filename); + + Date lastDataUpdateDate = config.getLastDataUpdateDate(); + + reports.generateDechargePDF(dechargePDF, locale, lastDataUpdateDate, surveyName); + + // ajout du reftax dans le zip + File reftaxFile = new File(basedir, CoserConstants.Category.REFTAX_SPECIES.getStorageFileName()); + FileUtils.copyFileToDirectory(reftaxFile, archiveDir); + + // make zip + resultZip = File.createTempFile("coser-source-", ".zip"); + resultZip.deleteOnExit(); + ZipUtil.compress(resultZip, archiveDir); + + // clean directory + FileUtils.deleteDirectory(tempDir); + } catch (IOException e) { + throw new CoserTechnicalException("Can't create zip file", e); + } catch (CoserBusinessException e) { + throw new CoserTechnicalException("Can't create zip file", e); + } + + FileResult result = new FileResult(repository.getId(), resultZip); + return result; + } + +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/repository/legacy/RawDataResultProducer.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/CoserRequestBuilder.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/CoserRequestBuilder.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/CoserRequestBuilder.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -23,7 +23,10 @@ */ import fr.ifremer.coser.result.CoserRequest; +import fr.ifremer.coser.util.DataType; +import org.apache.commons.collections4.CollectionUtils; +import java.util.List; import java.util.Locale; /** @@ -48,6 +51,16 @@ protected IndicatorRequest.ResultType resultType; + protected List<DataType> extractTypeList; + + protected List<String> zoneList; + + protected List<String> speciesList; + + protected List<String> populationIndicatorList; + + protected List<String> communityIndicatorList; + public CoserRequestBuilder(Locale locale) { this.locale = locale; } @@ -77,6 +90,31 @@ return this; } + public CoserRequestBuilder addExtractTypeList(List<DataType> extractTypeSet) { + this.extractTypeList = extractTypeSet; + return this; + } + + public CoserRequestBuilder addZoneList(List<String> zoneList) { + this.zoneList = zoneList; + return this; + } + + public CoserRequestBuilder addSpeciesList(List<String> speciesList) { + this.speciesList = speciesList; + return this; + } + + public CoserRequestBuilder addPopulationIndicatorList(List<String> populationIndicatorList) { + this.populationIndicatorList = populationIndicatorList; + return this; + } + + public CoserRequestBuilder addCommunityIndicatorList(List<String> communityIndicatorList) { + this.communityIndicatorList = communityIndicatorList; + return this; + } + public MapRequest toMapRequest() { MapRequest request = new MapRequest(); flush(request); @@ -101,6 +139,12 @@ return request; } + public ExtractRequest toExtractRequest() { + ExtractRequest request = new ExtractRequest(); + flush(request); + return request; + } + protected <R extends CoserRequest> void flush(R request) { request.setLocale(locale); if (request instanceof CoserRequestFacadeAware) { @@ -127,6 +171,25 @@ ((IndicatorRequest) request).setResultType(resultType); } } + + if (request instanceof ExtractRequest) { + if (CollectionUtils.isNotEmpty(extractTypeList)) { + ((ExtractRequest) request).setExtractTypeList(extractTypeList); + } + if (CollectionUtils.isNotEmpty(zoneList)) { + ((ExtractRequest) request).setZoneList(zoneList); + } + if (CollectionUtils.isNotEmpty(populationIndicatorList)) { + ((ExtractRequest) request).setPopulationIndicatorList(populationIndicatorList); + } + if (CollectionUtils.isNotEmpty(communityIndicatorList)) { + ((ExtractRequest) request).setCommunityIndicatorList(communityIndicatorList); + } + if (CollectionUtils.isNotEmpty(speciesList)) { + ((ExtractRequest) request).setSpeciesList(speciesList); + } + + } } } Added: trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/ExtractRequest.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/ExtractRequest.java (rev 0) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/ExtractRequest.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,122 @@ +package fr.ifremer.coser.result.request; + +/* + * #%L + * Coser :: Business + * %% + * Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + * %% + * 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 com.google.common.base.Preconditions; +import fr.ifremer.coser.result.CoserRequest; +import fr.ifremer.coser.util.DataType; +import org.apache.commons.collections4.CollectionUtils; + +import java.util.List; +import java.util.Locale; + +/** + * Request to extract data. + * <p/> + * Created on 3/9/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 1.5 + */ +public class ExtractRequest implements CoserRequest { + + private static final long serialVersionUID = 1L; + + protected Locale locale; + + protected List<String> zoneList; + + protected List<String> populationIndicatorList; + + protected List<String> communityIndicatorList; + + protected List<String> speciesList; + + protected List<DataType> extractTypeList; + + @Override + public Locale getLocale() { + return locale; + } + + @Override + public void setLocale(Locale locale) { + Preconditions.checkNotNull(locale); + this.locale = locale; + } + + @Override + public boolean isFilled() { + return !(locale == null || + CollectionUtils.isEmpty(extractTypeList) || + CollectionUtils.isEmpty(zoneList) || + CollectionUtils.isEmpty(populationIndicatorList) || + CollectionUtils.isEmpty(communityIndicatorList) || + CollectionUtils.isEmpty(speciesList)); + } + + public List<DataType> getExtractTypeList() { + return extractTypeList; + } + + public void setExtractTypeList(List<DataType> extractTypeSet) { + Preconditions.checkArgument(CollectionUtils.isNotEmpty(extractTypeSet)); + this.extractTypeList = extractTypeSet; + } + + public List<String> getZoneList() { + return zoneList; + } + + public void setZoneList(List<String> zoneList) { + Preconditions.checkArgument(CollectionUtils.isNotEmpty(zoneList)); + this.zoneList = zoneList; + } + + public List<String> getPopulationIndicatorList() { + return populationIndicatorList; + } + + public void setPopulationIndicatorList(List<String> populationIndicatorList) { + Preconditions.checkArgument(CollectionUtils.isNotEmpty(populationIndicatorList)); + this.populationIndicatorList = populationIndicatorList; + } + + public List<String> getCommunityIndicatorList() { + return communityIndicatorList; + } + + public void setCommunityIndicatorList(List<String> communityIndicatorList) { + Preconditions.checkArgument(CollectionUtils.isNotEmpty(communityIndicatorList)); + this.communityIndicatorList = communityIndicatorList; + } + + public List<String> getSpeciesList() { + return speciesList; + } + + public void setSpeciesList(List<String> speciesList) { + Preconditions.checkArgument(CollectionUtils.isNotEmpty(speciesList)); + this.speciesList = speciesList; + } +} Property changes on: trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/ExtractRequest.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/IndicatorRequest.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/IndicatorRequest.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/result/request/IndicatorRequest.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -109,6 +109,7 @@ } public void setIndicator(String indicator) { + Preconditions.checkNotNull(indicator); this.indicator = indicator; } Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/storage/DataStorages.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/storage/DataStorages.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/storage/DataStorages.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -113,12 +113,12 @@ * his name is generated then using the {@link File#createTempFile(String, String)} using the given {@code prefix} * and {@code suffix}. * + * @param dataStorage the storage to save * @param prefix prefix of generated file name * @param suffix suffix of generated file name - * @param dataStorage the storage to save * @return the file where the storage was saved */ - public static File save(String prefix, String suffix, DataStorage dataStorage) throws CoserTechnicalException { + public static File save(DataStorage dataStorage, String prefix, String suffix) throws CoserTechnicalException { File file; try { @@ -131,6 +131,27 @@ try { writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), CoserConstants.CSV_FILE_ENCODING)); + save(dataStorage, writer); + writer.close(); + writer.close(); + } catch (IOException ex) { + throw new CoserTechnicalException("Can't save data", ex); + } finally { + IOUtils.closeQuietly(writer); + } + return file; + } + + /** + * Save a datastorage to a writer. + * + * @param dataStorage the storage to save + * @param writer where to save storage + */ + public static void save(DataStorage dataStorage, Writer writer) throws CoserTechnicalException { + + try { + for (String[] contentDatas : dataStorage) { // start at 1 to not output "line" column for (int i = 1; i < contentDatas.length; i++) { @@ -155,7 +176,5 @@ } finally { IOUtils.closeQuietly(writer); } - return file; } - } Modified: trunk/coser-business/src/main/java/fr/ifremer/coser/util/DataType.java =================================================================== --- trunk/coser-business/src/main/java/fr/ifremer/coser/util/DataType.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/main/java/fr/ifremer/coser/util/DataType.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -2,7 +2,7 @@ * #%L * Coser :: Business * %% - * Copyright (C) 2012 Ifremer, Codelutin, Chatellier Eric + * Copyright (C) 2012 Ifremer, Codelutin, Chatellier Eric, Chemit Tony * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as @@ -22,16 +22,42 @@ package fr.ifremer.coser.util; +import com.google.common.collect.Maps; + +import java.util.Locale; +import java.util.Map; + +import static org.nuiton.i18n.I18n.l; +import static org.nuiton.i18n.I18n.n; + /** * Les types de données gérées par le site internet, sur lesquelle il est * possible de filtrer dans le formulaire de recherche. - * + * * @author echatellier * @since 1.4 */ public enum DataType { - MAP, - POPULATION, - COMMUNITY, - SOURCE + MAP(n("coser.business.data.type.map")), + POPULATION(n("coser.business.data.type.population")), + COMMUNITY(n("coser.business.data.type.community")), + SOURCE(n("coser.business.data.type.source")); + + private final String i18nKey; + + DataType(String i18nKey) { + this.i18nKey = i18nKey; + } + + public String getLabel(Locale locale) { + return l(locale, i18nKey); + } + + public static Map<String, String> getExtractTypes(Locale locale) { + Map<String, String> result = Maps.newLinkedHashMap(); + for (DataType dataType : DataType.values()) { + result.put(dataType.name(), dataType.getLabel(locale)); + } + return result; + } } Modified: trunk/coser-business/src/main/resources/i18n/coser-business_en_GB.properties =================================================================== --- trunk/coser-business/src/main/resources/i18n/coser-business_en_GB.properties 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/main/resources/i18n/coser-business_en_GB.properties 2014-03-11 09:28:43 UTC (rev 1141) @@ -101,6 +101,10 @@ coser.business.control.step.lengthoutliers=Searching for aberrants lengths \: %s (%d%%) coser.business.control.step.observation=Checking observation number \: %s (%d%%) coser.business.control.step.xworks=Line checks \: %s (%d%%) +coser.business.data.type.community=Community indices by area +coser.business.data.type.map=Species distribution maps by area +coser.business.data.type.population=Population indices by species by area +coser.business.data.type.source=Raw data by sampling unit (generally by haul) coser.business.dataDisclaimer.filename=DataDisclaimer.pdf coser.business.extract.creationdate=Creation date \: coser.business.extract.extractdata=Data @@ -142,10 +146,13 @@ coser.business.result.rsufiResultAlreadyExists=Result %s already exists \! coser.business.resultupload.duplicatedresult=Result %s/%s/%s duplicate another result for zone %s \! coser.business.selection.notValidatedControl=Not validated control \! +coser.business.specesList.name=%s List %s +coser.business.specesList.nameForAll=All List %s coser.business.uploadresult.checkcollision=Checking zone collisions coser.business.uploadresult.modifyResultOptions=Modify result options coser.business.uploadresult.preparezip=Preparing zip archive… coser.business.uploadresult.sendzip=Sending zip archive… +coser.business.year=Year coser.config.control.diffcatchlength.description=Percentage difference allowed between catch and length (in percent, for example 5% set 5.0) coser.config.control.nobsmin.description=Minimal observation number coser.config.control.standarddeviationtoaverage.description=Length outliers (how many strandard deviation to average) Modified: trunk/coser-business/src/main/resources/i18n/coser-business_fr_FR.properties =================================================================== --- trunk/coser-business/src/main/resources/i18n/coser-business_fr_FR.properties 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/main/resources/i18n/coser-business_fr_FR.properties 2014-03-11 09:28:43 UTC (rev 1141) @@ -101,6 +101,10 @@ coser.business.control.step.lengthoutliers=Recherche des longueurs abérrantes \: %s (%d%%) coser.business.control.step.observation=Vérification du nombre d'observation \: %s (%d%%) coser.business.control.step.xworks=Validation par lignes \: %s (%d%%) +coser.business.data.type.community=Des indices de communauté par zone +coser.business.data.type.map=Des cartes de distribution par espèce et par zone +coser.business.data.type.population=Des indices biologiques par espèce et par zone +coser.business.data.type.source=Des données par opération d'échantillonnage (en général par trait de chalut) coser.business.dataDisclaimer.filename=DechargeDonnees.pdf coser.business.extract.creationdate=Date de création \: coser.business.extract.extractdata=Données du graphique @@ -142,10 +146,13 @@ coser.business.result.rsufiResultAlreadyExists=Le résultat %s existe déjà \! coser.business.resultupload.duplicatedresult=Le résultat %s/%s/%s duplique un autre résultat pour la zone %s \! coser.business.selection.notValidatedControl=Contrôle non validé \! +coser.business.specesList.name=%s Liste %s +coser.business.specesList.nameForAll=Tous Liste %s coser.business.uploadresult.checkcollision=Vérification des collisions de zones coser.business.uploadresult.modifyResultOptions=Modification des options des résultats coser.business.uploadresult.preparezip=Préparation de l'archive zip… coser.business.uploadresult.sendzip=Envoi de l'archive zip… +coser.business.year=Année coser.config.control.diffcatchlength.description=Pourcentage d'écart toléré entre les captures et les tailles (en pourcent, par exemple pour 5% mettre 5.0) coser.config.control.nobsmin.description=Nombre minimal d'observation coser.config.control.standarddeviationtoaverage.description=Tailles aberrantes (combien de fois l'écart type par rapport à la moyenne) Modified: trunk/coser-business/src/test/java/fr/ifremer/coser/result/repository/echobase/EchoBaseResultRepositoryTest.java =================================================================== --- trunk/coser-business/src/test/java/fr/ifremer/coser/result/repository/echobase/EchoBaseResultRepositoryTest.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-business/src/test/java/fr/ifremer/coser/result/repository/echobase/EchoBaseResultRepositoryTest.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -89,14 +89,12 @@ // pas de zones pour la facade mapRequest.setFacade("mediteranee"); availableZones = repository1.getAvailableZones(mapRequest); - Assert.assertNotNull(availableZones); - Assert.assertTrue(availableZones.isEmpty()); + Assert.assertNull(availableZones); // facade inconnue mapRequest.setFacade("mediteranee2"); availableZones = repository1.getAvailableZones(mapRequest); - Assert.assertNotNull(availableZones); - Assert.assertTrue(availableZones.isEmpty()); + Assert.assertNull(availableZones); // Population request @@ -113,14 +111,12 @@ // pas de zones pour la facade popRequest.setFacade("mediteranee"); availableZones = repository1.getAvailableZones(popRequest); - Assert.assertNotNull(availableZones); - Assert.assertTrue(availableZones.isEmpty()); + Assert.assertNull(availableZones); // facade inconnue popRequest.setFacade("mediteranee2"); availableZones = repository1.getAvailableZones(popRequest); - Assert.assertNotNull(availableZones); - Assert.assertTrue(availableZones.isEmpty()); + Assert.assertNull(availableZones); // Community request @@ -137,14 +133,12 @@ // pas de zones pour la facade comRequest.setFacade("mediteranee"); availableZones = repository1.getAvailableZones(comRequest); - Assert.assertNotNull(availableZones); - Assert.assertTrue(availableZones.isEmpty()); + Assert.assertNull(availableZones); // facade inconnue comRequest.setFacade("mediteranee2"); availableZones = repository1.getAvailableZones(comRequest); - Assert.assertNotNull(availableZones); - Assert.assertTrue(availableZones.isEmpty()); + Assert.assertNull(availableZones); } } Modified: trunk/coser-web/src/main/java/fr/ifremer/coser/web/ServiceHelper.java =================================================================== --- trunk/coser-web/src/main/java/fr/ifremer/coser/web/ServiceHelper.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-web/src/main/java/fr/ifremer/coser/web/ServiceHelper.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -28,15 +28,12 @@ import fr.ifremer.coser.result.CoserResultEngine; import fr.ifremer.coser.result.FileResult; import fr.ifremer.coser.result.repository.ResultRepositoryProvider; -import fr.ifremer.coser.result.repository.legacy.LegacyResultRepository; import fr.ifremer.coser.result.request.CoserRequestSpeciesAware; import fr.ifremer.coser.result.request.CoserRequestZoneAware; import fr.ifremer.coser.result.request.IndicatorRequest; import fr.ifremer.coser.services.WebService; import fr.ifremer.coser.util.DataType; import fr.ifremer.coser.web.actions.common.CoserAction; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.nuiton.config.ArgumentsParserException; import org.nuiton.i18n.I18n; import org.nuiton.i18n.init.DefaultI18nInitializer; @@ -61,9 +58,6 @@ */ public class ServiceHelper { - /** Logger. */ - private static final Log log = LogFactory.getLog(ServiceHelper.class); - private static WebService webService; private static CoserResultEngine resultService; @@ -199,7 +193,7 @@ // --- Indicator methods ----------------------------------------------- // // --------------------------------------------------------------------- // - public Map<String, String> getAvailableIndicators(IndicatorRequest request) { + public Map<String, String> getAvailableIndicators(CoserRequest request) { return resultService.getAvailableIndicators(request); } @@ -281,29 +275,6 @@ } } - public FileResult extractData(List<String> selectZones, - List<DataType> selectTypes, - List<String> selectSpecies, - List<String> selectComIndicators, - List<String> selectPopIndicators, - Locale locale) { - try { - File file = webService.extractData(selectZones, - selectTypes, - selectSpecies, - selectComIndicators, - selectPopIndicators, - locale); - FileResult fileResult = new FileResult(LegacyResultRepository.ID, file); - return fileResult; - } catch (CoserBusinessException e) { - if (log.isErrorEnabled()) { - log.error("Can't extract data", e); - } - throw new CoserWebException("Can't extract data", e); - } - } - // --------------------------------------------------------------------- // // --- Misc methods ---------------------------------------------------- // // --------------------------------------------------------------------- // Modified: trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/com/GraphDataAction.java =================================================================== --- trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/com/GraphDataAction.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/com/GraphDataAction.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -102,6 +102,7 @@ if (list == null) { + //TODO Improve this (add a getFirstAvailableSpecies method) // on prend la première entrée dans le fichier Map<String, String> lists = getService().getAvailableSpecies(request); if (!lists.isEmpty()) { Modified: trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/com/GraphDownloadAction.java =================================================================== --- trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/com/GraphDownloadAction.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/com/GraphDownloadAction.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -103,6 +103,7 @@ if (list == null) { + //TODO Improve this (add a getFirstAvailableSpecies method) // on prend la première entrée dans le fichier Map<String, String> lists = getService().getAvailableSpecies(request); if (!lists.isEmpty()) { Modified: trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/common/CoserAction.java =================================================================== --- trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/common/CoserAction.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/common/CoserAction.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -26,6 +26,8 @@ import fr.ifremer.coser.web.ServiceHelper; import org.nuiton.web.struts2.BaseAction; +import java.util.Locale; + /** * Toutes les actions doivent étendre celle ci. Contient le code commun * récurent, et notamment les actions utilisé par le layout et devant @@ -87,10 +89,19 @@ * @since 1.5 */ protected CoserRequestBuilder requestBuilder() { - return new CoserRequestBuilder(getLocale()); + return requestBuilder(getLocale()); } /** + * @param locale locale to use (while using execute and wait action we keep the locale in session...) + * @return a new request builder. + * @since 1.5 + */ + protected CoserRequestBuilder requestBuilder(Locale locale) { + return new CoserRequestBuilder(locale); + } + + /** * @return service helper for this action * @since 1.5 */ Modified: trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/search/ExtractAction.java =================================================================== --- trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/search/ExtractAction.java 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-web/src/main/java/fr/ifremer/coser/web/actions/search/ExtractAction.java 2014-03-11 09:28:43 UTC (rev 1141) @@ -21,7 +21,9 @@ package fr.ifremer.coser.web.actions.search; +import com.google.common.collect.Lists; import fr.ifremer.coser.result.FileResult; +import fr.ifremer.coser.result.request.ExtractRequest; import fr.ifremer.coser.util.DataType; import fr.ifremer.coser.web.actions.common.CoserAction; import org.apache.commons.collections4.CollectionUtils; @@ -58,8 +60,12 @@ public static final String DOWNLOAD = "download"; + public static final String LOCALE_ATTRIBUTE = "locale"; + protected Map<String, String> zones; + protected Map<String, String> types; + protected List<String> selectZones; protected List<DataType> selectTypes; @@ -96,6 +102,10 @@ this.selectZones = selectZones; } + public Map<String, String> getTypes() { + return types; + } + public List<DataType> getSelectTypes() { return selectTypes; } @@ -144,6 +154,11 @@ this.submitAction = submitAction; } + // used by validation + public boolean isAccepted() { + return accepted; + } + public void setAccepted(boolean accepted) { this.accepted = accepted; } @@ -167,17 +182,31 @@ } else { result = INPUT; + types = DataType.getExtractTypes(getLocale()); // renvoi la liste des id subzone-survey et leurs label associé zones = getService().getZoneForFacade(); + if (CollectionUtils.isNotEmpty(selectZones)) { - species = getService().getSpecies(selectZones); - if (selectTypes != null && selectTypes.contains(DataType.COMMUNITY)) { - comIndicators = getService().getIndicators(selectZones, DataType.COMMUNITY); + ExtractRequest extractRequest = requestBuilder(). + addZoneList(selectZones). + toExtractRequest(); + + species = getService().getAvailableSpecies(extractRequest); + + if (selectTypes != null) { + + if (selectTypes.contains(DataType.COMMUNITY)) { + + extractRequest.setExtractTypeList(Lists.newArrayList(DataType.COMMUNITY)); + comIndicators = getService().getAvailableIndicators(extractRequest); + } + + if (selectTypes.contains(DataType.POPULATION)) { + extractRequest.setExtractTypeList(Lists.newArrayList(DataType.POPULATION)); + popIndicators = getService().getAvailableIndicators(extractRequest); + } } - if (selectTypes != null && selectTypes.contains(DataType.POPULATION)) { - popIndicators = getService().getIndicators(selectZones, DataType.POPULATION); - } } } @@ -186,22 +215,14 @@ @Action(value = "extract-quality", results = { - @Result(location = "/WEB-INF/content/search/extract-success.jsp"), + @Result(name = "input", location = "/WEB-INF/content/search/extract-success.jsp"), @Result(name = DOWNLOAD, type = "redirect", params = { "location", "${location}"})}) public String quality() { - String result; - if (!accepted) { - addFieldError("accepted", getText("message.quality.notaccepted")); - result = SUCCESS; - } else { - - // petit hack pour mettre la locale dans la session car - // après, on n'a plus accès au context dans le executeAndWait - request.getSession().setAttribute("locale", getLocale()); - result = DOWNLOAD; - } - return result; + // petit hack pour mettre la locale dans la session car + // après, on n'a plus accès au context dans le executeAndWait + request.getSession().setAttribute(LOCALE_ATTRIBUTE, getLocale()); + return DOWNLOAD; } /** @@ -247,15 +268,18 @@ @Result(type = "stream", params = {"contentType", "application/zip", "contentDisposition", "attachment; filename=\"${filename}\""})}) public String download() { - Locale locale = (Locale) request.getSession().getAttribute("locale"); + Locale locale = (Locale) request.getSession().getAttribute(LOCALE_ATTRIBUTE); - resultFile = getService().extractData(selectZones, - selectTypes, - selectSpecies, - selectComIndicators, - selectPopIndicators, - locale); + ExtractRequest extractRequest = requestBuilder(locale). + addZoneList(selectZones). + addExtractTypeList(selectTypes). + addSpeciesList(selectSpecies). + addCommunityIndicatorList(selectComIndicators). + addPopulationIndicatorList(selectPopIndicators). + toExtractRequest(); + resultFile = getService().getFileResult(extractRequest); + return SUCCESS; } @@ -268,6 +292,26 @@ return "Indicateurs_Ifremer.zip"; } + // @Action(value = "extract-quality", +// results = { +// @Result(location = "/WEB-INF/content/search/extract-success.jsp"), +// @Result(name = DOWNLOAD, type = "redirect", params = { +// "location", "${location}"})}) +// public String quality() { +// String result; +// if (!accepted) { +// addFieldError("accepted", getText("message.quality.notaccepted")); +// result = SUCCESS; +// } else { +// +// // petit hack pour mettre la locale dans la session car +// // après, on n'a plus accès au context dans le executeAndWait +// request.getSession().setAttribute("locale", getLocale()); +// result = DOWNLOAD; +// } +// return result; +// } +// // protected File zipFile; // // @Override Added: trunk/coser-web/src/main/resources/fr/ifremer/coser/web/actions/search/ExtractAction-extract-quality-validation.xml =================================================================== --- trunk/coser-web/src/main/resources/fr/ifremer/coser/web/actions/search/ExtractAction-extract-quality-validation.xml (rev 0) +++ trunk/coser-web/src/main/resources/fr/ifremer/coser/web/actions/search/ExtractAction-extract-quality-validation.xml 2014-03-11 09:28:43 UTC (rev 1141) @@ -0,0 +1,34 @@ +<!-- + #%L + Coser :: Web + %% + Copyright (C) 2010 - 2014 Ifremer, Codelutin, Chemit Tony + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero 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 Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + #L% + --> +<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + + <field name="accepted"> + + <field-validator type="fieldexpression"> + <param name="expression">accepted</param> + <message key="message.quality.notaccepted"/> + </field-validator> + + </field> + +</validators> \ No newline at end of file Property changes on: trunk/coser-web/src/main/resources/fr/ifremer/coser/web/actions/search/ExtractAction-extract-quality-validation.xml ___________________________________________________________________ Added: svn:mime-type + text/xml Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/coser-web/src/main/webapp/WEB-INF/content/search/extract-input.jsp =================================================================== --- trunk/coser-web/src/main/webapp/WEB-INF/content/search/extract-input.jsp 2014-03-10 10:23:18 UTC (rev 1140) +++ trunk/coser-web/src/main/webapp/WEB-INF/content/search/extract-input.jsp 2014-03-11 09:28:43 UTC (rev 1141) @@ -2,7 +2,7 @@ #%L Coser :: Web %% - Copyright (C) 2012 Ifremer, Codelutin, Chatellier Eric + Copyright (C) 2012 Ifremer, Codelutin, Chatellier Eric, Chemit Tony %% This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -57,6 +57,15 @@ <td><s:text name="message.common.datatypes" /> :</td> <td> <select name="selectTypes" multiple="multiple" style="width:100%" id="selectTypes"> + <s:iterator value="types" var="type"> + <option value="<s:property value="key" />" + <s:if test="selectTypes.contains(#type.key)"> + selected="selected" + </s:if>> + <s:property value="value" /></option> + </s:iterator> + </select> + </td><%-- <option value="<s:property value="@fr.ifremer.coser.util.DataType@MAP" />" <s:if test="selectTypes.contains(@fr.ifremer.coser.util.DataType@MAP)"> selected="selected" @@ -77,7 +86,7 @@ selected="selected" </s:if>> <s:text name="message.index.datatypesource.short" /></option> - </select></td> + </select></td>--%> <td style="vertical-align:top"> <img src="<s:url value='/images/stock_select_table.png' />" onClick="javascript:coserSelectAll($('#selectTypes'))"
participants (1)
-
tchemit@users.forge.codelutin.com