Project

General

Profile

Download (26 KB) Statistics
| Branch: | Revision:
1
package eu.etaxonomy.cdm.app.pesi.merging;
2

    
3
import java.io.File;
4
import java.io.FileOutputStream;
5
import java.io.IOException;
6
import java.io.OutputStreamWriter;
7
import java.io.Writer;
8
import java.lang.reflect.InvocationTargetException;
9
import java.lang.reflect.Method;
10
import java.nio.charset.StandardCharsets;
11
import java.util.ArrayList;
12
import java.util.Arrays;
13
import java.util.HashMap;
14
import java.util.HashSet;
15
import java.util.Iterator;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19
import java.util.UUID;
20

    
21
import org.apache.log4j.Logger;
22
import org.springframework.transaction.TransactionStatus;
23

    
24
import eu.etaxonomy.cdm.api.application.CdmApplicationController;
25
import eu.etaxonomy.cdm.app.common.CdmDestinations;
26
import eu.etaxonomy.cdm.common.CdmUtils;
27
import eu.etaxonomy.cdm.common.StringComparator;
28
import eu.etaxonomy.cdm.database.DbSchemaValidation;
29
import eu.etaxonomy.cdm.database.ICdmDataSource;
30
import eu.etaxonomy.cdm.io.api.application.CdmIoApplicationController;
31
import eu.etaxonomy.cdm.io.pesi.out.PesiTransformer;
32
import eu.etaxonomy.cdm.model.common.CdmBase;
33
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
34
import eu.etaxonomy.cdm.model.name.Rank;
35
import eu.etaxonomy.cdm.model.name.TaxonName;
36
import eu.etaxonomy.cdm.model.taxon.Synonym;
37
import eu.etaxonomy.cdm.model.taxon.Taxon;
38
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
39
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
40
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
41
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
42
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
43

    
44
public class PesiFindIdenticalNamesActivator {
45

    
46
    private static final Logger logger = Logger.getLogger(PesiFindIdenticalNamesActivator.class);
47

    
48
    //static final ICdmDataSource faunaEuropaeaSource = CdmDestinations.localH2();
49
	static final ICdmDataSource pesiSource = CdmDestinations.cdm_pesi2019_final();
50

    
51
	static final String path = System.getProperty("user.home")+File.separator+".cdmLibrary"+File.separator+"pesi"+File.separator+"pesimerge";
52

    
53
	private static UUID emSourceUuid = PesiTransformer.uuidSourceRefEuroMed;
54
	private static UUID ermsSourceUuid = PesiTransformer.uuidSourceRefErms;
55
	private static UUID faunaEuSourceUuid = PesiTransformer.uuidSourceRefFaunaEuropaea;
56
	private static UUID ifSourceUuid = PesiTransformer.uuidSourceRefIndexFungorum;
57
	private static List<UUID> sourceRefUuids = new ArrayList<>();
58
	private static Map<UUID,String> sourcesLabels = new HashMap<>();
59

    
60
    static {
61
        sourceRefUuids.addAll(Arrays.asList(new UUID[]{emSourceUuid, ermsSourceUuid, faunaEuSourceUuid, ifSourceUuid}));
62
        sourcesLabels.put(emSourceUuid, "E+M");
63
        sourcesLabels.put(ermsSourceUuid, "ERMS");
64
        sourcesLabels.put(faunaEuSourceUuid, "FauEu");
65
        sourcesLabels.put(ifSourceUuid, "IF");
66
    }
67

    
68
	private void invoke(ICdmDataSource source){
69

    
70
        CdmApplicationController app = CdmIoApplicationController.NewInstance(source, DbSchemaValidation.VALIDATE, false);
71

    
72
        List<String> propertyPaths = new ArrayList<>();
73
        propertyPaths.add("sources.*");
74
        propertyPaths.add("sources.idInSource");
75
        propertyPaths.add("sources.idNamespace");
76
        propertyPaths.add("taxonBases.*");
77
        propertyPaths.add("taxonBases.relationsFromThisTaxon");
78
        propertyPaths.add("taxonBases.taxonNodes.*");
79
        propertyPaths.add("taxonBases.taxonNodes.parent.*");
80
        propertyPaths.add("taxonBases.taxonNodes.childNodes.*");
81
        propertyPaths.add("taxonBases.taxonNodes.childNodes.classification.rootNode.childNodes.*");
82
        propertyPaths.add("taxonBases.taxonNodes.parent.taxon.name.*");
83
        propertyPaths.add("taxonBases.acceptedTaxon.taxonNodes.*");
84
        propertyPaths.add("taxonBases.acceptedTaxon.taxonNodes.childNodes.*");
85
        propertyPaths.add("taxonBases.acceptedTaxon.taxonNodes.childNodes.classification.rootNode.childNodes.*");
86
        System.out.println("Start getIdenticalNames...");
87

    
88
        Map<String, Map<UUID, Set<TaxonName>>> namesOfIdenticalTaxa;
89
        TransactionStatus tx = app.startTransaction(true);
90
        try {
91
            namesOfIdenticalTaxa = app.getTaxonService().findIdenticalTaxonNames(sourceRefUuids, propertyPaths);
92
        } catch (Exception e) {
93
            e.printStackTrace();
94
            return;
95
        }
96
        System.out.println("Start creating merging objects");
97
        List<Map<UUID, List<PesiMergeObject>>> mergingObjects = createMergeObjects(namesOfIdenticalTaxa, app);
98
        app.commitTransaction(tx);
99

    
100
        boolean resultOK = true;
101
        System.out.println("Start creating csv files");
102
        resultOK &= writeSameNamesToCsvFile(mergingObjects, path + "_namesAll.csv");
103
        resultOK &= writeSameNamesDifferentAuthorToCsv(mergingObjects, path + "_authors.csv");
104
        resultOK &= writeSameNamesDifferentStatusToCsv(mergingObjects, path + "_status.csv");
105
        resultOK &= writeSameNamesDifferentPhylumToCsv(mergingObjects, path + "_phylum.csv");
106
        resultOK &= writeSameNamesDifferentParentToCsv(mergingObjects, path + "_parent.csv");
107
        resultOK &= writeSameNamesDifferentRankToCsv(mergingObjects, path + "_rank.csv");
108

    
109
        System.out.println("End find identical names for PESI: " + resultOK + ". Results written to " + path);
110
	}
111

    
112
	private boolean writeSameNamesToCsvFile(
113
			List<Map<UUID,List<PesiMergeObject>>> mergingObjects, String sFileName) {
114

    
115
	    String header = "same names (all)";
116
        String methodName = null;
117
        return writeDifference(header, methodName, mergingObjects, sFileName);
118
	}
119

    
120
	private boolean writeSameNamesDifferentPhylumToCsv(
121
	        List<Map<UUID,List<PesiMergeObject>>> mergingObjects, String sFileName){
122

    
123
	    String header = "same names but different phylum";
124
	    String methodName = "getPhylum";
125
	    return writeDifference(header, methodName, mergingObjects, sFileName);
126
	}
127

    
128
    private boolean writeSameNamesDifferentParentToCsv(
129
	        List<Map<UUID,List<PesiMergeObject>>> mergingObjects, String sFileName){
130

    
131
		    String header = "same names but different parent";
132
	        String methodName = "getParentString";
133
	        return writeDifference(header, methodName, mergingObjects, sFileName);
134
	}
135

    
136
	private boolean writeSameNamesDifferentRankToCsv(
137
	        List<Map<UUID,List<PesiMergeObject>>> mergingObjects, String sFileName){
138

    
139
        String header = "same names but different rank";
140
        String methodName = "getRank";
141
        return writeDifference(header, methodName, mergingObjects, sFileName);
142
	}
143

    
144
    private boolean writeSameNamesDifferentStatusToCsv(
145
            List<Map<UUID,List<PesiMergeObject>>> mergingObjects, String sFileName){
146

    
147
        String header = "same names but different status";
148
        String methodName = "isStatus";
149
        return writeDifference(header, methodName, mergingObjects, sFileName);
150
    }
151

    
152
    private boolean writeSameNamesDifferentAuthorToCsv(
153
            List<Map<UUID,List<PesiMergeObject>>> mergingObjects, String sFileName){
154

    
155
        String header = "same names but different author";
156
        String methodName = "getAuthor";
157
        return writeDifference(header, methodName, mergingObjects, sFileName);
158
    }
159

    
160
    private boolean writeDifference(String header,
161
            String methodName,
162
            List<Map<UUID,List<PesiMergeObject>>> mergingObjects,
163
            String sFileName) {
164

    
165
        try{
166
            Method method = methodName == null? null : PesiMergeObject.class.getMethod(methodName);
167

    
168
            Writer writer = new OutputStreamWriter(new FileOutputStream(new File(sFileName)), StandardCharsets.UTF_8);
169

    
170
            //create Header
171
            createHeader(writer, header);
172

    
173
            //write data
174
            for (Map<UUID,List<PesiMergeObject>> merging : mergingObjects){
175
                boolean isNextNameCache = true;
176
                List<UUID> mySources = new ArrayList<>(merging.keySet());
177
                for (int i = 0; i<mySources.size()-1; i++){
178
                    for (int j = i+1; j<mySources.size(); j++){
179
                        boolean differenceExists = false;
180
                        List<PesiMergeObject> mergeList1 = merging.get(mySources.get(i));
181
                        List<PesiMergeObject> mergeList2 = merging.get(mySources.get(j));
182
                        for (PesiMergeObject merge1 : mergeList1){
183
                            for (PesiMergeObject merge2 : mergeList2){
184
                                differenceExists |= isDifferent(merge1, merge2, method);
185
                            }
186
                        }
187
                        if (differenceExists){
188
                            for (PesiMergeObject merge1 : mergeList1){
189
                                for (PesiMergeObject merge2 : mergeList2){
190
                                    writeCsvLine(writer, merge1, merge2, method, isNextNameCache);
191
                                    isNextNameCache = false;
192
                                }
193
                            }
194
                        }
195
                    }
196
                }
197
            }
198
            writer.flush();
199
            writer.close();
200
            return true;
201
        }catch(NoSuchMethodException | SecurityException | IOException e){
202
            logger.error(e.getMessage());
203
            return false;
204
        }
205
    }
206

    
207
    private boolean isDifferent(PesiMergeObject merge1, PesiMergeObject merge2, Method method){
208

    
209
        try {
210
            if (method == null){
211
                return true;
212
            }
213
            Object value1 = method.invoke(merge1);
214
            Object value2 = method.invoke(merge2);
215
            return !CdmUtils.nullSafeEqual(value1, value2);
216
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
217
            e.printStackTrace();
218
            return true;
219
        }
220
    }
221

    
222
    //old method when all sources were in 1 line
223
    private boolean isDifferent(Map<UUID, PesiMergeObject> merging, Method method)
224
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
225

    
226
        if (method == null){
227
            return true;
228
        }
229
        Object value = null;
230
        boolean isFirst = true;
231
        for (UUID sourceUuid: merging.keySet()){
232
            if (isFirst){
233
                value = method.invoke(merging.get(sourceUuid));
234
                isFirst = false;
235
            }else{
236
                Object newValue = method.invoke(merging.get(sourceUuid));
237
                if (!CdmUtils.nullSafeEqual(newValue, value)){
238
                    return true;
239
                }
240
            }
241
        }
242
        return false;
243
    }
