View Javadoc
1   package fr.ifremer.reefdb.dao.referential.pmfm;
2   
3   /*
4    * #%L
5    * Reef DB :: 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.*;
27  import fr.ifremer.quadrige3.core.dao.referential.StatusCode;
28  import fr.ifremer.quadrige3.core.dao.referential.StatusImpl;
29  import fr.ifremer.quadrige3.core.dao.referential.UnitImpl;
30  import fr.ifremer.quadrige3.core.dao.referential.pmfm.*;
31  import fr.ifremer.quadrige3.core.dao.technical.Assert;
32  import fr.ifremer.quadrige3.core.dao.technical.hibernate.TemporaryDataHelper;
33  import fr.ifremer.quadrige3.core.service.technical.CacheService;
34  import fr.ifremer.reefdb.config.ReefDbConfiguration;
35  import fr.ifremer.reefdb.dao.referential.ReefDbUnitDao;
36  import fr.ifremer.reefdb.dao.referential.transcribing.ReefDbTranscribingItemDao;
37  import fr.ifremer.reefdb.dao.technical.Daos;
38  import fr.ifremer.reefdb.dto.ReefDbBeanFactory;
39  import fr.ifremer.reefdb.dto.ReefDbBeans;
40  import fr.ifremer.reefdb.dto.referential.pmfm.FractionDTO;
41  import fr.ifremer.reefdb.dto.referential.pmfm.MatrixDTO;
42  import fr.ifremer.reefdb.dto.referential.pmfm.PmfmDTO;
43  import fr.ifremer.reefdb.dto.referential.pmfm.QualitativeValueDTO;
44  import org.apache.commons.collections4.CollectionUtils;
45  import org.apache.commons.logging.Log;
46  import org.apache.commons.logging.LogFactory;
47  import org.hibernate.Query;
48  import org.hibernate.SessionFactory;
49  import org.hibernate.type.IntegerType;
50  import org.hibernate.type.StringType;
51  import org.springframework.beans.factory.annotation.Autowired;
52  import org.springframework.cache.Cache;
53  import org.springframework.dao.DataRetrievalFailureException;
54  import org.springframework.stereotype.Repository;
55  
56  import javax.annotation.Resource;
57  import java.util.*;
58  
59  /**
60   * <p>ReefDbPmfmDaoImpl class.</p>
61   *
62   */
63  @Repository("reefDbPmfmDao")
64  public class ReefDbPmfmDaoImpl extends PmfmDaoImpl implements ReefDbPmfmDao {
65  
66      private static final Log log = LogFactory.getLog(ReefDbPmfmDaoImpl.class);
67  
68      private static final Multimap<String, String> columnNamesByProgramTableNames = ImmutableListMultimap.<String, String>builder()
69              .put("PMFM_STRATEGY", "PMFM_ID").build();
70  
71      private static final Multimap<String, String> columnNamesByDataTableNames = ImmutableListMultimap.<String, String>builder()
72              .put("MEASUREMENT", "PMFM_ID")
73              .put("MEASUREMENT_FILE", "PMFM_ID")
74              .put("TAXON_MEASUREMENT", "PMFM_ID").build();
75  
76      private static final Map<String, String> validationDateColumnNameByDataTableNames = ImmutableMap.<String, String>builder()
77              .put("MEASUREMENT", "MEAS_VALID_DT")
78              .put("MEASUREMENT_FILE", "MEAS_FILE_VALID_DT")
79              .put("TAXON_MEASUREMENT", "TAXON_MEAS_VALID_DT").build();
80  
81      @Resource
82      protected CacheService cacheService;
83  
84      @Resource
85      protected ReefDbConfiguration config;
86  
87      @Resource(name = "reefDbParameterDao")
88      protected ReefDbParameterDao parameterDao;
89  
90      @Resource(name = "reefDbMethodDao")
91      protected ReefDbMethodDao methodDao;
92  
93      @Resource(name = "reefDbFractionDao")
94      protected ReefDbFractionDao fractionDao;
95  
96      @Resource(name = "reefDbMatrixDao")
97      protected ReefDbMatrixDao matrixDao;
98  
99      @Resource(name = "reefDbUnitDao")
100     protected ReefDbUnitDao unitDao;
101 
102     @Resource(name = "reefDbTranscribingItemDao")
103     protected ReefDbTranscribingItemDao transcribingItemDao;
104 
105     @Resource(name = "reefDbQualitativeValueDao")
106     protected ReefDbQualitativeValueDao qualitativeValueDao;
107 
108     /**
109      * <p>Constructor for ReefDbPmfmDaoImpl.</p>
110      *
111      * @param sessionFactory a {@link org.hibernate.SessionFactory} object.
112      */
113     @Autowired
114     public ReefDbPmfmDaoImpl(SessionFactory sessionFactory) {
115         super(sessionFactory);
116     }
117 
118     /** {@inheritDoc} */
119     @Override
120     public List<PmfmDTO> getAllPmfms(List<String> statusCodes) {
121 
122         Cache cacheById = cacheService.getCache(PMFM_BY_ID_CACHE);
123 
124         // Read all transcribing names
125         Map<Integer, String> transcribingNamesById = getTranscribingNames();
126 
127         Iterator<Object[]> it = Daos.queryIteratorWithStatus(createQuery("allPmfms"), statusCodes);
128 
129         List<PmfmDTO> result = Lists.newArrayList();
130         while (it.hasNext()) {
131             Object[] source = it.next();
132 
133             // Create the VO
134             PmfmDTO pmfm = toPmfmDTO(Arrays.asList(source).iterator(), transcribingNamesById);
135 
136             result.add(pmfm);
137             cacheById.put(pmfm.getId(), pmfm);
138         }
139 
140         return ImmutableList.copyOf(result);
141     }
142 
143     /** {@inheritDoc} */
144     @Override
145     public List<PmfmDTO> findPmfms(String parameterCode, Integer matrixId, Integer fractionId, Integer methodId, Integer unitId, String pmfmName, List<String> statusCodes) {
146         // Read all transcribing names
147         Map<Integer, String> transcribingNamesById = getTranscribingNames();
148 
149         Query query = createQuery("pmfmsByCriteria",
150                 "parameterCode", StringType.INSTANCE, parameterCode,
151                 "matrixId", IntegerType.INSTANCE, matrixId,
152                 "fractionId", IntegerType.INSTANCE, fractionId,
153                 "methodId", IntegerType.INSTANCE, methodId,
154                 "unitId", IntegerType.INSTANCE, unitId,
155                 "pmfmName", StringType.INSTANCE, pmfmName);
156 
157         Iterator<Object[]> it = Daos.queryIteratorWithStatus(query, statusCodes);
158 
159         // other solution: use criteria API and findByExample
160         List<PmfmDTO> result = Lists.newArrayList();
161         while (it.hasNext()) {
162             Object[] source = it.next();
163 
164             // Create the VO
165             PmfmDTO pmfm = toPmfmDTO(Arrays.asList(source).iterator(), transcribingNamesById);
166             result.add(pmfm);
167         }
168 
169         return ImmutableList.copyOf(result);
170     }
171 
172     /** {@inheritDoc} */
173     @Override
174     public void savePmfms(List<? extends PmfmDTO> pmfms) {
175         if (CollectionUtils.isEmpty(pmfms)) {
176             return;
177         }
178 
179         for (PmfmDTO pmfm : pmfms) {
180             if (pmfm.isDirty()) {
181                 savePmfm(pmfm);
182                 pmfm.setDirty(false);
183             }
184         }
185         getSession().flush();
186         getSession().clear();
187     }
188 
189     /** {@inheritDoc} */
190     @Override
191     public void deletePmfms(List<Integer> pmfmIds) {
192         if (pmfmIds == null) return;
193         pmfmIds.stream().filter(Objects::nonNull).distinct().forEach(this::remove);
194         getSession().flush();
195         getSession().clear();
196     }
197 
198     /** {@inheritDoc} */
199     @Override
200     public void replaceTemporaryPmfm(Integer sourceId, Integer targetId, boolean delete) {
201         Assert.notNull(sourceId);
202         Assert.notNull(targetId);
203 
204         executeMultipleUpdateWithNullCondition(columnNamesByDataTableNames, validationDateColumnNameByDataTableNames, sourceId, targetId);
205 
206         if (delete) {
207             // delete temporary
208             remove(sourceId);
209         }
210 
211         getSession().flush();
212         getSession().clear();
213     }
214 
215     /** {@inheritDoc} */
216     @Override
217     public boolean isPmfmUsedInData(int pmfmId) {
218 
219         return executeMultipleCount(columnNamesByDataTableNames, pmfmId);
220     }
221 
222     /** {@inheritDoc} */
223     @Override
224     public boolean isPmfmUsedInValidatedData(int pmfmId) {
225 
226         return executeMultipleCountWithNotNullCondition(columnNamesByDataTableNames, validationDateColumnNameByDataTableNames, pmfmId);
227     }
228 
229     /** {@inheritDoc} */
230     @Override
231     public boolean isPmfmUsedInProgram(int pmfmId) {
232 
233         return executeMultipleCount(columnNamesByProgramTableNames, pmfmId);
234     }
235 
236     /** {@inheritDoc} */
237     @Override
238     public boolean isPmfmUsedInRules(int pmfmId) {
239 
240         return queryCount("countRulePmfmByPmfmId", "pmfmId", IntegerType.INSTANCE, pmfmId) > 0;
241     }
242 
243     /** {@inheritDoc} */
244     @Override
245     public PmfmDTO getPmfmById(int pmfmId) {
246         Object[] source = queryUnique("pmfmById",
247                 "pmfmId", IntegerType.INSTANCE, pmfmId);
248 
249         if (source == null) {
250             throw new DataRetrievalFailureException("can't load pmfm with id = " + pmfmId);
251         }
252 
253         return toPmfmDTO(Arrays.asList(source).iterator(), getTranscribingNames());
254     }
255 
256     /** {@inheritDoc} */
257     @Override
258     @SuppressWarnings("unchecked")
259     public List<PmfmDTO> getPmfmsByIds(List<Integer> pmfmIds) {
260         // Read all transcribing names
261         Map<Integer, String> transcribingNamesById = getTranscribingNames();
262 
263         Iterator<Object[]> it = createQuery("pmfmByIds")
264                 .setParameterList("pmfmIds", pmfmIds)
265                 .iterate();
266 
267         List<PmfmDTO> result = Lists.newArrayList();
268         while (it.hasNext()) {
269             Object[] source = it.next();
270 
271             // Create the VO
272             result.add(toPmfmDTO(Arrays.asList(source).iterator(), transcribingNamesById));
273         }
274 
275         return result;
276     }
277 
278     // INTERNAL METHODS
279 
280     private Map<Integer, String> getTranscribingNames() {
281         return transcribingItemDao.getAllTranscribingItemsById(config.getTranscribingItemTypeLbForPmfmNm());
282     }
283 
284     private void savePmfm(PmfmDTO pmfm) {
285         Assert.notNull(pmfm);
286         Assert.notNull(pmfm.getParameter());
287         Assert.notNull(pmfm.getMatrix());
288         Assert.notNull(pmfm.getFraction());
289         Assert.notNull(pmfm.getMethod());
290         Assert.notNull(pmfm.getUnit());
291 
292         if (pmfm.getStatus() == null) {
293             pmfm.setStatus(Daos.getStatus(StatusCode.LOCAL_ENABLE));
294         }
295         Assert.isTrue(ReefDbBeans.isLocalStatus(pmfm.getStatus()), "source must have local status");
296 
297         Pmfm target;
298         if (pmfm.getId() == null) {
299             target = Pmfm.Factory.newInstance();
300             target.setPmfmId(TemporaryDataHelper.getNewNegativeIdForTemporaryData(getSession(), target.getClass()));
301         } else {
302             target = get(pmfm.getId());
303             Assert.isTrue(ReefDbBeans.isLocalStatus(target.getStatus()), "target must have local status");
304         }
305 
306         target.setStatus(load(StatusImpl.class, pmfm.getStatus().getCode()));
307         target.setParameter(load(ParameterImpl.class, pmfm.getParameter().getCode()));
308         target.setMatrix(load(MatrixImpl.class, pmfm.getMatrix().getId()));
309         target.setFraction(load(FractionImpl.class, pmfm.getFraction().getId()));
310         target.setMethod(load(MethodImpl.class, pmfm.getMethod().getId()));
311         target.setUnit(load(UnitImpl.class, pmfm.getUnit().getId()));
312 
313         target.setUpdateDt(newUpdateTimestamp());
314 
315         getSession().save(target);
316         pmfm.setId(target.getPmfmId());
317 
318         // qualitative values
319         if (pmfm.sizeQualitativeValues() > 0) {
320 
321             Map<Integer, PmfmQualValue> remainingPQV = ReefDbBeans.mapByProperty(target.getPmfmQualValues(), "pmfmQualValuePk.qualitativeValue.qualValueId");
322             for (QualitativeValueDTO qualitativeValue : pmfm.getQualitativeValues()) {
323                 if (remainingPQV.remove(qualitativeValue.getId()) == null) {
324                     // add PmfmQualValue
325                     QualitativeValue targetQV = load(QualitativeValueImpl.class, qualitativeValue.getId());
326                     PmfmQualValue pmfmQualValue = PmfmQualValue.Factory.newInstance();
327                     pmfmQualValue.setPmfm(target);
328                     pmfmQualValue.setQualitativeValue(targetQV);
329                     PmfmQualValuePK pmfmQualValuePK = new PmfmQualValuePK((QualitativeValueImpl) targetQV, (PmfmImpl) target);
330                     pmfmQualValue.setPmfmQualValuePk(pmfmQualValuePK);
331                     target.addPmfmQualValues(pmfmQualValue);
332                 }
333 
334             }
335 
336             if (!remainingPQV.isEmpty()) {
337                 target.getPmfmQualValues().removeAll(remainingPQV.values());
338             }
339 
340         } else if (target.getPmfmQualValues() != null) {
341             target.getPmfmQualValues().clear();
342         }
343 
344         getSession().save(target);
345     }
346 
347     private PmfmDTO toPmfmDTO(Iterator<Object> source, Map<Integer, String> transcribingNamesById) {
348         PmfmDTO result = ReefDbBeanFactory.newPmfmDTO();
349 
350         result.setId((Integer) source.next());
351         result.setStatus(Daos.getStatus((String) source.next()));
352 
353         // parameter by cache
354         result.setParameter(parameterDao.getParameterByCode((String) source.next()));
355 
356         // matrix by cache
357         MatrixDTO matrix = ReefDbBeans.clone(matrixDao.getMatrixById((int) source.next()));
358         // remove some redundant data
359         matrix.setFractions(null);
360         result.setMatrix(matrix);
361 
362         // fraction by cache
363         FractionDTO fraction = ReefDbBeans.clone(fractionDao.getFractionById((int) source.next()));
364         // remove some redundant data
365         fraction.setMatrixes(null);
366         result.setFraction(fraction);
367 
368         // method by cache
369         result.setMethod(methodDao.getMethodById((int) source.next()));
370 
371         // unit by cache
372         result.setUnit(unitDao.getUnitById((int) source.next()));
373 
374         result.setComment((String) source.next());
375         result.setCreationDate(Daos.convertToDate(source.next()));
376         result.setUpdateDate(Daos.convertToDate(source.next()));
377 
378         // name
379         if (transcribingNamesById != null) {
380             result.setName(transcribingNamesById.get(result.getId()));
381         }
382 
383         // QV
384         result.setQualitativeValues(qualitativeValueDao.getQualitativeValuesByPmfmId(result.getId()));
385 
386         return result;
387     }
388 
389 }