3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
11 package eu
.etaxonomy
.cdm
.api
.service
;
13 import java
.io
.IOException
;
14 import java
.util
.ArrayList
;
15 import java
.util
.Collection
;
16 import java
.util
.HashMap
;
17 import java
.util
.HashSet
;
18 import java
.util
.List
;
21 import java
.util
.UUID
;
23 import org
.apache
.log4j
.Logger
;
24 import org
.apache
.lucene
.index
.CorruptIndexException
;
25 import org
.apache
.lucene
.index
.Term
;
26 import org
.apache
.lucene
.queryParser
.ParseException
;
27 import org
.apache
.lucene
.search
.BooleanClause
.Occur
;
28 import org
.apache
.lucene
.search
.BooleanQuery
;
29 import org
.apache
.lucene
.search
.FuzzyLikeThisQuery
;
30 import org
.apache
.lucene
.search
.TopDocs
;
31 import org
.apache
.lucene
.search
.WildcardQuery
;
32 import org
.hibernate
.criterion
.Criterion
;
33 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
34 import org
.springframework
.beans
.factory
.annotation
.Qualifier
;
35 import org
.springframework
.stereotype
.Service
;
36 import org
.springframework
.transaction
.annotation
.Transactional
;
38 import eu
.etaxonomy
.cdm
.api
.service
.config
.NameDeletionConfigurator
;
39 import eu
.etaxonomy
.cdm
.api
.service
.exception
.ReferencedObjectUndeletableException
;
40 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
41 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.AbstractPagerImpl
;
42 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
43 import eu
.etaxonomy
.cdm
.api
.service
.search
.DocumentSearchResult
;
44 import eu
.etaxonomy
.cdm
.api
.service
.search
.ILuceneIndexToolProvider
;
45 import eu
.etaxonomy
.cdm
.api
.service
.search
.ISearchResultBuilder
;
46 import eu
.etaxonomy
.cdm
.api
.service
.search
.LuceneSearch
;
47 import eu
.etaxonomy
.cdm
.api
.service
.search
.QueryFactory
;
48 import eu
.etaxonomy
.cdm
.api
.service
.search
.SearchResult
;
49 import eu
.etaxonomy
.cdm
.api
.service
.search
.SearchResultBuilder
;
50 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
51 import eu
.etaxonomy
.cdm
.model
.CdmBaseType
;
52 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
53 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
54 import eu
.etaxonomy
.cdm
.model
.common
.OrderedTermVocabulary
;
55 import eu
.etaxonomy
.cdm
.model
.common
.ReferencedEntityBase
;
56 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
57 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
.Direction
;
58 import eu
.etaxonomy
.cdm
.model
.common
.TermVocabulary
;
59 import eu
.etaxonomy
.cdm
.model
.common
.UuidAndTitleCache
;
60 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementSource
;
61 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
62 import eu
.etaxonomy
.cdm
.model
.name
.HybridRelationship
;
63 import eu
.etaxonomy
.cdm
.model
.name
.HybridRelationshipType
;
64 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationship
;
65 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationshipType
;
66 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignation
;
67 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatus
;
68 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatusType
;
69 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
70 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
71 import eu
.etaxonomy
.cdm
.model
.name
.SpecimenTypeDesignationStatus
;
72 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
73 import eu
.etaxonomy
.cdm
.model
.name
.TypeDesignationBase
;
74 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnit
;
75 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ICdmGenericDao
;
76 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IOrderedTermVocabularyDao
;
77 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IReferencedEntityDao
;
78 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ITermVocabularyDao
;
79 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.IHomotypicalGroupDao
;
80 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.INomenclaturalStatusDao
;
81 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.ITaxonNameDao
;
82 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.ITypeDesignationDao
;
83 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
84 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
85 import eu
.etaxonomy
.cdm
.strategy
.cache
.TaggedText
;
86 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
87 import eu
.etaxonomy
.cdm
.strategy
.parser
.NonViralNameParserImpl
;
91 @Transactional(readOnly
= true)
92 public class NameServiceImpl
extends IdentifiableServiceBase
<TaxonNameBase
,ITaxonNameDao
> implements INameService
{
93 static private final Logger logger
= Logger
.getLogger(NameServiceImpl
.class);
96 protected ITermVocabularyDao vocabularyDao
;
98 protected IOrderedTermVocabularyDao orderedVocabularyDao
;
100 @Qualifier("refEntDao")
101 protected IReferencedEntityDao
<ReferencedEntityBase
> referencedEntityDao
;
103 private INomenclaturalStatusDao nomStatusDao
;
105 private ITypeDesignationDao typeDesignationDao
;
107 private IHomotypicalGroupDao homotypicalGroupDao
;
109 private ICdmGenericDao genericDao
;
111 private ILuceneIndexToolProvider luceneIndexToolProvider
;
116 public NameServiceImpl(){
117 if (logger
.isDebugEnabled()) { logger
.debug("Load NameService Bean"); }
120 //********************* METHODS ****************************************************************//
123 * @see eu.etaxonomy.cdm.api.service.ServiceBase#delete(eu.etaxonomy.cdm.model.common.CdmBase)
126 public UUID
delete(TaxonNameBase name
){
127 NameDeletionConfigurator config
= new NameDeletionConfigurator();
129 return delete(name
, config
);
130 } catch (ReferencedObjectUndeletableException e
) {
131 //TODO throw DeleteException - current implementation is preliminary for testing
132 throw new RuntimeException(e
);
137 * @see eu.etaxonomy.cdm.api.service.INameService#delete(eu.etaxonomy.cdm.model.name.TaxonNameBase, eu.etaxonomy.cdm.api.service.NameDeletionConfigurator)
140 public UUID
delete(TaxonNameBase name
, NameDeletionConfigurator config
) throws ReferencedObjectUndeletableException
{
145 //remove references to this name
146 removeNameRelationshipsByDeleteConfig(name
, config
);
148 //check if this name is still used somewhere
151 if (! name
.getNameRelations().isEmpty()){
152 String message
= "Name can't be deleted as it is used in name relationship(s). Remove name relationships prior to deletion.";
153 throw new ReferencedObjectUndeletableException(message
);
158 if (! name
.getTaxonBases().isEmpty()){
159 String message
= "Name can't be deleted as it is used in concept(s). Remove or change concept prior to deletion.";
160 throw new ReferencedObjectUndeletableException(message
);
163 //hybrid relationships
164 if (name
.isInstanceOf(NonViralName
.class)){
165 NonViralName nvn
= CdmBase
.deproxy(name
, NonViralName
.class);
166 // if (! nvn.getHybridChildRelations().isEmpty()){
167 // String message = "Name can't be deleted as it is a child in (a) hybrid relationship(s). Remove hybrid relationships prior to deletion.";
168 // throw new RuntimeException(message);
170 if (! nvn
.getHybridParentRelations().isEmpty()){
171 String message
= "Name can't be deleted as it is a parent in (a) hybrid relationship(s). Remove hybrid relationships prior to deletion.";
172 throw new ReferencedObjectUndeletableException(message
);
176 //all type designation relationships are removed as they belong to the name
177 deleteTypeDesignation(name
, null);
178 // //type designations
179 // if (! name.getTypeDesignations().isEmpty()){
180 // String message = "Name can't be deleted as it has types. Remove types prior to deletion.";
181 // throw new ReferrencedObjectUndeletableException(message);
184 //check references with only reverse mapping
185 Set
<CdmBase
> referencingObjects
= genericDao
.getReferencingObjects(name
);
186 for (CdmBase referencingObject
: referencingObjects
){
187 //DerivedUnit?.storedUnder
188 if (referencingObject
.isInstanceOf(DerivedUnit
.class)){
189 String message
= "Name can't be deleted as it is used as derivedUnit#storedUnder by %s. Remove 'stored under' prior to deleting this name";
190 message
= String
.format(message
, CdmBase
.deproxy(referencingObject
, DerivedUnit
.class).getTitleCache());
191 throw new ReferencedObjectUndeletableException(message
);
193 //DescriptionElementSource#nameUsedInSource
194 if (referencingObject
.isInstanceOf(DescriptionElementSource
.class)){
195 String message
= "Name can't be deleted as it is used as descriptionElementSource#nameUsedInSource";
196 throw new ReferencedObjectUndeletableException(message
);
198 //NameTypeDesignation#typeName
199 if (referencingObject
.isInstanceOf(NameTypeDesignation
.class)){
200 String message
= "Name can't be deleted as it is used as a name type in a NameTypeDesignation";
201 throw new ReferencedObjectUndeletableException(message
);
204 //TaxonNameDescriptions#taxonName
205 //deleted via cascade?
207 //NomenclaturalStatus
208 //deleted via cascade?
212 //TODO inline references
215 return name
.getUuid();
219 * @see eu.etaxonomy.cdm.api.service.INameService#deleteTypeDesignation(eu.etaxonomy.cdm.model.name.TaxonNameBase, eu.etaxonomy.cdm.model.name.TypeDesignationBase)
222 public void deleteTypeDesignation(TaxonNameBase name
, TypeDesignationBase typeDesignation
){
223 if (name
== null && typeDesignation
== null){
225 }else if (name
!= null && typeDesignation
!= null){
226 removeSingleDesignation(name
, typeDesignation
);
227 }else if (name
!= null){
228 Set
<TypeDesignationBase
> designationSet
= new HashSet
<TypeDesignationBase
>(name
.getTypeDesignations());
229 for (Object o
: designationSet
){
230 TypeDesignationBase desig
= CdmBase
.deproxy(o
, TypeDesignationBase
.class);
231 removeSingleDesignation(name
, desig
);
233 }else if (typeDesignation
!= null){
234 Set
<TaxonNameBase
> nameSet
= new HashSet
<TaxonNameBase
>(typeDesignation
.getTypifiedNames());
235 for (Object o
: nameSet
){
236 TaxonNameBase singleName
= CdmBase
.deproxy(o
, TaxonNameBase
.class);
237 removeSingleDesignation(singleName
, typeDesignation
);
244 * @param typeDesignation
246 private void removeSingleDesignation(TaxonNameBase name
, TypeDesignationBase typeDesignation
) {
247 name
.removeTypeDesignation(typeDesignation
);
248 if (typeDesignation
.getTypifiedNames().isEmpty()){
249 typeDesignation
.removeType();
250 typeDesignationDao
.delete(typeDesignation
);
260 private void removeNameRelationshipsByDeleteConfig(TaxonNameBase name
, NameDeletionConfigurator config
) {
261 if (config
.isRemoveAllNameRelationships()){
262 Set
<NameRelationship
> rels
= name
.getNameRelations();
263 for (NameRelationship rel
: rels
){
264 name
.removeNameRelationship(rel
);
267 //relations to this name
268 Set
<NameRelationship
> rels
= name
.getRelationsToThisName();
269 for (NameRelationship rel
: rels
){
270 if (config
.isIgnoreHasBasionym() && NameRelationshipType
.BASIONYM().equals(rel
.getType() )){
271 name
.removeNameRelationship(rel
);
272 }else if (config
.isIgnoreHasReplacedSynonym() && NameRelationshipType
.REPLACED_SYNONYM().equals(rel
.getType())){
273 name
.removeNameRelationship(rel
);
276 //relations from this name
277 rels
= name
.getRelationsFromThisName();
278 for (NameRelationship rel
: rels
){
279 if (config
.isIgnoreIsBasionymFor() && NameRelationshipType
.BASIONYM().equals(rel
.getType()) ){
280 name
.removeNameRelationship(rel
);
281 }else if (config
.isIgnoreIsReplacedSynonymFor() && NameRelationshipType
.REPLACED_SYNONYM().equals(rel
.getType())){
282 name
.removeNameRelationship(rel
);
289 //********************* METHODS ****************************************************************//
292 * @deprecated To be removed for harmonization see http://dev.e-taxonomy.eu/trac/wiki/CdmLibraryConventions
293 * duplicate of findByName
297 public List
getNamesByName(String name
){
298 return super.findCdmObjectsByTitle(name
);
302 * TODO candidate for harmonization
303 * new name findByName
306 public List
<NonViralName
> getNamesByNameCache(String nameCache
){
307 List result
= dao
.findByName(nameCache
, MatchMode
.EXACT
, null, null, null, null);
313 * TODO candidate for harmonization
314 * new name saveHomotypicalGroups
319 public List
<NonViralName
> findNamesByTitleCache(String titleCache
, MatchMode matchMode
, List
<String
> propertyPaths
){
320 List result
= dao
.findByTitle(titleCache
, matchMode
, null, null, null ,propertyPaths
);
325 * TODO candidate for harmonization
326 * new name saveHomotypicalGroups
331 public List
<NonViralName
> findNamesByNameCache(String nameCache
, MatchMode matchMode
, List
<String
> propertyPaths
){
332 List result
= dao
.findByName(nameCache
, matchMode
, null, null, null ,propertyPaths
);
337 * @deprecated To be removed for harmonization see http://dev.e-taxonomy.eu/trac/wiki/CdmLibraryConventions
338 * Replace by load(UUID, propertyPaths)
342 public NonViralName
findNameByUuid(UUID uuid
, List
<String
> propertyPaths
){
343 return (NonViralName
)dao
.findByUuid(uuid
, null ,propertyPaths
);
347 * TODO candidate for harmonization
350 public List
getNamesByName(String name
, CdmBase sessionObject
){
351 return super.findCdmObjectsByTitle(name
, sessionObject
);
355 * @deprecated To be removed for harmonization see http://dev.e-taxonomy.eu/trac/wiki/CdmLibraryConventions
356 * duplicate of findByTitle(clazz, queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths)
360 public List
findNamesByTitle(String title
){
361 return super.findCdmObjectsByTitle(title
);
365 * @deprecated To be removed for harmonization see http://dev.e-taxonomy.eu/trac/wiki/CdmLibraryConventions
366 * duplicate of findByTitle()
370 public List
findNamesByTitle(String title
, CdmBase sessionObject
){
371 return super.findCdmObjectsByTitle(title
, sessionObject
);
375 * TODO candidate for harmonization
376 * new name saveHomotypicalGroups
379 @Transactional(readOnly
= false)
380 public Map
<UUID
, HomotypicalGroup
> saveAllHomotypicalGroups(Collection
<HomotypicalGroup
> homotypicalGroups
){
381 return homotypicalGroupDao
.saveAll(homotypicalGroups
);
385 * TODO candidate for harmonization
386 * new name saveTypeDesignations
389 @Transactional(readOnly
= false)
390 public Map
<UUID
, TypeDesignationBase
> saveTypeDesignationAll(Collection
<TypeDesignationBase
> typeDesignationCollection
){
391 return typeDesignationDao
.saveAll(typeDesignationCollection
);
395 * TODO candidate for harmonization
396 * new name saveReferencedEntities
399 @Transactional(readOnly
= false)
400 public Map
<UUID
, ReferencedEntityBase
> saveReferencedEntitiesAll(Collection
<ReferencedEntityBase
> referencedEntityCollection
){
401 return referencedEntityDao
.saveAll(referencedEntityCollection
);
405 * TODO candidate for harmonization
408 public List
<TaxonNameBase
> getAllNames(int limit
, int start
){
409 return dao
.list(limit
, start
);
413 * TODO candidate for harmonization
414 * new name getNomenclaturalStatus
417 public List
<NomenclaturalStatus
> getAllNomenclaturalStatus(int limit
, int start
){
418 return nomStatusDao
.list(limit
, start
);
422 * TODO candidate for harmonization
423 * new name getTypeDesignations
426 public List
<TypeDesignationBase
> getAllTypeDesignations(int limit
, int start
){
427 return typeDesignationDao
.getAllTypeDesignations(limit
, start
);
430 * FIXME Candidate for harmonization
431 * homotypicalGroupService.list
434 public List
<HomotypicalGroup
> getAllHomotypicalGroups(int limit
, int start
){
435 return homotypicalGroupDao
.list(limit
, start
);
439 * FIXME Candidate for harmonization
444 public List
<RelationshipBase
> getAllRelationships(int limit
, int start
){
445 return dao
.getAllRelationships(limit
, start
);
449 * FIXME Candidate for harmonization
450 * is this not the same as termService.getVocabulary(VocabularyEnum.Rank)
451 * since this returns OrderedTermVocabulary
454 * @see eu.etaxonomy.cdm.api.service.INameService#getRankVocabulary()
457 public OrderedTermVocabulary
<Rank
> getRankVocabulary() {
458 String uuidString
= "ef0d1ce1-26e3-4e83-b47b-ca74eed40b1b";
459 UUID uuid
= UUID
.fromString(uuidString
);
460 OrderedTermVocabulary
<Rank
> rankVocabulary
=
461 (OrderedTermVocabulary
)orderedVocabularyDao
.findByUuid(uuid
);
462 return rankVocabulary
;
466 * FIXME Candidate for harmonization
467 * is this the same as termService.getVocabulary(VocabularyEnum.NameRelationshipType)
469 * @see eu.etaxonomy.cdm.api.service.INameService#getNameRelationshipTypeVocabulary()
472 public TermVocabulary
<NameRelationshipType
> getNameRelationshipTypeVocabulary() {
473 String uuidString
= "6878cb82-c1a4-4613-b012-7e73b413c8cd";
474 UUID uuid
= UUID
.fromString(uuidString
);
475 TermVocabulary
<NameRelationshipType
> nameRelTypeVocabulary
=
476 vocabularyDao
.findByUuid(uuid
);
477 return nameRelTypeVocabulary
;
481 * FIXME Candidate for harmonization
482 * is this the same as termService.getVocabulary(VocabularyEnum.StatusType)
484 * @see eu.etaxonomy.cdm.api.service.INameService#getStatusTypeVocabulary()
487 public TermVocabulary
<NomenclaturalStatusType
> getStatusTypeVocabulary() {
488 String uuidString
= "bb28cdca-2f8a-4f11-9c21-517e9ae87f1f";
489 UUID uuid
= UUID
.fromString(uuidString
);
490 TermVocabulary
<NomenclaturalStatusType
> nomStatusTypeVocabulary
=
491 vocabularyDao
.findByUuid(uuid
);
492 return nomStatusTypeVocabulary
;
496 * FIXME Candidate for harmonization
497 * is this the same as termService.getVocabulary(VocabularyEnum.SpecimenTypeDesignationStatus)
499 * @see eu.etaxonomy.cdm.api.service.INameService#getTypeDesignationStatusVocabulary()
502 public TermVocabulary
<SpecimenTypeDesignationStatus
> getSpecimenTypeDesignationStatusVocabulary() {
503 String uuidString
= "ab177bd7-d3c8-4e58-a388-226fff6ba3c2";
504 UUID uuid
= UUID
.fromString(uuidString
);
505 TermVocabulary
<SpecimenTypeDesignationStatus
> typeDesigStatusVocabulary
=
506 vocabularyDao
.findByUuid(uuid
);
507 return typeDesigStatusVocabulary
;
511 * FIXME Candidate for harmonization
512 * is this the same as termService.getVocabulary(VocabularyEnum.SpecimenTypeDesignationStatus)
513 * and also seems to duplicate the above method, differing only in the DAO used and the return type
515 * @see eu.etaxonomy.cdm.api.service.INameService#getTypeDesignationStatusVocabulary()
518 public OrderedTermVocabulary
<SpecimenTypeDesignationStatus
> getSpecimenTypeDesignationVocabulary() {
519 String uuidString
= "ab177bd7-d3c8-4e58-a388-226fff6ba3c2";
520 UUID uuid
= UUID
.fromString(uuidString
);
521 OrderedTermVocabulary
<SpecimenTypeDesignationStatus
> typeDesignationVocabulary
=
522 (OrderedTermVocabulary
)orderedVocabularyDao
.findByUuid(uuid
);
523 return typeDesignationVocabulary
;
529 protected void setDao(ITaxonNameDao dao
) {
534 public Pager
<HybridRelationship
> getHybridNames(NonViralName name
, HybridRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
535 Integer numberOfResults
= dao
.countHybridNames(name
, type
);
537 List
<HybridRelationship
> results
= new ArrayList
<HybridRelationship
>();
538 if(AbstractPagerImpl
.hasResultsInRange(numberOfResults
.longValue(), pageNumber
, pageSize
)) { // no point checking again
539 results
= dao
.getHybridNames(name
, type
, pageSize
, pageNumber
,orderHints
,propertyPaths
);
542 return new DefaultPagerImpl
<HybridRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
546 * @see eu.etaxonomy.cdm.api.service.INameService#listNameRelationships(eu.etaxonomy.cdm.model.name.TaxonNameBase, eu.etaxonomy.cdm.model.common.RelationshipBase.Direction, eu.etaxonomy.cdm.model.name.NameRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
549 public List
<NameRelationship
> listNameRelationships(TaxonNameBase name
, Direction direction
, NameRelationshipType type
, Integer pageSize
,
550 Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
552 Integer numberOfResults
= dao
.countNameRelationships(name
, NameRelationship
.Direction
.relatedFrom
, type
);
554 List
<NameRelationship
> results
= new ArrayList
<NameRelationship
>();
555 if (AbstractPagerImpl
.hasResultsInRange(numberOfResults
.longValue(), pageNumber
, pageSize
)) { // no point checking again
556 results
= dao
.getNameRelationships(name
, direction
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
562 protected LuceneSearch
prepareFindByFuzzyNameSearch(Class
<?
extends CdmBase
> clazz
,
566 List
<Language
> languages
,
567 boolean highlightFragments
) {
568 String similarity
= Float
.toString(accuracy
);
569 String searchSuffix
= "~" + similarity
;
572 BooleanQuery finalQuery
= new BooleanQuery(false);
573 BooleanQuery textQuery
= new BooleanQuery(false);
575 LuceneSearch luceneSearch
= new LuceneSearch(luceneIndexToolProvider
, TaxonNameBase
.class);
576 QueryFactory queryFactory
= luceneIndexToolProvider
.newQueryFactoryFor(TaxonNameBase
.class);
578 // SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING, false)};
579 // luceneSearch.setSortFields(sortFields);
581 // ---- search criteria
582 luceneSearch
.setCdmTypRestriction(clazz
);
584 FuzzyLikeThisQuery fltq
= new FuzzyLikeThisQuery(maxNoOfResults
, luceneSearch
.getAnalyzer());
585 if(nvn
.getGenusOrUninomial() != null && !nvn
.getGenusOrUninomial().equals("")) {
586 fltq
.addTerms(nvn
.getGenusOrUninomial().toLowerCase(), "genusOrUninomial", accuracy
, 3);
588 //textQuery.add(new RegexQuery (new Term ("genusOrUninomial", "^[a-zA-Z]*")), Occur.MUST_NOT);
589 textQuery
.add(queryFactory
.newTermQuery("genusOrUninomial", "_null_", false), Occur
.MUST
);
592 if(nvn
.getInfraGenericEpithet() != null && !nvn
.getInfraGenericEpithet().equals("")){
593 fltq
.addTerms(nvn
.getInfraGenericEpithet().toLowerCase(), "infraGenericEpithet", accuracy
, 3);
595 //textQuery.add(new RegexQuery (new Term ("infraGenericEpithet", "^[a-zA-Z]*")), Occur.MUST_NOT);
596 textQuery
.add(queryFactory
.newTermQuery("infraGenericEpithet", "_null_", false), Occur
.MUST
);
599 if(nvn
.getSpecificEpithet() != null && !nvn
.getSpecificEpithet().equals("")){
600 fltq
.addTerms(nvn
.getSpecificEpithet().toLowerCase(), "specificEpithet", accuracy
, 3);
602 //textQuery.add(new RegexQuery (new Term ("specificEpithet", "^[a-zA-Z]*")), Occur.MUST_NOT);
603 textQuery
.add(queryFactory
.newTermQuery("specificEpithet", "_null_", false), Occur
.MUST
);
606 if(nvn
.getInfraSpecificEpithet() != null && !nvn
.getInfraSpecificEpithet().equals("")){
607 fltq
.addTerms(nvn
.getInfraSpecificEpithet().toLowerCase(), "infraSpecificEpithet", accuracy
, 3);
609 //textQuery.add(new RegexQuery (new Term ("infraSpecificEpithet", "^[a-zA-Z]*")), Occur.MUST_NOT);
610 textQuery
.add(queryFactory
.newTermQuery("infraSpecificEpithet", "_null_", false), Occur
.MUST
);
613 if(nvn
.getAuthorshipCache() != null && !nvn
.getAuthorshipCache().equals("")){
614 fltq
.addTerms(nvn
.getAuthorshipCache().toLowerCase(), "authorshipCache", accuracy
, 3);
616 //textQuery.add(new RegexQuery (new Term ("authorshipCache", "^[a-zA-Z]*")), Occur.MUST_NOT);
619 textQuery
.add(fltq
, Occur
.MUST
);
621 finalQuery
.add(textQuery
, Occur
.MUST
);
623 luceneSearch
.setQuery(finalQuery
);
625 if(highlightFragments
){
626 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
631 protected LuceneSearch
prepareFindByFuzzyNameCacheSearch(Class
<?
extends CdmBase
> clazz
,
635 List
<Language
> languages
,
636 boolean highlightFragments
) {
638 LuceneSearch luceneSearch
= new LuceneSearch(luceneIndexToolProvider
, TaxonNameBase
.class);
639 QueryFactory queryFactory
= luceneIndexToolProvider
.newQueryFactoryFor(TaxonNameBase
.class);
641 // SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING, false)};
642 // luceneSearch.setSortFields(sortFields);
644 // ---- search criteria
645 luceneSearch
.setCdmTypRestriction(clazz
);
646 FuzzyLikeThisQuery fltq
= new FuzzyLikeThisQuery(maxNoOfResults
, luceneSearch
.getAnalyzer());
648 fltq
.addTerms(name
, "nameCache", accuracy
, 3);
650 BooleanQuery finalQuery
= new BooleanQuery(false);
652 finalQuery
.add(fltq
, Occur
.MUST
);
654 luceneSearch
.setQuery(finalQuery
);
656 if(highlightFragments
){
657 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
662 protected LuceneSearch
prepareFindByExactNameSearch(Class
<?
extends CdmBase
> clazz
,
665 List
<Language
> languages
,
666 boolean highlightFragments
) {
667 BooleanQuery finalQuery
= new BooleanQuery();
668 BooleanQuery textQuery
= new BooleanQuery();
670 LuceneSearch luceneSearch
= new LuceneSearch(luceneIndexToolProvider
, TaxonNameBase
.class);
671 QueryFactory queryFactory
= luceneIndexToolProvider
.newQueryFactoryFor(TaxonNameBase
.class);
673 // SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING, false)};
674 // luceneSearch.setSortFields(sortFields);
676 // ---- search criteria
677 luceneSearch
.setCdmTypRestriction(clazz
);
679 if(name
!= null && !name
.equals("")) {
681 textQuery
.add(new WildcardQuery(new Term("nameCache", name
+ "*")), Occur
.MUST
);
683 textQuery
.add(queryFactory
.newTermQuery("nameCache", name
, false), Occur
.MUST
);
687 luceneSearch
.setQuery(textQuery
);
689 if(highlightFragments
){
690 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
696 public List
<SearchResult
<TaxonNameBase
>> findByNameFuzzySearch(
699 List
<Language
> languages
,
700 boolean highlightFragments
,
701 List
<String
> propertyPaths
,
702 int maxNoOfResults
) throws CorruptIndexException
, IOException
, ParseException
{
704 logger
.info("Name to fuzzy search for : " + name
);
705 // parse the input name
706 NonViralNameParserImpl parser
= new NonViralNameParserImpl();
707 NonViralName nvn
= parser
.parseFullName(name
);
708 if(name
!= null && !name
.equals("") && nvn
== null) {
709 throw new ParseException("Could not parse name " + name
);
711 LuceneSearch luceneSearch
= prepareFindByFuzzyNameSearch(null, nvn
, accuracy
, maxNoOfResults
, languages
, highlightFragments
);
713 // --- execute search
714 TopDocs topDocs
= luceneSearch
.executeSearch(maxNoOfResults
);
717 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
718 idFieldMap
.put(CdmBaseType
.NONVIRALNAME
, "id");
720 // --- initialize taxa, highlight matches ....
721 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
723 @SuppressWarnings("rawtypes")
724 List
<SearchResult
<TaxonNameBase
>> searchResults
= searchResultBuilder
.createResultSet(
725 topDocs
, luceneSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
727 return searchResults
;
732 public List
<DocumentSearchResult
> findByNameFuzzySearch(
735 List
<Language
> languages
,
736 boolean highlightFragments
,
737 int maxNoOfResults
) throws CorruptIndexException
, IOException
, ParseException
{
739 logger
.info("Name to fuzzy search for : " + name
);
740 // parse the input name
741 NonViralNameParserImpl parser
= new NonViralNameParserImpl();
742 NonViralName nvn
= parser
.parseFullName(name
);
743 if(name
!= null && !name
.equals("") && nvn
== null) {
744 throw new ParseException("Could not parse name " + name
);
746 LuceneSearch luceneSearch
= prepareFindByFuzzyNameSearch(null, nvn
, accuracy
, maxNoOfResults
, languages
, highlightFragments
);
748 // --- execute search
749 TopDocs topDocs
= luceneSearch
.executeSearch(maxNoOfResults
);
751 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
753 // --- initialize taxa, highlight matches ....
754 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
756 @SuppressWarnings("rawtypes")
757 List
<DocumentSearchResult
> searchResults
= searchResultBuilder
.createResultSet(topDocs
, luceneSearch
.getHighlightFields());
759 return searchResults
;
763 public List
<DocumentSearchResult
> findByFuzzyNameCacheSearch(
766 List
<Language
> languages
,
767 boolean highlightFragments
,
768 int maxNoOfResults
) throws CorruptIndexException
, IOException
, ParseException
{
770 logger
.info("Name to fuzzy search for : " + name
);
772 LuceneSearch luceneSearch
= prepareFindByFuzzyNameCacheSearch(null, name
, accuracy
, maxNoOfResults
, languages
, highlightFragments
);
774 // --- execute search
775 TopDocs topDocs
= luceneSearch
.executeSearch(maxNoOfResults
);
776 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
778 // --- initialize taxa, highlight matches ....
779 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
781 @SuppressWarnings("rawtypes")
782 List
<DocumentSearchResult
> searchResults
= searchResultBuilder
.createResultSet(topDocs
, luceneSearch
.getHighlightFields());
784 return searchResults
;
788 public List
<DocumentSearchResult
> findByNameExactSearch(
791 List
<Language
> languages
,
792 boolean highlightFragments
,
793 int maxNoOfResults
) throws CorruptIndexException
, IOException
, ParseException
{
795 logger
.info("Name to exact search for : " + name
);
797 LuceneSearch luceneSearch
= prepareFindByExactNameSearch(null, name
, wildcard
, languages
, highlightFragments
);
799 // --- execute search
802 TopDocs topDocs
= luceneSearch
.executeSearch(maxNoOfResults
);
804 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
806 // --- initialize taxa, highlight matches ....
807 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
809 @SuppressWarnings("rawtypes")
810 List
<DocumentSearchResult
> searchResults
= searchResultBuilder
.createResultSet(topDocs
, luceneSearch
.getHighlightFields());
812 return searchResults
;
816 * @see eu.etaxonomy.cdm.api.service.INameService#pageNameRelationships(eu.etaxonomy.cdm.model.name.TaxonNameBase, eu.etaxonomy.cdm.model.common.RelationshipBase.Direction, eu.etaxonomy.cdm.model.name.NameRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
819 public Pager
<NameRelationship
> pageNameRelationships(TaxonNameBase name
, Direction direction
, NameRelationshipType type
, Integer pageSize
,
820 Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
821 List
<NameRelationship
> results
= listNameRelationships(name
, direction
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
822 return new DefaultPagerImpl
<NameRelationship
>(pageNumber
, results
.size(), pageSize
, results
);
826 public List
<NameRelationship
> listFromNameRelationships(TaxonNameBase name
, NameRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
827 return listNameRelationships(name
, Direction
.relatedFrom
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
831 public Pager
<NameRelationship
> pageFromNameRelationships(TaxonNameBase name
, NameRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
832 List
<NameRelationship
> results
= listNameRelationships(name
, Direction
.relatedFrom
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
833 return new DefaultPagerImpl
<NameRelationship
>(pageNumber
, results
.size(), pageSize
, results
);
837 public List
<NameRelationship
> listToNameRelationships(TaxonNameBase name
, NameRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
838 return listNameRelationships(name
, Direction
.relatedTo
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
842 public Pager
<NameRelationship
> pageToNameRelationships(TaxonNameBase name
, NameRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
843 List
<NameRelationship
> results
= listNameRelationships(name
, Direction
.relatedTo
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
844 return new DefaultPagerImpl
<NameRelationship
>(pageNumber
, results
.size(), pageSize
, results
);
848 public Pager
<TypeDesignationBase
> getTypeDesignations(TaxonNameBase name
, SpecimenTypeDesignationStatus status
,
849 Integer pageSize
, Integer pageNumber
) {
850 return getTypeDesignations(name
, status
, pageSize
, pageNumber
, null);
854 public Pager
<TypeDesignationBase
> getTypeDesignations(TaxonNameBase name
, SpecimenTypeDesignationStatus status
,
855 Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
){
856 Integer numberOfResults
= dao
.countTypeDesignations(name
, status
);
858 List
<TypeDesignationBase
> results
= new ArrayList
<TypeDesignationBase
>();
859 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
860 results
= dao
.getTypeDesignations(name
, status
, pageSize
, pageNumber
, propertyPaths
);
863 return new DefaultPagerImpl
<TypeDesignationBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
867 * FIXME Candidate for harmonization
871 public Pager
<TaxonNameBase
> searchNames(String uninomial
,String infraGenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
,
872 List
<String
> propertyPaths
) {
873 Integer numberOfResults
= dao
.countNames(uninomial
, infraGenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
875 List
<TaxonNameBase
> results
= new ArrayList
<TaxonNameBase
>();
876 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
877 results
= dao
.searchNames(uninomial
, infraGenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
880 return new DefaultPagerImpl
<TaxonNameBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
884 * @see eu.etaxonomy.cdm.api.service.INameService#getUuidAndTitleCacheOfNames()
887 public List
<UuidAndTitleCache
> getUuidAndTitleCacheOfNames() {
888 return dao
.getUuidAndTitleCacheOfNames();
892 public Pager
<TaxonNameBase
> findByName(Class
<?
extends TaxonNameBase
> clazz
, String queryString
, MatchMode matchmode
, List
<Criterion
> criteria
, Integer pageSize
,Integer pageNumber
, List
<OrderHint
> orderHints
,List
<String
> propertyPaths
) {
893 Integer numberOfResults
= dao
.countByName(clazz
, queryString
, matchmode
, criteria
);
895 List
<TaxonNameBase
> results
= new ArrayList
<TaxonNameBase
>();
896 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
897 results
= dao
.findByName(clazz
, queryString
, matchmode
, criteria
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
900 return new DefaultPagerImpl
<TaxonNameBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
904 public HomotypicalGroup
findHomotypicalGroup(UUID uuid
) {
905 return homotypicalGroupDao
.findByUuid(uuid
);
910 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
913 @Transactional(readOnly
= false)
914 public void updateTitleCache(Class
<?
extends TaxonNameBase
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<TaxonNameBase
> cacheStrategy
, IProgressMonitor monitor
) {
916 clazz
= TaxonNameBase
.class;
918 super.updateTitleCacheImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
923 protected void setOtherCachesNull(TaxonNameBase name
) {
924 if (name
.isInstanceOf(NonViralName
.class)){
925 NonViralName
<?
> nvn
= CdmBase
.deproxy(name
, NonViralName
.class);
926 if (! nvn
.isProtectedNameCache()){
927 nvn
.setNameCache(null, false);
929 if (! nvn
.isProtectedAuthorshipCache()){
930 nvn
.setAuthorshipCache(null, false);
932 if (! nvn
.isProtectedFullTitleCache()){
933 nvn
.setFullTitleCache(null, false);
939 * @see eu.etaxonomy.cdm.api.service.INameService#getTaggedName(eu.etaxonomy.cdm.model.name.TaxonNameBase)
942 public List
<TaggedText
> getTaggedName(UUID uuid
) {
943 TaxonNameBase taxonNameBase
= dao
.load(uuid
);
944 List taggedName
= taxonNameBase
.getTaggedName();