244

    
245
	private void createHeader(Writer writer, String firstLine){
246
	 	try {
247
            writer.append(firstLine);
248
            writer.append('\n');
249
            writeHeaderPair(writer, "taxon uuid");
250
            writeHeaderPair(writer, "taxon id");
251
            writer.append("next name cache").append(";");
252
            writer.append("diff").append(";");
253
            writeHeaderPair(writer, "source");
254
            writeHeaderPair(writer, "name uuid");
255
            writeHeaderPair(writer, "idInSource");
256
            writeHeaderPair(writer, "nameCache");
257
            writeHeaderPair(writer, "author");
258
            writeHeaderPair(writer, "rank");
259
            writeHeaderPair(writer, "kingdom");
260
            writeHeaderPair(writer, "phylum");
261
            writeHeaderPair(writer, "family");
262
            writeHeaderPair(writer, "parentString");
263
            writeHeaderPair(writer, "parentRankString");
264
            writeHeaderPair(writer, "status");
265
            writer.append('\n');
266
        } catch (IOException e) {
267
            e.printStackTrace();
268
        }
269
	}
270

    
271
    private void writeHeaderPair(Writer writer, String header) throws IOException {
272
        writer.append(header+"1").append(';');
273
        writer.append(header+"2").append(';');
274
    }
