1 package net.sumaris.core.dao.referential.taxon;
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 com.google.common.collect.ArrayListMultimap;
27 import com.google.common.collect.ImmutableList;
28 import com.google.common.collect.Multimap;
29 import net.sumaris.core.dao.referential.PmfmDao;
30 import net.sumaris.core.dao.referential.ReferentialDao;
31 import net.sumaris.core.dao.referential.ReferentialSpecifications;
32 import net.sumaris.core.dao.technical.SortDirection;
33 import net.sumaris.core.dao.technical.jpa.SumarisJpaRepositoryImpl;
34 import net.sumaris.core.model.referential.pmfm.PmfmEnum;
35 import net.sumaris.core.model.referential.pmfm.QualitativeValue;
36 import net.sumaris.core.model.referential.taxon.TaxonGroup;
37 import net.sumaris.core.model.referential.taxon.TaxonGroupHistoricalRecord;
38 import net.sumaris.core.model.referential.taxon.TaxonGroupTypeId;
39 import net.sumaris.core.model.referential.taxon.TaxonName;
40 import net.sumaris.core.model.technical.optimization.taxon.TaxonGroup2TaxonHierarchy;
41 import net.sumaris.core.model.technical.optimization.taxon.TaxonGroupHierarchy;
42 import net.sumaris.core.util.Beans;
43 import net.sumaris.core.vo.filter.ReferentialFilterVO;
44 import net.sumaris.core.vo.referential.PmfmVO;
45 import net.sumaris.core.vo.referential.ReferentialVO;
46 import net.sumaris.core.vo.referential.TaxonGroupVO;
47 import net.sumaris.core.vo.referential.TaxonNameVO;
48 import org.apache.commons.collections4.CollectionUtils;
49 import org.apache.commons.lang3.StringUtils;
50 import org.apache.commons.lang3.mutable.MutableInt;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53 import org.springframework.beans.factory.annotation.Autowired;
54 import org.springframework.dao.DataRetrievalFailureException;
55 import org.springframework.data.domain.Sort;
56 import org.springframework.data.jpa.domain.Specification;
57
58 import javax.persistence.EntityManager;
59 import javax.persistence.Parameter;
60 import javax.persistence.TemporalType;
61 import javax.persistence.TypedQuery;
62 import javax.persistence.criteria.CriteriaQuery;
63 import java.util.Date;
64 import java.util.List;
65 import java.util.stream.Collectors;
66
67 import static net.sumaris.core.dao.referential.taxon.TaxonGroupSpecifications.*;
68
69 public class TaxonGroupRepositoryImpl
70 extends SumarisJpaRepositoryImpl<TaxonGroup, Integer>
71 implements TaxonGroupRepositoryExtend {
72
73
74 private static final Logger log =
75 LoggerFactory.getLogger(TaxonGroupRepositoryImpl.class);
76
77 @Autowired
78 private TaxonNameDao taxonNameDao;
79
80 @Autowired
81 private ReferentialDao referentialDao;
82
83 @Autowired
84 private PmfmDao pmfmDao;
85
86 public TaxonGroupRepositoryImpl(EntityManager entityManager) {
87 super(TaxonGroup.class, entityManager);
88 }
89
90 @Override
91 public List<TaxonGroupVO> findTargetSpeciesByFilter(
92 ReferentialFilterVO filter,
93 int offset,
94 int size,
95 String sortAttribute,
96 SortDirection sortDirection) {
97
98 Preconditions.checkNotNull(filter);
99 Integer[] gearIds = (filter.getLevelId() != null) ? new Integer[]{filter.getLevelId()} :
100 filter.getLevelIds();
101
102 Specification<TaxonGroup> specification = Specification.where(
103 ReferentialSpecifications.<TaxonGroup>searchText(filter.getSearchAttribute(), "searchText"))
104 .and(hasType(TaxonGroupTypeId.METIER_SPECIES.getId()))
105 .and(inStatusIds(filter.getStatusIds()))
106 .and(inGearIds(gearIds));
107
108 String searchText = StringUtils.isBlank(filter.getSearchText()) ? null : (filter.getSearchText() + "*")
109 .replaceAll("[*]+", "*")
110 .replaceAll("[%]", "\\%")
111 .replaceAll("[*]", "%");
112
113 TypedQuery<TaxonGroup> query = getQuery(specification, TaxonGroup.class, getPageable(offset, size, sortAttribute, sortDirection));
114
115 Parameter<String> searchTextParam = query.getParameter("searchText", String.class);
116 if (searchTextParam != null) {
117 query.setParameter(searchTextParam, searchText);
118 }
119
120 return query.getResultStream()
121 .distinct()
122 .map(this::toTaxonGroupVO)
123 .collect(Collectors.toList());
124 }
125
126
127 @Override
128 public TaxonGroupVO toTaxonGroupVO(TaxonGroup source) {
129 TaxonGroupVOial/TaxonGroupVO.html#TaxonGroupVO">TaxonGroupVO target = new TaxonGroupVO();
130
131 Beans.copyProperties(source, target);
132
133
134 target.setStatusId(source.getStatus().getId());
135
136 return target;
137 }
138
139 @Override
140 public long countTaxonGroupHierarchy() {
141 return (Long)getEntityManager().createQuery("select count(*) from TaxonGroupHierarchy").getSingleResult();
142 }
143
144 @Override
145 public void updateTaxonGroupHierarchies() {
146 if (log.isInfoEnabled()) {
147 log.info("Updating technical tables {TAXON_GROUP_HIERARCHY} and {TAXON_GROUP2TAXON_HIERARCHY}...");
148 }
149 updateTaxonGroupHierarchy();
150 updateTaxonGroup2TaxonHierarchy();
151 }
152
153 @Override
154 public void updateTaxonGroupHierarchy() {
155 final EntityManager em = getEntityManager();
156
157
158 final Multimap<Integer, Integer> existingLinkToRemove = ArrayListMultimap.create();
159 CriteriaQuery<TaxonGroupHierarchy> query = em.getCriteriaBuilder().createQuery(TaxonGroupHierarchy.class);
160 query.from(TaxonGroupHierarchy.class);
161 em.createQuery(query).getResultStream()
162 .forEach(th -> existingLinkToRemove.put(th.getParentTaxonGroup().getId(), th.getChildTaxonGroup().getId()));
163
164 final MutableInt insertCounter = new MutableInt();
165
166
167 findAll(Sort.by(TaxonGroup.Fields.ID))
168 .stream()
169 .forEach(tg -> {
170 Integer childId = tg.getId();
171
172 if (!existingLinkToRemove.remove(childId, childId)) {
173 TaxonGroupHierarchy/optimization/taxon/TaxonGroupHierarchy.html#TaxonGroupHierarchy">TaxonGroupHierarchy tgh = new TaxonGroupHierarchy();
174 tgh.setParentTaxonGroup(load(TaxonGroup.class, childId));
175 tgh.setChildTaxonGroup(load(TaxonGroup.class, childId));
176 em.persist(tgh);
177 insertCounter.increment();
178 }
179
180 TaxonGroup parent = tg.getParentTaxonGroup();
181 while (parent != null) {
182 if (!existingLinkToRemove.remove(parent.getId(), childId)) {
183 TaxonGroupHierarchy/optimization/taxon/TaxonGroupHierarchy.html#TaxonGroupHierarchy">TaxonGroupHierarchy tgh = new TaxonGroupHierarchy();
184 tgh.setParentTaxonGroup(load(TaxonGroup.class, parent.getId()));
185 tgh.setChildTaxonGroup(load(TaxonGroup.class, childId));
186 em.persist(tgh);
187 insertCounter.increment();
188 }
189 parent = parent.getParentTaxonGroup();
190 }
191 });
192
193 em.flush();
194 em.clear();
195
196
197 final MutableInt deleteCounter = new MutableInt();
198 if (!existingLinkToRemove.isEmpty()) {
199 existingLinkToRemove.entries().forEach(entry -> {
200 int deletedRowCount = em.createQuery("delete from TaxonGroupHierarchy where parentTaxonGroup.id=:parentId and childTaxonGroup.id=:childId")
201 .setParameter("parentId", entry.getKey())
202 .setParameter("childId", entry.getValue())
203 .executeUpdate();
204 deleteCounter.add(deletedRowCount);
205 });
206 }
207
208 log.info(String.format("Technical table TAXON_GROUP_HISTORY successfully updated. (inserts: %s, deletes: %s)",
209 insertCounter.getValue(), deleteCounter.getValue()));
210 }
211
212 @Override
213 public void updateTaxonGroup2TaxonHierarchy() {
214 final EntityManager em = getEntityManager();
215
216
217 final Multimap<Integer, Integer> existingLinkToRemove = ArrayListMultimap.create();
218 {
219 CriteriaQuery<TaxonGroup2TaxonHierarchy> query = em.getCriteriaBuilder().createQuery(TaxonGroup2TaxonHierarchy.class);
220 query.from(TaxonGroup2TaxonHierarchy.class);
221 em.createQuery(query).getResultStream()
222 .forEach(th -> existingLinkToRemove.put(th.getParentTaxonGroup().getId(), th.getChildReferenceTaxon().getId()));
223 }
224
225
226 final MutableInt insertCounter = new MutableInt();
227 {
228 CriteriaQuery<TaxonGroupHistoricalRecord> query = em.getCriteriaBuilder().createQuery(TaxonGroupHistoricalRecord.class);
229 query.from(TaxonGroupHistoricalRecord.class);
230 em.createQuery(query).getResultStream()
231 .forEach(history -> {
232 Integer parentId = history.getTaxonGroup().getId();
233 Integer childId = history.getReferenceTaxon().getId();
234
235 if (!existingLinkToRemove.remove(parentId, childId)) {
236 TaxonGroup2TaxonHierarchyn/taxon/TaxonGroup2TaxonHierarchy.html#TaxonGroup2TaxonHierarchy">TaxonGroup2TaxonHierarchy hierarchy = new TaxonGroup2TaxonHierarchy();
237 hierarchy.setParentTaxonGroup(history.getTaxonGroup());
238 hierarchy.setChildReferenceTaxon(history.getReferenceTaxon());
239 hierarchy.setStartDate(history.getStartDate());
240 hierarchy.setEndDate(history.getEndDate());
241 hierarchy.setIsInherited(false);
242 em.persist(hierarchy);
243 insertCounter.increment();
244 }
245
246 TaxonNameVO parent = taxonNameDao.getTaxonNameReferent(childId);
247 List<TaxonName> children = taxonNameDao.getAllTaxonNameByParentIds(ImmutableList.of(parent.getId()));
248 while (CollectionUtils.isNotEmpty(children)) {
249 children.forEach(child -> {
250 Integer inheritedChildId = child.getReferenceTaxon().getId();
251 if (!existingLinkToRemove.remove(parentId, inheritedChildId)) {
252 TaxonGroup2TaxonHierarchyn/taxon/TaxonGroup2TaxonHierarchy.html#TaxonGroup2TaxonHierarchy">TaxonGroup2TaxonHierarchy hierarchy = new TaxonGroup2TaxonHierarchy();
253 hierarchy.setParentTaxonGroup(history.getTaxonGroup());
254 hierarchy.setChildReferenceTaxon(child.getReferenceTaxon());
255 hierarchy.setStartDate(history.getStartDate());
256 hierarchy.setEndDate(history.getEndDate());
257 hierarchy.setIsInherited(true);
258 em.persist(hierarchy);
259 insertCounter.increment();
260 }
261 });
262 children = taxonNameDao.getAllTaxonNameByParentIds(
263 children.stream()
264 .map(TaxonName::getId)
265 .collect(Collectors.toList()));
266 }
267 });
268 }
269
270 em.flush();
271 em.clear();
272
273
274 final MutableInt deleteCounter = new MutableInt();
275 if (!existingLinkToRemove.isEmpty()) {
276 existingLinkToRemove.entries().forEach(entry -> {
277 int nbRow = em.createQuery("delete from TaxonGroup2TaxonHierarchy where parentTaxonGroup.id=:parentId and childReferenceTaxon.id=:childId")
278 .setParameter("parentId", entry.getKey())
279 .setParameter("childId", entry.getValue())
280 .executeUpdate();
281 deleteCounter.add(nbRow);
282 });
283 }
284
285 log.info(String.format("Technical table TAXON_GROUP2TAXON_HISTORY successfully updated. (inserts: %s, deletes: %s)",
286 insertCounter.getValue(), deleteCounter.getValue()));
287 }
288
289 @Override
290 public List<ReferentialVO> getAllDressingByTaxonGroupId(int taxonGroupId, Date startDate, Date endDate, int locationId) {
291 Preconditions.checkNotNull(startDate);
292
293 List<ReferentialVO> result = getEntityManager()
294 .createNamedQuery("RoundWeightConversion.dressingByTaxonGroupId", QualitativeValue.class)
295 .setParameter("taxonGroupId", taxonGroupId)
296 .setParameter("startDate", startDate, TemporalType.DATE)
297
298 .setParameter("endDate", endDate != null ? endDate : startDate, TemporalType.DATE)
299 .setParameter("locationId", locationId)
300 .getResultStream()
301 .map(p -> referentialDao.toReferentialVO(p))
302 .collect(Collectors.toList());
303
304 if (CollectionUtils.isNotEmpty(result)) {
305 return result;
306 }
307
308
309 PmfmVO pmfm = pmfmDao.get(PmfmEnum.DRESSING.getId());
310 if (pmfm == null) {
311 throw new DataRetrievalFailureException("PMFM for dressing not found");
312 }
313 return pmfm.getQualitativeValues();
314
315 }
316
317 @Override
318 public List<ReferentialVO> getAllPreservingByTaxonGroupId(int taxonGroupId, Date startDate, Date endDate, int locationId) {
319 Preconditions.checkNotNull(startDate);
320
321 List<ReferentialVO> result = getEntityManager()
322 .createNamedQuery("RoundWeightConversion.preservingByTaxonGroupId", QualitativeValue.class)
323 .setParameter("taxonGroupId", taxonGroupId)
324 .setParameter("startDate", startDate, TemporalType.DATE)
325
326 .setParameter("endDate", endDate != null ? endDate : startDate, TemporalType.DATE)
327 .setParameter("locationId", locationId)
328 .getResultStream()
329 .map(p -> referentialDao.toReferentialVO(p))
330 .collect(Collectors.toList());
331
332 if (CollectionUtils.isNotEmpty(result)) {
333 return result;
334 }
335
336
337 PmfmVO pmfm = pmfmDao.get(PmfmEnum.PRESERVATION.getId());
338 if (pmfm == null) {
339 throw new DataRetrievalFailureException("PMFM for preservation not found");
340 }
341 return pmfm.getQualitativeValues();
342 }
343 }