Project

General

Profile

Download (13.5 KB) Statistics
| Branch: | Tag: | Revision:
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.HashMap;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.UUID;
18

    
19
import org.apache.log4j.Logger;
20
import org.hibernate.Query;
21
import org.springframework.beans.factory.annotation.Autowired;
22
import org.springframework.beans.factory.annotation.Qualifier;
23
import org.springframework.stereotype.Repository;
24

    
25
import eu.etaxonomy.cdm.model.name.Rank;
26
import eu.etaxonomy.cdm.model.taxon.Classification;
27
import eu.etaxonomy.cdm.model.taxon.Taxon;
28
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
29
import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;
30
import eu.etaxonomy.cdm.persistence.dao.taxon.IClassificationDao;
31
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
32
import eu.etaxonomy.cdm.persistence.dto.ClassificationLookupDTO;
33

    
34
/**
35
 * @author a.mueller
36
 * @created 16.06.2009
37
 */
38
@Repository
39
@Qualifier("classificationDaoHibernateImpl")
40
public class ClassificationDaoHibernateImpl extends IdentifiableDaoBase<Classification>
41
        implements IClassificationDao {
42
    @SuppressWarnings("unused")
43
    private static final Logger logger = Logger.getLogger(ClassificationDaoHibernateImpl.class);
44

    
45
    @Autowired
46
    private ITaxonNodeDao taxonNodeDao;
47

    
48
    public ClassificationDaoHibernateImpl() {
49
        super(Classification.class);
50
        indexedClasses = new Class[1];
51
        indexedClasses[0] = Classification.class;
52
    }
53

    
54
    @Override
55
    @SuppressWarnings("unchecked")
56
    public List<TaxonNode> listRankSpecificRootNodes(Classification classification, Rank rank,
57
            Integer limit, Integer start, List<String> propertyPaths, int queryIndex){
58

    
59
        List<TaxonNode> results = new ArrayList<TaxonNode>();
60
        Query[] queries = prepareRankSpecificRootNodes(classification, rank, false);
61

    
62
        // since this method is using two queries sequentially the handling of limit and start
63
        // is a bit more complex
64
        // the prepareRankSpecificRootNodes returns 1 or 2 queries
65

    
66
        Query q = queries[queryIndex];
67
        if(limit != null) {
68
            q.setMaxResults(limit);
69
            if(start != null) {
70
                q.setFirstResult(start);
71
            }
72
        }
73
//        long start_t = System.currentTimeMillis();
74
        results = q.list();
75
//        System.err.println("dao.listRankSpecificRootNodes() - query[" + queryIndex + "].list() " + (System.currentTimeMillis() - start_t));
76
//        start_t = System.currentTimeMillis();
77
        defaultBeanInitializer.initializeAll(results, propertyPaths);
78
//        System.err.println("dao.listRankSpecificRootNodes() - defaultBeanInitializer.initializeAll() " + (System.currentTimeMillis() - start_t));
79

    
80
        return results;
81

    
82
    }
83

    
84
    @Override
85
    public long[] countRankSpecificRootNodes(Classification classification, Rank rank) {
86

    
87
        long[] result = new long[(rank == null ? 1 : 2)];
88
        Query[] queries = prepareRankSpecificRootNodes(classification, rank, true);
89
        int i = 0;
90
        for(Query q : queries) {
91
            result[i++] = (Long)q.uniqueResult();
92
        }
93
        return result;
94
    }
95

    
96
    /**
97
     * See <a href="http://dev.e-taxonomy.eu/trac/wiki/CdmClassificationRankSpecificRootnodes">
98
     * http://dev.e-taxonomy.eu/trac/wiki/CdmClassificationRankSpecificRootnodes</a>
99
     *
100
     * @param classification
101
     * @param rank
102
     * @return
103
     *      one or two Queries as array, depending on the <code>rank</code> parameter:
104
     *      <code>rank == null</code>: array with one item, <code>rank != null</code>: array with two items.
105
     */
106
    private Query[] prepareRankSpecificRootNodes(Classification classification, Rank rank, boolean doCount) {
107
        Query query1;
108
        Query query2 = null;
109

    
110
        String whereClassification = "";
111
        if (classification != null){
112
            whereClassification = " AND tn.classification = :classification ";
113
        }
114

    
115
        String selectWhat = doCount ? "count(distinct tn)" : "distinct tn";
116

    
117
        String joinFetch = doCount ? "" : " JOIN FETCH tn.taxon t JOIN FETCH t.name n LEFT JOIN FETCH n.rank LEFT JOIN FETCH t.sec ";
118

    
119
        if(rank == null){
120
            String hql = "SELECT " + selectWhat + " FROM TaxonNode tn" +
121
                    joinFetch +
122
                    " WHERE tn.parent.parent = null " +
123
                    whereClassification;
124
            query1 = getSession().createQuery(hql);
125
        } else {
126
            // this is for the cases
127
            //   - exact match of the ranks
128
            //   - rank of root node is lower but is has no parents
129
            String hql1 = "SELECT " + selectWhat + " FROM TaxonNode tn " +
130
                    joinFetch +
131
                    " WHERE " +
132
                    " (tn.taxon.name.rank = :rank" +
133
                    "   OR (tn.taxon.name.rank.orderIndex > :rankOrderIndex AND tn.parent.parent = null)" +
134
                    " )"
135
                    + whereClassification ;
136

    
137
            // this is for the case
138
            //   - rank of root node is lower and it has a parent with higher rank
139
            String hql2 = "SELECT " + selectWhat + " FROM TaxonNode tn JOIN tn.parent as parent" +
140
                    joinFetch +
141
                    " WHERE " +
142
                    " (tn.taxon.name.rank.orderIndex > :rankOrderIndex AND parent.taxon.name.rank.orderIndex < :rankOrderIndex )"
143
                    + whereClassification ;
144
            query1 = getSession().createQuery(hql1);
145
            query2 = getSession().createQuery(hql2);
146
            query1.setParameter("rank", rank);
147
            query1.setParameter("rankOrderIndex", rank.getOrderIndex());
148
            query2.setParameter("rankOrderIndex", rank.getOrderIndex());
149
        }
150

    
151
        if (classification != null){
152
            query1.setParameter("classification", classification);
153
            if(query2 != null) {
154
                query2.setParameter("classification", classification);
155
            }
156
        }
157
        if(query2 != null) {
158
            return new Query[]{query1, query2};
159
        } else {
160
            return new Query[]{query1};
161
        }
162
    }
163

    
164
    @Override
165
    public List<TaxonNode> listChildrenOf(Taxon taxon, Classification classification, Integer pageSize, Integer pageIndex, List<String> propertyPaths){
166
    	 Query query = prepareListChildrenOf(taxon, classification, false);
167

    
168
         setPagingParameter(query, pageSize, pageIndex);
169

    
170
         @SuppressWarnings("unchecked")
171
         List<TaxonNode> result = query.list();
172
         //check if array is "empty" (not containing null objects)
173
         if(!result.isEmpty() && result.iterator().next()==null){
174
         	return java.util.Collections.emptyList();
175
         }
176
         defaultBeanInitializer.initializeAll(result, propertyPaths);
177
         return result;
178
    }
179

    
180
    @Override
181
    public TaxonNode getRootNode(UUID classificationUuid){
182
        String queryString = "select tn from TaxonNode tn, Classification c where tn = c.rootNode and c.uuid = :classificationUuid";
183

    
184
        Query query = getSession().createQuery(queryString);
185
        query.setParameter("classificationUuid", classificationUuid);
186

    
187

    
188
        List results = query.list();
189
        if(results.size()!=1){
190
            return null;
191
        }
192
        return taxonNodeDao.load(((TaxonNode) results.iterator().next()).getUuid());
193
    }
194

    
195
    @Override
196
    public List<TaxonNode> listSiblingsOf(Taxon taxon, Classification classification, Integer pageSize, Integer pageIndex, List<String> propertyPaths){
197
         Query query = prepareListSiblingsOf(taxon, classification, false);
198

    
199
         setPagingParameter(query, pageSize, pageIndex);
200

    
201
         @SuppressWarnings("unchecked")
202
         List<TaxonNode> result = query.list();
203
         //check if array is "empty" (not containing null objects)
204
         if(!result.isEmpty() && result.iterator().next()==null){
205
            return java.util.Collections.emptyList();
206
         }
207
         defaultBeanInitializer.initializeAll(result, propertyPaths);
208
         return result;
209
    }
210

    
211

    
212

    
213
    @Override
214
    public Long countChildrenOf(Taxon taxon, Classification classification){
215
        Query query = prepareListChildrenOf(taxon, classification, true);
216
        Long count = (Long) query.uniqueResult();
217
        return count;
218
    }
219

    
220
    @Override
221
    public Long countSiblingsOf(Taxon taxon, Classification classification){
222
        Query query = prepareListSiblingsOf(taxon, classification, true);
223
        Long count = (Long) query.uniqueResult();
224
        return count;
225
    }
226

    
227
    private Query prepareListChildrenOf(Taxon taxon, Classification classification, boolean doCount){
228

    
229
    	String selectWhat = doCount ? "count(cn)" : "cn";
230

    
231
         String hql = "select " + selectWhat + " from TaxonNode as tn JOIN tn.classification as c JOIN tn.taxon as t JOIN tn.childNodes as cn "
232
                 + "where t = :taxon and c = :classification";
233
         Query query = getSession().createQuery(hql);
234
         query.setParameter("taxon", taxon);
235
         query.setParameter("classification", classification);
236
         return query;
237
    }
238

    
239
    private Query prepareListSiblingsOf(Taxon taxon, Classification classification, boolean doCount){
240

    
241
        String selectWhat = doCount ? "count(tn)" : "tn";
242

    
243
         String subSelect = "SELECT tn.parent FROM TaxonNode as tn JOIN tn.classification as c JOIN tn.taxon as t "
244
                 + "WHERE t = :taxon AND c = :classification";
245
         String hql = "SELECT " + selectWhat + " FROM TaxonNode as tn WHERE tn.parent IN ( " + subSelect + ")";
246
         Query query = getSession().createQuery(hql);
247
         query.setParameter("taxon", taxon);
248
         query.setParameter("classification", classification);
249
         return query;
250
    }
251

    
252

    
253
    @Override
254
    public UUID delete(Classification persistentObject){
255
        //delete all childnodes, then delete the tree
256

    
257
        List<TaxonNode> nodes = persistentObject.getChildNodes();
258
        List<TaxonNode> nodesTmp = new ArrayList<TaxonNode>(nodes);
259

    
260
//        Iterator<TaxonNode> nodesIterator = nodes.iterator();
261
        for(TaxonNode node : nodesTmp){
262
            persistentObject.deleteChildNode(node, true);
263
            taxonNodeDao.delete(node, true);
264
        }
265

    
266
        TaxonNode rootNode = persistentObject.getRootNode();
267
        persistentObject.removeRootNode();
268
        taxonNodeDao.delete(rootNode);
269
        super.delete(persistentObject);
270

    
271
        return persistentObject.getUuid();
272
    }
273

    
274
    @Override
275
    public ClassificationLookupDTO classificationLookup(Classification classification) {
276

    
277
        ClassificationLookupDTO classificationLookupDTO = new ClassificationLookupDTO(classification);
278

    
279
        // only for debugging:
280
//        logger.setLevel(Level.TRACE);
281
//        Logger.getLogger("org.hibernate.SQL").setLevel(Level.DEBUG);
282

    
283
        String hql = "select t.id, n.rank, tp.id from TaxonNode as tn join tn.classification as c join tn.taxon as t join t.name as n "
284
                + " left join tn.parent as tnp left join tnp.taxon as tp "
285
                + " where c = :classification";
286
        Query query = getSession().createQuery(hql);
287
        query.setParameter("classification", classification);
288
        @SuppressWarnings("unchecked")
289
        List<Object[]> result = query.list();
290
        for(Object[] row : result) {
291
            Integer parentId = null;
292
            parentId = (Integer) row[2];
293
            classificationLookupDTO.add((Integer)row[0], (Rank)row[1], parentId);
294
        }
295

    
296
        return classificationLookupDTO ;
297
    }
298

    
299
    @Override
300
    public Map<UUID, String> treeIndexForTaxonUuids(UUID classificationUuid,
301
            List<UUID> taxonUuids) {
302
        String hql = " SELECT t.uuid, tn.treeIndex "
303
                + " FROM Taxon t JOIN t.taxonNodes tn "
304
                + " WHERE (1=1)"
305
                + "     AND tn.classification.uuid = :classificationUuid "
306
                + "     AND t.uuid IN (:taxonUuids) "
307
                ;
308
        Query query =  getSession().createQuery(hql);
309
        query.setParameter("classificationUuid", classificationUuid);
310
        query.setParameterList("taxonUuids", taxonUuids);
311

    
312
        Map<UUID, String> result = new HashMap<>();
313
        @SuppressWarnings("unchecked")
314
        List<Object[]> list = query.list();
315
        for (Object[] o : list){
316
            result.put((UUID)o[0], (String)o[1]);
317
        }
318
        return result;
319
    }
320

    
321

    
322
    /**
323
     * {@inheritDoc}
324
     */
325
    @Override
326
    public Map<UUID, UUID> getTaxonNodeUuidByTaxonUuid(UUID classificationUuid, List<UUID> taxonUuids) {
327
        String hql = " SELECT t.uuid, tn.uuid "
328
                + " FROM Taxon t JOIN t.taxonNodes tn "
329
                + " WHERE (1=1)"
330
                + "     AND tn.classification.uuid = :classificationUuid "
331
                + "     AND t.uuid IN (:taxonUuids) "
332
                ;
333
        Query query =  getSession().createQuery(hql);
334
        query.setParameter("classificationUuid", classificationUuid);
335
        query.setParameterList("taxonUuids", taxonUuids);
336

    
337
        Map<UUID, UUID> result = new HashMap<>();
338
        @SuppressWarnings("unchecked")
339
        List<Object[]> list = query.list();
340
        for (Object[] o : list){
341
            result.put((UUID)o[0], (UUID)o[1]);
342
        }
343
        return result;
344
    }
345

    
346

    
347

    
348
}
(1-1/4)