Project

General

Profile

Download (55.5 KB) Statistics
| Branch: | Tag: | Revision:
1 2622a38b Andreas Müller
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
10
package eu.etaxonomy.cdm.api.service;
11
12
import java.io.IOException;
13
import java.util.ArrayList;
14 8b7b8537 Patrick Plitzner
import java.util.Arrays;
15 2622a38b Andreas Müller
import java.util.Collection;
16
import java.util.HashMap;
17
import java.util.HashSet;
18
import java.util.List;
19
import java.util.Map;
20 9fc2a8a0 Andreas Kohlbecker
import java.util.Optional;
21 2622a38b Andreas Müller
import java.util.Set;
22
import java.util.UUID;
23
24
import org.apache.log4j.Logger;
25
import org.apache.lucene.index.Term;
26
import org.apache.lucene.sandbox.queries.FuzzyLikeThisQuery;
27
import org.apache.lucene.search.BooleanClause.Occur;
28
import org.apache.lucene.search.BooleanQuery;
29 f6b282fc Andreas Kohlbecker
import org.apache.lucene.search.BooleanQuery.Builder;
30 2622a38b Andreas Müller
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;
37
38
import eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase;
39
import eu.etaxonomy.cdm.api.service.config.NameDeletionConfigurator;
40 72312cbc Andreas Kohlbecker
import eu.etaxonomy.cdm.api.service.dto.TypeDesignationStatusFilter;
41 2622a38b Andreas Müller
import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
42
import eu.etaxonomy.cdm.api.service.pager.Pager;
43
import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;
44
import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
45
import eu.etaxonomy.cdm.api.service.search.DocumentSearchResult;
46
import eu.etaxonomy.cdm.api.service.search.ILuceneIndexToolProvider;
47
import eu.etaxonomy.cdm.api.service.search.ISearchResultBuilder;
48 3ca8a283 Patrick Plitzner
import eu.etaxonomy.cdm.api.service.search.LuceneParseException;
49 2622a38b Andreas Müller
import eu.etaxonomy.cdm.api.service.search.LuceneSearch;
50
import eu.etaxonomy.cdm.api.service.search.QueryFactory;
51
import eu.etaxonomy.cdm.api.service.search.SearchResult;
52
import eu.etaxonomy.cdm.api.service.search.SearchResultBuilder;
53 9fc2a8a0 Andreas Kohlbecker
import eu.etaxonomy.cdm.api.utility.TaxonNamePartsFilter;
54 2622a38b Andreas Müller
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
55
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
56
import eu.etaxonomy.cdm.model.CdmBaseType;
57 a9bd2165 Andreas Müller
import eu.etaxonomy.cdm.model.agent.Person;
58
import eu.etaxonomy.cdm.model.agent.Team;
59 72eb424b Andreas Müller
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
60 2622a38b Andreas Müller
import eu.etaxonomy.cdm.model.common.CdmBase;
61
import eu.etaxonomy.cdm.model.common.Language;
62
import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;
63 eac82784 Andreas Müller
import eu.etaxonomy.cdm.model.common.SourcedEntityBase;
64 2622a38b Andreas Müller
import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
65
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
66
import eu.etaxonomy.cdm.model.name.HybridRelationship;
67
import eu.etaxonomy.cdm.model.name.HybridRelationshipType;
68 396a8759 Andreas Müller
import eu.etaxonomy.cdm.model.name.INonViralName;
69 2622a38b Andreas Müller
import eu.etaxonomy.cdm.model.name.NameRelationship;
70
import eu.etaxonomy.cdm.model.name.NameRelationshipType;
71
import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
72 72eb424b Andreas Müller
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
73 c1a8faa1 Andreas Müller
import eu.etaxonomy.cdm.model.name.NomenclaturalSource;
74 2622a38b Andreas Müller
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
75
import eu.etaxonomy.cdm.model.name.Rank;
76 9b23bbdc Katja Luther
import eu.etaxonomy.cdm.model.name.Registration;
77 99366401 Patrick Plitzner
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
78 2622a38b Andreas Müller
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus;
79 9dc896c9 Andreas Müller
import eu.etaxonomy.cdm.model.name.TaxonName;
80 0020d108 Andreas Müller
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
81 2622a38b Andreas Müller
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
82 72312cbc Andreas Kohlbecker
import eu.etaxonomy.cdm.model.name.TypeDesignationStatusBase;
83 99366401 Patrick Plitzner
import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;
84 2622a38b Andreas Müller
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
85
import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;
86 46567e3a Patrick Plitzner
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
87 99366401 Patrick Plitzner
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
88 72eb424b Andreas Müller
import eu.etaxonomy.cdm.model.reference.Reference;
89 1e97edc1 Katja Luther
import eu.etaxonomy.cdm.model.taxon.Taxon;
90
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
91 2622a38b Andreas Müller
import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;
92 eac82784 Andreas Müller
import eu.etaxonomy.cdm.persistence.dao.common.ISourcedEntityDao;
93 67c8f20e Andreas Kohlbecker
import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
94 aa8cf7e6 Andreas Kohlbecker
import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
95 2622a38b Andreas Müller
import eu.etaxonomy.cdm.persistence.dao.name.IHomotypicalGroupDao;
96
import eu.etaxonomy.cdm.persistence.dao.name.INomenclaturalStatusDao;
97
import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao;
98
import eu.etaxonomy.cdm.persistence.dao.name.ITypeDesignationDao;
99 c1a8faa1 Andreas Müller
import eu.etaxonomy.cdm.persistence.dao.reference.IOriginalSourceDao;
100 9fc2a8a0 Andreas Kohlbecker
import eu.etaxonomy.cdm.persistence.dto.TaxonNameParts;
101 2622a38b Andreas Müller
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
102
import eu.etaxonomy.cdm.persistence.query.MatchMode;
103
import eu.etaxonomy.cdm.persistence.query.OrderHint;
104
import eu.etaxonomy.cdm.strategy.cache.TaggedText;
105
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
106 c078cfb8 Andreas Müller
import eu.etaxonomy.cdm.strategy.match.IMatchStrategy;
107 72eb424b Andreas Müller
import eu.etaxonomy.cdm.strategy.match.IMatchable;
108
import eu.etaxonomy.cdm.strategy.match.IParsedMatchStrategy;
109
import eu.etaxonomy.cdm.strategy.match.MatchException;
110
import eu.etaxonomy.cdm.strategy.match.MatchStrategyFactory;
111 2622a38b Andreas Müller
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
112
113
114
@Service
115
@Transactional(readOnly = true)
116 f13dc62d Andreas Müller
public class NameServiceImpl
117
          extends IdentifiableServiceBase<TaxonName,ITaxonNameDao>
