Project

General

Profile

Download (23.5 KB) Statistics
| Branch: | Revision:
1
/**
2
* Copyright (C) 2009 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
package eu.etaxonomy.cdm.io.pesi.out;
10

    
11
import java.util.ArrayList;
12
import java.util.EnumSet;
13
import java.util.HashSet;
14
import java.util.Iterator;
15
import java.util.List;
16
import java.util.Set;
17
import java.util.UUID;
18

    
19
import org.apache.log4j.Logger;
20

    
21
import eu.etaxonomy.cdm.api.service.pager.Pager;
22
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
23
import eu.etaxonomy.cdm.io.common.DbExportBase;
24
import eu.etaxonomy.cdm.io.common.mapping.out.DbLastActionMapper;
25
import eu.etaxonomy.cdm.io.pesi.erms.ErmsTransformer;
26
import eu.etaxonomy.cdm.model.common.AnnotationType;
27
import eu.etaxonomy.cdm.model.common.CdmBase;
28
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
29
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
30
import eu.etaxonomy.cdm.model.common.Marker;
31
import eu.etaxonomy.cdm.model.common.MarkerType;
32
import eu.etaxonomy.cdm.model.common.RelationshipBase;
33
import eu.etaxonomy.cdm.model.description.Feature;
34
import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
35
import eu.etaxonomy.cdm.model.description.TextData;
36
import eu.etaxonomy.cdm.model.name.HybridRelationship;
37
import eu.etaxonomy.cdm.model.name.INonViralName;
38
import eu.etaxonomy.cdm.model.name.NameRelationship;
39
import eu.etaxonomy.cdm.model.name.NameRelationshipType;
40
import eu.etaxonomy.cdm.model.name.TaxonName;
41
import eu.etaxonomy.cdm.model.reference.Reference;
42
import eu.etaxonomy.cdm.model.taxon.Synonym;
43
import eu.etaxonomy.cdm.model.taxon.Taxon;
44
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
45
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
46
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
47
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
48
import eu.etaxonomy.cdm.persistence.query.OrderHint;
49
import eu.etaxonomy.cdm.strategy.cache.name.TaxonNameDefaultCacheStrategy;
50
import eu.etaxonomy.cdm.strategy.cache.name.ZooNameNoMarkerCacheStrategy;
51

    
52
/**
53
 * @author e.-m.lee
54
 * @since 12.02.2010
55
 */
