View Javadoc
1   package fr.ifremer.quadrige3.core.dao.data.survey;
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  
26  import com.google.common.collect.Lists;
27  import fr.ifremer.quadrige3.core.dao.ObjectTypes;
28  import fr.ifremer.quadrige3.core.dao.administration.program.Program;
29  import fr.ifremer.quadrige3.core.dao.data.measurement.Measurement;
30  import fr.ifremer.quadrige3.core.dao.data.measurement.MeasurementExtendDao;
31  import fr.ifremer.quadrige3.core.dao.data.measurement.TaxonMeasurement;
32  import fr.ifremer.quadrige3.core.dao.data.measurement.TaxonMeasurementExtendDao;
33  import fr.ifremer.quadrige3.core.dao.data.samplingoperation.SamplingOperation;
34  import fr.ifremer.quadrige3.core.dao.referential.monitoringLocation.MonitoringLocation;
35  import fr.ifremer.quadrige3.core.dao.system.synchronization.DeletedItemHistoryExtendDao;
36  import fr.ifremer.quadrige3.core.dao.system.synchronization.SynchronizationStatus;
37  import fr.ifremer.quadrige3.core.dao.technical.Assert;
38  import fr.ifremer.quadrige3.core.dao.technical.Daos;
39  import fr.ifremer.quadrige3.core.vo.administration.program.ProgramVO;
40  import fr.ifremer.quadrige3.core.vo.data.survey.LightSurveyVO;
41  import fr.ifremer.quadrige3.core.vo.referential.monitoringLocation.MonitoringLocationVO;
42  import fr.ifremer.quadrige3.synchro.meta.data.DataSynchroTables;
43  import org.apache.commons.collections4.CollectionUtils;
44  import org.apache.commons.logging.Log;
45  import org.apache.commons.logging.LogFactory;
46  import org.hibernate.Query;
47  import org.hibernate.Session;
48  import org.hibernate.SessionFactory;
49  import org.hibernate.type.IntegerType;
50  import org.hibernate.type.StringType;
51  import org.springframework.beans.factory.annotation.Autowired;
52  import org.springframework.stereotype.Repository;
53  
54  import javax.annotation.Resource;
55  import java.util.Collection;
56  import java.util.List;
57  import java.util.Set;
58  
59  /**
60   * <p>
61   * SurveyDaoImpl class.
62   * </p>
63   * 
64   */
65  @Repository("surveyDao")
66  public class SurveyDaoImpl extends SurveyDaoBase implements SurveyExtendDao {
67  
68  	/**
69  	 * Logger.
70  	 */
71  	private static final Log log = LogFactory.getLog(SurveyDaoImpl.class);
72  
73  	private static final Set<String> surveyObjectTypesCodes = ObjectTypes.getObjectTypeFromTableName(DataSynchroTables.SURVEY.name());
74  
75  	private static final String[] SYNCHRONIZATION_STATUS_NOT_EXPORTED = new String[] {
76  			SynchronizationStatus.DIRTY.getValue(),
77  			SynchronizationStatus.READY_TO_SYNCHRONIZE.getValue()
78  	};
79  
80  	@Resource
81  	private DeletedItemHistoryExtendDao deletedItemHistoryDao;
82  
83  	@Resource
84  	private MeasurementExtendDao measurementDao;
85  
86  	@Resource
87  	private TaxonMeasurementExtendDao taxonMeasurementDao;
88  
89  	/**
90  	 * <p>
91  	 * Constructor for SurveyDaoImpl.
92  	 * </p>
93  	 * 
94  	 * @param sessionFactory
95  	 *            a {@link org.hibernate.SessionFactory} object.
96  	 */
97  	@Autowired
98  	public SurveyDaoImpl(SessionFactory sessionFactory) {
99  		super();
100 		setSessionFactory(sessionFactory);
101 	}
102 
103 	/** {@inheritDoc} */
104 	@Override
105 	public LightSurveyVO getLightSurveyById(int surveyId) {
106 
107 		// Load entity by id
108 		Survey source = get(surveyId);
109 		if (source == null)
110 			return null;
111 
112 		return toLightSurveyVO(source);
113 	}
114 
115 	/** {@inheritDoc} */
116 	@Override
117 	public void removeUsingDeletedItemHistory(int surveyId, Integer recorderPersonId) {
118 		// Load entity by id
119 		Survey survey = get(surveyId);
120 		boolean hasBeenSynchronized = (survey.getRemoteId() != null);
121 
122 		// in classic remove AND with deletedItemHistory
123 
124 		// If entity is not in server: do a classic remove
125 		if (!hasBeenSynchronized) {
126 			remove(survey.getSurveyId());
127 			return;
128 		}
129 
130 		Assert.notNull(recorderPersonId, "Argument 'recorderPersonId' must not be null");
131 
132 		// Add a record into DeletedItemHistory
133 		deletedItemHistoryDao.insertDeletedItem(
134 				SurveyImpl.class,
135 				survey,
136 				recorderPersonId);
137 
138 		// Change synchronization status to DELETED
139 		survey.setSynchronizationStatus(SynchronizationStatus.DELETED.getValue());
140 		getSession().save(survey);
141 	}
142 
143 	/** {@inheritDoc} */
144 	@Override
145 	public void removeByIds(Collection<Integer> ids) {
146 		for (Integer id : ids) {
147 			remove(id);
148 		}
149 	}
150 
151 	/** {@inheritDoc} */
152 	@Override
153 	public int updateSynchronizationStatus(int surveyId, SynchronizationStatus synchronizationStatus) {
154 		return updateSynchronizationStatus(Lists.newArrayList(surveyId), synchronizationStatus);
155 	}
156 
157 	/** {@inheritDoc} */
158 	@Override
159 	public int updateSynchronizationStatus(List<Integer> surveyIds, SynchronizationStatus synchronizationStatus) {
160 		Assert.notNull(synchronizationStatus);
161 		return queryUpdate("updateSurveySynchronizationStatus",
162 				"surveyIds", null, surveyIds,
163 				"synchronizationStatus", StringType.INSTANCE, synchronizationStatus.getValue());
164 	}
165 
166 	/** {@inheritDoc} */
167 	@Override
168 	public int updateHasMeasFlag(int surveyId) {
169 		return updateHasMeasFlag(Lists.newArrayList(surveyId));
170 	}
171 
172 	/** {@inheritDoc} */
173 	@Override
174 	public int updateHasMeasFlag(List<Integer> surveyIds) {
175 		Assert.notEmpty(surveyIds);
176 
177 		if (log.isDebugEnabled()) {
178 			log.debug(String.format("Updating HAS_MEAS flag on surveys: %s", surveyIds.toString()));
179 		}
180 		int rowCount = 0;
181 
182 		// get surveys WITH meas
183 		final List<Integer> surveyIdsWithMeas = queryListTyped("surveyIdsWithMeas",
184 				"surveyIds", null, surveyIds);
185 		boolean hasSurveysWithMeas = CollectionUtils.isNotEmpty(surveyIdsWithMeas);
186 
187 		// get surveys WITHOUT meas
188 		List<Integer> surveyIdsNoMeas;
189 		if (!hasSurveysWithMeas) {
190 			surveyIdsNoMeas = surveyIds;
191 		}
192 		else {
193 			// remove surveyIdsNoMeas from the input list
194 			surveyIdsNoMeas = Lists.newArrayList(surveyIds);
195 			surveyIdsNoMeas.removeAll(surveyIdsWithMeas);
196 		}
197 
198 		// Update surveys WITH meas
199 		if (hasSurveysWithMeas) {
200 			rowCount += queryUpdate("updateSurveyHasMeas",
201 					"surveyHasMeas", StringType.INSTANCE, Daos.convertToString(true),
202 					"surveyIds", null, surveyIdsWithMeas);
203 		}
204 
205 		// Update surveys WITHOUT meas
206 		if (CollectionUtils.isNotEmpty(surveyIdsNoMeas)) {
207 			rowCount += queryUpdate("updateSurveyHasMeas",
208 					"surveyHasMeas", StringType.INSTANCE, Daos.convertToString(false),
209 					"surveyIds", null, surveyIdsNoMeas);
210 		}
211 
212 		return rowCount;
213 	}
214 
215 	/** {@inheritDoc} */
216 	@Override
217 	public boolean isReadyToSynchronizeStatusForRecorderPerson(int recorderPersonId) {
218 
219 		// TODO: add also DELETED ITEMS !!!!!!!!!!!
220 
221 		// count observed locations
222 		Long nb = queryUniqueTyped("countSurveyBySynchronizationStatus",
223 				"recorderPersonId", IntegerType.INSTANCE, recorderPersonId,
224 				"synchronizationStatus", StringType.INSTANCE, SynchronizationStatus.READY_TO_SYNCHRONIZE.value());
225 
226 		return nb > 0;
227 	}
228 
229 	/** {@inheritDoc} */
230 	@Override
231 	@SuppressWarnings("unchecked")
232 	public List<Integer> getCleanableSurveyIds() {
233 		Query query = createQuery("cleanableSurveyIds",
234 				"syncSynchronizationStatus", StringType.INSTANCE, SynchronizationStatus.SYNCHRONIZED.value());
235 		query.setParameterList("objectTypes", surveyObjectTypesCodes);
236 
237 		return (List<Integer>) query.list();
238 	}
239 
240 	@Override
241 	public void applySurveyProgramsToChildren(int surveyId) {
242 		// Get the survey
243 		Survey survey = get(SurveyImpl.class, surveyId);
244 		Assert.size(survey.getPrograms(), 1);
245 
246 		List<Integer> samplingOperIds = Lists.newArrayList();
247 
248 		// Update sampling operations prog
249 		Session session = getSession();
250 		for (SamplingOperation so: survey.getSamplingOperations()) {
251 			so.getPrograms().clear();
252 			so.getPrograms().addAll(survey.getPrograms());
253 			session.update(so);
254 
255 			samplingOperIds.add(so.getSamplingOperId());
256 		}
257 
258 		// Update survey measurements
259 		{
260 			// Measurements
261 			List<Measurement> measurements = measurementDao.loadBySurveyId(surveyId);
262 			for (Measurement m: measurements) {
263 				m.getPrograms().clear();
264 				m.getPrograms().addAll(survey.getPrograms());
265 				session.update(m);
266 			}
267 			// Taxon measurements
268 			List<TaxonMeasurement> taxonMeasurements = taxonMeasurementDao.loadBySurveyId(surveyId);
269 			for (TaxonMeasurement m: taxonMeasurements) {
270 				m.getPrograms().clear();
271 				m.getPrograms().addAll(survey.getPrograms());
272 				session.update(m);
273 			}
274 		}
275 
276 		// Update sampling operation measurements
277 		if (CollectionUtils.isNotEmpty(samplingOperIds)){
278 			// Measurements
279 			List<Measurement> measurements = measurementDao.loadBySamplingOperIds(samplingOperIds);
280 			for (Measurement m: measurements) {
281 				m.getPrograms().clear();
282 				m.getPrograms().addAll(survey.getPrograms());
283 				session.update(m);
284 			}
285 			// Taxon measurements
286 			List<TaxonMeasurement> taxonMeasurements = taxonMeasurementDao.loadBySamplingOperIds(samplingOperIds);
287 			for (TaxonMeasurement m: taxonMeasurements) {
288 				m.getPrograms().clear();
289 				m.getPrograms().addAll(survey.getPrograms());
290 				session.update(m);
291 			}
292 
293 			// TODO (if sample used in a client application): update measurements on sample
294 		}
295 
296 	}
297 
298 	/* -- Internal methods -- */
299 
300 	/**
301 	 * <p>
302 	 * toLightSurveyVO.
303 	 * </p>
304 	 * 
305 	 * @param source
306 	 *            a {@link fr.ifremer.quadrige3.core.dao.data.survey.Survey} object.
307 	 * @return a {@link fr.ifremer.quadrige3.core.vo.data.survey.LightSurveyVO} object.
308 	 */
309 	protected LightSurveyVO toLightSurveyVO(Survey source) {
310 		LightSurveyVO target = new LightSurveyVO();
311 
312 		toLightSurveyVO(source, target);
313 
314 		return target;
315 	}
316 
317 	/**
318 	 * <p>
319 	 * toLightSurveyVO.
320 	 * </p>
321 	 * 
322 	 * @param source
323 	 *            a {@link fr.ifremer.quadrige3.core.dao.data.survey.Survey} object.
324 	 * @param target
325 	 *            a {@link fr.ifremer.quadrige3.core.vo.data.survey.LightSurveyVO} object.
326 	 */
327 	protected void toLightSurveyVO(Survey source, LightSurveyVO target) {
328 
329 		// survey date
330 		target.setSurveyDt(source.getSurveyDt());
331 
332 		// monitoring location
333 		if (source.getMonitoringLocation() == null) {
334 			target.setMonitoringLocation(null);
335 		}
336 		else {
337 			target.setMonitoringLocation(toMonitoringLocationVO(source.getMonitoringLocation()));
338 		}
339 
340 		// programs
341 		if (CollectionUtils.isEmpty(source.getPrograms())) {
342 			target.setPrograms(null);
343 		}
344 		else {
345 			List<ProgramVO> programList = Lists.newArrayList();
346 			for (Program program : source.getPrograms()) {
347 				ProgramVO vo = toProgramVO(program);
348 				programList.add(vo);
349 			}
350 			target.setPrograms(programList.toArray(new ProgramVO[programList.size()]));
351 		}
352 	}
353 
354 	/**
355 	 * <p>
356 	 * toMonitoringLocationVO.
357 	 * </p>
358 	 * 
359 	 * @param source
360 	 *            a {@link fr.ifremer.quadrige3.core.dao.referential.monitoringLocation.MonitoringLocation} object.
361 	 * @return a {@link fr.ifremer.quadrige3.core.vo.referential.monitoringLocation.MonitoringLocationVO} object.
362 	 */
363 	protected MonitoringLocationVO toMonitoringLocationVO(MonitoringLocation source) {
364 		MonitoringLocationVO target = new MonitoringLocationVO();
365 
366 		// id
367 		target.setId(source.getMonLocId());
368 
369 		// label
370 		target.setLabel(source.getMonLocLb());
371 
372 		// name
373 		target.setName(source.getMonLocNm());
374 
375 		return target;
376 	}
377 
378 	/**
379 	 * <p>
380 	 * toProgramVO.
381 	 * </p>
382 	 * 
383 	 * @param source
384 	 *            a {@link fr.ifremer.quadrige3.core.dao.administration.program.Program} object.
385 	 * @return a {@link fr.ifremer.quadrige3.core.vo.administration.program.ProgramVO} object.
386 	 */
387 	protected ProgramVO toProgramVO(Program source) {
388 		ProgramVO target = new ProgramVO();
389 
390 		// code
391 		target.setProgCd(source.getProgCd());
392 
393 		// name
394 		target.setProgNm(source.getProgNm());
395 
396 		return target;
397 	}
398 
399 }