118
          implements INameService {
119 b36706c7 Andreas Müller
120 2622a38b Andreas Müller
    static private final Logger logger = Logger.getLogger(NameServiceImpl.class);
121
122
    @Autowired
123 c1a8faa1 Andreas Müller
    private IOccurrenceService occurrenceService;
124 2622a38b Andreas Müller
    @Autowired
125 c1a8faa1 Andreas Müller
    private ICollectionService collectionService;
126 2622a38b Andreas Müller
    @Autowired
127 c1a8faa1 Andreas Müller
    private ITaxonService taxonService;
128 99366401 Patrick Plitzner
    @Autowired
129 c1a8faa1 Andreas Müller
    private ICommonService commonService;
130 1e97edc1 Katja Luther
    @Autowired
131 eac82784 Andreas Müller
    @Qualifier("sourcedEntityDao")
132 c1a8faa1 Andreas Müller
    private ISourcedEntityDao<SourcedEntityBase<?>> sourcedEntityDao;
133 eac82784 Andreas Müller
    @Autowired
134 2622a38b Andreas Müller
    private INomenclaturalStatusDao nomStatusDao;
135
    @Autowired
136
    private ITypeDesignationDao typeDesignationDao;
137
    @Autowired
138
    private IHomotypicalGroupDao homotypicalGroupDao;
139
    @Autowired
140
    private ICdmGenericDao genericDao;
141
    @Autowired
142
    private ILuceneIndexToolProvider luceneIndexToolProvider;
143 72eb424b Andreas Müller
    @Autowired
144 c1a8faa1 Andreas Müller
    private IOriginalSourceDao sourcedDao;
145 72eb424b Andreas Müller
146 aa8cf7e6 Andreas Kohlbecker
    @Autowired
147
    // @Qualifier("defaultBeanInitializer")
148
    protected IBeanInitializer defaultBeanInitializer;
149 2622a38b Andreas Müller
150 b36706c7 Andreas Müller
//***************************** CONSTRUCTOR **********************************/
151
152 2622a38b Andreas Müller
    /**
153
     * Constructor
154
     */
155 7b43c8a7 Andreas Müller
    public NameServiceImpl(){}
156 2622a38b Andreas Müller
157 b36706c7 Andreas Müller
//********************* METHODS ***********************************************//
158 2622a38b Andreas Müller
159
    @Override
160
    @Transactional(readOnly = false)
161
    public DeleteResult delete(UUID nameUUID){
162
        NameDeletionConfigurator config = new NameDeletionConfigurator();
163
        DeleteResult result = delete(nameUUID, config);
164
        return result;
165
    }
166
167
    @Override
168 9dc896c9 Andreas Müller
    public DeleteResult delete(TaxonName name){
169 2622a38b Andreas Müller
        return delete(name.getUuid());
170
    }
171
172
    @Override
173
    @Transactional(readOnly = false)
174 1f088ad4 Andreas Müller
    public DeleteResult delete(TaxonName name, NameDeletionConfigurator config) {
175 a80ca382 Katja Luther
        DeleteResult result = new DeleteResult();
176 2622a38b Andreas Müller
177 a80ca382 Katja Luther
        if (name == null){
178
            result.setAbort();
179 2622a38b Andreas Müller
            return result;
180
        }
181
182 a80ca382 Katja Luther
        try{
183
            result = this.isDeletable(name, config);
184 2622a38b Andreas Müller
        }catch(Exception e){
185 a80ca382 Katja Luther
            result.addException(e);
186
            result.setError();
187
            return result;
188 2622a38b Andreas Müller
        }
189
        if (result.isOk()){
190
        //remove references to this name
191 a80ca382 Katja Luther
            removeNameRelationshipsByDeleteConfig(name, config);
192 2622a38b Andreas Müller
193
           //remove name from homotypical group
194
            HomotypicalGroup homotypicalGroup = name.getHomotypicalGroup();
195
            if (homotypicalGroup != null){
196
                homotypicalGroup.removeTypifiedName(name, false);
197
            }
198
199
             //all type designation relationships are removed as they belong to the name
200 a80ca382 Katja Luther
            deleteTypeDesignation(name, null);
201
    //      //type designations
202
    //      if (! name.getTypeDesignations().isEmpty()){
203
    //          String message = "Name can't be deleted as it has types. Remove types prior to deletion.";
204
    //          throw new ReferrencedObjectUndeletableException(message);
205
    //      }
206 2622a38b Andreas Müller
207 a80ca382 Katja Luther
            try{
208 7b43c8a7 Andreas Müller
                dao.delete(name);
209 815a9015 Katja Luther
                result.addDeletedObject(name);
210 a80ca382 Katja Luther
            }catch(Exception e){
211
                result.addException(e);
212
                result.setError();
213
            }
214
            return result;
215 2622a38b Andreas Müller
        }
216
217
        return result;
218
    }
219
220 a80ca382 Katja Luther
    @Override
221
    @Transactional(readOnly = false)
222
    public DeleteResult delete(UUID nameUUID, NameDeletionConfigurator config) {
223
224 1f088ad4 Andreas Müller
        TaxonName name = dao.load(nameUUID);
225 a80ca382 Katja Luther
        return delete(name, config);
226
    }
227
228 2622a38b Andreas Müller
    @Override
229 99366401 Patrick Plitzner
    @Transactional(readOnly = false)
230 8b7b8537 Patrick Plitzner
    public UpdateResult cloneTypeDesignation(UUID nameUuid, SpecimenTypeDesignation baseDesignation,
231 3262af01 Patrick Plitzner
            String accessionNumber, String barcode, String catalogNumber,
232
            UUID collectionUuid, SpecimenTypeDesignationStatus typeStatus){
233 99366401 Patrick Plitzner
        UpdateResult result = new UpdateResult();
234
235 8b7b8537 Patrick Plitzner
        DerivedUnit baseSpecimen = HibernateProxyHelper.deproxy(occurrenceService.load(baseDesignation.getTypeSpecimen().getUuid(), Arrays.asList("collection")), DerivedUnit.class);
236 99366401 Patrick Plitzner
        DerivedUnit duplicate = DerivedUnit.NewInstance(baseSpecimen.getRecordBasis());
237
        DerivationEvent derivedFrom = baseSpecimen.getDerivedFrom();
238 46567e3a Patrick Plitzner
        Collection<FieldUnit> fieldUnits = occurrenceService.findFieldUnits(baseSpecimen.getUuid(), null);
239
        if(fieldUnits.size()!=1){
240
            result.addException(new Exception("More than one or no field unit found for specimen"));
241
            result.setError();
242
            return result;
243
        }
244 99366401 Patrick Plitzner
        for (SpecimenOrObservationBase original : derivedFrom.getOriginals()) {
245
            DerivationEvent.NewSimpleInstance(original, duplicate, derivedFrom.getType());
246
        }
247
        duplicate.setAccessionNumber(accessionNumber);
248 3262af01 Patrick Plitzner
        duplicate.setBarcode(barcode);
249
        duplicate.setCatalogNumber(catalogNumber);
250 8b7b8537 Patrick Plitzner
        duplicate.setCollection(collectionService.load(collectionUuid));
251 99366401 Patrick Plitzner
        SpecimenTypeDesignation typeDesignation = SpecimenTypeDesignation.NewInstance();
252
        typeDesignation.setTypeSpecimen(duplicate);
253
        typeDesignation.setTypeStatus(typeStatus);
254 8b7b8537 Patrick Plitzner
255
        TaxonName name = load(nameUuid);
256 99366401 Patrick Plitzner
        name.getTypeDesignations().add(typeDesignation);
257
258
        result.setCdmEntity(typeDesignation);
259
        result.addUpdatedObject(name);
260
        return result;
261
    }
262
263
    @Override
264 05948447 Katja Luther
    @Transactional
265 d825b848 Andreas Müller
    public DeleteResult deleteTypeDesignation(TaxonName name, TypeDesignationBase<?> typeDesignation){
266 7b43c8a7 Andreas Müller
    	if(typeDesignation != null && typeDesignation .isPersited()){
267 eac82784 Andreas Müller
    		typeDesignation = HibernateProxyHelper.deproxy(sourcedEntityDao.load(typeDesignation.getUuid()), TypeDesignationBase.class);
268 fff47116 Patrick Plitzner
    	}
269 7d256eab Patrick Plitzner
270 efcfd4bb Patrick Plitzner
        DeleteResult result = new DeleteResult();
271 2622a38b Andreas Müller
        if (name == null && typeDesignation == null){
272 efcfd4bb Patrick Plitzner
            result.setError();
273
            return result;
274 2622a38b Andreas Müller
        }else if (name != null && typeDesignation != null){
275
            removeSingleDesignation(name, typeDesignation);
276
        }else if (name != null){
277 66122abe Andreas Müller
            @SuppressWarnings("rawtypes")
278 556e3ea7 Andreas Müller
            Set<TypeDesignationBase<?>> designationSet = new HashSet(name.getTypeDesignations());
279 66122abe Andreas Müller
            for (TypeDesignationBase<?> desig : designationSet){
280
                desig = CdmBase.deproxy(desig);
281 2622a38b Andreas Müller
                removeSingleDesignation(name, desig);
282
            }
283
        }else if (typeDesignation != null){
284 7b43c8a7 Andreas Müller
            @SuppressWarnings("unchecked")
285 556e3ea7 Andreas Müller
            Set<TaxonName> nameSet = new HashSet(typeDesignation.getTypifiedNames());
286 66122abe Andreas Müller
            for (TaxonName singleName : nameSet){
287
                singleName = CdmBase.deproxy(singleName);
288 2622a38b Andreas Müller
                removeSingleDesignation(singleName, typeDesignation);
289
            }
290
        }
291 815a9015 Katja Luther
        result.addDeletedObject(typeDesignation);
292 efcfd4bb Patrick Plitzner
        result.addUpdatedObject(name);
293
        return result;
294
    }
295
296
297
    @Override
298 a4ea6502 Katja Luther
    @Transactional(readOnly = false)
299 efcfd4bb Patrick Plitzner
    public DeleteResult deleteTypeDesignation(UUID nameUuid, UUID typeDesignationUuid){
300 9dc896c9 Andreas Müller
        TaxonName nameBase = load(nameUuid);
301 eac82784 Andreas Müller
        TypeDesignationBase<?> typeDesignation = HibernateProxyHelper.deproxy(sourcedEntityDao.load(typeDesignationUuid), TypeDesignationBase.class);
302 efcfd4bb Patrick Plitzner
        return deleteTypeDesignation(nameBase, typeDesignation);
303 2622a38b Andreas Müller
    }
304
305
    /**
306
     * @param name
307
     * @param typeDesignation
308
     */
309 a4ea6502 Katja Luther
    @Transactional
310 d825b848 Andreas Müller
    private void removeSingleDesignation(TaxonName name, TypeDesignationBase<?> typeDesignation) {
311
312 2622a38b Andreas Müller
        name.removeTypeDesignation(typeDesignation);
313
        if (typeDesignation.getTypifiedNames().isEmpty()){
314
            typeDesignation.removeType();
315 9b23bbdc Katja Luther
            if (!typeDesignation.getRegistrations().isEmpty()){
316
                for(Object reg: typeDesignation.getRegistrations()){
317
                    if (reg instanceof Registration){
318
                        ((Registration)reg).removeTypeDesignation(typeDesignation);
319
                    }
320
                }
321
            }
322 d825b848 Andreas Müller
323 2622a38b Andreas Müller
            typeDesignationDao.delete(typeDesignation);
324 815a9015 Katja Luther
325 2622a38b Andreas Müller
        }
326
    }
327
328
329
330
    /**
331
     * @param name
332
     * @param config
333
     */
334 db183545 Andreas Müller
    private void removeNameRelationshipsByDeleteConfig(TaxonName name, NameDeletionConfigurator config) {
335 2622a38b Andreas Müller
        try {
336
            if (config.isRemoveAllNameRelationships()){
337
                Set<NameRelationship> rels = getModifiableSet(name.getNameRelations());
338
                for (NameRelationship rel : rels){
339
                    name.removeNameRelationship(rel);
340
                }
341
            }else{
342
                //relations to this name
343
                Set<NameRelationship> rels = getModifiableSet(name.getRelationsToThisName());
344
                for (NameRelationship rel : rels){
345
                    if (config.isIgnoreHasBasionym() && NameRelationshipType.BASIONYM().equals(rel.getType() )){
346
                            name.removeNameRelationship(rel);
347
                    }else if (config.isIgnoreHasReplacedSynonym() && NameRelationshipType.REPLACED_SYNONYM().equals(rel.getType())){
348
                        name.removeNameRelationship(rel);
349
                    }
350
                }
351
                //relations from this name
352
                rels = getModifiableSet(name.getRelationsFromThisName());
353
                for (NameRelationship rel : rels){
354
                    if (config.isIgnoreIsBasionymFor() && NameRelationshipType.BASIONYM().equals(rel.getType())  ){
355
                        name.removeNameRelationship(rel);
356
                    }else if (config.isIgnoreIsReplacedSynonymFor() && NameRelationshipType.REPLACED_SYNONYM().equals(rel.getType())){
357
                        name.removeNameRelationship(rel);
358
                    }
359
                }
360
361
            }
362
        } catch (Exception e) {
363
            throw new RuntimeException(e);
364
        }
365
    }
366
367
    /**
368
     * @param name
369
     * @return
370
     */
371
    private Set<NameRelationship> getModifiableSet(Set<NameRelationship> relations) {
372
        Set<NameRelationship> rels = new HashSet<NameRelationship>();
373
        for (NameRelationship rel : relations){
374
            rels.add(rel);
375
        }
376
        return rels;
377
    }
378
379
//********************* METHODS ****************************************************************//
380
381
382
    /**
383
     * TODO candidate for harmonization
384
     * new name findByName
385
     */
386
    @Override
387 05c87b75 Andreas Müller
    @Deprecated
388 9dc896c9 Andreas Müller
    public List<TaxonName> getNamesByNameCache(String nameCache){
389 05c87b75 Andreas Müller
        boolean includeAuthors = false;
390
        List result = dao.findByName(includeAuthors, nameCache, MatchMode.EXACT, null, null, null, null);
391 2622a38b Andreas Müller
        return result;
392
    }
393
394
    /**
395
     * TODO candidate for harmonization
396
     * new name saveHomotypicalGroups
397
     *
398
     * findByTitle
399
     */
400
    @Override
401 4ad2dc40 Andreas Müller
    @Deprecated
402 9dc896c9 Andreas Müller
    public List<TaxonName> findNamesByTitleCache(String titleCache, MatchMode matchMode, List<String> propertyPaths){
403 9fc2a8a0 Andreas Kohlbecker
        List result = dao.findByTitle(titleCache, matchMode, null, null, null, propertyPaths);
404 2622a38b Andreas Müller
        return result;
405
    }
406
407
    /**
408
     * TODO candidate for harmonization
409
     * new name saveHomotypicalGroups
410
     *
411
     * findByTitle
412
     */
413
    @Override
414 4ad2dc40 Andreas Müller
    @Deprecated
415 9dc896c9 Andreas Müller
    public List<TaxonName> findNamesByNameCache(String nameCache, MatchMode matchMode, List<String> propertyPaths){
416 e11ed28f Andreas Müller
        List<TaxonName> result = dao.findByName(false, nameCache, matchMode, null, null, null , propertyPaths);
417 2622a38b Andreas Müller
        return result;
418
    }
419
420 9fc2a8a0 Andreas Kohlbecker
    @Override
421
    public Pager<TaxonNameParts> findTaxonNameParts(Optional<String> genusOrUninomial,
422
            Optional<String> infraGenericEpithet, Optional<String> specificEpithet,
423 2ac69f0c Andreas Kohlbecker
            Optional<String> infraSpecificEpithet, Rank rank, Set<UUID> excludedNamesUuids,
424 efc5d1e3 Andreas Kohlbecker
            Integer pageSize, Integer pageIndex, List<OrderHint> orderHints) {
425 9fc2a8a0 Andreas Kohlbecker
426
427 2ac69f0c Andreas Kohlbecker
        long count = dao.countTaxonNameParts(genusOrUninomial, infraGenericEpithet, specificEpithet, infraGenericEpithet, rank, excludedNamesUuids);
428 9fc2a8a0 Andreas Kohlbecker
429
        List<TaxonNameParts> results;
430
        if(AbstractPagerImpl.hasResultsInRange(count, pageIndex, pageSize)){
431
            results = dao.findTaxonNameParts(genusOrUninomial, infraGenericEpithet, specificEpithet, infraSpecificEpithet,
432 2ac69f0c Andreas Kohlbecker
                    rank, excludedNamesUuids,
433 9fc2a8a0 Andreas Kohlbecker
                    pageSize, pageIndex, orderHints);
434
        } else {
435
            results = new ArrayList<>();
436
        }
437
438
        return new DefaultPagerImpl<TaxonNameParts>(pageIndex, count, pageSize, results);
439
    }
440
441
    /**
442
     * {@inheritDoc}
443
     */
444
    @Override
445
    public Pager<TaxonNameParts> findTaxonNameParts(TaxonNamePartsFilter filter, String namePartQueryString,
446
            Integer pageSize, Integer pageIndex, List<OrderHint> orderHints) {
447
448
        return findTaxonNameParts(
449
                filter.uninomialQueryString(namePartQueryString),
450
                filter.infraGenericEpithet(namePartQueryString),
451
                filter.specificEpithet(namePartQueryString),
452
                filter.infraspecificEpithet(namePartQueryString),
453
                filter.getRank(),
454 2ac69f0c Andreas Kohlbecker
                filter.getExludedNamesUuids(),
455 9fc2a8a0 Andreas Kohlbecker
                pageSize, pageIndex, orderHints);
456
    }
457
458 2622a38b Andreas Müller
    /**
459
     * TODO candidate for harmonization
460
     * new name saveHomotypicalGroups
461
     */
462
    @Override
463
    @Transactional(readOnly = false)
464
    public Map<UUID, HomotypicalGroup> saveAllHomotypicalGroups(Collection<HomotypicalGroup> homotypicalGroups){
465
        return homotypicalGroupDao.saveAll(homotypicalGroups);
466
    }
467
468
    /**
469
     * TODO candidate for harmonization
470
     * new name saveTypeDesignations
471
     */
472
    @Override
473
    @Transactional(readOnly = false)
474 d825b848 Andreas Müller
    public Map<UUID, TypeDesignationBase<?>> saveTypeDesignationAll(Collection<TypeDesignationBase<?>> typeDesignationCollection){
475 2622a38b Andreas Müller
        return typeDesignationDao.saveAll(typeDesignationCollection);
476
    }
477
478
    /**
479
     * TODO candidate for harmonization
480
     * new name getNomenclaturalStatus
481
     */
482
    @Override
483
    public List<NomenclaturalStatus> getAllNomenclaturalStatus(int limit, int start){
484
        return nomStatusDao.list(limit, start);
485
    }
486
487 49fdbd9a Andreas Kohlbecker
    @Override
488
    public NomenclaturalStatus loadNomenclaturalStatus(UUID uuid,  List<String> propertyPaths){
489
        return nomStatusDao.load(uuid, propertyPaths);
490
    }
491
492 2622a38b Andreas Müller
    /**
493
     * TODO candidate for harmonization
494
     * new name getTypeDesignations
495
     */
496
    @Override
497 d825b848 Andreas Müller
    public List<TypeDesignationBase<?>> getAllTypeDesignations(int limit, int start){
498 2622a38b Andreas Müller
        return typeDesignationDao.getAllTypeDesignations(limit, start);
499
    }
500 c1d7cb61 Andreas Kohlbecker
501 85b0276d Katja Luther
    @Override
502 d825b848 Andreas Müller
    public TypeDesignationBase<?> loadTypeDesignation(int id, List<String> propertyPaths){
503 c1d7cb61 Andreas Kohlbecker
        return typeDesignationDao.load(id, propertyPaths);
504
    }
505
506 85b0276d Katja Luther
    @Override
507 d825b848 Andreas Müller
    public TypeDesignationBase<?> loadTypeDesignation(UUID uuid, List<String> propertyPaths){
508 c1d7cb61 Andreas Kohlbecker
        return typeDesignationDao.load(uuid, propertyPaths);
509
    }
510 03e4c253 Andreas Müller
511 a0880292 Andreas Kohlbecker
    @Override
512
    public List<TypeDesignationBase<?>> loadTypeDesignations(List<UUID> uuids, List<String> propertyPaths){
513
    	if(uuids == null) {
514
            return null;
515
        }
516
517
        List<TypeDesignationBase<?>> entities = new ArrayList<>();
518
        for(UUID uuid : uuids) {
519
            entities.add(uuid == null ? null : typeDesignationDao.load(uuid, propertyPaths));
520
        }
521
        return entities;
522
    }
523 c1d7cb61 Andreas Kohlbecker
524
    /**
525 2622a38b Andreas Müller
     * FIXME Candidate for harmonization
526
     * homotypicalGroupService.list
527
     */
528
    @Override
529
    public List<HomotypicalGroup> getAllHomotypicalGroups(int limit, int start){
530
        return homotypicalGroupDao.list(limit, start);
531
    }
532
533 c1a8faa1 Andreas Müller
534
    @Override
535
    public List<NomenclaturalSource> listOriginalSpellings(Integer pageSize, Integer pageNumber,
536
            List<OrderHint> orderHints, List<String> propertyPaths) {
537
538
        Long numberOfResults = sourcedDao.countWithNameUsedInSource(NomenclaturalSource.class);
539
        List<NomenclaturalSource> results = new ArrayList<>();
540
        if(numberOfResults > 0) {
541
            results = sourcedDao.listWithNameUsedInSource(NomenclaturalSource.class, pageSize, pageNumber, orderHints, propertyPaths);
542
        }
543
        return results;
544
    }
545
546 2622a38b Andreas Müller
    @Override
547 4ad2dc40 Andreas Müller
    public List<NameRelationship> listNameRelationships(Set<NameRelationshipType> types,
548
            Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
549
550
        Long numberOfResults = dao.countNameRelationships(types);
551
        List<NameRelationship> results = new ArrayList<>();
552
        if(numberOfResults > 0) {
553
            results = dao.getNameRelationships(types, pageSize, pageNumber, orderHints, propertyPaths);
554
        }
555
        return results;
556 2622a38b Andreas Müller
    }
557
558 4ad2dc40 Andreas Müller
    @Override
559
    public List<HybridRelationship> listHybridRelationships(Set<HybridRelationshipType> types,
560
            Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
561
562
        Long numberOfResults = dao.countHybridRelationships(types);
563
        List<HybridRelationship> results = new ArrayList<>();
564
        if(numberOfResults > 0) {
565
            results = dao.getHybridRelationships(types, pageSize, pageNumber, orderHints, propertyPaths);
566
        }
567
        return results;
568
    }
569 2622a38b Andreas Müller
570
571
    @Override
572
    @Autowired
573
    protected void setDao(ITaxonNameDao dao) {
574
        this.dao = dao;
575
    }
576
577
    @Override
578 d7919b1c Andreas Müller
    public Pager<HybridRelationship> getHybridNames(INonViralName name,	HybridRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
579 2622a38b Andreas Müller
        Integer numberOfResults = dao.countHybridNames(name, type);
580
581
        List<HybridRelationship> results = new ArrayList<HybridRelationship>();
582
        if(AbstractPagerImpl.hasResultsInRange(numberOfResults.longValue(), pageNumber, pageSize)) { // no point checking again
583
            results = dao.getHybridNames(name, type, pageSize, pageNumber,orderHints,propertyPaths);
584
        }
585
586
        return new DefaultPagerImpl<HybridRelationship>(pageNumber, numberOfResults, pageSize, results);
587
    }
588
589
    @Override
590 9dc896c9 Andreas Müller
    public List<NameRelationship> listNameRelationships(TaxonName name,	Direction direction, NameRelationshipType type, Integer pageSize,
591 2622a38b Andreas Müller
            Integer pageNumber, List<OrderHint> orderHints,	List<String> propertyPaths) {
592
593
        Integer numberOfResults = dao.countNameRelationships(name, direction, type);
594
595
        List<NameRelationship> results = new ArrayList<NameRelationship>();
596
        if (AbstractPagerImpl.hasResultsInRange(numberOfResults.longValue(), pageNumber, pageSize)) { // no point checking again
597
            results = dao.getNameRelationships(name, direction, type, pageSize,	pageNumber, orderHints, propertyPaths);
598
        }
599
        return results;
600
    }
601
602
603
    protected LuceneSearch prepareFindByFuzzyNameSearch(Class<? extends CdmBase> clazz,
604 d7919b1c Andreas Müller
            INonViralName nvn,
605 2622a38b Andreas Müller
            float accuracy,
606
            int maxNoOfResults,
607
            List<Language> languages,
608
            boolean highlightFragments) {
609
        String similarity = Float.toString(accuracy);
610
        String searchSuffix = "~" + similarity;
611
612
613 f6b282fc Andreas Kohlbecker
        Builder finalQueryBuilder = new Builder();
614
        finalQueryBuilder.setDisableCoord(false);
615
        Builder textQueryBuilder = new Builder();
616
        textQueryBuilder.setDisableCoord(false);
617 2622a38b Andreas Müller
618 9dc896c9 Andreas Müller
        LuceneSearch luceneSearch = new LuceneSearch(luceneIndexToolProvider, TaxonName.class);
619
        QueryFactory queryFactory = luceneIndexToolProvider.newQueryFactoryFor(TaxonName.class);
620 2622a38b Andreas Müller
621
//    	SortField[] sortFields = new  SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING,  false)};
622
//    	luceneSearch.setSortFields(sortFields);
623
624
        // ---- search criteria
625
        luceneSearch.setCdmTypRestriction(clazz);
626
627
        FuzzyLikeThisQuery fltq = new FuzzyLikeThisQuery(maxNoOfResults, luceneSearch.getAnalyzer());
628
        if(nvn.getGenusOrUninomial() != null && !nvn.getGenusOrUninomial().equals("")) {
629
            fltq.addTerms(nvn.getGenusOrUninomial().toLowerCase(), "genusOrUninomial", accuracy, 3);
630
        } else {
631
            //textQuery.add(new RegexQuery (new Term ("genusOrUninomial", "^[a-zA-Z]*")), Occur.MUST_NOT);
632 f6b282fc Andreas Kohlbecker
            textQueryBuilder.add(queryFactory.newTermQuery("genusOrUninomial", "_null_", false), Occur.MUST);
633 2622a38b Andreas Müller
        }
634
635
        if(nvn.getInfraGenericEpithet() != null && !nvn.getInfraGenericEpithet().equals("")){
636
            fltq.addTerms(nvn.getInfraGenericEpithet().toLowerCase(), "infraGenericEpithet", accuracy, 3);
637
        } else {
638
            //textQuery.add(new RegexQuery (new Term ("infraGenericEpithet", "^[a-zA-Z]*")), Occur.MUST_NOT);
639 f6b282fc Andreas Kohlbecker
            textQueryBuilder.add(queryFactory.newTermQuery("infraGenericEpithet", "_null_", false), Occur.MUST);
640 2622a38b Andreas Müller
        }
641
642
        if(nvn.getSpecificEpithet() != null && !nvn.getSpecificEpithet().equals("")){
643
            fltq.addTerms(nvn.getSpecificEpithet().toLowerCase(), "specificEpithet", accuracy, 3);
644
        } else {
645
            //textQuery.add(new RegexQuery (new Term ("specificEpithet", "^[a-zA-Z]*")), Occur.MUST_NOT);
646 f6b282fc Andreas Kohlbecker
            textQueryBuilder.add(queryFactory.newTermQuery("specificEpithet", "_null_", false), Occur.MUST);
647 2622a38b Andreas Müller
        }
648
649
        if(nvn.getInfraSpecificEpithet() != null && !nvn.getInfraSpecificEpithet().equals("")){
650
            fltq.addTerms(nvn.getInfraSpecificEpithet().toLowerCase(), "infraSpecificEpithet", accuracy, 3);
651
        } else {
652
            //textQuery.add(new RegexQuery (new Term ("infraSpecificEpithet", "^[a-zA-Z]*")), Occur.MUST_NOT);
653 f6b282fc Andreas Kohlbecker
            textQueryBuilder.add(queryFactory.newTermQuery("infraSpecificEpithet", "_null_", false), Occur.MUST);
654 2622a38b Andreas Müller
        }
655
656
        if(nvn.getAuthorshipCache() != null && !nvn.getAuthorshipCache().equals("")){
657
            fltq.addTerms(nvn.getAuthorshipCache().toLowerCase(), "authorshipCache", accuracy, 3);
658
        } else {
659
            //textQuery.add(new RegexQuery (new Term ("authorshipCache", "^[a-zA-Z]*")), Occur.MUST_NOT);
660
        }
661
662 f6b282fc Andreas Kohlbecker
        textQueryBuilder.add(fltq, Occur.MUST);
663 2622a38b Andreas Müller
664 f6b282fc Andreas Kohlbecker
        BooleanQuery textQuery = textQueryBuilder.build();
665
        finalQueryBuilder.add(textQuery, Occur.MUST);
666 2622a38b Andreas Müller
667 f6b282fc Andreas Kohlbecker
        luceneSearch.setQuery(finalQueryBuilder.build());
668 2622a38b Andreas Müller
669
        if(highlightFragments){
670
            luceneSearch.setHighlightFields(queryFactory.getTextFieldNamesAsArray());
671
        }
672
        return luceneSearch;
673
    }
674
675
    protected LuceneSearch prepareFindByFuzzyNameCacheSearch(Class<? extends CdmBase> clazz,
676
            String name,
677
            float accuracy,
678
            int maxNoOfResults,
679
            List<Language> languages,
680
            boolean highlightFragments) {
681
682 9dc896c9 Andreas Müller
        LuceneSearch luceneSearch = new LuceneSearch(luceneIndexToolProvider, TaxonName.class);
683
        QueryFactory queryFactory = luceneIndexToolProvider.newQueryFactoryFor(TaxonName.class);
684 2622a38b Andreas Müller
685
//    	SortField[] sortFields = new  SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING,  false)};
686
//    	luceneSearch.setSortFields(sortFields);
687
688
        // ---- search criteria
689
        luceneSearch.setCdmTypRestriction(clazz);
690
        FuzzyLikeThisQuery fltq = new FuzzyLikeThisQuery(maxNoOfResults, luceneSearch.getAnalyzer());
691
692
        fltq.addTerms(name, "nameCache", accuracy, 3);
693
694
         BooleanQuery finalQuery = new BooleanQuery(false);
695
696
         finalQuery.add(fltq, Occur.MUST);
697
698
        luceneSearch.setQuery(finalQuery);
699
700
        if(highlightFragments){
701
            luceneSearch.setHighlightFields(queryFactory.getTextFieldNamesAsArray());
702
        }
703
        return luceneSearch;
704
    }
705
706
    protected LuceneSearch prepareFindByExactNameSearch(Class<? extends CdmBase> clazz,
707
            String name,
708
            boolean wildcard,
709
            List<Language> languages,
710
            boolean highlightFragments) {
711 f6b282fc Andreas Kohlbecker
        Builder textQueryBuilder = new Builder();
712 2622a38b Andreas Müller
713 9dc896c9 Andreas Müller
        LuceneSearch luceneSearch = new LuceneSearch(luceneIndexToolProvider, TaxonName.class);
714
        QueryFactory queryFactory = luceneIndexToolProvider.newQueryFactoryFor(TaxonName.class);
715 2622a38b Andreas Müller
716
//    	SortField[] sortFields = new  SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING,  false)};
717
//    	luceneSearch.setSortFields(sortFields);
718
719
        // ---- search criteria
720
        luceneSearch.setCdmTypRestriction(clazz);
721
722
        if(name != null && !name.equals("")) {
723
            if(wildcard) {
724 f6b282fc Andreas Kohlbecker
                textQueryBuilder.add(new WildcardQuery(new Term("nameCache", name + "*")), Occur.MUST);
725 2622a38b Andreas Müller
            } else {
726 f6b282fc Andreas Kohlbecker
                textQueryBuilder.add(queryFactory.newTermQuery("nameCache", name, false), Occur.MUST);
727 2622a38b Andreas Müller
            }
728
        }
729
730 f6b282fc Andreas Kohlbecker
        luceneSearch.setQuery(textQueryBuilder.build());
731 2622a38b Andreas Müller
732
        if(highlightFragments){
733
            luceneSearch.setHighlightFields(queryFactory.getTextFieldNamesAsArray());
734
        }
735
        return luceneSearch;
736
    }
737
738
    @Override
739 9dc896c9 Andreas Müller
    public List<SearchResult<TaxonName>> findByNameFuzzySearch(
740 2622a38b Andreas Müller
            String name,
741
            float accuracy,
742
            List<Language> languages,
743
            boolean highlightFragments,
744
            List<String> propertyPaths,
745 3ca8a283 Patrick Plitzner
            int maxNoOfResults) throws IOException, LuceneParseException {
746 2622a38b Andreas Müller
747
        logger.info("Name to fuzzy search for : " + name);
748
        // parse the input name
749
        NonViralNameParserImpl parser = new NonViralNameParserImpl();
750 d7919b1c Andreas Müller
        INonViralName nvn = parser.parseFullName(name);
751 2622a38b Andreas Müller
        if(name != null && !name.equals("") && nvn == null) {
752 3ca8a283 Patrick Plitzner
            throw new LuceneParseException("Could not parse name " + name);
753 2622a38b Andreas Müller
        }
754
        LuceneSearch luceneSearch = prepareFindByFuzzyNameSearch(null, nvn, accuracy, maxNoOfResults, languages, highlightFragments);
755
756
        // --- execute search
757
        TopDocs topDocs = luceneSearch.executeSearch(maxNoOfResults);
758
759
760
        Map<CdmBaseType, String> idFieldMap = new HashMap<CdmBaseType, String>();
761
        idFieldMap.put(CdmBaseType.NONVIRALNAME, "id");
762
763
        // --- initialize taxa, highlight matches ....
764
        ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, luceneSearch.getQuery());
765
766
        @SuppressWarnings("rawtypes")
767 9dc896c9 Andreas Müller
        List<SearchResult<TaxonName>> searchResults = searchResultBuilder.createResultSet(
768 2622a38b Andreas Müller
                topDocs, luceneSearch.getHighlightFields(), dao, idFieldMap, propertyPaths);
769
770
        return searchResults;
771
772
    }