56
public abstract class PesiExportBase
57
              extends DbExportBase<PesiExportConfigurator, PesiExportState, PesiTransformer> {
58

    
59
    private static final long serialVersionUID = 6226747017958138156L;
60
    private static final Logger logger = Logger.getLogger(PesiExportBase.class);
61

    
62
	protected static final boolean IS_CACHE = true;
63

    
64
	private static Set<NameRelationshipType> excludedRelTypes = new HashSet<>();
65

    
66
	private static TaxonNameDefaultCacheStrategy zooNameStrategy = ZooNameNoMarkerCacheStrategy.NewInstance();
67
	private static TaxonNameDefaultCacheStrategy botanicalNameStrategy = TaxonNameDefaultCacheStrategy.NewInstance();
68

    
69
	public PesiExportBase() {
70
		super();
71
	}
72

    
73
	protected <CLASS extends TaxonBase> List<CLASS> getNextTaxonPartition(Class<CLASS> clazz, int limit,
74
	        int partitionCount, List<String> propertyPath) {
75

    
76
	    List<OrderHint> orderHints = new ArrayList<>();
77
		orderHints.add(new OrderHint("id", OrderHint.SortOrder.ASCENDING ));
78

    
79
		List<CLASS> list = getTaxonService().list(clazz, limit, partitionCount * limit, orderHints, propertyPath);
80

    
81
		if (list.isEmpty()){
82
			return null;
83
		}
84

    
85
		Iterator<CLASS> it = list.iterator();
86
		while (it.hasNext()){
87
			TaxonBase<?> taxonBase = it.next();
88
			if (! isPesiTaxon(taxonBase)){
89
				it.remove();
90
			}
91
			taxonBase = null;
92
		}
93
		it = null;
94
		return list;
95
	}
96

    
97
	protected List<TaxonNameDescription> getNextNameDescriptionPartition(int limit, int partitionCount, List<String> propertyPath) {
98
		List<OrderHint> orderHints = new ArrayList<>();
99
		orderHints.add(new OrderHint("id", OrderHint.SortOrder.ASCENDING ));
100
		Pager<TaxonNameDescription> l = getDescriptionService().getTaxonNameDescriptions(null, limit, partitionCount, propertyPath);
101
		List<TaxonNameDescription> list = l.getRecords();
102
		if (list.isEmpty()){
103
			return null;
104
		}
105

    
106
		Iterator<TaxonNameDescription> it = list.iterator();
107
		while (it.hasNext()){
108
			TaxonNameDescription nameDescription = it.next();
109
			if (! isPesiNameDescriptionTaxon(nameDescription)){
110
				it.remove();
111
			}
112
		}
113
		return list;
114
	}
115

    
116
	private boolean isPesiNameDescriptionTaxon(TaxonNameDescription nameDescription) {
117
		TaxonName name = nameDescription.getTaxonName();
118
		if (isPurePesiName(name)){
119
			return true;
120
		}else{
121
			Set<TaxonBase> taxa = name.getTaxonBases();
122
			for (TaxonBase<?> taxonBase : taxa){
123
				if (isPesiTaxon(taxonBase)){
124
					return true;
125
				}
126
			}
127
		}
128
		return false;
129
	}
130

    
131
	/**
132
	 * Returns the next list of pure names. If finished result will be null. If list is empty there may be result in further partitions.
133
	 */
134
	protected List<TaxonName> getNextPureNamePartition(Class<TaxonName> clazz,int limit, int partitionCount) {
135
		List<OrderHint> orderHints = new ArrayList<>();
136
		orderHints.add(new OrderHint("id", OrderHint.SortOrder.ASCENDING ));
137
//		List<String> propPath = Arrays.asList(new String[]{"taxonBases"});
138

    
139
		List<TaxonName> list = getNameService().list(clazz, limit, partitionCount * limit, orderHints, null);
140
		if (list.isEmpty()){
141
			return null;
142
		}
143
		Iterator<TaxonName> it = list.iterator();
144
		while (it.hasNext()){
145
		    TaxonName taxonName = HibernateProxyHelper.deproxy(it.next());
146
			if (! isPurePesiName(taxonName)){
147
				it.remove();
148
			}
149
		}
150
		return list;
151
	}
152

    
153
	protected <CLASS extends RelationshipBase> List<CLASS> getNextNameRelationshipPartition(
154
	                Class<CLASS> clazz, int pageSize, int partitionCount, List<String> propertyPaths) {
155

    
156
	    List<CLASS> result = new ArrayList<>();
157
		List<OrderHint> orderHints = null;
158
		List<CLASS> list;
159
		if (NameRelationship.class.isAssignableFrom(clazz)){
160
            list = (List<CLASS>)getNameService().listNameRelationships(null, pageSize, partitionCount, orderHints, propertyPaths);
161
        }else if (HybridRelationship.class.isAssignableFrom(clazz)){
162
            list = (List<CLASS>)getNameService().listHybridRelationships(null, pageSize, partitionCount, orderHints, propertyPaths);
163
        }else{
164
            throw new RuntimeException("Only NameRelationship or HybridRelationship allowed here");
165
        }
166
		if (list.isEmpty()){
167
			return null;
168
		}
169
		for (CLASS rel : list){
170
			if (isPesiNameRelationship(rel)){
171
				result.add(rel);
172
			}
173
		}
174
		return result;
175
	}
176

    
177
	protected <CLASS extends RelationshipBase> List<CLASS> getNextTaxonRelationshipPartition( int limit, int partitionCount, List<String> propertyPaths) {
178

    
179
	    List<CLASS> result = new ArrayList<>();
180

    
181
	    List<OrderHint> orderHints = null;
182
		@SuppressWarnings("unchecked")
183
        List<CLASS> list = (List<CLASS>)this.getTaxonService()
184
		        .listTaxonRelationships(null, limit, partitionCount, orderHints, propertyPaths);
185

    
186
		if (list.isEmpty()){
187
			return null;
188
		}
189

    
190
		for (CLASS rel : list){
191
			if (isPesiTaxonOrSynonymRelationship(rel)){
192
				result.add(rel);
193
			}
194
		}
195
		return result;
196
	}
197

    
198
    protected List<TaxonNode> getNextTaxonNodePartition( int limit, int partitionCount, List<String> propertyPaths) {
199

    
200
        List<TaxonNode> result = new ArrayList<>();
201

    
202
        List<OrderHint> orderHints = null;
203
        List<TaxonNode> list = this.getTaxonNodeService()
204
            .list(TaxonNode.class, limit, limit * partitionCount, orderHints, propertyPaths);
205

    
206
        if (list.isEmpty()){
207
            return null;
208
        }
209

    
210
        for (TaxonNode tn : list){
211
            if (isPesiTaxonNode(tn)){
212
                result.add(tn);
213
            }
214
        }
215
        return result;
216
    }
217

    
218
    protected boolean isPesiTaxonNode(TaxonNode tn){
219
        TaxonBase<?> fromTaxon;
220
        Taxon toTaxon;
221

    
222
        fromTaxon = tn.getTaxon();
223
        toTaxon = tn.getParent()== null? null: tn.getParent().getTaxon();
224

    
225
        return (isPesiTaxon(fromTaxon, true) && isPesiTaxon(toTaxon, true));
226
    }
227

    
228
	protected boolean isPesiNameRelationship(RelationshipBase<?,?,?> rel){
229
		TaxonName name1;
230
		TaxonName name2;
231
		if (rel.isInstanceOf(HybridRelationship.class)){
232
			HybridRelationship hybridRel = CdmBase.deproxy(rel, HybridRelationship.class);
233
			name1 = hybridRel.getParentName();
234
			name2 = hybridRel.getHybridName();
235
		}else if (rel.isInstanceOf(NameRelationship.class)){
236
			NameRelationship nameRel = CdmBase.deproxy(rel, NameRelationship.class);
237
			name1 = nameRel.getFromName();
238
			name2 = nameRel.getToName();
239
		}else{
240
			logger.warn ("Only hybrid- and name-relationships alowed here");
241
			return false;
242
		}
243
		return (isPesiName(name1) && isPesiName(name2));
244
	}
245

    
246
	private boolean isPesiName(TaxonName name) {
247
		return hasPesiTaxon(name) || isPurePesiName(name);
248
	}
249

    
250
	protected boolean isPesiTaxonOrSynonymRelationship(RelationshipBase rel){
251
		TaxonBase<?> fromTaxon;
252
		Taxon toTaxon;
253
		// TODO:fix!!!
254
//		if (rel.isInstanceOf(SynonymRelationship.class)){
255
//			SynonymRelationship synRel = CdmBase.deproxy(rel, SynonymRelationship.class);
256
//			fromTaxon = synRel.getSynonym();
257
//			toTaxon = synRel.getAcceptedTaxon();
258
//			synRel = null;
259
//		}else
260
		if (rel.isInstanceOf(TaxonRelationship.class)){
261
			TaxonRelationship taxRel = CdmBase.deproxy(rel, TaxonRelationship.class);
262
			fromTaxon = taxRel.getFromTaxon();
263
			toTaxon = taxRel.getToTaxon();
264
			taxRel = null;
265
		}else{
266
			logger.warn ("Only synonym - and taxon-relationships allowed here");
267
			return false;
268
		}
269
		return (isPesiTaxon(fromTaxon, false) && isPesiTaxon(toTaxon, true));
270
	}
271

    
272
	/**
273
	 * Decides if a name is not used as the name part of a PESI taxon (and therefore is
274
	 * exported to PESI as taxon already) but is related to a name used as a PESI taxon
275
	 * (e.g. as basionym, orthographic variant, etc.) and therefore should be exported
276
	 * to PESI as part of the name relationship.
277
	 * @param taxonName
278
	 * @return
279
	 */
280
	protected boolean isPurePesiName(TaxonName taxonName){
281
		if (hasPesiTaxon(taxonName)){
282
			return false;
283
		}
284

    
285
		//from names
286
		for (NameRelationship rel :taxonName.getRelationsFromThisName()){
287
			TaxonName relatedName = rel.getToName();
288
			if (hasPesiTaxon(relatedName)){
289
				return true;
290
			}
291
		}
292

    
293
		//excluded relationships on to-side
294
		initExcludedRelTypes();
295

    
296
		//to names
297
		for (NameRelationship rel :taxonName.getRelationsToThisName()){
298
			//exclude certain types
299
			if (excludedRelTypes.contains(rel.getType())){
300
				continue;
301
			}
302
			TaxonName relatedName = rel.getFromName();
303
			if (hasPesiTaxon(relatedName)){
304
				return true;
305
			}
306
		}
307

    
308
		//include hybrid parents, but no childs
309

    
310
		for (HybridRelationship rel : taxonName.getHybridParentRelations()){
311
			INonViralName child = rel.getHybridName();
312
			if (hasPesiTaxon(child)){
313
				return true;
314
			}
315
		}
316

    
317
		return false;
318
	}
319

    
320

    
321
	private void initExcludedRelTypes() {
322
		if (excludedRelTypes.isEmpty()){
323
			excludedRelTypes.add(NameRelationshipType.BASIONYM());
324
			excludedRelTypes.add(NameRelationshipType.REPLACED_SYNONYM());
325
			excludedRelTypes.add(NameRelationshipType.ORTHOGRAPHIC_VARIANT());
326
		}
327
	}
328

    
329

    
330
	/**
331
	 * Decides if a given name has "PESI taxa" attached.
332
	 *
333
	 * @see #getPesiTaxa(TaxonNameBase)
334
	 * @see #isPesiTaxon(TaxonBase)
335
	 * @param taxonName
336
	 * @return
337
	 */
338
	protected boolean hasPesiTaxon(INonViralName taxonName) {
339
		for (TaxonBase<?> taxon : taxonName.getTaxonBases()){
340
			if (isPesiTaxon(taxon)){
341
				return true;
342
			}
343
		}
344
		return false;
345
	}
346

    
347
	/**
348
	 * Returns those concepts (taxon bases) for the given name that
349
	 * are pesi taxa.
350
	 *
351
	 *  @see #isPesiTaxon(TaxonBase)
352
	 * @param name
353
	 * @return
354
	 */
355
	protected Set<TaxonBase<?>> getPesiTaxa(TaxonName name){
356
		Set<TaxonBase<?>> result = new HashSet<>();
357
		for (TaxonBase<?> taxonBase : name.getTaxonBases()){
358
			if (isPesiTaxon(taxonBase)){
359
				result.add(taxonBase);
360
			}
361
		}
362
		return result;
363
	}
364

    
365
	/**
366
	 * @see #isPesiTaxon(TaxonBase, boolean)
367
	 * @return
368
	 */
369
	protected static boolean isPesiTaxon(TaxonBase taxonBase) {
370
		return isPesiTaxon(taxonBase, false);
371
	}
372

    
373
	/**
374
	 * Checks if this taxon base is a taxon that is to be exported to PESI. This is generally the case
375
	 * but not for taxa that are marked as "unpublish". Synonyms and misapplied names are exported if they are
376
	 * related at least to one accepted taxon that is also exported, except for those misapplied names
377
	 * marked as misapplied names created by Euro+Med common names ({@linkplain http://dev.e-taxonomy.eu/trac/ticket/2786} ).
378
	 * The list of conditions may change in future.
379
	 * @param taxonBase
380
	 * @return
381
	 */
382
	protected static boolean isPesiTaxon(TaxonBase<?> taxonBase, boolean excludeMisappliedNames) {
383
		if (taxonBase == null){
384
		    return false;
385
		}
386
	    //handle accepted taxa
387
		if (taxonBase.isInstanceOf(Taxon.class)){
388
			Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);
389
			return isPesiAcceptedTaxon(excludeMisappliedNames, taxon);
390
		//handle synonyms
391
		}else if (taxonBase.isInstanceOf(Synonym.class)){
392
			Synonym synonym = CdmBase.deproxy(taxonBase, Synonym.class);
393
			return isPesiSynonym(synonym);
394
		}else {
395
			throw new RuntimeException("Unknown taxon base type: " + taxonBase.getClass());
396
		}
397
	}
