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 net.sumaris.core.dao.administration.programStrategy.ProgramDao;
26 import net.sumaris.core.dao.administration.user.DepartmentDao;
27 import net.sumaris.core.dao.administration.user.PersonDao;
28 import net.sumaris.core.dao.technical.Daos;
29 import net.sumaris.core.dao.technical.SortDirection;
30 import net.sumaris.core.dao.technical.jpa.SumarisJpaRepositoryImpl;
31 import net.sumaris.core.dao.technical.model.IEntity;
32 import net.sumaris.core.model.administration.user.Person;
33 import net.sumaris.core.model.data.*;
34 import net.sumaris.core.util.Beans;
35 import net.sumaris.core.vo.administration.programStrategy.ProgramFetchOptions;
36 import net.sumaris.core.vo.administration.user.DepartmentVO;
37 import net.sumaris.core.vo.administration.user.PersonVO;
38 import net.sumaris.core.vo.data.DataFetchOptions;
39 import net.sumaris.core.vo.data.IRootDataVO;
40 import net.sumaris.core.vo.data.VesselSnapshotVO;
41 import net.sumaris.core.vo.filter.IRootDataFilter;
42 import org.apache.commons.collections4.CollectionUtils;
43 import org.apache.commons.collections4.SetUtils;
44 import org.apache.commons.lang3.NotImplementedException;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47 import org.springframework.beans.factory.annotation.Autowired;
48 import org.springframework.data.domain.*;
49 import org.springframework.data.jpa.domain.Specification;
50 import org.springframework.lang.Nullable;
51
52 import javax.persistence.EntityManager;
53 import java.sql.Timestamp;
54 import java.util.Date;
55 import java.util.List;
56 import java.util.Map;
57 import java.util.Set;
58 import java.util.stream.Collectors;
59
60 public class RootDataRepositoryImpl<
61 E extends IRootDataEntity<ID>,
62 ID extends Integer,
63 V extends IRootDataVO<ID>,
64 F extends IRootDataFilter
65 >
66 extends SumarisJpaRepositoryImpl<E, Integer>
67 implements RootDataRepository<E, ID, V, F> {
68
69
70
71
72 private static final Logger log =
73 LoggerFactory.getLogger(RootDataRepositoryImpl.class);
74
75 @Autowired
76 private PersonDao personDao;
77
78 @Autowired
79 private DepartmentDao departmentDao;
80
81 @Autowired
82 private ProgramDao programDao;
83
84 public RootDataRepositoryImpl(Class<E> domainClass,
85 EntityManager entityManager) {
86 super(domainClass, entityManager);
87 }
88
89 @Override
90 public List<V> findAll(F filter) {
91 return findAll(toSpecification(filter)).stream().map(this::toVO).collect(Collectors.toList());
92 }
93
94 @Override
95 public List<V> findAll(F filter, DataFetchOptions fetchOptions) {
96 return findAll(toSpecification(filter)).stream()
97 .map(e -> this.toVO(e, fetchOptions))
98 .collect(Collectors.toList());
99 }
100
101 @Override
102 public Page<V> findAll(F filter, Pageable pageable) {
103 return findAll(toSpecification(filter), pageable)
104 .map(e -> this.toVO(e));
105 }
106
107 @Override
108 public Page<V> findAll(F filter, Pageable pageable, DataFetchOptions fetchOptions) {
109 return findAll(toSpecification(filter), pageable)
110 .map(e -> this.toVO(e, fetchOptions));
111 }
112
113 @Override
114 public Page<V> findAll(int offset, int size, String sortAttribute, SortDirection sortDirection, DataFetchOptions fetchOptions) {
115 return findAll(PageRequest.of(offset / size, size, Sort.Direction.fromString(sortDirection.toString()), sortAttribute))
116 .map(e -> this.toVO(e, fetchOptions));
117 }
118
119 @Override
120 public Page<V> findAll(F filter, int offset, int size, String sortAttribute, SortDirection sortDirection, DataFetchOptions fetchOptions) {
121 return findAll(toSpecification(filter), getPageable(offset, size, sortAttribute, sortDirection))
122 .map(e -> this.toVO(e, fetchOptions));
123 }
124
125 @Override
126 public List<V> findAllAsVO(@Nullable Specification<E> spec) {
127 return super.findAll(spec).stream().map(this::toVO).collect(Collectors.toList());
128 }
129
130 @Override
131 public Page<V> findAllAsVO(@Nullable Specification<E> spec, Pageable pageable) {
132 return super.findAll(spec, pageable).map(this::toVO);
133 }
134
135 @Override
136 public Page<V> findAllAsVO(@Nullable Specification<E> spec, Pageable pageable, DataFetchOptions fetchOptions) {
137 return super.findAll(spec, pageable).map(e -> this.toVO(e, fetchOptions));
138 }
139
140 @Override
141 public List<V> findAllAsVO(@Nullable Specification<E> spec, DataFetchOptions fetchOptions) {
142 return super.findAll(spec).stream()
143 .map(e -> this.toVO(e, fetchOptions))
144 .collect(Collectors.toList());
145 }
146
147 @Override
148 public long count(F filter) {
149 return count(toSpecification(filter));
150 }
151
152 @Override
153 public V get(int id) {
154 return toVO(this.getOne(id));
155 }
156
157 @Override
158 public V get(int id, DataFetchOptions fetchOptions) {
159 return toVO(this.getOne(id), fetchOptions);
160 }
161
162 @Override
163 public V save(V vo) {
164 E entity = toEntity(vo);
165
166 if (entity.getId() == null) {
167 entity.setCreationDate(new Date());
168 }
169
170
171 Daos.checkUpdateDateForUpdate(vo, entity);
172
173
174 Timestamp newUpdateDate = getDatabaseCurrentTimestamp();
175 entity.setUpdateDate(newUpdateDate);
176
177 E savedEntity = save(entity);
178
179 vo.setId(savedEntity.getId());
180
181 return vo;
182 }
183
184 @Override
185 public V control(V vo) {
186 throw new NotImplementedException("Not implemented yet");
187 }
188
189 @Override
190 public V validate(V vo) {
191 throw new NotImplementedException("Not implemented yet");
192 }
193
194 @Override
195 public V unvalidate(V vo) {
196 throw new NotImplementedException("Not implemented yet");
197 }
198
199 public E toEntity(V vo) {
200 E entity;
201 if (vo.getId() != null) {
202 entity = getOne(vo.getId());
203 } else {
204 entity = createEntity();
205 }
206 toEntity(vo, entity, true);
207 return entity;
208 }
209
210
211 public void toEntity(V source, E target, boolean copyIfNull) {
212 DataDaos.copyRootDataProperties(getEntityManager(), source, target, copyIfNull);
213
214
215 if (source instanceof IWithObserversEntityodel/data/IWithObserversEntity.html#IWithObserversEntity">IWithObserversEntity && target instanceof IWithObserversEntity) {
216 Set<PersonVO> sourceObservers = ((IWithObserversEntity) source).getObservers();
217 Set<Person> targetObservers = SetUtils.emptyIfNull(((IWithObserversEntity) target).getObservers());
218 if (copyIfNull || sourceObservers != null) {
219 if (CollectionUtils.isEmpty(sourceObservers)) {
220 if (CollectionUtils.isNotEmpty(targetObservers)) {
221 targetObservers.clear();
222 }
223 } else {
224 Map<Integer, Person> observersToRemove = Beans.splitById(targetObservers);
225 sourceObservers.stream()
226 .map(IEntity::getId)
227 .forEach(personId -> {
228 if (observersToRemove.remove(personId) == null) {
229
230 targetObservers.add(load(Person.class, personId));
231 }
232 });
233
234
235 targetObservers.removeAll(observersToRemove.values());
236 }
237 }
238 }
239 }
240
241
242
243 public V toVO(E source) {
244 return toVO(source, null);
245 }
246
247
248 public V toVO(E source, DataFetchOptions fetchOptions) {
249 V target = createVO();
250 toVO(source, target, fetchOptions, true);
251 return target;
252 }
253
254
255 public void toVO(E source, V target, DataFetchOptions fetchOptions, boolean copyIfNull) {
256 Beans.copyProperties(source, target);
257
258 target.setQualityFlagId(source.getQualityFlag().getId());
259
260
261 if (source.getProgram() != null) {
262 target.setProgram(programDao.toProgramVO(source.getProgram(),
263 ProgramFetchOptions.builder().withProperties(false)
264 .build()));
265 }
266
267
268 if (source instanceof IWithVesselEntity && target instanceof IWithVesselSnapshotEntity) {
269 VesselSnapshotVOtml#VesselSnapshotVO">VesselSnapshotVO vesselSnapshot = new VesselSnapshotVO();
270 vesselSnapshot.setId((Integer) ((IWithVesselEntity) source).getVessel().getId());
271 ((IWithVesselSnapshotEntity<Integer, VesselSnapshotVO>) target).setVesselSnapshot(vesselSnapshot);
272 }
273
274
275 if (fetchOptions == null || fetchOptions.isWithRecorderDepartment()) {
276 DepartmentVO recorderDepartment = departmentDao.toDepartmentVO(source.getRecorderDepartment());
277 target.setRecorderDepartment(recorderDepartment);
278 }
279
280
281 if ((fetchOptions == null || fetchOptions.isWithRecorderPerson()) && source.getRecorderPerson() != null) {
282 PersonVO recorderPerson = personDao.toPersonVO(source.getRecorderPerson());
283 target.setRecorderPerson(recorderPerson);
284 }
285
286
287 if (source instanceof IWithObserversEntityodel/data/IWithObserversEntity.html#IWithObserversEntity">IWithObserversEntity && target instanceof IWithObserversEntity) {
288 Set<Person> sourceObservers = ((IWithObserversEntity) source).getObservers();
289 if ((fetchOptions == null || fetchOptions.isWithObservers()) && CollectionUtils.isNotEmpty(sourceObservers)) {
290 Set<PersonVO> observers = sourceObservers.stream()
291 .map(personDao::toPersonVO)
292 .collect(Collectors.toSet());
293 ((IWithObserversEntity<Integer, PersonVO>) target).setObservers(observers);
294 }
295 }
296 }
297
298
299 public V createVO() {
300 try {
301 return getVOClass().newInstance();
302 } catch (Exception e) {
303 throw new RuntimeException(e);
304 }
305 }
306
307
308 public Class<V> getVOClass() {
309 throw new NotImplementedException("Not implemented yet. Should be override by subclass");
310 }
311
312 @Override
313 public Specification<E> toSpecification(@Nullable F filter) {
314 throw new NotImplementedException("Not implemented yet. Should be override by subclass");
315 }
316
317
318
319
320 protected void copyVessel(IWithVesselSnapshotEntity<Integer, VesselSnapshotVO> source,
321 IWithVesselEntity<Integer, Vessel> target,
322 boolean copyIfNull) {
323 DataDaos.copyVessel(getEntityManager(), source, target, copyIfNull);
324 }
325
326
327 protected void copyObservers(IWithObserversEntity<Integer, PersonVO> source,
328 IWithObserversEntity<Integer, Person> target,
329 boolean copyIfNull) {
330 DataDaos.copyObservers(getEntityManager(), source, target, copyIfNull);
331 }
332
333
334 }