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  import com.google.common.base.Function;
26  import com.google.common.base.Preconditions;
27  import fr.ifremer.quadrige2.core.dao.technical.Dates;
28  import fr.ifremer.quadrige2.core.exception.Quadrige2TechnicalException;
29  import fr.ifremer.quadrige2.core.dao.administration.user.DepartmentImpl;
30  import fr.ifremer.quadrige2.core.dao.referential.FrequencyImpl;
31  import fr.ifremer.quadrige2.core.dao.referential.monitoringLocation.MonitoringLocationImpl;
32  import fr.ifremer.quadrige2.core.dao.referential.taxon.ReferenceTaxonImpl;
33  import fr.ifremer.quadrige2.core.dao.referential.taxon.TaxonGroupImpl;
34  import fr.ifremer.quadrige2.core.exception.BadUpdateDtException;
35  import fr.ifremer.quadrige2.core.dao.technical.Beans;
36  import fr.ifremer.quadrige2.core.dao.technical.Daos;
37  import fr.ifremer.quadrige2.core.vo.administration.strategy.AppliedPeriodVO;
38  import fr.ifremer.quadrige2.core.vo.administration.strategy.AppliedStrategyVO;
39  import fr.ifremer.quadrige2.core.vo.administration.strategy.PmfmAppliedStrategyVO;
40  import org.apache.commons.collections4.CollectionUtils;
41  import org.apache.commons.collections4.MapUtils;
42  import org.apache.commons.lang3.ArrayUtils;
43  import org.hibernate.SessionFactory;
44  import org.nuiton.i18n.I18n;
45  import org.springframework.beans.factory.annotation.Autowired;
46  import org.springframework.context.annotation.Lazy;
47  import org.springframework.stereotype.Repository;
48  
49  import javax.annotation.Nullable;
50  import javax.annotation.Resource;
51  import java.sql.Timestamp;
52  import java.util.Collection;
53  import java.util.Map;
54  import java.util.Objects;
55  
56  /**
57   * <p>
58   * AppliedStrategyDaoImpl class.
59   * </p>
60   * 
61   * @see AppliedStrategy
62   */
63  @Repository("appliedStrategyDao")
64  @Lazy
65  public class AppliedStrategyDaoImpl
66  		extends AppliedStrategyDaoBase
67  {
68  	@Resource
69  	private AppliedPeriodDao appliedPeriodDao;
70  
71  	@Resource
72  	private PmfmAppliedStrategyDao pmfmAppliedStrategyDao;
73  
74  	/**
75  	 * Constructor used by Spring
76  	 * 
77  	 * @param sessionFactory
78  	 *            a {@link org.hibernate.SessionFactory} object.
79  	 */
80  	@Autowired
81  	public AppliedStrategyDaoImpl(SessionFactory sessionFactory) {
82  		super();
83  		setSessionFactory(sessionFactory);
84  	}
85  
86  	/** {@inheritDoc} */
87  	@Override
88  	public void remove(Collection<AppliedStrategy> entities) {
89  		Preconditions.checkNotNull(entities);
90  		Preconditions.checkArgument(entities.size() > 0);
91  
92  		for (AppliedStrategy entity : entities) {
93  			remove(entity);
94  		}
95  	}
96  
97  	/** {@inheritDoc} */
98  	@Override
99  	public void remove(Integer stratId) {
100 		AppliedStrategy entity = get(stratId);
101 		remove(entity);
102 	}
103 
104 	/** {@inheritDoc} */
105 	@Override
106 	public void remove(AppliedStrategy entity) {
107 
108 		// Remove applied periods
109 		if (CollectionUtils.isNotEmpty(entity.getAppliedPeriods())) {
110 			appliedPeriodDao.remove(entity.getAppliedPeriods());
111 			entity.getAppliedPeriods().clear();
112 		}
113 
114 		// Remove Pmfm applied strategies
115 		if (CollectionUtils.isNotEmpty(entity.getPmfmAppliedStrategies())) {
116 			pmfmAppliedStrategyDao.remove(entity.getPmfmAppliedStrategies());
117 			entity.getPmfmAppliedStrategies().clear();
118 		}
119 
120 		super.remove(entity);
121 	}
122 
123 	/** {@inheritDoc} */
124 	public void toAppliedStrategyVO(
125 			AppliedStrategy source,
126 			AppliedStrategyVO target)
127 	{
128 		super.toAppliedStrategyVO(source, target);
129 
130 		// Strategy
131 		if (source.getStrategy() == null) {
132 			target.setStratId(null);
133 		}
134 		else {
135 			target.setStratId(source.getStrategy().getStratId());
136 		}
137 
138 		// Analysis department
139 		if (source.getDepartment() == null) {
140 			target.setDepId(null);
141 		}
142 		else {
143 			target.setDepId(source.getDepartment().getDepId());
144 		}
145 
146 		// Taxon group
147 		if (source.getTaxonGroup() == null) {
148 			target.setTaxonGroupId(null);
149 		}
150 		else {
151 			target.setTaxonGroupId(source.getTaxonGroup().getTaxonGroupId());
152 		}
153 
154 		// Reference taxon
155 		if (source.getReferenceTaxon() == null) {
156 			target.setRefTaxonId(null);
157 		}
158 		else {
159 			target.setRefTaxonId(source.getReferenceTaxon().getRefTaxonId());
160 		}
161 
162 		// Monitoring location
163 		if (source.getMonitoringLocation() == null) {
164 			target.setMonLocId(null);
165 		}
166 		else {
167 			target.setMonLocId(source.getMonitoringLocation().getMonLocId());
168 		}
169 
170 		// Frequency
171 		if (source.getFrequency() == null) {
172 			target.setFreqCd(null);
173 		}
174 		else {
175 			target.setFreqCd(source.getFrequency().getFreqCd());
176 		}
177 
178 		// Applied period
179 		if (CollectionUtils.isEmpty(source.getAppliedPeriods())) {
180 			target.setAppliedPeriodVOs(null);
181 		}
182 		else {
183 			target.setAppliedPeriodVOs(appliedPeriodDao.toAppliedPeriodVOArray(source.getAppliedPeriods()));
184 		}
185 
186 		// Pmfm applied strategies
187 		if (CollectionUtils.isEmpty(source.getPmfmAppliedStrategies())) {
188 			target.setPmfmAppliedStrategyVOs(null);
189 		}
190 		else {
191 			target.setPmfmAppliedStrategyVOs(pmfmAppliedStrategyDao.toPmfmAppliedStrategyVOArray(source.getPmfmAppliedStrategies()));
192 		}
193 	}
194 
195 	/**
196 	 * Retrieves the entity object that is associated with the specified value object
197 	 * from the object store. If no such entity object exists in the object store,
198 	 * a new, blank entity is created
199 	 */
200 	private AppliedStrategy loadAppliedStrategyFromAppliedStrategyVO(AppliedStrategyVO appliedStrategyVO)
201 	{
202 		AppliedStrategy appliedStrategy = null;
203 		if (appliedStrategyVO.getAppliedStratId() != null) {
204 			appliedStrategy = this.get(appliedStrategyVO.getAppliedStratId());
205 		}
206 		if (appliedStrategy == null)
207 		{
208 			appliedStrategy = AppliedStrategy.Factory.newInstance();
209 		}
210 		return appliedStrategy;
211 	}
212 
213 	/** {@inheritDoc} */
214 	public AppliedStrategy appliedStrategyVOToEntity(AppliedStrategyVO appliedStrategyVO)
215 	{
216 		AppliedStrategy entity = this.loadAppliedStrategyFromAppliedStrategyVO(appliedStrategyVO);
217 		this.appliedStrategyVOToEntity(appliedStrategyVO, entity, true);
218 		return entity;
219 	}
220 
221 	/** {@inheritDoc} */
222 	@Override
223 	public void appliedStrategyVOToEntity(
224 			AppliedStrategyVO source,
225 			AppliedStrategy target,
226 			boolean copyIfNull)
227 	{
228 		appliedStrategyVOToEntity(source, target, copyIfNull, null, false, false);
229 
230 	}
231 
232 	/* -- Internal methods -- */
233 
234 	/** {@inheritDoc} */
235 	@Override
236 	protected AppliedStrategyVO handleSave(AppliedStrategyVO source, Map<Integer, Integer> pmfmStratIdMapping, Timestamp updateDt) throws Exception {
237 		Preconditions.checkNotNull(source);
238 		Preconditions.checkArgument(source.getStratId() != null || (source.getStrategyVO() != null && source.getStrategyVO().getStratId() != null));
239 
240 		// Load
241 		Integer stratId = source.getStratId();
242 		if (stratId == null) {
243 			stratId = source.getStrategyVO().getStratId();
244 		}
245 		Strategy parent = get(StrategyImpl.class, stratId);
246 
247 		// Load entity
248 		AppliedStrategy entity = null;
249 		boolean isNew = false;
250 		if (source.getAppliedStratId() != null) {
251 			entity = get(source.getAppliedStratId());
252 		}
253 		if (entity == null) {
254 			entity = AppliedStrategy.Factory.newInstance();
255 			parent.addAppliedStrategies(entity);
256 			entity.setStrategy(parent);
257 			isNew = true;
258 		}
259 
260 		// update update_dt
261 		Timestamp newUpdateDt = updateDt;
262 		if (newUpdateDt == null) {
263 			newUpdateDt = getDatabaseCurrentTimestamp();
264 		}
265 		source.setUpdateDt(newUpdateDt);
266 
267 		// VO -> Entity
268 		appliedStrategyVOToEntity(source, entity, true, newUpdateDt, false, false);
269 
270 		// Save entity
271 		if (isNew) {
272 			Integer appliedStratId = (Integer) getSession().save(entity);
273 			source.setAppliedStratId(appliedStratId);
274 		} else {
275 			getSession().update(entity);
276 		}
277 
278 		// Check update_dt
279 		if (!isNew) {
280 			if (entity.getUpdateDt() != null) {
281 				Timestamp serverUpdateDtNoMillisecond = Dates.resetMillisecond(entity.getUpdateDt());
282 				Timestamp sourceUpdateDtNoMillisecond = Dates.resetMillisecond(source.getUpdateDt());
283 				if (!Objects.equals(sourceUpdateDtNoMillisecond, serverUpdateDtNoMillisecond)) {
284 					throw new BadUpdateDtException(I18n.t("quadrige2.dao.appliedStrategy.badUpdateDt", source.getAppliedStratId(),
285 							serverUpdateDtNoMillisecond, sourceUpdateDtNoMillisecond));
286 				}
287 			}
288 		}
289 
290 		// Keep trace of items to remove
291 		Map<AppliedPeriodPK, AppliedPeriod> appliedPeriodsToRemove = Beans.splitByProperty(entity.getAppliedPeriods(), "appliedPeriodPk");
292 		Map<PmfmAppliedStrategyPK, PmfmAppliedStrategy> pmfmAppliedStrategiesToRemove = Beans.splitByProperty(entity.getPmfmAppliedStrategies(),
293 				"pmfmAppliedStrategyPk");
294 
295 		// Applied periods
296 		if (ArrayUtils.isNotEmpty(source.getAppliedPeriodVOs())) {
297 			for (AppliedPeriodVO appliedPeriodVO : source.getAppliedPeriodVOs()) {
298 
299 				// Make sure the link to current entity is OK
300 				appliedPeriodVO.setAppliedStratId(entity.getAppliedStratId());
301 
302 				AppliedPeriod appliedPeriodEntity = appliedPeriodDao.appliedPeriodVOToEntity(appliedPeriodVO);
303 				appliedPeriodEntity.setUpdateDt(newUpdateDt);
304 				getSession().saveOrUpdate(appliedPeriodEntity);
305 
306 				// Remove from items to remove
307 				boolean isNewAppliedPeriod = (appliedPeriodsToRemove.remove(appliedPeriodEntity.getAppliedPeriodPk()) == null);
308 
309 				// If need, add it to the applied strategy
310 				if (isNewAppliedPeriod) {
311 					entity.addAppliedPeriods(appliedPeriodEntity);
312 				}
313 			}
314 		}
315 
316 		// Pmfm applied strategies
317 		if (ArrayUtils.isNotEmpty(source.getPmfmAppliedStrategyVOs())) {
318 			for (PmfmAppliedStrategyVO pmfmAppliedStrategyVO : source.getPmfmAppliedStrategyVOs()) {
319 
320 				pmfmAppliedStrategyVO.setAppliedStratId(entity.getAppliedStratId());
321 
322 				// Remap pmfm strat id
323 				Integer newPmfmStratId = pmfmStratIdMapping.get(pmfmAppliedStrategyVO.getPmfmStratId());
324 				if (newPmfmStratId == null) {
325 					throw new Quadrige2TechnicalException(String.format(
326 							"Could not retrieve a valid PMFM_STRAT_ID for the given PMFM_APPLIED_STRATEGY.PMFM_STRAT_ID [%s]",
327 							pmfmAppliedStrategyVO.getPmfmStratId()));
328 				}
329 				pmfmAppliedStrategyVO.setPmfmStratId(newPmfmStratId);
330 
331 				PmfmAppliedStrategy pmfmAppliedStrategyEntity = pmfmAppliedStrategyDao.pmfmAppliedStrategyVOToEntity(pmfmAppliedStrategyVO);
332 				pmfmAppliedStrategyEntity.setUpdateDt(newUpdateDt);
333 
334 				getSession().saveOrUpdate(pmfmAppliedStrategyEntity);
335 
336 				// Remove from items to remove
337 				boolean isNewPmfmAppliedStrategy = (pmfmAppliedStrategiesToRemove.remove(pmfmAppliedStrategyEntity.getPmfmAppliedStrategyPk()) == null);
338 
339 				// If need, add it to the applied strategy
340 				if (isNewPmfmAppliedStrategy) {
341 					entity.addPmfmAppliedStrategies(pmfmAppliedStrategyEntity);
342 				}
343 			}
344 		}
345 
346 		// Remove unused applied periods
347 		if (MapUtils.isNotEmpty(appliedPeriodsToRemove)) {
348 			appliedPeriodDao.remove(appliedPeriodsToRemove.values());
349 			entity.getAppliedPeriods().removeAll(appliedPeriodsToRemove.values());
350 		}
351 
352 		// Remove unused pmfm applied strategy
353 		if (MapUtils.isNotEmpty(pmfmAppliedStrategiesToRemove)) {
354 			pmfmAppliedStrategyDao.remove(pmfmAppliedStrategiesToRemove.values());
355 			entity.getPmfmAppliedStrategies().removeAll(pmfmAppliedStrategiesToRemove.values());
356 		}
357 
358 		return source;
359 	}
360 
361 	/**
362 	 * <p>
363 	 * appliedStrategyVOToEntity.
364 	 * </p>
365 	 * 
366 	 * @param source
367 	 *            a {@link fr.ifremer.quadrige2.core.vo.administration.strategy.AppliedStrategyVO} object.
368 	 * @param target
369 	 *            a {@link fr.ifremer.quadrige2.core.dao.administration.strategy.AppliedStrategy} object.
370 	 * @param copyIfNull
371 	 *            a boolean.
372 	 * @param updateDt
373 	 *            a {@link java.sql.Timestamp} object.
374 	 * @param withAppliedPeriods
375 	 *            a boolean.
376 	 * @param withPmfmAppliedStrategies
377 	 *            a boolean.
378 	 */
379 	protected void appliedStrategyVOToEntity(
380 			AppliedStrategyVO source,
381 			AppliedStrategy target,
382 			boolean copyIfNull,
383 			final Timestamp updateDt,
384 			boolean withAppliedPeriods,
385 			boolean withPmfmAppliedStrategies)
386 	{
387 		super.appliedStrategyVOToEntity(source, target, copyIfNull);
388 
389 		// Strategy
390 		if (copyIfNull || source.getStratId() != null || source.getStrategyVO() != null) {
391 			if (source.getStratId() == null && source.getStrategyVO() == null) {
392 				target.setStrategy(null);
393 
394 			}
395 			else {
396 				Integer stratId = source.getStratId();
397 				if (stratId == null) {
398 					stratId = source.getStrategyVO().getStratId();
399 				}
400 				target.setStrategy(load(StrategyImpl.class, stratId));
401 			}
402 		}
403 
404 		// Analysis department
405 		if (copyIfNull || source.getDepId() != null)
406 		{
407 			if (source.getDepId() == null) {
408 				target.setDepartment(null);
409 			}
410 			else {
411 				target.setDepartment(load(DepartmentImpl.class, source.getDepId()));
412 			}
413 		}
414 
415 		// Taxon group
416 		if (copyIfNull || source.getTaxonGroupId() != null)
417 		{
418 			if (source.getTaxonGroupId() == null) {
419 				target.setTaxonGroup(null);
420 			}
421 			else {
422 				target.setTaxonGroup(load(TaxonGroupImpl.class, source.getTaxonGroupId()));
423 			}
424 		}
425 
426 		// Reference taxon
427 		if (copyIfNull || source.getRefTaxonId() != null)
428 		{
429 			if (source.getRefTaxonId() == null) {
430 				target.setReferenceTaxon(null);
431 			}
432 			else {
433 				target.setReferenceTaxon(load(ReferenceTaxonImpl.class, source.getRefTaxonId()));
434 			}
435 		}
436 
437 		// Monitoring location
438 		if (copyIfNull || source.getMonLocId() != null)
439 		{
440 			if (source.getMonLocId() == null) {
441 				target.setMonitoringLocation(null);
442 			}
443 			else {
444 				target.setMonitoringLocation(load(MonitoringLocationImpl.class, source.getMonLocId()));
445 			}
446 		}
447 
448 		// Frequency
449 		if (copyIfNull || source.getFreqCd() != null)
450 		{
451 			if (source.getFreqCd() == null) {
452 				target.setFrequency(null);
453 			}
454 			else {
455 				target.setFrequency(load(FrequencyImpl.class, source.getFreqCd()));
456 			}
457 		}
458 
459 		// Applied periods
460 		if (withAppliedPeriods) {
461 			fillAppliedPeriod(source, target, copyIfNull, updateDt);
462 		}
463 
464 		// Pmfm applied strategies
465 		if (withPmfmAppliedStrategies) {
466 			fillPmfmAppliedStrategies(source, target, copyIfNull, updateDt);
467 		}
468 	}
469 
470 	/**
471 	 * <p>
472 	 * fillAppliedPeriod.
473 	 * </p>
474 	 * 
475 	 * @param source
476 	 *            a {@link fr.ifremer.quadrige2.core.vo.administration.strategy.AppliedStrategyVO} object.
477 	 * @param target
478 	 *            a {@link fr.ifremer.quadrige2.core.dao.administration.strategy.AppliedStrategy} object.
479 	 * @param copyIfNull
480 	 *            a boolean.
481 	 * @param updateDt
482 	 *            a {@link java.sql.Timestamp} object.
483 	 */
484 	protected void fillAppliedPeriod(AppliedStrategyVO source,
485 			final AppliedStrategy target,
486 			boolean copyIfNull,
487 			final Timestamp updateDt) {
488 
489 		// Applied periods
490 		if (copyIfNull || ArrayUtils.isNotEmpty(source.getAppliedPeriodVOs())) {
491 			if (ArrayUtils.isEmpty(source.getAppliedPeriodVOs())) {
492 				target.getAppliedPeriods().clear();
493 			} else {
494 				Daos.replaceEntities(
495 						target.getAppliedPeriods(),
496 						source.getAppliedPeriodVOs(),
497 						new Function<AppliedPeriodVO, AppliedPeriod>() {
498 							@Nullable
499 							@Override
500 							public AppliedPeriod apply(AppliedPeriodVO source) {
501 								AppliedPeriod entity = appliedPeriodDao.appliedPeriodVOToEntity(source);
502 								entity.setAppliedStrategy(target);
503 								if (updateDt != null) {
504 									entity.setUpdateDt(updateDt);
505 								}
506 								return entity;
507 							}
508 						});
509 			}
510 		}
511 	}
512 
513 	/**
514 	 * <p>
515 	 * fillPmfmAppliedStrategies.
516 	 * </p>
517 	 * 
518 	 * @param source
519 	 *            a {@link fr.ifremer.quadrige2.core.vo.administration.strategy.AppliedStrategyVO} object.
520 	 * @param target
521 	 *            a {@link fr.ifremer.quadrige2.core.dao.administration.strategy.AppliedStrategy} object.
522 	 * @param copyIfNull
523 	 *            a boolean.
524 	 * @param updateDt
525 	 *            a {@link java.sql.Timestamp} object.
526 	 */
527 	protected void fillPmfmAppliedStrategies(AppliedStrategyVO source,
528 			AppliedStrategy target,
529 			boolean copyIfNull,
530 			final Timestamp updateDt) {
531 
532 		// Pmfm applied strategies
533 		if (copyIfNull || ArrayUtils.isNotEmpty(source.getPmfmAppliedStrategyVOs())) {
534 			if (ArrayUtils.isEmpty(source.getPmfmAppliedStrategyVOs())) {
535 				target.getPmfmAppliedStrategies().clear();
536 			}
537 			else {
538 				Daos.replaceEntities(
539 						target.getPmfmAppliedStrategies(),
540 						source.getPmfmAppliedStrategyVOs(),
541 						new Function<PmfmAppliedStrategyVO, PmfmAppliedStrategy>() {
542 							@Nullable
543 							@Override
544 							public PmfmAppliedStrategy apply(PmfmAppliedStrategyVO source) {
545 								return pmfmAppliedStrategyDao.pmfmAppliedStrategyVOToEntity(source);
546 							}
547 						});
548 			}
549 		}
550 	}
551 }