View Javadoc
1   package fr.ifremer.dali.dao.system.extraction;
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.config.DaliConfiguration;
28  import fr.ifremer.dali.dao.administration.program.DaliProgramDao;
29  import fr.ifremer.dali.dao.administration.user.DaliDepartmentDao;
30  import fr.ifremer.dali.dao.administration.user.DaliQuserDao;
31  import fr.ifremer.dali.dao.data.survey.DaliCampaignDao;
32  import fr.ifremer.dali.dao.referential.DaliAnalysisInstrumentDao;
33  import fr.ifremer.dali.dao.referential.DaliReferentialDao;
34  import fr.ifremer.dali.dao.referential.DaliSamplingEquipmentDao;
35  import fr.ifremer.dali.dao.referential.monitoringLocation.DaliMonitoringLocationDao;
36  import fr.ifremer.dali.dao.referential.pmfm.DaliPmfmDao;
37  import fr.ifremer.dali.dao.referential.taxon.DaliTaxonGroupDao;
38  import fr.ifremer.dali.dao.referential.taxon.DaliTaxonNameDao;
39  import fr.ifremer.dali.dao.system.filter.DaliFilterDao;
40  import fr.ifremer.dali.dao.technical.Daos;
41  import fr.ifremer.dali.dto.DaliBeanFactory;
42  import fr.ifremer.dali.dto.DaliBeans;
43  import fr.ifremer.dali.dto.configuration.filter.FilterDTO;
44  import fr.ifremer.dali.dto.enums.ExtractionFilterTypeValues;
45  import fr.ifremer.dali.dto.referential.GroupingTypeDTO;
46  import fr.ifremer.dali.dto.referential.pmfm.PmfmDTO;
47  import fr.ifremer.dali.dto.system.extraction.ExtractionDTO;
48  import fr.ifremer.dali.dto.system.extraction.ExtractionParameterDTO;
49  import fr.ifremer.dali.dto.system.extraction.ExtractionPeriodDTO;
50  import fr.ifremer.dali.dto.system.extraction.PmfmPresetDTO;
51  import fr.ifremer.dali.service.DaliBusinessException;
52  import fr.ifremer.dali.service.DaliDataContext;
53  import fr.ifremer.dali.service.DaliTechnicalException;
54  import fr.ifremer.dali.vo.ExtractionParameterVO;
55  import fr.ifremer.dali.vo.ExtractionVO;
56  import fr.ifremer.dali.vo.FilterVO;
57  import fr.ifremer.dali.vo.PresetVO;
58  import fr.ifremer.quadrige3.core.dao.referential.monitoringLocation.ProjectionSystemImpl;
59  import fr.ifremer.quadrige3.core.dao.system.extraction.*;
60  import fr.ifremer.quadrige3.core.dao.system.filter.Filter;
61  import fr.ifremer.quadrige3.core.dao.system.filter.FilterTypeId;
62  import fr.ifremer.quadrige3.core.dao.technical.Assert;
63  import fr.ifremer.quadrige3.core.dao.technical.Dates;
64  import fr.ifremer.quadrige3.core.dao.technical.gson.Gsons;
65  import fr.ifremer.quadrige3.core.service.technical.CacheService;
66  import fr.ifremer.quadrige3.ui.core.dto.QuadrigeBean;
67  import org.apache.commons.collections4.CollectionUtils;
68  import org.hibernate.Session;
69  import org.hibernate.SessionFactory;
70  import org.hibernate.type.IntegerType;
71  import org.hibernate.type.StringType;
72  import org.springframework.beans.factory.InitializingBean;
73  import org.springframework.beans.factory.annotation.Autowired;
74  import org.springframework.cache.Cache;
75  import org.springframework.dao.DataRetrievalFailureException;
76  import org.springframework.stereotype.Repository;
77  
78  import javax.annotation.Resource;
79  import java.io.File;
80  import java.util.*;
81  import java.util.function.Function;
82  import java.util.regex.Matcher;
83  import java.util.regex.Pattern;
84  import java.util.stream.Collectors;
85  
86  import static org.nuiton.i18n.I18n.t;
87  
88  /**
89   * <p>DaliExtractionDaoImpl class.</p>
90   *
91   * @author Ludovic
92   */
93  @Repository("daliExtractionDao")
94  public class DaliExtractionDaoImpl extends ExtractFilterDaoImpl implements DaliExtractionDao, InitializingBean {
95  
96  //    private static final Log log = LogFactory.getLog(DaliExtractionDaoImpl.class);
97  
98      private static final String FILE_PATTERN = "Extraction_%s.json";
99      public static final String DATE_FORMAT = "ddMMyyyy";
100     public static final String DATE_SEPARATOR = "_";
101 
102     @Resource(name = "daliDataContext")
103     private DaliDataContext dataContext;
104 
105     @Resource(name = "daliQuserDao")
106     private DaliQuserDao quserDao;
107 
108     @Resource(name = "daliFilterDao")
109     private DaliFilterDao filterDao;
110 
111     @Resource(name = "daliReferentialDao")
112     private DaliReferentialDao referentialDao;
113 
114     @Resource(name = "daliPmfmDao")
115     protected DaliPmfmDao pmfmDao;
116 
117     @Resource(name = "daliAnalysisInstrumentDao")
118     private DaliAnalysisInstrumentDao analysisInstrumentDao;
119 
120     @Resource(name = "daliSamplingEquipmentDao")
121     private DaliSamplingEquipmentDao samplingEquipmentDao;
122 
123     @Resource(name = "daliTaxonNameDao")
124     private DaliTaxonNameDao taxonNameDao;
125 
126     @Resource(name = "daliTaxonGroupDao")
127     private DaliTaxonGroupDao taxonGroupDao;
128 
129     @Resource(name = "daliMonitoringLocationDao")
130     private DaliMonitoringLocationDao locationDao;
131 
132     @Resource(name = "daliProgramDao")
133     private DaliProgramDao programDao;
134 
135     @Resource(name = "daliCampaignDao")
136     private DaliCampaignDao campaignDao;
137 
138     @Resource(name = "daliDepartmentDao")
139     protected DaliDepartmentDao departmentDao;
140 
141     @Autowired
142     protected DaliConfiguration config;
143 
144     @Autowired
145     protected CacheService cacheService;
146 
147     private String defaultFileTypeCd;
148     private String defaultGroupTypePmfmCd;
149     private String defaultTableTypeCd;
150     private String defaultProjectionSystemCd;
151 
152     /**
153      * <p>Constructor for DaliExtractionDaoImpl.</p>
154      *
155      * @param sessionFactory a {@link org.hibernate.SessionFactory} object.
156      */
157     @Autowired
158     public DaliExtractionDaoImpl(SessionFactory sessionFactory) {
159         super(sessionFactory);
160     }
161 
162     /**
163      * {@inheritDoc}
164      */
165     @Override
166     public void afterPropertiesSet() {
167         initConstants();
168     }
169 
170     /**
171      * {@inheritDoc}
172      */
173     @Override
174     public List<ExtractionDTO> getAllExtractions() {
175         return getAllExtractions(true);
176     }
177 
178     @Override
179     public List<ExtractionDTO> getAllLightExtractions() {
180         return getAllExtractions(false);
181     }
182 
183     private List<ExtractionDTO> getAllExtractions(boolean withFiltersAndConfiguration) {
184         Iterator<Object[]> it = queryIterator("allExtractions");
185 
186         List<ExtractionDTO> extractions = Lists.newArrayList();
187         while (it.hasNext()) {
188             Object[] row = it.next();
189             ExtractionDTO extraction = toExtractionDTO(Arrays.asList(row).iterator());
190             if (withFiltersAndConfiguration) {
191                 loadFilters(extraction);
192                 loadParameter(extraction);
193             }
194             extractions.add(extraction);
195         }
196 
197         return extractions;
198     }
199 
200     /**
201      * {@inheritDoc}
202      */
203     @Override
204     public ExtractionDTO getExtractionById(int extractionId) {
205 
206         Object[] row = queryUnique("extractionById", "extractionId", IntegerType.INSTANCE, extractionId);
207 
208         if (row == null) {
209             throw new DataRetrievalFailureException("can't load extraction with id = " + extractionId);
210         }
211 
212         ExtractionDTO extraction = toExtractionDTO(Arrays.asList(row).iterator());
213         loadFilters(extraction);
214         loadParameter(extraction);
215         return extraction;
216     }
217 
218     /**
219      * {@inheritDoc}
220      */
221     @Override
222     public List<ExtractionDTO> searchExtractionByProgram(String programCode) {
223         Assert.notNull(programCode);
224 
225         Iterator<Object[]> it = queryIterator("extractionsByProgramCode",
226                 "programFilterTypeId", IntegerType.INSTANCE, FilterTypeId.PROGRAM.getValue(),
227                 "programCode", StringType.INSTANCE, programCode);
228 
229         List<ExtractionDTO> extractions = Lists.newArrayList();
230         while (it.hasNext()) {
231             Object[] row = it.next();
232             ExtractionDTO extraction = toExtractionDTO(Arrays.asList(row).iterator());
233             loadFilters(extraction);
234             loadParameter(extraction);
235             extractions.add(extraction);
236         }
237 
238         return extractions;
239     }
240 
241     /**
242      * {@inheritDoc}
243      */
244     @Override
245     public void saveExtraction(ExtractionDTO extraction) {
246         Assert.notNull(extraction);
247         Assert.notNull(extraction.getName());
248         Assert.notEmpty(extraction.getFilters());
249 
250         ExtractFilter entity;
251         boolean isNew = false;
252         if (extraction.getId() == null) {
253             entity = ExtractFilter.Factory.newInstance();
254             isNew = true;
255         } else {
256             entity = get(extraction.getId());
257             if (entity == null) {
258                 throw new DataRetrievalFailureException("Could not retrieve extraction with id=" + extraction.getId());
259             }
260         }
261 
262         beanToEntity(extraction, entity);
263 
264         if (isNew) {
265 
266             getSession().save(entity);
267             extraction.setId(entity.getExtractFilterId());
268         } else {
269             getSession().update(entity);
270         }
271 
272         savePeriods(extraction, entity);
273 
274         saveFilters(extraction, entity);
275 
276         saveParameter(extraction);
277 
278         getSession().flush();
279         getSession().clear();
280     }
281 
282     @Override
283     public void exportExtraction(ExtractionDTO extraction, File exportFile) {
284 
285         // Convert to VO
286         ExtractionVO extractionVO = toExtractionVO(extraction);
287 
288         // Serialize to exportFile
289         Gsons.serializeToFile(extractionVO, exportFile);
290 
291     }
292 
293     @Override
294     public ExtractionDTO importExtraction(File importFile) {
295 
296         // Deserialize from importFile
297         ExtractionVO extractionVO = Gsons.deserializeFile(importFile, ExtractionVO.class);
298 
299         // Convert to DTO
300         return toExtractionDTO(extractionVO);
301     }
302 
303     /**
304      * {@inheritDoc}
305      */
306     @Override
307     public void remove(ExtractFilter extractFilter) {
308 
309         extractFilter.getExtractSurveyPeriods().clear();
310         extractFilter.getFilters().clear();
311 
312         super.remove(extractFilter);
313     }
314 
315     // PRIVATE METHODS
316 
317     private void beanToEntity(ExtractionDTO extraction, ExtractFilter entity) {
318 
319         // mandatory attribute
320         entity.setExtractFilterNm(extraction.getName());
321 
322         // add user
323         if (extraction.getUser() == null) {
324             int userId = dataContext.getPrincipalUserId();
325             extraction.setUser(quserDao.getUserById(userId));
326             entity.setQuser(quserDao.get(userId));
327         }
328 
329         // optional attributes
330         entity.setExtractFilterInSitu(Daos.convertToString(false));
331         entity.setExtractFilterIsQualif(Daos.convertToString(false));
332 
333         // file type (= Text only)
334         if (entity.getExtractFileTypes() != null) {
335             if (entity.getExtractFileTypes().size() != 1 || !Objects.equals(entity.getExtractFileTypes().iterator().next().getExtractFileTypeCd(), defaultFileTypeCd)) {
336                 // bad file type, so recreate it
337                 entity.getExtractFileTypes().clear();
338                 entity.addExtractFileTypes(load(ExtractFileTypeImpl.class, defaultFileTypeCd));
339             }
340         } else {
341             // no file type, so create it
342             entity.setExtractFileTypes(Lists.newArrayList(load(ExtractFileTypeImpl.class, defaultFileTypeCd)));
343         }
344 
345         // group type pmfm (=PMFM)
346         if (entity.getExtractGroupTypePmfms() != null) {
347             if (entity.getExtractGroupTypePmfms().size() != 1 || !Objects.equals(entity.getExtractGroupTypePmfms().iterator().next().getExtractGroupTypePmfmCd(), defaultGroupTypePmfmCd)) {
348                 // bad group type, so recreate it
349                 entity.getExtractGroupTypePmfms().clear();
350                 entity.addExtractGroupTypePmfms(load(ExtractGroupTypePmfmImpl.class, defaultGroupTypePmfmCd));
351             }
352         } else {
353             // no group type, so create it
354             entity.setExtractGroupTypePmfms(Lists.newArrayList(load(ExtractGroupTypePmfmImpl.class, defaultGroupTypePmfmCd)));
355         }
356 
357         // table type (=inline)
358         entity.setExtractTableType(load(ExtractTableTypeImpl.class, defaultTableTypeCd));
359         // no aggregation level
360         entity.setExtractAgregationLevel(null);
361 
362         // projection system
363         entity.setProjectionSystem(load(ProjectionSystemImpl.class, defaultProjectionSystemCd));
364 
365     }
366 
367     private void savePeriods(ExtractionDTO extraction, ExtractFilter entity) {
368 
369         // Get existing periods
370         Map<Integer, ExtractSurveyPeriod> existingExtractSurveyPeriods = DaliBeans.mapByProperty(entity.getExtractSurveyPeriods(), "extractSurveyPeriodId");
371 
372         // find period filter
373         FilterDTO periodFilter = DaliBeans.findByProperty(extraction.getFilters(), FilterDTO.PROPERTY_FILTER_TYPE_ID, ExtractionFilterTypeValues.PERIOD.getFilterTypeId());
374         Assert.notNull(periodFilter);
375         Assert.notEmpty(periodFilter.getElements());
376 
377         for (QuadrigeBean bean : periodFilter.getElements()) {
378             ExtractionPeriodDTO period = (ExtractionPeriodDTO) bean;
379             Assert.notNull(period.getStartDate());
380             Assert.notNull(period.getEndDate());
381 
382             boolean isNew = false;
383             ExtractSurveyPeriod extractSurveyPeriod = existingExtractSurveyPeriods.remove(period.getId());
384             if (extractSurveyPeriod == null) {
385                 extractSurveyPeriod = ExtractSurveyPeriod.Factory.newInstance();
386                 extractSurveyPeriod.setExtractFilter(entity);
387                 isNew = true;
388             }
389             extractSurveyPeriod.setExtractSurveyPeriodStartDt(Dates.convertToDate(period.getStartDate(), config.getDbTimezone()));
390             extractSurveyPeriod.setExtractSurveyPeriodEndDt(Dates.convertToDate(period.getEndDate(), config.getDbTimezone()));
391 
392             if (isNew) {
393                 getSession().save(extractSurveyPeriod);
394                 period.setId(extractSurveyPeriod.getExtractSurveyPeriodId());
395             } else {
396                 getSession().update(extractSurveyPeriod);
397             }
398         }
399 
400         // remove remaining
401         if (!existingExtractSurveyPeriods.isEmpty()) {
402             entity.getExtractSurveyPeriods().removeAll(existingExtractSurveyPeriods.values());
403         }
404     }
405 
406     private void saveFilters(ExtractionDTO extraction, ExtractFilter entity) {
407 
408         int userId = extraction.getUser().getId();
409         Map<Integer, Filter> existingFilters = DaliBeans.mapByProperty(entity.getFilters(), "filterId");
410 
411         if (CollectionUtils.isNotEmpty(extraction.getFilters())) {
412             for (FilterDTO filter : extraction.getFilters()) {
413 
414                 // don't save period as filter
415                 if (ExtractionFilterTypeValues.getExtractionFilterType(filter.getFilterTypeId()) == ExtractionFilterTypeValues.PERIOD) {
416                     continue;
417                 }
418 
419                 // compute a specific name for each filter
420                 filter.setName(String.format("EXT_%d_%s", extraction.getId(), ExtractionFilterTypeValues.getExtractionFilterType(filter.getFilterTypeId())));
421 
422                 if (existingFilters.remove(filter.getId()) == null) {
423                     // new filter
424                     Filter newFilter = filterDao.saveFilter(filter, userId);
425                     newFilter.setExtractFilter(entity);
426                     getSession().update(newFilter);
427                     entity.addFilters(newFilter);
428                 } else if (filter.isDirty()) {
429                     // update filter
430                     filterDao.saveFilter(filter, userId);
431                 }
432             }
433         }
434 
435         if (!existingFilters.isEmpty()) {
436             // remove remaining
437             for (Filter filterToRemove : existingFilters.values()) {
438                 entity.removeFilters(filterToRemove);
439             }
440         }
441     }
442 
443     private ExtractionDTO toExtractionDTO(Iterator<Object> iterator) {
444         ExtractionDTO extraction = DaliBeanFactory.newExtractionDTO();
445         extraction.setId((Integer) iterator.next());
446         extraction.setName((String) iterator.next());
447 
448         Integer userId = (Integer) iterator.next();
449         if (userId != null) {
450             extraction.setUser(quserDao.getUserById(userId));
451         }
452 
453         return extraction;
454     }
455 
456     private void loadFilters(ExtractionDTO extraction) {
457 
458         extraction.setFilters(getFilters(extraction.getId()));
459 
460         // get the orderItemType filter and load the groupingType now
461         FilterDTO orderItemTypeFilter = DaliBeans.getFilterOfType(extraction, ExtractionFilterTypeValues.ORDER_ITEM_TYPE);
462         if (orderItemTypeFilter != null) {
463             if (!orderItemTypeFilter.isFilterLoaded()) {
464                 List<String> groupingTypeCodes = filterDao.getFilteredElementsByFilterId(orderItemTypeFilter.getId());
465                 orderItemTypeFilter.setElements(getGroupingType(groupingTypeCodes));
466                 orderItemTypeFilter.setFilterLoaded(true);
467             }
468         }
469 
470         // add extraction periods in filters
471         FilterDTO periodFilter = DaliBeanFactory.newFilterDTO();
472         periodFilter.setFilterTypeId(ExtractionFilterTypeValues.PERIOD.getFilterTypeId());
473         periodFilter.setElements(getPeriods(extraction.getId()));
474         periodFilter.setFilterLoaded(true);
475         extraction.addFilters(periodFilter);
476 
477     }
478 
479     private List<GroupingTypeDTO> getGroupingType(Collection<String> groupingTypeCodes) {
480 
481         if (groupingTypeCodes != null) {
482             if (CollectionUtils.size(groupingTypeCodes) > 1) {
483                 throw new DaliTechnicalException("Wrong number of grouping type code, must be <= 1");
484             }
485 
486             return Collections.singletonList(DaliBeans.findByProperty(
487                     referentialDao.getAllGroupingTypes(),
488                     GroupingTypeDTO.PROPERTY_CODE,
489                     groupingTypeCodes.iterator().next()));
490         }
491         return null;
492     }
493 
494     private Collection<FilterDTO> getFilters(Integer extractionId) {
495 
496         List<FilterDTO> filters = Lists.newArrayList();
497         Iterator<Integer> rows = queryIteratorTyped("extractionFilterIdByExtractionById", "extractionId", IntegerType.INSTANCE, extractionId);
498         Cache filterCache = cacheService.getCache(DaliFilterDao.FILTER_BY_ID_CACHE);
499         while (rows.hasNext()) {
500             Integer filterId = rows.next();
501 
502             // must evict actual filter from cache because it continues to be linked even the extraction is not saved
503             filterCache.evict(filterId);
504 
505             // get the filter but don't load elements
506             filters.add(filterDao.getFilterById(filterId));
507         }
508         return filters;
509     }
510 
511     private List<ExtractionPeriodDTO> getPeriods(int extractionId) {
512 
513         Iterator<Object[]> rows = queryIterator("extractionPeriodByExtractionById", "extractionId", IntegerType.INSTANCE, extractionId);
514         List<ExtractionPeriodDTO> periods = Lists.newArrayList();
515 
516         while (rows.hasNext()) {
517             Object[] row = rows.next();
518             ExtractionPeriodDTO period = DaliBeanFactory.newExtractionPeriodDTO();
519             period.setId((Integer) row[0]);
520             period.setStartDate(Dates.convertToLocalDate(Daos.convertToDate(row[1]), config.getDbTimezone()));
521             period.setEndDate(Dates.convertToLocalDate(Daos.convertToDate(row[2]), config.getDbTimezone()));
522             periods.add(period);
523         }
524         return periods;
525     }
526 
527     private void loadParameter(ExtractionDTO extraction) {
528 
529         Assert.notNull(extraction);
530         Assert.notNull(extraction.getId());
531 
532         ExtractionParameterVO parameter = Gsons.deserializeFile(getParameterFile(extraction.getId()), ExtractionParameterVO.class);
533         extraction.setParameter(toExtractionParameterDTO(parameter));
534     }
535 
536     private void saveParameter(ExtractionDTO extraction) {
537 
538         Assert.notNull(extraction);
539         Assert.notNull(extraction.getId());
540 
541         ExtractionParameterVO parameterVO = toExtractionParameterVO(extraction.getParameter());
542         Gsons.serializeToFile(parameterVO, getParameterFile(extraction.getId()));
543 
544     }
545 
546     private File getParameterFile(int extractionId) {
547 
548         File dir = config.getExtractionConfigDirectory();
549         if (!dir.isDirectory()) dir.mkdir();
550 
551         return new File(dir, String.format(FILE_PATTERN, extractionId));
552 
553     }
554 
555     private ExtractionVO toExtractionVO(ExtractionDTO extraction) {
556         ExtractionVO extractionVO = new ExtractionVO();
557         extractionVO.setName(extraction.getName());
558         extractionVO.setParameter(toExtractionParameterVO(extraction.getParameter()));
559 
560         for (FilterDTO filter : extraction.getFilters()) {
561             FilterVO filterVO = new FilterVO();
562             filterVO.setType(filter.getFilterTypeId());
563             if (filterVO.getType() == ExtractionFilterTypeValues.PERIOD.getFilterTypeId()) {
564                 filterVO.setElementIds(filter.getElements().stream()
565                         .map((Function<QuadrigeBean, ExtractionPeriodDTO>) ExtractionPeriodDTO.class::cast)
566                         .map(period -> Dates.formatDate(period.getStartDate(), DATE_FORMAT) + DATE_SEPARATOR + Dates.formatDate(period.getEndDate(), DATE_FORMAT))
567                         .collect(Collectors.toList()));
568             } else {
569                 filterVO.setElementIds(DaliBeans.collectStringIds(filter.getElements()));
570             }
571             extractionVO.addFilter(filterVO);
572         }
573 
574         return extractionVO;
575     }
576 
577     private ExtractionParameterVO toExtractionParameterVO(ExtractionParameterDTO extractionParameter) {
578         ExtractionParameterVO parameterVO = new ExtractionParameterVO();
579 
580         if (extractionParameter != null) {
581 
582             // set fill zero parameter
583             parameterVO.setFillZero(extractionParameter.isFillZero());
584 
585             // set pmfm preset
586             parameterVO.setPreset(toPresetVO(extractionParameter.getPmfmPresets()));
587 
588             // set result pmfm Ids
589             parameterVO.setResultPmfmIds(DaliBeans.collectIds(extractionParameter.getPmfmResults()));
590         }
591         return parameterVO;
592     }
593 
594     private PresetVO toPresetVO(Collection<PmfmPresetDTO> pmfmPresets) {
595         if (CollectionUtils.isEmpty(pmfmPresets)) return null;
596         PresetVO presetVO = new PresetVO();
597         for (PmfmPresetDTO pmfmPreset : pmfmPresets) {
598             presetVO.addPmfmPreset(pmfmPreset.getPmfm().getId(), DaliBeans.collectIds(pmfmPreset.getQualitativeValues()));
599         }
600         return presetVO;
601     }
602 
603     private ExtractionParameterDTO toExtractionParameterDTO(ExtractionParameterVO parameter) {
604         ExtractionParameterDTO extractionParameterDTO = DaliBeanFactory.newExtractionParameterDTO();
605 
606         if (parameter != null) {
607             extractionParameterDTO.setFillZero(parameter.isFillZero());
608 
609             // get pmfm presets and get beans
610             extractionParameterDTO.setPmfmPresets(toPmfmPresetDTOs(parameter.getPreset()));
611 
612             // get result pmfms
613             if (CollectionUtils.isNotEmpty(parameter.getResultPmfmIds())) {
614 
615                 extractionParameterDTO.setPmfmResults(parameter.getResultPmfmIds().stream().map(pmfmId -> pmfmDao.getPmfmById(pmfmId)).collect(Collectors.toList()));
616             }
617         }
618         return extractionParameterDTO;
619     }
620 
621     private List<PmfmPresetDTO> toPmfmPresetDTOs(PresetVO preset) {
622         if (preset == null) return null;
623         List<PmfmPresetDTO> pmfmPresets = new ArrayList<>();
624         for (Integer pmfmId : preset.getPmfmIds()) {
625 
626             PmfmPresetDTO pmfmPreset = DaliBeanFactory.newPmfmPresetDTO();
627             PmfmDTO pmfm = pmfmDao.getPmfmById(pmfmId);
628             pmfmPreset.setPmfm(pmfm);
629             Collection<Integer> qvIds = preset.getQualitativeValueIds(pmfmId);
630             pmfmPreset.setQualitativeValues(pmfm.getQualitativeValues().stream().filter(qv -> qvIds.contains(qv.getId())).collect(Collectors.toList()));
631 
632             pmfmPresets.add(pmfmPreset);
633         }
634         return pmfmPresets;
635     }
636 
637     private ExtractionDTO toExtractionDTO(ExtractionVO extractionVO) {
638 
639         ExtractionDTO extraction = DaliBeanFactory.newExtractionDTO();
640         // Find existing extraction filter with this name
641         extraction.setName(getNextName(extractionVO.getName()));
642         try {
643             extraction.setParameter(toExtractionParameterDTO(extractionVO.getParameter()));
644         } catch (DataRetrievalFailureException e) {
645             throw new DaliBusinessException(t("dali.error.import.referentialNotFound.message", ExtractionFilterTypeValues.PMFM.getLabel()));
646         }
647 
648         for (FilterVO filterVO : extractionVO.getFilters()) {
649             FilterDTO filter = DaliBeanFactory.newFilterDTO();
650             filter.setFilterTypeId(filterVO.getType());
651             ExtractionFilterTypeValues filterType = ExtractionFilterTypeValues.getExtractionFilterType(filter.getFilterTypeId());
652             Assert.notNull(filterType);
653             List<? extends QuadrigeBean> elements = null;
654             switch (filterType) {
655                 case PERIOD:
656                     List<ExtractionPeriodDTO> periods = new ArrayList<>();
657                     for (String dates : filterVO.getElementIds()) {
658                         ExtractionPeriodDTO period = DaliBeanFactory.newExtractionPeriodDTO();
659                         period.setStartDate(Dates.safeParseLocalDate(dates.substring(0, dates.indexOf(DATE_SEPARATOR)), DATE_FORMAT));
660                         period.setEndDate(Dates.safeParseLocalDate(dates.substring(dates.indexOf(DATE_SEPARATOR) + 1), DATE_FORMAT));
661                         periods.add(period);
662                     }
663                     elements = periods;
664                     break;
665                 case PROGRAM:
666                     elements = programDao.getProgramsByCodes(filterVO.getElementIds());
667                     break;
668                 case LOCATION:
669                     elements = locationDao.getLocationsByIds(filterVO.getElementIds().stream().map(Integer::valueOf).collect(Collectors.toList()));
670                     break;
671                 case CAMPAIGN:
672                     elements = campaignDao.getCampaignsByIds(filterVO.getElementIds().stream().map(Integer::valueOf).collect(Collectors.toList()));
673                     break;
674                 case SAMPLING_EQUIPMENT:
675                     elements = samplingEquipmentDao.getSamplingEquipmentsByIds(filterVO.getElementIds().stream().map(Integer::valueOf).collect(Collectors.toList()));
676                     break;
677                 case TAXON:
678                     elements = taxonNameDao.getTaxonNamesByIds(filterVO.getElementIds().stream().map(Integer::valueOf).collect(Collectors.toList()));
679                     break;
680                 case TAXON_GROUP:
681                     elements = taxonGroupDao.getTaxonGroupsByIds(filterVO.getElementIds().stream().map(Integer::valueOf).collect(Collectors.toList()));
682                     break;
683                 case DEPARTMENT:
684                     elements = departmentDao.getDepartmentsByIds(filterVO.getElementIds().stream().map(Integer::valueOf).collect(Collectors.toList()));
685                     break;
686                 case PMFM:
687                     elements = pmfmDao.getPmfmsByIds(filterVO.getElementIds().stream().map(Integer::valueOf).collect(Collectors.toList()));
688                     break;
689                 case ORDER_ITEM_TYPE:
690                     elements = getGroupingType(filterVO.getElementIds());
691                     break;
692             }
693 
694             if (CollectionUtils.size(filterVO.getElementIds()) != CollectionUtils.size(elements)) {
695                 throw new DaliBusinessException(t("dali.error.import.referentialNotFound.message", filterType.getLabel()));
696             }
697 
698             filter.setElements(elements);
699 
700             filter.setFilterLoaded(true);
701             extraction.addFilters(filter);
702         }
703 
704         return extraction;
705     }
706 
707     /**
708      * Get next unused name. Compute "name (auto_inc_suffix)"
709      *
710      * @param name current name
711      * @return the next unused name
712      */
713     private String getNextName(String name) {
714         List<String> names = getAllLightExtractions().stream().map(ExtractionDTO::getName).collect(Collectors.toList());
715         Pattern namePattern = Pattern.compile("(.*\\()([0-9]+)(\\)$)");
716         int suffix = 0;
717 
718         while (names.contains(name)) {
719             Matcher matcher = namePattern.matcher(name);
720             boolean hasSuffix = matcher.matches();
721 
722             if (hasSuffix) {
723                 String group = matcher.group(2);
724                 suffix = Integer.valueOf(group);
725                 name = String.format("%s%d%s", matcher.group(1), ++suffix, matcher.group(3));
726             } else {
727                 name = String.format("%s (%d)", name, ++suffix);
728             }
729         }
730 
731         return name;
732     }
733 
734     private void initConstants() {
735 
736         defaultFileTypeCd = config.getExtractionFileTypeCode();
737         defaultGroupTypePmfmCd = config.getExtractionGroupTypePmfmCode();
738         defaultTableTypeCd = config.getExtractionTableTypeCode();
739         defaultProjectionSystemCd = config.getExtractionProjectionSystemCode();
740 
741         // check constants in DB
742         if (config.isDbCheckConstantsEnable()) {
743             checkDbConstants();
744         }
745 
746     }
747 
748     private void checkDbConstants() {
749 
750         Session session = getSessionFactory().openSession();
751         try {
752             Assert.notNull(session.get(ExtractFileTypeImpl.class, defaultFileTypeCd));
753             Assert.notNull(session.get(ExtractGroupTypePmfmImpl.class, defaultGroupTypePmfmCd));
754             Assert.notNull(session.get(ExtractTableTypeImpl.class, defaultTableTypeCd));
755             Assert.notNull(session.get(ProjectionSystemImpl.class, defaultProjectionSystemCd));
756         } finally {
757             Daos.closeSilently(session);
758         }
759     }
760 
761 }