275

    
276
    private void writeCsvLine(Writer writer,
277
           PesiMergeObject merge1, PesiMergeObject merge2,
278
           Method method, boolean isNextNameCache){
279

    
280
        writePair(writer, merge1, merge2, "UuidTaxon");
281
        writePair(writer, merge1, merge2, "IdTaxon");
282
        writeSingleValue(writer, isNextNameCache?"1":"0");
283
        boolean different = isDifferent(merge1,  merge2, method);
284
        writeSingleValue(writer, different?"1":"0");
285
        writeSingleValue(writer, sourcesLabels.get(UUID.fromString(merge1.getUuidSource())));
286
        writeSingleValue(writer, sourcesLabels.get(UUID.fromString(merge2.getUuidSource())));
287
        writePair(writer, merge1, merge2, "UuidName");
288
        writePair(writer, merge1, merge2, "IdInSource");
289
        writePair(writer, merge1, merge2, "NameCache");
290
        writePair(writer, merge1, merge2, "Author");
291
        writePair(writer, merge1, merge2, "Rank");
292
        writePairNode(writer, merge1, merge2, "Kingdom");
293
        writePairNode(writer, merge1, merge2, "Phylum");
294
        writePairNode(writer, merge1, merge2, "Family");
295
        writePair(writer, merge1, merge2, "ParentString");
296
        writePair(writer, merge1, merge2, "ParentRankString");
297
        writeSingleValue(writer, merge1.isStatus()?"accepted":"synonym");
298
        writeSingleValue(writer, merge2.isStatus()?"accepted":"synonym");
299
        try {
300
            writer.append('\n');
301
        } catch (IOException e) {
302
            e.printStackTrace();
303
        }
304
    }
