2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.taxon
;
11 import java
.util
.ArrayList
;
12 import java
.util
.List
;
14 import java
.util
.UUID
;
16 import org
.apache
.log4j
.Logger
;
17 import org
.apache
.lucene
.analysis
.SimpleAnalyzer
;
18 import org
.apache
.lucene
.queryParser
.ParseException
;
19 import org
.apache
.lucene
.queryParser
.QueryParser
;
20 import org
.apache
.lucene
.search
.Sort
;
21 import org
.apache
.lucene
.search
.SortField
;
22 import org
.hibernate
.Criteria
;
23 import org
.hibernate
.FetchMode
;
24 import org
.hibernate
.Hibernate
;
25 import org
.hibernate
.LazyInitializationException
;
26 import org
.hibernate
.Query
;
27 import org
.hibernate
.criterion
.Criterion
;
28 import org
.hibernate
.criterion
.Projections
;
29 import org
.hibernate
.criterion
.Restrictions
;
30 import org
.hibernate
.search
.FullTextSession
;
31 import org
.hibernate
.search
.Search
;
32 import org
.hibernate
.search
.SearchFactory
;
33 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
34 import org
.springframework
.beans
.factory
.annotation
.Qualifier
;
35 import org
.springframework
.dao
.DataAccessException
;
36 import org
.springframework
.stereotype
.Repository
;
38 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
39 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
40 import eu
.etaxonomy
.cdm
.model
.common
.OriginalSource
;
41 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
42 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
43 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
44 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceBase
;
45 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
46 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationship
;
47 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
48 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
49 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
50 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
51 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
52 import eu
.etaxonomy
.cdm
.persistence
.dao
.QueryParseException
;
53 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ITitledDao
;
54 import eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.AlternativeSpellingSuggestionParser
;
55 import eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.common
.IdentifiableDaoBase
;
56 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonDao
;
57 import eu
.etaxonomy
.cdm
.persistence
.fetch
.CdmFetch
;
65 @Qualifier("taxonDaoHibernateImpl")
66 public class TaxonDaoHibernateImpl
extends IdentifiableDaoBase
<TaxonBase
> implements ITaxonDao
{
67 private AlternativeSpellingSuggestionParser
<TaxonBase
> alternativeSpellingSuggestionParser
;
69 private static final Logger logger
= Logger
.getLogger(TaxonDaoHibernateImpl
.class);
71 public TaxonDaoHibernateImpl() {
72 super(TaxonBase
.class);
75 @Autowired(required
= false) //TODO switched of because it caused problems when starting CdmApplicationController
76 public void setAlternativeSpellingSuggestionParser(AlternativeSpellingSuggestionParser
<TaxonBase
> alternativeSpellingSuggestionParser
) {
77 this.alternativeSpellingSuggestionParser
= alternativeSpellingSuggestionParser
;
81 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase)
83 public List
<Taxon
> getRootTaxa(ReferenceBase sec
) {
84 return getRootTaxa(sec
, CdmFetch
.FETCH_CHILDTAXA(), true, false);
90 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase, eu.etaxonomy.cdm.persistence.fetch.CdmFetch, java.lang.Boolean, java.lang.Boolean)
92 public List
<Taxon
> getRootTaxa(ReferenceBase sec
, CdmFetch cdmFetch
, Boolean onlyWithChildren
, Boolean withMisapplications
) {
93 if (onlyWithChildren
== null){
94 onlyWithChildren
= true;
96 if (withMisapplications
== null){
97 withMisapplications
= true;
99 if (cdmFetch
== null){
100 cdmFetch
= CdmFetch
.NO_FETCH();
104 // String query = "from Taxon root ";
105 // query += " where root.taxonomicParentCache is NULL ";
107 // query += " AND root.sec.id = :sec ";
109 // Query q = getSession().createQuery(query);
111 // q.setInteger("sec", sec.getId());
115 Criteria crit
= getSession().createCriteria(Taxon
.class);
116 crit
.add(Restrictions
.isNull("taxonomicParentCache"));
118 crit
.add(Restrictions
.eq("sec", sec
) );
122 if (! cdmFetch
.includes(CdmFetch
.FETCH_CHILDTAXA())){
123 logger
.warn("no child taxa fetch");
124 //TODO overwrite LAZY (SELECT) does not work (bug in hibernate?)
125 crit
.setFetchMode("relationsToThisTaxon.fromTaxon", FetchMode
.LAZY
);
128 List
<Taxon
> results
= new ArrayList
<Taxon
>();
129 for(Taxon taxon
: (List
<Taxon
>) crit
.list()){
131 //TODO create restriction instead
132 if (onlyWithChildren
== false || taxon
.hasTaxonomicChildren()){
133 if (withMisapplications
== true || ! taxon
.isMisappliedName()){
141 public List
<TaxonBase
> getTaxaByName(String queryString
, ReferenceBase sec
) {
143 return getTaxaByName(queryString
, true, sec
);
146 public List
<TaxonBase
> getTaxaByName(String queryString
, Boolean accepted
, ReferenceBase sec
) {
148 Criteria criteria
= null;
149 if (accepted
== true) {
150 criteria
= getSession().createCriteria(Taxon
.class);
152 criteria
= getSession().createCriteria(Synonym
.class);
155 criteria
.setFetchMode( "name", FetchMode
.JOIN
);
156 criteria
.createAlias("name", "name");
159 if(sec
.getId() == 0){
160 getSession().save(sec
);
162 criteria
.add(Restrictions
.eq("sec", sec
) );
164 if (queryString
!= null) {
165 criteria
.add(Restrictions
.ilike("name.nameCache", queryString
));
167 List
<TaxonBase
> results
= criteria
.list();
171 public List
<TaxonBase
> getAllTaxonBases(Integer pagesize
, Integer page
) {
172 Criteria crit
= getSession().createCriteria(TaxonBase
.class);
173 List
<TaxonBase
> results
= crit
.list();
174 // TODO add page & pagesize criteria
178 public List
<Synonym
> getAllSynonyms(Integer limit
, Integer start
) {
179 Criteria crit
= getSession().createCriteria(Synonym
.class);
180 List
<Synonym
> results
= crit
.list();
184 public List
<Taxon
> getAllTaxa(Integer limit
, Integer start
) {
185 Criteria crit
= getSession().createCriteria(Taxon
.class);
186 List
<Taxon
> results
= crit
.list();
190 public List
<RelationshipBase
> getAllRelationships(Integer limit
, Integer start
) {
191 Criteria crit
= getSession().createCriteria(RelationshipBase
.class);
192 List
<RelationshipBase
> results
= crit
.list();
197 public UUID
delete(TaxonBase taxonBase
) throws DataAccessException
{
198 //getSession().update(taxonBase); doesn't work with lazy collections
199 if (taxonBase
== null){
200 logger
.warn("TaxonBase was 'null'");
205 Set
<Annotation
> annotations
= taxonBase
.getAnnotations();
206 for (Annotation annotation
: annotations
){
207 taxonBase
.removeAnnotation(annotation
);
209 } catch (LazyInitializationException e
) {
210 logger
.warn("LazyInitializationException: " + e
);
214 Set
<Marker
> markers
= taxonBase
.getMarkers();
215 for (Marker marker
: markers
){
216 taxonBase
.removeMarker(marker
);
218 } catch (LazyInitializationException e
) {
219 logger
.warn("LazyInitializationException: " + e
);
223 Set
<OriginalSource
> origSources
= taxonBase
.getSources();
224 for (OriginalSource source
: origSources
){
225 taxonBase
.removeSource(source
);
227 } catch (LazyInitializationException e
) {
228 logger
.warn("LazyInitializationException: " + e
);
231 TaxonNameBase taxonNameBase
=taxonBase
.getName();
232 if (taxonNameBase
!= null){
233 taxonNameBase
.removeTaxonBase(taxonBase
);
235 if (taxonBase
instanceof Taxon
){
237 Taxon taxon
= (Taxon
)taxonBase
;
238 Set
<TaxonRelationship
> taxRels
= taxon
.getTaxonRelations();
239 for (TaxonRelationship taxRel
: taxRels
){
240 taxon
.removeTaxonRelation(taxRel
);
242 //SynonymRelationships
243 Set
<SynonymRelationship
> synRels
= taxon
.getSynonymRelations();
244 for (SynonymRelationship synRel
: synRels
){
245 taxon
.removeSynonymRelation(synRel
);
248 else if (taxonBase
instanceof Synonym
){
249 Synonym synonym
= (Synonym
)taxonBase
;
250 Set
<SynonymRelationship
> synRels
= synonym
.getSynonymRelations();
251 for (SynonymRelationship synRel
: synRels
){
252 synonym
.removeSynonymRelation(synRel
);
255 return super.delete(taxonBase
);
259 // TODO add generic return type !!
260 public List
findByName(String queryString
, ITitledDao
.MATCH_MODE matchMode
, int page
, int pagesize
, boolean onlyAcccepted
) {
261 ArrayList
<Criterion
> criteria
= new ArrayList
<Criterion
>();
262 //TODO ... Restrictions.eq(propertyName, value)
263 return super.findByTitle(queryString
, matchMode
, page
, pagesize
, criteria
);
267 public int countMatchesByName(String queryString
, ITitledDao
.MATCH_MODE matchMode
, boolean onlyAcccepted
) {
269 Criteria crit
= getSession().createCriteria(type
);
270 crit
.add(Restrictions
.ilike("persistentTitleCache", matchMode
.queryStringFrom(queryString
)));
271 crit
.setProjection(Projections
.rowCount());
272 int result
= ((Integer
)crit
.list().get(0)).intValue();
277 public int countMatchesByName(String queryString
, ITitledDao
.MATCH_MODE matchMode
, boolean onlyAcccepted
, List
<Criterion
> criteria
) {
279 Criteria crit
= getSession().createCriteria(type
);
280 crit
.add(Restrictions
.ilike("persistentTitleCache", matchMode
.queryStringFrom(queryString
)));
281 if(criteria
!= null){
282 for (Criterion criterion
: criteria
) {
286 crit
.setProjection(Projections
.rowCount());
287 int result
= ((Integer
)crit
.list().get(0)).intValue();
291 public int countRelatedTaxa(Taxon taxon
, TaxonRelationshipType type
) {
295 query
= getSession().createQuery("select count(taxonRelationship) from TaxonRelationship taxonRelationship where taxonRelationship.relatedTo = :relatedTo");
297 query
= getSession().createQuery("select count(taxonRelationship) from TaxonRelationship taxonRelationship where taxonRelationship.relatedTo = :relatedTo and taxonRelationship.type = :type");
298 query
.setParameter("type",type
);
301 query
.setParameter("relatedTo", taxon
);
303 return ((Long
)query
.uniqueResult()).intValue();
306 public int countSynonyms(Taxon taxon
, SynonymRelationshipType type
) {
310 query
= getSession().createQuery("select count(synonymRelationship) from SynonymRelationship synonymRelationship where synonymRelationship.relatedTo = :relatedTo");
312 query
= getSession().createQuery("select count(synonymRelationship) from SynonymRelationship synonymRelationship where synonymRelationship.relatedTo = :relatedTo and synonymRelationship.type = :type");
313 query
.setParameter("type",type
);
316 query
.setParameter("relatedTo", taxon
);
318 return ((Long
)query
.uniqueResult()).intValue();
321 public int countTaxa(String queryString
, Boolean accepted
) {
322 QueryParser queryParser
= new QueryParser("name.persistentTitleCache", new SimpleAnalyzer());
325 org
.apache
.lucene
.search
.Query query
= queryParser
.parse(queryString
);
327 FullTextSession fullTextSession
= Search
.createFullTextSession(this.getSession());
328 org
.hibernate
.search
.FullTextQuery fullTextQuery
= null;
330 if(accepted
== null) {
331 fullTextQuery
= fullTextSession
.createFullTextQuery(query
, TaxonBase
.class);
334 fullTextQuery
= fullTextSession
.createFullTextQuery(query
, Taxon
.class);
336 fullTextQuery
= fullTextSession
.createFullTextQuery(query
, Synonym
.class);
340 Integer result
= fullTextQuery
.getResultSize();
343 } catch (ParseException e
) {
344 throw new QueryParseException(e
, queryString
);
348 public int countTaxaByName(String queryString
, Boolean accepted
, ReferenceBase sec
) {
350 Criteria criteria
= null;
352 if (accepted
== true) {
353 criteria
= getSession().createCriteria(Taxon
.class);
355 criteria
= getSession().createCriteria(Synonym
.class);
358 criteria
.setFetchMode( "name", FetchMode
.JOIN
);
359 criteria
.createAlias("name", "name");
362 if(sec
.getId() == 0){
363 getSession().save(sec
);
365 criteria
.add(Restrictions
.eq("sec", sec
) );
367 if (queryString
!= null) {
368 criteria
.add(Restrictions
.ilike("name.nameCache", queryString
));
370 criteria
.setProjection(Projections
.projectionList().add(Projections
.rowCount()));
372 return (Integer
)criteria
.uniqueResult();
375 public int countTaxaByName(Boolean accepted
, String genusOrUninomial
, String infraGenericEpithet
, String specificEpithet
, String infraSpecificEpithet
, Rank rank
) {
376 Criteria criteria
= null;
378 if(accepted
== null) {
379 criteria
= getSession().createCriteria(TaxonBase
.class);
382 criteria
= getSession().createCriteria(Taxon
.class);
384 criteria
= getSession().createCriteria(Synonym
.class);
388 criteria
.setFetchMode( "name", FetchMode
.JOIN
);
389 criteria
.createAlias("name", "name");
391 if(genusOrUninomial
!= null) {
392 criteria
.add(Restrictions
.eq("name.genusOrUninomial", genusOrUninomial
));
395 if(infraGenericEpithet
!= null) {
396 criteria
.add(Restrictions
.eq("name.infraGenericEpithet", infraGenericEpithet
));
399 if(specificEpithet
!= null) {
400 criteria
.add(Restrictions
.eq("name.specificEpithet", specificEpithet
));
403 if(infraSpecificEpithet
!= null) {
404 criteria
.add(Restrictions
.eq("name.infraSpecificEpithet", infraSpecificEpithet
));
408 criteria
.add(Restrictions
.eq("name.rank", rank
));
411 criteria
.setProjection(Projections
.projectionList().add(Projections
.rowCount()));
413 return (Integer
)criteria
.uniqueResult();
416 public List
<TaxonBase
> findTaxaByName(Boolean accepted
, String genusOrUninomial
, String infraGenericEpithet
, String specificEpithet
, String infraSpecificEpithet
, Rank rank
, Integer pageSize
, Integer pageNumber
) {
417 Criteria criteria
= null;
419 if(accepted
== null) {
420 criteria
= getSession().createCriteria(TaxonBase
.class);
423 criteria
= getSession().createCriteria(Taxon
.class);
425 criteria
= getSession().createCriteria(Synonym
.class);
429 criteria
.setFetchMode( "name", FetchMode
.JOIN
);
430 criteria
.createAlias("name", "name");
432 if(genusOrUninomial
!= null) {
433 criteria
.add(Restrictions
.eq("name.genusOrUninomial", genusOrUninomial
));
436 if(infraGenericEpithet
!= null) {
437 criteria
.add(Restrictions
.eq("name.infraGenericEpithet", infraGenericEpithet
));
439 criteria
.add(Restrictions
.isNull("name.infraGenericEpithet"));
442 if(specificEpithet
!= null) {
443 criteria
.add(Restrictions
.eq("name.specificEpithet", specificEpithet
));
446 if(infraSpecificEpithet
!= null) {
447 criteria
.add(Restrictions
.eq("name.infraSpecificEpithet", infraSpecificEpithet
));
451 criteria
.add(Restrictions
.eq("name.rank", rank
));
454 if(pageSize
!= null) {
455 criteria
.setMaxResults(pageSize
);
456 if(pageNumber
!= null) {
457 criteria
.setFirstResult(pageNumber
* pageSize
);
459 criteria
.setFirstResult(0);
463 return (List
<TaxonBase
>)criteria
.list();
466 public List
<TaxonRelationship
> getRelatedTaxa(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
) {
470 query
= getSession().createQuery("select taxonRelationship from TaxonRelationship taxonRelationship join fetch taxonRelationship.relatedFrom where taxonRelationship.relatedTo = :relatedTo");
472 query
= getSession().createQuery("select taxonRelationship from TaxonRelationship taxonRelationship join fetch taxonRelationship.relatedFrom where taxonRelationship.relatedTo = :relatedTo and taxonRelationship.type = :type");
473 query
.setParameter("type",type
);
476 query
.setParameter("relatedTo", taxon
);
478 if(pageSize
!= null) {
479 query
.setMaxResults(pageSize
);
480 if(pageNumber
!= null) {
481 query
.setFirstResult(pageNumber
* pageSize
);
483 query
.setFirstResult(0);
487 return (List
<TaxonRelationship
>)query
.list();
490 public List
<SynonymRelationship
> getSynonyms(Taxon taxon
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
) {
494 query
= getSession().createQuery("select synonymRelationship from SynonymRelationship synonymRelationship join fetch synonymRelationship.relatedFrom where synonymRelationship.relatedTo = :relatedTo");
496 query
= getSession().createQuery("select synonymRelationship from SynonymRelationship synonymRelationship join fetch synonymRelationship.relatedFrom where synonymRelationship.relatedTo = :relatedTo and synonymRelationship.type = :type");
497 query
.setParameter("type",type
);
500 query
.setParameter("relatedTo", taxon
);
502 if(pageSize
!= null) {
503 query
.setMaxResults(pageSize
);
504 if(pageNumber
!= null) {
505 query
.setFirstResult(pageNumber
* pageSize
);
507 query
.setFirstResult(0);
511 return (List
<SynonymRelationship
>)query
.list();
514 public List
<TaxonBase
> searchTaxa(String queryString
, Boolean accepted
, Integer pageSize
, Integer pageNumber
) {
515 QueryParser queryParser
= new QueryParser("name.persistentTitleCache", new SimpleAnalyzer());
516 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
519 org
.apache
.lucene
.search
.Query query
= queryParser
.parse(queryString
);
521 FullTextSession fullTextSession
= Search
.createFullTextSession(getSession());
522 org
.hibernate
.search
.FullTextQuery fullTextQuery
= null;
523 Criteria criteria
= null;
525 if(accepted
== null) {
526 fullTextQuery
= fullTextSession
.createFullTextQuery(query
, TaxonBase
.class);
527 criteria
= getSession().createCriteria( TaxonBase
.class );
530 fullTextQuery
= fullTextSession
.createFullTextQuery(query
, Taxon
.class);
531 criteria
= getSession().createCriteria( Taxon
.class );
533 fullTextQuery
= fullTextSession
.createFullTextQuery(query
, Synonym
.class);
534 criteria
= getSession().createCriteria( Synonym
.class );
538 org
.apache
.lucene
.search
.Sort sort
= new Sort(new SortField("name.titleCache_forSort"));
539 fullTextQuery
.setSort(sort
);
541 criteria
.setFetchMode( "name", FetchMode
.JOIN
);
542 fullTextQuery
.setCriteriaQuery(criteria
);
544 if(pageSize
!= null) {
545 fullTextQuery
.setMaxResults(pageSize
);
546 if(pageNumber
!= null) {
547 fullTextQuery
.setFirstResult(pageNumber
* pageSize
);
549 fullTextQuery
.setFirstResult(0);
553 return (List
<TaxonBase
>)fullTextQuery
.list();
555 } catch (ParseException e
) {
556 throw new QueryParseException(e
, queryString
);
560 public void purgeIndex() {
561 FullTextSession fullTextSession
= Search
.createFullTextSession(getSession());
563 fullTextSession
.purgeAll(type
); // remove all taxon base from indexes
564 // fullTextSession.flushToIndexes() not implemented in 3.0.0.GA
567 public void rebuildIndex() {
568 FullTextSession fullTextSession
= Search
.createFullTextSession(getSession());
570 for(TaxonBase taxonBase
: list(null,null)) { // re-index all taxon base
571 Hibernate
.initialize(taxonBase
.getName());
572 fullTextSession
.index(taxonBase
);
574 // fullTextSession.flushToIndexes() not implemented in 3.0.0.GA
577 public void optimizeIndex() {
578 FullTextSession fullTextSession
= Search
.createFullTextSession(getSession());
579 SearchFactory searchFactory
= fullTextSession
.getSearchFactory();
580 searchFactory
.optimize(type
); // optimize the indices ()
581 // fullTextSession.flushToIndexes() not implemented in 3.0.0.GA
584 public String
suggestQuery(String queryString
) {
586 String alternativeQueryString
= null;
587 alternativeSpellingSuggestionParser
.parse(queryString
);
588 org
.apache
.lucene
.search
.Query alternativeQuery
= alternativeSpellingSuggestionParser
.suggest(queryString
);
589 if(alternativeQuery
!= null) {
590 alternativeQueryString
= alternativeQuery
.toString("name.persistentTitleCache");
592 return alternativeQueryString
;
593 } catch (ParseException e
) {
594 throw new QueryParseException(e
, queryString
);