773
774
    @Override
775
    public List<DocumentSearchResult> findByNameFuzzySearch(
776
            String name,
777
            float accuracy,
778
            List<Language> languages,
779
            boolean highlightFragments,
780 3ca8a283 Patrick Plitzner
            int maxNoOfResults) throws IOException, LuceneParseException {
781 2622a38b Andreas Müller
782
        logger.info("Name to fuzzy search for : " + name);
783
        // parse the input name
784
        NonViralNameParserImpl parser = new NonViralNameParserImpl();
785 d7919b1c Andreas Müller
        INonViralName nvn = parser.parseFullName(name);
786 2622a38b Andreas Müller
        if(name != null && !name.equals("") && nvn == null) {
787 3ca8a283 Patrick Plitzner
            throw new LuceneParseException("Could not parse name " + name);
788 2622a38b Andreas Müller
        }
789
        LuceneSearch luceneSearch = prepareFindByFuzzyNameSearch(null, nvn, accuracy, maxNoOfResults, languages, highlightFragments);
790
791
        // --- execute search
792
        TopDocs topDocs = luceneSearch.executeSearch(maxNoOfResults);
793
794
        Map<CdmBaseType, String> idFieldMap = new HashMap<CdmBaseType, String>();
795
796
        // --- initialize taxa, highlight matches ....
797
        ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, luceneSearch.getQuery());