398

    
399
    private static boolean isPesiSynonym(Synonym synonym) {
400
        boolean hasAcceptedPesiTaxon = false;
401

    
402
        hasAcceptedPesiTaxon = isPesiTaxon(synonym.getAcceptedTaxon());
403
        if (!hasAcceptedPesiTaxon) {if (logger.isDebugEnabled()){logger.debug("Synonym has no accepted PESI taxon: " +  synonym.getUuid() + ", (" +  synonym.getTitleCache() + ")");}}
404

    
405
        return hasAcceptedPesiTaxon && synonym.isPublish();
406
    }
407

    
408
    private static boolean isPesiAcceptedTaxon(boolean excludeMisappliedNames, Taxon taxon) {
409
        if (! taxon.isPublish()){
410
        	return false;
411
        }
412

    
413
        //handle PESI accepted taxa
414
        if (! taxon.isMisapplication()){
415
        	for (Marker marker : taxon.getMarkers()){
416
        		if (marker.getValue() == false && marker.getMarkerType().equals(MarkerType.PUBLISH())){
417
        			return false;
418
        		}
419
        	}
420
        	return true;
421
        //handle misapplied names
422
        }else{
423
        	if (excludeMisappliedNames){
424
        		return false;
425
        	}
426
        	for (TaxonRelationship taxRel : taxon.getRelationsFromThisTaxon()){
427
        		if (taxRel.getType().isAnyMisappliedName()){
428
//						logger.warn(taxRel.getUuid() + "; " + taxRel.getToTaxon().getUuid() + " + " + taxRel.getToTaxon().getTitleCache());
429
        			if (isPesiTaxon(taxRel.getToTaxon(), true)){
430
        				return true;
431
        			}
432
        		}
433
        	}
434
        	if (logger.isDebugEnabled()){ logger.debug("Misapplied name has no accepted PESI taxon: " +  taxon.getUuid() + ", (" +  taxon.getTitleCache() + ")");}
435
        	return false;
436
        }
437
    }
