1 package fr.ifremer.tutti.service.operationimport;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
58
59
60
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
78 List<String> headers =getService(ProtocolCaracteristicsImportExportService.class).loadProtocolCaracteristicsImportColumns(columnsFile);
79
80
81 ImportFromColumnFileModel importModel = new ImportFromColumnFileModel(';', new HashSet<>(headers), persistenceService, dataContext, fishingoperation);
82 ImportConf conf = new ImportConf();
83 conf.setStrictMode(false);
84
85
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
120
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
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 }