Project

General

Profile

Download (21.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.math.BigInteger;
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.List;
19
import java.util.Map;
20
import java.util.Set;
21
import java.util.UUID;
22

    
23
import org.apache.log4j.Logger;
24
import org.hibernate.Criteria;
25
import org.hibernate.Hibernate;
26
import org.hibernate.Query;
27
import org.hibernate.criterion.Projections;
28
import org.hibernate.criterion.Restrictions;
29
import org.springframework.beans.factory.annotation.Autowired;
30
import org.springframework.beans.factory.annotation.Qualifier;
31
import org.springframework.stereotype.Repository;
32

    
33
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
34
import eu.etaxonomy.cdm.model.common.TreeIndex;
35
import eu.etaxonomy.cdm.model.reference.Reference;
36
import eu.etaxonomy.cdm.model.taxon.Classification;
37
import eu.etaxonomy.cdm.model.taxon.Synonym;
38
import eu.etaxonomy.cdm.model.taxon.Taxon;
39
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
40
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
41
import eu.etaxonomy.cdm.model.taxon.TaxonNodeAgentRelation;
42
import eu.etaxonomy.cdm.persistence.dao.hibernate.common.AnnotatableDaoImpl;
43
import eu.etaxonomy.cdm.persistence.dao.taxon.IClassificationDao;
44
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
45
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
46
import eu.etaxonomy.cdm.persistence.dto.MergeResult;
47
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
48

    
49
/**
50
 * @author a.mueller
51
 * @created 16.06.2009
52
 */
53
@Repository
54
@Qualifier("taxonNodeDaoHibernateImpl")
55
public class TaxonNodeDaoHibernateImpl extends AnnotatableDaoImpl<TaxonNode>
56
		implements ITaxonNodeDao {
57
	@SuppressWarnings("unused")
58
	private static final Logger logger = Logger.getLogger(TaxonNodeDaoHibernateImpl.class);
59

    
60
	@Autowired
61
	private ITaxonDao taxonDao;
62
	@Autowired
63
	private IClassificationDao classificationDao;
64

    
65
	public TaxonNodeDaoHibernateImpl() {
66
		super(TaxonNode.class);
67
	}
68
	@Override
69
	public UUID delete(TaxonNode persistentObject, boolean deleteChildren){
70
		Taxon taxon = persistentObject.getTaxon();
71
		taxon = HibernateProxyHelper.deproxy(taxon, Taxon.class);
72

    
73
		/*Session session = this.getSession();
74
		Query query = session.createQuery("from TaxonNode t where t.taxon = :taxon");
75
		query.setParameter("taxon", taxon);
76
		List result = query.list();*/
77
		if (taxon != null){
78
		    Hibernate.initialize(taxon);
79
		    Hibernate.initialize(taxon.getTaxonNodes());
80
			Set<TaxonNode> nodes = taxon.getTaxonNodes();
81
			//Hibernate.initialize(taxon.getTaxonNodes());
82
			for (TaxonNode node:nodes) {
83
			    System.out.println("Number of nodes: " + nodes.size());
84
                node = HibernateProxyHelper.deproxy(node, TaxonNode.class);
85

    
86
			    if (node.equals(persistentObject)){
87
			        if (node.hasChildNodes()){
88
			            Iterator<TaxonNode> childNodes = node.getChildNodes().iterator();
89
			            TaxonNode childNode;
90
			            List<TaxonNode> listForDeletion = new ArrayList<TaxonNode>();
91
	                    while (childNodes.hasNext()){
92
	                        childNode = childNodes.next();
93
	                        listForDeletion.add(childNode);
94
	                        childNodes.remove();
95

    
96
	                    }
97
	                    for (TaxonNode deleteNode:listForDeletion){
98
	                        delete(deleteNode, deleteChildren);
99
	                    }
100
	                }
101

    
102
			        taxon.removeTaxonNode(node, deleteChildren);
103
			        taxonDao.saveOrUpdate(taxon);
104
    				taxon = HibernateProxyHelper.deproxy(taxonDao.findByUuid(taxon.getUuid()), Taxon.class);
105
    				taxonDao.delete(taxon);
106

    
107
			    }
108
			}
109
		}
110

    
111
		UUID result = super.delete(persistentObject);
112

    
113
		return result;
114
	}
115

    
116
	@Override
117
	public List<TaxonNode> getTaxonOfAcceptedTaxaByClassification(Classification classification, Integer start, Integer end) {
118
		int classificationId = classification.getId();
119
		String limit = "";
120
		if(start !=null && end != null){
121
		    limit = "LIMIT "+start+"," +end;
122
		}
123
		//FIXME write test
124
        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;
125
        @SuppressWarnings("unchecked")
126
        List<TaxonNode> result  = getSession().createSQLQuery(queryString).addEntity(TaxonNode.class).list();
127

    
128
       return result;
129
	}
130

    
131
    @Override
132
    public int countTaxonOfAcceptedTaxaByClassification(Classification classification){
133
        int classificationId = classification.getId();
134
        //FIXME write test
135
        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;
136
         @SuppressWarnings("unchecked")
137
        List<BigInteger> result = getSession().createSQLQuery(queryString).list();
138
         return result.get(0).intValue ();
139
    }
140

    
141
    @Override
142
    public List<UuidAndTitleCache<TaxonNode>> listChildNodesAsUuidAndTitleCache(UuidAndTitleCache<TaxonNode> parent) {
143
        String queryString = "select tn.uuid, tn.id, tx.titleCache from TaxonNode tn INNER JOIN tn.taxon as tx where tn.parent.id = :parentId";
144
        Query query =  getSession().createQuery(queryString);
145
        query.setParameter("parentId", parent.getId());
146
        List<UuidAndTitleCache<TaxonNode>> list = new ArrayList<>();
147

    
148
        @SuppressWarnings("unchecked")
149
        List<Object[]> result = query.list();
150

    
151
        for(Object[] object : result){
152
            list.add(new UuidAndTitleCache<TaxonNode>((UUID) object[0],(Integer) object[1], (String) object[2]));
153
        }
154
        return list;
155
    }
156

    
157
    @Override
158
    public List<UuidAndTitleCache<TaxonNode>> getUuidAndTitleCache(Integer limit, String pattern, UUID classificationUuid) {
159
        String queryString = "select tn.uuid, tn.id, tx.titleCache from TaxonNode tn "
160
        		+ "INNER JOIN tn.taxon as tx "
161
        		+ "INNER JOIN tn.classification as cls "
162
        		+ "WHERE tx.titleCache like :pattern ";
163
        if(classificationUuid!=null){
164
        	queryString += "AND cls.uuid = :classificationUuid";
165
        }
166
        Query query =  getSession().createQuery(queryString);
167

    
168
        query.setParameter("pattern", pattern.toLowerCase()+"%");
169
        query.setParameter("classificationUuid", classificationUuid);
170

    
171
        List<UuidAndTitleCache<TaxonNode>> list = new ArrayList<>();
172

    
173
        @SuppressWarnings("unchecked")
174
        List<Object[]> result = query.list();
175

    
176
        for(Object[] object : result){
177
            list.add(new UuidAndTitleCache<TaxonNode>((UUID) object[0],(Integer) object[1], (String) object[2]));
178
        }
179
        return list;
180
    }
181

    
182
    /**
183
     * {@inheritDoc}
184
     */
185
    @Override
186
    public UuidAndTitleCache<TaxonNode> getParentUuidAndTitleCache(UuidAndTitleCache<TaxonNode> child) {
187
        String queryString = "select tn.parent.uuid, tn.parent.id, tn.parent.taxon.titleCache, tn.parent.classification.titleCache "
188
                + " from TaxonNode tn"
189
                + " LEFT OUTER JOIN tn.parent.taxon"
190
                + " where tn.id = :childId";
191
        Query query =  getSession().createQuery(queryString);
192
        query.setParameter("childId", child.getId());
193
        List<UuidAndTitleCache<TaxonNode>> list = new ArrayList<>();
194

    
195
        @SuppressWarnings("unchecked")
196
        List<Object[]> result = query.list();
197

    
198
        for(Object[] object : result){
199
            UUID uuid = (UUID) object[0];
200
            Integer id = (Integer) object[1];
201
            String taxonTitleCache = (String) object[2];
202
            String classificationTitleCache = (String) object[3];
203
            if(taxonTitleCache!=null){
204
                list.add(new UuidAndTitleCache<TaxonNode>(uuid,id, taxonTitleCache));
205
            }
206
            else{
207
                list.add(new UuidAndTitleCache<TaxonNode>(uuid,id, classificationTitleCache));
208
            }
209
        }
210
        if(list.size()==1){
211
            return list.iterator().next();
212
        }
213
        return null;
214
    }
215

    
216
    @Override
217
    public List<TaxonNode> listChildrenOf(TaxonNode node, Integer pageSize, Integer pageIndex, List<String> propertyPaths, boolean recursive){
218
    	if (recursive == true){
219
    		Criteria crit = getSession().createCriteria(TaxonNode.class);
220
    		crit.add( Restrictions.like("treeIndex", node.treeIndex()+ "%") );
221
    		if(pageSize != null) {
222
                crit.setMaxResults(pageSize);
223
                if(pageIndex != null) {
224
                    crit.setFirstResult(pageIndex * pageSize);
225
                } else {
226
                    crit.setFirstResult(0);
227
                }
228
            }
229
    		@SuppressWarnings("unchecked")
230
            List<TaxonNode> results = crit.list();
231
    		results.remove(node);
232
    		defaultBeanInitializer.initializeAll(results, propertyPaths);
233
    		return results;
234
    	}else{
235
    		return classificationDao.listChildrenOf(node.getTaxon(), node.getClassification(), pageSize, pageIndex, propertyPaths);
236
    	}
237

    
238
    }
239

    
240
    @Override
241
	public Long countChildrenOf(TaxonNode node, Classification classification,
242
			boolean recursive) {
243

    
244
		if (recursive == true){
245
			Criteria crit = getSession().createCriteria(TaxonNode.class);
246
    		crit.add( Restrictions.like("treeIndex", node.treeIndex()+ "%") );
247
    		crit.setProjection(Projections.rowCount());
248
    		return ((Integer)crit.uniqueResult().hashCode()).longValue();
249
		}else{
250
			return classificationDao.countChildrenOf(node.getTaxon(), classification);
251
		}
252
	}
253
    /**
254
     * {@inheritDoc}
255
     */
256
    @Override
257
    public List<TaxonNodeAgentRelation> listTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid,
258
            UUID agentUuid, UUID rankUuid, UUID relTypeUuid, Integer start, Integer limit, List<String> propertyPaths) {
259

    
260

    
261
        StringBuilder hql = prepareListTaxonNodeAgentRelations(taxonUuid, classificationUuid, agentUuid, rankUuid, relTypeUuid, false);
262

    
263
        Query query =  getSession().createQuery(hql.toString());
264

    
265
        if(limit != null) {
266
            query.setMaxResults(limit);
267
            if(start != null) {
268
                query.setFirstResult(start);
269
            }
270
        }
271

    
272
        setParamsForListTaxonNodeAgentRelations(taxonUuid, classificationUuid, agentUuid, rankUuid, relTypeUuid, query);
273

    
274
        @SuppressWarnings("unchecked")
275
        List<TaxonNodeAgentRelation> records = query.list();
276

    
277
        if(propertyPaths != null) {
278
            defaultBeanInitializer.initializeAll(records, propertyPaths);
279
        }
280
        return records;
281
    }
282

    
283
    /**
284
     * {@inheritDoc}
285
     */
286
    @Override
287
    public long countTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid, UUID agentUuid, UUID rankUuid, UUID relTypeUuid) {
288

    
289
        StringBuilder hql = prepareListTaxonNodeAgentRelations(taxonUuid, classificationUuid, agentUuid, rankUuid, relTypeUuid, true);
290
        Query query =  getSession().createQuery(hql.toString());
291

    
292
        setParamsForListTaxonNodeAgentRelations(taxonUuid, classificationUuid, agentUuid, rankUuid, relTypeUuid, query);
293

    
294
        Long count = Long.parseLong(query.uniqueResult().toString());
295

    
296
        return count;
297
    }