438

    
439
	@Override
440
    protected Object getDbIdCdmWithExceptions(CdmBase cdmBase, PesiExportState state) {
441
		if (cdmBase.isInstanceOf(TaxonName.class)){
442
		    TaxonName name = CdmBase.deproxy(cdmBase, TaxonName.class);
443
		    if (name.getTaxonBases().size()>1){
444
		        logger.warn("Name has multiple taxa. Can't define correct ID. Use first one." + name.getUuid());
445
		    }
446
		    if (!name.getTaxonBases().isEmpty()){
447
		        TaxonBase<?> tb = name.getTaxonBases().iterator().next();
448
		        return this.getDbId(tb, state);
449
            }else{
450
                return ( cdmBase.getId() + state.getConfig().getNameIdStart() );
451
            }
452
		}else if (isAdditionalSource(cdmBase) ){
453
			return ( cdmBase.getId() + 2 * state.getConfig().getNameIdStart() );  //make it a separate variable if conflicts occur.
454
		}else{
455
			return super.getDbIdCdmWithExceptions(cdmBase, state);
456
		}
457
	}
458

    
459
	private boolean isAdditionalSource(CdmBase cdmBase) {
460
		if (cdmBase.isInstanceOf(TextData.class)){
461
			TextData textData = CdmBase.deproxy(cdmBase, TextData.class);
462
			if (textData.getFeature().equals(Feature.ADDITIONAL_PUBLICATION()) ||
463
					textData.getFeature().equals(Feature.CITATION())){
464
				return true;
465
			}
466
		}
467
		return false;
468
	}
