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
.lang
.reflect
.Field
;
12 import java
.util
.ArrayList
;
13 import java
.util
.Collection
;
14 import java
.util
.Comparator
;
15 import java
.util
.HashSet
;
16 import java
.util
.Iterator
;
17 import java
.util
.List
;
19 import java
.util
.SortedSet
;
20 import java
.util
.TreeSet
;
21 import java
.util
.UUID
;
23 import org
.apache
.log4j
.Logger
;
24 import org
.apache
.lucene
.analysis
.SimpleAnalyzer
;
25 import org
.apache
.lucene
.queryParser
.ParseException
;
26 import org
.apache
.lucene
.queryParser
.QueryParser
;
27 import org
.hibernate
.Criteria
;
28 import org
.hibernate
.FetchMode
;
29 import org
.hibernate
.Hibernate
;
30 import org
.hibernate
.Query
;
31 import org
.hibernate
.criterion
.Criterion
;
32 import org
.hibernate
.criterion
.Projections
;
33 import org
.hibernate
.criterion
.Restrictions
;
34 import org
.hibernate
.envers
.query
.AuditEntity
;
35 import org
.hibernate
.envers
.query
.AuditQuery
;
36 import org
.hibernate
.search
.FullTextSession
;
37 import org
.hibernate
.search
.Search
;
38 import org
.hibernate
.search
.SearchFactory
;
39 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
40 import org
.springframework
.beans
.factory
.annotation
.Qualifier
;
41 import org
.springframework
.dao
.DataAccessException
;
42 import org
.springframework
.stereotype
.Repository
;
43 import org
.springframework
.util
.ReflectionUtils
;
45 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
46 import eu
.etaxonomy
.cdm
.model
.common
.Extension
;
47 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
48 import eu
.etaxonomy
.cdm
.model
.common
.LSID
;
49 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
50 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
51 import eu
.etaxonomy
.cdm
.model
.common
.UuidAndTitleCache
;
52 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
.Direction
;
53 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
54 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
55 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
56 import eu
.etaxonomy
.cdm
.model
.media
.Rights
;
57 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
58 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceBase
;
59 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
60 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationship
;
61 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
62 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
63 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
64 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
65 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
66 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
67 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonomicTree
;
68 import eu
.etaxonomy
.cdm
.model
.view
.AuditEvent
;
69 import eu
.etaxonomy
.cdm
.persistence
.dao
.QueryParseException
;
70 import eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.AlternativeSpellingSuggestionParser
;
71 import eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.common
.IdentifiableDaoBase
;
72 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonDao
;
73 import eu
.etaxonomy
.cdm
.persistence
.fetch
.CdmFetch
;
74 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
75 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
84 @Qualifier("taxonDaoHibernateImpl")
85 public class TaxonDaoHibernateImpl
extends IdentifiableDaoBase
<TaxonBase
> implements ITaxonDao
{
86 private AlternativeSpellingSuggestionParser
<TaxonBase
> alternativeSpellingSuggestionParser
;
87 private static final Logger logger
= Logger
.getLogger(TaxonDaoHibernateImpl
.class);
89 private String defaultField
= "name.titleCache";
90 private Class
<?
extends TaxonBase
> indexedClasses
[];
92 public TaxonDaoHibernateImpl() {
93 super(TaxonBase
.class);
94 indexedClasses
= new Class
[2];
95 indexedClasses
[0] = Taxon
.class;
96 indexedClasses
[1] = Synonym
.class;
99 @Autowired(required
= false) //TODO switched of because it caused problems when starting CdmApplicationController
100 public void setAlternativeSpellingSuggestionParser(AlternativeSpellingSuggestionParser
<TaxonBase
> alternativeSpellingSuggestionParser
) {
101 this.alternativeSpellingSuggestionParser
= alternativeSpellingSuggestionParser
;
106 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase)
108 public List
<Taxon
> getRootTaxa(ReferenceBase sec
) {
109 return getRootTaxa(sec
, CdmFetch
.FETCH_CHILDTAXA(), true, false);
113 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.ReferenceBase, eu.etaxonomy.cdm.persistence.fetch.CdmFetch, java.lang.Boolean, java.lang.Boolean)
115 public List
<Taxon
> getRootTaxa(Rank rank
, ReferenceBase sec
, CdmFetch cdmFetch
, Boolean onlyWithChildren
, Boolean withMisapplications
, List
<String
> propertyPaths
) {
116 checkNotInPriorView("TaxonDaoHibernateImpl.getRootTaxa(Rank rank, ReferenceBase sec, CdmFetch cdmFetch, Boolean onlyWithChildren, Boolean withMisapplications)");
117 if (onlyWithChildren
== null){
118 onlyWithChildren
= true;
120 if (withMisapplications
== null){
121 withMisapplications
= true;
123 if (cdmFetch
== null){
124 cdmFetch
= CdmFetch
.NO_FETCH();
127 Criteria crit
= getSession().createCriteria(Taxon
.class);
129 crit
.setFetchMode("name", FetchMode
.JOIN
);
130 crit
.createAlias("name", "name");
133 crit
.add(Restrictions
.eq("name.rank", rank
));
135 crit
.add(Restrictions
.isNull("taxonomicParentCache"));
139 crit
.add(Restrictions
.eq("sec", sec
) );
142 if (! cdmFetch
.includes(CdmFetch
.FETCH_CHILDTAXA())){
143 logger
.info("Not fetching child taxa");
144 //TODO overwrite LAZY (SELECT) does not work (bug in hibernate?)
145 crit
.setFetchMode("relationsToThisTaxon.fromTaxon", FetchMode
.LAZY
);
148 List
<Taxon
> results
= new ArrayList
<Taxon
>();
149 List
<Taxon
> taxa
= crit
.list();
150 for(Taxon taxon
: taxa
){
154 //TODO create restriction instead
155 // (a) not using cache fields
156 /*Hibernate.initialize(taxon.getRelationsFromThisTaxon());
157 if (onlyWithChildren == false || taxon.getRelationsFromThisTaxon().size() > 0){
158 if (withMisapplications == true || ! taxon.isMisappliedName()){
159 defaultBeanInitializer.initialize(taxon, propertyPaths);
163 // (b) using cache fields
164 if (onlyWithChildren
== false || taxon
.hasTaxonomicChildren()){
165 if (withMisapplications
== true || ! taxon
.isMisappliedName()){
166 defaultBeanInitializer
.initialize(taxon
, propertyPaths
);
175 * @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)
177 public List
<Taxon
> getRootTaxa(ReferenceBase sec
, CdmFetch cdmFetch
, Boolean onlyWithChildren
, Boolean withMisapplications
) {
178 return getRootTaxa(null, sec
, cdmFetch
, onlyWithChildren
, withMisapplications
, null);
182 public List
<TaxonBase
> getTaxaByName(String queryString
, ReferenceBase sec
) {
184 return getTaxaByName(queryString
, true, sec
);
187 public List
<TaxonBase
> getTaxaByName(String queryString
, Boolean accepted
, ReferenceBase sec
) {
188 checkNotInPriorView("TaxonDaoHibernateImpl.getTaxaByName(String name, ReferenceBase sec)");
190 Criteria criteria
= null;
191 if (accepted
== true) {
192 criteria
= getSession().createCriteria(Taxon
.class);
194 criteria
= getSession().createCriteria(Synonym
.class);
197 criteria
.setFetchMode( "name", FetchMode
.JOIN
);
198 criteria
.createAlias("name", "name");
200 if (sec
!= null && sec
.getId() != 0) {
201 criteria
.add(Restrictions
.eq("sec", sec
) );
204 if (queryString
!= null) {
205 criteria
.add(Restrictions
.ilike("name.nameCache", queryString
));
208 return (List
<TaxonBase
>)criteria
.list();
211 public List
<TaxonBase
> getTaxaByName(Class
<?
extends TaxonBase
> clazz
, String queryString
, MatchMode matchMode
,
212 Integer pageSize
, Integer pageNumber
) {
214 return getTaxaByName(clazz
, queryString
, null, matchMode
, null, pageSize
, pageNumber
, null);
217 public List
<TaxonBase
> getTaxaByName(String queryString
, MatchMode matchMode
,
218 Boolean accepted
, Integer pageSize
, Integer pageNumber
) {
220 if (accepted
== true) {
221 return getTaxaByName(Taxon
.class, queryString
, matchMode
, pageSize
, pageNumber
);
223 return getTaxaByName(Synonym
.class, queryString
, matchMode
, pageSize
, pageNumber
);
228 public List
<TaxonBase
> getTaxaByName(Class
<?
extends TaxonBase
> clazz
, String queryString
, TaxonomicTree taxonomicTree
,
229 MatchMode matchMode
, Set
<NamedArea
> namedAreas
, Integer pageSize
,
230 Integer pageNumber
, List
<String
> propertyPaths
) {
232 boolean doCount
= false;
233 Query query
= prepareTaxaByName(clazz
, queryString
, taxonomicTree
, matchMode
, namedAreas
, pageSize
, pageNumber
, doCount
);
235 List
<TaxonBase
> results
= query
.list();
236 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
239 return new ArrayList
<TaxonBase
>();
246 * @param taxonomicTree TODO
254 * FIXME implement taxontree restriction & implement test: see {@link TaxonDaoHibernateImplTest#testCountTaxaByName()}
256 private Query
prepareTaxaByName(Class
<?
extends TaxonBase
> clazz
, String queryString
, TaxonomicTree taxonomicTree
,
257 MatchMode matchMode
, Set
<NamedArea
> namedAreas
, Integer pageSize
, Integer pageNumber
, boolean doCount
) {
259 //TODO ? checkNotInPriorView("TaxonDaoHibernateImpl.countTaxaByName(String queryString, Boolean accepted, ReferenceBase sec)");
261 String hqlQueryString
= matchMode
.queryStringFrom(queryString
);
263 String matchOperator
;
264 if (matchMode
== MatchMode
.EXACT
) {
267 matchOperator
= "like";
270 String selectWhat
= (doCount ?
"count(t)": "t");
273 Set
<NamedArea
> areasExpanded
= new HashSet
<NamedArea
>();
274 if(namedAreas
!= null && namedAreas
.size() > 0){
275 // expand areas and restrict by distribution area
276 List
<NamedArea
> childAreas
;
277 Query areaQuery
= getSession().createQuery("select childArea from NamedArea as childArea left join childArea.partOf as parentArea where parentArea = :area");
278 expandNamedAreas(namedAreas
, areasExpanded
, areaQuery
);
280 boolean doAreaRestriction
= areasExpanded
.size() > 0;
282 String taxonSubselect
= null;
283 String synonymSubselect
= null;
285 if(taxonomicTree
!= null){
287 if(doAreaRestriction
){
289 taxonSubselect
= "select t from" +
291 " join e.inDescription d" +
294 " join t.taxonNodes as tn "+
296 " e.area in (:namedAreas) AND" +
297 " tn.taxonomicTree = :taxonomicTree" +
298 " AND n.nameCache " + matchOperator
+ " :queryString";
300 synonymSubselect
= "select s from" +
302 " join e.inDescription d" +
303 " join d.taxon t" + // the taxa
304 " join t.taxonNodes as tn "+
305 " join t.synonymRelations sr" +
306 " join sr.relatedFrom s" + // the synonyms
309 " e.area in (:namedAreas) AND" +
310 " tn.taxonomicTree = :taxonomicTree" +
311 " AND sn.nameCache " + matchOperator
+ " :queryString";
315 taxonSubselect
= "select t from" +
318 " join t.taxonNodes as tn "+
320 " tn.taxonomicTree = :taxonomicTree" +
321 " AND n.nameCache " + matchOperator
+ " :queryString";
323 synonymSubselect
= "select s from" +
324 " Taxon t" + // the taxa
325 " join t.taxonNodes as tn "+
326 " join t.synonymRelations sr" +
327 " join sr.relatedFrom s" + // the synonyms
330 " tn.taxonomicTree = :taxonomicTree" +
331 " AND sn.nameCache " + matchOperator
+ " :queryString";
335 if(doAreaRestriction
){
337 taxonSubselect
= "select t from " +
339 " join e.inDescription d" +
343 (doAreaRestriction ?
" e.area in (:namedAreas) AND" : "") +
344 " n.nameCache " + matchOperator
+ " :queryString";
346 synonymSubselect
= "select s from" +
348 " join e.inDescription d" +
349 " join d.taxon t" + // the taxa
350 " join t.synonymRelations sr" +
351 " join sr.relatedFrom s" + // the synonyms
354 (doAreaRestriction ?
" e.area in (:namedAreas) AND" : "") +
355 " sn.nameCache " + matchOperator
+ " :queryString";
359 taxonSubselect
= "select t from " +
363 " n.nameCache " + matchOperator
+ " :queryString";
365 synonymSubselect
= "select s from" +
366 " Taxon t" + // the taxa
367 " join t.synonymRelations sr" +
368 " join sr.relatedFrom s" + // the synonyms
371 " sn.nameCache " + matchOperator
+ " :queryString";
375 // TODO mysql needs optimization: see http://www.xaprb.com/blog/2006/04/30/how-to-optimize-subqueries-and-joins-in-mysql/#commen
376 Query subTaxon
= null;
377 Query subSynonym
= null;
378 if(clazz
.equals(Taxon
.class)){
380 subTaxon
= getSession().createQuery(taxonSubselect
).setParameter("queryString", hqlQueryString
);;
381 if(doAreaRestriction
){
382 subTaxon
.setParameterList("namedAreas", areasExpanded
);
384 if(taxonomicTree
!= null){
385 subTaxon
.setParameter("taxonomicTree", taxonomicTree
);
387 } else if(clazz
.equals(Synonym
.class)){
389 subSynonym
= getSession().createQuery(synonymSubselect
).setParameter("queryString", hqlQueryString
);;
391 if(doAreaRestriction
){
392 subSynonym
.setParameterList("namedAreas", areasExpanded
);
394 if(taxonomicTree
!= null){
395 subSynonym
.setParameter("taxonomicTree", taxonomicTree
);
398 // find taxa and synonyms
399 subSynonym
= getSession().createQuery(synonymSubselect
).setParameter("queryString", hqlQueryString
);;
400 subTaxon
= getSession().createQuery(taxonSubselect
).setParameter("queryString", hqlQueryString
);;
401 if(doAreaRestriction
){
402 subTaxon
.setParameterList("namedAreas", areasExpanded
);
403 subSynonym
.setParameterList("namedAreas", areasExpanded
);
405 if(taxonomicTree
!= null){
406 subTaxon
.setParameter("taxonomicTree", taxonomicTree
);
407 subSynonym
.setParameter("taxonomicTree", taxonomicTree
);
411 List
<TaxonBase
> taxa
= null;
412 List
<TaxonBase
> synonyms
= null;
413 if(clazz
.equals(Taxon
.class)){
414 taxa
= subTaxon
.list();
415 System
.err
.println("number of taxa: " +taxa
.size());
416 }else if (clazz
.equals(Synonym
.class)){
417 System
.err
.println(subSynonym
.getQueryString());
418 synonyms
= subSynonym
.list();
419 System
.err
.println("number of synonyms: " +synonyms
.size());
421 System
.err
.println(subTaxon
.getQueryString());
422 taxa
= subTaxon
.list();
423 System
.err
.println("number of taxa: " +taxa
.size());
424 synonyms
= subSynonym
.list();
425 System
.err
.println("number of synonyms: " +synonyms
.size());
427 if(clazz
.equals(Taxon
.class)){
429 hql
= "select " + selectWhat
+ " from " + clazz
.getSimpleName() + " t" + " where t in (:taxa)";
431 hql
= "select " + selectWhat
+ " from " + clazz
.getSimpleName() + " t";
433 } else if(clazz
.equals(Synonym
.class) ){
434 if (synonyms
.size()>0){
435 hql
= "select " + selectWhat
+ " from " + clazz
.getSimpleName() + " t" + " where t in (:synonyms)";
437 hql
= "select " + selectWhat
+ " from " + clazz
.getSimpleName() + " t";
440 if(synonyms
.size()>0 && taxa
.size()>0){
441 hql
= "select " + selectWhat
+ " from " + clazz
.getSimpleName() + " t" + " where t in (:taxa) OR t in (:synonyms)";
442 }else if (synonyms
.size()>0 ){
443 hql
= "select " + selectWhat
+ " from " + clazz
.getSimpleName() + " t"
444 + " where t in (:synonyms)";
445 } else if (taxa
.size()>0 ){
446 hql
= "select " + selectWhat
+ " from " + clazz
.getSimpleName() + " t" + " where t in (:taxa) ";
448 hql
= "select " + selectWhat
+ " from " + clazz
.getSimpleName() + " t";
452 if (hql
== "") return null;
454 hql
+= " order by t.titleCache"; //" order by t.name.nameCache";
457 Query query
= getSession().createQuery(hql
);
459 if(clazz
.equals(Taxon
.class) && taxa
.size()>0){
461 query
.setParameterList("taxa", taxa
);
462 } else if(clazz
.equals(Synonym
.class) && synonyms
.size()>0){
464 query
.setParameterList("synonyms", synonyms
);
468 // find taxa and synonyms
470 query
.setParameterList("taxa", taxa
);
471 if (synonyms
.size()>0)
472 query
.setParameterList("synonyms",synonyms
);
475 System
.err
.println("query: " +query
.getQueryString());
476 if(pageSize
!= null && !doCount
) {
477 query
.setMaxResults(pageSize
);
478 if(pageNumber
!= null) {
479 query
.setFirstResult(pageNumber
* pageSize
);
487 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countTaxaByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, eu.etaxonomy.cdm.persistence.query.SelectMode, eu.etaxonomy.cdm.model.reference.ReferenceBase, java.util.Set)
489 public long countTaxaByName(Class
<?
extends TaxonBase
> clazz
, String queryString
, TaxonomicTree taxonomicTree
,
490 MatchMode matchMode
, Set
<NamedArea
> namedAreas
) {
492 boolean doCount
= true;
493 Query query
= prepareTaxaByName(clazz
, queryString
, taxonomicTree
, matchMode
, namedAreas
, null, null, doCount
);
495 return (Long
)query
.uniqueResult();
503 * @param areasExpanded
506 private void expandNamedAreas(Collection
<NamedArea
> namedAreas
, Set
<NamedArea
> areasExpanded
, Query areaQuery
) {
507 List
<NamedArea
> childAreas
;
508 for(NamedArea a
: namedAreas
){
509 areasExpanded
.add(a
);
510 areaQuery
.setParameter("area", a
);
511 childAreas
= areaQuery
.list();
512 if(childAreas
.size() > 0){
513 areasExpanded
.addAll(childAreas
);
514 expandNamedAreas(childAreas
, areasExpanded
, areaQuery
);
520 // * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countTaxaByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, eu.etaxonomy.cdm.persistence.query.SelectMode)
522 // public Integer countTaxaByName(String queryString, MatchMode matchMode, SelectMode selectMode) {
523 // return countTaxaByName(queryString, matchMode, selectMode, null);
527 // * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countTaxaByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, eu.etaxonomy.cdm.persistence.query.SelectMode, eu.etaxonomy.cdm.model.reference.ReferenceBase)
529 // public Integer countTaxaByName(String queryString,
530 // MatchMode matchMode, SelectMode selectMode, ReferenceBase sec) {
532 // Long count = countTaxaByName(queryString, matchMode, selectMode, sec, null);
533 // return count.intValue();
537 // public Integer countTaxaByName(String queryString, MatchMode matchMode, Boolean accepted) {
539 // SelectMode selectMode = (accepted ? SelectMode.TAXA : SelectMode.SYNONYMS);
540 // Long count = countTaxaByName(queryString, matchMode, selectMode, null, null);
541 // return count.intValue();
545 public List
<TaxonBase
> getAllTaxonBases(Integer pagesize
, Integer page
) {
546 return super.list(pagesize
, page
);
549 public List
<Synonym
> getAllSynonyms(Integer limit
, Integer start
) {
550 Criteria criteria
= getSession().createCriteria(Synonym
.class);
553 criteria
.setFirstResult(start
);
554 criteria
.setMaxResults(limit
);
557 return criteria
.list();
560 public List
<Taxon
> getAllTaxa(Integer limit
, Integer start
) {
561 Criteria criteria
= getSession().createCriteria(Taxon
.class);
564 criteria
.setFirstResult(start
);
565 criteria
.setMaxResults(limit
);
568 return criteria
.list();
573 public List
<RelationshipBase
> getAllRelationships(Integer limit
, Integer start
) {
574 AuditEvent auditEvent
= getAuditEventFromContext();
575 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
576 Criteria criteria
= getSession().createCriteria(RelationshipBase
.class);
577 return (List
<RelationshipBase
>)criteria
.list();
579 AuditQuery query
= getAuditReader().createQuery().forEntitiesAtRevision(RelationshipBase
.class,auditEvent
.getRevisionNumber());
580 return (List
<RelationshipBase
>)query
.getResultList();
584 /** Sets the taxonomic parent to null. Does not handle taxonomic relationships. */
585 // private boolean nullifyTaxonomicParent(Taxon taxon) {
588 // Method nullifyTaxonomicParent = taxon.getClass().getMethod("nullifyTaxonomicParent");
589 // nullifyTaxonomicParent.invoke(taxon);
590 // } catch (NoSuchMethodException ex) {
591 // logger.error("NoSuchMethod: " + ex.getMessage());
593 // } catch (IllegalArgumentException ex) {
594 // logger.error("IllegalArgumentException: " + ex.getMessage());
596 // } catch (IllegalAccessException ex) {
597 // logger.error("IllegalAccessException: " + ex.getMessage());
599 // } catch (InvocationTargetException ex) {
600 // logger.error("IllegalAccessException: " + ex.getMessage());
607 public UUID
delete(TaxonBase taxonBase
) throws DataAccessException
{
608 if (taxonBase
== null){
609 logger
.warn("TaxonBase was 'null'");
613 // Merge the object in if it is detached
615 // I think this is preferable to catching lazy initialization errors
616 // as that solution only swallows and hides the exception, but doesn't
617 // actually solve it.
618 getSession().merge(taxonBase
);
620 for(Iterator
<Annotation
> iterator
= taxonBase
.getAnnotations().iterator(); iterator
.hasNext();) {
621 Annotation annotation
= iterator
.next();
622 annotation
.setAnnotatedObj(null);
624 getSession().delete(annotation
);
627 for(Iterator
<Marker
> iterator
= taxonBase
.getMarkers().iterator(); iterator
.hasNext();) {
628 Marker marker
= iterator
.next();
629 marker
.setMarkedObj(null);
631 getSession().delete(marker
);
634 for(Iterator
<Extension
> iterator
= taxonBase
.getExtensions().iterator(); iterator
.hasNext();) {
635 Extension extension
= iterator
.next();
636 extension
.setExtendedObj(null);
638 getSession().delete(extension
);
641 for(Iterator
<IdentifiableSource
> iterator
= taxonBase
.getSources().iterator(); iterator
.hasNext();) {
642 IdentifiableSource source
= iterator
.next();
643 source
.setSourcedObj(null);
645 getSession().delete(source
);
648 for(Iterator
<Rights
> iterator
= taxonBase
.getRights().iterator(); iterator
.hasNext();) {
649 Rights rights
= iterator
.next();
651 getSession().delete(rights
);
654 if (taxonBase
instanceof Taxon
){ // is Taxon
656 Taxon taxon
= (Taxon
)taxonBase
;
658 for (Iterator
<TaxonRelationship
> iterator
= taxon
.getRelationsFromThisTaxon().iterator(); iterator
.hasNext();){
659 TaxonRelationship relationFromThisTaxon
= iterator
.next();
662 // decrease children count of taxonomic parent by one
663 if (relationFromThisTaxon
.getType().equals(TaxonRelationshipType
.TAXONOMICALLY_INCLUDED_IN())) {
664 Taxon toTaxon
= relationFromThisTaxon
.getToTaxon(); // parent
665 if (toTaxon
!= null) {
666 toTaxon
.setTaxonomicChildrenCount(toTaxon
.getTaxonomicChildrenCount() - 1);
669 relationFromThisTaxon
.setToTaxon(null);
670 relationFromThisTaxon
.setFromTaxon(null);
671 getSession().delete(relationFromThisTaxon
);
674 for (Iterator
<TaxonRelationship
> iterator
= taxon
.getRelationsToThisTaxon().iterator(); iterator
.hasNext();){
675 TaxonRelationship relationToThisTaxon
= iterator
.next();
678 // set parent cache of child to null
679 if (relationToThisTaxon
.getType().equals(TaxonRelationshipType
.TAXONOMICALLY_INCLUDED_IN())) {
680 Taxon fromTaxon
= relationToThisTaxon
.getFromTaxon(); // child
681 if (fromTaxon
!= null) {
682 fromTaxon
.nullifyTaxonomicParent();
685 relationToThisTaxon
.setFromTaxon(null);
686 relationToThisTaxon
.setToTaxon(null);
687 getSession().delete(relationToThisTaxon
);
690 //SynonymRelationships
691 for (Iterator
<SynonymRelationship
> iterator
= taxon
.getSynonymRelations().iterator(); iterator
.hasNext();){
692 SynonymRelationship synonymRelation
= iterator
.next();
694 synonymRelation
.setAcceptedTaxon(null);
695 synonymRelation
.setSynonym(null);
696 getSession().delete(synonymRelation
);
700 for (Iterator
<TaxonDescription
> iterDesc
= taxon
.getDescriptions().iterator(); iterDesc
.hasNext();) {
701 TaxonDescription taxonDescription
= iterDesc
.next();
703 //taxonDescription.setTaxon(null);
704 Field field
= ReflectionUtils
.findField(TaxonDescription
.class, "taxon", Taxon
.class);
705 ReflectionUtils
.makeAccessible(field
);
706 ReflectionUtils
.setField(field
, taxonDescription
, null);
707 for (Iterator
<DescriptionElementBase
> iterDescElem
=
708 taxonDescription
.getElements().iterator(); iterDescElem
.hasNext();) {
709 DescriptionElementBase descriptionElement
= iterDescElem
.next();
710 iterDescElem
.remove();
711 getSession().delete(descriptionElement
);
713 getSession().delete(taxonDescription
);
716 taxon
.nullifyTaxonomicParent();
718 } else { //is Synonym
719 Synonym synonym
= (Synonym
)taxonBase
;
720 for (Iterator
<SynonymRelationship
> iterator
= synonym
.getSynonymRelations().iterator(); iterator
.hasNext();){
721 SynonymRelationship synonymRelation
= iterator
.next();
723 synonymRelation
.setAcceptedTaxon(null);
724 synonymRelation
.setSynonym(null);
727 return super.delete(taxonBase
);
731 // TODO add generic return type !!
732 public List
findByName(String queryString
, MatchMode matchMode
, int page
, int pagesize
, boolean onlyAcccepted
) {
733 ArrayList
<Criterion
> criteria
= new ArrayList
<Criterion
>();
734 //TODO ... Restrictions.eq(propertyName, value)
735 return super.findByTitle(queryString
, matchMode
, page
, pagesize
, criteria
);
739 public int countMatchesByName(String queryString
, MatchMode matchMode
, boolean onlyAcccepted
) {
740 checkNotInPriorView("TaxonDaoHibernateImpl.countMatchesByName(String queryString, ITitledDao.MATCH_MODE matchMode, boolean onlyAcccepted)");
741 Criteria crit
= getSession().createCriteria(type
);
742 crit
.add(Restrictions
.ilike("titleCache", matchMode
.queryStringFrom(queryString
)));
743 crit
.setProjection(Projections
.rowCount());
744 int result
= ((Integer
)crit
.list().get(0)).intValue();
749 public int countMatchesByName(String queryString
, MatchMode matchMode
, boolean onlyAcccepted
, List
<Criterion
> criteria
) {
750 checkNotInPriorView("TaxonDaoHibernateImpl.countMatchesByName(String queryString, ITitledDao.MATCH_MODE matchMode, boolean onlyAcccepted, List<Criterion> criteria)");
751 Criteria crit
= getSession().createCriteria(type
);
752 crit
.add(Restrictions
.ilike("titleCache", matchMode
.queryStringFrom(queryString
)));
753 if(criteria
!= null){
754 for (Criterion criterion
: criteria
) {
758 crit
.setProjection(Projections
.rowCount());
759 int result
= ((Integer
)crit
.list().get(0)).intValue();
763 public int countTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Direction direction
) {
764 AuditEvent auditEvent
= getAuditEventFromContext();
765 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
769 query
= getSession().createQuery("select count(taxonRelationship) from TaxonRelationship taxonRelationship where taxonRelationship."+direction
+" = :relatedTaxon");
771 query
= getSession().createQuery("select count(taxonRelationship) from TaxonRelationship taxonRelationship where taxonRelationship."+direction
+" = :relatedTaxon and taxonRelationship.type = :type");
772 query
.setParameter("type",type
);
774 query
.setParameter("relatedTaxon", taxon
);
776 return ((Long
)query
.uniqueResult()).intValue();
778 AuditQuery query
= getAuditReader().createQuery().forEntitiesAtRevision(TaxonRelationship
.class,auditEvent
.getRevisionNumber());
779 query
.add(AuditEntity
.relatedId(direction
.toString()).eq(taxon
.getId()));
780 query
.addProjection(AuditEntity
.id().count("id"));
783 query
.add(AuditEntity
.relatedId("type").eq(type
.getId()));
786 return ((Long
)query
.getSingleResult()).intValue();
790 public int countSynonyms(Taxon taxon
, SynonymRelationshipType type
) {
791 AuditEvent auditEvent
= getAuditEventFromContext();
792 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
796 query
= getSession().createQuery("select count(synonymRelationship) from SynonymRelationship synonymRelationship where synonymRelationship.relatedTo = :relatedTo");
798 query
= getSession().createQuery("select count(synonymRelationship) from SynonymRelationship synonymRelationship where synonymRelationship.relatedTo = :relatedTo and synonymRelationship.type = :type");
799 query
.setParameter("type",type
);
802 query
.setParameter("relatedTo", taxon
);
804 return ((Long
)query
.uniqueResult()).intValue();
806 AuditQuery query
= getAuditReader().createQuery().forEntitiesAtRevision(SynonymRelationship
.class,auditEvent
.getRevisionNumber());
807 query
.add(AuditEntity
.relatedId("relatedTo").eq(taxon
.getId()));
808 query
.addProjection(AuditEntity
.id().count("id"));
811 query
.add(AuditEntity
.relatedId("type").eq(type
.getId()));
814 return ((Long
)query
.getSingleResult()).intValue();
818 public int count(Class
<?
extends TaxonBase
> clazz
, String queryString
) {
819 checkNotInPriorView("TaxonDaoHibernateImpl.count(String queryString, Boolean accepted)");
820 QueryParser queryParser
= new QueryParser(defaultField
, new SimpleAnalyzer());
823 org
.apache
.lucene
.search
.Query query
= queryParser
.parse(queryString
);
825 FullTextSession fullTextSession
= Search
.getFullTextSession(this.getSession());
826 org
.hibernate
.search
.FullTextQuery fullTextQuery
= null;
829 fullTextQuery
= fullTextSession
.createFullTextQuery(query
, type
);
831 fullTextQuery
= fullTextSession
.createFullTextQuery(query
, clazz
);
834 Integer result
= fullTextQuery
.getResultSize();
837 } catch (ParseException e
) {
838 throw new QueryParseException(e
, queryString
);
842 // public int countTaxaByName(String queryString, Boolean accepted, ReferenceBase sec) {
844 // SelectMode selectMode = (accepted ? SelectMode.TAXA : SelectMode.SYNONYMS);
845 // Long count = countTaxaByName(queryString, MatchMode.ANYWHERE, selectMode , sec, null);
847 // return count.intValue();
850 public int countTaxaByName(Class
<?
extends TaxonBase
> clazz
, String genusOrUninomial
, String infraGenericEpithet
, String specificEpithet
, String infraSpecificEpithet
, Rank rank
) {
851 checkNotInPriorView("TaxonDaoHibernateImpl.countTaxaByName(Boolean accepted, String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, Rank rank)");
852 Criteria criteria
= null;
855 criteria
= getSession().createCriteria(TaxonBase
.class);
857 criteria
= getSession().createCriteria(clazz
);
860 criteria
.setFetchMode( "name", FetchMode
.JOIN
);
861 criteria
.createAlias("name", "name");
863 if(genusOrUninomial
!= null) {
864 criteria
.add(Restrictions
.eq("name.genusOrUninomial", genusOrUninomial
));
867 if(infraGenericEpithet
!= null) {
868 criteria
.add(Restrictions
.eq("name.infraGenericEpithet", infraGenericEpithet
));
871 if(specificEpithet
!= null) {
872 criteria
.add(Restrictions
.eq("name.specificEpithet", specificEpithet
));
875 if(infraSpecificEpithet
!= null) {
876 criteria
.add(Restrictions
.eq("name.infraSpecificEpithet", infraSpecificEpithet
));
880 criteria
.add(Restrictions
.eq("name.rank", rank
));
883 criteria
.setProjection(Projections
.projectionList().add(Projections
.rowCount()));
885 return (Integer
)criteria
.uniqueResult();
888 public List
<TaxonBase
> findTaxaByName(Class
<?
extends TaxonBase
> clazz
, String genusOrUninomial
, String infraGenericEpithet
, String specificEpithet
, String infraSpecificEpithet
, Rank rank
, Integer pageSize
, Integer pageNumber
) {
889 checkNotInPriorView("TaxonDaoHibernateImpl.findTaxaByName(Boolean accepted, String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, Rank rank, Integer pageSize, Integer pageNumber)");
890 Criteria criteria
= null;
893 criteria
= getSession().createCriteria(TaxonBase
.class);
895 criteria
= getSession().createCriteria(clazz
);
898 criteria
.setFetchMode( "name", FetchMode
.JOIN
);
899 criteria
.createAlias("name", "name");
901 if(genusOrUninomial
== null) {
902 criteria
.add(Restrictions
.isNull("name.genusOrUninomial"));
903 } else if(!genusOrUninomial
.equals("*")) {
904 criteria
.add(Restrictions
.eq("name.genusOrUninomial", genusOrUninomial
));
907 if(infraGenericEpithet
== null) {
908 criteria
.add(Restrictions
.isNull("name.infraGenericEpithet"));
909 } else if(!infraGenericEpithet
.equals("*")) {
910 criteria
.add(Restrictions
.eq("name.infraGenericEpithet", infraGenericEpithet
));
913 if(specificEpithet
== null) {
914 criteria
.add(Restrictions
.isNull("name.specificEpithet"));
915 } else if(!specificEpithet
.equals("*")) {
916 criteria
.add(Restrictions
.eq("name.specificEpithet", specificEpithet
));
920 if(infraSpecificEpithet
== null) {
921 criteria
.add(Restrictions
.isNull("name.infraSpecificEpithet"));
922 } else if(!infraSpecificEpithet
.equals("*")) {
923 criteria
.add(Restrictions
.eq("name.infraSpecificEpithet", infraSpecificEpithet
));
927 criteria
.add(Restrictions
.eq("name.rank", rank
));
930 if(pageSize
!= null) {
931 criteria
.setMaxResults(pageSize
);
932 if(pageNumber
!= null) {
933 criteria
.setFirstResult(pageNumber
* pageSize
);
935 criteria
.setFirstResult(0);
939 return (List
<TaxonBase
>)criteria
.list();
942 public List
<TaxonRelationship
> getTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
, Direction direction
) {
943 AuditEvent auditEvent
= getAuditEventFromContext();
944 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
945 Criteria criteria
= getSession().createCriteria(TaxonRelationship
.class);
947 criteria
.add(Restrictions
.eq("relatedTo", taxon
));
949 criteria
.add(Restrictions
.eq("type", type
));
952 addOrder(criteria
,orderHints
);
954 if(pageSize
!= null) {
955 criteria
.setMaxResults(pageSize
);
956 if(pageNumber
!= null) {
957 criteria
.setFirstResult(pageNumber
* pageSize
);
959 criteria
.setFirstResult(0);
963 List
<TaxonRelationship
> result
= (List
<TaxonRelationship
>)criteria
.list();
964 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
968 AuditQuery query
= getAuditReader().createQuery().forEntitiesAtRevision(TaxonRelationship
.class,auditEvent
.getRevisionNumber());
969 query
.add(AuditEntity
.relatedId("relatedTo").eq(taxon
.getId()));
972 query
.add(AuditEntity
.relatedId("type").eq(type
.getId()));
975 if(pageSize
!= null) {
976 query
.setMaxResults(pageSize
);
977 if(pageNumber
!= null) {
978 query
.setFirstResult(pageNumber
* pageSize
);
980 query
.setFirstResult(0);
984 List
<TaxonRelationship
> result
= (List
<TaxonRelationship
>)query
.getResultList();
985 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
987 // Ugly, but for now, there is no way to sort on a related entity property in Envers,
988 // and we can't live without this functionality in CATE as it screws up the whole
990 if(orderHints
!= null && !orderHints
.isEmpty()) {
991 SortedSet
<TaxonRelationship
> sortedList
= new TreeSet
<TaxonRelationship
>(new TaxonRelationshipFromTaxonComparator());
992 sortedList
.addAll(result
);
993 return new ArrayList
<TaxonRelationship
>(sortedList
);
1000 class TaxonRelationshipFromTaxonComparator
implements Comparator
<TaxonRelationship
> {
1002 public int compare(TaxonRelationship o1
, TaxonRelationship o2
) {
1003 return o1
.getFromTaxon().getTitleCache().compareTo(o2
.getFromTaxon().getTitleCache());
1008 public List
<SynonymRelationship
> getSynonyms(Taxon taxon
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
1009 AuditEvent auditEvent
= getAuditEventFromContext();
1010 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
1011 Criteria criteria
= getSession().createCriteria(SynonymRelationship
.class);
1013 criteria
.add(Restrictions
.eq("relatedTo", taxon
));
1015 criteria
.add(Restrictions
.eq("type", type
));
1018 addOrder(criteria
,orderHints
);
1020 if(pageSize
!= null) {
1021 criteria
.setMaxResults(pageSize
);
1022 if(pageNumber
!= null) {
1023 criteria
.setFirstResult(pageNumber
* pageSize
);
1025 criteria
.setFirstResult(0);
1029 List
<SynonymRelationship
> result
= (List
<SynonymRelationship
>)criteria
.list();
1030 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
1034 AuditQuery query
= getAuditReader().createQuery().forEntitiesAtRevision(SynonymRelationship
.class,auditEvent
.getRevisionNumber());
1035 query
.add(AuditEntity
.relatedId("relatedTo").eq(taxon
.getId()));
1038 query
.add(AuditEntity
.relatedId("type").eq(type
.getId()));
1041 if(pageSize
!= null) {
1042 query
.setMaxResults(pageSize
);
1043 if(pageNumber
!= null) {
1044 query
.setFirstResult(pageNumber
* pageSize
);
1046 query
.setFirstResult(0);
1050 List
<SynonymRelationship
> result
= (List
<SynonymRelationship
>)query
.getResultList();
1051 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
1057 public List
<TaxonBase
> search(Class
<?
extends TaxonBase
> clazz
, String queryString
,Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
1058 checkNotInPriorView("TaxonDaoHibernateImpl.searchTaxa(String queryString, Boolean accepted, Integer pageSize, Integer pageNumber)");
1059 QueryParser queryParser
= new QueryParser(defaultField
, new SimpleAnalyzer());
1060 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
1063 org
.apache
.lucene
.search
.Query query
= queryParser
.parse(queryString
);
1065 FullTextSession fullTextSession
= Search
.getFullTextSession(getSession());
1066 org
.hibernate
.search
.FullTextQuery fullTextQuery
= null;
1069 fullTextQuery
= fullTextSession
.createFullTextQuery(query
, TaxonBase
.class);
1071 fullTextQuery
= fullTextSession
.createFullTextQuery(query
, clazz
);
1074 addOrder(fullTextQuery
,orderHints
);
1076 if(pageSize
!= null) {
1077 fullTextQuery
.setMaxResults(pageSize
);
1078 if(pageNumber
!= null) {
1079 fullTextQuery
.setFirstResult(pageNumber
* pageSize
);
1081 fullTextQuery
.setFirstResult(0);
1085 List
<TaxonBase
> result
= (List
<TaxonBase
>)fullTextQuery
.list();
1086 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
1089 } catch (ParseException e
) {
1090 throw new QueryParseException(e
, queryString
);
1094 public void purgeIndex() {
1095 FullTextSession fullTextSession
= Search
.getFullTextSession(getSession());
1096 for(Class clazz
: indexedClasses
) {
1097 fullTextSession
.purgeAll(clazz
); // remove all taxon base from indexes
1099 fullTextSession
.flushToIndexes();
1102 public void rebuildIndex() {
1103 FullTextSession fullTextSession
= Search
.getFullTextSession(getSession());
1105 for(TaxonBase taxonBase
: list(null,null)) { // re-index all taxon base
1106 Hibernate
.initialize(taxonBase
.getName());
1107 fullTextSession
.index(taxonBase
);
1109 fullTextSession
.flushToIndexes();
1112 public void optimizeIndex() {
1113 FullTextSession fullTextSession
= Search
.getFullTextSession(getSession());
1114 SearchFactory searchFactory
= fullTextSession
.getSearchFactory();
1115 for(Class clazz
: indexedClasses
) {
1116 searchFactory
.optimize(clazz
); // optimize the indices ()
1118 fullTextSession
.flushToIndexes();
1121 public String
suggestQuery(String queryString
) {
1122 checkNotInPriorView("TaxonDaoHibernateImpl.suggestQuery(String queryString)");
1123 String alternativeQueryString
= null;
1124 if (alternativeSpellingSuggestionParser
!= null) {
1127 alternativeSpellingSuggestionParser
.parse(queryString
);
1128 org
.apache
.lucene
.search
.Query alternativeQuery
= alternativeSpellingSuggestionParser
.suggest(queryString
);
1129 if (alternativeQuery
!= null) {
1130 alternativeQueryString
= alternativeQuery
1131 .toString("name.titleCache");
1134 } catch (ParseException e
) {
1135 throw new QueryParseException(e
, queryString
);
1138 return alternativeQueryString
;
1143 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheOfAcceptedTaxa(eu.etaxonomy.cdm.model.taxon.TaxonomicTree)
1145 public List
<UuidAndTitleCache
<TaxonNode
>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByTaxonomicTree(TaxonomicTree taxonomicTree
) {
1147 int taxonomicTreeId
= taxonomicTree
.getId();
1149 String queryString
= "SELECT nodes.uuid, taxa.titleCache FROM TaxonNode AS nodes LEFT JOIN TaxonBase AS taxa ON nodes.taxon_id = taxa.id WHERE taxa.DTYPE = 'Taxon' AND nodes.taxonomictree_id = " + taxonomicTreeId
;
1151 List
<Object
[]> result
= getSession().createSQLQuery(queryString
).list();
1153 if(result
.size() == 0){
1156 List
<UuidAndTitleCache
<TaxonNode
>> list
= new ArrayList
<UuidAndTitleCache
<TaxonNode
>>(result
.size());
1158 for (Object object
: result
){
1160 Object
[] objectArray
= (Object
[]) object
;
1162 UUID uuid
= UUID
.fromString((String
) objectArray
[0]);
1163 String titleCache
= (String
) objectArray
[1];
1165 list
.add(new UuidAndTitleCache(TaxonNode
.class, uuid
, titleCache
));
1173 public class UuidAndTitleCacheOfAcceptedTaxon
{
1178 public UuidAndTitleCacheOfAcceptedTaxon(UUID uuid
, String titleCache
){
1180 this.titleCache
= titleCache
;
1183 public UUID
getUuid() {
1187 public void setUuid(UUID uuid
) {
1191 public String
getTitleCache() {
1195 public void setTitleCache(String titleCache
) {
1196 this.titleCache
= titleCache
;
1201 public TaxonBase
find(LSID lsid
) {
1202 TaxonBase taxonBase
= super.find(lsid
);
1203 if(taxonBase
!= null) {
1204 List
<String
> propertyPaths
= new ArrayList
<String
>();
1205 propertyPaths
.add("createdBy");
1206 propertyPaths
.add("updatedBy");
1207 propertyPaths
.add("name");
1208 propertyPaths
.add("sec");
1209 propertyPaths
.add("relationsToThisTaxon");
1210 propertyPaths
.add("relationsToThisTaxon.fromTaxon");
1211 propertyPaths
.add("relationsToThisTaxon.toTaxon");
1212 propertyPaths
.add("relationsFromThisTaxon");
1213 propertyPaths
.add("relationsFromThisTaxon.toTaxon");
1214 propertyPaths
.add("relationsToThisTaxon.type");
1215 propertyPaths
.add("synonymRelations");
1216 propertyPaths
.add("synonymRelations.synonym");
1217 propertyPaths
.add("synonymRelations.type");
1218 propertyPaths
.add("descriptions");
1220 defaultBeanInitializer
.initialize(taxonBase
, propertyPaths
);