798
799
        @SuppressWarnings("rawtypes")
800
        List<DocumentSearchResult> searchResults = searchResultBuilder.createResultSet(topDocs, luceneSearch.getHighlightFields());
801
802
        return searchResults;
803
    }
804
805
    @Override
806
    public List<DocumentSearchResult> findByFuzzyNameCacheSearch(
807
            String name,
808
            float accuracy,
809
            List<Language> languages,
810
            boolean highlightFragments,
811 3ca8a283 Patrick Plitzner
            int maxNoOfResults) throws IOException, LuceneParseException {
812 2622a38b Andreas Müller
813
        logger.info("Name to fuzzy search for : " + name);
814
815
        LuceneSearch luceneSearch = prepareFindByFuzzyNameCacheSearch(null, name, accuracy, maxNoOfResults, languages, highlightFragments);
816
817
        // --- execute search
818
        TopDocs topDocs = luceneSearch.executeSearch(maxNoOfResults);
819
        Map<CdmBaseType, String> idFieldMap = new HashMap<CdmBaseType, String>();
820
821
        // --- initialize taxa, highlight matches ....
822
        ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, luceneSearch.getQuery());
823
824
        @SuppressWarnings("rawtypes")
825
        List<DocumentSearchResult> searchResults = searchResultBuilder.createResultSet(topDocs, luceneSearch.getHighlightFields());