305

    
306
    private void writeSingleValue(Writer writer, String value) {
307
        try {
308
            writer.append(value).append(";");
309
        } catch (Exception e) {
310
            e.printStackTrace();
311
        }
312
    }
313

    
314
    private void writePairNode(Writer writer, PesiMergeObject merge1, PesiMergeObject merge2, String methodName) {
315
        try {
316
            Method method = PesiMergeObject.class.getDeclaredMethod("get"+methodName);
317
            TaxonNodeDto value = (TaxonNodeDto) method.invoke(merge1);
318
            writer.append(value==null?"":value.getTitleCache()).append(";");
319
            value = (TaxonNodeDto) method.invoke(merge2);
320
            writer.append(value==null?"":value.getTitleCache()).append(";");
321
        } catch (Exception e) {
322
            e.printStackTrace();
323
        }
324
    }
325

    
326
    private void writePair(Writer writer, PesiMergeObject merge1, PesiMergeObject merge2, String methodName) {
327
        try {
328
            Method method = PesiMergeObject.class.getDeclaredMethod("get"+methodName);
329
            String value1 = (String) method.invoke(merge1);
330
            writer.append(normalize(value1)).append(";");
331
            String value2 = (String) method.invoke(merge2);
332
            writer.append(normalize(value2)).append(";");
333
        } catch (Exception e) {
334
            e.printStackTrace();
335
        }
336
    }
337

    
338
    private String normalize(String val) {
339
        return CdmUtils.Nz(val).replace(";", "@");
340
    }
341

    
342
    private void writeCsvLine(Writer writer, Map<UUID,PesiMergeObject> mergeObjects, Map<UUID,String> sources) throws IOException{
343

    
344
        for (UUID uuid : sourceRefUuids){
345
	        PesiMergeObject merging = mergeObjects.get(uuid);
346
	        if(merging == null){
347
	            continue;
348
	        }
349
	        writer.append(Nz(sources.get(uuid))).append(";");
350
            writer.append(Nz(merging.getUuidName())).append(";");
351
	        writer.append(Nz(merging.getIdInSource())).append(";");
352
	        writer.append(Nz(merging.getNameCache())).append(";");
353
	        writer.append(Nz(merging.getAuthor())).append(";");
354
	        writer.append(Nz(merging.getRank())).append(";");
355
	        if (merging.isStatus()){
356
	            writer.append("accepted").append(";");
357
	        }else{
358
	            writer.append("synonym").append(";");
359
	        }
360
	        writer.append(Nz(merging.getPhylum() != null? merging.getPhylum().getTitleCache(): "")).append(";");
361
	        writer.append(Nz(merging.getParentString())).append(";");
362
	        writer.append(Nz(merging.getParentRankString())).append(";");
363
	    }
364
        writer.append('\n');
365
	}
