View Javadoc
1   package fr.ifremer.quadrige3.core.dao.administration.program;
2   
3   /*-
4    * #%L
5    * Quadrige3 Core :: Quadrige3 Client 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.collect.ImmutableList;
26  import fr.ifremer.quadrige3.core.dao.administration.metaprogamme.Metaprogramme;
27  import fr.ifremer.quadrige3.core.dao.administration.metaprogamme.MetaprogrammeDao;
28  import fr.ifremer.quadrige3.core.dao.administration.strategy.Strategy;
29  import fr.ifremer.quadrige3.core.dao.administration.strategy.StrategyDao;
30  import fr.ifremer.quadrige3.core.dao.data.survey.Campaign;
31  import fr.ifremer.quadrige3.core.dao.referential.StatusImpl;
32  import fr.ifremer.quadrige3.core.dao.system.rule.RuleList;
33  import fr.ifremer.quadrige3.core.dao.system.rule.RuleListDao;
34  import fr.ifremer.quadrige3.core.dao.technical.Assert;
35  import fr.ifremer.quadrige3.core.dao.technical.Beans;
36  import fr.ifremer.quadrige3.core.dao.technical.Daos;
37  import fr.ifremer.quadrige3.core.vo.administration.program.MonLocProgVO;
38  import fr.ifremer.quadrige3.core.vo.administration.program.ProgramVO;
39  import fr.ifremer.quadrige3.core.vo.administration.strategy.StrategyVO;
40  import org.apache.commons.collections4.CollectionUtils;
41  import org.apache.commons.lang3.ArrayUtils;
42  import org.apache.commons.logging.Log;
43  import org.apache.commons.logging.LogFactory;
44  import org.hibernate.SQLQuery;
45  import org.hibernate.SessionFactory;
46  import org.hibernate.type.StringType;
47  import org.springframework.beans.factory.annotation.Autowired;
48  import org.springframework.context.annotation.Lazy;
49  import org.springframework.stereotype.Repository;
50  
51  import javax.annotation.Resource;
52  import java.sql.Timestamp;
53  import java.util.Collection;
54  import java.util.Iterator;
55  import java.util.List;
56  
57  /**
58   * <p>
59   * ProgramDaoImpl class.
60   * </p>
61   * 
62   * @see Program
63   */
64  @Repository("programDao")
65  @Lazy
66  public class ProgramDaoImpl
67  		extends ProgramDaoBase
68  {
69  	/** Logger. */
70  	private static final Log log =
71  			LogFactory.getLog(ProgramDaoImpl.class);
72  
73  	@Resource
74  	private ProgDepProgPrivDao progDepProgPrivDao;
75  
76  	@Resource
77  	private ProgQuserProgPrivDao progQuserProgPrivDao;
78  
79  	@Resource
80  	private MonLocProgDao monLocProgDao;
81  
82  	@Resource(name = "strategyDao")
83  	private StrategyDao strategyDao;
84  
85  	@Resource
86  	private MoratoriumDao moratoriumDao;
87  
88  	@Resource
89  	private MetaprogrammeDao metaprogrammeDao;
90  
91  	@Resource
92  	private RuleListDao ruleListDao;
93  
94  	/**
95  	 * Constructor used by Spring
96  	 * 
97  	 * @param sessionFactory
98  	 *            a {@link org.hibernate.SessionFactory} object.
99  	 */
100 	@Autowired
101 	public ProgramDaoImpl(SessionFactory sessionFactory) {
102 		super();
103 		setSessionFactory(sessionFactory);
104 	}
105 
106 	/** {@inheritDoc} */
107 	@Override
108 	public void remove(Collection<Program> entities) {
109 		Assert.notEmpty(entities);
110 
111 		for (Program entity : entities) {
112 			remove(entity);
113 		}
114 	}
115 
116 	/** {@inheritDoc} */
117 	@Override
118 	public void remove(String progCd) {
119 		Program entity = get(progCd);
120 		if (entity != null) {
121 			remove(entity);
122 		}
123 	}
124 
125 	/** {@inheritDoc} */
126 	@Override
127 	public void remove(Program entity) {
128 		Assert.notNull(entity);
129 		Assert.notNull(entity.getProgCd());
130 
131 		// Remove linked moratoriums
132 		Iterator<Moratorium> moratoriums = queryIteratorTyped("moratoriumsByProgCd", "progCd", StringType.INSTANCE, entity.getProgCd());
133 		while (moratoriums.hasNext()) {
134 			Moratorium moratorium = moratoriums.next();
135 			moratoriumDao.remove(moratorium);
136 		}
137 
138 		// Remove linked metaprograms
139 		Iterator<Metaprogramme> metaprograms = queryIteratorTyped("metaprogramsByProgCd", "progCd", StringType.INSTANCE, entity.getProgCd());
140 		while (metaprograms.hasNext()) {
141 			Metaprogramme metaprogram = metaprograms.next();
142 			metaprogrammeDao.remove(metaprogram);
143 		}
144 
145 		// Remove linked campaigns
146 		// Mantis #37953: all campaigns must be imported, delete only CAMPAIGN_PROG
147 		Iterator<Campaign> campaigns = queryIteratorTyped("campaignsByProgCd", "progCd", StringType.INSTANCE, entity.getProgCd());
148 		while (campaigns.hasNext()) {
149 			Campaign campaign = campaigns.next();
150 			campaign.getPrograms().remove(entity);
151 			getSession().update(campaign);
152 //			campaignDao.remove(campaign);
153 		}
154 
155 		// Remove linked rule lists
156 		Iterator<RuleList> ruleLists = queryIteratorTyped("ruleListsByProgCd", "progCd", StringType.INSTANCE, entity.getProgCd());
157 		while (ruleLists.hasNext()) {
158 			RuleList ruleList = ruleLists.next();
159 			ruleList.getPrograms().remove(entity);
160 			// remove rule list if no more program, or just remove the link
161 			if (ruleList.getPrograms().isEmpty()) {
162 				ruleListDao.remove(ruleList);
163 			} else {
164 				getSession().update(ruleList);
165 			}
166 		}
167 
168 		// Remove links with survey
169 		SQLQuery query = createSQLQuery("removeSurveyProg", "progCd", StringType.INSTANCE, entity.getProgCd());
170 		int nbSurveyProgDeleted = query.executeUpdate();
171 		if (nbSurveyProgDeleted > 0) {
172 			// Should never occur
173 			log.warn(String.format("Deleting %s links to survey, while removing program '%s'. This should never occur.", nbSurveyProgDeleted,
174 					entity.getProgCd()));
175 		}
176 
177 		// Remove strategies
178 		if (CollectionUtils.isNotEmpty(entity.getStrategies())) {
179 			strategyDao.remove(ImmutableList.copyOf(entity.getStrategies()));
180 			entity.getStrategies().clear();
181 		}
182 
183 		// Remove privileges
184 		if (CollectionUtils.isNotEmpty(entity.getProgQuserProgPrivs())) {
185 			entity.getProgQuserProgPrivs().clear();
186 		}
187 		if (CollectionUtils.isNotEmpty(entity.getProgDepProgPrivs())) {
188 			entity.getProgDepProgPrivs().clear();
189 		}
190 
191 		super.remove(entity);
192 	}
193 
194 	/** {@inheritDoc} */
195 	public void toProgramVO(
196 			Program source,
197 			ProgramVO target)
198 	{
199 		// copy base attributes
200 		super.toProgramVO(source, target);
201 
202 		// Status
203 		if (source.getStatus() == null) {
204 			target.setStatusCd(null);
205 		}
206 		else {
207 			target.setStatusCd(source.getStatus().getStatusCd());
208 		}
209 
210 		// privileges on department
211 		if (CollectionUtils.isEmpty(source.getProgDepProgPrivs())) {
212 			target.setProgDepProgPrivVOs(null);
213 		}
214 		else {
215 			target.setProgDepProgPrivVOs(progDepProgPrivDao.toProgDepProgPrivVOArray(source.getProgDepProgPrivs()));
216 		}
217 
218 		// privileges on user
219 		if (CollectionUtils.isEmpty(source.getProgQuserProgPrivs())) {
220 			target.setProgQuserProgPrivVOs(null);
221 		}
222 		else {
223 			target.setProgQuserProgPrivVOs(progQuserProgPrivDao.toProgQuserProgPrivVOArray(source.getProgQuserProgPrivs()));
224 		}
225 
226 		// Monitoring location
227 		if (CollectionUtils.isEmpty(source.getMonLocProgs())) {
228 			target.setMonLocProgVOs(null);
229 		}
230 		else {
231 			target.setMonLocProgVOs(monLocProgDao.toMonLocProgVOArray(source.getMonLocProgs()));
232 		}
233 
234 		// Strategies
235 		if (CollectionUtils.isEmpty(source.getStrategies())) {
236 			target.setStrategyVOs(null);
237 		}
238 		else {
239 			target.setStrategyVOs(strategyDao.toStrategyVOArray(source.getStrategies()));
240 		}
241 	}
242 
243 	/**
244 	 * Retrieves the entity object that is associated with the specified value object
245 	 * from the object store. If no such entity object exists in the object store,
246 	 * a new, blank entity is created
247 	 */
248 	private Program loadProgramFromProgramVO(ProgramVO programVO)
249 	{
250 		Program program = null;
251 		if (programVO.getProgCd() != null) {
252 			program = this.get(programVO.getProgCd());
253 		}
254 		if (program == null)
255 		{
256 			program = Program.Factory.newInstance();
257 		}
258 		return program;
259 	}
260 
261 	/** {@inheritDoc} */
262 	public Program programVOToEntity(ProgramVO programVO)
263 	{
264 		Program entity = this.loadProgramFromProgramVO(programVO);
265 		this.programVOToEntity(programVO, entity, true);
266 		return entity;
267 	}
268 
269 	/** {@inheritDoc} */
270 	@Override
271 	public void programVOToEntity(
272 			final ProgramVO source,
273 			final Program target,
274 			boolean copyIfNull)
275 	{
276 		programVOToEntity(source, target, copyIfNull, null, false);
277 	}
278 
279 	/**
280 	 * {@inheritDoc}
281 	 * 
282 	 * -- Internal methods --
283 	 */
284 	@Override
285 	protected ProgramVO handleSave(ProgramVO source) {
286 		Assert.notNull(source.getProgCd());
287 
288 		// Load (or create) the entity
289 		Program entity = get(source.getProgCd());
290 		boolean isNew = false;
291 		if (entity == null) {
292 			entity = Program.Factory.newInstance();
293 			isNew = true;
294 		}
295 
296 		// Check update_dt :
297 		// NOT NEED on a client database
298 
299 		// Update update_dt
300 		// NOT NEED on a client database
301 
302 		// VO -> Entity
303 		programVOToEntity(source,
304 				entity,
305 				true /* copyIfNull */,
306 				null /* do not change given update_dt */,
307 				false/* do not convert strategies (will be done later in method) */
308 		);
309 
310 		// Save entity
311 		if (isNew) {
312 			getSession().save(entity);
313 		} else {
314 			getSession().update(entity);
315 		}
316 
317 		List<Integer> monLocProgIdsToRemove = Beans.collectProperties(entity.getMonLocProgs(), "monLocProgId");
318 		List<Integer> strategiesIdsToRemove = Beans.collectProperties(entity.getStrategies(), "stratId");
319 
320 		// Monitoring location
321 		if (ArrayUtils.isNotEmpty(source.getMonLocProgVOs())){
322 			for (MonLocProgVO vo : source.getMonLocProgVOs()) {
323 				vo.setProgCd(entity.getProgCd());
324 				MonLocProg monLocProg = monLocProgDao.monLocProgVOToEntity(vo);
325 				monLocProg.setProgram(entity);
326 				if (monLocProg.getMonLocProgId() == null) {
327 					monLocProg.setMonLocProgId(vo.getMonLocProgId());
328 					getSession().save(monLocProg);
329 				}
330 				else {
331 					getSession().update(monLocProg);
332 				}
333 				monLocProgIdsToRemove.remove(vo.getMonLocProgId());
334 			}
335 		}
336 
337 		// Save strategies
338 		if (ArrayUtils.isNotEmpty(source.getStrategyVOs())) {
339 			for (StrategyVO strategyVO : source.getStrategyVOs()) {
340 				strategyVO.setProgCd(entity.getProgCd());
341 				strategyVO = strategyDao.save(strategyVO, null);
342 
343 				strategiesIdsToRemove.remove(strategyVO.getStratId());
344 			}
345 		}
346 
347 		getSession().flush();
348 		getSession().clear();
349 
350 		// remove unused mon log progs
351 		if (CollectionUtils.isNotEmpty(monLocProgIdsToRemove)) {
352 			monLocProgIdsToRemove.forEach(monLocProgDao::remove);
353 		}
354 		// remove unused strategies
355 		if (CollectionUtils.isNotEmpty(strategiesIdsToRemove)) {
356 			strategiesIdsToRemove.forEach(strategyDao::remove);
357 		}
358 
359 		return source;
360 	}
361 
362 	@Override
363 	protected void handleUpdateDate(String programCode) {
364 		// nothing
365 	}
366 
367 	/**
368 	 * <p>
369 	 * programVOToEntity.
370 	 * </p>
371 	 * 
372 	 * @param source
373 	 *            a {@link fr.ifremer.quadrige3.core.vo.administration.program.ProgramVO} object.
374 	 * @param target
375 	 *            a {@link fr.ifremer.quadrige3.core.dao.administration.program.Program} object.
376 	 * @param copyIfNull
377 	 *            a boolean.
378 	 * @param updateDt
379 	 *            a {@link java.sql.Timestamp} object.
380 	 * @param withChildren
381 	 *            a boolean.
382 	 */
383 	protected void programVOToEntity(
384 			ProgramVO source,
385 			Program target,
386 			boolean copyIfNull,
387 			final Timestamp updateDt,
388 			boolean withChildren)
389 	{
390 		// Copy simple attributes
391 		super.programVOToEntity(source, target, copyIfNull);
392 
393 		// Code
394 		if (copyIfNull || source.getProgCd() != null)
395 		{
396 			target.setProgCd(source.getProgCd());
397 		}
398 
399 		// Status
400 		if (copyIfNull || source.getStatusCd() != null)
401 		{
402 			if (source.getStatusCd() == null) {
403 				target.setStatus(null);
404 			}
405 			else {
406 				target.setStatus(load(StatusImpl.class, source.getStatusCd()));
407 			}
408 		}
409 
410 		// Privilege on department
411 		if (copyIfNull || ArrayUtils.isNotEmpty(source.getProgDepProgPrivVOs()))
412 		{
413 			if (ArrayUtils.isEmpty(source.getProgDepProgPrivVOs())) {
414 				target.getProgDepProgPrivs().clear();
415 			}
416 			else {
417 				Daos.replaceEntities(target.getProgDepProgPrivs(),
418 						source.getProgDepProgPrivVOs(),
419 						vo -> {
420 							ProgDepProgPriv entity = progDepProgPrivDao.progDepProgPrivVOToEntity(vo);
421 							if (updateDt != null) {
422 								entity.setUpdateDt(updateDt);
423 							}
424 							return entity;
425 						});
426 			}
427 		}
428 
429 		// Privilege on user
430 		if (copyIfNull || ArrayUtils.isNotEmpty(source.getProgQuserProgPrivVOs()))
431 		{
432 			if (ArrayUtils.isEmpty(source.getProgQuserProgPrivVOs())) {
433 				target.getProgQuserProgPrivs().clear();
434 			}
435 			else {
436 				Daos.replaceEntities(target.getProgQuserProgPrivs(),
437 						source.getProgQuserProgPrivVOs(),
438 						vo -> {
439 							ProgQuserProgPriv entity = progQuserProgPrivDao.progQuserProgPrivVOToEntity(vo);
440 							if (updateDt != null) {
441 								entity.setUpdateDt(updateDt);
442 							}
443 							return entity;
444 						});
445 			}
446 		}
447 
448 
449 		if (withChildren)
450 		{
451 
452 			// Monitoring location
453 			if (copyIfNull || ArrayUtils.isNotEmpty(source.getMonLocProgVOs()))
454 			{
455 				if (ArrayUtils.isEmpty(source.getMonLocProgVOs())) {
456 					target.getMonLocProgs().clear();
457 				}
458 				else {
459 					Daos.replaceEntities(target.getMonLocProgs(),
460 							source.getMonLocProgVOs(),
461 							vo -> {
462 								MonLocProg entity = monLocProgDao.monLocProgVOToEntity(vo);
463 								entity.setProgram(target);
464 								if (entity.getMonLocProgId() == null) {
465 									// assigned id (see mantis #28120)
466 									entity.setMonLocProgId(vo.getMonLocProgId());
467 									getSession().save(entity);
468 								}
469 								return entity;
470 							});
471 				}
472 			}
473 
474 			// Strategies
475 			if (copyIfNull || source.getStrategyVOs() != null) {
476 				if (source.getStrategyVOs() == null) {
477 					target.getStrategies().clear();
478 				}
479 				else {
480 					Daos.replaceEntities(target.getStrategies(),
481 							source.getStrategyVOs(),
482 							vo -> {
483 								Strategy strategy = strategyDao.strategyVOToEntity(vo);
484 								strategy.setProgram(target);
485 								return strategy;
486 							});
487 				}
488 			}
489 		}
490 	}
491 
492 }