1 package fr.ifremer.dali.dao.administration.strategy;
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 import com.google.common.base.Joiner;
27 import com.google.common.collect.*;
28 import fr.ifremer.dali.config.DaliConfiguration;
29 import fr.ifremer.dali.dao.administration.user.DaliDepartmentDao;
30 import fr.ifremer.dali.dao.referential.DaliReferentialDao;
31 import fr.ifremer.dali.dao.referential.monitoringLocation.DaliMonitoringLocationDao;
32 import fr.ifremer.dali.dao.referential.pmfm.DaliPmfmDao;
33 import fr.ifremer.dali.dao.technical.Daos;
34 import fr.ifremer.dali.dto.DaliBeanFactory;
35 import fr.ifremer.dali.dto.DaliBeans;
36 import fr.ifremer.dali.dto.configuration.programStrategy.*;
37 import fr.ifremer.dali.dto.referential.DepartmentDTO;
38 import fr.ifremer.dali.dto.referential.LocationDTO;
39 import fr.ifremer.dali.service.DaliTechnicalException;
40 import fr.ifremer.quadrige3.core.dao.administration.program.ProgramImpl;
41 import fr.ifremer.quadrige3.core.dao.administration.strategy.*;
42 import fr.ifremer.quadrige3.core.dao.administration.user.DepartmentImpl;
43 import fr.ifremer.quadrige3.core.dao.administration.user.QuserImpl;
44 import fr.ifremer.quadrige3.core.dao.referential.AcquisitionLevel;
45 import fr.ifremer.quadrige3.core.dao.referential.AcquisitionLevelCode;
46 import fr.ifremer.quadrige3.core.dao.referential.AcquisitionLevelImpl;
47 import fr.ifremer.quadrige3.core.dao.referential.monitoringLocation.MonitoringLocationImpl;
48 import fr.ifremer.quadrige3.core.dao.referential.pmfm.PmfmImpl;
49 import fr.ifremer.quadrige3.core.dao.system.synchronization.SynchronizationStatus;
50 import fr.ifremer.quadrige3.core.dao.technical.Assert;
51 import fr.ifremer.quadrige3.core.dao.technical.Dates;
52 import fr.ifremer.quadrige3.core.dao.technical.hibernate.TemporaryDataHelper;
53 import fr.ifremer.quadrige3.core.exception.SaveForbiddenException;
54 import fr.ifremer.quadrige3.ui.core.dto.QuadrigeBeanComparator;
55 import fr.ifremer.quadrige3.ui.core.dto.QuadrigeBeans;
56 import org.apache.commons.collections4.CollectionUtils;
57 import org.apache.commons.lang3.BooleanUtils;
58 import org.apache.commons.logging.Log;
59 import org.apache.commons.logging.LogFactory;
60 import org.hibernate.Query;
61 import org.hibernate.SessionFactory;
62 import org.hibernate.type.DateType;
63 import org.hibernate.type.IntegerType;
64 import org.hibernate.type.StringType;
65 import org.springframework.beans.factory.annotation.Autowired;
66 import org.springframework.stereotype.Repository;
67
68 import javax.annotation.Resource;
69 import java.time.LocalDate;
70 import java.time.format.DateTimeFormatter;
71 import java.util.*;
72 import java.util.stream.Collectors;
73
74
75
76
77
78
79 @Repository("daliStrategyDao")
80 public class DaliStrategyDaoImpl extends StrategyDaoImpl implements DaliStrategyDao {
81
82 private static final Log LOG = LogFactory.getLog(DaliStrategyDaoImpl.class);
83 private static final String DATE_PATTERN = "yyyyMMdd";
84
85 @Resource(name = "daliDepartmentDao")
86 protected DaliDepartmentDao departmentDao;
87
88 @Resource(name = "daliPmfmDao")
89 protected DaliPmfmDao pmfmDao;
90
91 @Resource(name = "daliMonitoringLocationDao")
92 protected DaliMonitoringLocationDao monitoringLocationDao;
93
94 @Resource
95 protected DaliConfiguration config;
96
97 @Resource(name = "daliReferentialDao")
98 protected DaliReferentialDao referentialDao;
99
100 @Resource()
101 protected AppliedStrategyDao appliedStrategyDao;
102
103 @Resource()
104 protected PmfmStrategyDaoImpl pmfmStrategyDao;
105
106
107
108
109
110
111 @Autowired
112 public DaliStrategyDaoImpl(SessionFactory sessionFactory) {
113 super(sessionFactory);
114 }
115
116
117 @Override
118 public List<StrategyDTO> getStrategiesByProgramCode(String programCode) {
119
120 Iterator<Object[]> rows = queryIterator("strategiesByProgramCode",
121 "programCode", StringType.INSTANCE, programCode);
122
123 List<StrategyDTO> result = Lists.newArrayList();
124 while (rows.hasNext()) {
125 Object[] row = rows.next();
126 result.add(toStrategyDTO(Arrays.asList(row).iterator()));
127 }
128
129 return ImmutableList.copyOf(result);
130
131 }
132
133
134 @Override
135 public List<AppliedStrategyDTO> getAppliedStrategiesByProgramCode(String programCode) {
136
137 Iterator<Object[]> rows = queryIterator("appliedStrategiesByProgramCode",
138 "programCode", StringType.INSTANCE, programCode);
139
140 List<AppliedStrategyDTO> result = Lists.newArrayList();
141 while (rows.hasNext()) {
142 Iterator<Object> row = Arrays.asList(rows.next()).iterator();
143 result.add(toAppliedStrategyDTO(row));
144 }
145
146 return ImmutableList.copyOf(result);
147 }
148
149
150 @Override
151 public List<AppliedStrategyDTO> getAppliedStrategiesByStrategyId(Integer strategyId) {
152
153 Iterator<Object[]> rows = queryIterator("appliedStrategiesByStrategyId",
154 "strategyId", IntegerType.INSTANCE, strategyId);
155
156 List<AppliedStrategyDTO> result = Lists.newArrayList();
157 while (rows.hasNext()) {
158 Iterator<Object> row = Arrays.asList(rows.next()).iterator();
159 result.add(toAppliedStrategyDTO(row));
160 }
161
162 return ImmutableList.copyOf(result);
163 }
164
165
166 @Override
167 public List<AppliedStrategyDTO> getAppliedPeriodsByStrategyId(Integer strategyId) {
168
169 Iterator<Object[]> rows = queryIterator("appliedPeriodsByStrategyId",
170 "strategyId", IntegerType.INSTANCE, strategyId);
171
172 TimeZone dbTimezone = config.getDbTimezone();
173 List<AppliedStrategyDTO> result = Lists.newArrayList();
174 while (rows.hasNext()) {
175 Iterator<Object> row = Arrays.asList(rows.next()).iterator();
176 result.add(toAppliedPeriod(row, dbTimezone));
177 }
178
179 return ImmutableList.copyOf(result);
180 }
181
182
183 @Override
184 public Multimap<Integer, AppliedStrategyDTO> getAllAppliedPeriodsByProgramCode(String programCode) {
185
186 Iterator<Object[]> rows = queryIterator("allAppliedPeriodsByProgramCode",
187 "programCode", StringType.INSTANCE, programCode);
188
189 Multimap<Integer, AppliedStrategyDTO> result = ArrayListMultimap.create();
190 TimeZone dbTimezone = config.getDbTimezone();
191 while (rows.hasNext()) {
192 Iterator<Object> row = Arrays.asList(rows.next()).iterator();
193 Integer strategyId = (Integer) row.next();
194 AppliedStrategyDTO appliedStrategy = toAppliedPeriod(row, dbTimezone);
195 result.put(strategyId, appliedStrategy);
196 }
197
198 return result;
199 }
200
201
202 @Override
203 public List<PmfmStrategyDTO> getPmfmsAppliedStrategy(Integer strategyId) {
204
205 Iterator<Object[]> rows = queryIterator("pmfmsAppliedStrategyByStrategyId",
206 "strategyId", IntegerType.INSTANCE, strategyId);
207
208 List<PmfmStrategyDTO> result = Lists.newArrayList();
209 PmfmStrategyDTO previousDTO = null;
210 while (rows.hasNext()) {
211 Iterator<Object> row = Arrays.asList(rows.next()).iterator();
212 PmfmStrategyDTO currentDTO = toPmfmStrategyDTO(row);
213 if (previousDTO != null) {
214
215 if (Objects.equals(previousDTO, currentDTO)) {
216 currentDTO = previousDTO;
217 }
218
219 else {
220 result.add(previousDTO);
221 previousDTO = currentDTO;
222 }
223 } else {
224 previousDTO = currentDTO;
225 }
226
227 String acquisitionLevelCode = (String) row.next();
228 currentDTO.setSurvey(BooleanUtils.toBoolean(currentDTO.isSurvey())
229 || AcquisitionLevelCode.SURVEY.getValue().equals(acquisitionLevelCode));
230 currentDTO.setSampling(BooleanUtils.toBoolean(currentDTO.isSampling())
231 || AcquisitionLevelCode.SAMPLING_OPERATION.getValue().equals(acquisitionLevelCode));
232 }
233
234 if (previousDTO != null) {
235 result.add(previousDTO);
236 }
237
238
239 fillQualitativeValues(result);
240
241 return ImmutableList.copyOf(result);
242 }
243
244
245 @Override
246 public Set<PmfmStrategyDTO> getPmfmStrategiesByProgramCodeAndLocation(String programCode, Integer monitoringLocationId, LocalDate date) {
247 Assert.notBlank(programCode);
248 Assert.notNull(monitoringLocationId);
249 Assert.notNull(date);
250
251 List<ProgStratDTO> appliedStrategies = getAppliedStrategiesByProgramCodeAndMonitoringLocationId(programCode, monitoringLocationId);
252 Set<PmfmStrategyDTO> pmfmStrategies = Sets.newHashSet();
253
254 for (ProgStratDTO appliedStrategy : appliedStrategies) {
255
256 if (appliedStrategy.getStartDate() != null && appliedStrategy.getEndDate() != null && Dates.isBetween(date, appliedStrategy.getStartDate(), appliedStrategy.getEndDate())) {
257 pmfmStrategies.addAll(getPmfmsAppliedStrategy(appliedStrategy.getId()));
258 }
259 }
260
261 return ImmutableSet.copyOf(pmfmStrategies);
262 }
263
264 @Override
265 public Set<PmfmStrategyDTO> getPmfmStrategiesByProgramCodesAndDates(Collection<String> programCodes, LocalDate startDate, LocalDate endDate) {
266 Set<PmfmStrategyDTO> pmfmStrategies = new HashSet<>();
267
268 List<ProgStratDTO> appliedStrategies = getAppliedStrategiesByProgramCodes(programCodes);
269 for (ProgStratDTO appliedStrategy: appliedStrategies) {
270
271 if (appliedStrategy.getStartDate() != null && appliedStrategy.getEndDate() != null
272 && !appliedStrategy.getStartDate().isAfter(endDate) && !appliedStrategy.getEndDate().isBefore(startDate)) {
273
274 pmfmStrategies.addAll(getPmfmsAppliedStrategy(appliedStrategy.getId()));
275 }
276 }
277
278 return ImmutableSet.copyOf(pmfmStrategies);
279
280 }
281
282
283 @Override
284 public List<ProgStratDTO> getAppliedStrategiesByProgramCodeAndMonitoringLocationId(String programCode, int monitoringLocationId) {
285 Iterator<Object[]> rows = queryIterator("appliedStrategiesByProgramCodeAndMonitoringLocationId",
286 "programCode", StringType.INSTANCE, programCode,
287 "monitoringLocationId", IntegerType.INSTANCE, monitoringLocationId);
288
289 List<ProgStratDTO> result = Lists.newArrayList();
290 TimeZone dbTimezone = config.getDbTimezone();
291 while (rows.hasNext()) {
292 result.add(toProgStratDTO(Arrays.asList(rows.next()).iterator(), dbTimezone));
293 }
294
295 return ImmutableList.copyOf(result);
296 }
297
298 @SuppressWarnings("unchecked")
299 private List<ProgStratDTO> getAppliedStrategiesByProgramCodes(Collection<String> programCodes) {
300 Query query = createQuery("appliedStrategiesByProgramCodes").setParameterList("programCodes", programCodes);
301 Iterator<Object[]> rows = query.iterate();
302
303 List<ProgStratDTO> result = Lists.newArrayList();
304 TimeZone dbTimezone = config.getDbTimezone();
305 while (rows.hasNext()) {
306 result.add(toProgStratDTO(Arrays.asList(rows.next()).iterator(), dbTimezone));
307 }
308
309 return result;
310 }
311
312 @Override
313 public DepartmentDTO getAnalysisDepartmentByAppliedStrategyId(int appliedStrategyId) {
314
315 List<Integer> depIds = queryListTyped("analysisDepartmentByAppliedStrategyId",
316 "appliedStrategyId", IntegerType.INSTANCE, appliedStrategyId);
317
318 depIds = depIds.stream().filter(Objects::nonNull).collect(Collectors.toList());
319
320 if (CollectionUtils.isEmpty(depIds)) {
321 return null;
322 } else if (depIds.size() > 1) {
323
324 LOG.warn(String.format("More than one analysis department %s for applied strategy %s", depIds, appliedStrategyId));
325 }
326
327 return departmentDao.getDepartmentById(depIds.get(0));
328
329 }
330
331
332 @Override
333 public void saveStrategies(ProgramDTO program) {
334 Assert.notNull(program);
335 Assert.notBlank(program.getCode());
336
337 List<Integer> remainingStrategieIds = queryListTyped("stratIdsByProgCd",
338 "programCode", StringType.INSTANCE, program.getCode());
339
340 for (StrategyDTO strategy : program.getStrategies()) {
341 Strategy target = null;
342
343 if (strategy.getId() != null) {
344 target = get(strategy.getId());
345 }
346
347 boolean isNew = false;
348 if (target == null) {
349 target = Strategy.Factory.newInstance();
350 Integer newId = TemporaryDataHelper.<Integer>getNewNegativeIdForTemporaryData(getSession(), target.getClass());
351 target.setStratId(newId);
352 target.setProgram(load(ProgramImpl.class, program.getCode()));
353 target.setStratCreationDt(newCreateDate());
354 isNew = true;
355 } else {
356 remainingStrategieIds.remove(target.getStratId());
357 }
358
359
360 strategyDTOToEntity(program, strategy, target);
361
362
363 if (isNew) {
364 getSession().save(target);
365 strategy.setId(target.getStratId());
366 }
367 else {
368 getSession().update(target);
369 }
370
371 getSession().flush();
372
373 TimeZone dbTimezone = config.getDbTimezone();
374
375
376 if (strategy.isPmfmStrategiesLoaded() || !strategy.isPmfmStrategiesEmpty()) {
377 if (!strategy.isPmfmStrategiesEmpty()) {
378
379 Map<Integer, PmfmStrategy> remainingPmfmStrategy = DaliBeans.mapByProperty(target.getPmfmStrategies(), "pmfmStratId");
380 int rank = 1;
381
382 for (PmfmStrategyDTO pmfmStrategyDTO : strategy.getPmfmStrategies()) {
383
384 PmfmStrategy pmfmStrategy = null;
385 if (pmfmStrategyDTO.getId() != null) {
386 pmfmStrategy = remainingPmfmStrategy.remove(pmfmStrategyDTO.getId());
387 }
388 if (pmfmStrategy == null) {
389
390 pmfmStrategy = PmfmStrategy.Factory.newInstance();
391 Integer newId = TemporaryDataHelper.<Integer>getNewNegativeIdForTemporaryData(getSession(), pmfmStrategy.getClass());
392 pmfmStrategy.setPmfmStratId(newId);
393 pmfmStrategy.setPmfmStratParAcquisNumber(1);
394 }
395
396 savePmfmStrategy(pmfmStrategyDTO, pmfmStrategy, rank++);
397 pmfmStrategy.setStrategy(target);
398 target.addPmfmStrategies(pmfmStrategy);
399 getSession().save(pmfmStrategy);
400 pmfmStrategyDTO.setId(pmfmStrategy.getPmfmStratId());
401
402
403 saveQualitativeValues(pmfmStrategyDTO);
404
405 }
406
407
408 if (!remainingPmfmStrategy.isEmpty()) {
409 target.getPmfmStrategies().removeAll(remainingPmfmStrategy.values());
410 List<Integer> pmfmStrategyIds = DaliBeans.collectProperties(remainingPmfmStrategy.values(), "pmfmStratId");
411 deletePmfmStrategies(pmfmStrategyIds);
412 }
413
414 } else {
415 if (CollectionUtils.isNotEmpty(target.getPmfmStrategies())) {
416
417 List<Integer> pmfmStrategyIds = DaliBeans.collectProperties(target.getPmfmStrategies(), "pmfmStratId");
418 target.getPmfmStrategies().clear();
419 deletePmfmStrategies(pmfmStrategyIds);
420 }
421 }
422 }
423
424
425 if (strategy.isAppliedStrategiesLoaded() || !strategy.isAppliedStrategiesEmpty()) {
426 if (!strategy.isAppliedStrategiesEmpty()) {
427
428 Map<Integer, AppliedStrategy> remainingAppliedStrategies = DaliBeans.mapByProperty(target.getAppliedStrategies(), "appliedStratId");
429 Map<String, AppliedStrategy> remainingAppliedStrategyByKey = buildAppliedStrategyMap(remainingAppliedStrategies.values(), dbTimezone);
430 AppliedStrategy previousAppliedStrategy = null;
431
432 strategy.getAppliedStrategies().sort(new QuadrigeBeanComparator());
433 for (AppliedStrategyDTO appliedStrategy : strategy.getAppliedStrategies()) {
434
435
436
437 if (appliedStrategy.getStartDate() == null && appliedStrategy.getEndDate() == null ) {
438 continue;
439 }
440
441 AppliedStrategy targetAppliedStrategy = null;
442 if (previousAppliedStrategy != null) {
443
444 Integer previousDepId = previousAppliedStrategy.getDepartment() == null ? 0 : previousAppliedStrategy.getDepartment().getDepId();
445 if (previousAppliedStrategy.getMonitoringLocation().getMonLocId().equals(appliedStrategy.getId())
446 && previousDepId.equals(appliedStrategy.getSamplingDepartment() == null ? 0 : appliedStrategy.getSamplingDepartment().getId())) {
447 targetAppliedStrategy = previousAppliedStrategy;
448 }
449 }
450 if (targetAppliedStrategy == null) {
451 targetAppliedStrategy = remainingAppliedStrategies.remove(appliedStrategy.getAppliedStrategyId());
452 if (targetAppliedStrategy == null) {
453 targetAppliedStrategy = AppliedStrategy.Factory.newInstance();
454 Integer newId = TemporaryDataHelper.<Integer>getNewNegativeIdForTemporaryData(getSession(), targetAppliedStrategy.getClass());
455 targetAppliedStrategy.setAppliedStratId(newId);
456 targetAppliedStrategy.setStrategy(target);
457 target.addAppliedStrategies(targetAppliedStrategy);
458 targetAppliedStrategy.setMonitoringLocation(load(MonitoringLocationImpl.class, appliedStrategy.getId()));
459 }
460 if (appliedStrategy.getSamplingDepartment() != null) {
461 targetAppliedStrategy.setDepartment(load(DepartmentImpl.class, appliedStrategy.getSamplingDepartment().getId()));
462 } else {
463 targetAppliedStrategy.setDepartment(null);
464 }
465 getSession().save(targetAppliedStrategy);
466 getSession().flush();
467 appliedStrategy.setAppliedStrategyId(targetAppliedStrategy.getAppliedStratId());
468 previousAppliedStrategy = targetAppliedStrategy;
469 }
470
471
472 String appliedStrategyKey = buildAppliedStrategyKey(appliedStrategy);
473
474 AppliedStrategy existingAppliedStrategy = remainingAppliedStrategyByKey.remove(appliedStrategyKey);
475 if (existingAppliedStrategy == null && appliedStrategy.getStartDate() != null && appliedStrategy.getEndDate() != null) {
476
477
478 AppliedPeriod appliedPeriod = AppliedPeriod.Factory.newInstance();
479 AppliedPeriodPK appliedPeriodPK = new AppliedPeriodPK();
480 appliedPeriodPK.setAppliedStrategy((AppliedStrategyImpl) targetAppliedStrategy);
481 appliedPeriodPK.setAppliedPeriodStartDt(Dates.convertToDate(appliedStrategy.getStartDate(), dbTimezone));
482 appliedPeriod.setAppliedPeriodPk(appliedPeriodPK);
483 appliedPeriod.setAppliedPeriodEndDt(Dates.convertToDate(appliedStrategy.getEndDate(), dbTimezone));
484
485
486 AppliedPeriod periodToUpdate = null;
487 for (AppliedPeriod existingPeriod : targetAppliedStrategy.getAppliedPeriods()) {
488 LocalDate startDate = Dates.convertToLocalDate(existingPeriod.getAppliedPeriodPk().getAppliedPeriodStartDt(), dbTimezone);
489 if (Dates.isSameDay(startDate, appliedStrategy.getStartDate())) {
490 periodToUpdate = existingPeriod;
491 break;
492 }
493 }
494
495 if (periodToUpdate == null) {
496
497 targetAppliedStrategy.addAppliedPeriods(appliedPeriod);
498 } else {
499
500 periodToUpdate.setAppliedPeriodEndDt(Dates.convertToDate(appliedStrategy.getEndDate(), dbTimezone));
501
502 checkDataOutsidePeriod(periodToUpdate);
503
504 getSession().update(periodToUpdate);
505 }
506 getSession().update(targetAppliedStrategy);
507 }
508
509
510 savePmfmAppliedStrategies(strategy, target, targetAppliedStrategy, appliedStrategy.getAnalysisDepartment());
511
512
513 getSession().update(targetAppliedStrategy);
514 }
515
516 if (!remainingAppliedStrategyByKey.isEmpty()) {
517
518 for (String key : remainingAppliedStrategyByKey.keySet()) {
519 AppliedStrategy appliedStrategy = remainingAppliedStrategyByKey.get(key);
520
521 if (remainingAppliedStrategies.containsValue(appliedStrategy)) {
522 continue;
523 }
524 List<String> value = DaliBeans.split(key, "|");
525 String startDateValue = value.get(1);
526 LocalDate startDate = parseAppliedStrategyDate(startDateValue);
527 String endDateValue = value.get(2);
528 LocalDate endDate = parseAppliedStrategyDate(endDateValue);
529 Iterator<AppliedPeriod> it = appliedStrategy.getAppliedPeriods().iterator();
530 while (it.hasNext()) {
531 AppliedPeriod appliedPeriod = it.next();
532 LocalDate appliedPeriodStartDate = Dates.convertToLocalDate(appliedPeriod.getAppliedPeriodStartDt(), dbTimezone);
533 LocalDate appliedPeriodEndDate = Dates.convertToLocalDate(appliedPeriod.getAppliedPeriodEndDt(), dbTimezone);
534 if (Dates.isSameDay(appliedPeriodStartDate, startDate) && Dates.isSameDay(appliedPeriodEndDate, endDate)) {
535
536 checkDataInsidePeriod(appliedPeriod);
537 it.remove();
538 }
539 }
540 getSession().update(appliedStrategy);
541 }
542 }
543
544
545 if (!remainingAppliedStrategies.isEmpty()) {
546 target.getAppliedStrategies().removeAll(remainingAppliedStrategies.values());
547
548 deleteAppliedStrategies(remainingAppliedStrategies.keySet());
549 }
550
551 } else {
552
553 if (CollectionUtils.isNotEmpty(target.getAppliedStrategies())) {
554 List<Integer> appliedStrategyIds = DaliBeans.collectProperties(target.getAppliedStrategies(), "appliedStratId");
555 target.getAppliedStrategies().clear();
556 deleteAppliedStrategies(appliedStrategyIds);
557 }
558 }
559 }
560
561
562 update(target);
563
564 getSession().flush();
565 getSession().clear();
566 }
567
568
569 if (!remainingStrategieIds.isEmpty()) {
570 removeByIds(remainingStrategieIds);
571 }
572 }
573
574 private void checkDataInsidePeriod(AppliedPeriod periodToDelete) {
575 long count = queryCount("countSurveysByProgramLocationAndInsideDates",
576 "programCode", StringType.INSTANCE, periodToDelete.getAppliedPeriodPk().getAppliedStrategy().getStrategy().getProgram().getProgCd(),
577 "locationId", IntegerType.INSTANCE, periodToDelete.getAppliedPeriodPk().getAppliedStrategy().getMonitoringLocation().getMonLocId(),
578 "appliedStrategyId", IntegerType.INSTANCE, periodToDelete.getAppliedPeriodPk().getAppliedStrategy().getAppliedStratId(),
579 "startDate", DateType.INSTANCE, periodToDelete.getAppliedPeriodPk().getAppliedPeriodStartDt(),
580 "endDate", DateType.INSTANCE, periodToDelete.getAppliedPeriodEndDt(),
581 "synchronizationStatusToIgnore", StringType.INSTANCE, SynchronizationStatus.DELETED.getValue()
582 );
583
584 if (count > 0)
585 throw new SaveForbiddenException(SaveForbiddenException.Type.ATTACHED_DATA, "surveys inside deleted period",
586 Collections.singleton(periodToDelete.getAppliedPeriodPk().getAppliedStrategy().getStrategy().getStratNm()));
587
588 }
589
590 private void checkDataOutsidePeriod(AppliedPeriod periodToUpdate) {
591 long count = queryCount("countSurveysByProgramLocationAndOutsideDates",
592 "programCode", StringType.INSTANCE, periodToUpdate.getAppliedPeriodPk().getAppliedStrategy().getStrategy().getProgram().getProgCd(),
593 "locationId", IntegerType.INSTANCE, periodToUpdate.getAppliedPeriodPk().getAppliedStrategy().getMonitoringLocation().getMonLocId(),
594 "appliedStrategyId", IntegerType.INSTANCE, periodToUpdate.getAppliedPeriodPk().getAppliedStrategy().getAppliedStratId(),
595 "startDate", DateType.INSTANCE, periodToUpdate.getAppliedPeriodPk().getAppliedPeriodStartDt(),
596 "endDate", DateType.INSTANCE, periodToUpdate.getAppliedPeriodEndDt(),
597 "synchronizationStatusToIgnore", StringType.INSTANCE, SynchronizationStatus.DELETED.getValue()
598 );
599
600 if (count > 0)
601 throw new SaveForbiddenException(SaveForbiddenException.Type.ATTACHED_DATA, "surveys outside modified period",
602 Collections.singleton(periodToUpdate.getAppliedPeriodPk().getAppliedStrategy().getStrategy().getStratNm()));
603
604 }
605
606 private void savePmfmAppliedStrategies(StrategyDTO strategy, Strategy target, AppliedStrategy appliedStrategy, DepartmentDTO analysisDepartment) {
607
608 if (strategy.isPmfmStrategiesLoaded()) {
609 if (!strategy.isPmfmStrategiesEmpty()) {
610
611 Map<Integer, PmfmAppliedStrategy> remainingPmfmAppliedStrategiesByPmfmStrategyId =
612 DaliBeans.mapByProperty(appliedStrategy.getPmfmAppliedStrategies(), "pmfmAppliedStrategyPk.pmfmStrategy.pmfmStratId");
613
614
615 for (PmfmStrategy pmfmStrategy : target.getPmfmStrategies()) {
616
617 Integer pmfmStrategyId = pmfmStrategy.getPmfmStratId();
618
619 PmfmAppliedStrategy pmfmAppliedStrategy = remainingPmfmAppliedStrategiesByPmfmStrategyId.remove(pmfmStrategyId);
620 if (pmfmAppliedStrategy == null) {
621
622 pmfmAppliedStrategy = PmfmAppliedStrategy.Factory.newInstance();
623 PmfmAppliedStrategyPK pmfmAppliedStrategyPK = new PmfmAppliedStrategyPK();
624 pmfmAppliedStrategyPK.setAppliedStrategy((AppliedStrategyImpl) appliedStrategy);
625 pmfmAppliedStrategyPK.setPmfmStrategy((PmfmStrategyImpl) pmfmStrategy);
626 pmfmAppliedStrategy.setPmfmAppliedStrategyPk(pmfmAppliedStrategyPK);
627 }
628
629
630
631 if (analysisDepartment != null) {
632 pmfmAppliedStrategy.setDepartment(load(DepartmentImpl.class, analysisDepartment.getId()));
633 } else {
634 pmfmAppliedStrategy.setDepartment(null);
635 }
636
637
638 getSession().saveOrUpdate(pmfmAppliedStrategy);
639 appliedStrategy.addPmfmAppliedStrategies(pmfmAppliedStrategy);
640 }
641
642
643 if (!remainingPmfmAppliedStrategiesByPmfmStrategyId.isEmpty()) {
644 appliedStrategy.getPmfmAppliedStrategies().removeAll(remainingPmfmAppliedStrategiesByPmfmStrategyId.values());
645 }
646
647 } else {
648
649 if (appliedStrategy.getPmfmAppliedStrategies() != null) {
650 appliedStrategy.getPmfmAppliedStrategies().clear();
651 }
652 }
653 }
654 }
655
656 private void savePmfmStrategy(PmfmStrategyDTO pmfmStrategyDTO, PmfmStrategy pmfmStrategy, int rank) {
657
658
659 pmfmStrategy.setPmfmStratPresRk(rank);
660
661
662 pmfmStrategy.setPmfm(load(PmfmImpl.class, pmfmStrategyDTO.getPmfm().getId()));
663
664
665 pmfmStrategy.setPmfmStratParIsIndiv(Daos.convertToString(pmfmStrategyDTO.isGrouping()));
666
667
668 pmfmStrategy.setPmfmStratIsUniqueByTaxon(Daos.convertToString(pmfmStrategyDTO.isUnique()));
669
670
671 Map<String, AcquisitionLevel> remainingAcquisitionLevels = DaliBeans.mapByProperty(pmfmStrategy.getAcquisitionLevels(), "acquisLevelCd");
672
673
674 if (BooleanUtils.toBoolean(pmfmStrategyDTO.isSurvey())) {
675 AcquisitionLevel acquisitionLevel = remainingAcquisitionLevels.remove(AcquisitionLevelCode.SURVEY.getValue());
676 if (acquisitionLevel == null) {
677
678 acquisitionLevel = load(AcquisitionLevelImpl.class, AcquisitionLevelCode.SURVEY.getValue());
679 pmfmStrategy.addAcquisitionLevels(acquisitionLevel);
680 }
681 }
682
683
684 if (BooleanUtils.toBoolean(pmfmStrategyDTO.isSampling())) {
685 AcquisitionLevel acquisitionLevel = remainingAcquisitionLevels.remove(AcquisitionLevelCode.SAMPLING_OPERATION.getValue());
686 if (acquisitionLevel == null) {
687
688 acquisitionLevel = load(AcquisitionLevelImpl.class, AcquisitionLevelCode.SAMPLING_OPERATION.getValue());
689 pmfmStrategy.addAcquisitionLevels(acquisitionLevel);
690 }
691 }
692
693
694 if (!remainingAcquisitionLevels.isEmpty()) {
695 pmfmStrategy.getAcquisitionLevels().removeAll(remainingAcquisitionLevels.values());
696 }
697 }
698
699
700 @Override
701 public void deleteAppliedStrategies(String programCode, Collection<Integer> monitoringLocationIds) {
702 Assert.notBlank(programCode);
703 if (monitoringLocationIds == null) return;
704 Set<Integer> idsToDelete = monitoringLocationIds.stream().filter(Objects::nonNull).collect(Collectors.toSet());
705 if (CollectionUtils.isEmpty(idsToDelete)) return;
706
707 Query query = createQuery("deleteAppliedStrategiesByProgramCodeAndMonitoringLocationIds", "programCode", StringType.INSTANCE, programCode);
708 query.setParameterList("monitoringLocationIds", idsToDelete);
709 query.executeUpdate();
710
711 getSession().flush();
712 getSession().clear();
713 }
714
715
716 @Override
717 public void removeByProgramCode(String programCode) {
718 Assert.notBlank(programCode);
719
720
721 List<Integer> strategyIds = DaliBeans.collectIds(getStrategiesByProgramCode(programCode));
722 removeByStrategyIds(strategyIds);
723 }
724
725
726 @Override
727 public void removeByStrategyIds(Collection<Integer> strategyIds) {
728 if (strategyIds == null) return;
729 Set<Integer> idsToDelete = strategyIds.stream().filter(Objects::nonNull).collect(Collectors.toSet());
730 if (CollectionUtils.isEmpty(idsToDelete)) return;
731
732
733
734 idsToDelete.forEach(this::remove);
735 }
736
737
738 @Override
739 public void deleteAppliedStrategies(Collection<Integer> appliedStrategyIds) {
740 if (appliedStrategyIds == null) return;
741 Set<Integer> idsToDelete = appliedStrategyIds.stream().filter(Objects::nonNull).collect(Collectors.toSet());
742 if (CollectionUtils.isEmpty(idsToDelete)) return;
743
744
745 idsToDelete.forEach(idToDelete -> appliedStrategyDao.remove(idToDelete));
746
747
748
749
750
751 }
752
753 private void deletePmfmStrategies(List<Integer> pmfmStrategyIds) {
754 if (pmfmStrategyIds == null) return;
755 Set<Integer> idsToDelete = pmfmStrategyIds.stream().filter(Objects::nonNull).collect(Collectors.toSet());
756 if (CollectionUtils.isEmpty(idsToDelete)) return;
757
758
759 pmfmStrategyDao.deleteQualitativeValues(idsToDelete);
760
761
762 Query query = createQuery("deletePmfmAppliedStrategiesByPmfmStrategyIds");
763 query.setParameterList("pmfmStrategyIds", idsToDelete);
764 query.executeUpdate();
765
766 query = createQuery("deletePmfmStrategiesByIds");
767 query.setParameterList("pmfmStrategyIds", idsToDelete);
768 query.executeUpdate();
769 }
770
771
772 @Override
773 public void saveStrategyByLocation(ProgStratDTO strategy, int locationId) {
774
775 Assert.notNull(strategy);
776 Assert.notNull(strategy.getId());
777 Assert.isTrue((strategy.getStartDate() == null) == (strategy.getEndDate() == null));
778
779 AppliedStrategyImpl target = get(AppliedStrategyImpl.class, strategy.getAppliedStrategyId());
780
781 Assert.notNull(target);
782
783 Assert.equals(target.getMonitoringLocation().getMonLocId(), locationId);
784
785 TimeZone dbTimezone = config.getDbTimezone();
786
787 Collection<AppliedPeriod> appliedPeriods = target.getAppliedPeriods();
788 if (appliedPeriods.size() > 1) {
789 throw new DaliTechnicalException("can't update more than 1 applied periods");
790 }
791 if (strategy.getStartDate() != null && strategy.getEndDate() != null) {
792
793 boolean create = false;
794
795 AppliedPeriod appliedPeriod = null;
796 if (CollectionUtils.isEmpty(appliedPeriods)) {
797 create = true;
798 } else {
799 appliedPeriod = appliedPeriods.iterator().next();
800 if (!Dates.isSameDay(Dates.convertToLocalDate(appliedPeriod.getAppliedPeriodStartDt(), dbTimezone), strategy.getStartDate())) {
801
802 target.getAppliedPeriods().clear();
803 create = true;
804 }
805 }
806 if (create) {
807 appliedPeriod = AppliedPeriod.Factory.newInstance();
808 AppliedPeriodPK appliedPeriodPK = new AppliedPeriodPK();
809 appliedPeriodPK.setAppliedStrategy(target);
810 appliedPeriodPK.setAppliedPeriodStartDt(Dates.convertToDate(strategy.getStartDate(), dbTimezone));
811 appliedPeriod.setAppliedPeriodPk(appliedPeriodPK);
812 appliedPeriod.setAppliedPeriodEndDt(Dates.convertToDate(strategy.getEndDate(), dbTimezone));
813 target.addAppliedPeriods(appliedPeriod);
814 } else {
815
816 appliedPeriod.setAppliedPeriodEndDt(Dates.convertToDate(strategy.getEndDate(), dbTimezone));
817 getSession().update(appliedPeriod);
818 }
819 getSession().update(target);
820
821 } else {
822
823 target.getAppliedPeriods().clear();
824 getSession().update(target);
825 }
826
827 getSession().flush();
828 getSession().clear();
829 }
830
831
832
833 private Map<String, AppliedStrategy> buildAppliedStrategyMap(Collection<AppliedStrategy> appliedStrategies, TimeZone dbTimezone) {
834 Map<String, AppliedStrategy> result = Maps.newHashMap();
835
836 for (AppliedStrategy appliedStrategy : appliedStrategies) {
837
838 if (CollectionUtils.isNotEmpty(appliedStrategy.getAppliedPeriods())) {
839 for (AppliedPeriod appliedPeriod : appliedStrategy.getAppliedPeriods()) {
840
841 Object[] parts = new Object[]{
842 appliedStrategy.getMonitoringLocation().getMonLocId(),
843 formatAppliedStrategyDate(Dates.convertToLocalDate(appliedPeriod.getAppliedPeriodStartDt(), dbTimezone)),
844 formatAppliedStrategyDate(Dates.convertToLocalDate(appliedPeriod.getAppliedPeriodEndDt(), dbTimezone))
845 };
846 String key = Joiner.on('|').useForNull("null").join(parts);
847 result.put(key, appliedStrategy);
848
849 }
850 } else {
851
852 Object[] parts = new Object[]{
853 appliedStrategy.getMonitoringLocation().getMonLocId(),
854 null, null
855 };
856 String key = Joiner.on('|').useForNull("null").join(parts);
857 result.put(key, appliedStrategy);
858 }
859 }
860
861 return result;
862 }
863
864 private String buildAppliedStrategyKey(AppliedStrategyDTO appliedStrategy) {
865 Assert.notNull(appliedStrategy);
866 Assert.notNull(appliedStrategy.getId());
867 return Joiner.on('|').useForNull("null").join(
868 appliedStrategy.getId(),
869 formatAppliedStrategyDate(appliedStrategy.getStartDate()),
870 formatAppliedStrategyDate(appliedStrategy.getEndDate())
871 );
872 }
873
874 private String formatAppliedStrategyDate(LocalDate date) {
875 return date.format(DateTimeFormatter.ofPattern(DATE_PATTERN));
876 }
877
878 private LocalDate parseAppliedStrategyDate(String string) {
879 return LocalDate.parse(string, DateTimeFormatter.ofPattern(DATE_PATTERN));
880 }
881
882
883 private StrategyDTO toStrategyDTO(Iterator<Object> source) {
884 StrategyDTO result = DaliBeanFactory.newStrategyDTO();
885
886
887 result.setId((Integer) source.next());
888
889
890 result.setName((String) source.next());
891
892
893 result.setComment((String) source.next());
894
895 return result;
896 }
897
898 private AppliedStrategyDTO toAppliedStrategyDTO(Iterator<Object> source) {
899 AppliedStrategyDTO target = DaliBeanFactory.newAppliedStrategyDTO();
900
901
902 target.setAppliedStrategyId((Integer) source.next());
903
904
905 target.setId((Integer) source.next());
906
907
908 LocationDTO location = monitoringLocationDao.getLocationById(target.getId());
909
910
911 target.setLabel(location.getLabel());
912
913
914 target.setName(location.getName());
915
916
917 target.setComment(location.getComment());
918
919
920 target.setStatus(location.getStatus());
921
922
923 Integer departmentId = (Integer) source.next();
924 if (departmentId != null) {
925 target.setSamplingDepartment(departmentDao.getDepartmentById(departmentId));
926 }
927
928 return target;
929 }
930
931 private AppliedStrategyDTO toAppliedPeriod(Iterator<Object> source, TimeZone dbTimezone) {
932
933 AppliedStrategyDTO target = toAppliedStrategyDTO(source);
934
935
936 target.setStartDate(Dates.convertToLocalDate(Daos.convertToDate(source.next()), dbTimezone));
937 target.setEndDate(Dates.convertToLocalDate(Daos.convertToDate(source.next()), dbTimezone));
938
939
940 target.setPreviousStartDate(target.getStartDate());
941 target.setPreviousEndDate(target.getEndDate());
942
943 return target;
944 }
945
946 private PmfmStrategyDTO toPmfmStrategyDTO(Iterator<Object> source) {
947 PmfmStrategyDTO target = DaliBeanFactory.newPmfmStrategyDTO();
948
949
950 target.setId((Integer) source.next());
951
952
953 target.setPmfm(pmfmDao.getPmfmById((Integer) source.next()));
954
955
956
957
958
959
960 target.setGrouping(Daos.safeConvertToBoolean(source.next(), false));
961
962 target.setUnique(Daos.safeConvertToBoolean(source.next(), false));
963
964
965 target.setRankOrder((Integer) source.next());
966
967 return target;
968 }
969
970
971
972
973
974
975
976 private ProgStratDTO toProgStratDTO(Iterator<Object> source, TimeZone dbTimezone) {
977 ProgStratDTO target = DaliBeanFactory.newProgStratDTO();
978
979
980 target.setAppliedStrategyId((Integer) source.next());
981
982
983 {
984 ProgramDTO program = DaliBeanFactory.newProgramDTO();
985 target.setProgram(program);
986
987
988 program.setCode((String) source.next());
989 program.setName((String) source.next());
990 program.setStatus(referentialDao.getStatusByCode((String) source.next()));
991 }
992
993
994 target.setId((Integer) source.next());
995 target.setName((String) source.next());
996
997
998 target.setStartDate(Dates.convertToLocalDate(Daos.convertToDate(source.next()), dbTimezone));
999 target.setEndDate(Dates.convertToLocalDate(Daos.convertToDate(source.next()), dbTimezone));
1000
1001 Integer depId = (Integer) source.next();
1002 if (depId != null) {
1003 target.setDepartment(departmentDao.getDepartmentById(depId));
1004 }
1005
1006 return target;
1007 }
1008
1009
1010
1011
1012
1013
1014
1015
1016 private void strategyDTOToEntity(ProgramDTO program, StrategyDTO source, Strategy target) {
1017
1018 target.setStratNm(source.getName());
1019 target.setStratDc(source.getComment());
1020
1021
1022 if (QuadrigeBeans.isLocalStatus(program.getStatus())) {
1023 target.setUpdateDt(newUpdateTimestamp());
1024 }
1025
1026
1027 if (CollectionUtils.isEmpty(program.getManagerPersons())) {
1028 if (CollectionUtils.isNotEmpty(target.getQusers())) {
1029 target.getQusers().clear();
1030 }
1031 }
1032 else {
1033 Daos.replaceEntities(
1034 target.getQusers(),
1035 program.getManagerPersons(),
1036 person -> load(QuserImpl.class, person.getId())
1037 );
1038 }
1039 }
1040
1041
1042 private void fillQualitativeValues(List<PmfmStrategyDTO> pmfmStrategies) {
1043 pmfmStrategies.forEach(pmfmStrategy -> {
1044
1045
1046 List<Integer> qvIds = pmfmStrategyDao.getQualitativeValueIds(pmfmStrategy.getId());
1047
1048 pmfmStrategy.setQualitativeValues(
1049 pmfmStrategy.getPmfm().getQualitativeValues().stream()
1050 .filter(qualitativeValueDTO -> CollectionUtils.isEmpty(qvIds) || qvIds.contains(qualitativeValueDTO.getId()))
1051 .collect(Collectors.toList())
1052 );
1053
1054 });
1055 }
1056
1057 private void saveQualitativeValues(PmfmStrategyDTO pmfmStrategy) {
1058
1059
1060 pmfmStrategyDao.deleteQualitativeValues(pmfmStrategy.getId());
1061
1062 if (pmfmStrategy.sizeQualitativeValues() != pmfmStrategy.getPmfm().sizeQualitativeValues()) {
1063
1064 pmfmStrategy.getQualitativeValues()
1065 .forEach(qualitativeValueDTO -> pmfmStrategyDao.saveQualitativeValue(pmfmStrategy.getId(), pmfmStrategy.getPmfm().getId(), qualitativeValueDTO.getId()));
1066 }
1067 }
1068
1069
1070 }