298
    /**
299
     * @param taxonUuid
300
     * @param classificationUuid
301
     * @param agentUuid
302
     * @param relTypeUuid TODO
303
     * @param doCount TODO
304
     * @param rankId
305
     *     limit to taxa having this rank, only applies if <code>taxonUuid = null</code>
306
     * @return
307
     */
308
    private StringBuilder prepareListTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid, UUID agentUuid, UUID rankUuid, UUID relTypeUuid, boolean doCount) {
309

    
310
        StringBuilder hql = new StringBuilder();
311

    
312
        String join_fetch_mode = doCount ? "join" : "join fetch";
313

    
314
        if(doCount) {
315
            hql.append("select count(tnar)");
316
        } else {
317
            hql.append("select tnar");
318
        }
319

    
320
        hql.append(" from TaxonNodeAgentRelation as tnar ");
321
        if(taxonUuid != null) {
322
            // taxonUuid is search filter, do not fetch it
323
            hql.append(" join tnar.taxonNode as tn join tn.taxon as t ");
324
        } else {
325
            hql.append(join_fetch_mode).append(" tnar.taxonNode as tn ").append(join_fetch_mode).append(" tn.taxon as t ");
326
            if(rankUuid != null) {
327
                hql.append(" join t.name as n ");
328
            }
329
        }
330
        hql.append(" join tn.classification as c ");
331
        if(agentUuid != null) {
332
            // agentUuid is search filter, do not fetch it
333
//            hql.append(" join tnar.agent as a ");
334
            hql.append(join_fetch_mode).append(" tnar.agent as a ");
335
        } else {
336
            hql.append(join_fetch_mode).append(" tnar.agent as a ");
337
        }
338

    
339
        hql.append(" where 1 = 1 ");
340

    
341
        if(relTypeUuid != null) {
342
            hql.append(" and tnar.type.uuid = :relTypeUuid ");
343
        }
344

    
345
        if(taxonUuid != null) {
346
            hql.append(" and t.uuid = :taxonUuid ");
347
        } else {
348
            if(rankUuid != null) {
349
                hql.append(" and n.rank.uuid = :rankUuid ");
350
            }
351
        }
352
        if(classificationUuid != null) {
353
            hql.append(" and c.uuid = :classificationUuid ");
354
        }
355
        if(agentUuid != null) {
356
            hql.append(" and a.uuid = :agentUuid ");
357
        }
358

    
359
        hql.append(" order by a.titleCache");
360
        return hql;
361
    }
