View Javadoc
1   package net.sumaris.core.dao.administration.user;
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.util.Beans;
27  import net.sumaris.core.dao.technical.SortDirection;
28  import net.sumaris.core.dao.technical.hibernate.HibernateDaoSupport;
29  import net.sumaris.core.model.administration.user.Department;
30  import net.sumaris.core.model.data.ImageAttachment;
31  import net.sumaris.core.model.referential.IReferentialEntity;
32  import net.sumaris.core.model.referential.Status;
33  import net.sumaris.core.vo.administration.user.DepartmentVO;
34  import net.sumaris.core.vo.filter.DepartmentFilterVO;
35  import org.apache.commons.collections4.CollectionUtils;
36  import org.apache.commons.lang3.StringUtils;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  import org.springframework.dao.EmptyResultDataAccessException;
40  import org.springframework.stereotype.Repository;
41  
42  import javax.persistence.EntityManager;
43  import javax.persistence.LockModeType;
44  import javax.persistence.NoResultException;
45  import javax.persistence.criteria.*;
46  import java.sql.Timestamp;
47  import java.util.Collection;
48  import java.util.List;
49  import java.util.Objects;
50  import java.util.stream.Collectors;
51  import java.util.stream.Stream;
52  
53  @Repository("departmentDao")
54  public class DepartmentDaoImpl extends HibernateDaoSupport implements DepartmentDao {
55  
56      /** Logger. */
57      private static final Logger log =
58              LoggerFactory.getLogger(DepartmentDaoImpl.class);
59  
60      @Override
61      public List<DepartmentVO> findByFilter(DepartmentFilterVO filter, int offset, int size, String sortAttribute, SortDirection sortDirection) {
62          Preconditions.checkNotNull(filter);
63          Preconditions.checkArgument(offset >= 0);
64          Preconditions.checkArgument(size > 0);
65  
66          List<Integer> statusIds = CollectionUtils.isEmpty(filter.getStatusIds()) ?
67                  null : filter.getStatusIds();
68  
69          EntityManager entityManager = getEntityManager();
70          CriteriaBuilder builder = entityManager.getCriteriaBuilder();
71          CriteriaQuery<Department> query = builder.createQuery(Department.class);
72          Root<Department> root = query.from(Department.class);
73  
74          Join<Department, Status> statusJoin = root.join(Department.Fields.STATUS, JoinType.INNER);
75          Join<Department, ImageAttachment> logoJoin = root.join(Department.Fields.LOGO, JoinType.LEFT);
76  
77          ParameterExpression<Boolean> hasStatusIdsParam = builder.parameter(Boolean.class);
78          ParameterExpression<Collection> statusIdsParam = builder.parameter(Collection.class);
79          ParameterExpression<Boolean> withLogoParam = builder.parameter(Boolean.class);
80  
81          query.select(root)
82                  .where(
83                          builder.and(
84                                  // status Id
85                                  builder.or(
86                                      builder.isFalse(hasStatusIdsParam),
87                                      builder.in(statusJoin.get(IReferentialEntity.Fields.ID)).value(statusIdsParam)
88                                  ),
89                                  // with logo
90                                  builder.or(
91                                          builder.isNull(withLogoParam),
92                                          builder.isNotNull(logoJoin.get(IReferentialEntity.Fields.ID))
93                                  )
94                          ));
95  
96          if (StringUtils.isNotBlank(sortAttribute)) {
97              if (sortDirection == SortDirection.ASC) {
98                  query.orderBy(builder.asc(root.get(sortAttribute)));
99              } else {
100                 query.orderBy(builder.desc(root.get(sortAttribute)));
101             }
102         }
103 
104         return entityManager.createQuery(query)
105                 .setParameter(hasStatusIdsParam, CollectionUtils.isNotEmpty(statusIds))
106                 .setParameter(statusIdsParam, statusIds)
107                 .setParameter(withLogoParam, isTrueOrNull(filter.getWithLogo()))
108                 .setFirstResult(offset)
109                 .setMaxResults(size)
110                 .getResultList()
111                 .stream()
112                 .map(this::toDepartmentVO)
113                 .filter(Objects::nonNull)
114                 //FIXME: this failed in unitre test DepartmentServiceTest
115                 // .sorted(Beans.naturalComparator(sortAttribute, sortDirection))
116                 .collect(Collectors.toList());
117     }
118 
119     @Override
120     public DepartmentVO get(int id) {
121         return toDepartmentVO(get(Department.class, id));
122     }
123 
124     @Override
125     public Department getByLabelOrNull(final String label) {
126 
127         EntityManager entityManager = getEntityManager();
128         CriteriaBuilder builder = entityManager.getCriteriaBuilder();
129         CriteriaQuery<Department> query = builder.createQuery(Department.class);
130         Root<Department> root = query.from(Department.class);
131 
132         ParameterExpression<String> labelParam = builder.parameter(String.class);
133 
134         query.select(root)
135                 .where(builder.equal(root.get(Department.Fields.LABEL), labelParam));
136 
137         try {
138             return entityManager.createQuery(query)
139                     .setParameter(labelParam, label)
140                     .getSingleResult();
141         } catch (EmptyResultDataAccessException | NoResultException e) {
142             return null;
143         }
144     }
145 
146     @Override
147     public DepartmentVO./../../../../../net/sumaris/core/vo/administration/user/DepartmentVO.html#DepartmentVO">DepartmentVO save(DepartmentVO source) {
148         Preconditions.checkNotNull(source);
149         Preconditions.checkNotNull(source.getLabel());
150         Preconditions.checkNotNull(source.getName());
151         Preconditions.checkNotNull(source.getSiteUrl());
152 
153         EntityManager entityManager = getEntityManager();
154         Department entity = null;
155         if (source.getId() != null) {
156             entity = entityManager.find(Department.class, source.getId());
157         }
158         boolean isNew = (entity == null);
159         if (isNew) {
160             entity = new Department();
161         }
162 
163         if (!isNew) {
164             // Check update date
165             checkUpdateDateForUpdate(source, entity);
166 
167             // Lock entityName
168             lockForUpdate(entity, LockModeType.PESSIMISTIC_WRITE);
169         }
170 
171         departmentVOToEntity(source, entity, true);
172 
173         // Update update_dt
174         Timestamp newUpdateDate = getDatabaseCurrentTimestamp();
175         entity.setUpdateDate(newUpdateDate);
176 
177         // Save entityName
178         if (isNew) {
179             // Force creation date
180             entity.setCreationDate(newUpdateDate);
181             source.setCreationDate(newUpdateDate);
182 
183             entityManager.persist(entity);
184             source.setId(entity.getId());
185         } else {
186             entityManager.merge(entity);
187         }
188 
189         source.setUpdateDate(newUpdateDate);
190 
191         getEntityManager().flush();
192         getEntityManager().clear();
193 
194         return source;
195     }
196 
197     @Override
198     public void delete(int id) {
199 
200         log.debug(String.format("Deleting department {id=%s}...", id));
201         delete(Department.class, id);
202     }
203 
204     @Override
205     public DepartmentVO toDepartmentVO(Department source) {
206         if (source == null) return null;
207         DepartmentVOration/user/DepartmentVO.html#DepartmentVO">DepartmentVO target = new DepartmentVO();
208 
209         Beans.copyProperties(source, target);
210 
211         // Status
212         target.setStatusId(source.getStatus().getId());
213 
214         // Has logo
215         target.setHasLogo(source.getLogo() != null);
216 
217         return target;
218     }
219 
220     /* -- protected methods -- */
221 
222     protected List<DepartmentVO> toDepartmentVOs(List<Department> source) {
223         return source.stream()
224                 .map(this::toDepartmentVO)
225                 .filter(Objects::nonNull)
226                 .collect(Collectors.toList());
227     }
228 
229     protected List<DepartmentVO> toDepartmentVOs(Stream<Department> source, String sortAttribute, SortDirection sortDirection) {
230         return source
231                 .map(this::toDepartmentVO)
232                 .filter(Objects::nonNull)
233                 .sorted(Beans.naturalComparator(sortAttribute, sortDirection))
234                 .collect(Collectors.toList());
235     }
236 
237     protected void departmentVOToEntity(DepartmentVO source, Department target, boolean copyIfNull) {
238 
239         Beans.copyProperties(source, target);
240 
241         // Status
242         if (copyIfNull || source.getStatusId() != null) {
243             if (source.getStatusId() == null) {
244                 target.setStatus(null);
245             }
246             else {
247                 target.setStatus(load(Status.class, source.getStatusId()));
248             }
249         }
250     }
251 
252     private Boolean isTrueOrNull(Boolean value) {
253         return Boolean.TRUE.equals(value) ? value : null;
254     }
255 
256 }