View Javadoc
1   package net.sumaris.core.dao.data;
2   
3   /*-
4    * #%L
5    * SUMARiS:: Core
6    * %%
7    * Copyright (C) 2018 SUMARiS Consortium
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   *
19   * You should have received a copy of the GNU General Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/gpl-3.0.html>.
22   * #L%
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       * Logger.
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         // Check update date
171         Daos.checkUpdateDateForUpdate(vo, entity);
172 
173         // Update update_dt
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     //@Override
211     public void toEntity(V source, E target, boolean copyIfNull) {
212         DataDaos.copyRootDataProperties(getEntityManager(), source, target, copyIfNull);
213 
214         // Observers
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                                     // Add new item
230                                     targetObservers.add(load(Person.class, personId));
231                                 }
232                             });
233 
234                     // Remove deleted tableNames
235                     targetObservers.removeAll(observersToRemove.values());
236                 }
237             }
238         }
239     }
240 
241 
242     //@Override
243     public V toVO(E source) {
244         return toVO(source, null);
245     }
246 
247     //@Override
248     public V toVO(E source, DataFetchOptions fetchOptions) {
249         V target = createVO();
250         toVO(source, target, fetchOptions, true);
251         return target;
252     }
253 
254     //@Override
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         // Program
261         if (source.getProgram() != null) {
262             target.setProgram(programDao.toProgramVO(source.getProgram(),
263                     ProgramFetchOptions.builder().withProperties(false)
264                             .build()));
265         }
266 
267         // Vessel
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         // Recorder department
275         if (fetchOptions == null || fetchOptions.isWithRecorderDepartment()) {
276             DepartmentVO recorderDepartment = departmentDao.toDepartmentVO(source.getRecorderDepartment());
277             target.setRecorderDepartment(recorderDepartment);
278         }
279 
280         // Recorder person
281         if ((fetchOptions == null || fetchOptions.isWithRecorderPerson()) && source.getRecorderPerson() != null) {
282             PersonVO recorderPerson = personDao.toPersonVO(source.getRecorderPerson());
283             target.setRecorderPerson(recorderPerson);
284         }
285 
286         // Observers
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     //@Override
299     public V createVO() {
300         try {
301             return getVOClass().newInstance();
302         } catch (Exception e) {
303             throw new RuntimeException(e);
304         }
305     }
306 
307     //@Override
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     /* -- protected methods -- */
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 }