362
    /**
363
     * @param taxonUuid
364
     * @param classificationUuid
365
     * @param agentUuid
366
     * @param relTypeUuid TODO
367
     * @param query
368
     * @param rankId TODO
369
     */
370
    private void setParamsForListTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid, UUID agentUuid,
371
            UUID rankUuid, UUID relTypeUuid, Query query) {
372

    
373
        if(taxonUuid != null) {
374
            query.setParameter("taxonUuid", taxonUuid);
375
        } else {
376
            if(rankUuid != null) {
377
                query.setParameter("rankUuid", rankUuid);
378
            }
379
        }
380
        if(classificationUuid != null) {
381
            query.setParameter("classificationUuid", classificationUuid);
382
        }
383
        if(agentUuid != null) {
384
            query.setParameter("agentUuid", agentUuid);
385
        }
386
        if(relTypeUuid != null) {
387
            query.setParameter("relTypeUuid", relTypeUuid);
388
        }
389
    }
390

    
391
    @Override
392
    public Map<TreeIndex, Integer> rankOrderIndexForTreeIndex(List<TreeIndex> treeIndexes,
393
            Integer minRankOrderIndex,
394
            Integer maxRankOrderIndex) {
395

    
396
        Map<TreeIndex, Integer> result = new HashMap<>();
397
        if (treeIndexes == null || treeIndexes.isEmpty()){
398
            return result;
399
        }
400

    
401
        String hql = " SELECT tn.treeIndex, r.orderIndex "
402
                + " FROM TaxonNode tn JOIN tn.taxon t JOIN t.name n JOIN n.rank r "
403
                + " WHERE tn.treeIndex IN (:treeIndexes) ";
404
        if (minRankOrderIndex != null){
405
            hql += " AND r.orderIndex <= :minOrderIndex";
406
        }
407
        if (maxRankOrderIndex != null){
408
            hql += " AND r.orderIndex >= :maxOrderIndex";
409
        }
410

    
411
        Query query =  getSession().createQuery(hql);
412
        query.setParameterList("treeIndexes", TreeIndex.toString(treeIndexes));
413
        if (minRankOrderIndex != null){
414
            query.setParameter("minOrderIndex", minRankOrderIndex);
415
        }
416
        if (maxRankOrderIndex != null){
417
            query.setParameter("maxOrderIndex", maxRankOrderIndex);
418
        }
419

    
420
        @SuppressWarnings("unchecked")
421
        List<Object[]> list = query.list();
422
        for (Object[] o : list){
423
            result.put(TreeIndex.NewInstance((String)o[0]), (Integer)o[1]);
424
        }
425
        return result;
426
    }
