3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
11 package eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.taxon
;
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
;
20 import java
.util
.UUID
;
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
;
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
;
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);
55 private ITaxonDao taxonDao
;
57 private IClassificationDao classificationDao
;
59 public TaxonNodeDaoHibernateImpl() {
60 super(TaxonNode
.class);
63 public UUID
delete(TaxonNode persistentObject
, boolean deleteChildren
){
64 Taxon taxon
= persistentObject
.getTaxon();
65 taxon
= HibernateProxyHelper
.deproxy(taxon
, Taxon
.class);
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();*/
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);
80 if (node
.equals(persistentObject
)){
81 if (node
.hasChildNodes()){
82 Iterator
<TaxonNode
> childNodes
= node
.getChildNodes().iterator();
84 List
<TaxonNode
> listForDeletion
= new ArrayList
<TaxonNode
>();
85 while (childNodes
.hasNext()){
86 childNode
= childNodes
.next();
87 listForDeletion
.add(childNode
);
91 for (TaxonNode deleteNode
:listForDeletion
){
92 delete(deleteNode
, deleteChildren
);
96 taxon
.removeTaxonNode(node
, deleteChildren
);
97 taxonDao
.saveOrUpdate(taxon
);
98 taxon
= HibernateProxyHelper
.deproxy(taxonDao
.findByUuid(taxon
.getUuid()), Taxon
.class);
99 taxonDao
.delete(taxon
);
105 UUID result
= super.delete(persistentObject
);
111 public List
<TaxonNode
> getTaxonOfAcceptedTaxaByClassification(Classification classification
, Integer start
, Integer end
) {
112 int classificationId
= classification
.getId();
114 if(start
!=null && end
!= null){
115 limit
= "LIMIT "+start
+"," +end
;
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();
127 public int countTaxonOfAcceptedTaxaByClassification(Classification classification
){
128 int classificationId
= classification
.getId();
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 ();
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
<>();
142 List
<Object
[]> result
= query
.list();
144 for(Object
[] object
: result
){
145 list
.add(new UuidAndTitleCache
<TaxonNode
>((UUID
) object
[0],(Integer
) object
[1], (String
) object
[2]));
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";
159 Query query
= getSession().createQuery(queryString
);
161 query
.setParameter("pattern", pattern
.toLowerCase()+"%");
162 query
.setParameter("classificationUuid", classificationUuid
);
164 List
<UuidAndTitleCache
<TaxonNode
>> list
= new ArrayList
<>();
166 List
<Object
[]> result
= query
.list();
168 for(Object
[] object
: result
){
169 list
.add(new UuidAndTitleCache
<TaxonNode
>((UUID
) object
[0],(Integer
) object
[1], (String
) object
[2]));
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
<>();
187 List
<Object
[]> result
= query
.list();
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
));
198 list
.add(new UuidAndTitleCache
<TaxonNode
>(uuid
,id
, classificationTitleCache
));
202 return list
.iterator().next();
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
);
217 crit
.setFirstResult(0);
220 List
<TaxonNode
> results
= crit
.list();
221 results
.remove(node
);
222 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
225 return classificationDao
.listChildrenOf(node
.getTaxon(), node
.getClassification(), pageSize
, pageIndex
, propertyPaths
);
231 public Long
countChildrenOf(TaxonNode node
, Classification classification
,
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();
240 return classificationDao
.countChildrenOf(node
.getTaxon(), classification
);
247 public List
<TaxonNodeAgentRelation
> listTaxonNodeAgentRelations(UUID taxonUuid
, UUID classificationUuid
,
248 UUID agentUuid
, UUID rankUuid
, UUID relTypeUuid
, Integer start
, Integer limit
, List
<String
> propertyPaths
) {
251 StringBuilder hql
= prepareListTaxonNodeAgentRelations(taxonUuid
, classificationUuid
, agentUuid
, rankUuid
, relTypeUuid
, false);
253 Query query
= getSession().createQuery(hql
.toString());
256 query
.setMaxResults(limit
);
258 query
.setFirstResult(start
);
262 setParamsForListTaxonNodeAgentRelations(taxonUuid
, classificationUuid
, agentUuid
, rankUuid
, relTypeUuid
, query
);
264 List
<TaxonNodeAgentRelation
> records
= query
.list();
266 if(propertyPaths
!= null) {
267 defaultBeanInitializer
.initializeAll(records
, propertyPaths
);
276 public long countTaxonNodeAgentRelations(UUID taxonUuid
, UUID classificationUuid
, UUID agentUuid
, UUID rankUuid
, UUID relTypeUuid
) {
278 StringBuilder hql
= prepareListTaxonNodeAgentRelations(taxonUuid
, classificationUuid
, agentUuid
, rankUuid
, relTypeUuid
, true);
279 Query query
= getSession().createQuery(hql
.toString());
281 setParamsForListTaxonNodeAgentRelations(taxonUuid
, classificationUuid
, agentUuid
, rankUuid
, relTypeUuid
, query
);
283 Long count
= Long
.parseLong(query
.uniqueResult().toString());
289 * @param classificationUuid
291 * @param relTypeUuid TODO
292 * @param doCount TODO
294 * limit to taxa having this rank, only applies if <code>taxonUuid = null</code>
297 private StringBuilder
prepareListTaxonNodeAgentRelations(UUID taxonUuid
, UUID classificationUuid
, UUID agentUuid
, UUID rankUuid
, UUID relTypeUuid
, boolean doCount
) {
299 StringBuilder hql
= new StringBuilder();
301 String join_fetch_mode
= doCount ?
"join" : "join fetch";
304 hql
.append("select count(tnar)");
306 hql
.append("select tnar");
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 ");
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 ");
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 ");
325 hql
.append(join_fetch_mode
).append(" tnar.agent as a ");
328 hql
.append(" where 1 = 1 ");
330 if(relTypeUuid
!= null) {
331 hql
.append(" and tnar.type.uuid = :relTypeUuid ");
334 if(taxonUuid
!= null) {
335 hql
.append(" and t.uuid = :taxonUuid ");
337 if(rankUuid
!= null) {
338 hql
.append(" and n.rank.uuid = :rankUuid ");
341 if(classificationUuid
!= null) {
342 hql
.append(" and c.uuid = :classificationUuid ");
344 if(agentUuid
!= null) {
345 hql
.append(" and a.uuid = :agentUuid ");
348 hql
.append(" order by a.titleCache");
353 * @param classificationUuid
355 * @param relTypeUuid TODO
359 private void setParamsForListTaxonNodeAgentRelations(UUID taxonUuid
, UUID classificationUuid
, UUID agentUuid
,
360 UUID rankUuid
, UUID relTypeUuid
, Query query
) {
362 if(taxonUuid
!= null) {
363 query
.setParameter("taxonUuid", taxonUuid
);
365 if(rankUuid
!= null) {
366 query
.setParameter("rankUuid", rankUuid
);
369 if(classificationUuid
!= null) {
370 query
.setParameter("classificationUuid", classificationUuid
);
372 if(agentUuid
!= null) {
373 query
.setParameter("agentUuid", agentUuid
);
375 if(relTypeUuid
!= null) {
376 query
.setParameter("relTypeUuid", relTypeUuid
);
381 public Map
<String
, Integer
> rankOrderIndexForTreeIndex(List
<String
> treeIndexes
,
382 Integer minRankOrderIndex
,
383 Integer maxRankOrderIndex
) {
385 Map
<String
, Integer
> result
= new HashMap
<>();
386 if (treeIndexes
== null || treeIndexes
.isEmpty()){
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";
396 if (maxRankOrderIndex
!= null){
397 hql
+= " AND r.orderIndex >= :maxOrderIndex";
400 Query query
= getSession().createQuery(hql
);
401 query
.setParameterList("treeIndexes", treeIndexes
);
402 if (minRankOrderIndex
!= null){
403 query
.setParameter("minOrderIndex", minRankOrderIndex
);
405 if (maxRankOrderIndex
!= null){
406 query
.setParameter("maxOrderIndex", maxRankOrderIndex
);
409 @SuppressWarnings("unchecked")
410 List
<Object
[]> list
= query
.list();
411 for (Object
[] o
: list
){
412 result
.put((String
)o
[0], (Integer
)o
[1]);
418 public Map
<String
, UuidAndTitleCache
<?
>> taxonUuidsForTreeIndexes(Set
<String
> treeIndexes
) {
419 Map
<String
, UuidAndTitleCache
<?
>> result
= new HashMap
<>();
420 if (treeIndexes
== null || treeIndexes
.isEmpty()){
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
);
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]));