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.Fraction;
33  import fr.ifremer.quadrige3.core.dao.referential.pmfm.FractionDaoImpl;
34  import fr.ifremer.quadrige3.core.dao.referential.pmfm.Matrix;
35  import fr.ifremer.quadrige3.core.dao.referential.pmfm.MatrixImpl;
36  import fr.ifremer.quadrige3.core.dao.technical.Assert;
37  import fr.ifremer.quadrige3.core.dao.technical.hibernate.TemporaryDataHelper;
38  import fr.ifremer.quadrige3.core.service.technical.CacheService;
39  import fr.ifremer.reefdb.dao.technical.Daos;
40  import fr.ifremer.reefdb.dto.ReefDbBeanFactory;
41  import fr.ifremer.reefdb.dto.ReefDbBeans;
42  import fr.ifremer.reefdb.dto.referential.pmfm.FractionDTO;
43  import fr.ifremer.reefdb.dto.referential.pmfm.MatrixDTO;
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.springframework.beans.factory.annotation.Autowired;
49  import org.springframework.dao.DataRetrievalFailureException;
50  import org.springframework.stereotype.Repository;
51  
52  import javax.annotation.Resource;
53  import java.util.*;
54  
55  /**
56   * Fraction DAO
57   * Created by Ludovic on 29/07/2015.
58   */
59  @Repository("reefDbFractionDao")
60  public class ReefDbFractionDaoImpl extends FractionDaoImpl implements ReefDbFractionDao {
61  
62      private static final Multimap<String, String> columnNamesByRulesTableNames = ImmutableListMultimap.<String, String>builder()
63              .put("RULE_PMFM", "FRACTION_ID").build();
64  
65      private static final Multimap<String, String> columnNamesByReferentialTableNames = ImmutableListMultimap.<String, String>builder()
66              .put("FRACTION_MATRIX", "FRACTION_ID")
67              .put("PMFM", "FRACTION_ID").build();
68  
69      @Resource
70      protected CacheService cacheService;
71  
72      @Resource(name = "reefDbMatrixDao")
73      protected ReefDbMatrixDao matrixDao;
74  
75      /**
76       * Constructor used by Spring
77       *
78       * @param sessionFactory a {@link org.hibernate.SessionFactory} object.
79       */
80      @Autowired
81      public ReefDbFractionDaoImpl(SessionFactory sessionFactory) {
82          super(sessionFactory);
83      }
84  
85      /** {@inheritDoc} */
86      @Override
87      public List<FractionDTO> getAllFractions(List<String> statusCodes) {
88  
89          Iterator<Object[]> it = Daos.queryIteratorWithStatus(createQuery("allFractions"), statusCodes);
90  
91          List<FractionDTO> result = Lists.newArrayList();
92          FractionDTO fraction = null;
93          while (it.hasNext()) {
94              Object[] row = it.next();
95              Iterator<Object> rowIt = Arrays.asList(row).iterator();
96  
97              if (fraction == null || !fraction.getId().equals(row[0])) {
98                  fraction = toFractionDTO(rowIt);
99                  result.add(fraction);
100             } else {
101                 // dummy iteration
102                 toFractionDTO(rowIt);
103             }
104 
105             // the last element is the associated matrix
106             Integer matrixId = (Integer) rowIt.next();
107             if (matrixId != null) {
108                 MatrixDTO matrix = matrixDao.getMatrixById(matrixId);
109                 fraction.addMatrixes(matrix);
110                 matrix.addFractions(fraction);
111             }
112         }
113 
114         return ImmutableList.copyOf(result);
115     }
116 
117     /** {@inheritDoc} */
118     @Override
119     public FractionDTO getFractionById(int fractionId) {
120 
121         Iterator<Object[]> it = queryIterator("fractionById", "fractionId", IntegerType.INSTANCE, fractionId);
122 
123         if (!it.hasNext()) {
124             throw new DataRetrievalFailureException("can't load fraction with id = " + fractionId);
125         }
126 
127         FractionDTO fraction = null;
128         while (it.hasNext()) {
129             Object[] row = it.next();
130             Iterator<Object> rowIt = Arrays.asList(row).iterator();
131             if (fraction == null) {
132                 fraction = toFractionDTO(rowIt);
133             } else {
134                 toFractionDTO(rowIt);
135             }
136             // the last element is the associated matrix
137             Integer matrixId = (Integer) rowIt.next();
138             if (matrixId != null) {
139                 MatrixDTO matrix = matrixDao.getMatrixById(matrixId);
140                 fraction.addMatrixes(matrix);
141                 matrix.addFractions(fraction);
142             }
143         }
144         return fraction;
145     }
146 
147     /** {@inheritDoc} */
148     @Override
149     public List<FractionDTO> getFractionsByMatrixId(Integer matrixId) {
150         Iterator<Object[]> it = queryIterator("fractionsByMatrixId", "matrixId", IntegerType.INSTANCE, matrixId);
151 
152         List<FractionDTO> result = Lists.newArrayList();
153         while (it.hasNext()) {
154             Object[] row = it.next();
155             result.add(toFractionDTO(Arrays.asList(row).iterator()));
156         }
157 
158         return ImmutableList.copyOf(result);
159 
160     }
161 
162     /** {@inheritDoc} */
163     @Override
164     public List<FractionDTO> findFractions(Integer fractionId, List<String> statusCodes) {
165 
166         Query query = createQuery("fractionByCriteria", "fractionId", IntegerType.INSTANCE, fractionId);
167         Iterator<Object[]> it = Daos.queryIteratorWithStatus(query, statusCodes);
168 
169         List<FractionDTO> result = Lists.newArrayList();
170         FractionDTO fraction = null;
171         while (it.hasNext()) {
172             Object[] row = it.next();
173             Iterator<Object> rowIt = Arrays.asList(row).iterator();
174 
175             if (fraction == null || !fraction.getId().equals(row[0])) {
176                 fraction = toFractionDTO(rowIt);
177                 result.add(fraction);
178             } else {
179                 // dummy iteration
180                 toFractionDTO(rowIt);
181             }
182 
183             // the last element is the associated matrix
184             Integer matrixId = (Integer) rowIt.next();
185             if (matrixId != null) {
186                 MatrixDTO matrix = matrixDao.getMatrixById(matrixId);
187                 fraction.addMatrixes(matrix);
188                 matrix.addFractions(fraction);
189             }
190         }
191 
192         return ImmutableList.copyOf(result);
193 
194     }
195 
196     /** {@inheritDoc} */
197     @Override
198     public void saveFractions(List<? extends FractionDTO> fractions) {
199         if (CollectionUtils.isEmpty(fractions)) {
200             return;
201         }
202 
203         for (FractionDTO fraction : fractions) {
204             if (fraction.isDirty()) {
205                 saveFraction(fraction);
206                 fraction.setDirty(false);
207             }
208         }
209         getSession().flush();
210         getSession().clear();
211     }
212 
213     /** {@inheritDoc} */
214     @Override
215     public void deleteFractions(List<Integer> fractionIds) {
216         if (fractionIds == null) return;
217         fractionIds.stream().filter(Objects::nonNull).distinct().forEach(this::remove);
218         getSession().flush();
219         getSession().clear();
220     }
221 
222     /** {@inheritDoc} */
223     @Override
224     public void replaceTemporaryFraction(Integer sourceId, Integer targetId, boolean delete) {
225         Assert.notNull(sourceId);
226         Assert.notNull(targetId);
227 
228         executeMultipleUpdate(columnNamesByReferentialTableNames, sourceId, targetId);
229 
230         if (delete) {
231             // delete temporary
232             remove(sourceId);
233         }
234 
235         getSession().flush();
236         getSession().clear();
237     }
238 
239     /** {@inheritDoc} */
240     @Override
241     public boolean isFractionUsedInProgram(int fractionId) {
242 
243         return queryCount("countPmfmStrategyByFractionId", "fractionId", IntegerType.INSTANCE, fractionId) > 0;
244     }
245 
246     /** {@inheritDoc} */
247     @Override
248     public boolean isFractionUsedInRules(int fractionId) {
249 
250         return executeMultipleCount(columnNamesByRulesTableNames, fractionId);
251     }
252 
253     /** {@inheritDoc} */
254     @Override
255     public boolean isFractionUsedInReferential(int fractionId) {
256 
257         return executeMultipleCount(columnNamesByReferentialTableNames, fractionId) || isFractionUsedInRules(fractionId);
258     }
259 
260     private void saveFraction(FractionDTO fraction) {
261         Assert.notNull(fraction);
262         Assert.notBlank(fraction.getName());
263 
264         if (fraction.getStatus() == null) {
265             fraction.setStatus(Daos.getStatus(StatusCode.LOCAL_ENABLE));
266         }
267         Assert.isTrue(ReefDbBeans.isLocalStatus(fraction.getStatus()), "source must have local status");
268 
269         Fraction target;
270         if (fraction.getId() == null) {
271             target = Fraction.Factory.newInstance();
272             target.setFractionId(TemporaryDataHelper.getNewNegativeIdForTemporaryData(getSession(), target.getClass()));
273         } else {
274             target = get(fraction.getId());
275             Assert.isTrue(ReefDbBeans.isLocalStatus(target.getStatus()), "target must have local status");
276         }
277 
278         target.setFractionNm(fraction.getName());
279         target.setFractionDc(fraction.getDescription());
280         target.setStatus(load(StatusImpl.class, fraction.getStatus().getCode()));
281         if (target.getFractionCreationDt() == null) {
282             target.setFractionCreationDt(newCreateDate());
283         }
284         target.setUpdateDt(newUpdateTimestamp());
285 
286         getSession().save(target);
287         fraction.setId(target.getFractionId());
288 
289         // save associated matrices
290         if (fraction.sizeMatrixes() > 0) {
291 
292             Map<Integer, Matrix> remainingMatrices = ReefDbBeans.mapByProperty(target.getMatrixes(), "matrixId");
293             for (MatrixDTO matrix : fraction.getMatrixes()) {
294                 if (remainingMatrices.remove(matrix.getId()) == null) {
295                     // add matrix
296                     target.addMatrixes(load(MatrixImpl.class, matrix.getId()));
297                 }
298             }
299 
300             if (!remainingMatrices.isEmpty()) {
301                 target.getMatrixes().removeAll(remainingMatrices.values());
302             }
303 
304         } else if (target.getMatrixes() != null) {
305             target.getMatrixes().clear();
306         }
307 
308         getSession().save(target);
309     }
310 
311     private FractionDTO toFractionDTO(Iterator<Object> source) {
312         FractionDTO result = ReefDbBeanFactory.newFractionDTO();
313         result.setId((Integer) source.next());
314         result.setName((String) source.next());
315         result.setDescription((String) source.next());
316         result.setStatus(Daos.getStatus((String) source.next()));
317         result.setComment((String) source.next());
318         result.setCreationDate(Daos.convertToDate(source.next()));
319         result.setUpdateDate(Daos.convertToDate(source.next()));
320         return result;
321     }
322 
323 }