View Javadoc
1   package fr.ifremer.tutti.service.operationimport;
2   
3   /*
4    * #%L
5    * Tutti :: Service
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2012 - 2014 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU General Public License as
13   * published by the Free Software Foundation, either version 3 of the
14   * License, or (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public
22   * License along with this program.  If not, see
23   * <http://www.gnu.org/licenses/gpl-3.0.html>.
24   * #L%
25   */
26  
27  import com.google.common.base.Predicate;
28  import com.google.common.collect.Maps;
29  import fr.ifremer.tutti.persistence.entities.data.FishingOperation;
30  import fr.ifremer.tutti.persistence.entities.protocol.OperationFieldMappingRow;
31  import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocol;
32  import fr.ifremer.tutti.service.AbstractTuttiService;
33  import fr.ifremer.tutti.service.PersistenceService;
34  import fr.ifremer.tutti.service.TuttiDataContext;
35  import fr.ifremer.tutti.service.TuttiServiceContext;
36  import fr.ifremer.tutti.service.protocol.ProtocolCaracteristicsImportExportService;
37  import org.apache.commons.lang3.StringUtils;
38  import org.nuiton.csv.AbstractImportErrorInfo;
39  import org.nuiton.csv.Import2;
40  import org.nuiton.csv.ImportConf;
41  import org.nuiton.csv.ImportRow;
42  import org.nuiton.jaxx.application.ApplicationTechnicalException;
43  import org.nuiton.util.DateUtil;
44  
45  import java.io.File;
46  import java.io.FileInputStream;
47  import java.io.FileNotFoundException;
48  import java.io.IOException;
49  import java.util.Date;
50  import java.util.HashSet;
51  import java.util.List;
52  import java.util.Map;
53  import java.util.Objects;
54  import java.util.Set;
55  
56  /**
57   * Created on 12/11/14.
58   *
59   * @author Tony Chemit - chemit@codelutin.com
60   * @since 3.10
61   */
62  public class FishingOperationImportService extends AbstractTuttiService {
63  
64      protected PersistenceService persistenceService;
65  
66      private TuttiDataContext dataContext;
67  
68      @Override
69      public void setServiceContext(TuttiServiceContext context) {
70          super.setServiceContext(context);
71          persistenceService = getService(PersistenceService.class);
72          dataContext = context.getDataContext();
73      }
74  
75      public void importCaracteristicsFromColumnFile(File columnsFile, FishingOperation fishingoperation) throws ImportFromColumnFileInvalidRowException, ImportFromColumnFileFishingOperationNotFoundException, ImportFromColumnFileMissingHeaderException, IOException {
76  
77          // Get import file headers
78          List<String> headers =getService(ProtocolCaracteristicsImportExportService.class).loadProtocolCaracteristicsImportColumns(columnsFile);
79  
80          // Create import model
81          ImportFromColumnFileModel importModel = new ImportFromColumnFileModel(';', new HashSet<>(headers), persistenceService, dataContext, fishingoperation);
82          ImportConf conf = new ImportConf();
83          conf.setStrictMode(false);
84  
85          // Create matching row predicate
86          MatchingFishingOperationNaturalIdPredicate matchingRowPredicate = new MatchingFishingOperationNaturalIdPredicate(
87                  fishingoperation.getStationNumber(),
88                  fishingoperation.getFishingOperationNumber(),
89                  fishingoperation.getGearShootingStartDate(),
90                  dataContext.getProtocol());
91  
92          try (Import2<FishingOperation> operationUIModelImport = Import2.newImport(conf, importModel, new FileInputStream(columnsFile))) {
93  
94              doImport(operationUIModelImport, matchingRowPredicate);
95  
96          } catch (FileNotFoundException e) {
97              throw new ApplicationTechnicalException("Could not find import file " + columnsFile);
98          }
99  
100     }
101 
102     protected void doImport(Import2<FishingOperation> operationUIModelImport,
103                             MatchingFishingOperationNaturalIdPredicate matchingRowPredicate) throws ImportFromColumnFileInvalidRowException, ImportFromColumnFileFishingOperationNotFoundException {
104 
105 
106         boolean found = false;
107         for (ImportRow<FishingOperation> next : operationUIModelImport) {
108 
109             FishingOperation fishingOperation = next.getBean();
110 
111             if (matchingRowPredicate.apply(fishingOperation)) {
112                 if (!next.isValid()) {
113 
114                     Set<AbstractImportErrorInfo<FishingOperation>> errors = next.getErrors();
115                     throw new ImportFromColumnFileInvalidRowException(errors);
116 
117                 }
118 
119                 // valid row was found
120                 // can quit right now the import
121                 found = true;
122 
123                 break;
124             }
125 
126         }
127 
128         if (!found) {
129             throw new ImportFromColumnFileFishingOperationNotFoundException();
130         }
131 
132     }
133 
134     protected static class MatchingFishingOperationNaturalIdPredicate implements Predicate<FishingOperation> {
135 
136         protected final String stationNumber;
137 
138         protected final Integer fishingOperationNumber;
139 
140         protected final Date modelGearShootingStartOnlyDate;
141 
142         protected final Map<String, OperationFieldMappingRow> mappingRowsByField;
143 
144         MatchingFishingOperationNaturalIdPredicate(String stationNumber,
145                                                    Integer fishingOperationNumber,
146                                                    Date modelGearShootingStartDate,
147                                                    TuttiProtocol protocol) {
148             this.stationNumber = stationNumber;
149             this.fishingOperationNumber = fishingOperationNumber;
150 
151             if (modelGearShootingStartDate != null) {
152                 this.modelGearShootingStartOnlyDate = DateUtil.getDay(modelGearShootingStartDate);
153             } else {
154                 this.modelGearShootingStartOnlyDate = null;
155             }
156 
157             this.mappingRowsByField = Maps.uniqueIndex(protocol.getOperationFieldMapping(), OperationFieldMappingRow::getField);
158         }
159 
160         @Override
161         public boolean apply(FishingOperation fishingOperation) {
162 
163             OperationFieldMappingRow operationNumberRow = mappingRowsByField.get(FishingOperation.PROPERTY_FISHING_OPERATION_NUMBER);
164             OperationFieldMappingRow stationNumberRow = mappingRowsByField.get(FishingOperation.PROPERTY_STATION_NUMBER);
165             OperationFieldMappingRow startDateRow = mappingRowsByField.get(FishingOperation.PROPERTY_GEAR_SHOOTING_START_DATE);
166 
167             String operationNumberColumn = operationNumberRow != null ? operationNumberRow.getImportColumn() : null;
168             String stationColumn = stationNumberRow != null ? stationNumberRow.getImportColumn() : null;
169             String startDateColumn = startDateRow != null ? startDateRow.getImportColumn() : null;
170 
171             boolean sameStationNumber = Objects.equals(fishingOperation.getStationNumber(), stationNumber);
172             boolean sameFishingOperationNumber = Objects.equals(fishingOperation.getFishingOperationNumber(), fishingOperationNumber);
173             // check if the dates (not time) are equals, but push the time to the model
174             Date gearShootingStartDate = fishingOperation.getGearShootingStartDate();
175             if (gearShootingStartDate != null) {
176                 gearShootingStartDate = DateUtil.getDay(gearShootingStartDate);
177             }
178             boolean sameGearShootingStartDate = Objects.equals(modelGearShootingStartOnlyDate, gearShootingStartDate);
179 
180             return (StringUtils.isBlank(stationColumn) || sameStationNumber)
181                    && (StringUtils.isBlank(operationNumberColumn) || sameFishingOperationNumber)
182                    && (StringUtils.isBlank(startDateColumn) || sameGearShootingStartDate);
183         }
184     }
185 
186 }