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.ImmutableList;
27  import com.google.common.collect.ImmutableListMultimap;
28  import com.google.common.collect.Lists;
29  import com.google.common.collect.Multimap;
30  import fr.ifremer.quadrige3.core.dao.referential.StatusCode;
31  import fr.ifremer.quadrige3.core.dao.referential.StatusImpl;
32  import fr.ifremer.quadrige3.core.dao.referential.pmfm.Parameter;
33  import fr.ifremer.quadrige3.core.dao.referential.pmfm.ParameterDaoImpl;
34  import fr.ifremer.quadrige3.core.dao.referential.pmfm.ParameterGroupImpl;
35  import fr.ifremer.quadrige3.core.dao.referential.pmfm.QualitativeValue;
36  import fr.ifremer.quadrige3.core.dao.technical.Assert;
37  import fr.ifremer.quadrige3.core.service.technical.CacheService;
38  import fr.ifremer.reefdb.dao.technical.Daos;
39  import fr.ifremer.reefdb.dto.ReefDbBeanFactory;
40  import fr.ifremer.reefdb.dto.ReefDbBeans;
41  import fr.ifremer.reefdb.dto.referential.pmfm.ParameterDTO;
42  import fr.ifremer.reefdb.dto.referential.pmfm.ParameterGroupDTO;
43  import fr.ifremer.reefdb.dto.referential.pmfm.QualitativeValueDTO;
44  import org.apache.commons.collections4.CollectionUtils;
45  import org.hibernate.Query;
46  import org.hibernate.SessionFactory;
47  import org.hibernate.type.IntegerType;
48  import org.hibernate.type.StringType;
49  import org.springframework.beans.factory.annotation.Autowired;
50  import org.springframework.cache.Cache;
51  import org.springframework.dao.DataRetrievalFailureException;
52  import org.springframework.stereotype.Repository;
53  
54  import javax.annotation.Resource;
55  import java.util.*;
56  import java.util.stream.Collectors;
57  
58  /**
59   * Parameter DAO
60   * Created by Ludovic on 29/07/2015.
61   */
62  @Repository("reefDbParameterDao")
63  public class ReefDbParameterDaoImpl extends ParameterDaoImpl implements ReefDbParameterDao {
64  
65      private static final Multimap<String, String> columnNamesByRulesTableNames = ImmutableListMultimap.<String, String>builder()
66              .put("RULE_PMFM", "PAR_CD").build();
67  
68      private static final Multimap<String, String> columnNamesByReferentialTableNames = ImmutableListMultimap.<String, String>builder()
69              .put("PMFM", "PAR_CD").build();
70  
71      @Resource
72      protected CacheService cacheService;
73  
74      @Resource(name = "reefDbPmfmDao")
75      protected ReefDbPmfmDao pmfmDao;
76  
77      @Resource(name = "reefDbQualitativeValueDao")
78      protected ReefDbQualitativeValueDao qualitativeValueDao;
79  
80      @Resource(name = "reefDbParameterDao")
81      protected ReefDbParameterDao loopbackDao;
82  
83      /**
84       * Constructor used by Spring
85       *
86       * @param sessionFactory a {@link org.hibernate.SessionFactory} object.
87       */
88      @Autowired
89      public ReefDbParameterDaoImpl(SessionFactory sessionFactory) {
90          super(sessionFactory);
91      }
92  
93      /** {@inheritDoc} */
94      @Override
95      public List<ParameterGroupDTO> getAllParameterGroups(List<String> statusCodes) {
96  
97          Cache cacheById = cacheService.getCache(PARAMETER_GROUP_BY_ID_CACHE);
98  
99          Iterator<Object[]> it = Daos.queryIteratorWithStatus(createQuery("allParameterGroups"), statusCodes);
100 
101         List<ParameterGroupDTO> result = Lists.newArrayList();
102         while (it.hasNext()) {
103             Object[] source = it.next();
104             ParameterGroupDTO parameter = toParameterGroupDTO(Arrays.asList(source).iterator());
105             result.add(parameter);
106             cacheById.put(parameter.getId(), parameter);
107         }
108 
109         return ImmutableList.copyOf(result);
110     }
111 
112     /** {@inheritDoc} */
113     @Override
114     public ParameterGroupDTO getParameterGroupById(int parameterGroupId) {
115         Object[] source = queryUnique("parameterGroupById", "parameterGroupId", IntegerType.INSTANCE, parameterGroupId);
116 
117         if (source == null) {
118             throw new DataRetrievalFailureException("can't load parameter group with id = " + parameterGroupId);
119         }
120 
121         return toParameterGroupDTO(Arrays.asList(source).iterator());
122     }
123 
124     /** {@inheritDoc} */
125     @Override
126     public List<ParameterDTO> getAllParameters(List<String> statusCodes) {
127 
128         Cache cacheByCode = cacheService.getCache(PARAMETER_BY_CODE_CACHE);
129 
130         Iterator<Object[]> it = Daos.queryIteratorWithStatus(createQuery("allParameters"), statusCodes);
131 
132         List<ParameterDTO> result = Lists.newArrayList();
133         while (it.hasNext()) {
134             Object[] source = it.next();
135             ParameterDTO parameter = toParameterDTO(Arrays.asList(source).iterator());
136             // without qualitative values
137             result.add(parameter);
138             cacheByCode.put(parameter.getCode(), parameter);
139         }
140 
141         return ImmutableList.copyOf(result);
142     }
143 
144     /** {@inheritDoc} */
145     @Override
146     public ParameterDTO getParameterByCode(String parameterCode) {
147         Assert.notBlank(parameterCode);
148 
149         Object[] source = queryUnique("parameterByCode", "parameterCode", StringType.INSTANCE, parameterCode);
150 
151         if (source == null) {
152             throw new DataRetrievalFailureException("can't load parameter with code = " + parameterCode);
153         }
154 
155         ParameterDTO result = toParameterDTO(Arrays.asList(source).iterator());
156         // add all associated Qualitative values
157         result.setQualitativeValues(qualitativeValueDao.getQualitativeValuesByParameterCode(result.getCode()));
158         return result;
159     }
160 
161     /** {@inheritDoc} */
162     @Override
163     public List<ParameterDTO> findParameters(String parameterCode, Integer parameterGroupId, List<String> statusCodes) {
164         Query query = createQuery("parametersByCriteria",
165                 "parameterCode", StringType.INSTANCE, parameterCode,
166                 "parameterGroupId", IntegerType.INSTANCE, parameterGroupId);
167 
168         Iterator<Object[]> it = Daos.queryIteratorWithStatus(query, statusCodes);
169 
170         // other solution: use criteria API and findByExample
171         List<ParameterDTO> result = Lists.newArrayList();
172         while (it.hasNext()) {
173             Object[] source = it.next();
174             ParameterDTO parameter = toParameterDTO(Arrays.asList(source).iterator());
175             // add all associated Qualitative values
176             parameter.setQualitativeValues(qualitativeValueDao.getQualitativeValuesByParameterCode(parameter.getCode()));
177             result.add(parameter);
178         }
179 
180         return ImmutableList.copyOf(result);
181     }
182 
183     /** {@inheritDoc} */
184     @Override
185     public void saveParameters(List<? extends ParameterDTO> parameters) {
186         if (CollectionUtils.isEmpty(parameters)) {
187             return;
188         }
189 
190         for (ParameterDTO parameter : parameters) {
191             if (parameter.isDirty()) {
192                 saveParameter(parameter);
193                 parameter.setDirty(false);
194                 parameter.setNewCode(false);
195             }
196         }
197         getSession().flush();
198         getSession().clear();
199     }
200 
201     /** {@inheritDoc} */
202     @Override
203     public void deleteParameters(List<String> parametersCodes) {
204         if (parametersCodes == null) return;
205         Set<String> idsToRemove = parametersCodes.stream().filter(Objects::nonNull).collect(Collectors.toSet());
206         for (String code : idsToRemove) {
207             remove(code);
208         }
209         getSession().flush();
210         getSession().clear();
211     }
212 
213     /** {@inheritDoc} */
214     @Override
215     public void remove(String parCd) {
216 
217         // remove qualitative values
218         Parameter parameter = get(parCd);
219         Collection<QualitativeValue> qualitativeValues = parameter.getQualitativeValues();
220         if (CollectionUtils.isNotEmpty(qualitativeValues)) {
221             qualitativeValueDao.remove(qualitativeValues);
222         }
223 
224         // remove entity
225         super.remove(parCd);
226     }
227 
228     /** {@inheritDoc} */
229     @Override
230     public void replaceTemporaryParameter(String sourceCode, String targetCode, boolean delete) {
231         Assert.notBlank(sourceCode);
232         Assert.notBlank(targetCode);
233 
234         executeMultipleUpdate(columnNamesByReferentialTableNames, sourceCode, targetCode);
235 
236         if (delete) {
237             // delete temporary
238             remove(sourceCode);
239         }
240 
241         getSession().flush();
242         getSession().clear();
243     }
244 
245     /** {@inheritDoc} */
246     @Override
247     public boolean isParameterUsedInProgram(String parameterCode) {
248 
249         return queryCount("countPmfmStrategyByParameterCode", "parameterCode", StringType.INSTANCE, parameterCode) > 0;
250     }
251 
252     /** {@inheritDoc} */
253     @Override
254     public boolean isParameterUsedInRules(String parameterCode) {
255 
256         return executeMultipleCount(columnNamesByRulesTableNames, parameterCode);
257     }
258 
259     /** {@inheritDoc} */
260     @Override
261     public boolean isParameterUsedInReferential(String parameterCode) {
262 
263         return executeMultipleCount(columnNamesByReferentialTableNames, parameterCode) || isParameterUsedInRules(parameterCode);
264     }
265 
266     private void saveParameter(ParameterDTO parameter) {
267         Assert.notNull(parameter);
268         Assert.notBlank(parameter.getCode());
269         Assert.notNull(parameter.getParameterGroup());
270 
271         if (parameter.getStatus() == null) {
272             parameter.setStatus(Daos.getStatus(StatusCode.LOCAL_ENABLE));
273         }
274         Assert.isTrue(ReefDbBeans.isLocalStatus(parameter.getStatus()), "source must have local status");
275 
276         Parameter target = get(parameter.getCode());
277         if (target == null) {
278             target = Parameter.Factory.newInstance();
279             target.setParCd(parameter.getCode());
280         } else {
281             Assert.isTrue(ReefDbBeans.isLocalStatus(target.getStatus()), "target must have local status");
282         }
283         target.setStatus(load(StatusImpl.class, parameter.getStatus().getCode()));
284         target.setParGroupId(load(ParameterGroupImpl.class, parameter.getParameterGroup().getId()));
285         target.setParNm(parameter.getName());
286         target.setParDc(parameter.getDescription());
287         target.setParIsQualitative(Daos.convertToString(parameter.isQualitative()));
288         target.setParIsTaxonomic(Daos.convertToString(parameter.isTaxonomic()));
289         target.setParIsCalculated(Daos.convertToString(parameter.isCalculated()));
290         if (target.getParCreationDt() == null) {
291             target.setParCreationDt(newCreateDate());
292         }
293         target.setUpdateDt(newUpdateTimestamp());
294 
295         getSession().save(target);
296         getSession().flush();
297 
298         // qualitative values
299         if (!parameter.isQualitativeValuesEmpty()) {
300 
301             Map<Integer, QualitativeValue> remainingQualitativeValuesById = ReefDbBeans.mapByProperty(target.getQualitativeValues(), "qualValueId");
302             for (QualitativeValueDTO qualitativeValue : parameter.getQualitativeValues()) {
303 
304                 remainingQualitativeValuesById.remove(qualitativeValue.getId());
305                 // create & add  OR  update
306                 qualitativeValueDao.saveQualitativeValue(parameter.getCode(), qualitativeValue);
307             }
308             if (!remainingQualitativeValuesById.isEmpty()) {
309                 // remove remaining values
310                 qualitativeValueDao.remove(remainingQualitativeValuesById.values());
311             }
312 
313         } else if (target.getQualitativeValues() != null) {
314             qualitativeValueDao.remove(target.getQualitativeValues());
315         }
316 
317         getSession().save(target);
318         getSession().flush();
319         getSession().clear();
320     }
321 
322     private ParameterGroupDTO toParameterGroupDTO(Iterator<Object> source) {
323         ParameterGroupDTO parameterGroup = ReefDbBeanFactory.newParameterGroupDTO();
324         parameterGroup.setId((Integer) source.next());
325         parameterGroup.setName((String) source.next());
326         parameterGroup.setDescription((String) source.next());
327         parameterGroup.setStatus(Daos.getStatus((String) source.next()));
328         Integer parentId = (Integer) source.next();
329         if (parentId != null) {
330             parameterGroup.setParentParameterGroup(loopbackDao.getParameterGroupById(parentId));
331         }
332         return parameterGroup;
333     }
334 
335     private ParameterDTO toParameterDTO(Iterator<Object> source) {
336         ParameterDTO result = ReefDbBeanFactory.newParameterDTO();
337         result.setCode((String) source.next());
338         result.setName((String) source.next());
339         result.setDescription((String) source.next());
340         result.setQualitative(Daos.safeConvertToBoolean(source.next()));
341         result.setCalculated(Daos.safeConvertToBoolean(source.next()));
342         result.setTaxonomic(Daos.safeConvertToBoolean(source.next()));
343         result.setStatus(Daos.getStatus((String) source.next()));
344         Integer groupId = (Integer) source.next();
345         if (groupId != null) {
346             result.setParameterGroup(loopbackDao.getParameterGroupById(groupId));
347         }
348         result.setComment((String) source.next());
349         result.setCreationDate(Daos.convertToDate(source.next()));
350         result.setUpdateDate(Daos.convertToDate(source.next()));
351         return result;
352     }
353 
354 }