Author: kmorin Date: 2013-03-26 17:46:19 +0100 (Tue, 26 Mar 2013) New Revision: 681 Url: http://forge.codelutin.com/projects/tutti/repository/revisions/681 Log: refs #1868 [CAPTURE] - Import/Export PUPITRI Added: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/PupitriCatch.java trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/SpeciesRow.java trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/SpeciesRowModel.java Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/CarrouselRow.java trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/CarrouselRowModel.java trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/TuttiPupitriImportExportService.java Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/CarrouselRow.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/CarrouselRow.java 2013-03-26 16:46:02 UTC (rev 680) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/CarrouselRow.java 2013-03-26 16:46:19 UTC (rev 681) @@ -58,8 +58,6 @@ public static final String PROPERTY_WEIGHT = "weight"; - public static final String PROPERTY_EMPTY = ""; - protected Integer operationCode; protected String rigNumber; Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/CarrouselRowModel.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/CarrouselRowModel.java 2013-03-26 16:46:02 UTC (rev 680) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/CarrouselRowModel.java 2013-03-26 16:46:19 UTC (rev 681) @@ -25,13 +25,12 @@ */ import fr.ifremer.tutti.service.TuttiCsvUtil; +import java.text.ParseException; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.util.csv.ValueParser; -import java.text.ParseException; - /** * @author kmorin <kmorin@codelutin.com> * @since 1.2 @@ -58,7 +57,7 @@ newMandatoryColumn(CarrouselRow.PROPERTY_SPECIES_ID, new ValueParser<String>() { public String parse(String string) throws ParseException { - return StringUtils.remove(string, '-'); + return StringUtils.remove(string, '-').trim(); } }); newMandatoryColumn(CarrouselRow.PROPERTY_SIGN); @@ -83,7 +82,6 @@ newIgnoredColumn(CarrouselRow.PROPERTY_BALANCE_ID); newIgnoredColumn(CarrouselRow.PROPERTY_TO_CONFIRM); newIgnoredColumn(CarrouselRow.PROPERTY_BOX_TYPE); - newIgnoredColumn(CarrouselRow.PROPERTY_EMPTY); } Added: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/PupitriCatch.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/PupitriCatch.java (rev 0) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/PupitriCatch.java 2013-03-26 16:46:19 UTC (rev 681) @@ -0,0 +1,102 @@ + +package fr.ifremer.tutti.service.pupitri; + +import com.google.common.collect.Maps; +import fr.ifremer.tutti.persistence.entities.referential.Species; +import java.io.Serializable; +import java.util.Map; + +/** + * + * @author kmorin <kmorin@codelutin.com> + * @since 1.2 + */ +public class PupitriCatch implements Serializable { + + private static final long serialVersionUID = 1L; + + public static enum Signs { + DEFAULT("0"), + MALE("1"), + FEMALE("2"), + SMALL("P"), + MEDIUM("M"), + BIG("G"); + + private String sign; + + Signs(String sign) { + this.sign = sign; + } + + public static Signs getSign(String sign) { + Signs result = null; + for (Signs s : values()) { + if (s.sign.equals(sign)) { + result = s; + break; + } + } + return result; + } + } + + protected Species species; + + protected boolean sorted; + + protected Map<Signs, Float> weightBySign = Maps.newHashMap(); + + public PupitriCatch(Species species, boolean sorted) { + this.species = species; + this.sorted = sorted; + } + + public Species getSpecies() { + return species; + } + + public boolean isSorted() { + return sorted; + } + + public Map<Signs, Float> getWeightBySign() { + return weightBySign; + } + + public void addToSign(String sign, Float weight) { + Signs s = Signs.getSign(sign); + Float f = weightBySign.get(s); + if (f == null) { + f = 0f; + } + f += weight; + weightBySign.put(s, f); + } + + @Override + public int hashCode() { + int speciesHashCode = species != null ? species.hashCode() : 0; + int sortedHashCode = sorted ? 0x55555555 : 0x2AAAAAAA; + return speciesHashCode ^ sortedHashCode; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final PupitriCatch other = (PupitriCatch) obj; + if (this.species != other.species && (this.species == null || !this.species.equals(other.species))) { + return false; + } + if (this.sorted != other.sorted) { + return false; + } + return true; + } + +} Added: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/SpeciesRow.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/SpeciesRow.java (rev 0) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/SpeciesRow.java 2013-03-26 16:46:19 UTC (rev 681) @@ -0,0 +1,51 @@ + +package fr.ifremer.tutti.service.pupitri; + +import java.io.Serializable; + +/** + * + * @author kmorin <kmorin@codelutin.com> + * @since 1.2 + */ +public class SpeciesRow implements Serializable { + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_CODE_FIRST_PART = "codeFirstPart"; + + public static final String PROPERTY_CODE_SECOND_PART = "codeSecondPart"; + + public static final String PROPERTY_SCIENTIFIC_NAME = "scientificName"; + + protected String codeFirstPart; + + protected String codeSecondPart; + + protected String scientificName; + + public String getCodeFirstPart() { + return codeFirstPart; + } + + public void setCodeFirstPart(String codeFirstPart) { + this.codeFirstPart = codeFirstPart; + } + + public String getCodeSecondPart() { + return codeSecondPart; + } + + public void setCodeSecondPart(String codeSecondPart) { + this.codeSecondPart = codeSecondPart; + } + + public String getScientificName() { + return scientificName; + } + + public void setScientificName(String scientificName) { + this.scientificName = scientificName; + } + +} Copied: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/SpeciesRowModel.java (from rev 677, trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/CarrouselRowModel.java) =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/SpeciesRowModel.java (rev 0) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/SpeciesRowModel.java 2013-03-26 16:46:19 UTC (rev 681) @@ -0,0 +1,57 @@ +package fr.ifremer.tutti.service.pupitri; + +/* + * #%L + * Tutti :: Service + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2012 - 2013 Ifremer + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ifremer.tutti.service.TuttiCsvUtil; +import java.text.ParseException; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.csv.ValueParser; + +/** + * @author kmorin <kmorin@codelutin.com> + * @since 1.2 + */ +public class SpeciesRowModel extends TuttiCsvUtil.AbstractTuttiImportExportModel<SpeciesRow> { + + private static final Log log = LogFactory.getLog(SpeciesRowModel.class); + + public SpeciesRowModel(char separator) { + super(separator); + + // import definition + + newColumnForImportExport(SpeciesRow.PROPERTY_CODE_FIRST_PART); + newColumnForImportExport(SpeciesRow.PROPERTY_CODE_SECOND_PART); + newColumnForImportExport(SpeciesRow.PROPERTY_SCIENTIFIC_NAME); + + } + + public SpeciesRow newEmptyInstance() { + return new SpeciesRow(); + } + +} Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/TuttiPupitriImportExportService.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/TuttiPupitriImportExportService.java 2013-03-26 16:46:02 UTC (rev 680) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/pupitri/TuttiPupitriImportExportService.java 2013-03-26 16:46:19 UTC (rev 681) @@ -25,11 +25,21 @@ */ import com.google.common.base.Charsets; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; import com.google.common.io.Files; import fr.ifremer.tutti.TuttiTechnicalException; import fr.ifremer.tutti.persistence.entities.data.CatchBatch; import fr.ifremer.tutti.persistence.entities.data.FishingOperation; +import fr.ifremer.tutti.persistence.entities.protocol.SpeciesProtocol; +import fr.ifremer.tutti.persistence.entities.referential.Species; import fr.ifremer.tutti.service.AbstractTuttiService; +import fr.ifremer.tutti.service.protocol.TuttiProtocolImportExportService; +import java.io.BufferedWriter; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; @@ -37,9 +47,16 @@ import org.nuiton.util.csv.Import; import java.io.File; +import java.io.IOException; import java.io.Reader; +import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.Map; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.nuiton.util.csv.Export; +import org.nuiton.util.csv.ExportModel; /** * @author kmorin <kmorin@codelutin.com> @@ -123,102 +140,181 @@ } - public void importPupitriCarrousel(File file, + public List<PupitriCatch> importPupitriCarrousel(File carrouselFile, + File speciesFile, FishingOperation operation, CatchBatch catchBatch, - Map<String, Float> sortedWeights, - Map<String, Float> unsortedWeights) { + List<Species> referentSpecies) { if (log.isInfoEnabled()) { log.info("Will import pupitri operation [" + operation.toString() + - "] carrousel from file: " + file); + "] carrousel from file: " + carrouselFile); } - char separator = ','; - CarrouselRowModel csvModel = new CarrouselRowModel(separator); - + List<PupitriCatch> result = Lists.newArrayList(); Reader reader = null; File fileWithHeaders = null; - Import<CarrouselRow> importer = null; + Import<SpeciesRow> speciesImporter = null; + Import<CarrouselRow> carrouselImporter = null; + + char speciesSeparator = ';'; + SpeciesRowModel speciesCsvModel = new SpeciesRowModel(speciesSeparator); + char carrouselSeparator = ','; + CarrouselRowModel carrouselCsvModel = new CarrouselRowModel(carrouselSeparator); + try { - fileWithHeaders = new File(FileUtils.getTempDirectory(), file.getName()); - String headers = CarrouselRow.PROPERTY_FILE_ORIGIN + separator + - CarrouselRow.PROPERTY_DATE + separator + - CarrouselRow.PROPERTY_TIME + separator + - CarrouselRow.PROPERTY_BALANCE_ID + separator + - CarrouselRow.PROPERTY_TO_CONFIRM + separator + - CarrouselRow.PROPERTY_OPERATION_CODE + separator + - CarrouselRow.PROPERTY_RIG_NUMBER + separator + - CarrouselRow.PROPERTY_BOX_TYPE + separator + - CarrouselRow.PROPERTY_SPECIES_ID + separator + - CarrouselRow.PROPERTY_SIGN + separator + - CarrouselRow.PROPERTY_DIRECTION + separator + - CarrouselRow.PROPERTY_WEIGHT + separator + - CarrouselRow.PROPERTY_EMPTY; - FileUtils.writeLines(fileWithHeaders, Collections.singletonList(headers)); - log.info(FileUtils.readFileToString(fileWithHeaders)); - FileUtils.writeLines(fileWithHeaders, FileUtils.readLines(file), true); - log.info(FileUtils.readFileToString(fileWithHeaders)); + // import the species + String[] header = new String [] { + SpeciesRow.PROPERTY_CODE_FIRST_PART, + SpeciesRow.PROPERTY_CODE_SECOND_PART, + SpeciesRow.PROPERTY_SCIENTIFIC_NAME + }; + fileWithHeaders = createFileWithHeaders(speciesFile, header, speciesSeparator); + reader = Files.newReader(fileWithHeaders, Charsets.UTF_8); + speciesImporter = Import.newImport(speciesCsvModel, reader); + // get the map of species by survey code + Multimap<String, Species> speciesBySurveyCode = + Multimaps.index(referentSpecies, new Function<Species, String>() { + @Override + public String apply(Species input) { + String surveyCode = String.valueOf(input.getSurveyCode()); + int end = Math.min(surveyCode.length(), 7); + return surveyCode.substring(0, end); + } + }); + // keep only the species whose survey code and name are the same + // in theimported file and the referent species + Map<String, Species> speciesMap = Maps.newHashMap(); + for (SpeciesRow bean : speciesImporter) { + String code = bean.getCodeFirstPart() + bean.getCodeSecondPart(); + Collection<Species> speciesCollection = speciesBySurveyCode.get(code.trim()); + for (Species species : speciesCollection) { + if (species.getName().equals(bean.getScientificName())) { + speciesMap.put(code, species); + break; + } + } + } + + // import the batches + header = new String[] { + CarrouselRow.PROPERTY_FILE_ORIGIN, + CarrouselRow.PROPERTY_DATE, + CarrouselRow.PROPERTY_TIME, + CarrouselRow.PROPERTY_BALANCE_ID, + CarrouselRow.PROPERTY_TO_CONFIRM, + CarrouselRow.PROPERTY_OPERATION_CODE, + CarrouselRow.PROPERTY_RIG_NUMBER, + CarrouselRow.PROPERTY_BOX_TYPE, + CarrouselRow.PROPERTY_SPECIES_ID, + CarrouselRow.PROPERTY_SIGN, + CarrouselRow.PROPERTY_DIRECTION, + CarrouselRow.PROPERTY_WEIGHT + }; + fileWithHeaders = createFileWithHeaders(carrouselFile, header, carrouselSeparator); reader = Files.newReader(fileWithHeaders, Charsets.UTF_8); + carrouselImporter = Import.newImport(carrouselCsvModel, reader); - importer = Import.newImport(csvModel, reader); - Integer operationNumber = operation.getFishingOperationNumber(); String rigNumber = operation.getMultirigAggregation(); Float carrouselSortedWeight = 0f; - for (CarrouselRow bean : importer) { + for (CarrouselRow bean : carrouselImporter) { + // is the bean from the current operation and rig ? if (bean.getOperationCode().equals(operationNumber) - && bean.getRigNumber().equals(rigNumber) - && "0".equals(bean.getSign())) { + && bean.getRigNumber().equals(rigNumber)) { String speciesId = bean.getSpeciesId(); - Map<String, Float> weights = null; + Species species = speciesMap.get(speciesId); Float beanWeight = bean.getWeight(); if (beanWeight < 0f) { beanWeight = 0f; } - + boolean sorted; switch (bean.getDirection()) { - case VAT: - weights = sortedWeights; - carrouselSortedWeight += beanWeight; + case HOV: + sorted = false; break; - case HOV: - weights = unsortedWeights; + default : + sorted = true; + carrouselSortedWeight += beanWeight; } - if (weights != null) { - Float speciesWeight = weights.get(speciesId); + if (species != null) { - if (speciesWeight == null) { - speciesWeight = beanWeight; - + PupitriCatch pupitriCatch = new PupitriCatch(species, sorted); + int catchIndex = result.indexOf(pupitriCatch); + if (catchIndex >= 0) { + pupitriCatch = result.get(catchIndex); } else { - speciesWeight += beanWeight; + result.add(pupitriCatch); } - weights.put(speciesId, speciesWeight); + pupitriCatch.addToSign(bean.getSign(), beanWeight); } } } catchBatch.setCatchTotalSortedCarousselWeight(carrouselSortedWeight); - importer.close(); + carrouselImporter.close(); + speciesImporter.close(); reader.close(); } catch (Exception e) { - throw new TuttiTechnicalException("Could not import protocol [" + operation.toString() + "] caracteristic from file " + file, e); + throw new TuttiTechnicalException("Could not import protocol [" + operation.toString() + "] caracteristic from file " + carrouselFile, e); } finally { - IOUtils.closeQuietly(importer); + IOUtils.closeQuietly(carrouselImporter); + IOUtils.closeQuietly(speciesImporter); IOUtils.closeQuietly(reader); FileUtils.deleteQuietly(fileWithHeaders); } + + return result; } + + public void exportSpecies(List<Species> species, File target) { + SpeciesRowModel speciesCsvModel = new SpeciesRowModel(';'); + + List<SpeciesRow> rows = Lists.newArrayList(); + + if (CollectionUtils.isNotEmpty(species)) { + rows = Lists.transform(species, new Function<Species, SpeciesRow>() { + + public SpeciesRow apply(Species input) { + Preconditions.checkNotNull(input.getSurveyCode(), + "Unable to export a species with a null survey code : " + input); + SpeciesRow row = new SpeciesRow(); + String codeFirstPart = StringUtils.substring(input.getSurveyCode(), 0, 4); + row.setCodeFirstPart(StringUtils.rightPad(codeFirstPart, 4)); + String codeSecondPart = StringUtils.substring(input.getSurveyCode(), 4, 7); + row.setCodeSecondPart(StringUtils.rightPad(codeSecondPart, 3)); + row.setScientificName(input.getName()); + return row; + } + }); + } + + try { + Export.exportToFile(speciesCsvModel, rows, target, Charsets.UTF_8, false); + + } catch (Exception e) { + throw new TuttiTechnicalException("Could not export all species to file " + target, e); + } + } + + protected File createFileWithHeaders(File file, String[] header, char separator) throws IOException { + File fileWithHeaders = new File(FileUtils.getTempDirectory(), file.getName()); + String headers = StringUtils.join(header, separator); + + FileUtils.writeLines(fileWithHeaders, Collections.singletonList(headers)); + FileUtils.writeLines(fileWithHeaders, FileUtils.readLines(file), true); + + return fileWithHeaders; + } }