826
827
        return searchResults;
828
    }
829
830
    @Override
831
    public List<DocumentSearchResult> findByNameExactSearch(
832
            String name,
833
            boolean wildcard,
834
            List<Language> languages,
835
            boolean highlightFragments,
836 3ca8a283 Patrick Plitzner
            int maxNoOfResults) throws IOException, LuceneParseException {
837 2622a38b Andreas Müller
838
        logger.info("Name to exact search for : " + name);
839
840
        LuceneSearch luceneSearch = prepareFindByExactNameSearch(null, name, wildcard, languages, highlightFragments);
841
842
        // --- execute search
843
844
845
        TopDocs topDocs = luceneSearch.executeSearch(maxNoOfResults);
846
847
        Map<CdmBaseType, String> idFieldMap = new HashMap<CdmBaseType, String>();
848
849
        // --- initialize taxa, highlight matches ....
850
        ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, luceneSearch.getQuery());
851
852
        @SuppressWarnings("rawtypes")
853
        List<DocumentSearchResult> searchResults = searchResultBuilder.createResultSet(topDocs, luceneSearch.getHighlightFields());
854
855
        return searchResults;
856
    }
857
858
    @Override
859 9dc896c9 Andreas Müller
    public Pager<NameRelationship> pageNameRelationships(TaxonName name, Direction direction, NameRelationshipType type, Integer pageSize,
860 2622a38b Andreas Müller
            Integer pageNumber, List<OrderHint> orderHints,	List<String> propertyPaths) {
861
        List<NameRelationship> results = listNameRelationships(name, direction, type, pageSize, pageNumber, orderHints, propertyPaths);
862
        return new DefaultPagerImpl<NameRelationship>(pageNumber, results.size(), pageSize, results);
863
    }
