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.dao.referential.DaliReferentialDao;
28  import fr.ifremer.quadrige3.core.dao.referential.StatusCode;
29  import fr.ifremer.quadrige3.core.dao.referential.TaxonGroupTypeCode;
30  import fr.ifremer.quadrige3.core.dao.referential.taxon.TaxonGroupDaoImpl;
31  import fr.ifremer.quadrige3.core.service.technical.CacheService;
32  import fr.ifremer.dali.dao.technical.Daos;
33  import fr.ifremer.dali.dto.DaliBeanFactory;
34  import fr.ifremer.dali.dto.DaliBeans;
35  import fr.ifremer.dali.dto.referential.TaxonDTO;
36  import fr.ifremer.dali.dto.referential.TaxonGroupDTO;
37  import org.apache.commons.collections4.CollectionUtils;
38  import org.hibernate.Query;
39  import org.hibernate.SessionFactory;
40  import org.hibernate.type.IntegerType;
41  import org.hibernate.type.StringType;
42  import org.springframework.beans.factory.annotation.Autowired;
43  import org.springframework.cache.Cache;
44  import org.springframework.cache.interceptor.SimpleKey;
45  import org.springframework.dao.DataRetrievalFailureException;
46  import org.springframework.stereotype.Repository;
47  
48  import javax.annotation.Resource;
49  import java.time.LocalDate;
50  import java.util.*;
51  import java.util.stream.Collectors;
52  
53  /**
54   * <p>DaliTaxonGroupDaoImpl class.</p>
55   *
56   */
57  @Repository("daliTaxonGroupDao")
58  public class DaliTaxonGroupDaoImpl extends TaxonGroupDaoImpl implements DaliTaxonGroupDao {
59  
60      @Resource
61      protected CacheService cacheService;
62  
63      @Resource(name = "daliTaxonNameDao")
64      private DaliTaxonNameDao taxonNameDao;
65      @Resource(name = "daliTaxonGroupDao")
66      private DaliTaxonGroupDao loopbackTaxonGroupDao;
67      @Resource(name = "daliReferentialDao")
68      protected DaliReferentialDao referentialDao;
69  
70      /**
71       * <p>Constructor for DaliTaxonGroupDaoImpl.</p>
72       *
73       * @param sessionFactory a {@link org.hibernate.SessionFactory} object.
74       */
75      @Autowired
76      public DaliTaxonGroupDaoImpl(SessionFactory sessionFactory) {
77          super(sessionFactory);
78      }
79  
80      /** {@inheritDoc} */
81      @Override
82      public List<TaxonGroupDTO> getAllTaxonGroups() {
83  
84          // get all needed cache to update
85          Cache cacheById = cacheService.getCache(TAXON_GROUP_BY_ID_CACHE);
86          Cache allTaxonNamesCache = cacheService.getCache(DaliTaxonNameDao.ALL_TAXON_NAMES_CACHE);
87          Cache taxonCache = cacheService.getCache(DaliTaxonNameDao.TAXON_NAME_BY_ID_CACHE);
88          Cache referenceTaxonCache = cacheService.getCache(DaliTaxonNameDao.TAXON_NAME_BY_REFERENCE_ID_CACHE);
89          Cache taxonNameByTaxonGroupIdCache = cacheService.getCache(DaliTaxonNameDao.TAXON_NAME_BY_TAXON_GROUP_ID_CACHE);
90  
91          // get all taxon names
92          List<TaxonDTO> allTaxonNames = taxonNameDao.getAllTaxonNames();
93          // get all taxon names map
94          LocalDate taxonRefDate = LocalDate.now();
95          Multimap<Integer, TaxonDTO> taxonMap = taxonNameDao.getAllTaxonNamesMapByTaxonGroupId(taxonRefDate);
96  
97          Query query = createQuery("allTaxonGroup",
98                  "taxonGroupTypeCode", StringType.INSTANCE, TaxonGroupTypeCode.IDENTIFICATION.getValue());
99          Iterator<Object[]> it = Daos.queryIteratorWithStatus(query,
100                 ImmutableList.of(StatusCode.ENABLE.getValue(), StatusCode.TEMPORARY.getValue()));
101 
102         // TODO : control TAXON_GROUP_EXCLUS, TAXON_GROUP_UPDATE ?
103         List<TaxonGroupDTO> result = new ArrayList<>();
104         while (it.hasNext()) {
105             Object[] source = it.next();
106             TaxonGroupDTO taxonGroup = toTaxonGroupDTO(Arrays.asList(source).iterator());
107 
108             // Clone this taxon group and remove parent & children
109             TaxonGroupDTO lightTaxonGroup = getLightTaxonGroup(taxonGroup);
110 
111             // add this taxon group to all taxon
112             Collection<TaxonDTO> taxons = taxonMap.get(taxonGroup.getId());
113             for (TaxonDTO taxon : taxons) {
114 
115                 // add this taxon group
116                 if (!taxon.containsTaxonGroups(lightTaxonGroup)) {
117                     taxon.addTaxonGroups(lightTaxonGroup);
118                 }
119 
120                 // need to update taxonNameById cache
121                 {
122                     TaxonDTO cachedTaxon = taxonCache.get(taxon.getId(), TaxonDTO.class);
123                     if (cachedTaxon != null && !cachedTaxon.containsTaxonGroups(lightTaxonGroup)) {
124                         cachedTaxon.addTaxonGroups(lightTaxonGroup);
125                         taxonCache.evict(taxon.getId());
126                         taxonCache.put(taxon.getId(), cachedTaxon);
127                     }
128                 }
129 
130                 // need to update reference taxon cache
131                 {
132                     TaxonDTO cachedReferenceTaxon = referenceTaxonCache.get(taxon.getReferenceTaxonId(), TaxonDTO.class);
133                     if (cachedReferenceTaxon != null && !cachedReferenceTaxon.containsTaxonGroups(lightTaxonGroup)) {
134                         cachedReferenceTaxon.addTaxonGroups(lightTaxonGroup);
135                         referenceTaxonCache.evict(taxon.getReferenceTaxonId());
136                         referenceTaxonCache.put(taxon.getReferenceTaxonId(), cachedReferenceTaxon);
137                     }
138                 }
139 
140                 // need to update allTaxonNames cache also
141                 {
142                     TaxonDTO cachedTaxon = DaliBeans.findById(allTaxonNames, taxon.getId());
143                     if (!cachedTaxon.containsTaxonGroups(lightTaxonGroup)) {
144                         cachedTaxon.addTaxonGroups(lightTaxonGroup);
145                     }
146                 }
147 
148                 // add taxon parent and referent
149                 taxonNameDao.fillParentAndReferent(taxon);
150             }
151 
152             // add taxon names
153             taxonGroup.addAllTaxons(taxons);
154 
155             // add to cache by id
156             cacheById.put(taxonGroup.getId(), taxonGroup);
157 
158             result.add(taxonGroup);
159         }
160 
161         // update taxonNameByTaxonGroupId cache
162         taxonNameByTaxonGroupIdCache.clear();
163         taxonNameByTaxonGroupIdCache.put(taxonRefDate, taxonMap);
164 
165         // update allTaxonNames cache
166         allTaxonNamesCache.put(SimpleKey.EMPTY, allTaxonNames);
167 
168         return ImmutableList.copyOf(result);
169     }
170 
171     /** {@inheritDoc} */
172     @Override
173     public TaxonGroupDTO getTaxonGroupById(int taxonGroupId) {
174 
175         // TODO : control TAXON_GROUP_EXCLUS, TAXON_GROUP_UPDATE ?
176         Object[] source = queryUnique("taxonGroupById", "taxonGroupId", IntegerType.INSTANCE, taxonGroupId);
177 
178         if (source == null) {
179             throw new DataRetrievalFailureException("can't load taxon group with id = " + taxonGroupId);
180         }
181 
182         TaxonGroupDTO taxonGroup = toTaxonGroupDTO(Arrays.asList(source).iterator());
183 
184         // Clone this taxon group and remove parent & children
185         TaxonGroupDTO lightTaxonGroup = getLightTaxonGroup(taxonGroup);
186 
187         Collection<TaxonDTO> taxons = taxonNameDao.getAllTaxonNamesMapByTaxonGroupId(LocalDate.now()).get(taxonGroupId);
188         for (TaxonDTO taxon : taxons) {
189             if (!taxon.containsTaxonGroups(lightTaxonGroup)) {
190                 taxon.addTaxonGroups(lightTaxonGroup);
191             }
192         }
193 
194         taxonGroup.addAllTaxons(taxons);
195         return taxonGroup;
196     }
197 
198     /** {@inheritDoc} */
199     @Override
200     public List<TaxonGroupDTO> getTaxonGroupsByIds(List<Integer> taxonGroupIds) {
201 
202         if (CollectionUtils.isEmpty(taxonGroupIds)) return new ArrayList<>();
203 
204         return loopbackTaxonGroupDao.getAllTaxonGroups().stream().filter(taxonGroup -> taxonGroupIds.contains(taxonGroup.getId())).collect(Collectors.toList());
205     }
206 
207     /** {@inheritDoc} */
208     @Override
209     public List<TaxonGroupDTO> findTaxonGroups(Integer parentTaxonGroupId, String label, String name, boolean isStrictName, List<String> statusCodes) {
210         // get all taxon names map
211         Multimap<Integer, TaxonDTO> taxonMap = taxonNameDao.getAllTaxonNamesMapByTaxonGroupId(LocalDate.now());
212 
213         Query query = createQuery("taxonGroupsByCriteria",
214                 "parentTaxonGroupId", IntegerType.INSTANCE, parentTaxonGroupId,
215                 "label", StringType.INSTANCE, label,
216                 "name", StringType.INSTANCE, isStrictName ? null : name,
217                 "strictName", StringType.INSTANCE, isStrictName ? name : null,
218                 "taxonGroupTypeCode", StringType.INSTANCE, TaxonGroupTypeCode.IDENTIFICATION.getValue());
219 
220         Iterator<Object[]> it = Daos.queryIteratorWithStatus(query, statusCodes);
221 
222         List<TaxonGroupDTO> result = new ArrayList<>();
223         while (it.hasNext()) {
224             Object[] source = it.next();
225             TaxonGroupDTO taxonGroup = toTaxonGroupDTO(Arrays.asList(source).iterator());
226             TaxonGroupDTO lightTaxonGroup = getLightTaxonGroup(taxonGroup);
227 
228             // add this taxon group to all taxon
229             Collection<TaxonDTO> taxons = taxonMap.get(taxonGroup.getId());
230             for (TaxonDTO taxon : taxons) {
231                 if (!taxon.containsTaxonGroups(lightTaxonGroup)) {
232                     taxon.addTaxonGroups(lightTaxonGroup);
233                 }
234             }
235 
236             taxonGroup.addAllTaxons(taxons);
237             result.add(taxonGroup);
238         }
239 
240         // Mantis #0027042: when parentTaxonGroupId is set, do a recursive search to populate sub groups
241         if (CollectionUtils.isNotEmpty(result) && parentTaxonGroupId != null) {
242             Set<TaxonGroupDTO> subTaxonGroups = Sets.newHashSet();
243             for (TaxonGroupDTO taxonGroup : result) {
244                 // populate sub groups
245                 subTaxonGroups.addAll(findTaxonGroups(taxonGroup.getId(), label, name, isStrictName, statusCodes));
246             }
247             result.addAll(subTaxonGroups);
248         }
249 
250         return ImmutableList.copyOf(result);
251     }
252 
253     private TaxonGroupDTO toTaxonGroupDTO(Iterator<Object> source) {
254         TaxonGroupDTO result = DaliBeanFactory.newTaxonGroupDTO();
255         result.setId((Integer) source.next());
256         result.setLabel((String) source.next());
257         result.setName((String) source.next());
258         result.setComment((String) source.next());
259         result.setExclusive(Daos.safeConvertToBoolean(source.next()));
260         result.setUpdate(Daos.safeConvertToBoolean(source.next()));
261         result.setType((String) source.next());
262 
263         // parent
264         Integer parentId = (Integer) source.next();
265         String parentLabel = (String) source.next();
266         String parentName = (String) source.next();
267 
268         if (parentId != null) {
269             TaxonGroupDTO parent = DaliBeanFactory.newTaxonGroupDTO();
270             parent.setId(parentId);
271             parent.setLabel(parentLabel);
272             parent.setName(parentName);
273 
274             result.setParentTaxonGroup(parent);
275         }
276 
277         result.setStatus(referentialDao.getStatusByCode((String) source.next()));
278         result.setCreationDate(Daos.convertToDate(source.next()));
279         result.setUpdateDate(Daos.convertToDate(source.next()));
280 
281         return result;
282     }
283 
284     private TaxonGroupDTO getLightTaxonGroup(TaxonGroupDTO taxonGroup) {
285         TaxonGroupDTO result = DaliBeans.clone(taxonGroup);
286         result.setTaxons(null);
287         result.setParentTaxonGroup(null);
288         return result;
289     }
290 
291 }