Author: tchemit Date: 2013-04-15 16:48:55 +0200 (Mon, 15 Apr 2013) New Revision: 777 Url: http://forge.codelutin.com/projects/tutti/repository/revisions/777 Log: refs #1875: [IMP/EXP] - Export des donn?\195?\169es de campagne : format g?\195?\169n?\195?\169rique Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiCsvUtil.java trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/catches/TuttiWeightComputingService.java trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/config/TuttiServiceConfig.java trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/config/TuttiServiceConfigOption.java trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/CatchExportModel.java trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/OperationExportModel.java trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/SurveyExportModel.java trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/SurveyExportRow.java trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/TuttiExportService.java trunk/tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties trunk/tutti-service/src/test/java/fr/ifremer/tutti/service/export/TuttiExportServiceTest.java Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiCsvUtil.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiCsvUtil.java 2013-04-15 10:40:39 UTC (rev 776) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/TuttiCsvUtil.java 2013-04-15 14:48:55 UTC (rev 777) @@ -24,9 +24,11 @@ * #L% */ +import com.google.common.base.Joiner; import fr.ifremer.tutti.TuttiTechnicalException; import fr.ifremer.tutti.persistence.entities.TuttiEntity; import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue; +import fr.ifremer.tutti.persistence.entities.referential.Person; import org.apache.commons.beanutils.BeanUtilsBean; import org.apache.commons.lang3.StringUtils; import org.nuiton.util.csv.Common; @@ -44,6 +46,7 @@ import java.text.ParseException; import java.util.Collections; import java.util.Date; +import java.util.List; import java.util.Map; import java.util.Set; @@ -243,15 +246,12 @@ public static final ValueParserFormatter<Date> YEAR = new DateValue("yyyy"); - public static final ValueParserFormatter<Date> DAY_EMPTY_TIME = - new DateValue("dd/MM/yyyy 00:00:00"); - - public static final ValueParserFormatter<Date> TIME = - new DateValue("HH:mm:ss"); - public static final ValueFormatter<Serializable> CARACTERISTIC_VALUE_FORMATTER = new CaracteristicValueFormatter(); + public static final ValueFormatter<List<Person>> LIST_PERSON_FORMATTER = + new ListPersonValueFormatter(); + public static <E> BeanPropertyFormatter<E> newBeanFormatter(String propertyName, String defaultNullValue) { return new BeanPropertyFormatter<E>(propertyName, defaultNullValue); @@ -351,6 +351,14 @@ } } + protected static class ListPersonValueFormatter implements ValueFormatter<List<Person>> { + + @Override + public String format(List<Person> value) { + return Joiner.on('|').join(value); + } + } + protected TuttiCsvUtil() { // no instance } Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/catches/TuttiWeightComputingService.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/catches/TuttiWeightComputingService.java 2013-04-15 10:40:39 UTC (rev 776) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/catches/TuttiWeightComputingService.java 2013-04-15 14:48:55 UTC (rev 777) @@ -24,6 +24,7 @@ * #L% */ +import com.google.common.collect.Maps; import fr.ifremer.tutti.TuttiBusinessException; import fr.ifremer.tutti.persistence.entities.data.BatchContainer; import fr.ifremer.tutti.persistence.entities.data.BenthosBatch; @@ -45,6 +46,7 @@ import org.nuiton.validator.NuitonValidatorResult; import java.util.List; +import java.util.Map; import static org.nuiton.i18n.I18n._; @@ -68,6 +70,52 @@ validationService = getService(ValidationService.class); } + /** + * To check if can compute for any fishing operation of the cruise given + * by his id. + * <p/> + * If no error found, then return is a empty map, otherwise the first error + * found for any bad fishing operation. + * <p/> + * Result keys are fishing operation id, values the first error for + * the fishing operation. + * + * @param cruiseId id of the cruise to check. + * @return map of errors, or empty map if no error found. + * @since 1.4 + */ + public Map<String, String> checkCruise(String cruiseId) { + + if (log.isDebugEnabled()) { + log.debug("Will check cruise: " + cruiseId); + } + Map<String, String> result = Maps.newTreeMap(); + + List<FishingOperation> allFishingOperation = + persistenceService.getAllFishingOperation(cruiseId); + + for (FishingOperation fishingOperation : allFishingOperation) { + + String fishingOperationId = fishingOperation.getId(); + CatchBatch catchBatch = persistenceService.getCatchBatchFromFishingOperation(fishingOperationId); + BatchContainer<SpeciesBatch> rootSpeciesBatch = persistenceService.getRootSpeciesBatch(fishingOperationId); + BatchContainer<BenthosBatch> rootBenthosBatch = persistenceService.getRootBenthosBatch(fishingOperationId); + BatchContainer<MarineLitterBatch> rootMarineLitterBatch = persistenceService.getRootMarineLitterBatch(fishingOperationId); + + try { + if (catchBatch != null) { + computeCatchBatchWeights(catchBatch, + rootSpeciesBatch, + rootBenthosBatch, + rootMarineLitterBatch); + } + } catch (TuttiBusinessException e) { + result.put(fishingOperationId, e.getMessage()); + } + } + return result; + } + public void computeCatchBatchWeights(CatchBatch catchBatch, BatchContainer<SpeciesBatch> rootSpeciesBatch, BatchContainer<BenthosBatch> rootBenthosBatch, Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/config/TuttiServiceConfig.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/config/TuttiServiceConfig.java 2013-04-15 10:40:39 UTC (rev 776) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/config/TuttiServiceConfig.java 2013-04-15 14:48:55 UTC (rev 777) @@ -106,6 +106,11 @@ TuttiServiceConfigOption.CSV_SEPARATOR.getKey()).charAt(0); } + public String getExportCountryId() { + return applicationConfig.getOption( + TuttiServiceConfigOption.EXPORT_COUNTRY_ID.getKey()); + } + public void prepareDirectories() { File dataDirectory = getDataDirectory(); Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/config/TuttiServiceConfigOption.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/config/TuttiServiceConfigOption.java 2013-04-15 10:40:39 UTC (rev 776) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/config/TuttiServiceConfigOption.java 2013-04-15 14:48:55 UTC (rev 777) @@ -67,6 +67,12 @@ n_("tutti.config.option.csv.separator.description"), ";", char.class), + EXPORT_COUNTRY_ID( + "tutti.export.countryId", + n_("tutti.config.option.export.countryId.description"), + "12", + char.class), + // TRANSIENT CONFIG VERSION( "tutti.version", Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/CatchExportModel.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/CatchExportModel.java 2013-04-15 10:40:39 UTC (rev 776) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/CatchExportModel.java 2013-04-15 14:48:55 UTC (rev 777) @@ -25,6 +25,7 @@ */ import fr.ifremer.tutti.persistence.entities.data.BatchContainer; +import fr.ifremer.tutti.persistence.entities.data.BenthosBatch; import fr.ifremer.tutti.persistence.entities.data.Cruise; import fr.ifremer.tutti.persistence.entities.data.FishingOperation; import fr.ifremer.tutti.persistence.entities.data.Program; @@ -52,16 +53,12 @@ newColumnForExport("NumOrdre_Station", FishingOperation.PROPERTY_FISHING_OPERATION_NUMBER, TuttiCsvUtil.INTEGER); newColumnForExport("Navire", Cruise.PROPERTY_VESSEL, Vessel.PROPERTY_NAME); -//FIXME newColumnForExport("Pays", Cruise.PROPERTY_VESSEL); newColumnForExport("Zone_Etude", "programeZoneName"); newColumnForExport("Id_Sismer", Cruise.PROPERTY_NAME); - newColumnForExport("Date_Deb_Campagne", Cruise.PROPERTY_BEGIN_DATE, TuttiCsvUtil.DAY_EMPTY_TIME); - newColumnForExport("Heure_Deb_Campagne", Cruise.PROPERTY_BEGIN_DATE, TuttiCsvUtil.TIME); + newColumnForExport("Date_Deb_Campagne", Cruise.PROPERTY_BEGIN_DATE, TuttiCsvUtil.DAY_TIME_SECOND); newColumnForExport("Port_Deb_Campagne", Cruise.PROPERTY_DEPARTURE_LOCATION); - newColumnForExport("Date_Fin_Campagne", Cruise.PROPERTY_END_DATE, TuttiCsvUtil.DAY_EMPTY_TIME); - newColumnForExport("Heure_Fin_Campagne", Cruise.PROPERTY_END_DATE, TuttiCsvUtil.TIME); + newColumnForExport("Date_Fin_Campagne", Cruise.PROPERTY_END_DATE, TuttiCsvUtil.DAY_TIME_SECOND); newColumnForExport("Port_Fin_Campagne", Cruise.PROPERTY_RETURN_LOCATION); -//FIXME newColumnForExport("Responsable_Serie", Cruise.PROPERTY_HEAD_OF_MISSION); newColumnForExport("Chef_Mission", Cruise.PROPERTY_HEAD_OF_MISSION); newColumnForExport("Resp_Salle_Tri", Cruise.PROPERTY_HEAD_OF_SORT_ROOM); newColumnForExport("Commentaire", Cruise.PROPERTY_COMMENT); @@ -70,10 +67,13 @@ public void prepareRows(List<CatchExportRow> rows, Cruise cruise, FishingOperation operation, - BatchContainer<SpeciesBatch> rootSpeciesBatch) { + BatchContainer<SpeciesBatch> rootSpeciesBatch, + BatchContainer<BenthosBatch> rootBenthosBatch) { CatchExportRow row = new CatchExportRow(); row.setCruise(cruise); row.setFishingOperation(operation); +// row.setRootSpeciesBatch(rootSpeciesBatch); +// row.setRootBenthosBatch(rootBenthosBatch); rows.add(row); } Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/OperationExportModel.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/OperationExportModel.java 2013-04-15 10:40:39 UTC (rev 776) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/OperationExportModel.java 2013-04-15 14:48:55 UTC (rev 777) @@ -66,19 +66,16 @@ newColumnForExport("Engin", Cruise.PROPERTY_GEAR, Gear.PROPERTY_NAME); newColumnForExport("Navire", Cruise.PROPERTY_VESSEL, Vessel.PROPERTY_NAME); - newColumnForExport("DateDeb_Op", FishingOperation.PROPERTY_GEAR_SHOOTING_START_DATE, TuttiCsvUtil.DAY_EMPTY_TIME); - newColumnForExport("HeureDeb_Op", FishingOperation.PROPERTY_GEAR_SHOOTING_START_DATE, TuttiCsvUtil.TIME); + newColumnForExport("DateDeb_Op", FishingOperation.PROPERTY_GEAR_SHOOTING_START_DATE, TuttiCsvUtil.DAY_TIME_SECOND); newColumnForExport("LatDeb", FishingOperation.PROPERTY_GEAR_SHOOTING_START_LATITUDE, TuttiCsvUtil.FLOAT); newColumnForExport("LongDeb", FishingOperation.PROPERTY_GEAR_SHOOTING_START_LONGITUDE, TuttiCsvUtil.FLOAT); - newColumnForExport("DateFin_Op", FishingOperation.PROPERTY_GEAR_SHOOTING_END_DATE, TuttiCsvUtil.DAY_EMPTY_TIME); - newColumnForExport("HeureFin_OP", FishingOperation.PROPERTY_GEAR_SHOOTING_END_DATE, TuttiCsvUtil.TIME); + newColumnForExport("DateFin_Op", FishingOperation.PROPERTY_GEAR_SHOOTING_END_DATE, TuttiCsvUtil.DAY_TIME_SECOND); newColumnForExport("LatFin", FishingOperation.PROPERTY_GEAR_SHOOTING_END_LATITUDE, TuttiCsvUtil.FLOAT); newColumnForExport("LongFin", FishingOperation.PROPERTY_GEAR_SHOOTING_END_LONGITUDE, TuttiCsvUtil.FLOAT); newColumnForExport("Duree", OperationExportRow.PROPERTY_DURATION); newColumnForExport("Strate", FishingOperation.PROPERTY_STRATA, TuttiLocation.PROPERTY_NAME, "NA"); newColumnForExport("Sous-Strate", FishingOperation.PROPERTY_SUB_STRATA, TuttiLocation.PROPERTY_NAME, "NA"); newColumnForExport("Localite", FishingOperation.PROPERTY_LOCATION, TuttiLocation.PROPERTY_NAME, "NA"); -//FIXME newColumnForExport("Rectangle_CIEM",); // Carré statistique newColumnForExport("Validite_OP", FishingOperation.PROPERTY_FISHING_OPERATION_VALID, TuttiCsvUtil.BOOLEAN); newColumnForExport("Rectiligne", FishingOperation.PROPERTY_FISHING_OPERATION_RECTILIGNE, TuttiCsvUtil.BOOLEAN); newColumnForExport("Distance", FishingOperation.PROPERTY_TRAWL_DISTANCE, TuttiCsvUtil.FLOAT); Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/SurveyExportModel.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/SurveyExportModel.java 2013-04-15 10:40:39 UTC (rev 776) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/SurveyExportModel.java 2013-04-15 14:48:55 UTC (rev 777) @@ -47,24 +47,24 @@ newColumnForExport("Serie", Cruise.PROPERTY_PROGRAM, Program.PROPERTY_NAME); newColumnForExport("Serie_Partielle", Cruise.PROPERTY_SURVEY_PART); newColumnForExport("Navire", Cruise.PROPERTY_VESSEL, Vessel.PROPERTY_NAME); -//FIXME newColumnForExport("Pays", Cruise.PROPERTY_VESSEL); + newColumnForExport("Pays", SurveyExportRow.PROPERTY_COUNTRY); newColumnForExport("Zone_Etude", Program.PROPERTY_ZONE, TuttiLocation.PROPERTY_NAME); newColumnForExport("Id_Sismer", Cruise.PROPERTY_NAME); - newColumnForExport("Date_Deb_Campagne", Cruise.PROPERTY_BEGIN_DATE, TuttiCsvUtil.DAY_EMPTY_TIME); - newColumnForExport("Heure_Deb_Campagne", Cruise.PROPERTY_BEGIN_DATE, TuttiCsvUtil.TIME); + newColumnForExport("Date_Deb_Campagne", Cruise.PROPERTY_BEGIN_DATE, TuttiCsvUtil.DAY_TIME_SECOND); newColumnForExport("Port_Deb_Campagne", Cruise.PROPERTY_DEPARTURE_LOCATION, TuttiLocation.PROPERTY_NAME); - newColumnForExport("Date_Fin_Campagne", Cruise.PROPERTY_END_DATE, TuttiCsvUtil.DAY_EMPTY_TIME); - newColumnForExport("Heure_Fin_Campagne", Cruise.PROPERTY_END_DATE, TuttiCsvUtil.TIME); + newColumnForExport("Date_Fin_Campagne", Cruise.PROPERTY_END_DATE, TuttiCsvUtil.DAY_TIME_SECOND); newColumnForExport("Port_Fin_Campagne", Cruise.PROPERTY_RETURN_LOCATION, TuttiLocation.PROPERTY_NAME); -//FIXME newColumnForExport("Responsable_Serie", Cruise.PROPERTY_HEAD_OF_MISSION); -// newColumnForExport("Chef_Mission", Cruise.PROPERTY_HEAD_OF_MISSION); -// newColumnForExport("Resp_Salle_Tri", Cruise.PROPERTY_HEAD_OF_SORT_ROOM); + newColumnForExport("Chef_Mission", Cruise.PROPERTY_HEAD_OF_MISSION, TuttiCsvUtil.LIST_PERSON_FORMATTER); + newColumnForExport("Resp_Salle_Tri", Cruise.PROPERTY_HEAD_OF_SORT_ROOM, TuttiCsvUtil.LIST_PERSON_FORMATTER); newColumnForExport("Commentaire", Cruise.PROPERTY_COMMENT); } - public void prepareRows(List<SurveyExportRow> rows, Cruise cruise) { + public void prepareRows(List<SurveyExportRow> rows, + Cruise cruise, + TuttiLocation country) { SurveyExportRow row = new SurveyExportRow(); row.setCruise(cruise); + row.setCountry(country); rows.add(row); } } \ No newline at end of file Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/SurveyExportRow.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/SurveyExportRow.java 2013-04-15 10:40:39 UTC (rev 776) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/SurveyExportRow.java 2013-04-15 14:48:55 UTC (rev 777) @@ -44,12 +44,20 @@ private static final long serialVersionUID = 1L; + public static final String PROPERTY_COUNTRY = "country"; + protected Cruise cruise; + protected TuttiLocation country; + public void setCruise(Cruise cruise) { this.cruise = cruise; } + public void setCountry(TuttiLocation country) { + this.country = country; + } + public Date getBeginDate() { return cruise.getBeginDate(); } @@ -71,8 +79,7 @@ } public String getCountry() { - //FIXME - return null; + return country.getLabel(); } public String getName() { Modified: trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/TuttiExportService.java =================================================================== --- trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/TuttiExportService.java 2013-04-15 10:40:39 UTC (rev 776) +++ trunk/tutti-service/src/main/java/fr/ifremer/tutti/service/export/TuttiExportService.java 2013-04-15 14:48:55 UTC (rev 777) @@ -28,27 +28,40 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.io.Files; +import fr.ifremer.tutti.TuttiBusinessException; import fr.ifremer.tutti.TuttiIOUtil; import fr.ifremer.tutti.TuttiTechnicalException; +import fr.ifremer.tutti.persistence.entities.TuttiEntities; import fr.ifremer.tutti.persistence.entities.data.BatchContainer; +import fr.ifremer.tutti.persistence.entities.data.BenthosBatch; import fr.ifremer.tutti.persistence.entities.data.Cruise; import fr.ifremer.tutti.persistence.entities.data.FishingOperation; +import fr.ifremer.tutti.persistence.entities.data.Program; import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch; import fr.ifremer.tutti.persistence.entities.referential.Caracteristic; +import fr.ifremer.tutti.persistence.entities.referential.TuttiLocation; import fr.ifremer.tutti.service.AbstractTuttiService; import fr.ifremer.tutti.service.DecoratorService; import fr.ifremer.tutti.service.PersistenceService; import fr.ifremer.tutti.service.TuttiCsvUtil; import fr.ifremer.tutti.service.TuttiServiceContext; +import fr.ifremer.tutti.service.catches.TuttiWeightComputingService; +import org.apache.commons.collections.MapUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.nuiton.util.csv.Export; +import org.nuiton.util.decorator.Decorator; import java.io.BufferedWriter; +import java.io.Closeable; import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; import java.util.List; +import java.util.Map; +import static org.nuiton.i18n.I18n._; + /** * To export data in the generic format. * <p/> @@ -66,6 +79,8 @@ protected DecoratorService decoratorService; + protected TuttiWeightComputingService tuttiWeightComputingService; + protected char csvSeparator; private Caracteristic verticalOpeningCaracteristic; @@ -74,17 +89,57 @@ private Caracteristic horizontalOpeningDoorCaracteristic; + private TuttiLocation country; + @Override public void setServiceContext(TuttiServiceContext context) { super.setServiceContext(context); persistenceService = getService(PersistenceService.class); decoratorService = getService(DecoratorService.class); + tuttiWeightComputingService = getService(TuttiWeightComputingService.class); + csvSeparator = context.getConfig().getCsvSeparator(); verticalOpeningCaracteristic = persistenceService.getVerticalOpeningCaracteristic(); horizontalOpeningWingCaracteristic = persistenceService.getHorizontalOpeningWingCaracteristic(); horizontalOpeningDoorCaracteristic = persistenceService.getHorizontalOpeningDoorCaracteristic(); + List<TuttiLocation> allCountry = persistenceService.getAllCountry(); + String countryId = context.getConfig().getExportCountryId(); + country = TuttiEntities.splitById(allCountry).get(countryId); } + public void exportProgram(String programId, File exportFile) { + Preconditions.checkNotNull(programId); + Preconditions.checkNotNull(exportFile); + + Program program = persistenceService.getProgram(programId); + Preconditions.checkNotNull(program); + + List<Cruise> allCruise = persistenceService.getAllCruise(programId); + for (Cruise cruise : allCruise) { + checkCruise(cruise); + } + + File basedir = new File(context.getConfig().newTempFile( + "exportProgram"), "exportProgram-" + programId); + + TuttiIOUtil.forceMkdir(basedir, "Could not create directory"); + + ExportContext exportContext = createExportContext(basedir); + + try { + for (Cruise cruise : allCruise) { + // load full cruise + cruise = persistenceService.getCruise(cruise.getId()); + exportCruise(cruise, exportContext); + } + TuttiIOUtil.close(exportContext, "Could not close export context"); + + TuttiIOUtil.zip(basedir, exportFile, "Could not create export zip"); + } finally { + IOUtils.closeQuietly(exportContext); + } + } + public void exportCruise(String cruiseId, File exportFile) { Preconditions.checkNotNull(cruiseId); @@ -93,155 +148,249 @@ Cruise cruise = persistenceService.getCruise(cruiseId); Preconditions.checkNotNull(cruise); - List<FishingOperation> operations = - persistenceService.getAllFishingOperation(cruiseId); + // check cruise fishing operations + checkCruise(cruise); File basedir = new File(context.getConfig().newTempFile( "exportCruise"), "exportCruise-" + cruiseId); TuttiIOUtil.forceMkdir(basedir, "Could not create directory"); - File surveyFile = new File(basedir, "survey.csv"); - exportSurvey(surveyFile, cruise); - File operationFile = new File(basedir, "operation.csv"); - exportOperations(operationFile, cruise, operations); + ExportContext exportContext = createExportContext(basedir); - File parameterFile = new File(basedir, "parameter.csv"); - exportParameters(parameterFile, cruise, operations); + try { + exportCruise(cruise, exportContext); + TuttiIOUtil.close(exportContext, "Could not close export context"); -// File catchesFile = new File(basedir, "catch.csv"); -// exportCatches(catchesFile, cruise, operations); + TuttiIOUtil.zip(basedir, exportFile, "Could not create export zip"); + } finally { + IOUtils.closeQuietly(exportContext); + } + } - TuttiIOUtil.zip(basedir, exportFile, "Could not create export zip"); + protected ExportContext createExportContext(File basedir) { + return new ExportContext( + basedir, + csvSeparator, + decoratorService, + verticalOpeningCaracteristic, + horizontalOpeningWingCaracteristic, + horizontalOpeningDoorCaracteristic); } - public void exportSurvey(File file, Cruise cruise) { + protected void checkCruise(Cruise cruise) { + Preconditions.checkNotNull(cruise); - if (log.isInfoEnabled()) { - log.info("Will export survey to file: " + file); + // check cruise fishing operations + Map<String, String> errors = + tuttiWeightComputingService.checkCruise(cruise.getId()); + + if (MapUtils.isNotEmpty(errors)) { + + // there is some fishing operations with some errors + + Decorator<Cruise> cruiseDecorator = + decoratorService.getDecoratorByType(Cruise.class); + + Decorator<FishingOperation> fishingOperationDecorator = + decoratorService.getDecoratorByType(FishingOperation.class); + StringBuilder sb = new StringBuilder(); + for (Map.Entry<String, String> entry : errors.entrySet()) { + String fishingOperationId = entry.getKey(); + FishingOperation fishingOperation = persistenceService.getFishingOperation(fishingOperationId); + String fishingOperationStr = fishingOperationDecorator.toString(fishingOperation); + sb.append(_("tutti.service.export.invalid.fishingOperation", fishingOperationStr, entry.getValue())); + } + String cruiseStr = cruiseDecorator.toString(cruise); + throw new TuttiBusinessException( + _("tutti.service.export.invalid.cruise", cruiseStr, sb.toString())); } + } - BufferedWriter writer = null; + protected void exportCruise(Cruise cruise, + ExportContext exportContext) { + + List<FishingOperation> operations = + persistenceService.getAllFishingOperation(cruise.getId()); + + exportSurvey(exportContext, cruise); + + exportOperations(exportContext, cruise, operations); + + exportParameters(exportContext, cruise, operations); + + exportCatches(exportContext, cruise, operations); + } + + protected void exportSurvey(ExportContext exportContext, + Cruise cruise) { try { - writer = Files.newWriter(file, Charsets.UTF_8); - SurveyExportModel model = new SurveyExportModel(csvSeparator); - List<SurveyExportRow> rows = Lists.newArrayList(); - model.prepareRows(rows, cruise); + exportContext.surveyModel.prepareRows(rows, cruise, country); - Export export = Export.newExport(model, rows); - export.write(writer); - writer.close(); + exportContext.surveyExport.write(rows, exportContext.surveyWriter); } catch (Exception e) { throw new TuttiTechnicalException( - "Could not export survey to file: " + file, e); - } finally { - IOUtils.closeQuietly(writer); + "Could not export survey.", e); } } - public void exportOperations(File file, - Cruise cruise, - List<FishingOperation> operations) { + protected void exportOperations(ExportContext exportContext, + Cruise cruise, + List<FishingOperation> operations) { + try { - if (log.isInfoEnabled()) { - log.info("Will export operations to file: " + file); + List<OperationExportRow> rows = Lists.newArrayList(); + exportContext.operationModel.prepareRows(rows, cruise, operations); + exportContext.operationExport.write(rows, exportContext.operationWriter); + } catch (Exception e) { + throw new TuttiTechnicalException( + "Could not export operations.", e); } + } - BufferedWriter writer = null; + protected void exportParameters(ExportContext exportContext, + Cruise cruise, + List<FishingOperation> operations) { + try { - writer = Files.newWriter(file, Charsets.UTF_8); - OperationExportModel model = - new OperationExportModel( - csvSeparator, - verticalOpeningCaracteristic, - horizontalOpeningWingCaracteristic, - horizontalOpeningDoorCaracteristic); + for (FishingOperation operation : operations) { + List<ParameterExportRow> rows = Lists.newArrayList(); + exportContext.parameterModel.prepareRows(rows, cruise, operation); + exportContext.parameterExport.write(rows, exportContext.parameterWriter); + } - List<OperationExportRow> rows = Lists.newArrayList(); - model.prepareRows(rows, cruise, operations); - - Export export = Export.newExport(model, rows); - export.write(writer); - writer.close(); } catch (Exception e) { throw new TuttiTechnicalException( - "Could not export operations to file: " + file, e); - } finally { - IOUtils.closeQuietly(writer); + "Could not export parameters.", e); } } - public void exportParameters(File file, + protected void exportCatches(ExportContext exportContext, Cruise cruise, List<FishingOperation> operations) { - if (log.isInfoEnabled()) { - log.info("Will export parameters to file: " + file); - } - - BufferedWriter writer = null; try { - writer = Files.newWriter(file, Charsets.UTF_8); - ParameterExportModel model = - new ParameterExportModel(csvSeparator, - decoratorService); + for (FishingOperation operation : operations) { - TuttiCsvUtil.TuttiRepeatableExport<ParameterExportRow> export = - TuttiCsvUtil.newRepeatableExport(model); + BatchContainer<SpeciesBatch> rootSpeciesBatch = + persistenceService.getRootSpeciesBatch(operation.getId()); - for (FishingOperation operation : operations) { - List<ParameterExportRow> rows = Lists.newArrayList(); - model.prepareRows(rows, cruise, operation); - export.write(rows, writer); + BatchContainer<BenthosBatch> rootBenthosBatch = + persistenceService.getRootBenthosBatch(operation.getId()); + + List<CatchExportRow> rows = Lists.newArrayList(); + exportContext.catchModel.prepareRows(rows, + cruise, + operation, + rootSpeciesBatch, + rootBenthosBatch); +// exportContext.catchExport.write(rows, exportContext.catchWriter); } - writer.close(); } catch (Exception e) { throw new TuttiTechnicalException( - "Could not export parameters to file: " + file, e); - } finally { - IOUtils.closeQuietly(writer); + "Could not export catches.", e); } } - public void exportCatches(File file, - Cruise cruise, - List<FishingOperation> operations) { + protected static class ExportContext implements Closeable { - if (log.isInfoEnabled()) { - log.info("Will export catches to file: " + file); - } + File surveyFile; - BufferedWriter writer = null; - try { - writer = Files.newWriter(file, Charsets.UTF_8); + File operationFile; - CatchExportModel model = new CatchExportModel(csvSeparator); + File parameterFile; - TuttiCsvUtil.TuttiRepeatableExport<CatchExportRow> export = - TuttiCsvUtil.newRepeatableExport(model); + File catchFile; - for (FishingOperation operation : operations) { + BufferedWriter surveyWriter; - BatchContainer<SpeciesBatch> rootSpeciesBatch = - persistenceService.getRootSpeciesBatch(operation.getId()); + BufferedWriter operationWriter; - List<CatchExportRow> rows = Lists.newArrayList(); - model.prepareRows(rows, cruise, operation, rootSpeciesBatch); - export.write(rows, writer); + BufferedWriter parameterWriter; + + BufferedWriter catchWriter; + + SurveyExportModel surveyModel; + + OperationExportModel operationModel; + + ParameterExportModel parameterModel; + + CatchExportModel catchModel; + + TuttiCsvUtil.TuttiRepeatableExport<SurveyExportRow> surveyExport; + + TuttiCsvUtil.TuttiRepeatableExport<OperationExportRow> operationExport; + + TuttiCsvUtil.TuttiRepeatableExport<ParameterExportRow> parameterExport; + + TuttiCsvUtil.TuttiRepeatableExport<CatchExportRow> catchExport; + + ExportContext(File basedir, + char csvSeparator, + DecoratorService decoratorService, + Caracteristic verticalOpeningCaracteristic, + Caracteristic horizontalOpeningWingCaracteristic, + Caracteristic horizontalOpeningDoorCaracteristic) { + + try { + + surveyFile = new File(basedir, "survey.csv"); + surveyWriter = Files.newWriter(surveyFile, Charsets.UTF_8); + + operationFile = new File(basedir, "operation.csv"); + operationWriter = Files.newWriter(operationFile, Charsets.UTF_8); + + parameterFile = new File(basedir, "parameter.csv"); + parameterWriter = Files.newWriter(parameterFile, Charsets.UTF_8); + + catchFile = new File(basedir, "catch.csv"); + catchWriter = Files.newWriter(catchFile, Charsets.UTF_8); + + } catch (FileNotFoundException e) { + + // should never happen + throw new TuttiTechnicalException( + "Could not create writer for export", e); } - writer.close(); - } catch (Exception e) { - throw new TuttiTechnicalException( - "Could not export catches to file: " + file, e); - } finally { - IOUtils.closeQuietly(writer); + surveyModel = new SurveyExportModel(csvSeparator); + + operationModel = + new OperationExportModel( + csvSeparator, + verticalOpeningCaracteristic, + horizontalOpeningWingCaracteristic, + horizontalOpeningDoorCaracteristic); + + parameterModel = new ParameterExportModel( + csvSeparator, decoratorService); + catchModel = new CatchExportModel(csvSeparator); + + surveyExport = TuttiCsvUtil.newRepeatableExport( + surveyModel); + + operationExport = TuttiCsvUtil.newRepeatableExport( + operationModel); + + parameterExport = TuttiCsvUtil.newRepeatableExport( + parameterModel); + + catchExport = TuttiCsvUtil.newRepeatableExport(catchModel); } + + @Override + public void close() throws IOException { + IOUtils.closeQuietly(surveyWriter); + IOUtils.closeQuietly(operationWriter); + IOUtils.closeQuietly(parameterWriter); + IOUtils.closeQuietly(catchWriter); + } } } Modified: trunk/tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties =================================================================== --- trunk/tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties 2013-04-15 10:40:39 UTC (rev 776) +++ trunk/tutti-service/src/main/resources/i18n/tutti-service_fr_FR.properties 2013-04-15 14:48:55 UTC (rev 777) @@ -1,6 +1,7 @@ tutti.config.option.basedir.description=Répertoire principale tutti.config.option.csv.separator.description=Caractère séparateur pour les import / export de fichier au format csv. tutti.config.option.data.directory.description=Répertoire de données de l'application. Vous pouvez utiliser l'expression ${tutti.data.directory} pour le référence dans d'autres propriétés de configuration (ex\: ${tutti.data.directory}/tmp). +tutti.config.option.export.countryId.description=L'id du pays à utiliser pour les exports (il s'agit de la valeur LOCATION.ID). tutti.config.option.inceptionYear.description=Année de démarrage du projet. tutti.config.option.organizationName.description=Nom de l'organisation dans la licence tutti.config.option.site.url.description=Url du site internet de l'application @@ -43,7 +44,7 @@ tutti.propety.no.vessel.name=Nom inconnu tutti.propety.no.zone=Pas de zone tutti.propety.vessel.nation.registrationCode=%s (nat.) -tutti.service.catches.computeWeights.error.incoherentBenthosTotalSorted= +tutti.service.catches.computeWeights.error.incoherentBenthosTotalSorted=Le poids total Vrac du benthos est inférieur à la somme des poids Vrac triés, inerte trié et vivant non détaillé trié tutti.service.catches.computeWeights.error.incoherentCategoryWeight=Le poids total des mensurations est supérieur au poids de la catégorie tutti.service.catches.computeWeights.error.incoherentMarineLitterTotal=Le poids total des macro-déchets est inférieur à la somme des poids des macro-déchets saisis tutti.service.catches.computeWeights.error.incoherentParentCategoryWeight=Le poids de la catégorie est différent de la somme des poids de ses sous-catégories @@ -52,6 +53,8 @@ tutti.service.catches.computeWeights.error.incoherentSampleWeight=Le poids de sous-échantillonage est supérieur au poids de la catégorie tutti.service.catches.computeWeights.error.incoherentSpeciesTotalSorted=Le poids total Vrac des espèces est inférieur à la somme des poids Vrac triés, inerte trié et vivant non détaillé trié tutti.service.catches.computeWeights.error.incoherentTotal=Le poids total de la capture ne correspond pas à la somme des poids totaux Vrac, Hors Vrac et non triés +tutti.service.export.invalid.cruise=L'export de la campagne %s ne peut pas être réalisé suite aux erreurs rencontrées sur ses traits lors de l'élévation des poids \:\n%s +tutti.service.export.invalid.fishingOperation=L'élévation des poids ne peut pas être réalisé sur le trait %s, pour la raison suivante %s tutti.validator.error.comment.too.long=Taille de commentaire trop longue (limitée à %s caractères) tutti.validator.error.cruise.beginDate.required=La date de début est obligatoire tutti.validator.error.cruise.dates.endBeforeStart=La date de fin doit être après la date de début Modified: trunk/tutti-service/src/test/java/fr/ifremer/tutti/service/export/TuttiExportServiceTest.java =================================================================== --- trunk/tutti-service/src/test/java/fr/ifremer/tutti/service/export/TuttiExportServiceTest.java 2013-04-15 10:40:39 UTC (rev 776) +++ trunk/tutti-service/src/test/java/fr/ifremer/tutti/service/export/TuttiExportServiceTest.java 2013-04-15 14:48:55 UTC (rev 777) @@ -42,6 +42,7 @@ import fr.ifremer.tutti.service.AbstractServiceTest; import fr.ifremer.tutti.service.PersistenceService; import fr.ifremer.tutti.service.TuttiServiceContext; +import fr.ifremer.tutti.service.catches.TuttiWeightComputingService; import fr.ifremer.tutti.service.config.TuttiServiceConfig; import org.apache.commons.io.Charsets; import org.apache.commons.lang3.time.DateUtils; @@ -68,6 +69,10 @@ protected TuttiExportService service; + protected List<TuttiLocation> countries; + + protected Program program; + protected Cruise cruise; protected List<FishingOperation> operations; @@ -84,6 +89,10 @@ createCaracteristics(); + countries = createCountries(); + + program = createProgram(); + cruise = createCruise(); operations = createOperations(cruise); @@ -95,7 +104,10 @@ Mockito.when(persistenceService.getVerticalOpeningCaracteristic()).thenReturn(caracteristicVerticalOpening); Mockito.when(persistenceService.getHorizontalOpeningDoorCaracteristic()).thenReturn(caracteristicHorizontalOpeningDoor); Mockito.when(persistenceService.getHorizontalOpeningWingCaracteristic()).thenReturn(caracteristicHorizontalOpeningWing); + Mockito.when(persistenceService.getProgram(Mockito.<String>any())).thenReturn(program); Mockito.when(persistenceService.getCruise(Mockito.<String>any())).thenReturn(cruise); + Mockito.when(persistenceService.getAllCruise(Mockito.<String>any())).thenReturn(Lists.newArrayList(cruise)); + Mockito.when(persistenceService.getAllCountry()).thenReturn(countries); Mockito.when(persistenceService.getAllFishingOperation(Mockito.<String>any())).thenReturn(operations); TuttiServiceContext serviceContextSpy = Mockito.spy(serviceContext); @@ -104,91 +116,132 @@ service = Mockito.mock(TuttiExportService.class, Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS)); service.setServiceContext(serviceContextSpy); + + TuttiWeightComputingService tuttiWeightComputingService = Mockito.mock( + TuttiWeightComputingService.class, + Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS)); + tuttiWeightComputingService.setServiceContext(serviceContextSpy); + service.tuttiWeightComputingService = tuttiWeightComputingService; + + } @Test - public void exportCruise() throws Exception { + public void exportProgram() throws Exception { - File exportFile = new File(datadirectory, "exportCruise.zip"); + File exportFile = new File(datadirectory, "exportProgram.zip"); Files.createParentDirs(exportFile); Assert.assertFalse(exportFile.exists()); - service.exportCruise(cruise.getId(), exportFile); + service.exportProgram(cruise.getId(), exportFile); Assert.assertTrue(exportFile.exists()); } @Test - public void exportSurvey() throws Exception { + public void exportCruise() throws Exception { - File exportFile = new File(datadirectory, "exportSurvey.csv"); + File exportFile = new File(datadirectory, "exportCruise.zip"); Files.createParentDirs(exportFile); Assert.assertFalse(exportFile.exists()); - service.exportSurvey(exportFile, cruise); + service.exportCruise(cruise.getId(), exportFile); Assert.assertTrue(exportFile.exists()); + } + @Test + public void exportSurvey() throws Exception { + + TuttiExportService.ExportContext exportContext = + service.createExportContext(datadirectory); + + try { + service.exportSurvey(exportContext, cruise); + } finally { + exportContext.close(); + } + Assert.assertTrue(exportContext.surveyFile.exists()); + Assert.assertEquals(Files.readLines(exportContext.surveyFile, Charsets.UTF_8).size(), 1 + 1); + if (log.isInfoEnabled()) { log.info("Survey export:\n" + - Files.toString(exportFile, Charsets.UTF_8)); + Files.toString(exportContext.surveyFile, Charsets.UTF_8)); } } @Test public void exportOperations() throws Exception { - File exportFile = new File(datadirectory, "exportOperations.csv"); + TuttiExportService.ExportContext exportContext = + service.createExportContext(datadirectory); - Files.createParentDirs(exportFile); + try { + service.exportOperations(exportContext, cruise, operations); + } finally { + exportContext.close(); + } + Assert.assertTrue(exportContext.operationFile.exists()); + Assert.assertEquals(Files.readLines(exportContext.operationFile, Charsets.UTF_8).size(), operations.size() + 1); - Assert.assertFalse(exportFile.exists()); - - service.exportOperations(exportFile, cruise, operations); - Assert.assertTrue(exportFile.exists()); - if (log.isInfoEnabled()) { log.info("Operation export:\n" + - Files.toString(exportFile, Charsets.UTF_8)); + Files.toString(exportContext.operationFile, Charsets.UTF_8)); } } @Test public void exportParameters() throws Exception { - File exportFile = new File(datadirectory, "exportParameters.csv"); + TuttiExportService.ExportContext exportContext = + service.createExportContext(datadirectory); - Files.createParentDirs(exportFile); + try { + service.exportParameters(exportContext, cruise, operations); + } finally { + exportContext.close(); + } + Assert.assertTrue(exportContext.parameterFile.exists()); + Assert.assertEquals(Files.readLines(exportContext.parameterFile, Charsets.UTF_8).size(), 1 + operations.size() * 7); - Assert.assertFalse(exportFile.exists()); - - service.exportParameters(exportFile, cruise, operations); - Assert.assertTrue(exportFile.exists()); - if (log.isInfoEnabled()) { log.info("Parameter export:\n" + - Files.toString(exportFile, Charsets.UTF_8)); + Files.toString(exportContext.parameterFile, Charsets.UTF_8)); } } //TODO public void exportCatches() throws Exception { - File exportFile = new File(datadirectory, "exportCatches.csv"); + TuttiExportService.ExportContext exportContext = + service.createExportContext(datadirectory); - Files.createParentDirs(exportFile); - - Assert.assertFalse(exportFile.exists()); - + try { + service.exportCatches(exportContext, cruise, operations); + } finally { + exportContext.close(); + } + Assert.assertTrue(exportContext.catchFile.exists()); + Assert.assertEquals(Files.readLines(exportContext.catchFile, Charsets.UTF_8).size(), 2); if (log.isInfoEnabled()) { log.info("Catch export:\n" + - Files.toString(exportFile, Charsets.UTF_8)); + Files.toString(exportContext.catchFile, Charsets.UTF_8)); } } - private Cruise createCruise() { + private List<TuttiLocation> createCountries() { + List<TuttiLocation> result = Lists.newArrayList(); + TuttiLocation country = TuttiBeanFactory.newTuttiLocation(); + country.setId(serviceContext.getConfig().getExportCountryId()); + country.setName("CountryName"); + country.setLabel("CountryLabel"); + result.add(country); + return result; + } + + private Program createProgram() { TuttiLocation programZone = TuttiBeanFactory.newTuttiLocation(); programZone.setId(0); programZone.setName("ProgramZoneName"); @@ -208,7 +261,21 @@ program.setId(1); program.setName("ProgramName"); program.setZone(programZone); + return program; + } + private Cruise createCruise() { + + TuttiLocation departureLocation = TuttiBeanFactory.newTuttiLocation(); + departureLocation.setId(1); + departureLocation.setName("DepartureLocationName"); + departureLocation.setLabel("DepartureLocationLabel"); + + TuttiLocation returnLocation = TuttiBeanFactory.newTuttiLocation(); + returnLocation.setId(2); + returnLocation.setName("ReturnLocationName"); + returnLocation.setLabel("ReturnLocationLabel"); + Cruise cruise = TuttiBeanFactory.newCruise(); cruise.setId(2); cruise.setName("CruiseName");