864
865
    @Override
866 9dc896c9 Andreas Müller
    public List<NameRelationship> listFromNameRelationships(TaxonName name, NameRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
867 2622a38b Andreas Müller
        return listNameRelationships(name, Direction.relatedFrom, type, pageSize, pageNumber, orderHints, propertyPaths);
868
    }
869
870
    @Override
871 9dc896c9 Andreas Müller
    public Pager<NameRelationship> pageFromNameRelationships(TaxonName name, NameRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
872 2622a38b Andreas Müller
        List<NameRelationship> results = listNameRelationships(name, Direction.relatedFrom, type, pageSize, pageNumber, orderHints, propertyPaths);
873
        return new DefaultPagerImpl<NameRelationship>(pageNumber, results.size(), pageSize, results);
874
    }
875
876
    @Override
877 9dc896c9 Andreas Müller
    public List<NameRelationship> listToNameRelationships(TaxonName name, NameRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
878 2622a38b Andreas Müller
        return listNameRelationships(name, Direction.relatedTo, type, pageSize, pageNumber, orderHints, propertyPaths);
879
    }
880
881
    @Override
882 9dc896c9 Andreas Müller
    public Pager<NameRelationship> pageToNameRelationships(TaxonName name, NameRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
883 2622a38b Andreas Müller
        List<NameRelationship> results = listNameRelationships(name, Direction.relatedTo, type, pageSize, pageNumber, orderHints, propertyPaths);
884
        return new DefaultPagerImpl<NameRelationship>(pageNumber, results.size(), pageSize, results);
885
    }
886
887
    @Override
888 9dc896c9 Andreas Müller
    public Pager<TypeDesignationBase> getTypeDesignations(TaxonName name, SpecimenTypeDesignationStatus status,
889 2622a38b Andreas Müller
            Integer pageSize, Integer pageNumber) {
890
        return getTypeDesignations(name, status, pageSize, pageNumber, null);
891
    }
892
893
    @Override
894 9dc896c9 Andreas Müller
    public Pager<TypeDesignationBase> getTypeDesignations(TaxonName name, SpecimenTypeDesignationStatus status,
895 2622a38b Andreas Müller
                Integer pageSize, Integer pageNumber, List<String> propertyPaths){
896 ea33ac4f Andreas Müller
        long numberOfResults = dao.countTypeDesignations(name, status);
897 2622a38b Andreas Müller
898 ea33ac4f Andreas Müller
        List<TypeDesignationBase> results = new ArrayList<>();
899
        if(AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)) {
900 2622a38b Andreas Müller
            results = dao.getTypeDesignations(name, null, status, pageSize, pageNumber, propertyPaths);
901
        }
902 ea33ac4f Andreas Müller
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
903 2622a38b Andreas Müller
    }
904
905 aa8cf7e6 Andreas Kohlbecker
    @Override
906
    public List<TypeDesignationBase> getTypeDesignationsInHomotypicalGroup(UUID nameUuid, Integer pageSize,
907
            Integer pageNumber, List<String> propertyPaths){
908 eae56a30 Andreas Müller
        TaxonName name = load(nameUuid, Arrays.asList("nomenclaturalSource.citation.authorship"));
909 aa8cf7e6 Andreas Kohlbecker
        Set<TypeDesignationBase<?>> typeDesignations = name.getHomotypicalGroup().getTypeDesignations();
910
        List<TypeDesignationBase> result = defaultBeanInitializer.initializeAll(new ArrayList(typeDesignations), propertyPaths);
911
        return result;
912
    }
913
914 2622a38b Andreas Müller
    /**
915
     * FIXME Candidate for harmonization
916
     * rename search
917
     */
918
    @Override
919 9dc896c9 Andreas Müller
    public Pager<TaxonName> searchNames(String uninomial,String infraGenericEpithet, String specificEpithet, String infraspecificEpithet, Rank rank, Integer pageSize,	Integer pageNumber, List<OrderHint> orderHints,
920 2622a38b Andreas Müller
            List<String> propertyPaths) {
921 9a21de1f Andreas Müller
        long numberOfResults = dao.countNames(uninomial, infraGenericEpithet, specificEpithet, infraspecificEpithet, rank);
922 2622a38b Andreas Müller
923 9a21de1f Andreas Müller
        List<TaxonName> results = new ArrayList<>();
924 2622a38b Andreas Müller
        if(numberOfResults > 0) { // no point checking again  //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
925
            results = dao.searchNames(uninomial, infraGenericEpithet, specificEpithet, infraspecificEpithet, rank, pageSize, pageNumber, orderHints, propertyPaths);
926
        }
927
928 9a21de1f Andreas Müller
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
929 2622a38b Andreas Müller
    }
930
931
    @Override
932 c51ef083 Katja Luther
    public List<UuidAndTitleCache> getUuidAndTitleCacheOfNames(Integer limit, String pattern) {
933
        return dao.getUuidAndTitleCacheOfNames(limit, pattern);
934 2622a38b Andreas Müller
    }
935
936
    @Override
937 e11ed28f Andreas Müller
    public Pager<TaxonName> findByName(Class<TaxonName> clazz, String queryString, MatchMode matchmode, List<Criterion> criteria,
938
            Integer pageSize,Integer pageNumber, List<OrderHint> orderHints,List<String> propertyPaths) {
939 05c87b75 Andreas Müller
         Long numberOfResults = dao.countByName(clazz, queryString, matchmode, criteria);
940 2622a38b Andreas Müller
941 9dc896c9 Andreas Müller
         List<TaxonName> results = new ArrayList<>();
942 2622a38b Andreas Müller
         if(numberOfResults > 0) { // no point checking again  //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
943
                results = dao.findByName(clazz, queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths);
944
         }
945
946 05c87b75 Andreas Müller
         return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
947 2622a38b Andreas Müller
    }
948
949 1e97edc1 Katja Luther
    @Override
950
    public List<TaxonName> findByFullTitle(Class<TaxonName> clazz, String queryString, MatchMode matchmode, List<Criterion> criteria,
951
            Integer pageSize,Integer pageNumber, List<OrderHint> orderHints,List<String> propertyPaths) {
952
         Long numberOfResults = dao.countByFullTitle(clazz, queryString, matchmode, criteria);
953
954
         List<TaxonName> results = new ArrayList<>();
955
         if(numberOfResults > 0) { // no point checking again  //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
956
                results = dao.findByFullTitle(queryString, matchmode, pageSize, pageNumber, criteria, propertyPaths);
957
         }
958
959
         return results;
960
    }
961
962
963 2622a38b Andreas Müller
    @Override
964
    public HomotypicalGroup findHomotypicalGroup(UUID uuid) {
965
        return homotypicalGroupDao.findByUuid(uuid);
966
    }
967
968
    @Override
969
    @Transactional(readOnly = false)
970 95371079 Katja Luther
    public UpdateResult updateCaches(Class<? extends TaxonName> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<TaxonName> cacheStrategy, IProgressMonitor monitor) {
971 2622a38b Andreas Müller
        if (clazz == null){
972 9dc896c9 Andreas Müller
            clazz = TaxonName.class;
973 2622a38b Andreas Müller
        }
974 95371079 Katja Luther
        return super.updateCachesImpl(clazz, stepSize, cacheStrategy, monitor);
975 2622a38b Andreas Müller
    }
976
977
978
    @Override
979
    public List<TaggedText> getTaggedName(UUID uuid) {
980 9dc896c9 Andreas Müller
        TaxonName taxonName = dao.load(uuid);
981
        List<TaggedText> taggedName = taxonName.getTaggedName();
982 2622a38b Andreas Müller
        return taggedName;
983
    }