469

    
470
	protected MarkerType getUuidMarkerType(UUID uuid, PesiExportState state){
471
		if (uuid == null){
472
			uuid = UUID.randomUUID();
473
		}
474

    
475
		MarkerType markerType = state.getMarkerType(uuid);
476
		if (markerType == null){
477
			if (uuid.equals(PesiTransformer.uuidMarkerGuidIsMissing)){
478
				markerType = MarkerType.NewInstance("Uuid is Missing", "Uuid is missing", null);
479
				markerType.setUuid(uuid);
480
			} else if (uuid.equals(PesiTransformer.uuidMarkerTypeHasNoLastAction)){
481
				markerType = MarkerType.NewInstance("Has no last Action", "Has no last action", null);
482
				markerType.setUuid(uuid);
483
			}
484
		}
485

    
486
		state.putMarkerType(markerType);
487
		return markerType;
488
	}
489

    
490
	protected static TaxonNameDefaultCacheStrategy getCacheStrategy(TaxonName taxonName) {
491
	    TaxonNameDefaultCacheStrategy cacheStrategy;
492
		if (taxonName.isZoological()){
493
			cacheStrategy = zooNameStrategy;
494
		}else if (taxonName.isBotanical()) {
495
			cacheStrategy = botanicalNameStrategy;
496
		}else{
497
			logger.error("Unhandled taxon name type. Can't define strategy class");
498
			cacheStrategy = botanicalNameStrategy;
499
		}
500
		return cacheStrategy;
501
	}
