ref #5458 Add classification filter to service method
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / persistence / dao / hibernate / taxon / TaxonNodeDaoHibernateImpl.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.cdm.persistence.dao.hibernate.taxon;
12
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.UUID;
21
22 import org.apache.log4j.Logger;
23 import org.hibernate.Criteria;
24 import org.hibernate.Hibernate;
25 import org.hibernate.Query;
26 import org.hibernate.criterion.Projections;
27 import org.hibernate.criterion.Restrictions;
28 import org.springframework.beans.factory.annotation.Autowired;
29 import org.springframework.beans.factory.annotation.Qualifier;
30 import org.springframework.stereotype.Repository;
31
32 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
33 import eu.etaxonomy.cdm.model.taxon.Classification;
34 import eu.etaxonomy.cdm.model.taxon.Taxon;
35 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
36 import eu.etaxonomy.cdm.model.taxon.TaxonNodeAgentRelation;
37 import eu.etaxonomy.cdm.persistence.dao.hibernate.common.AnnotatableDaoImpl;
38 import eu.etaxonomy.cdm.persistence.dao.taxon.IClassificationDao;
39 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
40 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
41 import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
42
43 /**
44 * @author a.mueller
45 * @created 16.06.2009
46 */
47 @Repository
48 @Qualifier("taxonNodeDaoHibernateImpl")
49 public class TaxonNodeDaoHibernateImpl extends AnnotatableDaoImpl<TaxonNode>
50 implements ITaxonNodeDao {
51 @SuppressWarnings("unused")
52 private static final Logger logger = Logger.getLogger(TaxonNodeDaoHibernateImpl.class);
53
54 @Autowired
55 private ITaxonDao taxonDao;
56 @Autowired
57 private IClassificationDao classificationDao;
58
59 public TaxonNodeDaoHibernateImpl() {
60 super(TaxonNode.class);
61 }
62 @Override
63 public UUID delete(TaxonNode persistentObject, boolean deleteChildren){
64 Taxon taxon = persistentObject.getTaxon();
65 taxon = HibernateProxyHelper.deproxy(taxon, Taxon.class);
66
67 /*Session session = this.getSession();
68 Query query = session.createQuery("from TaxonNode t where t.taxon = :taxon");
69 query.setParameter("taxon", taxon);
70 List result = query.list();*/
71 if (taxon != null){
72 Hibernate.initialize(taxon);
73 Hibernate.initialize(taxon.getTaxonNodes());
74 Set<TaxonNode> nodes = taxon.getTaxonNodes();
75 //Hibernate.initialize(taxon.getTaxonNodes());
76 for (TaxonNode node:nodes) {
77 System.out.println("Number of nodes: " + nodes.size());
78 node = HibernateProxyHelper.deproxy(node, TaxonNode.class);
79
80 if (node.equals(persistentObject)){
81 if (node.hasChildNodes()){
82 Iterator<TaxonNode> childNodes = node.getChildNodes().iterator();
83 TaxonNode childNode;
84 List<TaxonNode> listForDeletion = new ArrayList<TaxonNode>();
85 while (childNodes.hasNext()){
86 childNode = childNodes.next();
87 listForDeletion.add(childNode);
88 childNodes.remove();
89
90 }
91 for (TaxonNode deleteNode:listForDeletion){
92 delete(deleteNode, deleteChildren);
93 }
94 }
95
96 taxon.removeTaxonNode(node, deleteChildren);
97 taxonDao.saveOrUpdate(taxon);
98 taxon = HibernateProxyHelper.deproxy(taxonDao.findByUuid(taxon.getUuid()), Taxon.class);
99 taxonDao.delete(taxon);
100
101 }
102 }
103 }
104
105 UUID result = super.delete(persistentObject);
106
107 return result;
108 }
109
110 @Override
111 public List<TaxonNode> getTaxonOfAcceptedTaxaByClassification(Classification classification, Integer start, Integer end) {
112 int classificationId = classification.getId();
113 String limit = "";
114 if(start !=null && end != null){
115 limit = "LIMIT "+start+"," +end;
116 }
117 //FIXME write test
118 String queryString = "SELECT DISTINCT nodes.*,taxa.titleCache FROM TaxonNode AS nodes LEFT JOIN TaxonBase AS taxa ON nodes.taxon_id = taxa.id WHERE taxa.DTYPE = 'Taxon' AND nodes.classification_id = " + classificationId + " ORDER BY taxa.titleCache " + limit;
119 List<TaxonNode> result = getSession().createSQLQuery(queryString).addEntity(TaxonNode.class).list();
120
121 return result;
122
123
124 }
125
126 @Override
127 public int countTaxonOfAcceptedTaxaByClassification(Classification classification){
128 int classificationId = classification.getId();
129 //FIXME write test
130 String queryString = "SELECT DISTINCT COUNT('nodes.*') FROM TaxonNode AS nodes LEFT JOIN TaxonBase AS taxa ON nodes.taxon_id = taxa.id WHERE taxa.DTYPE = 'Taxon' AND nodes.classification_id = " + classificationId;
131 List<BigInteger> result = getSession().createSQLQuery(queryString).list();
132 return result.get(0).intValue ();
133 }
134
135 @Override
136 public List<UuidAndTitleCache<TaxonNode>> listChildNodesAsUuidAndTitleCache(UuidAndTitleCache<TaxonNode> parent) {
137 String queryString = "select tn.uuid, tn.id, tx.titleCache from TaxonNode tn INNER JOIN tn.taxon as tx where tn.parent.id = :parentId";
138 Query query = getSession().createQuery(queryString);
139 query.setParameter("parentId", parent.getId());
140 List<UuidAndTitleCache<TaxonNode>> list = new ArrayList<>();
141
142 List<Object[]> result = query.list();
143
144 for(Object[] object : result){
145 list.add(new UuidAndTitleCache<TaxonNode>((UUID) object[0],(Integer) object[1], (String) object[2]));
146 }
147 return list;
148 }
149
150 @Override
151 public List<UuidAndTitleCache<TaxonNode>> getUuidAndTitleCache(Integer limit, String pattern, UUID classificationUuid) {
152 String queryString = "select tn.uuid, tn.id, tx.titleCache from TaxonNode tn "
153 + "INNER JOIN tn.taxon as tx "
154 + "INNER JOIN tn.classification as cls "
155 + "WHERE tx.titleCache like :pattern ";
156 if(classificationUuid!=null){
157 queryString += "AND cls.uuid = :classificationUuid";
158 }
159 Query query = getSession().createQuery(queryString);
160
161 query.setParameter("pattern", pattern.toLowerCase()+"%");
162 query.setParameter("classificationUuid", classificationUuid);
163
164 List<UuidAndTitleCache<TaxonNode>> list = new ArrayList<>();
165
166 List<Object[]> result = query.list();
167
168 for(Object[] object : result){
169 list.add(new UuidAndTitleCache<TaxonNode>((UUID) object[0],(Integer) object[1], (String) object[2]));
170 }
171 return list;
172 }
173
174 /**
175 * {@inheritDoc}
176 */
177 @Override
178 public UuidAndTitleCache<TaxonNode> getParentUuidAndTitleCache(UuidAndTitleCache<TaxonNode> child) {
179 String queryString = "select tn.parent.uuid, tn.parent.id, tn.parent.taxon.titleCache, tn.parent.classification.titleCache "
180 + " from TaxonNode tn"
181 + " LEFT OUTER JOIN tn.parent.taxon"
182 + " where tn.id = :childId";
183 Query query = getSession().createQuery(queryString);
184 query.setParameter("childId", child.getId());
185 List<UuidAndTitleCache<TaxonNode>> list = new ArrayList<>();
186
187 List<Object[]> result = query.list();
188
189 for(Object[] object : result){
190 UUID uuid = (UUID) object[0];
191 Integer id = (Integer) object[1];
192 String taxonTitleCache = (String) object[2];
193 String classificationTitleCache = (String) object[3];
194 if(taxonTitleCache!=null){
195 list.add(new UuidAndTitleCache<TaxonNode>(uuid,id, taxonTitleCache));
196 }
197 else{
198 list.add(new UuidAndTitleCache<TaxonNode>(uuid,id, classificationTitleCache));
199 }
200 }
201 if(list.size()==1){
202 return list.iterator().next();
203 }
204 return null;
205 }
206
207 @Override
208 public List<TaxonNode> listChildrenOf(TaxonNode node, Integer pageSize, Integer pageIndex, List<String> propertyPaths, boolean recursive){
209 if (recursive == true){
210 Criteria crit = getSession().createCriteria(TaxonNode.class);
211 crit.add( Restrictions.like("treeIndex", node.treeIndex()+ "%") );
212 if(pageSize != null) {
213 crit.setMaxResults(pageSize);
214 if(pageIndex != null) {
215 crit.setFirstResult(pageIndex * pageSize);
216 } else {
217 crit.setFirstResult(0);
218 }
219 }
220 List<TaxonNode> results = crit.list();
221 results.remove(node);
222 defaultBeanInitializer.initializeAll(results, propertyPaths);
223 return results;
224 }else{
225 return classificationDao.listChildrenOf(node.getTaxon(), node.getClassification(), pageSize, pageIndex, propertyPaths);
226 }
227
228 }
229
230 @Override
231 public Long countChildrenOf(TaxonNode node, Classification classification,
232 boolean recursive) {
233
234 if (recursive == true){
235 Criteria crit = getSession().createCriteria(TaxonNode.class);
236 crit.add( Restrictions.like("treeIndex", node.treeIndex()+ "%") );
237 crit.setProjection(Projections.rowCount());
238 return ((Integer)crit.uniqueResult().hashCode()).longValue();
239 }else{
240 return classificationDao.countChildrenOf(node.getTaxon(), classification);
241 }
242 }
243 /**
244 * {@inheritDoc}
245 */
246 @Override
247 public List<TaxonNodeAgentRelation> listTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid,
248 UUID agentUuid, UUID rankUuid, UUID relTypeUuid, Integer start, Integer limit, List<String> propertyPaths) {
249
250
251 StringBuilder hql = prepareListTaxonNodeAgentRelations(taxonUuid, classificationUuid, agentUuid, rankUuid, relTypeUuid, false);
252
253 Query query = getSession().createQuery(hql.toString());
254
255 if(limit != null) {
256 query.setMaxResults(limit);
257 if(start != null) {
258 query.setFirstResult(start);
259 }
260 }
261
262 setParamsForListTaxonNodeAgentRelations(taxonUuid, classificationUuid, agentUuid, rankUuid, relTypeUuid, query);
263
264 List<TaxonNodeAgentRelation> records = query.list();
265
266 if(propertyPaths != null) {
267 defaultBeanInitializer.initializeAll(records, propertyPaths);
268 }
269 return records;
270 }
271
272 /**
273 * {@inheritDoc}
274 */
275 @Override
276 public long countTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid, UUID agentUuid, UUID rankUuid, UUID relTypeUuid) {
277
278 StringBuilder hql = prepareListTaxonNodeAgentRelations(taxonUuid, classificationUuid, agentUuid, rankUuid, relTypeUuid, true);
279 Query query = getSession().createQuery(hql.toString());
280
281 setParamsForListTaxonNodeAgentRelations(taxonUuid, classificationUuid, agentUuid, rankUuid, relTypeUuid, query);
282
283 Long count = Long.parseLong(query.uniqueResult().toString());
284
285 return count;
286 }
287 /**
288 * @param taxonUuid
289 * @param classificationUuid
290 * @param agentUuid
291 * @param relTypeUuid TODO
292 * @param doCount TODO
293 * @param rankId
294 * limit to taxa having this rank, only applies if <code>taxonUuid = null</code>
295 * @return
296 */
297 private StringBuilder prepareListTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid, UUID agentUuid, UUID rankUuid, UUID relTypeUuid, boolean doCount) {
298
299 StringBuilder hql = new StringBuilder();
300
301 String join_fetch_mode = doCount ? "join" : "join fetch";
302
303 if(doCount) {
304 hql.append("select count(tnar)");
305 } else {
306 hql.append("select tnar");
307 }
308
309 hql.append(" from TaxonNodeAgentRelation as tnar ");
310 if(taxonUuid != null) {
311 // taxonUuid is search filter, do not fetch it
312 hql.append(" join tnar.taxonNode as tn join tn.taxon as t ");
313 } else {
314 hql.append(join_fetch_mode).append(" tnar.taxonNode as tn ").append(join_fetch_mode).append(" tn.taxon as t ");
315 if(rankUuid != null) {
316 hql.append(" join t.name as n ");
317 }
318 }
319 hql.append(" join tn.classification as c ");
320 if(agentUuid != null) {
321 // agentUuid is search filter, do not fetch it
322 // hql.append(" join tnar.agent as a ");
323 hql.append(join_fetch_mode).append(" tnar.agent as a ");
324 } else {
325 hql.append(join_fetch_mode).append(" tnar.agent as a ");
326 }
327
328 hql.append(" where 1 = 1 ");
329
330 if(relTypeUuid != null) {
331 hql.append(" and tnar.type.uuid = :relTypeUuid ");
332 }
333
334 if(taxonUuid != null) {
335 hql.append(" and t.uuid = :taxonUuid ");
336 } else {
337 if(rankUuid != null) {
338 hql.append(" and n.rank.uuid = :rankUuid ");
339 }
340 }
341 if(classificationUuid != null) {
342 hql.append(" and c.uuid = :classificationUuid ");
343 }
344 if(agentUuid != null) {
345 hql.append(" and a.uuid = :agentUuid ");
346 }
347
348 hql.append(" order by a.titleCache");
349 return hql;
350 }
351 /**
352 * @param taxonUuid
353 * @param classificationUuid
354 * @param agentUuid
355 * @param relTypeUuid TODO
356 * @param query
357 * @param rankId TODO
358 */
359 private void setParamsForListTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid, UUID agentUuid,
360 UUID rankUuid, UUID relTypeUuid, Query query) {
361
362 if(taxonUuid != null) {
363 query.setParameter("taxonUuid", taxonUuid);
364 } else {
365 if(rankUuid != null) {
366 query.setParameter("rankUuid", rankUuid);
367 }
368 }
369 if(classificationUuid != null) {
370 query.setParameter("classificationUuid", classificationUuid);
371 }
372 if(agentUuid != null) {
373 query.setParameter("agentUuid", agentUuid);
374 }
375 if(relTypeUuid != null) {
376 query.setParameter("relTypeUuid", relTypeUuid);
377 }
378 }
379
380 @Override
381 public Map<String, Integer> rankOrderIndexForTreeIndex(List<String> treeIndexes,
382 Integer minRankOrderIndex,
383 Integer maxRankOrderIndex) {
384
385 Map<String, Integer> result = new HashMap<>();
386 if (treeIndexes == null || treeIndexes.isEmpty()){
387 return result;
388 }
389
390 String hql = " SELECT tn.treeIndex, r.orderIndex "
391 + " FROM TaxonNode tn JOIN tn.taxon t JOIN t.name n JOIN n.rank r "
392 + " WHERE tn.treeIndex IN (:treeIndexes) ";
393 if (minRankOrderIndex != null){
394 hql += " AND r.orderIndex <= :minOrderIndex";
395 }
396 if (maxRankOrderIndex != null){
397 hql += " AND r.orderIndex >= :maxOrderIndex";
398 }
399
400 Query query = getSession().createQuery(hql);
401 query.setParameterList("treeIndexes", treeIndexes);
402 if (minRankOrderIndex != null){
403 query.setParameter("minOrderIndex", minRankOrderIndex);
404 }
405 if (maxRankOrderIndex != null){
406 query.setParameter("maxOrderIndex", maxRankOrderIndex);
407 }
408
409 @SuppressWarnings("unchecked")
410 List<Object[]> list = query.list();
411 for (Object[] o : list){
412 result.put((String)o[0], (Integer)o[1]);
413 }
414 return result;
415 }
416
417 @Override
418 public Map<String, UuidAndTitleCache<?>> taxonUuidsForTreeIndexes(Set<String> treeIndexes) {
419 Map<String, UuidAndTitleCache<?>> result = new HashMap<>();
420 if (treeIndexes == null || treeIndexes.isEmpty()){
421 return result;
422 }
423
424 String hql = " SELECT tn.treeIndex, t.uuid, tnb.titleCache "
425 + " FROM TaxonNode tn JOIN tn.taxon t Join t.name tnb "
426 + " WHERE tn.treeIndex IN (:treeIndexes) ";
427 Query query = getSession().createQuery(hql);
428 query.setParameterList("treeIndexes", treeIndexes);
429
430 @SuppressWarnings("unchecked")
431 List<Object[]> list = query.list();
432 for (Object[] o : list){
433 result.put((String)o[0], new UuidAndTitleCache<>((UUID)o[1], null, (String)o[2]));
434 }
435 return result;
436 }
437
438
439
440 }