366

    
367
    private List<Map<UUID,List<PesiMergeObject>>> createMergeObjects(
368
            Map<String, Map<UUID, Set<TaxonName>>> identicalNames,
369
	        CdmApplicationController appCtr){
370

    
371
		List<Map<UUID,List<PesiMergeObject>>> merge = new ArrayList<>();
372

    
373
		List<String> nameCaches = new ArrayList<>(identicalNames.keySet());
374
		nameCaches.sort(StringComparator.Instance);
375
		for (String nameCache: nameCaches){
376
		    createSingleMergeObject(appCtr, merge, identicalNames.get(nameCache));
377
		}
378
		return merge;
379
	}
380

    
381
    private void createSingleMergeObject(CdmApplicationController appCtr,
382
            List<Map<UUID,List<PesiMergeObject>>> merge,
383
            Map<UUID, Set<TaxonName>> identicalNames) {
384

    
385
        Map<UUID,List<PesiMergeObject>> mergeMap = new HashMap<>();
386

    
387
        for (UUID sourceUuid : identicalNames.keySet()){
388
            Set<TaxonName> names = identicalNames.get(sourceUuid);
389
            List<PesiMergeObject> pmoList = new ArrayList<>();
390
            mergeMap.put(sourceUuid, pmoList);
391

    
392
            for (TaxonName name : names){
393
                String nameAndIdStr = name.getTitleCache() +  "; id = " + name.getId();
394
                @SuppressWarnings("rawtypes")
395
                Set<TaxonBase> taxonBases = name.getTaxonBases();
396
                if (taxonBases.isEmpty()){
397
                    logger.warn("No taxonbase attached to name. This is not yet handled: " + nameAndIdStr);
398
                    continue;
399
                }
400
                for (TaxonBase<?> taxonBase : taxonBases)                {
401
                    if (!taxonBase.isPublish()){
402
                        continue;
403
                    }
404
                    PesiMergeObject mergeObject = PesiMergeObject.NewInstance();
405
                    pmoList.add(mergeObject);
406

    
407
                    //uuid
408
                    mergeObject.setUuidSource(sourceUuid.toString());
409
                    mergeObject.setUuidName(name.getUuid().toString());
410
                    mergeObject.setUuidTaxon(taxonBase.getUuid().toString());
411
                    mergeObject.setIdTaxon(String.valueOf(taxonBase.getId()));
412

    
413
                    //nameCache
414
                    mergeObject.setNameCache(name.getNameCache());
415

    
416
                    //authorship
417
                    mergeObject.setAuthor(name.getAuthorshipCache());
418

    
419
                    //rank
420
                    mergeObject.setRank(name.getRank().getLabel());
421

    
422
                    //Kingdom
423
                    TaxonNodeDto kingdom = getHigherTaxon(appCtr, name, Rank.KINGDOM());
424
                    mergeObject.setKingdom(kingdom);
425

    
426
                    //Phylum/Division
427
                    TaxonNodeDto phylum = getHigherTaxon(appCtr, name, Rank.PHYLUM());
428
                    if(phylum == null){
429
                        phylum = getHigherTaxon(appCtr, name, Rank.DIVISION());
430
                    }
431
                    mergeObject.setPhylum(phylum);
432

    
433
                    //Family
434
                    TaxonNodeDto family = getHigherTaxon(appCtr, name, Rank.FAMILY());
435
                    mergeObject.setFamily(family);
436

    
437
                    //idInSource
438
                    Iterator<IdentifiableSource> sources = name.getSources().iterator();
439
                    //TODO idInSource - what if multiple sources exist?
440
                    if (sources.hasNext()){
441
                        IdentifiableSource source = sources.next();
442
                        String idInSource = source.getIdInSource();
443
                        mergeObject.setIdInSource(idInSource);
444
                    }
445

    
446
                    //status and parent
447
                    makeStatusAndParent(name, mergeObject);
448
                }
449
            }
450
        }
451

    
452
        merge.add(mergeMap);
453

    
454

    
455
        //set parent informations
456

    
457
        /*
458
        Set<HybridRelationship> parentRelations = zooName.getParentRelationships();
459
        Iterator parentIterator = parentRelations.iterator();
460
        HybridRelationship parentRel;
461
        ZoologicalName parentName;
462
        while (parentIterator.hasNext()){
463
            parentRel = (HybridRelationship)parentIterator.next();
464
            parentName = (ZoologicalName)parentRel.getParentName();
465
            mergeObject.setParentRankStringInErms(parentName.getRank().getLabel());
466
            mergeObject.setParentStringInErms(parentName.getNameCache());
467
        }
468

    
469
        parentRelations = zooName2.getParentRelationships();
470
        parentIterator = parentRelations.iterator();
471

    
472
        while (parentIterator.hasNext()){
473
            parentRel = (HybridRelationship)parentIterator.next();
474
            parentName = (ZoologicalName)parentRel.getParentName();
475
            mergeObject.setParentRankStringInFaunaEu(parentName.getRank().getLabel());
476
            mergeObject.setParentStringInFaunaEu(parentName.getNameCache());
477
        }*/
478

    
479

    
480
    }