502

    
503
	/**
504
	 * Checks whether a given taxon is a misapplied name.
505
	 * @param taxon The {@link TaxonBase Taxon}.
506
	 * @return Whether the given TaxonName is a misapplied name or not.
507
	 */
508
	protected static boolean isMisappliedName(TaxonBase<?> taxon) {
509
		return getAcceptedTaxonForMisappliedName(taxon) != null;
510
	}
511

    
512
	/**
513
     * Checks whether a given taxon is a pro parte or partial synonym.
514
     * @param taxon The {@link TaxonBase Taxon}.
515
     * @return <code>true</code> if the the given taxon is a pp or partial synonym
516
     */
517
    protected static boolean isProParteOrPartialSynonym(TaxonBase<?> taxon) {
518
        return getAcceptedTaxonForProParteSynonym(taxon) != null;
519
    }
520

    
521
	/**
522
	 * Returns the first accepted taxon for this misapplied name.
523
	 * If this misapplied name is not a misapplied name, <code>null</code> is returned.
524
	 * @param taxon The {@link TaxonBase Taxon}.
525
	 */
526
	protected static Taxon getAcceptedTaxonForMisappliedName(TaxonBase<?> taxon) {
527
		if (! taxon.isInstanceOf(Taxon.class)){
528
			return null;
529
		}
530
		Set<TaxonRelationship> taxonRelations = CdmBase.deproxy(taxon, Taxon.class).getRelationsFromThisTaxon();
531
		for (TaxonRelationship taxonRelationship : taxonRelations) {
532
			TaxonRelationshipType taxonRelationshipType = taxonRelationship.getType();
533
			if (taxonRelationshipType.isAnyMisappliedName()) {
534
				return taxonRelationship.getToTaxon();
535
			}
536
		}
537
		return null;
538
	}
539

    
540
    protected static Taxon getAcceptedTaxonForProParteSynonym(TaxonBase<?> taxon) {
541
        if (! taxon.isInstanceOf(Taxon.class)){
542
            return null;
543
        }
544
        Set<TaxonRelationship> taxonRelations = CdmBase.deproxy(taxon, Taxon.class).getRelationsFromThisTaxon();
545
        for (TaxonRelationship taxonRelationship : taxonRelations) {
546
            TaxonRelationshipType taxonRelationshipType = taxonRelationship.getType();
547
            if (taxonRelationshipType.isAnySynonym()) {
548
                return taxonRelationship.getToTaxon();
549
            }
550
        }
551
        return null;
552
    }
553

    
554
    protected List<AnnotationType> getLastActionAnnotationTypes() {
555
        Set<UUID> uuidSet = new HashSet<>();
556
        uuidSet.add(DbLastActionMapper.uuidAnnotationTypeLastActionDate);
557
        uuidSet.add(DbLastActionMapper.uuidAnnotationTypeLastAction);
558
        uuidSet.add(ErmsTransformer.uuidAnnSpeciesExpertName);
559
        @SuppressWarnings({"unchecked","rawtypes"})
560
        List<AnnotationType> result = (List)getTermService().find(uuidSet);
561
        return result;
562
    }
563

    
564
    protected enum PesiSource{
565
        EM,
566
        FE,
567
        ERMS,
568
        IF;
569

    
570
        private PesiSource(){
571

    
572
        }
573
    }
574

    
575
    /**
576
     * Returns the source (E+M, Fauna Europaea, Index Fungorum, ERMS) of a given
577
     * Identifiable Entity as an {@link EnumSet enum set}
578
     */