427

    
428
    @Override
429
    public Map<TreeIndex, UuidAndTitleCache<?>> taxonUuidsForTreeIndexes(Collection<TreeIndex> treeIndexes) {
430
        Map<TreeIndex, UuidAndTitleCache<?>> result = new HashMap<>();
431
        if (treeIndexes == null || treeIndexes.isEmpty()){
432
            return result;
433
        }
434

    
435
        String hql = " SELECT tn.treeIndex, t.uuid, tnb.titleCache "
436
                + " FROM TaxonNode tn JOIN tn.taxon t Join t.name tnb "
437
                + " WHERE tn.treeIndex IN (:treeIndexes) ";
438
        Query query =  getSession().createQuery(hql);
439
        query.setParameterList("treeIndexes", TreeIndex.toString(treeIndexes));
440

    
441
        @SuppressWarnings("unchecked")
442
        List<Object[]> list = query.list();
443
        for (Object[] o : list){
444
            result.put(TreeIndex.NewInstance((String)o[0]), new UuidAndTitleCache<>((UUID)o[1], null, (String)o[2]));
445
        }
446
        return result;
447
    }
448

    
449

    
450
    /**
451
     * {@inheritDoc}
452
     */
453
    //#3465
454
    @Override
455
    public Set<TaxonBase> setSecundumForSubtreeAcceptedTaxa(TreeIndex subTreeIndex, Reference newSec, boolean overwriteExisting, boolean includeSharedTaxa, boolean emptyDetail) {
456
        //for some reason this does not work, maybe because the listeners are not activated,
457
        //but also the first taxon for some reason does not get updated in terms of secundum, but only by the udpate listener
458
//        String where = "SELECT t.id FROM TaxonNode tn JOIN tn.taxon t " +
459
//                " WHERE tn.treeIndex like '%s%%' ORDER BY t.id";
460
//        where = String.format(where, subTreeIndex.toString());
461
//        Query query1 = getSession().createQuery(where);
462
//        List l = query1.list();
463
//
464
//        String hql = "UPDATE Taxon SET sec = :newSec, publish=false WHERE id IN (" + where + ")";
465
//        Query query = getSession().createQuery(hql);
466
//        query.setParameter("newSec", newSec);
467
//        int n = query.executeUpdate();
468

    
469
        String queryStr = acceptedForSubtreeQueryStr(includeSharedTaxa, subTreeIndex);
470
        if (!overwriteExisting){
471
            queryStr += " AND t.sec IS NULL ";
472
        }
473
        return setSecundum(newSec, emptyDetail, queryStr);
474

    
475
    }