481

    
482
    private void makeStatusAndParent(TaxonName name, PesiMergeObject mergeObject) {
483
        Set<Taxon> taxa = name.getTaxa();
484
        taxa = getReallyAcceptedTaxa(taxa);
485
        if (!taxa.isEmpty()){
486
            mergeObject.setStatus(true);
487
            Iterator<Taxon> taxaIterator = taxa.iterator();
488
            Taxon taxon = null;
489
            while (taxaIterator.hasNext()){
490
                taxon = taxaIterator.next();
491
                if (!taxon.isMisapplication()){
492
                    break;
493
                }
494
            }
495
            @SuppressWarnings("null")
496
            Set<TaxonNode> nodes = taxon.getTaxonNodes();
497
            Iterator<TaxonNode> taxonNodeIterator = nodes.iterator();
498
            TaxonNode parentNode = null;
499
            while (taxonNodeIterator.hasNext()){
500
                TaxonNode node = taxonNodeIterator.next();
501
                if (!node.isTopmostNode()){
502
                    parentNode = node.getParent();
503
                }
504
            }
505
            if (parentNode != null){
506
                TaxonName parentName = CdmBase.deproxy(parentNode.getTaxon().getName());
507
                String parentNameCache = parentName.getNameCache();
508
                mergeObject.setParentString(parentNameCache);
509
                mergeObject.setParentRankString(parentName.getRank().getLabel());
510
            }
511
        }else{
512
            mergeObject.setStatus(false);
513
            TaxonNode parentNode = getAcceptedNode(name);
514
            if (parentNode != null){
515
                TaxonName parentName = CdmBase.deproxy(parentNode.getTaxon().getName());
516
                String parentNameCache = parentName.getNameCache();
517
                mergeObject.setParentString(parentNameCache);
518
                mergeObject.setParentRankString(parentName.getRank().getLabel());
519
            }
520
        }
521
    }
522

    
523
    private TaxonNodeDto getHigherTaxon(CdmApplicationController appCtr, TaxonName name, Rank rank) {
524
        if (name.getRank().equals(rank)) {
525
            Taxon taxon = getAcceptedTaxon(name);
526
            if (taxon != null) {
527
                if (taxon.getTaxonNodes().isEmpty()){
528
                    return null;  //probably MAN
529
                }
530
                if (taxon.getTaxonNodes().size()>1){
531
                    logger.warn("More than 1 node not yet handled for getHigherTaxon. Take arbitrary one.");
532
                }
533
                TaxonNode node = taxon.getTaxonNodes().iterator().next();
534
                return new TaxonNodeDto(node);
535
            }
536
        }
537
        if (name.getRank().isHigher(rank)){
538
            return null;
539
        }else{
540
            Taxon taxon = getAcceptedTaxon(name);
541
            if (taxon.getTaxonNodes().isEmpty()){
542
                return null;
543
            }else{
544
                if (taxon.getTaxonNodes().size()>1){
545
                    logger.warn("More than 1 node not yet handled for getHigherTaxon. Take arbitrary one.");
546
                }
547
                TaxonNode node = taxon.getTaxonNodes().iterator().next();
548
                List<TaxonNodeDto> higherDtos = appCtr.getTaxonNodeService().taxonNodeDtoParentRank(node.getClassification(), rank, taxon);
549
                if (higherDtos.isEmpty()){
550
                    return null;
551
                }else {
552
                    if (higherDtos.size() > 1){
553
                        logger.warn("More than 1 higher dto. This is not yet implemented: " + taxon.getTitleCache());
554
                    }
555
                    return higherDtos.get(0);
556
                }
557
            }
558
        }
559
    }
