View Javadoc
1   package fr.ifremer.quadrige2.core.dao.administration.strategy;
2   
3   /*-
4    * #%L
5    * Quadrige2 Core :: Quadrige2 Server Core
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2017 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.base.Function;
27  import com.google.common.base.Preconditions;
28  import com.google.common.collect.Lists;
29  import com.google.common.collect.Maps;
30  import fr.ifremer.quadrige2.core.dao.administration.program.Program;
31  import fr.ifremer.quadrige2.core.dao.administration.program.ProgramImpl;
32  import fr.ifremer.quadrige2.core.dao.administration.user.Department;
33  import fr.ifremer.quadrige2.core.dao.administration.user.DepartmentImpl;
34  import fr.ifremer.quadrige2.core.dao.administration.user.Quser;
35  import fr.ifremer.quadrige2.core.dao.administration.user.QuserImpl;
36  import fr.ifremer.quadrige2.core.dao.system.synchronization.DeletedItemHistoryExtendDao;
37  import fr.ifremer.quadrige2.core.exception.BadUpdateDtException;
38  import fr.ifremer.quadrige2.core.dao.technical.Beans;
39  import fr.ifremer.quadrige2.core.dao.technical.Daos;
40  import fr.ifremer.quadrige2.core.dao.technical.Dates;
41  import fr.ifremer.quadrige2.core.vo.administration.strategy.AppliedStrategyVO;
42  import fr.ifremer.quadrige2.core.vo.administration.strategy.PmfmStrategyVO;
43  import fr.ifremer.quadrige2.core.vo.administration.strategy.StrategyVO;
44  import org.apache.commons.collections4.CollectionUtils;
45  import org.apache.commons.collections4.MapUtils;
46  import org.apache.commons.lang3.ArrayUtils;
47  import org.hibernate.SessionFactory;
48  import org.nuiton.i18n.I18n;
49  import org.springframework.beans.factory.annotation.Autowired;
50  import org.springframework.context.annotation.Lazy;
51  import org.springframework.stereotype.Repository;
52  
53  import javax.annotation.Nullable;
54  import javax.annotation.Resource;
55  import java.sql.Timestamp;
56  import java.util.Collection;
57  import java.util.List;
58  import java.util.Map;
59  import java.util.Objects;
60  
61  /**
62   * <p>
63   * StrategyDaoImpl class.
64   * </p>
65   *
66   * @see Strategy
67   */
68  @Repository("strategyDao")
69  @Lazy
70  public class StrategyDaoImpl
71          extends StrategyDaoBase {
72  
73      @Resource
74      private AppliedStrategyDao appliedStrategyDao;
75  
76      @Resource
77      private PmfmStrategyDao pmfmStrategyDao;
78  
79      @Resource(name = "deletedItemHistoryDao")
80      private DeletedItemHistoryExtendDao deletedItemHistoryDao;
81  
82      /**
83       * Constructor used by Spring
84       *
85       * @param sessionFactory a {@link org.hibernate.SessionFactory} object.
86       */
87      @Autowired
88      public StrategyDaoImpl(SessionFactory sessionFactory) {
89          super();
90          setSessionFactory(sessionFactory);
91      }
92  
93      /**
94       * {@inheritDoc}
95       */
96      @Override
97      public void remove(Collection<Strategy> entities) {
98          Preconditions.checkNotNull(entities);
99          Preconditions.checkArgument(entities.size() > 0);
100 
101         for (Strategy entity : entities) {
102             remove(entity);
103         }
104     }
105 
106     /**
107      * {@inheritDoc}
108      */
109     @Override
110     public void remove(Integer stratId) {
111         Strategy entity = get(stratId);
112         remove(entity);
113     }
114 
115     /**
116      * {@inheritDoc}
117      */
118     @Override
119     public void remove(Strategy entity) {
120 
121         // Remove applied strategies
122         if (CollectionUtils.isNotEmpty(entity.getAppliedStrategies())) {
123             appliedStrategyDao.remove(entity.getAppliedStrategies());
124             entity.getAppliedStrategies().clear();
125         }
126 
127         getSession().flush();
128 
129         // Remove PmfmStrategies
130         if (CollectionUtils.isNotEmpty(entity.getPmfmStrategies())) {
131             pmfmStrategyDao.remove(entity.getPmfmStrategies());
132             entity.getPmfmStrategies().clear();
133         }
134 
135         getSession().flush();
136 
137         // Insert into DeleteItemHistory
138         deletedItemHistoryDao.insertDeletedItem(StrategyImpl.class, entity);
139 
140         entity.getProgram().removeStrategies(entity);
141         super.remove(entity);
142     }
143 
144     /**
145      * {@inheritDoc}
146      */
147     public void toStrategyVO(
148             Strategy source,
149             StrategyVO target) {
150         // Copy basic attributes
151         super.toStrategyVO(source, target);
152 
153         // Program
154         if (source.getProgram() == null) {
155             target.setProgCd(null);
156         } else {
157             target.setProgCd(source.getProgram().getProgCd());
158         }
159 
160 		// resp deps
161 		if (CollectionUtils.isEmpty(source.getDepartments())) {
162 			target.setRespDepIds(null);
163 		}
164 		else {
165 			List<Integer> depIds = Beans.collectProperties(source.getDepartments(), "depId");
166 			target.setRespDepIds(depIds.toArray(new Integer[depIds.size()]));
167 		}
168 
169 		// Resp qusers
170 		if (CollectionUtils.isEmpty(source.getQusers())) {
171 			target.setRespQuserIds(null);
172 		}
173 		else {
174 			List<Integer> quserIds = Beans.collectProperties(source.getQusers(), "quserId");
175 			target.setRespQuserIds(quserIds.toArray(new Integer[quserIds.size()]));
176 		}
177 
178         // Applied strategies
179         if (CollectionUtils.isEmpty(source.getAppliedStrategies())) {
180             target.setAppliedStrategyVOs(null);
181         } else {
182             target.setAppliedStrategyVOs(appliedStrategyDao.toAppliedStrategyVOArray(source.getAppliedStrategies()));
183         }
184 
185         // Pmfm strategies
186         if (CollectionUtils.isEmpty(source.getPmfmStrategies())) {
187             target.setPmfmStrategyVOs(null);
188         } else {
189             target.setPmfmStrategyVOs(pmfmStrategyDao.toPmfmStrategyVOArray(source.getPmfmStrategies()));
190         }
191 
192     }
193 
194     /**
195      * Retrieves the entity object that is associated with the specified value object
196      * from the object store. If no such entity object exists in the object store,
197      * a new, blank entity is created
198      */
199     private Strategy loadStrategyFromStrategyVO(StrategyVO strategyVO) {
200         Strategy strategy = null;
201         if (strategyVO.getStratId() != null) {
202             strategy = this.get(strategyVO.getStratId());
203         }
204         if (strategy == null) {
205             strategy = Strategy.Factory.newInstance();
206         }
207         return strategy;
208     }
209 
210     /**
211      * {@inheritDoc}
212      */
213     public Strategy strategyVOToEntity(StrategyVO strategyVO) {
214         Strategy entity = this.loadStrategyFromStrategyVO(strategyVO);
215         this.strategyVOToEntity(strategyVO, entity, true);
216         return entity;
217     }
218 
219     /**
220      * {@inheritDoc}
221      */
222     public void strategyVOToEntity(
223             StrategyVO source,
224             Strategy target,
225             boolean copyIfNull) {
226         super.strategyVOToEntity(source, target, copyIfNull);
227 
228         // Program
229         if (copyIfNull || source.getProgCd() != null) {
230             if (source.getProgCd() == null) {
231                 target.setProgram(null);
232             } else {
233                 target.setProgram(load(ProgramImpl.class, source.getProgCd()));
234             }
235         }
236 
237 		// Resp departments
238 		if (copyIfNull || ArrayUtils.isNotEmpty(source.getRespDepIds())) {
239 			if (ArrayUtils.isEmpty(source.getRespDepIds())) {
240 				target.getDepartments().clear();
241 			}
242 			else {
243 				Daos.replaceEntities(
244 						target.getDepartments(),
245 						source.getRespDepIds(),
246 						depId -> load(DepartmentImpl.class, depId));
247 			}
248 		}
249 
250 		// Resp qusers
251 		if (copyIfNull || ArrayUtils.isNotEmpty(source.getRespQuserIds())) {
252 			if (ArrayUtils.isEmpty(source.getRespQuserIds())) {
253 				target.getQusers().clear();
254 			}
255 			else {
256 				Daos.replaceEntities(
257 						target.getQusers(),
258 						source.getRespQuserIds(),
259 						quserId -> load(QuserImpl.class, quserId));
260 			}
261 		}
262 	}
263 
264 	/* -- Internal method -- */
265 
266     /**
267      * {@inheritDoc}
268      */
269     @Override
270     protected StrategyVO handleSave(StrategyVO source, Timestamp updateDt) throws Exception {
271         Preconditions.checkNotNull(source);
272         Preconditions.checkNotNull(source.getProgCd());
273 
274         // Load parent
275         Program parent = get(ProgramImpl.class, source.getProgCd());
276 
277         // Load entity
278         Strategy entity = null;
279         boolean isNew = false;
280         if (source.getStratId() != null) {
281             entity = get(source.getStratId());
282         }
283         if (entity == null) {
284             entity = Strategy.Factory.newInstance();
285             parent.addStrategies(entity);
286             entity.setProgram(parent);
287             isNew = true;
288         }
289 
290         // Check update_dt
291         if (!isNew) {
292             if (entity.getUpdateDt() != null) {
293                 Timestamp serverUpdateDtNoMillisecond = Dates.resetMillisecond(entity.getUpdateDt());
294                 Timestamp sourceUpdateDtNoMillisecond = Dates.resetMillisecond(source.getUpdateDt());
295                 if (!Objects.equals(sourceUpdateDtNoMillisecond, serverUpdateDtNoMillisecond)) {
296                     throw new BadUpdateDtException(I18n.t("quadrige2.dao.strategy.badUpdateDt", source.getStratId(), serverUpdateDtNoMillisecond,
297                             sourceUpdateDtNoMillisecond));
298                 }
299             }
300         }
301 
302         // update update_dt
303         Timestamp newUpdateDt = updateDt;
304         if (newUpdateDt == null) {
305             newUpdateDt = getDatabaseCurrentTimestamp();
306         }
307         source.setUpdateDt(newUpdateDt);
308 
309         // VO -> Entity
310         strategyVOToEntity(source, entity, true);
311 
312         // Save entity
313         if (isNew) {
314             Integer stratId = (Integer) getSession().save(entity);
315             source.setStratId(stratId);
316         } else {
317             getSession().update(entity);
318         }
319 
320         // Keep trace of items to remove
321         Map<Integer, PmfmStrategy> pmfmStrategiesToRemove = Beans.splitByProperty(entity.getPmfmStrategies(), "pmfmStratId");
322         Map<Integer, AppliedStrategy> appliedStrategiesToRemove = Beans.splitByProperty(entity.getAppliedStrategies(), "appliedStratId");
323 
324         // Save pmfm strategies
325         Map<Integer, Integer> pmfmStratIdMapping = Maps.newHashMap();
326         if (ArrayUtils.isNotEmpty(source.getPmfmStrategyVOs())) {
327             for (PmfmStrategyVO pmfmStrategy : source.getPmfmStrategyVOs()) {
328                 // Remember old applied strategy
329                 Integer oldPmfmStratId = pmfmStrategy.getPmfmStratId();
330 
331                 // Update stratId (could have change)
332                 pmfmStrategy.setStratId(entity.getStratId());
333 
334                 PmfmStrategyVO savedPmfmStrategy = pmfmStrategyDao.save(pmfmStrategy, newUpdateDt);
335 
336                 if (oldPmfmStratId != null) {
337                     pmfmStratIdMapping.put(oldPmfmStratId, savedPmfmStrategy.getPmfmStratId());
338                 }
339 
340                 // Remove from items to remove
341                 pmfmStrategiesToRemove.remove(savedPmfmStrategy.getPmfmStratId());
342             }
343         }
344 
345         // Save applied strategies
346         if (ArrayUtils.isNotEmpty(source.getAppliedStrategyVOs())) {
347             for (AppliedStrategyVO appliedStrategy : source.getAppliedStrategyVOs()) {
348 
349                 // Update stratId (could have change)
350                 appliedStrategy.setStratId(entity.getStratId());
351 
352                 AppliedStrategyVO savedAppliedStrategyVO = appliedStrategyDao.save(appliedStrategy, pmfmStratIdMapping, newUpdateDt);
353 
354                 // Remove from items to remove
355                 appliedStrategiesToRemove.remove(savedAppliedStrategyVO.getAppliedStratId());
356             }
357         }
358 
359         // Remove unused pmfm strategies
360         if (MapUtils.isNotEmpty(pmfmStrategiesToRemove)) {
361             pmfmStrategyDao.remove(pmfmStrategiesToRemove.values());
362             entity.getPmfmStrategies().removeAll(pmfmStrategiesToRemove.values());
363         }
364 
365         // Remove unused applied strategies
366         if (MapUtils.isNotEmpty(appliedStrategiesToRemove)) {
367             appliedStrategyDao.remove(appliedStrategiesToRemove.values());
368             entity.getAppliedStrategies().removeAll(appliedStrategiesToRemove.values());
369         }
370 
371         return source;
372     }
373 
374     /**
375      * {@inheritDoc}
376      */
377     @Override
378     protected void handleRemoveByIds(Collection<Integer> stratIds) {
379         for (Integer stratId : stratIds) {
380             remove(stratId);
381         }
382     }
383 }