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.util.ArrayList;
|
14
|
import java.util.List;
|
15
|
import java.util.UUID;
|
16
|
|
17
|
import org.apache.log4j.Logger;
|
18
|
import org.hibernate.Query;
|
19
|
import org.springframework.beans.factory.annotation.Autowired;
|
20
|
import org.springframework.beans.factory.annotation.Qualifier;
|
21
|
import org.springframework.stereotype.Repository;
|
22
|
|
23
|
import eu.etaxonomy.cdm.model.name.Rank;
|
24
|
import eu.etaxonomy.cdm.model.taxon.Classification;
|
25
|
import eu.etaxonomy.cdm.model.taxon.Taxon;
|
26
|
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
|
27
|
import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;
|
28
|
import eu.etaxonomy.cdm.persistence.dao.taxon.IClassificationDao;
|
29
|
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
|
30
|
|
31
|
/**
|
32
|
* @author a.mueller
|
33
|
* @created 16.06.2009
|
34
|
* @version 1.0
|
35
|
*/
|
36
|
@Repository
|
37
|
@Qualifier("classificationDaoHibernateImpl")
|
38
|
public class ClassificationDaoHibernateImpl extends IdentifiableDaoBase<Classification>
|
39
|
implements IClassificationDao {
|
40
|
@SuppressWarnings("unused")
|
41
|
private static final Logger logger = Logger.getLogger(ClassificationDaoHibernateImpl.class);
|
42
|
|
43
|
@Autowired
|
44
|
private ITaxonNodeDao taxonNodeDao;
|
45
|
|
46
|
public ClassificationDaoHibernateImpl() {
|
47
|
super(Classification.class);
|
48
|
indexedClasses = new Class[1];
|
49
|
indexedClasses[0] = Classification.class;
|
50
|
}
|
51
|
|
52
|
@Override
|
53
|
@SuppressWarnings("unchecked")
|
54
|
public List<TaxonNode> listRankSpecificRootNodes(Classification classification, Rank rank,
|
55
|
Integer limit, Integer start, List<String> propertyPaths, int queryIndex){
|
56
|
|
57
|
List<TaxonNode> results = new ArrayList<TaxonNode>();
|
58
|
Query[] queries = prepareRankSpecificRootNodes(classification, rank, false);
|
59
|
|
60
|
// since this method is using two queries sequentially the handling of limit and start
|
61
|
// is a bit more complex
|
62
|
// the prepareRankSpecificRootNodes returns 1 or 2 queries
|
63
|
|
64
|
Query q = queries[queryIndex];
|
65
|
if(limit != null) {
|
66
|
q.setMaxResults(limit);
|
67
|
if(start != null) {
|
68
|
q.setFirstResult(start);
|
69
|
}
|
70
|
}
|
71
|
// long start_t = System.currentTimeMillis();
|
72
|
results = q.list();
|
73
|
// System.err.println("dao.listRankSpecificRootNodes() - query[" + queryIndex + "].list() " + (System.currentTimeMillis() - start_t));
|
74
|
// start_t = System.currentTimeMillis();
|
75
|
defaultBeanInitializer.initializeAll(results, propertyPaths);
|
76
|
// System.err.println("dao.listRankSpecificRootNodes() - defaultBeanInitializer.initializeAll() " + (System.currentTimeMillis() - start_t));
|
77
|
|
78
|
return results;
|
79
|
|
80
|
}
|
81
|
|
82
|
@Override
|
83
|
public long[] countRankSpecificRootNodes(Classification classification, Rank rank) {
|
84
|
|
85
|
long[] result = new long[(rank == null ? 1 : 2)];
|
86
|
Query[] queries = prepareRankSpecificRootNodes(classification, rank, true);
|
87
|
int i = 0;
|
88
|
for(Query q : queries) {
|
89
|
result[i++] = (Long)q.uniqueResult();
|
90
|
}
|
91
|
return result;
|
92
|
}
|
93
|
|
94
|
/**
|
95
|
* See <a href="http://dev.e-taxonomy.eu/trac/wiki/CdmClassificationRankSpecificRootnodes">
|
96
|
* http://dev.e-taxonomy.eu/trac/wiki/CdmClassificationRankSpecificRootnodes</a>
|
97
|
*
|
98
|
* @param classification
|
99
|
* @param rank
|
100
|
* @return
|
101
|
* one or two Queries as array, depending on the <code>rank</code> parameter:
|
102
|
* <code>rank == null</code>: array with one item, <code>rank != null</code>: array with two items.
|
103
|
*/
|
104
|
private Query[] prepareRankSpecificRootNodes(Classification classification, Rank rank, boolean doCount) {
|
105
|
Query query1;
|
106
|
Query query2 = null;
|
107
|
|
108
|
String whereClassification = "";
|
109
|
if (classification != null){
|
110
|
whereClassification = " AND tn.classification = :classification ";
|
111
|
}
|
112
|
|
113
|
String selectWhat = doCount ? "count(distinct tn)" : "distinct tn";
|
114
|
|
115
|
String joinFetch = doCount ? "" : " JOIN FETCH tn.taxon t JOIN FETCH t.name n LEFT JOIN FETCH n.rank LEFT JOIN FETCH t.sec ";
|
116
|
|
117
|
if(rank == null){
|
118
|
String hql = "SELECT " + selectWhat + " FROM TaxonNode tn" +
|
119
|
joinFetch +
|
120
|
" WHERE tn.parent.parent = null " +
|
121
|
whereClassification;
|
122
|
query1 = getSession().createQuery(hql);
|
123
|
} else {
|
124
|
// this is for the cases
|
125
|
// - exact match of the ranks
|
126
|
// - rank of root node is lower but is has no parents
|
127
|
String hql1 = "SELECT " + selectWhat + " FROM TaxonNode tn " +
|
128
|
joinFetch +
|
129
|
" WHERE " +
|
130
|
" (tn.taxon.name.rank = :rank" +
|
131
|
" OR (tn.taxon.name.rank.orderIndex > :rankOrderIndex AND tn.parent.parent = null)" +
|
132
|
" )"
|
133
|
+ whereClassification ;
|
134
|
|
135
|
// this is for the case
|
136
|
// - rank of root node is lower and it has a parent with higher rank
|
137
|
String hql2 = "SELECT " + selectWhat + " FROM TaxonNode tn JOIN tn.parent as parent" +
|
138
|
joinFetch +
|
139
|
" WHERE " +
|
140
|
" (tn.taxon.name.rank.orderIndex > :rankOrderIndex AND parent.taxon.name.rank.orderIndex < :rankOrderIndex )"
|
141
|
+ whereClassification ;
|
142
|
query1 = getSession().createQuery(hql1);
|
143
|
query2 = getSession().createQuery(hql2);
|
144
|
query1.setParameter("rank", rank);
|
145
|
query1.setParameter("rankOrderIndex", rank.getOrderIndex());
|
146
|
query2.setParameter("rankOrderIndex", rank.getOrderIndex());
|
147
|
}
|
148
|
|
149
|
if (classification != null){
|
150
|
query1.setParameter("classification", classification);
|
151
|
if(query2 != null) {
|
152
|
query2.setParameter("classification", classification);
|
153
|
}
|
154
|
}
|
155
|
if(query2 != null) {
|
156
|
return new Query[]{query1, query2};
|
157
|
} else {
|
158
|
return new Query[]{query1};
|
159
|
}
|
160
|
}
|
161
|
|
162
|
@Override
|
163
|
public List<TaxonNode> listChildrenOf(Taxon taxon, Classification classification, Integer pageSize, Integer pageIndex, List<String> propertyPaths){
|
164
|
Query query = prepareListChildrenOf(taxon, classification, false);
|
165
|
|
166
|
setPagingParameter(query, pageSize, pageIndex);
|
167
|
|
168
|
@SuppressWarnings("unchecked")
|
169
|
List<TaxonNode> result = query.list();
|
170
|
//check if array is "empty" (not containing null objects)
|
171
|
if(!result.isEmpty() && result.iterator().next()==null){
|
172
|
return java.util.Collections.emptyList();
|
173
|
}
|
174
|
defaultBeanInitializer.initializeAll(result, propertyPaths);
|
175
|
return result;
|
176
|
}
|
177
|
|
178
|
@Override
|
179
|
public List<TaxonNode> listSiblingsOf(Taxon taxon, Classification classification, Integer pageSize, Integer pageIndex, List<String> propertyPaths){
|
180
|
Query query = prepareListSiblingsOf(taxon, classification, false);
|
181
|
|
182
|
setPagingParameter(query, pageSize, pageIndex);
|
183
|
|
184
|
@SuppressWarnings("unchecked")
|
185
|
List<TaxonNode> result = query.list();
|
186
|
//check if array is "empty" (not containing null objects)
|
187
|
if(!result.isEmpty() && result.iterator().next()==null){
|
188
|
return java.util.Collections.emptyList();
|
189
|
}
|
190
|
defaultBeanInitializer.initializeAll(result, propertyPaths);
|
191
|
return result;
|
192
|
}
|
193
|
|
194
|
|
195
|
|
196
|
@Override
|
197
|
public Long countChildrenOf(Taxon taxon, Classification classification){
|
198
|
Query query = prepareListChildrenOf(taxon, classification, true);
|
199
|
Long count = (Long) query.uniqueResult();
|
200
|
return count;
|
201
|
}
|
202
|
|
203
|
@Override
|
204
|
public Long countSiblingsOf(Taxon taxon, Classification classification){
|
205
|
Query query = prepareListSiblingsOf(taxon, classification, true);
|
206
|
Long count = (Long) query.uniqueResult();
|
207
|
return count;
|
208
|
}
|
209
|
|
210
|
private Query prepareListChildrenOf(Taxon taxon, Classification classification, boolean doCount){
|
211
|
|
212
|
String selectWhat = doCount ? "count(cn)" : "cn";
|
213
|
|
214
|
String hql = "select " + selectWhat + " from TaxonNode as tn JOIN tn.classification as c JOIN tn.taxon as t JOIN tn.childNodes as cn "
|
215
|
+ "where t = :taxon and c = :classification";
|
216
|
Query query = getSession().createQuery(hql);
|
217
|
query.setParameter("taxon", taxon);
|
218
|
query.setParameter("classification", classification);
|
219
|
return query;
|
220
|
}
|
221
|
|
222
|
private Query prepareListSiblingsOf(Taxon taxon, Classification classification, boolean doCount){
|
223
|
|
224
|
String selectWhat = doCount ? "count(tn)" : "tn";
|
225
|
|
226
|
String subSelect = "SELECT tn.parent FROM TaxonNode as tn JOIN tn.classification as c JOIN tn.taxon as t "
|
227
|
+ "WHERE t = :taxon AND c = :classification";
|
228
|
String hql = "SELECT " + selectWhat + " FROM TaxonNode as tn WHERE tn.parent IN ( " + subSelect + ")";
|
229
|
Query query = getSession().createQuery(hql);
|
230
|
query.setParameter("taxon", taxon);
|
231
|
query.setParameter("classification", classification);
|
232
|
return query;
|
233
|
}
|
234
|
|
235
|
|
236
|
@Override
|
237
|
public UUID delete(Classification persistentObject){
|
238
|
//delete all childnodes, then delete the tree
|
239
|
|
240
|
List<TaxonNode> nodes = persistentObject.getChildNodes();
|
241
|
List<TaxonNode> nodesTmp = new ArrayList<TaxonNode>(nodes);
|
242
|
|
243
|
// Iterator<TaxonNode> nodesIterator = nodes.iterator();
|
244
|
for(TaxonNode node : nodesTmp){
|
245
|
persistentObject.deleteChildNode(node, true);
|
246
|
taxonNodeDao.delete(node, true);
|
247
|
}
|
248
|
|
249
|
TaxonNode rootNode = persistentObject.getRootNode();
|
250
|
persistentObject.removeRootNode();
|
251
|
taxonNodeDao.delete(rootNode);
|
252
|
super.delete(persistentObject);
|
253
|
|
254
|
return persistentObject.getUuid();
|
255
|
}
|
256
|
|
257
|
|
258
|
|
259
|
|
260
|
}
|