560

    
561
	private TaxonNode getAcceptedNode(TaxonName ermsName) {
562
	    TaxonNode parentNode = null;
563
		Set<TaxonBase> taxonBases = ermsName.getTaxonBases();
564
		if (!taxonBases.isEmpty()) {
565
		    Taxon taxon = null;
566
			TaxonBase<?> taxonBase = taxonBases.iterator().next();
567
			if (taxonBase instanceof Synonym) {
568
				taxon = ((Synonym)taxonBase).getAcceptedTaxon();
569
			}else{
570
			    taxon = getAccTaxonForTaxonSynonym((Taxon)taxonBase);
571
			}
572
			Set<TaxonNode> nodes = taxon.getTaxonNodes();
573
			if (!nodes.isEmpty()) {
574
			    parentNode = nodes.iterator().next();
575
			}
576
		}
577

    
578
		return parentNode;
579
	}
580

    
581
	private Taxon getAcceptedTaxon(TaxonName name) {
582
		Taxon taxon = null;
583
		//prefer accepted taxon
584
		if (name.getTaxa() != null && !name.getTaxa().isEmpty()){
585
			taxon = name.getTaxa().iterator().next();
586
			taxon = getAccTaxonForTaxonSynonym(taxon);
587
		//else take synonym
588
		}else if (name.getTaxonBases() != null && !name.getTaxonBases().isEmpty()){
589
			TaxonBase<?> taxonBase = name.getTaxonBases().iterator().next();
590
			if (taxonBase instanceof Synonym) {
591
				Synonym syn = (Synonym)taxonBase;
592
				taxon = syn.getAcceptedTaxon();
593
			}
594
		}
595
		return taxon;
596
	}
597

    
598
    private Taxon getAccTaxonForTaxonSynonym(Taxon taxon) {
599
        if (!taxon.getRelationsFromThisTaxon().isEmpty()){
600
            for (TaxonRelationship rel: taxon.getRelationsFromThisTaxon()){
601
                UUID uuidType = rel.getType().getUuid();
602
                if (uuidType.equals(TaxonRelationshipType.uuidSynonymOfTaxonRelationship)
603
                        || uuidType.equals(TaxonRelationshipType.uuidHeterotypicSynonymTaxonRelationship)
604
                        || uuidType.equals(TaxonRelationshipType.uuidHomotypicSynonymTaxonRelationship)){
605
                    taxon = rel.getToTaxon();
606
                }
607
            }
608
        }
609
        return taxon;
610
    }
611

    
612
    /**
613
     * Filters out the ERMS taxon synonyms
614
     */
615
    private Set<Taxon> getReallyAcceptedTaxa(Set<Taxon> taxa) {
616
        Set<Taxon> result = new HashSet<>();
617
        for (Taxon taxon : taxa){
618
            Taxon accTaxon = getAccTaxonForTaxonSynonym(taxon);
619
            if(taxon.equals(accTaxon)) {
620
                result.add(taxon);
621
            }
622
        }
623
        return result;
624
    }
625

    
626
    private CharSequence Nz(String str) {
627
        return CdmUtils.Nz(str);
628
    }
629

    
630
    public static void main(String[] args) {
631
        PesiFindIdenticalNamesActivator activator = new PesiFindIdenticalNamesActivator();
632
        activator.invoke(pesiSource);
633
        System.exit(0);
634
    }
635
}
(3-3/6)