1 package fr.ifremer.tutti.persistence.service.referential;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 import com.google.common.base.Preconditions;
28 import com.google.common.collect.Lists;
29 import fr.ifremer.adagio.core.dao.data.vessel.VesselExtendDao;
30 import fr.ifremer.adagio.core.dao.referential.StatusCode;
31 import fr.ifremer.adagio.core.dao.referential.VesselTypeId;
32 import fr.ifremer.adagio.core.dao.referential.location.LocationExtendDao;
33 import fr.ifremer.adagio.core.dao.referential.location.LocationLabel;
34 import fr.ifremer.adagio.core.dao.referential.location.LocationLevelId;
35 import fr.ifremer.adagio.core.dao.technical.hibernate.TemporaryDataHelper;
36 import fr.ifremer.tutti.persistence.entities.referential.Vessel;
37 import fr.ifremer.tutti.persistence.entities.referential.Vessels;
38 import org.apache.commons.lang3.StringUtils;
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41 import org.hibernate.type.DateType;
42 import org.hibernate.type.IntegerType;
43 import org.hibernate.type.StringType;
44 import org.nuiton.jaxx.application.ApplicationBusinessException;
45 import org.nuiton.jaxx.application.ApplicationTechnicalException;
46 import org.springframework.cache.Cache;
47 import org.springframework.dao.DataIntegrityViolationException;
48 import org.springframework.stereotype.Service;
49
50 import javax.annotation.Resource;
51 import java.util.Collection;
52 import java.util.Collections;
53 import java.util.Date;
54 import java.util.Iterator;
55 import java.util.List;
56
57
58
59
60
61
62
63 @Service("vesselPersistenceService")
64 public class VesselPersistenceServiceImpl extends ReferentialPersistenceServiceSupport implements VesselPersistenceService {
65
66
67 private static final Log log = LogFactory.getLog(VesselPersistenceServiceImpl.class);
68
69 @Resource(name = "vesselExtendDao")
70 protected VesselExtendDao vesselExtendDao;
71
72 @Resource(name = "locationDao")
73 protected LocationExtendDao locationDao;
74
75 @Override
76 public List<Vessel> getAllScientificVessel() {
77
78 Iterator<Object[]> list = queryListWithStatus(
79 "allVessels",
80 "refDate", DateType.INSTANCE, new Date(),
81 "vesselTypeId", IntegerType.INSTANCE, VesselTypeId.SCIENTIFIC_RESEARCH_VESSEL.getValue());
82
83 List<Vessel> result = Lists.newArrayList();
84 Cache vesselByCodeCache = cacheService.getCache("vesselByCode");
85 loadVessels(list, result, true, vesselByCodeCache);
86
87 return Collections.unmodifiableList(result);
88
89 }
90
91 @Override
92 public List<Vessel> getAllFishingVessel() {
93
94 Iterator<Object[]> list = queryListWithStatus(
95 "allVessels",
96 "refDate", DateType.INSTANCE, new Date(),
97 "vesselTypeId", IntegerType.INSTANCE, VesselTypeId.FISHING_VESSEL.getValue());
98
99 List<Vessel> result = Lists.newArrayList();
100 Cache vesselByCodeCache = cacheService.getCache("vesselByCode");
101 loadVessels(list, result, false, vesselByCodeCache);
102
103 return Collections.unmodifiableList(result);
104
105 }
106
107 @Override
108 public List<Vessel> getAllVesselWithObsoletes() {
109
110 List<Vessel> result = Lists.newArrayList();
111
112 Iterator<Object[]> fishingVesselList = queryListWithStatus2(
113 "allVesselsWithObsoletes",
114 "refDate", DateType.INSTANCE, new Date(),
115 "vesselTypeId", IntegerType.INSTANCE, VesselTypeId.FISHING_VESSEL.getValue());
116 loadVesselsWithObsoletes(fishingVesselList, result, false);
117 int fishingVesselCount = result.size();
118 if (log.isDebugEnabled()) {
119 log.debug("fishing vessels: " + fishingVesselCount);
120 }
121
122 Iterator<Object[]> scientificVesselList = queryListWithStatus2(
123 "allVesselsWithObsoletes",
124 "refDate", DateType.INSTANCE, new Date(),
125 "vesselTypeId", IntegerType.INSTANCE, VesselTypeId.SCIENTIFIC_RESEARCH_VESSEL.getValue());
126 loadVesselsWithObsoletes(scientificVesselList, result, true);
127 if (log.isDebugEnabled()) {
128 log.debug("scientific vessels: " + (result.size() - fishingVesselCount));
129 }
130
131 return Collections.unmodifiableList(result);
132
133 }
134
135 @Override
136 public Vessel getVessel(String vesselCode) {
137
138 if (log.isDebugEnabled()) {
139 log.debug("get vessel: " + vesselCode);
140 }
141
142
143 Iterator<Object[]> source = queryListWithStatus2(
144 "vesselByCode",
145 "vesselCode", StringType.INSTANCE, vesselCode,
146 "refDate", DateType.INSTANCE, new Date()
147 );
148 Object[] vesselSource = null;
149 while (source.hasNext()) {
150 vesselSource = source.next();
151 }
152 if (vesselSource == null) {
153 throw new ApplicationTechnicalException("Could not find vessel with code: " + vesselCode);
154 }
155 return loadVessel(vesselSource);
156
157 }
158
159 @Override
160 public boolean isTemporaryVesselUsed(String code) {
161
162 Long count = queryUniqueTyped("countVesselInCruise", "id", StringType.INSTANCE, code);
163 boolean result = count > 0;
164
165 if (!result) {
166 count = queryUniqueTyped("countVesselInFishingOperation", "id", StringType.INSTANCE, code);
167 result = count > 0;
168 }
169
170 if (!result) {
171 count = queryUniqueTyped("countVesselInOperationVesselAssociation", "id", StringType.INSTANCE, code);
172 result = count > 0;
173 }
174
175 if (!result) {
176 count = queryUniqueTyped("countVesselInDailyActivityCalendar", "id", StringType.INSTANCE, code);
177 result = count > 0;
178 }
179
180 if (!result) {
181 count = queryUniqueTyped("countVesselInLanding", "id", StringType.INSTANCE, code);
182 result = count > 0;
183 }
184
185 if (!result) {
186 count = queryUniqueTyped("countVesselInFishingtrip", "id", StringType.INSTANCE, code);
187 result = count > 0;
188 }
189
190 if (!result) {
191 count = queryUniqueTyped("countVesselInVesselUseFeatures", "id", StringType.INSTANCE, code);
192 result = count > 0;
193 }
194
195 if (!result) {
196 count = queryUniqueTyped("countVesselInGearUseFeatures", "id", StringType.INSTANCE, code);
197 result = count > 0;
198 }
199
200 if (!result) {
201 count = queryUniqueTyped("countVesselInGearPhysicalFeatures", "id", StringType.INSTANCE, code);
202 result = count > 0;
203 }
204
205 return result;
206
207 }
208
209 @Override
210 public List<Vessel> addTemporaryVessels(List<Vessel> vessels) {
211
212 Integer countryLocationId =
213 locationDao.getLocationIdByLabelAndLocationLevel(
214 LocationLabel.FRANCE.getValue(),
215 new Integer[]{LocationLevelId.PAYS_ISO3.getValue()});
216 if (countryLocationId == null) {
217 throw new DataIntegrityViolationException("Default country location not found, with label=" + LocationLabel.FRANCE.getValue());
218 }
219
220 List<Vessel> result = Lists.newArrayList();
221 for (Vessel source : vessels) {
222 Vessel added = addTemporaryVessel(source, countryLocationId);
223 result.add(added);
224 }
225 return Collections.unmodifiableList(result);
226
227 }
228
229 @Override
230 public List<Vessel> updateTemporaryVessels(List<Vessel> vessels) {
231
232 Integer countryLocationId =
233 locationDao.getLocationIdByLabelAndLocationLevel(
234 LocationLabel.FRANCE.getValue(),
235 new Integer[]{LocationLevelId.PAYS_ISO3.getValue()});
236 if (countryLocationId == null) {
237 throw new DataIntegrityViolationException("Default country location not found, with label=" + LocationLabel.FRANCE.getValue());
238 }
239
240 List<Vessel> result = Lists.newArrayList();
241 for (Vessel source : vessels) {
242 Vessel updated = updateTemporaryVessel(source, countryLocationId);
243 result.add(updated);
244 source = updateTemporaryVessel(source, countryLocationId);
245 result.add(source);
246 }
247 return Collections.unmodifiableList(result);
248
249 }
250
251 @Override
252 public List<Vessel> linkTemporaryVessels(List<Vessel> vessels) {
253
254 List<Vessel> result = Lists.newArrayList();
255 for (Vessel source : vessels) {
256 Vessel linked = linkTemporaryVessel(source);
257 result.add(linked);
258 }
259 return Collections.unmodifiableList(result);
260
261 }
262
263 @Override
264 public void replaceVessel(Vessel source, Vessel target, boolean delete) {
265
266 Preconditions.checkNotNull(source);
267 Preconditions.checkNotNull(target);
268 Preconditions.checkState(Vessels.isTemporary(source));
269 Preconditions.checkState(!Vessels.isTemporary(target));
270
271 String sourceId = source.getId();
272 String targetId = target.getId();
273
274 queryUpdate("replaceVesselInCruise",
275 "sourceId", StringType.INSTANCE, sourceId,
276 "targetId", StringType.INSTANCE, targetId);
277
278 queryUpdate("replaceVesselInFishingOperation",
279 "sourceId", StringType.INSTANCE, sourceId,
280 "targetId", StringType.INSTANCE, targetId);
281
282 queryUpdate("replaceVesselInOperationVesselAssociation",
283 "sourceId", StringType.INSTANCE, sourceId,
284 "targetId", StringType.INSTANCE, targetId);
285
286 queryUpdate("replaceVesselInDailyActivityCalendar",
287 "sourceId", StringType.INSTANCE, sourceId,
288 "targetId", StringType.INSTANCE, targetId);
289
290 queryUpdate("replaceVesselInLanding",
291 "sourceId", StringType.INSTANCE, sourceId,
292 "targetId", StringType.INSTANCE, targetId);
293
294 queryUpdate("replaceVesselInFishingtrip",
295 "sourceId", StringType.INSTANCE, sourceId,
296 "targetId", StringType.INSTANCE, targetId);
297
298 queryUpdate("replaceVesselInVesselUseFeatures",
299 "sourceId", StringType.INSTANCE, sourceId,
300 "targetId", StringType.INSTANCE, targetId);
301
302 queryUpdate("replaceVesselInGearUseFeatures",
303 "sourceId", StringType.INSTANCE, sourceId,
304 "targetId", StringType.INSTANCE, targetId);
305
306 queryUpdate("replaceVesselInGearPhysicalFeatures",
307 "sourceId", StringType.INSTANCE, sourceId,
308 "targetId", StringType.INSTANCE, targetId);
309
310
311
312 if (delete) {
313
314 deleteTemporaryVessel(sourceId);
315
316 }
317
318 }
319
320 @Override
321 public void deleteTemporaryVessels(Collection<String> codes) {
322
323 for (String code : codes) {
324 deleteTemporaryVessel(code);
325 }
326
327 }
328
329 @Override
330 public void deleteTemporaryVessel(String code) {
331
332 Preconditions.checkNotNull(code);
333 if (!code.startsWith(TemporaryDataHelper.TEMPORARY_NAME_PREFIX)) {
334 throw new ApplicationBusinessException(String.format("Can't delete a Vessel with a code %s not beginning with %s.", code, TemporaryDataHelper.TEMPORARY_NAME_PREFIX));
335 }
336 Vessel vessel = getVessel(code);
337 if (vessel == null) {
338 throw new ApplicationBusinessException(String.format("Vessel with code %s does not exists", code));
339 }
340
341 vesselExtendDao.removeTemporaryVessel(code);
342
343 }
344
345 protected Vessel addTemporaryVessel(Vessel source, Integer registrationLocationId) {
346
347 Preconditions.checkNotNull(source);
348 Preconditions.checkNotNull(source.getName());
349 Preconditions.checkNotNull(source.getInternationalRegistrationCode());
350 Preconditions.checkArgument(StringUtils.isBlank(source.getId()) || Vessels.isTemporaryId(source.getId()));
351
352 Integer vesselTypeId = getVesselTypeId(source);
353
354 fr.ifremer.adagio.core.dao.data.vessel.Vessel target =
355 vesselExtendDao.createAsTemporary(
356 null,
357 source.getInternationalRegistrationCode(),
358 registrationLocationId, source.getName(),
359 vesselTypeId,
360 false);
361
362
363 Vessel result = Vessels.newVessel();
364 result.setId(target.getCode());
365 result.setName(source.getName());
366 result.setRegistrationCode(source.getRegistrationCode());
367 result.setInternationalRegistrationCode(source.getInternationalRegistrationCode());
368 result.setScientificVessel(source.isScientificVessel());
369 setStatus(StatusCode.TEMPORARY.getValue(), result);
370 return result;
371
372 }
373
374 protected Vessel updateTemporaryVessel(Vessel source, Integer countryLocationId) {
375
376 Preconditions.checkNotNull(source);
377 Preconditions.checkNotNull(source.getId());
378 Preconditions.checkNotNull(source.getName());
379 Preconditions.checkNotNull(source.getInternationalRegistrationCode());
380 Preconditions.checkArgument(Vessels.isTemporaryId(source.getId()));
381
382
383 Vessel result = getVessel(source.getId());
384 result.setName(source.getName());
385 result.setRegistrationCode(source.getRegistrationCode());
386 result.setInternationalRegistrationCode(source.getInternationalRegistrationCode());
387 result.setScientificVessel(source.isScientificVessel());
388 setStatus(StatusCode.TEMPORARY.getValue(), result);
389
390 Integer vesselTypeId = getVesselTypeId(source);
391
392 vesselExtendDao.updateTemporaryVessel(
393 source.getId(),
394 source.getRegistrationCode(),
395 source.getInternationalRegistrationCode(),
396 countryLocationId,
397 source.getName(),
398 vesselTypeId,
399 false);
400
401 return result;
402
403 }
404
405 private Integer getVesselTypeId(Vessel source) {
406 Integer vesselTypeId;
407 if (source.isScientificVessel()) {
408 vesselTypeId = VesselTypeId.SCIENTIFIC_RESEARCH_VESSEL.getValue();
409 } else {
410 vesselTypeId = VesselTypeId.FISHING_VESSEL.getValue();
411 }
412 return vesselTypeId;
413 }
414
415 protected Vessel linkTemporaryVessel(Vessel source) {
416
417 Preconditions.checkNotNull(source);
418 Preconditions.checkNotNull(source.getId());
419 Preconditions.checkNotNull(source.getName());
420 Preconditions.checkNotNull(source.getInternationalRegistrationCode());
421 Preconditions.checkArgument(Vessels.isTemporaryId(source.getId()));
422
423
424
425 Iterator<Object[]> row = queryListWithStatus(
426 "vesselByInternationalRegistrationCode",
427 "vesselInternationalRegistrationCode", StringType.INSTANCE, source.getInternationalRegistrationCode(),
428 "refDate", DateType.INSTANCE, new Date()
429 );
430 return row.hasNext() ? loadVessel(row.next()) : null;
431
432 }
433
434 protected void loadVessels(Iterator<Object[]> list, List<Vessel> result, boolean scientificVessel, Cache vesselByCodeCache) {
435 while (list.hasNext()) {
436 Object[] source = list.next();
437 Vessel target = loadVessel(source);
438 target.setScientificVessel(scientificVessel);
439 result.add(target);
440
441 vesselByCodeCache.put(target.getId(), target);
442 }
443 }
444
445 protected void loadVesselsWithObsoletes(Iterator<Object[]> list, List<Vessel> result, boolean scientificVessel) {
446
447 Vessel lastTarget = null;
448 while (list.hasNext()) {
449 Object[] source = list.next();
450 Vessel target = loadVessel(source);
451 target.setScientificVessel(scientificVessel);
452 if (lastTarget != null && !target.getId().equals(lastTarget.getId())) {
453
454
455 result.add(lastTarget);
456 }
457 lastTarget = target;
458 }
459 result.add(lastTarget);
460
461 }
462
463 protected Vessel loadVessel(Object... source) {
464
465 Vessel target = Vessels.newVessel();
466 target.setId((String) source[0]);
467 target.setRegistrationCode((String) source[1]);
468 target.setInternationalRegistrationCode((String) source[2]);
469 target.setName((String) source[3]);
470 Integer vesselTypeId = (Integer) source[4];
471 boolean scientificVessel = VesselTypeId.SCIENTIFIC_RESEARCH_VESSEL.getValue().equals(vesselTypeId);
472 target.setScientificVessel(scientificVessel);
473 setStatus((String) source[5], target);
474 return target;
475
476 }
477
478 }