1 package net.sumaris.core.dao.data;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import com.google.common.base.Preconditions;
26 import com.google.common.collect.ArrayListMultimap;
27 import com.google.common.collect.Lists;
28 import com.google.common.collect.Maps;
29 import com.google.common.collect.Multimap;
30 import net.sumaris.core.dao.referential.PmfmDao;
31 import net.sumaris.core.dao.referential.ReferentialDao;
32 import net.sumaris.core.dao.technical.model.IEntity;
33 import net.sumaris.core.exception.ErrorCodes;
34 import net.sumaris.core.exception.SumarisTechnicalException;
35 import net.sumaris.core.model.administration.user.Department;
36 import net.sumaris.core.model.data.*;
37 import net.sumaris.core.model.referential.QualityFlag;
38 import net.sumaris.core.model.referential.pmfm.Pmfm;
39 import net.sumaris.core.model.referential.pmfm.QualitativeValue;
40 import net.sumaris.core.util.Beans;
41 import net.sumaris.core.vo.administration.user.DepartmentVO;
42 import net.sumaris.core.vo.data.MeasurementVO;
43 import net.sumaris.core.vo.referential.ParameterValueType;
44 import net.sumaris.core.vo.referential.PmfmVO;
45 import net.sumaris.core.vo.referential.ReferentialVO;
46 import org.apache.commons.collections4.CollectionUtils;
47 import org.apache.commons.collections4.MapUtils;
48 import org.apache.commons.lang3.StringUtils;
49 import org.nuiton.i18n.I18n;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52 import org.springframework.beans.BeanUtils;
53 import org.springframework.beans.factory.annotation.Autowired;
54 import org.springframework.stereotype.Repository;
55
56 import javax.persistence.EntityManager;
57 import javax.persistence.TypedQuery;
58 import javax.persistence.criteria.CriteriaBuilder;
59 import javax.persistence.criteria.CriteriaQuery;
60 import javax.persistence.criteria.ParameterExpression;
61 import javax.persistence.criteria.Root;
62 import java.beans.PropertyDescriptor;
63 import java.io.Serializable;
64 import java.sql.Timestamp;
65 import java.util.Collection;
66 import java.util.List;
67 import java.util.Map;
68 import java.util.Objects;
69 import java.util.stream.Collectors;
70
71 @Repository("measurementDao")
72 public class MeasurementDaoImpl extends BaseDataDaoImpl implements MeasurementDao {
73
74
75 private static final Logger log =
76 LoggerFactory.getLogger(MeasurementDaoImpl.class);
77
78 static {
79 I18n.n("sumaris.persistence.table.vesselUseMeasurement");
80 I18n.n("sumaris.persistence.table.gearUseMeasurement");
81 I18n.n("sumaris.persistence.table.physicalGearMeasurement");
82 I18n.n("sumaris.persistence.table.sampleMeasurement");
83 I18n.n("sumaris.persistence.table.batchSortingMeasurement");
84 I18n.n("sumaris.persistence.table.batchQuantificationMeasurement");
85 I18n.n("sumaris.persistence.table.observedLocationMeasurement");
86 }
87
88 protected static Multimap<Class<? extends IMeasurementEntity>, PropertyDescriptor> initParentPropertiesMap() {
89 Multimap<Class<? extends IMeasurementEntity>, PropertyDescriptor> result = ArrayListMultimap.create();
90
91
92 result.put(VesselUseMeasurement.class, BeanUtils.getPropertyDescriptor(VesselUseMeasurement.class, VesselUseMeasurement.Fields.TRIP));
93
94
95 result.put(PhysicalGearMeasurement.class, BeanUtils.getPropertyDescriptor(PhysicalGearMeasurement.class, PhysicalGearMeasurement.Fields.PHYSICAL_GEAR));
96
97
98 result.put(VesselUseMeasurement.class, BeanUtils.getPropertyDescriptor(VesselUseMeasurement.class, VesselUseMeasurement.Fields.OPERATION));
99 result.put(GearUseMeasurement.class, BeanUtils.getPropertyDescriptor(GearUseMeasurement.class, GearUseMeasurement.Fields.OPERATION));
100
101
102 result.put(ObservedLocationMeasurement.class, BeanUtils.getPropertyDescriptor(ObservedLocationMeasurement.class, ObservedLocationMeasurement.Fields.OBSERVED_LOCATION));
103
104
105 result.put(SampleMeasurement.class, BeanUtils.getPropertyDescriptor(SampleMeasurement.class, SampleMeasurement.Fields.SAMPLE));
106
107
108 result.put(BatchSortingMeasurement.class, BeanUtils.getPropertyDescriptor(BatchSortingMeasurement.class, BatchSortingMeasurement.Fields.BATCH));
109 result.put(BatchQuantificationMeasurement.class, BeanUtils.getPropertyDescriptor(BatchQuantificationMeasurement.class, BatchSortingMeasurement.Fields.BATCH));
110
111
112 result.put(SaleMeasurement.class, BeanUtils.getPropertyDescriptor(SaleMeasurement.class, SaleMeasurement.Fields.SALE));
113
114
115 result.put(LandingMeasurement.class, BeanUtils.getPropertyDescriptor(LandingMeasurement.class, LandingMeasurement.Fields.LANDING));
116
117 return result;
118 }
119
120 private Multimap<Class<? extends IMeasurementEntity>, PropertyDescriptor> parentPropertiesMap = initParentPropertiesMap();
121
122 @Autowired
123 private ReferentialDao referentialDao;
124
125 @Autowired
126 private PmfmDao pmfmDao;
127
128
129 @Override
130 public List<MeasurementVO> getTripVesselUseMeasurements(int tripId) {
131 return getMeasurementsByParentId(VesselUseMeasurement.class,
132 VesselUseMeasurement.Fields.TRIP,
133 tripId,
134 VesselUseMeasurement.Fields.RANK_ORDER
135 );
136 }
137
138 @Override
139 @SuppressWarnings("unchecked")
140 public Map<Integer, String> getTripVesselUseMeasurementsMap(int tripId) {
141 return getMeasurementsMapByParentId(VesselUseMeasurement.class,
142 VesselUseMeasurement.Fields.TRIP,
143 tripId,
144 VesselUseMeasurement.Fields.ID
145 );
146 }
147
148 @Override
149 public List<MeasurementVO> getPhysicalGearMeasurements(int physicalGearId) {
150 return getMeasurementsByParentId(PhysicalGearMeasurement.class,
151 PhysicalGearMeasurement.Fields.PHYSICAL_GEAR,
152 physicalGearId,
153 PhysicalGearMeasurement.Fields.RANK_ORDER
154 );
155 }
156
157 @Override
158 public Map<Integer, String> getPhysicalGearMeasurementsMap(int physicalGearId) {
159 return getMeasurementsMapByParentId(PhysicalGearMeasurement.class,
160 PhysicalGearMeasurement.Fields.PHYSICAL_GEAR,
161 physicalGearId,
162 PhysicalGearMeasurement.Fields.ID
163 );
164 }
165
166 @Override
167 @SuppressWarnings("unchecked")
168 public List<MeasurementVO> getOperationVesselUseMeasurements(int operationId) {
169 return getMeasurementsByParentId(VesselUseMeasurement.class,
170 VesselUseMeasurement.Fields.OPERATION,
171 operationId,
172 VesselUseMeasurement.Fields.RANK_ORDER
173 );
174 }
175
176 @Override
177 @SuppressWarnings("unchecked")
178 public Map<Integer, String> getOperationVesselUseMeasurementsMap(int operationId) {
179 return getMeasurementsMapByParentId(VesselUseMeasurement.class,
180 VesselUseMeasurement.Fields.OPERATION,
181 operationId,
182 VesselUseMeasurement.Fields.ID
183 );
184 }
185
186 @Override
187 public Map<Integer, String> getOperationGearUseMeasurementsMap(int operationId) {
188 return getMeasurementsMapByParentId(GearUseMeasurement.class,
189 GearUseMeasurement.Fields.OPERATION,
190 operationId,
191 GearUseMeasurement.Fields.ID
192 );
193 }
194
195 @Override
196 @SuppressWarnings("unchecked")
197 public List<MeasurementVO> getOperationGearUseMeasurements(int operationId) {
198 return getMeasurementsByParentId(GearUseMeasurement.class,
199 GearUseMeasurement.Fields.OPERATION,
200 operationId,
201 GearUseMeasurement.Fields.RANK_ORDER
202 );
203 }
204
205 @Override
206 @SuppressWarnings("unchecked")
207 public List<MeasurementVO> getSampleMeasurements(int sampleId) {
208 return getMeasurementsByParentId(SampleMeasurement.class,
209 SampleMeasurement.Fields.SAMPLE,
210 sampleId,
211 SampleMeasurement.Fields.RANK_ORDER
212 );
213 }
214
215 @Override
216 public List<MeasurementVO> getObservedLocationMeasurements(int observedLocationId) {
217 return getMeasurementsByParentId(ObservedLocationMeasurement.class,
218 ObservedLocationMeasurement.Fields.OBSERVED_LOCATION,
219 observedLocationId,
220 ObservedLocationMeasurement.Fields.RANK_ORDER
221 );
222 }
223
224 @Override
225 @SuppressWarnings("unchecked")
226 public Map<Integer, String> getSampleMeasurementsMap(int sampleId) {
227 return getMeasurementsMapByParentId(SampleMeasurement.class,
228 SampleMeasurement.Fields.SAMPLE,
229 sampleId,
230 SampleMeasurement.Fields.RANK_ORDER
231 );
232 }
233
234 @Override
235 @SuppressWarnings("unchecked")
236 public Map<Integer, String> getBatchSortingMeasurementsMap(int batchId) {
237 return getMeasurementsMapByParentId(BatchSortingMeasurement.class,
238 BatchSortingMeasurement.Fields.BATCH,
239 batchId,
240 BatchSortingMeasurement.Fields.RANK_ORDER
241 );
242 }
243
244 @Override
245 @SuppressWarnings("unchecked")
246 public Map<Integer, String> getBatchQuantificationMeasurementsMap(int batchId) {
247 return getMeasurementsMapByParentId(BatchQuantificationMeasurement.class,
248 BatchQuantificationMeasurement.Fields.BATCH,
249 batchId,
250 BatchQuantificationMeasurement.Fields.ID
251 );
252 }
253
254 @Override
255 @SuppressWarnings("unchecked")
256 public Map<Integer, String> getObservedLocationMeasurementsMap(int observedLocationId) {
257 return getMeasurementsMapByParentId(ObservedLocationMeasurement.class,
258 ObservedLocationMeasurement.Fields.OBSERVED_LOCATION,
259 observedLocationId,
260 ObservedLocationMeasurement.Fields.ID
261 );
262 }
263
264
265 @Override
266 @SuppressWarnings("unchecked")
267 public Map<Integer, String> getLandingMeasurementsMap(int landingId) {
268 return getMeasurementsMapByParentId(LandingMeasurement.class,
269 LandingMeasurement.Fields.LANDING,
270 landingId,
271 LandingMeasurement.Fields.ID
272 );
273 }
274
275 @Override
276 @SuppressWarnings("unchecked")
277 public List<MeasurementVO> getLandingMeasurements(int landingId) {
278 return getMeasurementsByParentId(LandingMeasurement.class,
279 LandingMeasurement.Fields.LANDING,
280 landingId,
281 LandingMeasurement.Fields.ID
282 );
283 }
284
285 @Override
286 public <T extends IMeasurementEntity> MeasurementVO toMeasurementVO(T source) {
287 if (source == null) return null;
288
289 MeasurementVOmentVO.html#MeasurementVO">MeasurementVO target = new MeasurementVO();
290
291 Beans.copyProperties(source, target);
292
293
294 if (source.getPmfm() != null) {
295 target.setPmfmId(source.getPmfm().getId());
296 }
297
298
299 if (source.getQualitativeValue() != null){
300 ReferentialVO qv = referentialDao.toReferentialVO(source.getQualitativeValue());
301 target.setQualitativeValue(qv);
302 }
303
304
305 target.setQualityFlagId(source.getQualityFlag().getId());
306
307
308 DepartmentVO recorderDepartment = referentialDao.toTypedVO(source.getRecorderDepartment(), DepartmentVO.class).orElse(null);
309 target.setRecorderDepartment(recorderDepartment);
310
311
312 target.setEntityName(getEntityName(source));
313
314 return target;
315 }
316
317 @Override
318 public List<MeasurementVO> saveTripVesselUseMeasurements(final int tripId, List<MeasurementVO> sources) {
319 Trip parent = get(Trip.class, tripId);
320 return saveMeasurements(VesselUseMeasurement.class, sources, parent.getMeasurements(), parent);
321 }
322
323 @Override
324 public Map<Integer, String> saveTripMeasurementsMap(int tripId, Map<Integer, String> sources) {
325 Trip parent = get(Trip.class, tripId);
326 return saveMeasurementsMap(VesselUseMeasurement.class, sources, parent.getMeasurements(), parent);
327 }
328
329 @Override
330 public List<MeasurementVO> savePhysicalGearMeasurements(final int physicalGearId, List<MeasurementVO> sources) {
331 PhysicalGear parent = get(PhysicalGear.class, physicalGearId);
332 return saveMeasurements(PhysicalGearMeasurement.class, sources, parent.getMeasurements(), parent);
333 }
334
335 @Override
336 public Map<Integer, String> savePhysicalGearMeasurementsMap(int physicalGearId, Map<Integer, String> sources) {
337 PhysicalGear parent = get(PhysicalGear.class, physicalGearId);
338 return saveMeasurementsMap(PhysicalGearMeasurement.class, sources, parent.getMeasurements(), parent);
339 }
340
341 @Override
342 public List<MeasurementVO> saveOperationGearUseMeasurements(final int operationId, List<MeasurementVO> sources) {
343 Operation parent = get(Operation.class, operationId);
344 return saveMeasurements(GearUseMeasurement.class, sources, parent.getGearUseMeasurements(), parent);
345 }
346
347 @Override
348 public List<MeasurementVO> saveOperationVesselUseMeasurements(final int operationId, List<MeasurementVO> sources) {
349 Operation parent = get(Operation.class, operationId);
350 return saveMeasurements(VesselUseMeasurement.class, sources, parent.getVesselUseMeasurements(), parent);
351 }
352
353 @Override
354 public Map<Integer, String> saveOperationGearUseMeasurementsMap(int operationId, Map<Integer, String> sources) {
355 Operation parent = get(Operation.class, operationId);
356 return saveMeasurementsMap(GearUseMeasurement.class, sources, parent.getGearUseMeasurements(), parent);
357 }
358
359 @Override
360 public Map<Integer, String> saveOperationVesselUseMeasurementsMap(int operationId, Map<Integer, String> sources) {
361 Operation parent = get(Operation.class, operationId);
362 return saveMeasurementsMap(VesselUseMeasurement.class, sources, parent.getVesselUseMeasurements(), parent);
363 }
364
365 @Override
366 public List<MeasurementVO> saveObservedLocationMeasurements(final int observedLocationId, List<MeasurementVO> sources) {
367 ObservedLocation parent = get(ObservedLocation.class, observedLocationId);
368 return saveMeasurements(ObservedLocationMeasurement.class, sources, parent.getMeasurements(), parent);
369 }
370
371 @Override
372 public Map<Integer, String> saveObservedLocationMeasurementsMap(final int observedLocationId, Map<Integer, String> sources) {
373 ObservedLocation parent = get(ObservedLocation.class, observedLocationId);
374 return saveMeasurementsMap(ObservedLocationMeasurement.class, sources, parent.getMeasurements(), parent);
375 }
376
377 @Override
378 public List<MeasurementVO> saveSaleMeasurements(final int saleId, List<MeasurementVO> sources) {
379 Sale parent = get(Sale.class, saleId);
380 return saveMeasurements(SaleMeasurement.class, sources, parent.getMeasurements(), parent);
381 }
382
383 @Override
384 public Map<Integer, String> saveSaleMeasurementsMap(final int saleId, Map<Integer, String> sources) {
385 Sale parent = get(Sale.class, saleId);
386 return saveMeasurementsMap(SaleMeasurement.class, sources, parent.getMeasurements(), parent);
387 }
388
389 @Override
390 public List<MeasurementVO> saveLandingMeasurements(final int landingId, List<MeasurementVO> sources) {
391 Landing parent = get(Landing.class, landingId);
392 return saveMeasurements(LandingMeasurement.class, sources, parent.getMeasurements(), parent);
393 }
394
395 @Override
396 public Map<Integer, String> saveLandingMeasurementsMap(final int landingId, Map<Integer, String> sources) {
397 Landing parent = get(Landing.class, landingId);
398 return saveMeasurementsMap(LandingMeasurement.class, sources, parent.getMeasurements(), parent);
399 }
400
401 @Override
402 public List<MeasurementVO> saveSampleMeasurements(final int sampleId, List<MeasurementVO> sources) {
403 Sample parent = get(Sample.class, sampleId);
404 return saveMeasurements(SampleMeasurement.class, sources, parent.getMeasurements(), parent);
405 }
406
407 @Override
408 public Map<Integer, String> saveSampleMeasurementsMap(final int sampleId, Map<Integer, String> sources) {
409 Sample parent = get(Sample.class, sampleId);
410 return saveMeasurementsMap(SampleMeasurement.class, sources, parent.getMeasurements(), parent);
411 }
412
413 @Override
414 public List<MeasurementVO> saveBatchSortingMeasurements(int batchId, List<MeasurementVO> sources) {
415 Batch parent = get(Batch.class, batchId);
416 return saveMeasurements(BatchSortingMeasurement.class, sources, parent.getSortingMeasurements(), parent);
417 }
418
419 @Override
420 public List<MeasurementVO> saveBatchQuantificationMeasurements(int batchId, List<MeasurementVO> sources) {
421 Batch parent = get(Batch.class, batchId);
422 return saveMeasurements(BatchSortingMeasurement.class, sources, parent.getSortingMeasurements(), parent);
423 }
424
425 @Override
426 public Map<Integer, String> saveBatchSortingMeasurementsMap(int batchId, Map<Integer, String> sources) {
427 Batch parent = get(Batch.class, batchId);
428 Preconditions.checkNotNull(parent, "Could not found batch with id=" + batchId);
429 return saveMeasurementsMap(BatchSortingMeasurement.class, sources, parent.getSortingMeasurements(), parent);
430 }
431
432 @Override
433 public Map<Integer, String> saveBatchQuantificationMeasurementsMap(int batchId, Map<Integer, String> sources) {
434 Batch parent = get(Batch.class, batchId);
435 return saveMeasurementsMap(BatchQuantificationMeasurement.class, sources, parent.getQuantificationMeasurements(), parent);
436 }
437
438 @Override
439 public List<MeasurementVO> saveVesselPhysicalMeasurements(int vesselFeaturesId, List<MeasurementVO> sources) {
440 VesselFeatures parent = get(VesselFeatures.class, vesselFeaturesId);
441 return saveMeasurements(VesselPhysicalMeasurement.class, sources, parent.getMeasurements(), parent);
442 }
443
444 @Override
445 public Map<Integer, String> saveVesselPhysicalMeasurementsMap(int vesselFeaturesId, Map<Integer, String> sources) {
446 VesselFeatures parent = get(VesselFeatures.class, vesselFeaturesId);
447 return saveMeasurementsMap(VesselPhysicalMeasurement.class, sources, parent.getMeasurements(), parent);
448 }
449
450 @Override
451 public List<MeasurementVO> getVesselFeaturesMeasurements(int vesselFeaturesId) {
452 return getMeasurementsByParentId(VesselPhysicalMeasurement.class,
453 VesselPhysicalMeasurement.Fields.VESSEL_FEATURES,
454 vesselFeaturesId,
455 VesselPhysicalMeasurement.Fields.ID
456 );
457 }
458
459 @Override
460 public Map<Integer, String> getVesselFeaturesMeasurementsMap(int vesselFeaturesId) {
461 return getMeasurementsMapByParentId(VesselPhysicalMeasurement.class,
462 VesselPhysicalMeasurement.Fields.VESSEL_FEATURES,
463 vesselFeaturesId,
464 VesselPhysicalMeasurement.Fields.ID
465 );
466 }
467
468 @Override
469 public <T extends IMeasurementEntity> List<MeasurementVO> saveMeasurements(
470 final Class<? extends IMeasurementEntity> entityClass,
471 List<MeasurementVO> sources,
472 List<T> target,
473 final IDataEntity<?> parent) {
474
475 final EntityManager em = getEntityManager();
476
477
478
479 final Map<Integer, T> sourceToRemove = Beans.splitById(Beans.getList(target));
480
481 int rankOrder = 1;
482 List<MeasurementVO> result = Lists.newArrayList();
483 for (MeasurementVO source: sources) {
484 if (isNotEmpty(source)) {
485 IMeasurementEntity entity = null;
486
487
488 if (source.getId() != null) {
489 entity = sourceToRemove.remove(source.getId());
490 }
491 boolean isNew = (entity == null);
492 if (isNew) {
493 try {
494 entity = entityClass.newInstance();
495 }
496 catch(IllegalAccessException | InstantiationException e) {
497 throw new SumarisTechnicalException(e);
498 }
499 }
500
501
502 measurementVOToEntity(source, entity, true);
503
504
505 if (entity instanceof ISortedMeasurementEntity) {
506 ((ISortedMeasurementEntity)entity).setRankOrder(rankOrder);
507 source.setRankOrder(rankOrder);
508 rankOrder++;
509 }
510
511
512 setParent(entity, parent.getClass(), parent.getId(), false);
513
514
515 Timestamp newUpdateDate = getDatabaseCurrentTimestamp();
516 entity.setUpdateDate(newUpdateDate);
517
518
519 if (isNew) {
520 em.persist(entity);
521 source.setId(entity.getId());
522 } else {
523 em.merge(entity);
524 }
525
526 source.setUpdateDate(newUpdateDate);
527 source.setEntityName(getEntityName(entity));
528
529 result.add(source);
530 }
531 }
532
533
534 if (MapUtils.isNotEmpty(sourceToRemove)) {
535 sourceToRemove.values().forEach(em::remove);
536 }
537
538 return result;
539 }
540
541
542
543 protected <T extends IMeasurementEntity> String getEntityName(T source) {
544 String classname = source.getClass().getSimpleName();
545 int index = classname.indexOf("$HibernateProxy");
546 if (index > 0) {
547 return classname.substring(0, index);
548 }
549 return classname;
550 }
551
552 protected <T extends IDataEntity> Class<T> getEntityClass(T source) {
553 String classname = source.getClass().getName();
554 int index = classname.indexOf("$HibernateProxy");
555 if (index > 0) {
556 try {
557 return (Class<T>) Class.forName(classname.substring(0, index));
558 }
559 catch(ClassNotFoundException t) {
560 throw new SumarisTechnicalException(t);
561 }
562 }
563 return (Class<T>)source.getClass();
564 }
565
566
567 protected <T extends IMeasurementEntity> Map<Integer, String> saveMeasurementsMap(
568 final Class<? extends T> entityClass,
569 Map<Integer, String> sources,
570 List<T> target,
571 final IDataEntity<?> parent) {
572
573 final EntityManager session = getEntityManager();
574
575
576
577
578
579 final Map<Integer, T> sourceToRemove = Beans.splitByProperty(Beans.getList(target), IMeasurementEntity.Fields.PMFM + "." + IMeasurementEntity.Fields.ID);
580
581 int rankOrder = 1;
582 for (Map.Entry<Integer, String> source: sources.entrySet()) {
583 Integer pmfmId = source.getKey();
584 String value = source.getValue();
585
586 if (StringUtils.isNotBlank(value)) {
587
588 IMeasurementEntity entity = sourceToRemove.remove(pmfmId);
589
590
591 boolean isNew = (entity == null);
592 if (isNew) {
593 try {
594 entity = entityClass.newInstance();
595 } catch (IllegalAccessException | InstantiationException e) {
596 throw new SumarisTechnicalException(e);
597 }
598 }
599
600
601 if (entity.getPmfm() == null) {
602 entity.setPmfm(load(Pmfm.class, pmfmId));
603 }
604
605
606 if (entity instanceof ISortedMeasurementEntity) {
607 ((ISortedMeasurementEntity) entity).setRankOrder(rankOrder++);
608 }
609
610
611 if (entity instanceof BatchQuantificationMeasurement) {
612 ((BatchQuantificationMeasurement) entity).setIsReferenceQuantification(rankOrder == 1);
613 }
614
615
616 fillDefaultProperties(parent, entity);
617
618
619 valueToEntity(value, pmfmId, entity);
620
621
622 setParent(entity, getEntityClass(parent), parent.getId(), false);
623
624
625 Timestamp newUpdateDate = getDatabaseCurrentTimestamp();
626 entity.setUpdateDate(newUpdateDate);
627
628
629 if (isNew) {
630 session.persist(entity);
631 } else {
632 session.merge(entity);
633 }
634 }
635 }
636
637
638 if (MapUtils.isNotEmpty(sourceToRemove)) {
639 boolean preserveHistoricalMeasurements = config.isPreserveHistoricalMeasurements();
640 sourceToRemove.values().stream()
641
642 .filter(entity -> sources.containsKey(entity.getPmfm().getId()) || !preserveHistoricalMeasurements)
643 .forEach(entity -> getEntityManager().remove(entity));
644 }
645
646 return sources;
647 }
648
649 protected <T extends IMeasurementEntity> List<MeasurementVO> getMeasurementsByParentId(Class<T> entityClass,
650 String parentPropertyName,
651 int parentId,
652 String sortByPropertyName) {
653 TypedQuery<T> query = getMeasurementsByParentIdQuery(entityClass, parentPropertyName, parentId, sortByPropertyName);
654 return toMeasurementVOs(query.getResultList());
655 }
656
657 protected <T extends IMeasurementEntity> Map<Integer, String> getMeasurementsMapByParentId(Class<T> entityClass,
658 String parentPropertyName,
659 int parentId,
660 String sortByPropertyName) {
661 TypedQuery<T> query = getMeasurementsByParentIdQuery(entityClass, parentPropertyName, parentId, sortByPropertyName);
662 return toMeasurementsMap(query.getResultList());
663 }
664
665
666
667 protected <T extends IMeasurementEntity> TypedQuery<T> getMeasurementsByParentIdQuery(Class<T> entityClass,
668 String parentPropertyName,
669 int parentId,
670 String sortByPropertyName) {
671 Preconditions.checkNotNull(sortByPropertyName);
672
673 CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
674 CriteriaQuery<T> query = builder.createQuery(entityClass);
675 Root<T> root = query.from(entityClass);
676
677 ParameterExpression<Integer> idParam = builder.parameter(Integer.class);
678
679 query.select(root)
680 .where(builder.equal(root.get(parentPropertyName).get(IEntity.Fields.ID), idParam))
681
682 .orderBy(builder.asc(root.get(sortByPropertyName)));
683
684 return getEntityManager().createQuery(query)
685 .setParameter(idParam, parentId);
686 }
687
688 protected <T extends IMeasurementEntity> List<MeasurementVO> toMeasurementVOs(List<T> source) {
689 return source.stream()
690 .map(this::toMeasurementVO)
691 .filter(Objects::nonNull)
692 .collect(Collectors.toList());
693 }
694
695 protected <T extends IMeasurementEntity> Map<Integer, String> toMeasurementsMap(List<T> source) {
696 final Map<Integer, String> result = Maps.newIdentityHashMap();
697 source.stream()
698 .filter(m -> m.getPmfm() != null && m.getPmfm().getId() != null)
699 .forEach(m -> {
700
701 if (m.getPmfm() != null && m.getPmfm().getId() != null) {
702 Object value = this.entityToValue(m);
703 if (value != null) {
704 result.put(m.getPmfm().getId(), value.toString());
705 }
706 }
707 });
708
709 return result;
710 }
711
712
713 protected void measurementVOToEntity(MeasurementVO source,
714 IMeasurementEntity target,
715 boolean copyIfNull) {
716
717 Beans.copyProperties(source, target);
718
719
720 target.setPmfm(load(Pmfm.class, source.getPmfmId()));
721
722
723 if (copyIfNull || source.getQualitativeValue() != null) {
724 if (source.getQualitativeValue() == null || source.getQualitativeValue().getId() == null) {
725 target.setQualitativeValue(null);
726 }
727 else {
728 target.setQualitativeValue(load(QualitativeValue.class, source.getQualitativeValue().getId()));
729 }
730 }
731
732
733 if (copyIfNull || source.getRecorderDepartment() != null) {
734 if (source.getRecorderDepartment() == null || source.getRecorderDepartment().getId() == null) {
735 target.setRecorderDepartment(null);
736 }
737 else {
738 target.setRecorderDepartment(load(Department.class, source.getRecorderDepartment().getId()));
739 }
740 }
741
742
743 if (copyIfNull || source.getQualityFlagId() != null) {
744 if (source.getQualityFlagId() == null) {
745 target.setQualityFlag(load(QualityFlag.class, config.getDefaultQualityFlagId()));
746 }
747 else {
748 target.setQualityFlag(load(QualityFlag.class, source.getQualityFlagId()));
749 }
750 }
751
752 }
753
754 protected void valueToEntity(String value, int pmfmId, IMeasurementEntity target) {
755
756 if (value == null) {
757 throw new SumarisTechnicalException(ErrorCodes.BAD_REQUEST, "Unable to set value NULL value on a measurement");
758 }
759
760 PmfmVO pmfm = pmfmDao.get(pmfmId);
761 if (pmfm == null) {
762 throw new SumarisTechnicalException(ErrorCodes.BAD_REQUEST, "Unable to find pmfm with id=" + pmfmId);
763 }
764
765 ParameterValueType type = ParameterValueType.fromPmfm(pmfm);
766 if (type == null) {
767 throw new SumarisTechnicalException(ErrorCodes.BAD_REQUEST, "Unable to find the type of the pmfm with id=" + pmfmId);
768 }
769
770 switch (type) {
771 case BOOLEAN:
772 target.setNumericalValue(Boolean.parseBoolean(value) || "1".equals(value) ? 1d : 0d);
773 break;
774 case QUALITATIVE_VALUE:
775
776 target.setQualitativeValue(load(QualitativeValue.class, Integer.parseInt(value)));
777 break;
778 case STRING:
779 target.setAlphanumericalValue(value);
780 break;
781 case DATE:
782 target.setAlphanumericalValue(value);
783 break;
784 case INTEGER:
785 case DOUBLE:
786 target.setNumericalValue(Double.parseDouble(value));
787 break;
788 default:
789
790 throw new SumarisTechnicalException( String.format("Unable to set measurement value {%s} for the type {%s}", value, type.name().toLowerCase()));
791 }
792 }
793
794 protected Object entityToValue(IMeasurementEntity source) {
795
796 Preconditions.checkNotNull(source);
797 Preconditions.checkNotNull(source.getPmfm());
798 Preconditions.checkNotNull(source.getPmfm().getId());
799
800 PmfmVO pmfm = pmfmDao.get(source.getPmfm().getId());
801
802 Preconditions.checkNotNull(pmfm, "Unable to find Pmfm with id=" + source.getPmfm().getId());
803
804 ParameterValueType type = ParameterValueType.fromPmfm(pmfm);
805 switch (type) {
806 case BOOLEAN:
807 return (source.getNumericalValue() != null && source.getNumericalValue().doubleValue() == 1d ? Boolean.TRUE : Boolean.FALSE);
808 case QUALITATIVE_VALUE:
809
810 return ((source.getQualitativeValue() != null && source.getQualitativeValue().getId() != null) ? source.getQualitativeValue().getId() : null);
811 case STRING:
812 case DATE:
813 return source.getAlphanumericalValue();
814 case INTEGER:
815 return ((source.getNumericalValue() != null) ? new Integer(source.getNumericalValue().intValue()) : null);
816 case DOUBLE:
817 return source.getNumericalValue();
818 default:
819
820 throw new SumarisTechnicalException( String.format("Unable to read measurement's value for the type {%s}. Measurement id=%s", type.name().toLowerCase(), source.getId()));
821 }
822 }
823
824 protected void fillDefaultProperties(IDataEntity<?> parent, IMeasurementEntity target) {
825
826
827 if (target.getRecorderDepartment() == null) {
828 if (parent.getRecorderDepartment() == null || parent.getRecorderDepartment().getId() == null) {
829 target.setRecorderDepartment(null);
830 }
831 else {
832 target.setRecorderDepartment(parent.getRecorderDepartment());
833 }
834 }
835
836
837 if (target.getQualityFlag() == null) {
838 target.setQualityFlag(load(QualityFlag.class, config.getDefaultQualityFlagId()));
839 }
840 }
841
842 protected void setParent(IMeasurementEntity target, final Class<?> parentClass, Serializable parentId, boolean copyIfNull) {
843
844
845 if (parentClass == null || (!copyIfNull && parentId == null)) return;
846
847
848 Collection<PropertyDescriptor> parentDescriptors = parentPropertiesMap.get(target.getClass());
849 if (CollectionUtils.isNotEmpty(parentDescriptors)) {
850
851
852 PropertyDescriptor parentProperty = parentDescriptors.stream()
853 .filter(property -> property.getPropertyType().isAssignableFrom(parentClass))
854 .findFirst().orElse(null);
855
856
857 if (parentProperty != null) {
858 try {
859 if (parentId == null) {
860 parentProperty.getWriteMethod().invoke(target, new Object[]{null});
861 } else {
862 Object parentEntity = load(parentClass, parentId);
863 parentProperty.getWriteMethod().invoke(target, parentEntity);
864 }
865 return;
866 } catch (Exception e) {
867 throw new SumarisTechnicalException(e);
868 }
869 }
870 }
871
872
873
874
875 if (target instanceof VesselUseMeasurement) {
876
877
878 if (parentClass.isAssignableFrom(Trip.class)) {
879 if (parentId == null) {
880 ((VesselUseMeasurement) target).setTrip(null);
881 } else {
882 ((VesselUseMeasurement) target).setTrip(load(Trip.class, parentId));
883 }
884 }
885
886
887 else if (parentClass.isAssignableFrom(Operation.class)) {
888 if (parentId == null) {
889 ((VesselUseMeasurement) target).setOperation(null);
890 } else {
891 ((VesselUseMeasurement) target).setOperation(load(Operation.class, parentId));
892 }
893 }
894 }
895
896
897 else if (target instanceof GearUseMeasurement) {
898
899 if (parentClass.isAssignableFrom(Operation.class)) {
900 if (parentId == null) {
901 ((GearUseMeasurement) target).setOperation(null);
902 } else {
903 ((GearUseMeasurement) target).setOperation(load(Operation.class, parentId));
904 }
905 }
906 }
907
908
909 else if (target instanceof PhysicalGearMeasurement) {
910
911 if (parentId == null) {
912 ((PhysicalGearMeasurement) target).setPhysicalGear(null);
913 } else {
914 ((PhysicalGearMeasurement) target).setPhysicalGear(load(PhysicalGear.class, parentId));
915 }
916 }
917
918
919 else if (target instanceof BatchQuantificationMeasurement) {
920 if (parentId == null) {
921 ((BatchQuantificationMeasurement) target).setBatch(null);
922 } else {
923 ((BatchQuantificationMeasurement) target).setBatch(load(Batch.class, parentId));
924 }
925 }
926
927
928 else if (target instanceof BatchSortingMeasurement) {
929 if (parentId == null) {
930 ((BatchSortingMeasurement) target).setBatch(null);
931 } else {
932 ((BatchSortingMeasurement) target).setBatch(load(Batch.class, parentId));
933 }
934 }
935
936
937 else {
938 throw new IllegalArgumentException(String.format("Class {%s} not manage yet in this method", target.getClass().getSimpleName()));
939 }
940
941 }
942
943 protected boolean isEmpty(MeasurementVO source) {
944 return StringUtils.isBlank(source.getAlphanumericalValue()) && source.getNumericalValue() == null
945 && (source.getQualitativeValue() == null || source.getQualitativeValue().getId() == null);
946 }
947 protected boolean isNotEmpty(MeasurementVO source) {
948 return !isEmpty(source);
949 }
950
951 }