984
985
986 1f088ad4 Andreas Müller
    public DeleteResult isDeletable(TaxonName name, DeleteConfiguratorBase config){
987 a80ca382 Katja Luther
        DeleteResult result = new DeleteResult();
988
989
        NameDeletionConfigurator nameConfig = null;
990
        if (config instanceof NameDeletionConfigurator){
991
            nameConfig = (NameDeletionConfigurator) config;
992
        }else{
993
             result.addException(new Exception("The delete configurator should be of the type NameDeletionConfigurator."));
994
             result.setError();
995
             return result;
996
        }
997
998
        if (!name.getNameRelations().isEmpty() && !nameConfig.isRemoveAllNameRelationships()){
999
            HomotypicalGroup homotypicalGroup = HibernateProxyHelper.deproxy(name.getHomotypicalGroup(), HomotypicalGroup.class);
1000 2622a38b Andreas Müller
1001 a80ca382 Katja Luther
            if (!nameConfig.isIgnoreIsBasionymFor() && homotypicalGroup.getBasionyms().contains(name)){
1002
                result.addException(new Exception( "Name can't be deleted as it is a basionym."));
1003
                result.setAbort();
1004 2622a38b Andreas Müller
            }
1005
            if (!nameConfig.isIgnoreHasBasionym() && (name.getBasionyms().size()>0)){
1006 a80ca382 Katja Luther
                result.addException(new Exception( "Name can't be deleted as it has a basionym."));
1007
                result.setAbort();
1008 2622a38b Andreas Müller
            }
1009
            Set<NameRelationship> relationships = name.getNameRelations();
1010
            for (NameRelationship rel: relationships){
1011 a80ca382 Katja Luther
                if (!rel.getType().equals(NameRelationshipType.BASIONYM())){
1012
                    result.addException(new Exception("Name can't be deleted as it is used in name relationship(s). Remove name relationships prior to deletion."));
1013
                    result.setAbort();
1014
                    break;
1015
                }
1016 2622a38b Andreas Müller
            }
1017
        }
1018
1019
        //concepts
1020
        if (! name.getTaxonBases().isEmpty()){
1021 a80ca382 Katja Luther
            result.addException(new Exception("Name can't be deleted as it is used in concept(s). Remove or change concept prior to deletion."));
1022
            result.setAbort();
1023 2622a38b Andreas Müller
        }
1024
1025
        //hybrid relationships
1026 e6d7b501 Andreas Müller
        if (name.isNonViral()){
1027 396a8759 Andreas Müller
            INonViralName nvn = name;
1028 645658b9 Katja Luther
            Set<HybridRelationship> parentHybridRelations = nvn.getHybridParentRelations();
1029
            //Hibernate.initialize(parentHybridRelations);
1030
            if (! parentHybridRelations.isEmpty()){
1031 a80ca382 Katja Luther
                result.addException(new Exception("Name can't be deleted as it is a parent in (a) hybrid relationship(s). Remove hybrid relationships prior to deletion."));
1032
                result.setAbort();
1033 2622a38b Andreas Müller
            }
1034
        }
1035 a80ca382 Katja Luther
        Set<CdmBase> referencingObjects = genericDao.getReferencingObjectsForDeletion(name);
1036 2622a38b Andreas Müller
        for (CdmBase referencingObject : referencingObjects){
1037
            //DerivedUnit?.storedUnder
1038
            if (referencingObject.isInstanceOf(DerivedUnit.class)){
1039
                String message = "Name can't be deleted as it is used as derivedUnit#storedUnder by %s. Remove 'stored under' prior to deleting this name";
1040
                message = String.format(message, CdmBase.deproxy(referencingObject, DerivedUnit.class).getTitleCache());
1041
                result.addException(new ReferencedObjectUndeletableException(message));
1042
                result.addRelatedObject(referencingObject);
1043
                result.setAbort();
1044
            }
1045
            //DescriptionElementSource#nameUsedInSource
1046
            else if (referencingObject.isInstanceOf(DescriptionElementSource.class)){
1047
                String message = "Name can't be deleted as it is used as descriptionElementSource#nameUsedInSource";
1048
                result.addException(new ReferencedObjectUndeletableException(message));
1049
                result.addRelatedObject(referencingObject);
1050
                result.setAbort();
1051
            }
1052
            //NameTypeDesignation#typeName
1053
            else if (referencingObject.isInstanceOf(NameTypeDesignation.class)){
1054 88b1995d Katja Luther
                NameTypeDesignation typeDesignation = HibernateProxyHelper.deproxy(referencingObject, NameTypeDesignation.class);
1055
1056 1e97edc1 Katja Luther
                if (typeDesignation.getTypeName().equals(name) && !typeDesignation.getTypifiedNames().isEmpty()){
1057 88b1995d Katja Luther
                    String message = "Name can't be deleted as it is used as a name type in a NameTypeDesignation";
1058
                    result.addException(new ReferencedObjectUndeletableException(message));
1059
                    result.addRelatedObject(referencingObject);
1060
                    result.setAbort();
1061
                }
1062 2622a38b Andreas Müller
            }
1063
            //DeterminationEvent#taxonName
1064
            else if (referencingObject.isInstanceOf(DeterminationEvent.class)){
1065
                String message = "Name can't be deleted as it is used as a determination event";
1066
                result.addException(new ReferencedObjectUndeletableException(message));
1067
                result.addRelatedObject(referencingObject);
1068
                result.setAbort();
1069
        }
1070
        }
1071
1072
        //TODO inline references
1073
1074
1075
        if (!nameConfig.isIgnoreIsReplacedSynonymFor() && name.isReplacedSynonym()){
1076
            String message = "Name can't be deleted as it is a replaced synonym.";
1077
            result.addException(new Exception(message));
1078
            result.setAbort();
1079
        }
1080
        if (!nameConfig.isIgnoreHasReplacedSynonym() && (name.getReplacedSynonyms().size()>0)){
1081
            String message = "Name can't be deleted as it has a replaced synonym.";
1082
            result.addException(new Exception(message));
1083
            result.setAbort();
1084
        }
1085 a80ca382 Katja Luther
        return result;
1086 2622a38b Andreas Müller
1087
    }
1088
1089 a80ca382 Katja Luther
1090
    @Override
1091
    public DeleteResult isDeletable(UUID nameUUID, DeleteConfiguratorBase config){
1092 1f088ad4 Andreas Müller
        TaxonName name = this.load(nameUUID);
1093 a80ca382 Katja Luther
        return isDeletable(name, config);
1094
    }
1095
1096 2622a38b Andreas Müller
    @Override
1097
    @Transactional(readOnly = true)
1098
    public UpdateResult setAsGroupsBasionym(UUID nameUuid) {
1099 9dc896c9 Andreas Müller
        TaxonName name = dao.load(nameUuid);
1100 2622a38b Andreas Müller
        UpdateResult result = new UpdateResult();
1101
        name.setAsGroupsBasionym();
1102
        result.addUpdatedObject(name);
1103
        return result;
1104
1105
    }
1106
1107
    @Override
1108
    public List<HashMap<String,String>> getNameRecords(){
1109
		return dao.getNameRecords();
1110
1111
    }
1112
1113 72312cbc Andreas Kohlbecker
    @Override
1114
    public List<TypeDesignationStatusBase> getTypeDesignationStatusInUse(){
1115
        return typeDesignationDao.getTypeDesignationStatusInUse();
1116
    }
1117
1118
    @Override
1119
    public Collection<TypeDesignationStatusFilter> getTypeDesignationStatusFilterTerms(List<Language> preferredLanguages){
1120
        List<TypeDesignationStatusBase> termList = typeDesignationDao.getTypeDesignationStatusInUse();
1121
        Map<String, TypeDesignationStatusFilter>  filterMap = new HashMap<>();
1122
        for(TypeDesignationStatusBase term : termList){
1123
            TypeDesignationStatusFilter filter = new TypeDesignationStatusFilter(term, preferredLanguages, true);
1124
            String key = filter.getKey();
1125
            if(filterMap.containsKey(key)){
1126
                filterMap.get(key).addStatus(term);
1127
            } else {
1128
                filterMap.put(key, filter);
1129
            }
1130
        }
1131
        return filterMap.values();
1132
    }
1133
1134 67c8f20e Andreas Kohlbecker
    @Override
1135
    public <S extends TaxonName> Pager<S> page(Class<S> clazz, List<Restriction<?>> restrictions, Integer pageSize,
1136
            Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths) {
1137
        return page(clazz, restrictions, pageSize, pageIndex, orderHints, propertyPaths, INCLUDE_UNPUBLISHED);
1138
    }
1139
1140
    @Override
1141
    public <S extends TaxonName> Pager<S> page(Class<S> clazz, List<Restriction<?>> restrictions, Integer pageSize,
1142
            Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths, boolean includeUnpublished) {
1143
1144
        List<S> records;
1145
        long resultSize = dao.count(clazz, restrictions);
1146
        if(AbstractPagerImpl.hasResultsInRange(resultSize, pageIndex, pageSize)){
1147
            records = dao.list(clazz, restrictions, pageSize, pageIndex, orderHints, propertyPaths, includeUnpublished);
1148
        } else {
1149
            records = new ArrayList<>();
1150
        }
1151
        Pager<S> pager = new DefaultPagerImpl<>(pageIndex, resultSize, pageSize, records);
1152
        return pager;
1153
    }
1154
1155 1e97edc1 Katja Luther
    @Override
