View Javadoc
1   package fr.ifremer.dali.dao.referential.taxon;
2   
3   /*
4    * #%L
5    * Dali :: Core
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2014 - 2015 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  import com.google.common.collect.*;
27  import fr.ifremer.dali.config.DaliConfiguration;
28  import fr.ifremer.dali.dao.referential.DaliReferentialDao;
29  import fr.ifremer.dali.dao.technical.Daos;
30  import fr.ifremer.dali.dto.DaliBeanFactory;
31  import fr.ifremer.dali.dto.referential.CitationDTO;
32  import fr.ifremer.dali.dto.referential.TaxonDTO;
33  import fr.ifremer.quadrige3.core.dao.referential.StatusCode;
34  import fr.ifremer.quadrige3.core.dao.referential.TaxonGroupTypeCode;
35  import fr.ifremer.quadrige3.core.dao.referential.taxon.TaxonNameDaoImpl;
36  import fr.ifremer.quadrige3.core.dao.technical.Dates;
37  import fr.ifremer.quadrige3.core.service.technical.CacheService;
38  import org.apache.commons.collections4.CollectionUtils;
39  import org.apache.commons.lang3.StringUtils;
40  import org.apache.commons.logging.Log;
41  import org.apache.commons.logging.LogFactory;
42  import org.hibernate.SessionFactory;
43  import org.hibernate.type.DateType;
44  import org.hibernate.type.IntegerType;
45  import org.hibernate.type.StringType;
46  import org.springframework.beans.factory.annotation.Autowired;
47  import org.springframework.cache.Cache;
48  import org.springframework.dao.DataRetrievalFailureException;
49  import org.springframework.stereotype.Repository;
50  
51  import javax.annotation.Nonnull;
52  import javax.annotation.Resource;
53  import java.time.LocalDate;
54  import java.util.*;
55  import java.util.stream.Collectors;
56  
57  /**
58   * <p>DaliTaxonNameDaoImpl class.</p>
59   *
60   */
61  @Repository("daliTaxonNameDao")
62  public class DaliTaxonNameDaoImpl extends TaxonNameDaoImpl implements DaliTaxonNameDao {
63  
64      private static final Log LOG = LogFactory.getLog(DaliTaxonNameDaoImpl.class);
65  
66      @Resource
67      protected CacheService cacheService;
68  
69      @Resource
70      protected DaliConfiguration config;
71  
72      @Resource(name = "daliReferentialDao")
73      private DaliReferentialDao referentialDao;
74  
75      @Resource(name = "daliTaxonNameDao")
76      private DaliTaxonNameDao loopbackTaxonNameDao;
77  
78      /**
79       * <p>Constructor for DaliTaxonNameDaoImpl.</p>
80       *
81       * @param sessionFactory a {@link org.hibernate.SessionFactory} object.
82       */
83      @Autowired
84      public DaliTaxonNameDaoImpl(SessionFactory sessionFactory) {
85          super(sessionFactory);
86      }
87  
88      /** {@inheritDoc} */
89      @Override
90      public List<TaxonDTO> getAllTaxonNames() {
91  
92          Cache cacheByReferenceId = cacheService.getCache(TAXON_NAME_BY_REFERENCE_ID_CACHE);
93          Cache cacheById = cacheService.getCache(TAXON_NAME_BY_ID_CACHE);
94  
95          Map<Integer, String> taxRefMap = loopbackTaxonNameDao.getTaxRefByTaxonNameId();
96          Map<Integer, String> wormsMap = loopbackTaxonNameDao.getWormsByTaxonNameId();
97  
98          Iterator<Object[]> it = queryIterator("allTaxonName");
99  
100         long nbTaxonName = 0;
101         long nbRefTaxon = 0;
102         List<TaxonDTO> result = new ArrayList<>();
103         while (it.hasNext()) {
104             Object[] source = it.next();
105             TaxonDTO taxon = toTaxonDTO(Arrays.asList(source).iterator());
106 
107             // add other references
108             taxon.setTaxRef(taxRefMap.get(taxon.getId()));
109             taxon.setWormsRef(wormsMap.get(taxon.getId()));
110 
111             result.add(taxon);
112 
113             // update cache by id
114             cacheById.put(taxon.getId(), taxon);
115             nbTaxonName++;
116             // update cache by reference id
117             if (taxon.isReferent()) {
118                 cacheByReferenceId.put(taxon.getReferenceTaxonId(), taxon);
119                 nbRefTaxon++;
120             }
121         }
122 
123         if (LOG.isDebugEnabled()) {
124             LOG.debug(String.format("%s Taxon name loaded, %s reference taxon loaded", nbTaxonName, nbRefTaxon));
125         }
126         return ImmutableList.copyOf(result);
127     }
128 
129     /** {@inheritDoc} */
130     @Override
131     public TaxonDTO getTaxonNameByReferenceId(int referenceTaxonId) {
132 
133         Object[] source = queryUnique("taxonNameByReferenceId", "taxonReferenceId", IntegerType.INSTANCE, referenceTaxonId);
134 
135         if (source == null) {
136             throw new DataRetrievalFailureException("Can't load taxon name with reference taxon id = " + referenceTaxonId);
137         }
138 
139         return toTaxonDTO(Arrays.asList(source).iterator());
140     }
141 
142     /** {@inheritDoc} */
143     @Override
144     public TaxonDTO getTaxonNameById(int taxonId) {
145 
146         Object[] source = queryUnique("taxonNameById", "taxonNameId", IntegerType.INSTANCE, taxonId);
147 
148         if (source == null) {
149             return null;
150         }
151 
152         TaxonDTO taxon = toTaxonDTO(Arrays.asList(source).iterator());
153         fillReferent(taxon);
154         return taxon;
155     }
156 
157     /** {@inheritDoc} */
158     @Override
159     public Multimap<Integer, TaxonDTO> getAllTaxonNamesMapByTaxonGroupId(@Nonnull LocalDate date) {
160 
161         Iterator<Object[]> it = queryIterator("taxonNameIdsWithTaxonGroupId",
162                 "referenceDate", DateType.INSTANCE, Dates.convertToDate(date, config.getDbTimezone()),
163                 "taxonGroupTypeCode", StringType.INSTANCE, TaxonGroupTypeCode.IDENTIFICATION.getValue());
164 
165         Multimap<Integer, TaxonDTO> result = ArrayListMultimap.create();
166         while (it.hasNext()) {
167             Object[] source = it.next();
168             Iterator<Object> row = Arrays.asList(source).iterator();
169             Integer taxonGroupId = (Integer) row.next();
170             result.put(taxonGroupId, loopbackTaxonNameDao.getTaxonNameById((Integer) row.next()));
171         }
172         return result;
173     }
174 
175     /** {@inheritDoc} */
176     @Override
177     public List<TaxonDTO> getTaxonNamesByIds(List<Integer> taxonIds) {
178 
179         if (CollectionUtils.isEmpty(taxonIds)) return new ArrayList<>();
180 
181         return loopbackTaxonNameDao.getAllTaxonNames().stream().filter(taxon -> taxonIds.contains(taxon.getId())).collect(Collectors.toList());
182     }
183 
184     /** {@inheritDoc} */
185     @Override
186     public void fillTaxonsProperties(List<TaxonDTO> taxons) {
187 
188         if (CollectionUtils.isEmpty(taxons)) {
189             return;
190         }
191 
192         Map<Integer, String> taxRefMap = loopbackTaxonNameDao.getTaxRefByTaxonNameId();
193         Map<Integer, String> wormsMap = loopbackTaxonNameDao.getWormsByTaxonNameId();
194 
195         for (TaxonDTO taxon : taxons) {
196 
197             // parent taxon and reference taxon
198             fillParentAndReferent(taxon);
199 
200             // composites
201             if (taxon.isVirtual()) {
202                 taxon.setCompositeTaxons(loopbackTaxonNameDao.getCompositeTaxonNames(taxon.getId()));
203             }
204 
205             // fill other references like (WORMS and TAXREFv80)
206             taxon.setTaxRef(taxRefMap.get(taxon.getId()));
207             taxon.setWormsRef(wormsMap.get(taxon.getId()));
208 
209         }
210     }
211 
212     private void fillTaxonProperties(TaxonDTO taxon) {
213 
214         // parent taxon and reference taxon
215         fillParentAndReferent(taxon);
216 
217         // fill other references like (WORMS and TAXREFv80)
218         taxon.setTaxRef(loopbackTaxonNameDao.getTaxRefByTaxonNameId().get(taxon.getId()));
219         taxon.setWormsRef(loopbackTaxonNameDao.getWormsByTaxonNameId().get(taxon.getId()));
220 
221     }
222 
223     /** {@inheritDoc} */
224     @Override
225     public List<TaxonDTO> findFullTaxonNamesByCriteria(String levelCode, String name, boolean isStrictName) {
226         List<TaxonDTO> result = findTaxonNamesByCriteria(levelCode, name, isStrictName);
227 
228         fillTaxonsProperties(result);
229 
230         return result;
231     }
232 
233     /** {@inheritDoc} */
234     @Override
235     public List<TaxonDTO> findTaxonNamesByCriteria(String levelCode, String name, boolean isStrictName) {
236 
237         List<TaxonDTO> result = new ArrayList<>();
238 
239         // for better performance if no parameter
240         if (StringUtils.isBlank(levelCode) && StringUtils.isBlank(name)) {
241 
242             result.addAll(loopbackTaxonNameDao.getAllTaxonNames());
243 
244         } else {
245 
246             Iterator<Object[]> it = queryIterator("taxonNamesByCriteria",
247                     "levelCd", StringType.INSTANCE, levelCode,
248                     "name", StringType.INSTANCE, isStrictName ? null : name,
249                     "strictName", StringType.INSTANCE, isStrictName ? name : null);
250 
251             while (it.hasNext()) {
252                 Object[] source = it.next();
253                 result.add(toTaxonDTO(Arrays.asList(source).iterator()));
254             }
255         }
256 
257         fillReferents(result);
258 
259         return ImmutableList.copyOf(result);
260     }
261 
262     /** {@inheritDoc} */
263     @Override
264     public List<TaxonDTO> getCompositeTaxonNames(Integer taxonNameId) {
265         Iterator<Object[]> it = queryIterator("compositeTaxonNamesByTaxonNameId",
266                 "taxonNameId", IntegerType.INSTANCE, taxonNameId);
267 
268         List<TaxonDTO> result = new ArrayList<>();
269         while (it.hasNext()) {
270             Object[] source = it.next();
271             TaxonDTO taxon = toTaxonDTO(Arrays.asList(source).iterator());
272             fillTaxonProperties(taxon);
273             result.add(taxon);
274         }
275         return result;
276     }
277 
278     /** {@inheritDoc} */
279     @Override
280     public Map<Integer, String> getTaxRefByTaxonNameId() {
281 
282         return getAlternateReferencesMap(config.getAlternativeTaxonOriginTaxRef());
283     }
284 
285     /** {@inheritDoc} */
286     @Override
287     public Map<Integer, String> getWormsByTaxonNameId() {
288 
289         return getAlternateReferencesMap(config.getAlternativeTaxonOriginWorms());
290     }
291 
292     private Map<Integer, String> getAlternateReferencesMap(String originCode) {
293 
294         Map<Integer, String> result = Maps.newHashMap();
295         if (StringUtils.isNotBlank(originCode)) {
296 
297             Iterator<Object[]> rows = queryIterator("alternateTaxonCode",
298                     "originCode", StringType.INSTANCE, originCode);
299 
300             while (rows.hasNext()) {
301                 Object[] row = rows.next();
302                 result.put((Integer) row[0], (String) row[1]);
303             }
304         }
305 
306         return result;
307     }
308 
309     // INTERNAL METHODS
310 
311     private TaxonDTO toTaxonDTO(Iterator<Object> source) {
312         TaxonDTO result = DaliBeanFactory.newTaxonDTO();
313 
314         // Id
315         result.setId((Integer) source.next());
316 
317         // Name (complete name)
318         result.setName((String) source.next());
319 
320         result.setComment((String) source.next());
321 
322         result.setReferent((Boolean) source.next());
323         result.setVirtual((Boolean) source.next());
324         result.setObsolete((Boolean) source.next());
325         result.setTemporary((Boolean) source.next());
326 
327         result.setReferenceTaxonId((Integer) source.next());
328         result.setParentTaxonId((Integer) source.next());
329 
330         String levelCode = (String) source.next();
331         Integer citationId = (Integer) source.next();
332         String citationName = (String) source.next();
333 
334         result.setCreationDate(Daos.convertToDate(source.next()));
335         result.setUpdateDate(Daos.convertToDate(source.next()));
336 
337         // taxonomic level
338         if (levelCode != null) {
339             result.setLevel(referentialDao.getTaxonomicLevelByCode(levelCode));
340         }
341 
342         // citation
343         if (citationId != null) {
344             CitationDTO citation = DaliBeanFactory.newCitationDTO();
345             citation.setId(citationId);
346             citation.setName(citationName);
347 
348             result.setCitation(citation);
349         }
350 
351         // Status
352         String statusCode = Boolean.TRUE.equals(result.isTemporary())
353                 ? StatusCode.TEMPORARY.getValue()
354                 : StatusCode.ENABLE.getValue();
355         result.setStatus(referentialDao.getStatusByCode(statusCode));
356 
357         return result;
358     }
359 
360     /** {@inheritDoc} */
361     @Override
362     public void fillParentAndReferent(TaxonDTO taxon) {
363 
364         // referent Taxon
365         fillReferent(taxon);
366 
367         // parent Taxon
368         if (taxon.getParentTaxonId() != null) {
369             if (taxon.getParentTaxonId().equals(taxon.getId())) {
370                 taxon.setParentTaxon(taxon);
371             } else {
372                 taxon.setParentTaxon(loopbackTaxonNameDao.getTaxonNameById(taxon.getParentTaxonId()));
373             }
374         }
375     }
376 
377     @Override
378     public void fillReferents(List<TaxonDTO> taxons) {
379 
380         if (taxons == null) return;
381         taxons.forEach(this::fillReferent);
382 
383     }
384 
385     private void fillReferent(TaxonDTO taxon) {
386 
387         // get referent taxon
388         if (taxon.getReferenceTaxon() == null || !Objects.equals(taxon.getReferenceTaxon().getId(), taxon.getReferenceTaxonId())) {
389             taxon.setReferenceTaxon(loopbackTaxonNameDao.getTaxonNameByReferenceId(taxon.getReferenceTaxonId()));
390         }
391     }
392 
393 }