476

    
477
    @Override
478
    public Set<TaxonBase> setSecundumForSubtreeSynonyms(TreeIndex subTreeIndex, Reference newSec, boolean overwriteExisting, boolean includeSharedTaxa, boolean emptyDetail) {
479

    
480
        String queryStr = synonymForSubtreeQueryStr(includeSharedTaxa, subTreeIndex);
481
        if (!overwriteExisting){
482
            queryStr += " AND syn.sec IS NULL ";
483
        }
484
        return setSecundum(newSec, emptyDetail, queryStr);
485
    }
486
    /**
487
     * @param newSec
488
     * @param emptyDetail
489
     * @param queryStr
490
     * @return
491
     */
492
    private <T extends TaxonBase<?>> Set<T> setSecundum(Reference newSec, boolean emptyDetail, String queryStr) {
493
        Query query = getSession().createQuery(queryStr);
494
        @SuppressWarnings("unchecked")
495
        List<T> synonymList = query.list();
496
        MergeResult mergeResult;
497
        Set<T> result = new HashSet<>();
498
        for (T taxonBase : synonymList){
499
            taxonBase = (T) taxonDao.load(taxonBase.getUuid());
500

    
501
            taxonBase.setSec(newSec);
502
            if (emptyDetail){
503
                taxonBase.setSecMicroReference(null);
504
            }
505

    
506
           result.add(taxonBase);
507

    
508
        }
509
      return result;
510
    }