1156
    public List<UuidAndTitleCache> getUuidAndTitleCacheOfSynonymy(Integer limit, UUID taxonUuid) {
1157 ba4b5517 Andreas Müller
        List<String> propertyPaths = new ArrayList<>();
1158 1e97edc1 Katja Luther
        propertyPaths.add("synonyms.name.*");
1159 ba4b5517 Andreas Müller
        TaxonBase<?> taxonBase = taxonService.load(taxonUuid, propertyPaths);
1160 1e97edc1 Katja Luther
        if (taxonBase instanceof Taxon){
1161
            Taxon taxon = (Taxon)taxonBase;
1162
            Set<TaxonName> names = taxon.getSynonymNames();
1163 ba4b5517 Andreas Müller
            List<UuidAndTitleCache> uuidAndTitleCacheList = new ArrayList<>();
1164 1e97edc1 Katja Luther
            UuidAndTitleCache<TaxonName> uuidAndTitleCache;
1165
            for (TaxonName name: names){
1166
                uuidAndTitleCache = new UuidAndTitleCache<TaxonName>(TaxonName.class, name.getUuid(), name.getId(), name.getTitleCache());
1167
                uuidAndTitleCacheList.add(uuidAndTitleCache);
1168
            }
1169
        }
1170
        return null;
1171
    }
1172
1173 72eb424b Andreas Müller
    @Override
1174 e26fd740 Andreas Müller
    public UpdateResult parseName(String stringToBeParsed, NomenclaturalCode code, Rank preferredRank, boolean doDeduplicate) {
1175 0020d108 Andreas Müller
        TaxonName name = TaxonNameFactory.NewNameInstance(code, preferredRank);
1176
        return parseName(name, stringToBeParsed, preferredRank, true, doDeduplicate);
1177
    }
1178
1179
    @Override
1180 aab00a6d Andreas Müller
    public UpdateResult parseName(TaxonName nameToBeFilled, String stringToBeParsed, Rank preferredRank,
1181
            boolean doEmpty, boolean doDeduplicate){
1182 e26fd740 Andreas Müller
        UpdateResult result = new UpdateResult();
1183 72eb424b Andreas Müller
        NonViralNameParserImpl nonViralNameParser = NonViralNameParserImpl.NewInstance();
1184 0020d108 Andreas Müller
        nonViralNameParser.parseReferencedName(nameToBeFilled, stringToBeParsed, preferredRank, doEmpty);
1185
        TaxonName name = nameToBeFilled;
1186 72eb424b Andreas Müller
        if(doDeduplicate) {
1187
            try {
1188 8ce66ade Andreas Müller
//                Level sqlLogLevel = Logger.getLogger("org.hibernate.SQL").getLevel();
1189
//                Logger.getLogger("org.hibernate.SQL").setLevel(Level.TRACE);
1190 a9bd2165 Andreas Müller
1191 72eb424b Andreas Müller
                //references
1192 0020d108 Andreas Müller
                if (name.getNomenclaturalReference()!= null && !name.getNomenclaturalReference().isPersited()){
1193 72eb424b Andreas Müller
                    Reference nomRef = name.getNomenclaturalReference();
1194 c078cfb8 Andreas Müller
                    IMatchStrategy referenceMatcher = MatchStrategyFactory.NewParsedReferenceInstance(nomRef);
1195 72eb424b Andreas Müller
                    List<Reference> matchingReferences = commonService.findMatching(nomRef, referenceMatcher);
1196
                    if(matchingReferences.size() >= 1){
1197
                        Reference duplicate = findBestMatching(nomRef, matchingReferences, referenceMatcher);
1198
                        name.setNomenclaturalReference(duplicate);
1199 aab00a6d Andreas Müller
                    }else{
1200
                        if (nomRef.getInReference() != null){
1201
                            List<Reference> matchingInReferences = commonService.findMatching(nomRef.getInReference(), MatchStrategyFactory.NewParsedReferenceInstance(nomRef.getInReference()));
1202
                            if(matchingInReferences.size() >= 1){
1203
                                Reference duplicate = findBestMatching(nomRef, matchingInReferences, referenceMatcher);
1204
                                nomRef.setInReference(duplicate);
1205
                            }
1206 72eb424b Andreas Müller
                        }
1207 aab00a6d Andreas Müller
                        TeamOrPersonBase<?> author = deduplicateAuthor(nomRef.getAuthorship());
1208 a9bd2165 Andreas Müller
                        nomRef.setAuthorship(author);
1209 72eb424b Andreas Müller
                    }
1210
                }
1211 a9bd2165 Andreas Müller
                Reference nomRef = name.getNomenclaturalReference();
1212 72eb424b Andreas Müller
                //authors
1213
                IParsedMatchStrategy authorMatcher = MatchStrategyFactory.NewParsedTeamOrPersonInstance();
1214 0020d108 Andreas Müller
                if (name.getCombinationAuthorship()!= null && !name.getCombinationAuthorship().isPersited()){
1215 a9bd2165 Andreas Müller
                    //use same nom.ref. author if possible (should always be possible if nom.ref. exists)
1216
                    if (nomRef != null && nomRef.getAuthorship() != null){
1217
                        if(authorMatcher.invoke(name.getCombinationAuthorship(), nomRef.getAuthorship()).isSuccessful()){
1218
                            name.setCombinationAuthorship(nomRef.getAuthorship());
1219
                        }
1220 72eb424b Andreas Müller
                    }
1221 a9bd2165 Andreas Müller
                    name.setCombinationAuthorship(deduplicateAuthor(name.getCombinationAuthorship()));
1222 72eb424b Andreas Müller
                }
1223 0020d108 Andreas Müller
                if (name.getExCombinationAuthorship()!= null && !name.getExCombinationAuthorship().isPersited()){
1224 a9bd2165 Andreas Müller
                    name.setExCombinationAuthorship(deduplicateAuthor(name.getExCombinationAuthorship()));
1225 72eb424b Andreas Müller
                }
1226 0020d108 Andreas Müller
                if (name.getBasionymAuthorship()!= null && !name.getBasionymAuthorship().isPersited()){
1227 a9bd2165 Andreas Müller
                    name.setBasionymAuthorship(deduplicateAuthor(name.getBasionymAuthorship()));
1228 72eb424b Andreas Müller
                }
1229 0020d108 Andreas Müller
                if (name.getExBasionymAuthorship()!= null && !name.getExBasionymAuthorship().isPersited()){
1230 a9bd2165 Andreas Müller
                    name.setExBasionymAuthorship(deduplicateAuthor(name.getExBasionymAuthorship()));
1231 72eb424b Andreas Müller
                }
1232 a9bd2165 Andreas Müller
//              Logger.getLogger("org.hibernate.SQL").setLevel(sqlLogLevel);
1233 72eb424b Andreas Müller
            } catch (MatchException e) {
1234
                throw new RuntimeException(e);
1235
            }
1236
        }
1237 e26fd740 Andreas Müller
        result.setCdmEntity(name);
1238
        return result;
1239 72eb424b Andreas Müller
    }
1240 67c8f20e Andreas Kohlbecker
1241 a9bd2165 Andreas Müller
    private TeamOrPersonBase<?> deduplicateAuthor(TeamOrPersonBase<?> authorship) throws MatchException {
1242
        if (authorship == null){
1243
            return null;
1244
        }
1245
        IParsedMatchStrategy authorMatcher = MatchStrategyFactory.NewParsedTeamOrPersonInstance();
1246
        List<TeamOrPersonBase<?>> matchingAuthors = commonService.findMatching(authorship, authorMatcher);
1247
        if(matchingAuthors.size() >= 1){
1248
            TeamOrPersonBase<?> duplicate = findBestMatching(authorship, matchingAuthors, authorMatcher);
1249
            return duplicate;
1250
        }else{
1251
            if (authorship instanceof Team){
1252
                deduplicateTeam((Team)authorship);
1253
            }
1254
            return authorship;
1255
        }
1256
    }
1257
1258
    private void deduplicateTeam(Team team) throws MatchException {
1259
        List<Person> members = team.getTeamMembers();
1260
        IParsedMatchStrategy personMatcher = MatchStrategyFactory.NewParsedPersonInstance();
1261
        for (int i =0; i< members.size(); i++){
1262
            Person person = CdmBase.deproxy(members.get(i));
1263
            List<Person> matchingPersons = commonService.findMatching(person, personMatcher);
1264
            if (matchingPersons.size() > 0){
1265
                person = findBestMatching(person, matchingPersons, personMatcher);
1266
                members.set(i, person);
1267
            }
1268
        }
1269
    }
1270 8ce66ade Andreas Müller
1271 72eb424b Andreas Müller
    private <M extends IMatchable> M findBestMatching(M matchable, List<M> matchingList,
1272 c078cfb8 Andreas Müller
            IMatchStrategy referenceMatcher) {
1273 72eb424b Andreas Müller
        // FIXME TODO resolve multiple duplications. Use first match for a start
1274 a9bd2165 Andreas Müller
        if(matchingList.isEmpty()){
1275
            return null;
1276
        }
1277 72eb424b Andreas Müller
        M bestMatching = matchingList.iterator().next();
1278
        return bestMatching;
1279
    }
1280 72312cbc Andreas Kohlbecker
1281 b36706c7 Andreas Müller
}