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 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      /** Logger. */
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          // Fetch locations
88          //getEntityManager().enableFetchProfile("with-location");
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         // Add sorting
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         // Load parent entity
125         Trip parent = get(Trip.class, tripId);
126 
127         // Remember existing entities
128         final List<Integer> sourcesIdsToRemove = Beans.collectIds(Beans.getList(parent.getOperations()));
129 
130         // Save each gears
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         // Remove unused entities
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             // Check update date
163             checkUpdateDateForUpdate(source, entity);
164 
165             // Lock entityName
166             lockForUpdate(entity);
167         }
168 
169         // VO -> Entity
170         operationVOToEntity(source, entity, true);
171 
172         // Update update_dt
173         Timestamp newUpdateDate = getDatabaseCurrentTimestamp();
174         entity.setUpdateDate(newUpdateDate);
175 
176         // Save entityName
177         if (isNew) {
178             // Force id to null, to use the generator
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         //session.flush();
190         //session.clear();
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         // Trip
211         if (source.getTrip() != null) {
212             target.setTripId(source.getTrip().getId());
213         }
214 
215         // Quality flag
216         target.setQualityFlagId(source.getQualityFlag().getId());
217 
218         // Physical gear
219         if (source.getPhysicalGear() != null) {
220             target.setPhysicalGearId(source.getPhysicalGear().getId());
221             target.setPhysicalGear(physicalGearDao.toPhysicalGearVO(source.getPhysicalGear(), false/*no details*/));
222         }
223 
224         // Métier
225         if (source.getMetier() != null) {
226             target.setMetier(metierDao.toMetierVO(source.getMetier()));
227         }
228 
229         // Recorder department
230         DepartmentVO recorderDepartment = referentialDao.toTypedVO(source.getRecorderDepartment(), DepartmentVO.class).orElse(null);
231         target.setRecorderDepartment(recorderDepartment);
232 
233         return target;
234     }
235 
236     /* -- protected methods -- */
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         // Trip
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         // Recorder department
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         // Quality flag
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         // Métier
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         // Physical gear
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 }