579
    protected static EnumSet<PesiSource> getSources(IdentifiableEntity<?> entity){
580
        EnumSet<PesiSource> result = EnumSet.noneOf(PesiSource.class);
581

    
582
        Set<IdentifiableSource> sources = getPesiSources(entity);
583
        for (IdentifiableSource source : sources) {
584
            Reference ref = source.getCitation();
585
            UUID refUuid = ref.getUuid();
586
            if (refUuid.equals(PesiTransformer.uuidSourceRefEuroMed)){
587
                result.add(PesiSource.EM);
588
            }else if (refUuid.equals(PesiTransformer.uuidSourceRefFaunaEuropaea)){
589
                result.add(PesiSource.FE);
590
            }else if (refUuid.equals(PesiTransformer.uuidSourceRefErms)){
591
                result.add(PesiSource.ERMS);
592
            }else if (refUuid.equals(PesiTransformer.uuidSourceRefIndexFungorum)){
593
                result.add(PesiSource.IF);
594
            }else{
595
                if (logger.isDebugEnabled()){logger.debug("Not a PESI source");}
596
            }
597
        }
598
        return result;
599
    }
600

    
601
    /**
602
     * Returns the Sources for a given TaxonName only.
603
     * @param identifiableEntity
604
     * @return The Sources.
605
     */
606
    protected static Set<IdentifiableSource> getPesiSources(IdentifiableEntity<?> identifiableEntity) {
607
        Set<IdentifiableSource> sources = new HashSet<>();
608

    
609
        //Taxon Names
610
        if (identifiableEntity.isInstanceOf(TaxonName.class)){
611
            // Sources from TaxonName
612
            TaxonName taxonName = CdmBase.deproxy(identifiableEntity, TaxonName.class);
613
            Set<IdentifiableSource> testSources = identifiableEntity.getSources();
614
            sources = filterPesiSources(testSources);
615

    
616
            if (sources.size() == 0 && testSources.size()>0){
617
                IdentifiableSource source = testSources.iterator().next();
618
                logger.warn("There are sources, but they are no pesi sources!!!" + source.getIdInSource() + " - " + source.getIdNamespace() + " - " + (source.getCitation()== null? "no reference" : source.getCitation().getTitleCache()));
619
            }
620
            if (sources.size() > 1) {
621
                logger.warn("This TaxonName has more than one Source: " + identifiableEntity.getUuid() + " (" + identifiableEntity.getTitleCache() + ")");
622
            }
623

    
624
            // name has no PESI source, take sources from TaxonBase
625
            if (sources == null || sources.isEmpty()) {
626
                Set<TaxonBase> taxa = taxonName.getTaxonBases();
627
                for (TaxonBase<?> taxonBase: taxa){
628
                    sources.addAll(filterPesiSources(taxonBase.getSources()));
629
                }
630
            }
631

    
632
        //for TaxonBases
633
        }else if (identifiableEntity.isInstanceOf(TaxonBase.class)){
634
            sources = filterPesiSources(identifiableEntity.getSources());
635
        } else {
636
            sources = filterPesiSources(identifiableEntity.getSources());
637
        }
638

    
639
        return sources;
640
    }
641

    
642
    // return all sources with a PESI reference
643
    protected static Set<IdentifiableSource> filterPesiSources(Set<? extends IdentifiableSource> sources) {
644
        Set<IdentifiableSource> result = new HashSet<>();
645
        for (IdentifiableSource source : sources){
646
            Reference ref = source.getCitation();
647
            if (ref != null){
648
                UUID refUuid = ref.getUuid();
649
                if (refUuid.equals(PesiTransformer.uuidSourceRefEuroMed) ||
650
                        refUuid.equals(PesiTransformer.uuidSourceRefFaunaEuropaea)||
651
                        refUuid.equals(PesiTransformer.uuidSourceRefErms)||
652
                        refUuid.equals(PesiTransformer.uuidSourceRefIndexFungorum) ||
653
                        refUuid.equals(PesiTransformer.uuidSourceRefAuct)){
654
                    result.add(source);
655
                }
656
            }
657
        }
658
        return result;
659
    }
660

    
661
}
(6-6/14)