1 package net.sumaris.core.dao.data;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import com.google.common.base.Preconditions;
26 import net.sumaris.core.dao.referential.ReferentialDao;
27 import net.sumaris.core.dao.referential.metier.MetierRepository;
28 import net.sumaris.core.dao.referential.taxon.TaxonGroupRepository;
29 import net.sumaris.core.dao.technical.SortDirection;
30 import net.sumaris.core.model.administration.user.Department;
31 import net.sumaris.core.model.data.Operation;
32 import net.sumaris.core.model.data.PhysicalGear;
33 import net.sumaris.core.model.data.Trip;
34 import net.sumaris.core.model.referential.IReferentialEntity;
35 import net.sumaris.core.model.referential.QualityFlag;
36 import net.sumaris.core.model.referential.metier.Metier;
37 import net.sumaris.core.util.Beans;
38 import net.sumaris.core.vo.administration.user.DepartmentVO;
39 import net.sumaris.core.vo.data.OperationVO;
40 import org.apache.commons.collections4.CollectionUtils;
41 import org.apache.commons.lang3.StringUtils;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.beans.factory.annotation.Autowired;
45 import org.springframework.stereotype.Repository;
46
47 import javax.persistence.EntityManager;
48 import javax.persistence.TypedQuery;
49 import javax.persistence.criteria.*;
50 import java.sql.Timestamp;
51 import java.util.List;
52 import java.util.Objects;
53 import java.util.stream.Collectors;
54
55 @Repository("operationDao")
56 public class OperationDaoImpl extends BaseDataDaoImpl implements OperationDao {
57
58
59 private static final Logger log =
60 LoggerFactory.getLogger(OperationDaoImpl.class);
61
62 @Autowired
63 private ReferentialDao referentialDao;
64
65 @Autowired
66 private SampleDao sampleDao;
67
68 @Autowired
69 private BatchDao batchDao;
70
71
72 @Autowired
73 private PhysicalGearDao physicalGearDao;
74
75 @Autowired
76 private TaxonGroupRepository taxonGroupDao;
77
78 @Autowired
79 private MetierRepository metierDao;
80
81 @Override
82 @SuppressWarnings("unchecked")
83 public List<OperationVO> getAllByTripId(int tripId, int offset, int size, String sortAttribute, SortDirection sortDirection) {
84 Preconditions.checkArgument(offset >= 0);
85 Preconditions.checkArgument(size > 0);
86
87
88
89
90 EntityManager entityManager = getEntityManager();
91 CriteriaBuilder builder = entityManager.getCriteriaBuilder();
92 CriteriaQuery<Operation> query = builder.createQuery(Operation.class);
93 Root<Operation> root = query.from(Operation.class);
94
95 ParameterExpression<Integer> operationIdParam = builder.parameter(Integer.class);
96
97 query.select(root)
98 .where(builder.equal(root.get(Operation.Fields.TRIP).get(IReferentialEntity.Fields.ID), operationIdParam));
99
100
101 if (StringUtils.isNotBlank(sortAttribute)) {
102 Expression<?> sortExpression = root.get(sortAttribute);
103 query.orderBy(SortDirection.DESC.equals(sortDirection) ?
104 builder.desc(sortExpression) :
105 builder.asc(sortExpression)
106 );
107 }
108
109 TypedQuery<Operation> q = entityManager.createQuery(query)
110 .setParameter(operationIdParam, tripId)
111 .setFirstResult(offset)
112 .setMaxResults(size);
113 return toOperationVOs(q.getResultList());
114 }
115
116 @Override
117 public OperationVO get(int id) {
118 Operation entity = get(Operation.class, id);
119 return toVO(entity);
120 }
121
122 @Override
123 public List<OperationVO> saveAllByTripId(int tripId, List<OperationVO> sources) {
124
125 Trip parent = get(Trip.class, tripId);
126
127
128 final List<Integer> sourcesIdsToRemove = Beans.collectIds(Beans.getList(parent.getOperations()));
129
130
131 List<OperationVO> result = sources.stream().map(source -> {
132 source.setTripId(tripId);
133 if (source.getId() != null) {
134 sourcesIdsToRemove.remove(source.getId());
135 }
136 return save(source);
137 }).collect(Collectors.toList());
138
139
140 if (CollectionUtils.isNotEmpty(sourcesIdsToRemove)) {
141 sourcesIdsToRemove.forEach(this::delete);
142 }
143
144 return result;
145 }
146
147 @Override
148 public OperationVO../../../../../net/sumaris/core/vo/data/OperationVO.html#OperationVO">OperationVO save(OperationVO source) {
149 Preconditions.checkNotNull(source);
150
151 EntityManager session = getEntityManager();
152 Operation entity = null;
153 if (source.getId() != null) {
154 entity = get(Operation.class, source.getId());
155 }
156 boolean isNew = (entity == null);
157 if (isNew) {
158 entity = new Operation();
159 }
160
161 if (!isNew) {
162
163 checkUpdateDateForUpdate(source, entity);
164
165
166 lockForUpdate(entity);
167 }
168
169
170 operationVOToEntity(source, entity, true);
171
172
173 Timestamp newUpdateDate = getDatabaseCurrentTimestamp();
174 entity.setUpdateDate(newUpdateDate);
175
176
177 if (isNew) {
178
179 entity.setId(null);
180
181 session.persist(entity);
182 source.setId(entity.getId());
183 } else {
184 session.merge(entity);
185 }
186
187 source.setUpdateDate(newUpdateDate);
188
189
190
191
192 return source;
193 }
194
195 @Override
196 public void delete(int id) {
197
198 log.debug(String.format("Deleting operation {id=%s}...", id));
199 delete(Operation.class, id);
200 }
201
202 @Override
203 public OperationVO toVO(Operation source) {
204 if (source == null) return null;
205
206 OperationVOtionVO.html#OperationVO">OperationVO target = new OperationVO();
207
208 Beans.copyProperties(source, target);
209
210
211 if (source.getTrip() != null) {
212 target.setTripId(source.getTrip().getId());
213 }
214
215
216 target.setQualityFlagId(source.getQualityFlag().getId());
217
218
219 if (source.getPhysicalGear() != null) {
220 target.setPhysicalGearId(source.getPhysicalGear().getId());
221 target.setPhysicalGear(physicalGearDao.toPhysicalGearVO(source.getPhysicalGear(), false));
222 }
223
224
225 if (source.getMetier() != null) {
226 target.setMetier(metierDao.toMetierVO(source.getMetier()));
227 }
228
229
230 DepartmentVO recorderDepartment = referentialDao.toTypedVO(source.getRecorderDepartment(), DepartmentVO.class).orElse(null);
231 target.setRecorderDepartment(recorderDepartment);
232
233 return target;
234 }
235
236
237
238 protected List<OperationVO> toOperationVOs(List<Operation> source) {
239 return source.stream()
240 .map(this::toVO)
241 .filter(Objects::nonNull)
242 .collect(Collectors.toList());
243 }
244
245 protected void operationVOToEntity(OperationVO source, Operation target, boolean copyIfNull) {
246
247 Beans.copyProperties(source, target);
248
249
250 Integer tripId = source.getTripId() != null ? source.getTripId() : (source.getTrip() != null ? source.getTrip().getId() : null);
251 if (copyIfNull || (tripId != null)) {
252 if (tripId == null) {
253 target.setTrip(null);
254 }
255 else {
256 target.setTrip(load(Trip.class, tripId));
257 }
258 }
259
260
261 if (copyIfNull || source.getRecorderDepartment() != null) {
262 if (source.getRecorderDepartment() == null || source.getRecorderDepartment().getId() == null) {
263 target.setRecorderDepartment(null);
264 }
265 else {
266 target.setRecorderDepartment(load(Department.class, source.getRecorderDepartment().getId()));
267 }
268 }
269
270
271 if (copyIfNull || source.getQualityFlagId() != null) {
272 if (source.getQualityFlagId() == null) {
273 target.setQualityFlag(load(QualityFlag.class, config.getDefaultQualityFlagId()));
274 }
275 else {
276 target.setQualityFlag(load(QualityFlag.class, source.getQualityFlagId()));
277 }
278 }
279
280
281 if (copyIfNull || source.getMetier() != null) {
282 if (source.getMetier() == null || source.getMetier().getId() == null) {
283 target.setMetier(null);
284 }
285 else {
286 target.setMetier(load(Metier.class, source.getMetier().getId()));
287 }
288 }
289
290
291 if (copyIfNull || source.getPhysicalGearId() != null || (source.getPhysicalGear() != null && source.getPhysicalGear().getId() != null)) {
292 Integer physicalGearId = source.getPhysicalGearId() != null ? source.getPhysicalGearId() : (
293 source.getPhysicalGear() != null ? source.getPhysicalGear().getId() : null
294 );
295 if (physicalGearId == null) {
296 target.setPhysicalGear(null);
297 }
298 else {
299 target.setPhysicalGear(load(PhysicalGear.class, physicalGearId));
300 }
301 }
302 }
303 }