511

    
512

    
513
    /**
514
     * {@inheritDoc}
515
     */
516
    @Override
517
    public Set<Taxon> setPublishForSubtreeAcceptedTaxa(TreeIndex subTreeIndex, boolean publish,
518
            boolean includeSharedTaxa) {
519
        String queryStr = acceptedForSubtreeQueryStr(includeSharedTaxa, subTreeIndex);
520
        return setPublish(publish, queryStr);
521
    }
522

    
523
    /**
524
     * {@inheritDoc}
525
     */
526
    @Override
527
    public Set<Synonym> setPublishForSubtreeSynonyms(TreeIndex subTreeIndex, boolean publish,
528
            boolean includeSharedTaxa) {
529
        String queryStr = synonymForSubtreeQueryStr(includeSharedTaxa, subTreeIndex);
530
        return setPublish(publish, queryStr);
531
    }
532

    
533
    /**
534
     * @param publish
535
     * @param queryStr
536
     * @return
537
     */
538
    private <T extends TaxonBase<?>> Set<T> setPublish(boolean publish, String queryStr) {
539
        Query query = getSession().createQuery(queryStr);
540
        @SuppressWarnings("unchecked")
541
        List<T> taxonList = query.list();
542
        for (T taxon : taxonList){
543
            taxon.setPublish(publish);
544
        }
545

    
546
        Set<T> result = new HashSet<>(taxonList);
547
        return result;
548
    }
549

    
550

    
551
    /**
552
     * @param includeSharedTaxa
553
     * @param subTreeIndex
554
     * @return
555
     */
556
    private String synonymForSubtreeQueryStr(boolean includeSharedTaxa, TreeIndex subTreeIndex) {
557
        String queryStr = "SELECT syn "
558
                + " FROM TaxonNode tn JOIN tn.taxon t JOIN t.synonyms syn"
559
                + " WHERE tn.treeIndex like '%s%%' ";
560
        if (!includeSharedTaxa){
561
            queryStr += " AND t.taxonNodes.size <= 1  ";
562
        }
563
        queryStr = String.format(queryStr, subTreeIndex.toString());
564

    
565
        return queryStr;
566
    }
567

    
568
    private String acceptedForSubtreeQueryStr(boolean includeSharedTaxa, TreeIndex subTreeIndex) {
569
        String queryStr = "SELECT t "
570
                + " FROM TaxonNode tn JOIN tn.taxon t "
571
                + " WHERE tn.treeIndex like '%s%%' ";
572
        if (!includeSharedTaxa){
573
            queryStr += " AND t.taxonNodes.size <= 1  ";
574
        }
575
        queryStr = String.format(queryStr, subTreeIndex.toString());
576

    
577
        return queryStr;
578
    }
579

    
580

    
581
}
(4-4/5)