Project

General

Profile

Download (31.4 KB) Statistics
| Branch: | Tag: | Revision:
1
package eu.etaxonomy.cdm.io.csv.caryophyllales.out;
2

    
3
import java.io.ByteArrayOutputStream;
4
import java.io.FileOutputStream;
5
import java.io.OutputStream;
6
import java.io.OutputStreamWriter;
7
import java.io.PrintWriter;
8
import java.util.ArrayList;
9
import java.util.Collections;
10
import java.util.HashMap;
11
import java.util.HashSet;
12
import java.util.Iterator;
13
import java.util.List;
14
import java.util.Set;
15
import java.util.TreeMap;
16
import java.util.UUID;
17

    
18
import org.apache.log4j.Logger;
19
import org.springframework.beans.factory.annotation.Autowired;
20
import org.springframework.stereotype.Component;
21

    
22
import eu.etaxonomy.cdm.api.service.dto.CondensedDistribution;
23
import eu.etaxonomy.cdm.api.service.pager.Pager;
24
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
25
import eu.etaxonomy.cdm.ext.geo.CondensedDistributionRecipe;
26
import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
27
import eu.etaxonomy.cdm.filter.TaxonNodeFilter;
28
import eu.etaxonomy.cdm.io.common.TaxonNodeOutStreamPartitioner;
29
import eu.etaxonomy.cdm.io.common.XmlExportState;
30
import eu.etaxonomy.cdm.model.common.CdmBase;
31
import eu.etaxonomy.cdm.model.common.Language;
32
import eu.etaxonomy.cdm.model.description.DescriptionBase;
33
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
34
import eu.etaxonomy.cdm.model.description.Distribution;
35
import eu.etaxonomy.cdm.model.description.Feature;
36
import eu.etaxonomy.cdm.model.description.TextData;
37
import eu.etaxonomy.cdm.model.location.NamedArea;
38
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
39
import eu.etaxonomy.cdm.model.name.HomotypicalGroupComparator;
40
import eu.etaxonomy.cdm.model.name.IBotanicalName;
41
import eu.etaxonomy.cdm.model.name.INonViralName;
42
import eu.etaxonomy.cdm.model.name.NameRelationship;
43
import eu.etaxonomy.cdm.model.name.NameRelationshipType;
44
import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
45
import eu.etaxonomy.cdm.model.name.NameTypeDesignationStatus;
46
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
47
import eu.etaxonomy.cdm.model.name.Rank;
48
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
49
import eu.etaxonomy.cdm.model.reference.Reference;
50
import eu.etaxonomy.cdm.model.taxon.HomotypicGroupTaxonComparator;
51
import eu.etaxonomy.cdm.model.taxon.Synonym;
52
import eu.etaxonomy.cdm.model.taxon.Taxon;
53
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
54
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
55
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
56
import eu.etaxonomy.cdm.persistence.query.MatchMode;
57

    
58

    
59

    
60
@Component
61
public class CsvNameExport extends CsvNameExportBase {
62
    private static final long serialVersionUID = 7289805663701807425L;
63

    
64
    private static final Logger logger = Logger.getLogger(CsvNameExport.class);
65

    
66
    @Autowired
67
    IEditGeoService geoService;
68

    
69
    HashMap<UUID, HashMap<String,String>> familyMap = new HashMap();
70
    HashMap<UUID, HashMap<String,String>> genusMap = new HashMap();
71

    
72
    List<HashMap<String,String>> nameRecords = new ArrayList<>();
73

    
74
    public CsvNameExport() {
75
        super();
76
        this.ioName = this.getClass().getSimpleName();
77
    }
78

    
79
    @Override
80
    protected void doInvoke(CsvNameExportState state) {
81
        CsvNameExportConfigurator config = state.getConfig();
82

    
83

    
84
        PrintWriter writer = null;
85

    
86
        try {
87

    
88
            switch(config.getTarget()) {
89
            case FILE :
90
                OutputStream os = new FileOutputStream(config.getDestination());
91
                os.write(239);
92
                os.write(187);
93
                os.write(191);
94
                writer = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
95
                break;
96
            case EXPORT_DATA :
97
                exportStream = new ByteArrayOutputStream();
98
                writer = new PrintWriter(exportStream);
99
                break;
100
            default:
101
                break;
102

    
103
            }
104

    
105
            List<HashMap<String, String>> result;
106
            if (config.getRank() == null){
107
                config.setRank(Rank.GENUS());
108
            }
109
            if (config.isNamesOnly()){
110
                txStatus = startTransaction();
111
                result = getNameService().getNameRecords();
112
            } else {
113
                result = getRecordsForPrintPub(state);
114
            }
115
            CsvRecord nameRecord;
116
            int count = 0;
117
            boolean isFirst = true;
118
            for (HashMap<String,String> record:result){
119
                if (count > 0){
120
                    isFirst = false;
121
                }
122
                count++;
123
                nameRecord = new CsvRecord(record, isFirst);
124
                nameRecord.print(writer, config);
125

    
126
            }
127
            if (exportStream != null){
128
                state.getResult().addExportData(getByteArray());
129
                //this.exportData.addExportData(exportStream.toByteArray());
130
            }
131
            writer.flush();
132

    
133
            writer.close();
134

    
135
        } catch (Exception e) {
136
            // TODO Auto-generated catch block
137
            e.printStackTrace();
138
        }
139
        if (txStatus != null  ){
140
            commitTransaction(txStatus);
141
        }
142
        return;
143

    
144

    
145
    }
146

    
147
    @Override
148
    public long countSteps(CsvNameExportState state) {
149
        TaxonNodeFilter filter = state.getConfig().getTaxonNodeFilter();
150
        return taxonNodeService.count(filter);
151
    }
152

    
153

    
154
    @Override
155
    protected boolean doCheck(CsvNameExportState state) {
156
        boolean result = true;
157
        logger.warn("No check implemented for " + this.ioName);
158
        return result;
159
    }
160

    
161
    @Override
162
    protected boolean isIgnore(CsvNameExportState state) {
163
        return false;
164
    }
165

    
166

    
167
    public List<HashMap<String,String>> getRecordsForPrintPub(CsvNameExportState state){
168
//        List<String> propertyPaths = new ArrayList<String>();
169
//        propertyPaths.add("childNodes");
170
//        txStatus = startTransaction();
171
//        Classification classification = getClassificationService().load(state.getConfig().getClassificationUUID());
172
//        TaxonNode rootNode;
173
//        if (classification != null){
174
//            rootNode = classification.getRootNode();
175
//        }else{
176
//            List<Classification> classifications = getClassificationService().list(Classification.class, 10, 0, null, null);
177
//            if (classifications.isEmpty()){
178
//                return null;
179
//            }
180
//            classification = classifications.get(0);
181
//            rootNode = classification.getRootNode();
182
//        }
183
//        rootNode = getTaxonNodeService().load(rootNode.getUuid(), propertyPaths);
184
//        Set<UUID> childrenUuids = new HashSet<UUID>();
185
//
186
//
187
//        rootNode = CdmBase.deproxy(rootNode);
188
//        rootNode.removeNullValueFromChildren();
189
//        for (TaxonNode child: rootNode.getChildNodes()){
190
//            child = CdmBase.deproxy(child);
191
//            childrenUuids.add(child.getUuid());
192
//        }
193
//        Set<UUID> parentsNodesUUID = new HashSet<UUID>(childrenUuids);
194
//        childrenUuids.clear();
195
//        List<TaxonNode> childrenNodes = new ArrayList<TaxonNode>();
196
//
197
//        findChildren(state, childrenUuids, parentsNodesUUID);
198

    
199
        IProgressMonitor monitor = state.getConfig().getProgressMonitor();
200
         @SuppressWarnings("unchecked")
201
        TaxonNodeOutStreamPartitioner<XmlExportState> partitioner
202
          = TaxonNodeOutStreamPartitioner.NewInstance(
203
                this, state, state.getConfig().getTaxonNodeFilter(),
204
                100, monitor, null);
205

    
206

    
207
            monitor.subTask("Start partitioning");
208
//            List<HashMap<String,String>> nameRecords = new ArrayList<>();
209
            TaxonNode node = partitioner.next();
210
            while (node != null){
211
              HashMap<String, String> nameRecord = createNewRecord(node, state);
212
              if (nameRecord != null){
213
                  nameRecords.add(nameRecord);
214
              }
215
              node = partitioner.next();
216
            }
217

    
218

    
219

    
220

    
221
//        List<HashMap<String,String>> nameRecords = new ArrayList<>();
222
//
223
//        childrenNodes = getTaxonNodeService().find(childrenUuids);
224
//        for(TaxonNode genusNode : childrenNodes)   {
225
//            nameRecords.add(createNewRecord(genusNode, state));
226
//            refreshTransaction();
227
//        }
228

    
229
        return nameRecords;
230

    
231
    }
232

    
233
//    /**
234
//     * @param state
235
//     * @param childrenUuids
236
//     * @param parentsNodesUUID
237
//     * @param familyNode
238
//     */
239
//    private void findChildren(CsvNameExportState state, Set<UUID> childrenUuids, Set<UUID> parentsNodesUUID) {
240
//        TaxonName name;
241
//        List<TaxonNode> familyNodes = getTaxonNodeService().find(parentsNodesUUID);
242
//        parentsNodesUUID =new HashSet<>();
243
//        for (TaxonNode familyNode: familyNodes){
244
//            familyNode = CdmBase.deproxy(familyNode);
245
//            familyNode.removeNullValueFromChildren();
246
//            for (TaxonNode child: familyNode.getChildNodes()){
247
//                child = CdmBase.deproxy(child);
248
//                Taxon taxon = CdmBase.deproxy(child.getTaxon());
249
//                if (taxon != null){
250
//                    name = CdmBase.deproxy(taxon.getName());
251
//                    if (child.getTaxon().getName().getRank().isLower(state.getConfig().getRank()) ) {
252
//                        childrenUuids.add(child.getUuid());
253
//                        if (child.hasChildNodes()){
254
//                            parentsNodesUUID.add(child.getUuid());
255
//                        }
256
//                    }else{
257
//                        parentsNodesUUID.add(child.getUuid());
258
//                    }
259
//                }
260
//            }
261
//            //refreshTransaction();
262
//            if (!parentsNodesUUID.isEmpty()){
263
//                findChildren(state, childrenUuids, parentsNodesUUID);
264
//            }
265
//        }
266
//
267
//    }
268

    
269

    
270

    
271

    
272
    private String createSynonymNameString(IBotanicalName synonymName, boolean isInvalid) {
273
        String synonymString = null;
274

    
275
        synonymString= createTaggedNameString(synonymName, isInvalid);
276
        Set<NameRelationship> nameRelations = synonymName.getNameRelations();
277

    
278
        INonViralName relatedName = null;
279
        String nameRelType = null;
280
        boolean first = true;
281
        boolean isInvalidRel = false;
282
        for (NameRelationship nameRel: nameRelations){
283
           // NameRelationship nameRel = nameRelations.iterator().next();
284
            if (!nameRel.getType().equals(NameRelationshipType.BASIONYM())){
285
                IBotanicalName fromName = CdmBase.deproxy(nameRel.getFromName());
286

    
287
                nameRel = CdmBase.deproxy(nameRel);
288
                nameRelType = nameRel.getType().getTitleCache();
289
                String relatedNameString = "";
290
                if (fromName.equals(synonymName)){
291
                    relatedName = nameRel.getToName();
292
                }else{
293
                    relatedName = nameRel.getFromName();
294
                }
295

    
296
                isInvalidRel = getStatus(relatedName);
297
                relatedNameString = createTaggedNameString(relatedName, isInvalidRel&&isInvalid);
298

    
299
                if (nameRel.getType().equals(NameRelationshipType.LATER_HOMONYM())){
300
                    if (synonymName.equals(nameRel.getFromName())){
301
                        if (first){
302
                            synonymString = synonymString + " [non " + relatedNameString ;
303
                            first = false;
304
                        } else{
305
                            synonymString = synonymString + " nec " + relatedNameString ;
306
                        }
307
                    }
308
                } else if (nameRel.getType().equals(NameRelationshipType.REPLACED_SYNONYM())){
309
                    //synonymString = synonymString + " [non " + relatedNameString + "]";
310
                } else if (nameRel.getType().equals(NameRelationshipType.BLOCKING_NAME_FOR())){
311
                    if (synonymName.equals(nameRel.getToName())){
312
                        if (first){
313
                            synonymString = synonymString + " [non " + relatedNameString ;
314
                            first = false;
315
                        } else{
316
                            synonymString = synonymString + " nec " + relatedNameString ;
317
                        }
318

    
319
                    }
320
                } else if (nameRel.getType().equals(NameRelationshipType.TREATED_AS_LATER_HOMONYM())){
321
                    if (first){
322
                        synonymString = synonymString + " [non " + relatedNameString ;
323
                        first = false;
324
                    } else{
325
                        synonymString = synonymString + " nec " + relatedNameString ;
326
                    }
327
                } else if (nameRel.getType().equals(NameRelationshipType.ALTERNATIVE_NAME())){
328
                    if (first){
329
                        synonymString = synonymString + " [non " + relatedNameString ;
330
                        first = false;
331
                    } else{
332
                        synonymString = synonymString + " nec " + relatedNameString ;
333
                    }
334
                } else if (nameRel.getType().equals(NameRelationshipType.CONSERVED_AGAINST())) {
335

    
336
                }else if (nameRel.getType().equals(NameRelationshipType.ORTHOGRAPHIC_VARIANT())){
337

    
338
                }
339
            }
340
        }
341
        if (!first){
342
            synonymString = synonymString + "]";
343
        }
344

    
345
        return synonymString;
346
    }
347

    
348
    /**
349
     * @param relatedName
350
     * @return
351
     */
352
    private boolean getStatus(INonViralName relatedName) {
353
        boolean result;
354
        if (!relatedName.getStatus().isEmpty()){
355
            NomenclaturalStatus status = CdmBase.deproxy(relatedName.getStatus().iterator().next());
356
            if (status.getType().isInvalidType()){
357
                result = true;
358
            }else{
359
                result = false;
360
            }
361
        }else{
362
            result = false;
363
        }
364
        return result;
365
    }
366

    
367
    private String createTaggedNameString(INonViralName name, boolean isInvalid){
368
        String nameString = null;
369
        if (name == null){
370
            return nameString;
371
        }
372

    
373
        nameString = name.generateFullTitle();
374
        if (isInvalid){
375
            nameString = nameString.replace(name.getTitleCache(), "\""+name.getTitleCache()+"\"");
376
        }
377
        if (name.getGenusOrUninomial() != null){
378
            nameString = nameString.replaceAll(name.getGenusOrUninomial(), "<i>"+ name.getGenusOrUninomial() + "</i>");
379
        }
380
        if (name.getInfraGenericEpithet() != null){
381
            nameString = nameString.replaceAll(name.getInfraGenericEpithet(),  "<i>"+ name.getInfraGenericEpithet() + "</i>");
382
        }
383
        if (name.getSpecificEpithet() != null){
384
            nameString = nameString.replaceAll(name.getSpecificEpithet(),  "<i>"+ name.getSpecificEpithet() + "</i>");
385
        }
386
        if (name.getInfraSpecificEpithet() != null && !name.isAutonym()){
387
            nameString = nameString.replaceAll(name.getInfraSpecificEpithet(),  "<i>"+ name.getInfraSpecificEpithet() + "</i>");
388
        }
389

    
390
        return nameString;
391
    }
392

    
393

    
394

    
395
//    private List<TaxonNode> getGenusNodes (UUID classificationUUID){
396
//        Classification classification = getClassificationService().load(classificationUUID);
397
//        TaxonNode rootNode = classification.getRootNode();
398
//        rootNode = getTaxonNodeService().load(rootNode.getUuid());
399
//        Set<UUID> childrenUuids = new HashSet<>();
400
//
401
//        for (TaxonNode child: rootNode.getChildNodes()){
402
//            child = CdmBase.deproxy(child);
403
//            childrenUuids.add(child.getUuid());
404
//        }
405
//
406
//        List<TaxonNode> familyNodes = getTaxonNodeService().find(childrenUuids);
407
//        childrenUuids.clear();
408
//        List<TaxonNode> genusNodes = new ArrayList<>();
409
//        for (TaxonNode familyNode: familyNodes){
410
//            for (TaxonNode child: familyNode.getChildNodes()){
411
//                child = CdmBase.deproxy(child);
412
//                childrenUuids.add(child.getUuid());
413
//            }
414
//
415
//            genusNodes = getTaxonNodeService().find(childrenUuids);
416
//        }
417
//        return genusNodes;
418
//    }
419

    
420
    private TaxonNode getHigherNode(TaxonNode node, Rank rank){
421

    
422
        Rank nodeRank = node.getTaxon().getName().getRank();
423
        if (nodeRank.isKindOf(rank)){
424
            return null;
425

    
426
        }else if (nodeRank.isHigher(rank)){
427
            return null;
428
        } else {
429
            return node.getAncestorOfRank(rank);
430
        }
431
    }
432

    
433
    private void extractDescriptions(HashMap<String, String> nameRecord, Taxon taxon, Feature feature, String columnName, CsvNameExportState state){
434
        StringBuffer descriptionsString = new StringBuffer();
435
        TextData textElement;
436
        Set<Distribution> distributions = new HashSet<>();
437
        if (taxon.getDescriptions().isEmpty()){
438
            nameRecord.put(columnName, null);
439
                return;
440
        }
441
        for (DescriptionBase<?> descriptionBase: taxon.getDescriptions()){
442
            if (!descriptionBase.isImageGallery()){
443
                Set<DescriptionElementBase> elements = descriptionBase.getElements();
444
                for (DescriptionElementBase element: elements){
445
                    if (element.getFeature().equals(feature)){
446
                        if (element instanceof TextData){
447
                            textElement = CdmBase.deproxy(element, TextData.class);
448
                            descriptionsString.append(textElement.getText(Language.ENGLISH()));
449

    
450
                        }else if (element instanceof Distribution ){
451

    
452
                            Distribution distribution = CdmBase.deproxy(element, Distribution.class);
453
                            distributions.add(distribution);
454
                        }
455

    
456
                    }
457
                }
458
            }
459
        }
460
        if (state.getConfig().isCondensedDistribution()){
461
            List<Language> langs = new ArrayList<Language>();
462
            langs.add(Language.ENGLISH());
463

    
464
            CondensedDistribution conDis = geoService.getCondensedDistribution(distributions, true, null,null,CondensedDistributionRecipe.FloraCuba, langs );
465

    
466
            nameRecord.put(columnName, conDis.toString());
467

    
468
        } else{
469
            NamedArea area ;
470
            for (Distribution distribution:distributions){
471

    
472
                if (descriptionsString.length()> 0 ){
473
                    descriptionsString.append(", ");
474
                }
475
                area = CdmBase.deproxy(distribution.getArea());
476
                if (area.getIdInVocabulary() != null){
477
                    descriptionsString.append(area.getIdInVocabulary());
478
                }else if (area.getSymbol() != null){
479
                    descriptionsString.append(area.getSymbol());
480
                }else{
481
                    descriptionsString.append(area.getLabel());
482
                }
483

    
484
            }
485
            nameRecord.put(columnName, descriptionsString.toString());
486
        }
487

    
488
    }
489

    
490
    private Feature getNotesFeature(CsvNameExportState state){
491
        if (state.getNotesFeature() != null){
492
            return state.getNotesFeature();
493
        } else{
494
            Pager<Feature> notesFeature = getTermService().findByTitleWithRestrictions(Feature.class, "Notes" ,MatchMode.EXACT, null, null, null, null, null);
495
            if (notesFeature.getRecords().size() == 0){
496
                return null;
497
            }else{
498
                Feature feature=  notesFeature.getRecords().iterator().next();
499
                state.setNotesFeature(feature);
500
                return feature;
501
            }
502
        }
503

    
504
    }
505

    
506
    private HashMap<String, String> createNewRecord(TaxonNode childNode, CsvNameExportState state){
507
        HashMap<String, String> nameRecord = new HashMap<>();
508
        nameRecord.put("classification", childNode.getClassification().getTitleCache());
509
        if (!childNode.getTaxon().getName().getRank().isLower(Rank.GENUS())){
510
            return null;
511
        }
512
        TaxonNode familyNode = getHigherNode(childNode, Rank.FAMILY());
513
        Taxon taxon;
514
        String nameString;
515
        IBotanicalName name;
516
        if (familyNode == null){
517
            nameRecord.put("familyTaxon", null);
518
            nameRecord.put("familyName", null);
519
            nameRecord.put("descriptionsFam", null);
520
        }else{
521
            familyNode = CdmBase.deproxy(familyNode);
522
            familyNode.getTaxon().setProtectedTitleCache(true);
523
            nameRecord.put("familyTaxon", familyNode.getTaxon().getTitleCache());
524
            if (familyMap.get(familyNode.getTaxon().getUuid()) != null){
525
                nameRecord.putAll(familyMap.get(familyNode.getTaxon().getUuid()));
526
            }else{
527
                taxon = (Taxon)getTaxonService().load(familyNode.getTaxon().getUuid());
528
                taxon = CdmBase.deproxy(taxon);
529
                name = CdmBase.deproxy(taxon.getName());
530
                nameRecord.put("familyName", name.getNameCache());
531
                extractDescriptions(nameRecord, taxon, Feature.INTRODUCTION(), "descriptionsFam", state);
532
                familyMap.put(familyNode.getTaxon().getUuid(), nameRecord);
533
            }
534

    
535
        }
536
        TaxonNode genusNode = getHigherNode(childNode, Rank.GENUS());
537
        if (genusNode!= null){
538
            genusNode = CdmBase.deproxy(genusNode);
539
            genusNode.getTaxon().setProtectedTitleCache(true);
540
            nameRecord.put("genusTaxon", genusNode.getTaxon().getTitleCache());
541
            if (genusMap.get(genusNode.getTaxon().getUuid()) != null){
542
                nameRecord.putAll(genusMap.get(genusNode.getTaxon().getUuid()));
543
            }else{
544
                taxon = (Taxon)getTaxonService().load(genusNode.getTaxon().getUuid());
545
                taxon = CdmBase.deproxy(taxon);
546
                name = CdmBase.deproxy(taxon.getName());
547
                if (name.getNameCache() != null){
548
                    nameRecord.put("genusName", name.getNameCache());
549
                }else{
550
                    nameRecord.put("genusName", name.getGenusOrUninomial());
551
                }
552
                extractDescriptions(nameRecord, taxon,getNotesFeature(state), "descriptionsGen", state);
553
                genusMap.put(genusNode.getTaxon().getUuid(), nameRecord);
554
            }
555

    
556

    
557
        }else{
558
            nameRecord.put("genusTaxon", null);
559
            nameRecord.put("genusName", null);
560
            nameRecord.put("descriptionsGen", null);
561
        }
562

    
563
//        taxon = (Taxon) getTaxonService().load(childNode.getTaxon().getUuid());
564
        taxon = CdmBase.deproxy(childNode.getTaxon());
565
        //  if (taxon.isPublish()){
566

    
567
        INonViralName nonViralName = taxon.getName();
568

    
569
        nameString = createTaggedNameString(nonViralName, false);
570
        nameRecord.put("childTaxon", taxon.getTitleCache());
571
        if (taxon.getSec()!= null){
572
            nameRecord.put("secRef", taxon.getSec().getTitleCache());
573
        }else{
574
            nameRecord.put("secRef", null);
575
        }
576

    
577
        getTaxonRelations(nameRecord, taxon);
578

    
579
        name = CdmBase.deproxy(taxon.getName());
580
        nameRecord.put("childName",nameString);
581
        nameRecord.put("nameId", String.valueOf(name.getId()));
582
        nameRecord.put("nameCache", name.getNameCache());
583
        nameRecord.put("titleName", name.getTitleCache());
584
        if (name.getNomenclaturalReference() != null){
585
            nameRecord.put("NomRefTitleCache", name.getNomenclaturalReference().getTitleCache());
586
        } else{
587
            nameRecord.put("NomRefTitleCache",null);
588
        }
589
        nameRecord.put("fullName", name.getNameCache());
590
        nameRecord.put("fullTitleCache",  name.getFullTitleCache());
591
        Set<TypeDesignationBase<?>> typeDesSet =  name.getTypeDesignations();
592
        Iterator<TypeDesignationBase<?>> it = typeDesSet.iterator();
593
        String typeNameString = NOT_DESIGNATED;
594
        String statusString = null;
595
        if (it.hasNext()){
596

    
597
            TypeDesignationBase<?> typeDes = CdmBase.deproxy(it.next());
598

    
599
            if (typeDes instanceof NameTypeDesignation){
600
                NameTypeDesignation nameTypeDes = CdmBase.deproxy(typeDes, NameTypeDesignation.class);
601

    
602
                IBotanicalName typeName =  CdmBase.deproxy(nameTypeDes.getTypeName());
603
                if (typeName != null){
604

    
605
                    typeNameString = "<i>" + typeName.getNameCache() +"</i> "  + typeName.getAuthorshipCache();
606
                    if (nameTypeDes.getTypeStatus() != null){
607
                        NameTypeDesignationStatus status = CdmBase.deproxy(nameTypeDes.getTypeStatus());
608
                        statusString = status.getTitleCache();
609
                    }
610
                }
611
            }
612
        }
613
        nameRecord.put("typeName", typeNameString);
614
        StringBuffer homotypicalSynonyms = new StringBuffer();
615
        TreeMap<HomotypicalGroup,List<Synonym>> heterotypicSynonymsList = new TreeMap<>(new HomotypicalGroupComparator());
616

    
617
        List<Synonym> homotypicSynonymsList = new ArrayList<>();
618
        StringBuffer heterotypicalSynonyms = new StringBuffer();
619
        List<Synonym> homotypicSynonyms;
620

    
621
        HomotypicalGroup group;
622
        IBotanicalName synonymName;
623
        String doubtfulTitleCache;
624
        for (Synonym synonym: taxon.getSynonyms()){
625
            synonymName = CdmBase.deproxy(synonym.getName());
626
            group = CdmBase.deproxy(synonymName.getHomotypicalGroup());
627
            synonymName.generateFullTitle();
628
            if (synonym.isDoubtful()){
629
                if (!synonymName.getFullTitleCache().startsWith("?")){
630
                    doubtfulTitleCache = "?" + synonymName.getFullTitleCache();
631
                    synonymName = (IBotanicalName) synonymName.clone();
632
                    synonymName.setFullTitleCache(doubtfulTitleCache, true);
633
                }
634
            }
635
            if (!group.equals(name.getHomotypicalGroup())){
636
                if (heterotypicSynonymsList.containsKey(group)){
637
                    heterotypicSynonymsList.get(group).add(synonym);
638
                }else{
639
                    homotypicSynonyms = new ArrayList<>();
640
                    homotypicSynonyms.add(synonym);
641
                    heterotypicSynonymsList.put(group, homotypicSynonyms);
642
                    homotypicSynonyms= null;
643
                }
644
            } else{
645
                synonymName.generateFullTitle();
646
                homotypicSynonymsList.add(synonym);
647
            }
648
        }
649

    
650

    
651

    
652
        String synonymString;
653
        boolean first = true;
654

    
655
        for (List<Synonym> list: heterotypicSynonymsList.values()){
656
            Collections.sort(list, new HomotypicGroupTaxonComparator(null));
657
            first = true;
658
            for (TaxonBase<?> synonym : list){
659
                NomenclaturalStatus status = null;
660
                if (!synonym.getName().getStatus().isEmpty()){
661
                    status = CdmBase.deproxy(synonym.getName().getStatus().iterator().next());
662
                    if (status.getType().isInvalidType()){
663
                        heterotypicalSynonyms.append(" <invalid> ");
664
                        synonymName = CdmBase.deproxy(synonym.getName());
665

    
666
                        synonymString = createSynonymNameString(synonymName, state.getConfig().isInvalidNamesQuoted()) ;
667
                        heterotypicalSynonyms.append(synonymString);
668
                        continue;
669
                    }
670
                }
671
                if (first){
672
                    heterotypicalSynonyms.append(" <heterotypic> ");
673
                }else{
674
                    heterotypicalSynonyms.append(" <homonym> ");
675
                }
676
                first = false;
677
                synonymName = CdmBase.deproxy(synonym.getName());
678
                synonymString = createSynonymNameString(synonymName, false);
679
                heterotypicalSynonyms.append(synonymString);
680
            }
681
        }
682

    
683
        first = true;
684
        Collections.sort(homotypicSynonymsList, new HomotypicGroupTaxonComparator(null)  );
685
        NomenclaturalStatus status = null;
686
        for (TaxonBase<?> synonym : homotypicSynonymsList){
687

    
688
            if (!synonym.getName().getStatus().isEmpty()){
689
                status = CdmBase.deproxy(synonym.getName().getStatus().iterator().next());
690
                if (status.getType().isInvalidType()){
691
                    homotypicalSynonyms.append(" <invalid> ");
692
                    synonymName = CdmBase.deproxy(synonym.getName());
693
                    synonymString = createSynonymNameString(synonymName, true);
694
                    homotypicalSynonyms.append(synonymString);
695
                    continue;
696
                }else if (!first){
697
                    homotypicalSynonyms.append(" <homonym> ");
698
                }
699

    
700
            }else if (!first){
701
                homotypicalSynonyms.append(" <homonym> ");
702
            }
703
            first = false;
704
            synonymName = CdmBase.deproxy(synonym.getName());
705

    
706
            synonymString = createSynonymNameString(synonymName, false);
707

    
708
            homotypicalSynonyms.append(synonymString);
709

    
710
        }
711

    
712
        nameRecord.put("synonyms_homotypic", homotypicalSynonyms.toString());
713
        nameRecord.put("synonyms_heterotypic", heterotypicalSynonyms.toString());
714
        nameRecord.put("status", statusString);
715

    
716
        Set<NameRelationship> nameRelations = name.getNameRelations();
717

    
718
        INonViralName relatedName = null;
719
        String nameRelType = null;
720
        String relNameString = null;
721
        if (nameRelations.size()>0){
722
            NameRelationship nameRel = nameRelations.iterator().next();
723
            IBotanicalName fromName = CdmBase.deproxy(nameRel.getFromName());
724
            if (fromName.equals(taxon.getName())){
725
                relatedName = nameRel.getToName();
726

    
727
            }else{
728
                relatedName = nameRel.getFromName();
729
            }
730
            nameRel = CdmBase.deproxy(nameRel);
731
            nameRelType = nameRel.getType().getTitleCache();
732
            relNameString  = createTaggedNameString(relatedName, getStatus(relatedName));
733
        }
734

    
735

    
736
        nameRecord.put("relatedName", relNameString);
737
        nameRecord.put("nameRelType", nameRelType);
738

    
739
        extractDescriptions(nameRecord, taxon, Feature.DISTRIBUTION(), "descriptions", state);
740
        return nameRecord;
741
    }
742

    
743
    /**
744
     * @param nameRecord
745
     * @param taxon
746
     */
747
    private void getTaxonRelations(HashMap<String, String> nameRecord, Taxon taxon) {
748
        Set<TaxonRelationship> relations = new HashSet<>();
749
        relations =taxon.getTaxonRelations();
750
        if (relations.isEmpty()){
751
            nameRecord.put("missappliedNames", null);
752
        }else{
753
            Taxon relatedTaxon = null;
754
            StringBuffer nameString = new StringBuffer();
755
            for (TaxonRelationship rel : relations){
756
                if (rel.getType().isAnyMisappliedName()){
757
                    relatedTaxon = rel.getFromTaxon();
758
                    Reference secRef = relatedTaxon.getSec();
759
                    String appendedPhrase = "";
760
                    if (relatedTaxon.getAppendedPhrase() != null){
761
                        appendedPhrase = relatedTaxon.getAppendedPhrase();
762
                    }
763
                    if (appendedPhrase.equals("sphalm.")){
764
                        String relNameString  = createTaggedNameString(relatedTaxon.getName(), getStatus(relatedTaxon.getName()));
765

    
766
                        nameRecord.put("relatedName", relNameString);
767
                        nameRecord.put("nameRelType", NameRelationshipType.ORTHOGRAPHIC_VARIANT().getTitleCache());
768
                        return;
769
                    }
770
                    if (secRef == null){
771
                        nameString.append("<misapplied>" +"\u201C" + createTaggedNameString(relatedTaxon.getName(), false) + "\u201D " + appendedPhrase);
772
                    } else if (secRef.getAuthorship() == null){
773
                        nameString.append("<misapplied>"+"\u201C" + createTaggedNameString(relatedTaxon.getName(), false) + "\u201D " + appendedPhrase + " sensu " + secRef.getTitleCache());
774
                    } else {
775
                        nameString.append("<misapplied>\"" + createTaggedNameString(relatedTaxon.getName(), false) + "\" " + appendedPhrase + " sensu " + secRef.getAuthorship().getFullTitle());
776
                    }
777

    
778
                }
779
            }
780
            nameRecord.put("missappliedNames", nameString.toString());
781
        }
782
    }
783

    
784
}
785

    
(1-1/5)