View Javadoc
1   package fr.ifremer.dali.dao.data.samplingoperation;
2   
3   /*
4    * #%L
5    * Dali :: Core
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2014 - 2015 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (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 Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  import com.google.common.collect.Lists;
27  import fr.ifremer.dali.dao.administration.user.DaliDepartmentDao;
28  import fr.ifremer.dali.dao.referential.DaliReferentialDao;
29  import fr.ifremer.dali.service.DaliDataContext;
30  import fr.ifremer.quadrige3.core.dao.administration.program.Program;
31  import fr.ifremer.quadrige3.core.dao.administration.user.DepartmentImpl;
32  import fr.ifremer.quadrige3.core.dao.data.samplingoperation.SamplingOperation;
33  import fr.ifremer.quadrige3.core.dao.data.samplingoperation.SamplingOperationDaoImpl;
34  import fr.ifremer.quadrige3.core.dao.data.survey.Survey;
35  import fr.ifremer.quadrige3.core.dao.data.survey.SurveyImpl;
36  import fr.ifremer.quadrige3.core.dao.referential.*;
37  import fr.ifremer.quadrige3.core.dao.referential.monitoringLocation.PositionningSystemImpl;
38  import fr.ifremer.quadrige3.core.dao.system.*;
39  import fr.ifremer.quadrige3.core.dao.technical.Daos;
40  import fr.ifremer.dali.dao.data.measurement.DaliMeasurementDao;
41  import fr.ifremer.dali.dao.data.photo.DaliPhotoDao;
42  import fr.ifremer.dali.dao.referential.DaliSamplingEquipmentDao;
43  import fr.ifremer.dali.dao.referential.DaliUnitDao;
44  import fr.ifremer.dali.dao.technical.Geometries;
45  import fr.ifremer.dali.dto.DaliBeanFactory;
46  import fr.ifremer.dali.dto.DaliBeans;
47  import fr.ifremer.dali.dto.data.measurement.MeasurementDTO;
48  import fr.ifremer.dali.dto.data.sampling.SamplingOperationDTO;
49  import org.apache.commons.collections4.CollectionUtils;
50  import org.hibernate.SessionFactory;
51  import org.hibernate.type.DateType;
52  import org.hibernate.type.IntegerType;
53  import org.hibernate.type.StringType;
54  import org.springframework.beans.factory.annotation.Autowired;
55  import org.springframework.dao.DataIntegrityViolationException;
56  import org.springframework.stereotype.Repository;
57  
58  import javax.annotation.Resource;
59  import java.util.*;
60  
61  /**
62   * <p>DaliSamplingOperationDaoImpl class.</p>
63   *
64   * @author Ludovic
65   */
66  @Repository("daliSamplingOperationDao")
67  public class DaliSamplingOperationDaoImpl extends SamplingOperationDaoImpl implements DaliSamplingOperationDao {
68  
69      @Resource(name = "daliReferentialDao")
70      private DaliReferentialDao referentialDao;
71  
72      @Resource(name = "daliSamplingEquipmentDao")
73      private DaliSamplingEquipmentDao samplingEquipmentDao;
74  
75      @Resource(name = "daliDepartmentDao")
76      protected DaliDepartmentDao departmentDao;
77  
78      @Resource(name = "daliMeasurementDao")
79      private DaliMeasurementDao measurementDao;
80  
81      @Resource(name = "daliPhotoDao")
82      private DaliPhotoDao photoDao;
83  
84      @Resource(name = "daliUnitDao")
85      private DaliUnitDao unitDao;
86  
87      @Resource(name = "daliDataContext")
88      private DaliDataContext dataContext;
89  
90      /**
91       * <p>Constructor for DaliSamplingOperationDaoImpl.</p>
92       *
93       * @param sessionFactory a {@link org.hibernate.SessionFactory} object.
94       */
95      @Autowired
96      public DaliSamplingOperationDaoImpl(SessionFactory sessionFactory) {
97          super(sessionFactory);
98      }
99  
100     /**
101      * {@inheritDoc}
102      */
103     @Override
104     public List<SamplingOperationDTO> getSamplingOperationsBySurveyId(int surveyId, boolean withIndividualMeasurements) {
105 
106         Iterator<Object[]> it = queryIterator("samplingOperationsBySurveyId",
107                 "surveyId", IntegerType.INSTANCE, surveyId);
108 
109         List<SamplingOperationDTO> result = Lists.newArrayList();
110 
111         while (it.hasNext()) {
112             Object[] source = it.next();
113             SamplingOperationDTO samplingOperation = toSamplingOperationDTO(Arrays.asList(source).iterator());
114 
115             // add measurements
116             loadMeasurements(samplingOperation, withIndividualMeasurements);
117 
118             result.add(samplingOperation);
119         }
120 
121         return result;
122     }
123 
124     /**
125      * {@inheritDoc}
126      */
127     @Override
128     public void saveSamplingOperationsBySurveyId(int surveyId, Collection<SamplingOperationDTO> samplingOperations) {
129 
130         Survey survey = load(SurveyImpl.class, surveyId);
131         List<Integer> existingSamplingOperationIds = DaliBeans.collectProperties(survey.getSamplingOperations(), "samplingOperId");
132 
133         if (CollectionUtils.isNotEmpty(samplingOperations)) {
134             for (SamplingOperationDTO samplingOperation : samplingOperations) {
135                 SamplingOperation target;
136                 if (samplingOperation.getId() == null) {
137                     samplingOperation.setDirty(true);
138                     target = SamplingOperation.Factory.newInstance();
139                 } else {
140                     target = get(samplingOperation.getId());
141                     existingSamplingOperationIds.remove(target.getSamplingOperId());
142 
143                     // check for utFormat change
144                     if (!Objects.equals(target.getSamplingOperUtFormat(), survey.getSurveyUtFormat())) {
145                         samplingOperation.setDirty(true);
146                     }
147 
148                     // check for geometry change (Mantis #46654)
149                     if (!Daos.safeConvertToBoolean(target.getSamplingOperActualPosition())) {
150                         samplingOperation.setDirty(true);
151                     }
152                 }
153 
154                 // save only if dirty
155                 if (samplingOperation.isDirty()) {
156 
157                     beanToEntity(samplingOperation, target, survey);
158 
159                     // set surveyId
160                     target.setSurvey(survey);
161 
162                     getSession().save(target);
163 
164                     // save geometry
165                     saveGeometry(samplingOperation, target, survey);
166 
167                     // update id
168                     samplingOperation.setId(target.getSamplingOperId());
169 
170                     // save measurements
171                     if (samplingOperation.isMeasurementsLoaded()) {
172                         List<MeasurementDTO> allMeasurements = Lists.newArrayList();
173                         allMeasurements.addAll(samplingOperation.getMeasurements());
174                         if (samplingOperation.isIndividualMeasurementsLoaded()) {
175                             allMeasurements.addAll(samplingOperation.getIndividualMeasurements());
176                         }
177                         measurementDao.saveMeasurementsBySamplingOperationId(samplingOperation.getId(), allMeasurements, samplingOperation.isIndividualMeasurementsLoaded());
178                     }
179 
180                     getSession().flush();
181                     getSession().clear();
182                     samplingOperation.setDirty(false);
183                 }
184             }
185         }
186 
187         // remove remaining sampling operations
188         if (!existingSamplingOperationIds.isEmpty()) {
189             for (Integer samplingOperationId : existingSamplingOperationIds) {
190                 remove(samplingOperationId);
191             }
192             getSession().flush();
193             getSession().clear();
194         }
195     }
196 
197     private void loadMeasurements(SamplingOperationDTO samplingOperation, boolean withIndividual) {
198 
199         List<MeasurementDTO> allMeasurements = measurementDao.getMeasurementsBySamplingOperationId(samplingOperation.getId(), withIndividual);
200         if (CollectionUtils.isNotEmpty(allMeasurements)) {
201 
202             // Iterate on all measurement to split them
203             for (MeasurementDTO measurement : allMeasurements) {
204 
205                 // link each measurement to sampling operation
206                 measurement.setSamplingOperation(samplingOperation);
207 
208                 if (measurement.getIndividualId() == null) {
209                     // Add to measurement
210                     samplingOperation.addMeasurements(measurement);
211                 } else if (withIndividual) {
212                     // If measurement has an individualId, split to other list
213                     samplingOperation.addIndividualMeasurements(measurement);
214                 }
215             }
216         }
217 
218         samplingOperation.setMeasurementsLoaded(true);
219         samplingOperation.setIndividualMeasurementsLoaded(withIndividual);
220     }
221 
222     /**
223      * {@inheritDoc}
224      */
225     @Override
226     public void removeBySurveyId(int surveyId) {
227 
228         // list all sampling operations delete them unitarily
229         Iterator<Object[]> it = queryIterator("samplingOperationsBySurveyId",
230                 "surveyId", IntegerType.INSTANCE, surveyId);
231 
232         List<Integer> samplingOperationIds = Lists.newArrayList();
233         while (it.hasNext()) {
234             Object[] source = it.next();
235 
236             // read only the Id
237             samplingOperationIds.add((Integer) source[0]);
238         }
239 
240         for (Integer samplingOperationId : samplingOperationIds) {
241             remove(samplingOperationId);
242         }
243     }
244 
245     /**
246      * {@inheritDoc}
247      */
248     @Override
249     public void remove(Integer samplingOperationId) {
250 
251         // remove measurement first
252         measurementDao.removeAllMeasurementsBySamplingOperationId(samplingOperationId);
253 
254         // removeMeasurementsByIds photos
255         photoDao.removeBySamplingOperationId(samplingOperationId);
256 
257         super.remove(samplingOperationId);
258     }
259 
260     @Override
261     public int validateBySurveyIds(Collection<Integer> surveyIds, Date validationDate) {
262         return createQuery("validateSamplingOperationBySurveyIds",
263                 "validationDate", DateType.INSTANCE, validationDate)
264                 .setParameterList("surveyIds", surveyIds)
265                 .executeUpdate();
266     }
267 
268     @Override
269     public int unvalidateBySurveyIds(Collection<Integer> surveyIds) {
270         return createQuery("unvalidateSamplingOperationBySurveyIds",
271                 "qualityFlag", StringType.INSTANCE, QualityFlagCode.NOT_QUALIFIED.getValue())
272                 .setParameterList("surveyIds", surveyIds)
273                 .executeUpdate();
274     }
275 
276     @Override
277     public int qualifyBySurveyIds(List<Integer> surveyIds, Date qualificationDate, String qualityLevelCode) {
278         return createQuery("qualifySamplingOperationBySurveyIds",
279                 "qualificationDate", DateType.INSTANCE, qualificationDate,
280                 "qualityFlag", StringType.INSTANCE, qualityLevelCode)
281                 .setParameterList("surveyIds", surveyIds)
282                 .executeUpdate();
283     }
284 
285     /**
286      * {@inheritDoc}
287      */
288     @Override
289     public void updateSamplingOperationsControlDate(Collection<Integer> samplingOperationIds, Date controlDate) {
290         createQuery("updateSamplingOperationControlDate")
291                 .setParameterList("operationIds", samplingOperationIds)
292                 .setParameter("controlDate", controlDate).executeUpdate();
293     }
294 
295     // INTERNAL METHODS
296     private SamplingOperationDTO toSamplingOperationDTO(Iterator<Object> it) {
297         SamplingOperationDTO result = DaliBeanFactory.newSamplingOperationDTO();
298 
299         result.setId((Integer) it.next());
300         result.setName((String) it.next());
301         result.setTime(Daos.convertToInteger((Number) it.next()));
302         result.setComment((String) it.next());
303         result.setControlDate(Daos.convertToDate(it.next()));
304         result.setSamplingEquipment(samplingEquipmentDao.getSamplingEquipmentById((int) it.next()));
305         result.setSamplingDepartment(departmentDao.getDepartmentById((int) it.next()));
306         result.setSize(Daos.convertToDouble((Float) it.next()));
307 
308         // optional
309         Integer unitId = (Integer) it.next();
310         if (unitId != null) {
311             result.setSizeUnit(unitDao.getUnitById(unitId));
312         }
313         Integer depthLevelId = (Integer) it.next();
314         if (depthLevelId != null) {
315             result.setDepthLevel(referentialDao.getDepthLevelById(depthLevelId));
316         }
317         result.setDepth(Daos.convertToDouble((Float) it.next()));
318         result.setMaxDepth(Daos.convertToDouble((Float) it.next()));
319         result.setMinDepth(Daos.convertToDouble((Float) it.next()));
320         result.setIndividualCount(Daos.convertToInteger((Number) it.next()));
321 
322         // Get positioning system
323         Integer posSystemId = (Integer) it.next();
324 
325         // is actual position ?
326         boolean isActualPosition = Daos.safeConvertToBoolean(it.next(), false);
327 
328         // Geometry and positioning system
329         // -> only keep if actualPosition = true (see mantis #28257)
330         String geometryStr = (String) it.next();
331         if (isActualPosition) {
332             result.setCoordinate(Geometries.getCoordinate(geometryStr));
333 
334             if (posSystemId != null) {
335                 result.setPositioning(referentialDao.getPositioningSystemById(posSystemId));
336             }
337         }
338 
339         return result;
340     }
341 
342     private void beanToEntity(SamplingOperationDTO bean, SamplingOperation entity, Survey survey) {
343 
344         entity.setSamplingOperLb(bean.getName());
345         entity.setSamplingOperTime(bean.getTime());
346         entity.setSamplingOperUtFormat(survey.getSurveyUtFormat());
347         entity.setSamplingOperCm(bean.getComment());
348         entity.setSamplingOperControlDt(bean.getControlDate());
349         entity.setSamplingEquipment(load(SamplingEquipmentImpl.class, bean.getSamplingEquipment().getId()));
350         entity.setDepartment(load(DepartmentImpl.class, bean.getSamplingDepartment().getId()));
351 
352         // Recorder Department (Mantis #42614 Only if REC_DEP_ID is null)
353         if (entity.getRecorderDepartment() == null) {
354             entity.setRecorderDepartment(load(DepartmentImpl.class, dataContext.getRecorderDepartmentId()));
355         }
356 
357         if (entity.getQualityFlag() == null) {
358             entity.setQualityFlag(getDefaultQualityFlag());
359         }
360         if (CollectionUtils.isNotEmpty(survey.getPrograms())) {
361             for (Program program : survey.getPrograms()) {
362                 entity.addPrograms(program);
363             }
364         }
365 
366         entity.setSamplingOperSize(bean.getSize() == null ? null : bean.getSize().floatValue());
367 
368         if (bean.getSizeUnit() == null) {
369             entity.setSizeUnit(null);
370         } else {
371             entity.setSizeUnit(load(UnitImpl.class, bean.getSizeUnit().getId()));
372         }
373 
374         if (bean.getDepthLevel() == null) {
375             entity.setDepthLevel(null);
376         } else {
377             entity.setDepthLevel(load(DepthLevelImpl.class, bean.getDepthLevel().getId()));
378         }
379         entity.setSamplingOperDepth(bean.getDepth() == null ? null : bean.getDepth().floatValue());
380         entity.setSamplingOperMaxDepth(bean.getMaxDepth() == null ? null : bean.getMaxDepth().floatValue());
381         entity.setSamplingOperMinDepth(bean.getMinDepth() == null ? null : bean.getMinDepth().floatValue());
382 
383         // set depth unit only if there is a depth (Mantis #45002)
384         if (entity.getSamplingOperDepth() != null || entity.getSamplingOperMinDepth() != null || entity.getSamplingOperMaxDepth() != null) {
385             // depth unit (meter is default)
386             entity.setDepthUnit(load(UnitImpl.class, UnitId.METER.getValue()));
387         } else {
388             entity.setDepthUnit(null);
389         }
390 
391         entity.setSamplingOperNumberIndiv(bean.getIndividualCount());
392 
393         if (bean.getPositioning() == null) {
394             entity.setPositionningSystem(null);
395         } else {
396             entity.setPositionningSystem(load(PositionningSystemImpl.class, bean.getPositioning().getId()));
397         }
398 
399     }
400 
401     private void saveGeometry(SamplingOperationDTO bean, SamplingOperation entity, Survey survey) {
402 
403         // If coordinates has been filled by user
404         if (Geometries.isValid(bean.getCoordinate())) {
405 
406             if (Geometries.isPoint(bean.getCoordinate())) {
407 
408                 // point
409                 if (entity.getSamplingOperPoints() != null && entity.getSamplingOperPoints().size() == 1) {
410 
411                     SamplingOperPoint pointToUpdate = entity.getSamplingOperPoints().iterator().next();
412                     if (!Geometries.equals(bean.getCoordinate(), pointToUpdate.getSamplingOperPosition())) {
413                         pointToUpdate.setSamplingOperPosition(Geometries.getPosition(bean.getCoordinate()));
414                         getSession().update(pointToUpdate);
415                     }
416 
417                 } else {
418                     // create a sampling operation point
419                     SamplingOperPoint point = SamplingOperPoint.Factory.newInstance();
420                     point.setSamplingOperation(entity);
421                     point.setSamplingOperPosition(Geometries.getPosition(bean.getCoordinate()));
422                     getSession().save(point);
423                     entity.getSamplingOperPoints().clear();
424                     entity.addSamplingOperPoints(point);
425                 }
426                 entity.getSamplingOperAreas().clear();
427 
428             } else {
429 
430                 // line
431                 if (entity.getSamplingOperLines() != null && entity.getSamplingOperLines().size() == 1) {
432 
433                     SamplingOperLine lineToUpdate = entity.getSamplingOperLines().iterator().next();
434                     if (!Geometries.equals(bean.getCoordinate(), lineToUpdate.getSamplingOperPosition())) {
435                         lineToUpdate.setSamplingOperPosition(Geometries.getPosition(bean.getCoordinate()));
436                         getSession().update(lineToUpdate);
437                     }
438 
439                 } else {
440                     // create a sampling operation line
441                     SamplingOperLine line = SamplingOperLine.Factory.newInstance();
442                     line.setSamplingOperation(entity);
443                     line.setSamplingOperPosition(Geometries.getPosition(bean.getCoordinate()));
444                     getSession().save(line);
445                     entity.getSamplingOperLines().clear();
446                     entity.addSamplingOperLines(line);
447                 }
448                 entity.getSamplingOperLines().clear();
449 
450             }
451 
452             // clear unused coordinates
453             entity.getSamplingOperAreas().clear();
454 
455             // Update flag to known is coordinate are filled by user or not (mantis #28257)
456             entity.setSamplingOperActualPosition(Daos.convertToString(true));
457 
458         } else {
459             saveGeometryFromSurvey(entity, survey);
460         }
461 
462         update(entity);
463 
464     }
465 
466     private void saveGeometryFromSurvey(SamplingOperation entity, Survey survey) {
467 
468         // Point geometry
469         if (CollectionUtils.size(survey.getSurveyPoints()) == 1) {
470             SurveyPoint sourcePoint = CollectionUtils.extractSingleton(survey.getSurveyPoints());
471 
472             // Survey has already a area, so update it
473             if (CollectionUtils.size(entity.getSamplingOperPoints()) == 1) {
474                 SamplingOperPoint targetPoint = CollectionUtils.extractSingleton(entity.getSamplingOperPoints());
475                 if (!Objects.equals(targetPoint.getSamplingOperPosition(), sourcePoint.getSurveyPosition())) {
476                     targetPoint.setSamplingOperPosition(sourcePoint.getSurveyPosition());
477                     getSession().update(targetPoint);
478                 }
479             }
480 
481             // No existing area: create new
482             else {
483                 SamplingOperPoint targetPoint = SamplingOperPoint.Factory.newInstance();
484                 targetPoint.setSamplingOperation(entity);
485                 targetPoint.setSamplingOperPosition(sourcePoint.getSurveyPosition());
486                 getSession().save(targetPoint);
487                 entity.getSamplingOperPoints().clear();
488                 entity.addSamplingOperPoints(targetPoint);
489             }
490 
491             // Clean unused
492             entity.getSamplingOperLines().clear();
493             entity.getSamplingOperAreas().clear();
494         }
495 
496         // Line geometry
497         else if (CollectionUtils.size(survey.getSurveyLines()) == 1) {
498             SurveyLine sourceLine = CollectionUtils.extractSingleton(survey.getSurveyLines());
499 
500             // Survey has already a area, so update it
501             if (CollectionUtils.size(entity.getSamplingOperLines()) == 1) {
502                 SamplingOperLine targetLine = CollectionUtils.extractSingleton(entity.getSamplingOperLines());
503                 if (!Objects.equals(sourceLine.getSurveyPosition(), targetLine.getSamplingOperPosition())) {
504                     targetLine.setSamplingOperPosition(sourceLine.getSurveyPosition());
505                     getSession().update(targetLine);
506                 }
507             }
508 
509             // No existing area: create new
510             else {
511                 SamplingOperLine targetLine = SamplingOperLine.Factory.newInstance();
512                 targetLine.setSamplingOperation(entity);
513                 targetLine.setSamplingOperPosition(sourceLine.getSurveyPosition());
514                 getSession().save(targetLine);
515                 entity.getSamplingOperLines().clear();
516                 entity.addSamplingOperLines(targetLine);
517             }
518 
519             // Clean unused
520             entity.getSamplingOperPoints().clear();
521             entity.getSamplingOperAreas().clear();
522         }
523 
524         // Area geometry
525         else if (CollectionUtils.size(survey.getSurveyAreas()) == 1) {
526             SurveyArea sourceArea = CollectionUtils.extractSingleton(survey.getSurveyAreas());
527 
528             // Survey has already a area, so update it
529             if (CollectionUtils.size(entity.getSamplingOperAreas()) == 1) {
530                 SamplingOperArea targetArea = CollectionUtils.extractSingleton(entity.getSamplingOperAreas());
531                 if (!Objects.equals(sourceArea.getSurveyPosition(), targetArea.getSamplingOperPosition())) {
532                     targetArea.setSamplingOperPosition(sourceArea.getSurveyPosition());
533                     getSession().update(targetArea);
534                 }
535             }
536 
537             // No existing area: create new
538             else {
539                 SamplingOperArea targetArea = SamplingOperArea.Factory.newInstance();
540                 targetArea.setSamplingOperation(entity);
541                 targetArea.setSamplingOperPosition(sourceArea.getSurveyPosition());
542                 getSession().save(targetArea);
543                 entity.getSamplingOperAreas().clear();
544                 entity.addSamplingOperAreas(targetArea);
545             }
546 
547             // Clean unused
548             entity.getSamplingOperPoints().clear();
549             entity.getSamplingOperLines().clear();
550         } else {
551             throw new DataIntegrityViolationException(String.format("Could not found geometry on survey [surveyId=%s].", survey.getSurveyId()));
552         }
553 
554         // Update flag to known is coordinate is not filled by user or not (mantis #28257)
555         entity.setSamplingOperActualPosition(Daos.convertToString(false));
556 
557         // Apply positioning system from survey (see mantis #28706)
558         entity.setPositionningSystem(survey.getPositionningSystem());
559     }
560 
561     /**
562      * return the default quality flag
563      *
564      * @return the default quality flag
565      */
566     private QualityFlag getDefaultQualityFlag() {
567         return load(QualityFlagImpl.class, QualityFlagCode.NOT_QUALIFIED.getValue()); // = non qualifié
568     }
569 
570 }