Project

General

Profile

Download (14.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9

    
10
package eu.etaxonomy.cdm.persistence.dao.hibernate.taxon;
11

    
12
import java.util.ArrayList;
13
import java.util.HashMap;
14
import java.util.HashSet;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.Set;
18
import java.util.UUID;
19

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

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

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

    
48
    @Autowired
49
    private ITaxonNodeDao taxonNodeDao;
50

    
51
    public ClassificationDaoHibernateImpl() {
52
        super(Classification.class);
53
        indexedClasses = new Class[1];
54
        indexedClasses[0] = Classification.class;
55
    }
56

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

    
62
        List<TaxonNode> results = new ArrayList<TaxonNode>();
63
        Query[] queries = prepareRankSpecificRootNodes(classification, rank, false);
64

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

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

    
83
        return results;
84

    
85
    }
86

    
87
    @Override
88
    public long[] countRankSpecificRootNodes(Classification classification, Rank rank) {
89

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

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

    
113
        String whereClassification = "";
114
        if (classification != null){
115
            whereClassification = " AND tn.classification = :classification ";
116
        }
117

    
118
        String selectWhat = doCount ? "count(distinct tn)" : "distinct tn";
119

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

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

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

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

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

    
171
         setPagingParameter(query, pageSize, pageIndex);
172

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

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

    
187
        Query query = getSession().createQuery(queryString);
188
        query.setParameter("classificationUuid", classificationUuid);
189

    
190

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

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

    
202
         setPagingParameter(query, pageSize, pageIndex);
203

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

    
214

    
215

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

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

    
230
    private Query prepareListChildrenOf(Taxon taxon, Classification classification, boolean doCount){
231

    
232
    	String selectWhat = doCount ? "count(cn)" : "cn";
233

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

    
242
    private Query prepareListSiblingsOf(Taxon taxon, Classification classification, boolean doCount){
243

    
244
        String selectWhat = doCount ? "count(tn)" : "tn";
245

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

    
255

    
256
    @Override
257
    public UUID delete(Classification persistentObject){
258
        //delete all child nodes, then delete the tree
259

    
260
        List<TaxonNode> nodes = persistentObject.getChildNodes();
261
        List<TaxonNode> nodesTmp = new ArrayList<TaxonNode>(nodes);
262

    
263
//        Iterator<TaxonNode> nodesIterator = nodes.iterator();
264
        for(TaxonNode node : nodesTmp){
265
            persistentObject.deleteChildNode(node, true);
266

    
267
            taxonNodeDao.delete(node, true);
268
        }
269

    
270
        TaxonNode rootNode = persistentObject.getRootNode();
271
        persistentObject.removeRootNode();
272
        taxonNodeDao.delete(rootNode);
273
        UUID uuid =super.delete(persistentObject);
274

    
275

    
276
        return persistentObject.getUuid();
277
    }
278

    
279
    @Override
280
    public ClassificationLookupDTO classificationLookup(Classification classification) {
281

    
282
        ClassificationLookupDTO classificationLookupDTO = new ClassificationLookupDTO(classification);
283

    
284
        // only for debugging:
285
//        logger.setLevel(Level.TRACE);
286
//        Logger.getLogger("org.hibernate.SQL").setLevel(Level.DEBUG);
287

    
288
        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 "
289
                + " left join tn.parent as tnp left join tnp.taxon as tp "
290
                + " where c = :classification";
291
        Query query = getSession().createQuery(hql);
292
        query.setParameter("classification", classification);
293
        @SuppressWarnings("unchecked")
294
        List<Object[]> result = query.list();
295
        for(Object[] row : result) {
296
            Integer parentId = null;
297
            parentId = (Integer) row[2];
298
            classificationLookupDTO.add((Integer)row[0], (Rank)row[1], parentId);
299
        }
300

    
301
        return classificationLookupDTO ;
302
    }
303

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

    
317
        Map<UUID, TreeIndex> result = new HashMap<>();
318
        @SuppressWarnings("unchecked")
319
        List<Object[]> list = query.list();
320
        for (Object[] o : list){
321
            result.put((UUID)o[0], TreeIndex.NewInstance((String)o[1]));
322
        }
323
        return result;
324
    }
325

    
326
    @Override
327
    public Set<TreeIndex> getMarkedTreeIndexes(MarkerType markerType, Boolean flag){
328
        String hql = " SELECT tn.treeIndex "
329
                + " FROM Taxon t JOIN t.taxonNodes tn "
330
                + "     JOIN t.markers m "
331
                + " WHERE (1=1)"
332
                + "   AND m.markerType = :markerType "
333
                ;
334
        if (flag != null){
335
            hql += "  AND m.flag = :flag ";
336

    
337
        }
338

    
339
        Query query =  getSession().createQuery(hql);
340
        if (flag != null){
341
            query.setParameter("flag", flag);
342
        }
343
        query.setParameter("markerType", markerType);
344

    
345
        Set<TreeIndex> result = new HashSet<>();
346
        @SuppressWarnings("unchecked")
347
        List<String> list = query.list();
348
        for (String o : list){
349
            result.add(TreeIndex.NewInstance(o));
350
        }
351
        return result;
352
    }
353

    
354
    @Override
355
    public Map<UUID, UUID> getTaxonNodeUuidByTaxonUuid(UUID classificationUuid, List<UUID> taxonUuids) {
356
        String hql = " SELECT t.uuid, tn.uuid "
357
                + " FROM Taxon t JOIN t.taxonNodes tn "
358
                + " WHERE (1=1)"
359
                + "     AND tn.classification.uuid = :classificationUuid "
360
                + "     AND t.uuid IN (:taxonUuids) "
361
                ;
362
        Query query =  getSession().createQuery(hql);
363
        query.setParameter("classificationUuid", classificationUuid);
364
        query.setParameterList("taxonUuids", taxonUuids);
365

    
366
        Map<UUID, UUID> result = new HashMap<>();
367
        @SuppressWarnings("unchecked")
368
        List<Object[]> list = query.list();
369
        for (Object[] o : list){
370
            result.put((UUID)o[0], (UUID)o[1]);
371
        }
372
        return result;
373
    }
374

    
375
}
(1-1/4)